diff --git a/trunk/src/nvcore/Array.h b/trunk/src/nvcore/Array.h index d3a7574..959e4df 100644 --- a/trunk/src/nvcore/Array.h +++ b/trunk/src/nvcore/Array.h @@ -14,19 +14,15 @@ container. This is forbidden to prevent an extra copy. */ -#include "nvcore.h" #include "Memory.h" #include "Debug.h" -#include "Stream.h" -#include "Utils.h" // swap #include "ForEach.h" // PseudoIndex -#include // memmove -#include // for placement new - namespace nv { + class Stream; + /** * Replacement for std::vector that is easier to debug and provides * some nice foreach enumerators. @@ -103,286 +99,33 @@ namespace nv NV_FORCEINLINE bool isNull() const { return m_buffer == NULL; } - /// Push an element at the end of the vector. - NV_FORCEINLINE void push_back( const T & val ) - { -#if 1 - nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size); - - uint old_size = m_size; - uint new_size = m_size + 1; - - setArraySize(new_size); - - construct_range(m_buffer, new_size, old_size, val); -#else - uint new_size = m_size + 1; - - if (new_size > m_capacity) - { - // @@ Is there any way to avoid this copy? - // @@ Can we create a copy without side effects? Ie. without calls to constructor/destructor. Use alloca + memcpy? - // @@ Assert instead of copy? - const T copy(val); // create a copy in case value is inside of this array. - - setArraySize(new_size); - - new (m_buffer+new_size-1) T(copy); - } - else - { - m_size = new_size; - new(m_buffer+new_size-1) T(val); - } -#endif // 0/1 - } - NV_FORCEINLINE void pushBack( const T & val ) - { - push_back(val); - } - NV_FORCEINLINE void append( const T & val ) - { - push_back(val); - } - - /// Qt like push operator. - NV_FORCEINLINE Array & operator<< ( T & t ) - { - push_back(t); - return *this; - } - - /// Pop the element at the end of the vector. - NV_FORCEINLINE void pop_back() - { - nvDebugCheck( m_size > 0 ); - resize( m_size - 1 ); - } - NV_FORCEINLINE void popBack() - { - pop_back(); - } - - /// Get back element. - NV_FORCEINLINE const T & back() const - { - nvDebugCheck( m_size > 0 ); - return m_buffer[m_size-1]; - } - - /// Get back element. - NV_FORCEINLINE T & back() - { - nvDebugCheck( m_size > 0 ); - return m_buffer[m_size-1]; - } - - /// Get front element. - NV_FORCEINLINE const T & front() const - { - nvDebugCheck( m_size > 0 ); - return m_buffer[0]; - } - - /// Get front element. - NV_FORCEINLINE T & front() - { - nvDebugCheck( m_size > 0 ); - return m_buffer[0]; - } - - /// Check if the given element is contained in the array. - NV_FORCEINLINE bool contains(const T & e) const - { - return find(e, NULL); - } - - /// Return true if element found. - NV_FORCEINLINE bool find(const T & element, uint * indexPtr) const - { - return find(element, 0, m_size, indexPtr); - } - - /// Return true if element found within the given range. - NV_FORCEINLINE bool find(const T & element, uint begin, uint end, uint * indexPtr) const - { - return ::nv::find(element, m_buffer, begin, end, indexPtr); - } - - /// Remove the element at the given index. This is an expensive operation! - void removeAt(uint index) - { - nvDebugCheck(index >= 0 && index < m_size); - - if (m_size == 1) { - clear(); - } - else { - m_buffer[index].~T(); - - memmove(m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index)); - m_size--; - } - } - - /// Remove the first instance of the given element. - bool remove(const T & element) - { - uint index; - if (find(element, &index)) { - removeAt(index); - return true; - } - return false; - } - - /// Insert the given element at the given index shifting all the elements up. - void insertAt(uint index, const T & val = T()) - { - nvDebugCheck( index >= 0 && index <= m_size ); - - setArraySize(m_size + 1); - - if (index < m_size - 1) { - memmove(m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index)); - } - - // Copy-construct into the newly opened slot. - new(m_buffer+index) T(val); - } - - /// Append the given data to our vector. - NV_FORCEINLINE void append(const Array & other) - { - append(other.m_buffer, other.m_size); - } - - /// Append the given data to our vector. - void append(const T other[], uint count) - { - if (count > 0) { - const uint old_size = m_size; - - setArraySize(m_size + count); - - for (uint i = 0; i < count; i++ ) { - new(m_buffer + old_size + i) T(other[i]); - } - } - } - - - /// Remove the given element by replacing it with the last one. - void replaceWithLast(uint index) - { - nvDebugCheck( index < m_size ); - nv::swap(m_buffer[index], back()); - (m_buffer+m_size-1)->~T(); - m_size--; - } - - - /// Resize the vector preserving existing elements. - void resize(uint new_size) - { - uint old_size = m_size; - - // Destruct old elements (if we're shrinking). - destroy_range(m_buffer, new_size, old_size); - - setArraySize(new_size); - - // Call default constructors - construct_range(m_buffer, new_size, old_size); - } - - - /// Resize the vector preserving existing elements and initializing the - /// new ones with the given value. - void resize(uint new_size, const T & elem) - { - nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size); - - uint old_size = m_size; - - // Destruct old elements (if we're shrinking). - destroy_range(m_buffer, new_size, old_size); - - setArraySize(new_size); - - // Call copy constructors - construct_range(m_buffer, new_size, old_size, elem); - } - - /// Clear the buffer. - NV_FORCEINLINE void clear() - { - // Destruct old elements - destroy_range(m_buffer, 0, m_size); - - m_size = 0; - } - - /// Shrink the allocated vector. - NV_FORCEINLINE void shrink() - { - if (m_size < m_capacity) { - setArrayCapacity(m_size); - } - } - - /// Preallocate space. - NV_FORCEINLINE void reserve(uint desired_size) - { - if (desired_size > m_capacity) { - setArrayCapacity(desired_size); - } - } - - /// Copy elements to this array. Resizes it if needed. - NV_FORCEINLINE void copy(const T * data, uint count) - { - destroy_range(m_buffer, count, m_size); - - setArraySize(count); - - ::nv::copy(m_buffer, data, count); - } - - /// Assignment operator. - NV_FORCEINLINE Array & operator=( const Array & a ) - { - copy(a.m_buffer, a.m_size); - return *this; - } - - // Release ownership of allocated memory and returns pointer to it. - T * release() { - T * tmp = m_buffer; - m_buffer = NULL; - m_capacity = 0; - m_size = 0; - return tmp; - } - - /// Array serialization. - friend Stream & operator<< ( Stream & s, Array & p ) - { - if (s.isLoading()) { - uint size; - s << size; - p.resize( size ); - } - else { - s << p.m_size; - } - - for (uint i = 0; i < p.m_size; i++) { - s << p.m_buffer[i]; - } - - return s; - } + void push_back( const T & val ); + void pushBack( const T & val ); + void append( const T & val ); + Array & operator<< ( T & t ); + void pop_back(); + void popBack(); + const T & back() const; + T & back(); + const T & front() const; + T & front(); + bool contains(const T & e) const; + bool find(const T & element, uint * indexPtr) const; + bool find(const T & element, uint begin, uint end, uint * indexPtr) const; + void removeAt(uint index); + bool remove(const T & element); + void insertAt(uint index, const T & val = T()); + void append(const Array & other); + void append(const T other[], uint count); + void replaceWithLast(uint index); + void resize(uint new_size); + void resize(uint new_size, const T & elem); + void clear(); + void shrink(); + void reserve(uint desired_size); + void copy(const T * data, uint count); + Array & operator=( const Array & a ); + T * release(); // Array enumerator. @@ -401,55 +144,18 @@ namespace nv } #endif - // Swap the members of this vector and the given vector. - friend void swapMembers(Array & a, Array & b) - { - nv::swap(a.m_buffer, b.m_buffer); - nv::swap(a.m_capacity, b.m_capacity); - nv::swap(a.m_size, b.m_size); - } + // Friends. + template + friend Stream & operator<< ( Stream & s, Array & p ); + + template + friend void swap(Array & a, Array & b); protected: - // Change array size. - void setArraySize(uint new_size) { - m_size = new_size; - - if (new_size > m_capacity) { - uint new_buffer_size; - if (m_capacity == 0) { - // first allocation is exact - new_buffer_size = new_size; - } - else { - // following allocations grow array by 25% - new_buffer_size = new_size + (new_size >> 2); - } - - setArrayCapacity( new_buffer_size ); - } - } - - // Change array capacity. - void setArrayCapacity(uint new_capacity) { - nvDebugCheck(new_capacity >= m_size); - - if (new_capacity == 0) { - // free the buffer. - if (m_buffer != NULL) { - free(m_buffer); - m_buffer = NULL; - } - } - else { - // realloc the buffer - m_buffer = realloc(m_buffer, new_capacity); - } - - m_capacity = new_capacity; - } - + void setArraySize(uint new_size); + void setArrayCapacity(uint new_capacity); T * m_buffer; uint m_capacity; @@ -457,13 +163,6 @@ protected: }; - - template - inline void swap(Array & a, Array & b) - { - swapMembers(a, b); - } - } // nv namespace diff --git a/trunk/src/nvcore/Array.inl b/trunk/src/nvcore/Array.inl new file mode 100755 index 0000000..d909175 --- /dev/null +++ b/trunk/src/nvcore/Array.inl @@ -0,0 +1,383 @@ +// This code is in the public domain -- Ignacio Castaņo + +#pragma once +#ifndef NV_CORE_ARRAY_INL +#define NV_CORE_ARRAY_INL + +#include "Array.h" + +#include "Stream.h" +#include "Utils.h" // swap + +#include // memmove +#include // for placement new + + + +namespace nv +{ + + // Push an element at the end of the vector. + template + NV_FORCEINLINE void Array::push_back( const T & val ) + { +#if 1 + nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size); + + uint old_size = m_size; + uint new_size = m_size + 1; + + setArraySize(new_size); + + construct_range(m_buffer, new_size, old_size, val); +#else + uint new_size = m_size + 1; + + if (new_size > m_capacity) + { + // @@ Is there any way to avoid this copy? + // @@ Can we create a copy without side effects? Ie. without calls to constructor/destructor. Use alloca + memcpy? + // @@ Assert instead of copy? + const T copy(val); // create a copy in case value is inside of this array. + + setArraySize(new_size); + + new (m_buffer+new_size-1) T(copy); + } + else + { + m_size = new_size; + new(m_buffer+new_size-1) T(val); + } +#endif // 0/1 + } + template + NV_FORCEINLINE void Array::pushBack( const T & val ) + { + push_back(val); + } + template + NV_FORCEINLINE void Array::append( const T & val ) + { + push_back(val); + } + + // Qt like push operator. + template + NV_FORCEINLINE Array & Array::operator<< ( T & t ) + { + push_back(t); + return *this; + } + + // Pop the element at the end of the vector. + template + NV_FORCEINLINE void Array::pop_back() + { + nvDebugCheck( m_size > 0 ); + resize( m_size - 1 ); + } + template + NV_FORCEINLINE void Array::popBack() + { + pop_back(); + } + + // Get back element. + template + NV_FORCEINLINE const T & Array::back() const + { + nvDebugCheck( m_size > 0 ); + return m_buffer[m_size-1]; + } + + // Get back element. + template + NV_FORCEINLINE T & Array::back() + { + nvDebugCheck( m_size > 0 ); + return m_buffer[m_size-1]; + } + + // Get front element. + template + NV_FORCEINLINE const T & Array::front() const + { + nvDebugCheck( m_size > 0 ); + return m_buffer[0]; + } + + // Get front element. + template + NV_FORCEINLINE T & Array::front() + { + nvDebugCheck( m_size > 0 ); + return m_buffer[0]; + } + + // Check if the given element is contained in the array. + template + NV_FORCEINLINE bool Array::contains(const T & e) const + { + return find(e, NULL); + } + + // Return true if element found. + template + NV_FORCEINLINE bool Array::find(const T & element, uint * indexPtr) const + { + return find(element, 0, m_size, indexPtr); + } + + // Return true if element found within the given range. + template + NV_FORCEINLINE bool Array::find(const T & element, uint begin, uint end, uint * indexPtr) const + { + return ::nv::find(element, m_buffer, begin, end, indexPtr); + } + + + // Remove the element at the given index. This is an expensive operation! + template + void Array::removeAt(uint index) + { + nvDebugCheck(index >= 0 && index < m_size); + + if (m_size == 1) { + clear(); + } + else { + m_buffer[index].~T(); + + memmove(m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index)); + m_size--; + } + } + + // Remove the first instance of the given element. + template + bool Array::remove(const T & element) + { + uint index; + if (find(element, &index)) { + removeAt(index); + return true; + } + return false; + } + + // Insert the given element at the given index shifting all the elements up. + template + void Array::insertAt(uint index, const T & val/*=T()*/) + { + nvDebugCheck( index >= 0 && index <= m_size ); + + setArraySize(m_size + 1); + + if (index < m_size - 1) { + memmove(m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index)); + } + + // Copy-construct into the newly opened slot. + new(m_buffer+index) T(val); + } + + // Append the given data to our vector. + template + NV_FORCEINLINE void Array::append(const Array & other) + { + append(other.m_buffer, other.m_size); + } + + // Append the given data to our vector. + template + void Array::append(const T other[], uint count) + { + if (count > 0) { + const uint old_size = m_size; + + setArraySize(m_size + count); + + for (uint i = 0; i < count; i++ ) { + new(m_buffer + old_size + i) T(other[i]); + } + } + } + + + // Remove the given element by replacing it with the last one. + template + void Array::replaceWithLast(uint index) + { + nvDebugCheck( index < m_size ); + nv::swap(m_buffer[index], back()); + (m_buffer+m_size-1)->~T(); + m_size--; + } + + // Resize the vector preserving existing elements. + template + void Array::resize(uint new_size) + { + uint old_size = m_size; + + // Destruct old elements (if we're shrinking). + destroy_range(m_buffer, new_size, old_size); + + setArraySize(new_size); + + // Call default constructors + construct_range(m_buffer, new_size, old_size); + } + + + // Resize the vector preserving existing elements and initializing the + // new ones with the given value. + template + void Array::resize(uint new_size, const T & elem) + { + nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size); + + uint old_size = m_size; + + // Destruct old elements (if we're shrinking). + destroy_range(m_buffer, new_size, old_size); + + setArraySize(new_size); + + // Call copy constructors + construct_range(m_buffer, new_size, old_size, elem); + } + + // Clear the buffer. + template + NV_FORCEINLINE void Array::clear() + { + // Destruct old elements + destroy_range(m_buffer, 0, m_size); + + m_size = 0; + } + + // Shrink the allocated vector. + template + NV_FORCEINLINE void Array::shrink() + { + if (m_size < m_capacity) { + setArrayCapacity(m_size); + } + } + + // Preallocate space. + template + NV_FORCEINLINE void Array::reserve(uint desired_size) + { + if (desired_size > m_capacity) { + setArrayCapacity(desired_size); + } + } + + // Copy elements to this array. Resizes it if needed. + template + NV_FORCEINLINE void Array::copy(const T * data, uint count) + { + destroy_range(m_buffer, count, m_size); + + setArraySize(count); + + ::nv::copy(m_buffer, data, count); + } + + // Assignment operator. + template + NV_FORCEINLINE Array & Array::operator=( const Array & a ) + { + copy(a.m_buffer, a.m_size); + return *this; + } + + // Release ownership of allocated memory and returns pointer to it. + template + T * Array::release() { + T * tmp = m_buffer; + m_buffer = NULL; + m_capacity = 0; + m_size = 0; + return tmp; + } + + + + // Change array size. + template + inline void Array::setArraySize(uint new_size) { + m_size = new_size; + + if (new_size > m_capacity) { + uint new_buffer_size; + if (m_capacity == 0) { + // first allocation is exact + new_buffer_size = new_size; + } + else { + // following allocations grow array by 25% + new_buffer_size = new_size + (new_size >> 2); + } + + setArrayCapacity( new_buffer_size ); + } + } + + // Change array capacity. + template + inline void Array::setArrayCapacity(uint new_capacity) { + nvDebugCheck(new_capacity >= m_size); + + if (new_capacity == 0) { + // free the buffer. + if (m_buffer != NULL) { + free(m_buffer); + m_buffer = NULL; + } + } + else { + // realloc the buffer + m_buffer = realloc(m_buffer, new_capacity); + } + + m_capacity = new_capacity; + } + + // Array serialization. + template + inline Stream & operator<< ( Stream & s, Array & p ) + { + if (s.isLoading()) { + uint size; + s << size; + p.resize( size ); + } + else { + s << p.m_size; + } + + for (uint i = 0; i < p.m_size; i++) { + s << p.m_buffer[i]; + } + + return s; + } + + // Swap the members of the two given vectors. + template + inline void swap(Array & a, Array & b) + { + nv::swap(a.m_buffer, b.m_buffer); + nv::swap(a.m_capacity, b.m_capacity); + nv::swap(a.m_size, b.m_size); + } + + +} // nv namespace + +#endif // NV_CORE_ARRAY_INL diff --git a/trunk/src/nvcore/Debug.h b/trunk/src/nvcore/Debug.h index ef87210..07d08c5 100644 --- a/trunk/src/nvcore/Debug.h +++ b/trunk/src/nvcore/Debug.h @@ -6,9 +6,8 @@ #include "nvcore.h" -#if defined(HAVE_STDARG_H) -# include // va_list -#endif +#include // va_list + // Make sure we are using our assert. #undef assert diff --git a/trunk/src/nvcore/DefsGnucDarwin.h b/trunk/src/nvcore/DefsGnucDarwin.h index 9e250cd..9d27730 100644 --- a/trunk/src/nvcore/DefsGnucDarwin.h +++ b/trunk/src/nvcore/DefsGnucDarwin.h @@ -3,7 +3,7 @@ #endif #include // uint8_t, int8_t, ... uintptr_t -//#include // operator new, size_t, NULL +#include // operator new, size_t, NULL // Function linkage #define DLL_IMPORT diff --git a/trunk/src/nvcore/DefsVcWin32.h b/trunk/src/nvcore/DefsVcWin32.h index e92d67c..1ba3fc5 100644 --- a/trunk/src/nvcore/DefsVcWin32.h +++ b/trunk/src/nvcore/DefsVcWin32.h @@ -81,3 +81,6 @@ typedef uint32 uint; #pragma warning(disable : 4675) // resolved overload was found by argument-dependent lookup */ + +#pragma warning(1 : 4705) // Report unused local variables. +#pragma warning(1 : 4555) // Expression has no effect. diff --git a/trunk/src/nvcore/ForEach.h b/trunk/src/nvcore/ForEach.h index 4a6bf29..71a573d 100644 --- a/trunk/src/nvcore/ForEach.h +++ b/trunk/src/nvcore/ForEach.h @@ -8,10 +8,8 @@ These foreach macros are very non-standard and somewhat confusing, but I like them. */ - #include "nvcore.h" - #if NV_CC_GNUC // If typeof is available: #define NV_FOREACH(i, container) \ @@ -24,6 +22,8 @@ for(typename typeof(container)::PseudoIndex i((container).start()); !(container) #else // If typeof not available: +#include // placement new + struct PseudoIndexWrapper { template PseudoIndexWrapper(const T & container) { diff --git a/trunk/src/nvcore/Hash.h b/trunk/src/nvcore/Hash.h new file mode 100755 index 0000000..ec691e3 --- /dev/null +++ b/trunk/src/nvcore/Hash.h @@ -0,0 +1,65 @@ +// This code is in the public domain -- Ignacio Castaņo + +#pragma once +#ifndef NV_CORE_HASH_H +#define NV_CORE_HASH_H + +#include "nvcore.h" + +namespace nv +{ + inline uint sdbmHash(const void * data_in, uint size, uint h = 5381) + { + const uint8 * data = (const uint8 *) data_in; + uint i = 0; + while (i < size) { + h = (h << 16) + (h << 6) - h + (uint) data[i++]; + } + return h; + } + + // Note that this hash does not handle NaN properly. + inline uint sdbmFloatHash(const float * f, uint count, uint h = 5381) + { + for (uint i = 0; i < count; i++) { + //nvDebugCheck(nv::isFinite(*f)); + union { float f; uint32 i; } x = { f[i] }; + if (x.i == 0x80000000) x.i = 0; + h = sdbmHash(&x, 4, h); + } + return h; + } + + + // Some hash functors: + template struct Hash + { + uint operator()(const Key & k) const { + return sdbmHash(&k, sizeof(Key)); + } + }; + /*template <> struct Hash + { + uint operator()(int x) const { return x; } + }; + template <> struct Hash + { + uint operator()(uint x) const { return x; } + };*/ + template <> struct Hash + { + uint operator()(float f) const { + return sdbmFloatHash(&f, 1); + } + }; + + template struct Equal + { + bool operator()(const Key & k0, const Key & k1) const { + return k0 == k1; + } + }; + +} // nv namespace + +#endif // NV_CORE_HASH_H diff --git a/trunk/src/nvcore/Memory.h b/trunk/src/nvcore/Memory.h index 52f03fa..79ce674 100644 --- a/trunk/src/nvcore/Memory.h +++ b/trunk/src/nvcore/Memory.h @@ -7,9 +7,9 @@ #include "nvcore.h" #include // malloc(), realloc() and free() -#include // size_t +//#include // size_t -#include // new and delete +//#include // new and delete #if NV_CC_GNUC diff --git a/trunk/src/nvcore/StdStream.h b/trunk/src/nvcore/StdStream.h index 65b91a0..7c0e438 100644 --- a/trunk/src/nvcore/StdStream.h +++ b/trunk/src/nvcore/StdStream.h @@ -1,8 +1,8 @@ // This code is in the public domain -- Ignacio Castaņo -#pragma once -#ifndef NV_CORE_STDSTREAM_H -#define NV_CORE_STDSTREAM_H +//#pragma once +//#ifndef NV_CORE_STDSTREAM_H +//#define NV_CORE_STDSTREAM_H #include "nvcore.h" #include "Stream.h" @@ -10,7 +10,6 @@ #include // fopen #include // memcpy -#include // std::exception namespace nv { @@ -378,7 +377,7 @@ namespace nv len = m_s->serialize( data, len ); if( m_s->isError() ) { - throw std::exception(); + throw; } return len; @@ -389,7 +388,7 @@ namespace nv m_s->seek( pos ); if( m_s->isError() ) { - throw std::exception(); + throw; } } @@ -445,4 +444,4 @@ namespace nv } // nv namespace -#endif // NV_CORE_STDSTREAM_H +//#endif // NV_CORE_STDSTREAM_H diff --git a/trunk/src/nvcore/StrLib.cpp b/trunk/src/nvcore/StrLib.cpp index 83a8887..8572177 100644 --- a/trunk/src/nvcore/StrLib.cpp +++ b/trunk/src/nvcore/StrLib.cpp @@ -2,8 +2,12 @@ #include "StrLib.h" +#include "Memory.h" +#include "Utils.h" // swap + #include // log #include // vsnprintf +#include // strlen, strcmp, etc. #if NV_CC_MSVC #include // vsnprintf @@ -66,6 +70,12 @@ namespace } +uint nv::strLen(const char * str) +{ + nvDebugCheck(str != NULL); + return toU32(strlen(str)); +} + int nv::strCmp(const char * s1, const char * s2) { nvDebugCheck(s1 != NULL); @@ -84,7 +94,28 @@ int nv::strCaseCmp(const char * s1, const char * s2) #endif } -void nv::strCpy(char * dst, int size, const char * src) +bool nv::strEqual(const char * s1, const char * s2) +{ + if (s1 == s2) return true; + if (s1 == NULL || s2 == NULL) return false; + return strCmp(s1, s2) == 0; +} + +bool nv::strBeginsWith(const char * dst, const char * prefix) +{ + //return strstr(dst, prefix) == dst; + return strncmp(dst, prefix, strlen(prefix)) == 0; +} + +// @@ Not tested. +bool nv::strEndsWith(const char * dst, const char * suffix) +{ + const size_t len = strlen(suffix); + return strncmp(dst + strlen(dst) - len, suffix, len) == 0; +} + + +void nv::strCpy(char * dst, uint size, const char * src) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); @@ -96,7 +127,7 @@ void nv::strCpy(char * dst, int size, const char * src) #endif } -void nv::strCpy(char * dst, int size, const char * src, int len) +void nv::strCpy(char * dst, uint size, const char * src, uint len) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); @@ -108,7 +139,7 @@ void nv::strCpy(char * dst, int size, const char * src, int len) #endif } -void nv::strCat(char * dst, int size, const char * src) +void nv::strCat(char * dst, uint size, const char * src) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); @@ -468,6 +499,13 @@ char * StringBuilder::release() return str; } +// Swap strings. +void nv::swap(StringBuilder & a, StringBuilder & b) { + swap(a.m_size, b.m_size); + swap(a.m_str, b.m_str); +} + + /// Get the file name from a path. const char * Path::fileName() const { @@ -604,7 +642,7 @@ void String::setString(const char * str) } } -void String::setString(const char * str, int length) +void String::setString(const char * str, uint length) { nvDebugCheck(str != NULL); @@ -622,3 +660,44 @@ void String::setString(const StringBuilder & str) addRef(); } } + +// Add reference count. +void String::addRef() +{ + if (data != NULL) + { + setRefCount(getRefCount() + 1); + } +} + +// Decrease reference count. +void String::release() +{ + if (data != NULL) + { + const uint16 count = getRefCount(); + setRefCount(count - 1); + if (count - 1 == 0) { + free(data - 2); + data = NULL; + } + } +} + +void String::allocString(const char * str, uint len) +{ + const char * ptr = malloc(2 + len + 1); + + setData( ptr ); + setRefCount( 0 ); + + // Copy string. + strCpy(const_cast(data), len+1, str, len); + + // Add terminating character. + const_cast(data)[len] = '\0'; +} + +void nv::swap(String & a, String & b) { + swap(a.data, b.data); +} diff --git a/trunk/src/nvcore/StrLib.h b/trunk/src/nvcore/StrLib.h index 544fa26..b9dd902 100644 --- a/trunk/src/nvcore/StrLib.h +++ b/trunk/src/nvcore/StrLib.h @@ -4,11 +4,10 @@ #ifndef NV_CORE_STRING_H #define NV_CORE_STRING_H -#include "nvcore.h" -#include "Memory.h" -#include "Utils.h" // swap, hash +#include "Debug.h" +#include "Hash.h" // hash -#include // strlen, strcmp, etc. +//#include // strlen, etc. #if NV_OS_WIN32 #define NV_PATH_SEPARATOR '\\' @@ -19,7 +18,7 @@ namespace nv { - uint strHash(const char * str, uint h) NV_PURE; + NVCORE_API uint strHash(const char * str, uint h) NV_PURE; /// String hash based on Bernstein's hash. inline uint strHash(const char * data, uint h = 5381) @@ -37,18 +36,23 @@ namespace nv }; + NVCORE_API uint strLen(const char * str) NV_PURE; NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE; + NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings. template <> struct Equal { - bool operator()(const char * a, const char * b) const { return strCmp(a, b) == 0; } + bool operator()(const char * a, const char * b) const { return strEqual(a, b); } }; + NVCORE_API bool strBeginsWith(const char * dst, const char * prefix) NV_PURE; + NVCORE_API bool strEndsWith(const char * dst, const char * suffix) NV_PURE; - NVCORE_API void strCpy(char * dst, int size, const char * src); - NVCORE_API void strCpy(char * dst, int size, const char * src, int len); - NVCORE_API void strCat(char * dst, int size, const char * src); + + NVCORE_API void strCpy(char * dst, uint size, const char * src); + NVCORE_API void strCpy(char * dst, uint size, const char * src, uint len); + NVCORE_API void strCat(char * dst, uint size, const char * src); NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE; @@ -110,13 +114,11 @@ namespace nv /// Equal operator. bool operator==( const StringBuilder & s ) const { - if (s.isNull()) return isNull(); - else if (isNull()) return false; - else return strcmp(s.m_str, m_str) != 0; + return strMatch(s.m_str, m_str); } /// Return the exact length. - uint length() const { return isNull() ? 0 : uint(strlen(m_str)); } + uint length() const { return isNull() ? 0 : strLen(m_str); } /// Return the size of the string container. uint capacity() const { return m_size; } @@ -124,11 +126,8 @@ namespace nv /// Return the hash of the string. uint hash() const { return isNull() ? 0 : strHash(m_str); } - /// Swap strings. - friend void swap(StringBuilder & a, StringBuilder & b) { - nv::swap(a.m_size, b.m_size); - nv::swap(a.m_str, b.m_str); - } + // Swap strings. + friend void swap(StringBuilder & a, StringBuilder & b); protected: @@ -242,52 +241,32 @@ namespace nv /// Equal operator. bool operator==( const String & str ) const { - if( str.data == data ) { - return true; - } - if ((data == NULL) != (str.data == NULL)) { - return false; - } - return strcmp(data, str.data) == 0; + return strMatch(str.data, data); } /// Equal operator. bool operator==( const char * str ) const { - nvCheck(str != NULL); // Use isNull! - if (data == NULL) { - return false; - } - return strcmp(data, str) == 0; + return strMatch(str, data); } /// Not equal operator. bool operator!=( const String & str ) const { - if( str.data == data ) { - return false; - } - if ((data == NULL) != (str.data == NULL)) { - return true; - } - return strcmp(data, str.data) != 0; + return !strMatch(str.data, data); } /// Not equal operator. bool operator!=( const char * str ) const { - nvCheck(str != NULL); // Use isNull! - if (data == NULL) { - return false; - } - return strcmp(data, str) != 0; + return !strMatch(str, data); } /// Returns true if this string is the null string. bool isNull() const { return data == NULL; } /// Return the exact length. - uint length() const { nvDebugCheck(data != NULL); return uint(strlen(data)); } + uint length() const { nvDebugCheck(data != NULL); return strLen(data); } /// Return the hash of the string. uint hash() const { nvDebugCheck(data != NULL); return strHash(data); } @@ -302,27 +281,10 @@ namespace nv private: // Add reference count. - void addRef() - { - if (data != NULL) - { - setRefCount(getRefCount() + 1); - } - } + void addRef(); // Decrease reference count. - void release() - { - if (data != NULL) - { - const uint16 count = getRefCount(); - setRefCount(count - 1); - if (count - 1 == 0) { - free(data - 2); - data = NULL; - } - } - } + void release(); uint16 getRefCount() const { @@ -342,31 +304,17 @@ namespace nv void allocString(const char * str) { - allocString(str, (int)strlen(str)); + allocString(str, strLen(str)); } - void allocString(const char * str, int len) - { - const char * ptr = malloc(2 + len + 1); - - setData( ptr ); - setRefCount( 0 ); - - // Copy string. - strCpy(const_cast(data), len+1, str, len); - - // Add terminating character. - const_cast(data)[len] = '\0'; - } + void allocString(const char * str, uint length); void setString(const char * str); - void setString(const char * str, int length); + void setString(const char * str, uint length); void setString(const StringBuilder & str); - /// Swap strings. - friend void swap(String & a, String & b) { - swap(a.data, b.data); - } + // Swap strings. + friend void swap(String & a, String & b); private: diff --git a/trunk/src/nvcore/TextWriter.cpp b/trunk/src/nvcore/TextWriter.cpp index 7205677..5a57c43 100644 --- a/trunk/src/nvcore/TextWriter.cpp +++ b/trunk/src/nvcore/TextWriter.cpp @@ -17,7 +17,7 @@ TextWriter::TextWriter(Stream * s) : void TextWriter::writeString(const char * str) { nvDebugCheck(s != NULL); - s->serialize(const_cast(str), (int)strlen(str)); + s->serialize(const_cast(str), strLen(str)); } void TextWriter::writeString(const char * str, uint len) diff --git a/trunk/src/nvcore/Utils.h b/trunk/src/nvcore/Utils.h index a15e523..2288ca7 100644 --- a/trunk/src/nvcore/Utils.h +++ b/trunk/src/nvcore/Utils.h @@ -4,9 +4,11 @@ #ifndef NV_CORE_UTILS_H #define NV_CORE_UTILS_H -#include "nvcore.h" #include "Debug.h" // nvDebugCheck +#include // for placement new + + // Just in case. Grrr. #undef min #undef max @@ -24,6 +26,10 @@ #define NV_INT64_MIN (-POSH_I64(9223372036854775808)) #define NV_UINT64_MAX POSH_U64(0xffffffffffffffff) +#define NV_HALF_MAX 65504.0F +#define NV_FLOAT_MAX 3.402823466e+38F + + namespace nv { // Less error prone than casting. From CB: @@ -172,59 +178,6 @@ namespace nv } - inline uint sdbmHash(const void * data_in, uint size, uint h = 5381) - { - const uint8 * data = (const uint8 *) data_in; - uint i = 0; - while (i < size) { - h = (h << 16) + (h << 6) - h + (uint) data[i++]; - } - return h; - } - - // Note that this hash does not handle NaN properly. - inline uint sdbmFloatHash(const float * f, uint count, uint h = 5381) - { - for (uint i = 0; i < count; i++) { - //nvDebugCheck(nv::isFinite(*f)); - union { float f; uint32 i; } x = { *f }; - if (x.i == 0x80000000) x.i = 0; - h = sdbmHash(&x, 4, h); - } - return h; - } - - - // Some hash functors: - template struct Hash - { - uint operator()(const Key & k) const { - return sdbmHash(&k, sizeof(Key)); - } - }; - template <> struct Hash - { - uint operator()(int x) const { return x; } - }; - template <> struct Hash - { - uint operator()(uint x) const { return x; } - }; - template <> struct Hash - { - uint operator()(float f) const { - return sdbmFloatHash(&f, 1); - } - }; - - template struct Equal - { - bool operator()(const Key & k0, const Key & k1) const { - return k0 == k1; - } - }; - - // @@ Move this to utils? /// Delete all the elements of a container. template