diff --git a/Misc/Misc.vcxproj b/Misc/Misc.vcxproj index 7e2973b1..76714140 100644 --- a/Misc/Misc.vcxproj +++ b/Misc/Misc.vcxproj @@ -24,13 +24,13 @@ - Application + StaticLibrary true v110 MultiByte - Application + StaticLibrary true v110 MultiByte diff --git a/Misc/Utilities.cpp b/Misc/Utilities.cpp index c3046aeb..502541b2 100644 --- a/Misc/Utilities.cpp +++ b/Misc/Utilities.cpp @@ -5,23 +5,25 @@ #include "Utilities.h" #include -#include using ::std::vector; using ::std::string; +using ::std::wstring; namespace Utility { // PRIVATE STATIC //////////////////////////////////////////////////// namespace PrivateStatic { - const ::std::locale systemDefaultLocale = ::std::locale(); + const ::std::locale system_default_locale = ::std::locale(); } // STRING //////////////////////////////////////////////////////////// namespace String { - vector & split( vector &output, const string &str, char delim, string::size_type offset ) + // string + + vector & Split( vector &output, const string &str, char delim, string::size_type offset ) { if( str.length() > 0 ) { @@ -42,13 +44,13 @@ namespace Utility { if( delimPos > offset ) output.push_back( str.substr( offset, delimPos - offset ) ); - String::split( output, str, delim, delimPos + 1 ); + String::Split( output, str, delim, delimPos + 1 ); } } return output; } - vector & split( vector &output, const string &str, const string &delim, string::size_type offset ) + vector & Split( vector &output, const string &str, const string &delim, string::size_type offset ) { if( str.length() > 0 ) { @@ -62,13 +64,13 @@ namespace Utility { if( delimPos > offset ) output.push_back( str.substr( offset, delimPos - offset ) ); - String::split( output, str, delim, delimPos + delim.length() ); + String::Split( output, str, delim, delimPos + delim.length() ); } } return output; } - vector & split( vector &output, const string &str, const vector &delim, string::size_type offset ) + vector & Split( vector &output, const string &str, const vector &delim, string::size_type offset ) { if( str.length() > 0 ) { @@ -94,13 +96,13 @@ namespace Utility { if( firstDelimPos > offset ) output.push_back( str.substr( offset, firstDelimPos - offset ) ); - String::split( output, str, delim, firstDelimPos + delim[delimRef].length() ); + String::Split( output, str, delim, firstDelimPos + delim[delimRef].length() ); } } return output; } - string trim( const string &str ) + string Trim( const string &str ) { string::size_type first = 0, last = str.length(); @@ -128,7 +130,7 @@ namespace Utility return str.substr( first, (++last) - first ); } - string & toLowerCase( string &output, const string &str ) + string & ToLowerCase( string &output, const string &str ) { int length = (int)str.length(); output.resize( length ); @@ -137,7 +139,7 @@ namespace Utility return output; } - string & toLowerCase( string &str ) + string & ToLowerCase( string &str ) { int length = (int)str.length(); for( int i = 0; i < length; ++i ) @@ -145,7 +147,7 @@ namespace Utility return str; } - string & toUpperCase( string &output, const string &str ) + string & ToUpperCase( string &output, const string &str ) { int length = (int)str.length(); output.resize( length ); @@ -154,7 +156,7 @@ namespace Utility return output; } - string & toUpperCase( string &str ) + string & ToUpperCase( string &str ) { int length = (int)str.length(); for( int i = 0; i < length; ++i ) @@ -162,14 +164,14 @@ namespace Utility return str; } - string & extractDirPath( string &output, const string &file, char dirDelimeter ) + string & ExtractDirPath( string &output, const string &file, char dirDelimeter ) { string d = " "; d[0] = dirDelimeter; - return String::extractDirPath( output, file, d ); + return String::ExtractDirPath( output, file, d ); } - string & extractDirPath( string &output, const string &file, const string &dirDelimeter ) + string & ExtractDirPath( string &output, const string &file, const string &dirDelimeter ) { string::size_type end = file.find_last_of( dirDelimeter ); if( end == string::npos ) @@ -185,7 +187,7 @@ namespace Utility return output; } - string & replaceCharacters( string &str, char characterToReplace, char newCharacter, const string::size_type &offset, const string::size_type &end ) + string & ReplaceCharacters( string &str, char characterToReplace, char newCharacter, const string::size_type &offset, const string::size_type &end ) { string::size_type i = offset; while( true ) @@ -197,12 +199,94 @@ namespace Utility } return str; } + + // wstring + + vector & Split( vector &output, const wstring &str, char delim, wstring::size_type offset ) + { + if( str.length() > 0 ) + { + while( offset < str.length() ) // trim + { + if( str[offset] == delim ) + ++offset; + else break; + } + + wstring::size_type delimPos = str.find_first_of( delim, offset ); + if( delimPos == wstring::npos ) + { + if( str.length() > offset ) + output.push_back( str.substr( offset, str.length() - offset ) ); + } + else + { + if( delimPos > offset ) + output.push_back( str.substr( offset, delimPos - offset ) ); + String::Split( output, str, delim, delimPos + 1 ); + } + } + return output; + } + + vector & Split( vector &output, const wstring &str, const wstring &delim, wstring::size_type offset ) + { + if( str.length() > 0 ) + { + wstring::size_type delimPos = str.find_first_of( delim, offset ); + if( delimPos == wstring::npos ) + { + if( str.length() > offset ) + output.push_back( str.substr( offset, str.length() - offset ) ); + } + else + { + if( delimPos > offset ) + output.push_back( str.substr( offset, delimPos - offset ) ); + String::Split( output, str, delim, delimPos + delim.length() ); + } + } + return output; + } + + vector & Split( vector &output, const wstring &str, const vector &delim, wstring::size_type offset ) + { + if( str.length() > 0 ) + { + wstring::size_type firstDelimPos = str.length(), delimPos; + + vector::size_type numDelims = delim.size(), delimRef = 0; + for( vector::size_type i = 0; i < numDelims ; ++i ) + { + delimPos = str.find_first_of( delim[i], offset ); + if( delimPos != wstring::npos ) if( delimPos < firstDelimPos ) + { + delimRef = i; + firstDelimPos = delimPos; + } + } + + if( firstDelimPos == str.length() ) + { + if( str.length() > offset ) + output.push_back( str.substr( offset, str.length() - offset ) ); + } + else + { + if( firstDelimPos > offset ) + output.push_back( str.substr( offset, firstDelimPos - offset ) ); + String::Split( output, str, delim, firstDelimPos + delim[delimRef].length() ); + } + } + return output; + } + } // STREAM //////////////////////////////////////////////////////////// namespace Stream { - float* readFloats( float *output, ::std::istream &input, unsigned int numFloats ) + float* ReadFloats( float *output, ::std::istream &input, unsigned int numFloats ) { string str; for( unsigned int i = 0; i < numFloats; ++i ) diff --git a/Misc/Utilities.h b/Misc/Utilities.h index aa9128c3..ba6e0c3a 100644 --- a/Misc/Utilities.h +++ b/Misc/Utilities.h @@ -11,69 +11,241 @@ #include #include #include +#include namespace Utility { + namespace Memory + { + template + struct UniquePointer + { + public: + UniquePointer( Type *assignedMemory = NULL ); + ~UniquePointer(); + + UniquePointer & operator = ( Type *assignedMemory ); + UniquePointer & operator = ( const UniquePointer &donor ); + + operator Type* (); + operator const Type* () const; + Type * operator -> (); + const Type * operator -> () const; + template Type & operator [] ( Index i ); + template const Type & operator [] ( Index i ) const; + + operator bool () const; + + Type* Release(); + bool haveOwnership() const; + + private: + mutable Type *ownedMemory; + }; + + // IMPLEMENTATIONS //////////////////////////////////////////////// + + template + UniquePointer::UniquePointer( Type *assignedMemory ) + { this->ownedMemory = assignedMemory; } + + template + UniquePointer::~UniquePointer() + { if( this->ownedMemory ) delete this->ownedMemory; } + + template + UniquePointer & UniquePointer::operator = ( Type *assignedMemory ) + { + if( this->ownedPointer ) delete this->ownedMemory; + this->ownedMemory = assignedMemory; + return *this; + } + + template + UniquePointer & UniquePointer::operator = ( const UniquePointer &donor ) + { + if( this->ownedMemory ) delete this->ownedMemory; + this->ownedMemory = donor.ownedMemory; + donor.ownedMemory = NULL; + return *this; + } + + template + UniquePointer::operator Type* () + { return this->ownedMemory; } + + template + UniquePointer::operator const Type* () const + { return this->ownedMemory; } + + template + Type * UniquePointer::operator -> () + { return this->ownedMemory; } + + template + const Type * UniquePointer::operator -> () const + { return this->ownedMemory; } + + template template + Type & UniquePointer::operator [] ( Index i ) + { return this->ownedMemory[i]; } + + template template + const Type & UniquePointer::operator [] ( Index i ) const + { return this->ownedMemory[i]; } + + template + UniquePointer::operator bool() const + { return this->ownedMemory != NULL; } + + template + Type* UniquePointer::Release() + { + Type *copy = this->ownedMemory; + this->ownedMemory = NULL; + return copy; + } + + template + inline bool UniquePointer::haveOwnership() const + { return this->operator bool(); } + } + namespace String { - // note to self: add a whitespaceSplit method? - ::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 ); - ::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 ); - ::std::vector<::std::string> & split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 ); - ::std::string trim( const ::std::string &str ); - ::std::string & toLowerCase( ::std::string &output, const ::std::string &str ); - ::std::string & toLowerCase( ::std::string &str ); - ::std::string & toUpperCase( ::std::string &output, const ::std::string &str ); - ::std::string & toUpperCase( ::std::string &str ); - ::std::string & extractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter ); - ::std::string & extractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter ); - ::std::string & replaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos ); + // string + + ::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 ); + ::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 ); + ::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 ); + ::std::string Trim( const ::std::string &str ); + ::std::string & ToLowerCase( ::std::string &output, const ::std::string &str ); + ::std::string & ToLowerCase( ::std::string &str ); + ::std::string & ToUpperCase( ::std::string &output, const ::std::string &str ); + ::std::string & ToUpperCase( ::std::string &str ); + ::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter ); + ::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter ); + ::std::string & ReplaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos ); + + // wstring + + ::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, char delim, ::std::wstring::size_type offset = 0 ); + ::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::wstring &delim, ::std::wstring::size_type offset = 0 ); + ::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::vector<::std::wstring> &delim, ::std::wstring::size_type offset = 0 ); } namespace Stream { - float* readFloats( float *output, ::std::istream &input, unsigned int numFloats ); + float* ReadFloats( float *output, ::std::istream &input, unsigned int numFloats ); } namespace StaticArray { - template - inline unsigned int numElementsOf( const ElementType(&)[num] ) + template + inline unsigned int NumElementsOf( const ScalarType(&)[num] ) { return num; } + + template + inline ScalarType & FirstElementOf( ScalarType (&arr)[num] ) + { return arr[0]; } + + template + inline ScalarType & LastElementOf( ScalarType (&arr)[num] ) + { return arr[num-1]; } } namespace Element { - template - inline void swap( ElementType &elementA, ElementType &elementB, ElementType &swapSpace ) + template + inline void Swap( ScalarType &elementA, ScalarType &elementB, ScalarType &swapSpace ) { swapSpace = elementA; elementA = elementB; elementB = swapSpace; } - template - inline void swap( ElementType &elementA, ElementType &elementB ) - { ElementType swapSpace; swap( elementA, elementB, swapSpace ); } + template + inline void Swap( ScalarType &elementA, ScalarType &elementB ) + { ScalarType swapSpace; Swap( elementA, elementB, swapSpace ); } } namespace Value { + using ::std::numeric_limits; + template - inline ValueType abs( const ValueType &value ) + inline ValueType Abs( const ValueType &value ) { return value < 0 ? value * -1 : value; } template - inline ValueType max( const ValueType &valueA, const ValueType &valueB ) + inline ValueType Max( const ValueType &valueA, const ValueType &valueB ) { return valueA > valueB ? valueA : valueB; } template - inline ValueType min( const ValueType &valueA, const ValueType &valueB ) + inline ValueType Min( const ValueType &valueA, const ValueType &valueB ) { return valueA < valueB ? valueA : valueB; } template - inline ValueType radian( const ValueType °ree ) + inline ValueType Average( const ValueType &valueA, const ValueType &valueB ) + { return (valueA + valueB) * 0.5f; } + + template + inline ValueType AverageWithDelta( const ValueType &origin, const ValueType &delta ) + { return origin + (delta * 0.5f); } + + template + inline ValueType Radian( const ValueType °ree ) { return degree * (3.1415926535897932384626433832795f / 180.0f); } template - inline ValueType degree( const ValueType &radian ) + inline ValueType Degree( const ValueType &radian ) { return radian * (180.0f / 3.1415926535897932384626433832795f); } + + // SPECIALIZATIONS ////////////////////////////////////////// + + template<> inline char Average( const char &valueA, const char &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline unsigned char Average( const unsigned char &valueA, const unsigned char &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline int Average( const int &valueA, const int &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline unsigned int Average( const unsigned int &valueA, const unsigned int &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline long Average( const long &valueA, const long &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline unsigned long Average( const unsigned long &valueA, const unsigned long &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline long long Average( const long long &valueA, const long long &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline unsigned long long Average( const unsigned long long &valueA, const unsigned long long &valueB ) + { return (valueA + valueB) >> 1; } + + template<> inline char AverageWithDelta( const char &origin, const char &delta ) + { return origin + (delta >> 1); } + + template<> inline unsigned char AverageWithDelta( const unsigned char &origin, const unsigned char &delta ) + { return origin + (delta >> 1); } + + template<> inline int AverageWithDelta( const int &origin, const int &delta ) + { return origin + (delta >> 1); } + + template<> inline unsigned int AverageWithDelta( const unsigned int &origin, const unsigned int &delta ) + { return origin + (delta >> 1); } + + template<> inline long AverageWithDelta( const long &origin, const long &delta ) + { return origin + (delta >> 1); } + + template<> inline unsigned long AverageWithDelta( const unsigned long &origin, const unsigned long &delta ) + { return origin + (delta >> 1); } + + template<> inline long long AverageWithDelta( const long long &origin, const long long &delta ) + { return origin + (delta >> 1); } + + template<> inline unsigned long long AverageWithDelta( const unsigned long long &origin, const unsigned long long &delta ) + { return origin + (delta >> 1); } } }