diff --git a/include/cinder/Utilities.h b/include/cinder/Utilities.h index 586e86c7af..b66eee353f 100644 --- a/include/cinder/Utilities.h +++ b/include/cinder/Utilities.h @@ -92,11 +92,73 @@ inline double fromString( const std::string &s ) { return atof( s.c_str() ); } CI_API bool asciiCaseEqual( const std::string &a, const std::string &b ); //! returns \c true if ASCII strings \a a and \a b are case-insensitively equal. Not Unicode-aware. CI_API bool asciiCaseEqual( const char *a, const char *b ); -//! returns equivalent of strcmp() using ASCII case-insensitive comparison +//! returns equivalent of strcmp() using ASCII case-insensitive comparison. Not Unicode-aware. CI_API int asciiCaseCmp( const char *a, const char *b ); +//! removes all whitespace (as defined by std::isspace()) from the beginning of \a str. Unicode aware. +CI_API void trimLeftInPlace( std::string &str ); +//! removes all whitespace (as defined by std::isspace()) from the beginning of \a str and returns a copy. Unicode aware. +CI_API std::string trimLeft( std::string str ); + +//! removes all whitespace (as defined by std::isspace()) from the end of \a str. Unicode aware. +CI_API void trimRightInPlace( std::string &str ); +//! removes all whitespace (as defined by std::isspace()) from the end of \a str and returns a copy. Unicode aware. +CI_API std::string trimRight( std::string str ); + +//! removes all whitespace (as defined by std::isspace()) removed from beginning and end of \a str. Unicode aware. +CI_API void trimInPlace( std::string &str ); //! returns a copy of \a str with all whitespace (as defined by std::isspace()) removed from beginning and end. Unicode aware. -CI_API std::string trim( const std::string &str ); +CI_API std::string trim( std::string str ); + +//! removes all specified \a characters from the beginning of \a str. Not Unicode-aware. +CI_API void trimLeftInPlace( std::string &str, const std::string &characters ); +//! removes all specified \a characters from the beginning of \a str. Not Unicode-aware. +CI_API std::string trimLeft( std::string str, const std::string &characters ); + +//! removes all specified \a characters from the end of \a str. Not Unicode-aware. +CI_API void trimRightInPlace( std::string &str, const std::string &characters ); +//! removes all specified \a characters from the end of \a str. Not Unicode-aware. +CI_API std::string trimRight( std::string str, const std::string &characters ); + +//! removes all specified \a characters from \a str. Not Unicode-aware. +CI_API void trimInPlace( std::string &str, const std::string &characters ); +//! removes all specified \a characters from \a str. Not Unicode-aware. +CI_API std::string trim( std::string str, const std::string &characters ); + +//! removes all occurrences of any of \a characters in \a str. Not Unicode-aware. +CI_API void filterInPlace( std::string &str, const std::string &characters ); +//! returns a copy of \a str with all occurrences of any of \a characters removed. Not Unicode-aware. +CI_API std::string filter( std::string str, const std::string &characters ); + +//! Converts the character \a c to lowercase. Not Unicode-aware. +CI_API char charToLower( const char c ); +//! Converts the character \a c to uppercase. Not Unicode-aware. +CI_API char charToUpper( const char c ); + +//! converts all characters to lowercase (using std::tolower()) in \a str. Not Unicode-aware. +CI_API void toLowerInPlace( std::string &str ); +//! returns a copy of \a str with all characters converted to lowercase (using std::tolower()). Not Unicode-aware. +CI_API std::string toLower( std::string str ); +//! converts all characters to uppercase (using std::toupper()) in \a str.Not Unicode-aware. +CI_API void toUpperInPlace( std::string &str ); +//! returns a copy of \a str with all characters converted to uppercase (using std::toupper()). Not Unicode-aware. +CI_API std::string toUpper( std::string str ); + +//! replaces all instances of \a find with \a replace in \a str. Unicode-aware. +CI_API void findReplaceInPlace( std::string &str, const std::string &find, const std::string &replace ); +//! replaces all instances of \a find with \a replace in \a str and returns a copy. Unicode-aware. +CI_API std::string findReplace( std::string str, const std::string &find, const std::string &replace ); + +//! returns whether character \a c is considered white space. Not Unicode-aware. +CI_API bool isWhiteSpace( char c ); +//! returns whether character \a c is a digit (0-9). Not Unicode-aware. +CI_API bool isDigit( char c ); +//! returns whether character \a c is a hexadecimal digit (0-9)+(a-f). Not Unicode-aware. +CI_API bool isHexDigit( char c ); +//! returns whether character \a c is alphabetic (a-z). Not Unicode-aware. +CI_API bool isAlpha( char c ); +//! returns whether character \a c is numeric (0-9)+(.+-eE). Not Unicode-aware. +CI_API bool isNumeric( char c ); //! Returns a stack trace (aka backtrace) where \c stackTrace()[0] == caller, \c stackTrace()[1] == caller's parent, etc CI_API std::vector stackTrace(); diff --git a/src/cinder/Utilities.cpp b/src/cinder/Utilities.cpp index d4f2ee3886..0c30ea2dcf 100644 --- a/src/cinder/Utilities.cpp +++ b/src/cinder/Utilities.cpp @@ -171,11 +171,219 @@ int asciiCaseCmp( const char *a, const char *b ) return ((int)std::toupper(*a)) - ((int)std::toupper(*b)); } -std::string trim( const std::string &str ) +void trimLeftInPlace( std::string &str ) { - size_t wsFront = str.find_first_not_of( " \f\n\r\t\v" ); - size_t wsBack = str.find_last_not_of( " \f\n\r\t\v" ); - return wsBack <= wsFront ? std::string() : str.substr( wsFront, wsBack - wsFront + 1 ); + str.erase( str.begin(), std::find_if( str.begin(), str.end(), []( std::string::value_type ch ) { return !std::isspace( ch ); } ) ); +} + +std::string trimLeft( std::string str ) +{ + trimLeftInPlace( str ); + return str; +} + +void trimRightInPlace( std::string &str ) +{ + str.erase( std::find_if( str.rbegin(), str.rend(), []( std::string::value_type ch ) { return !std::isspace( ch ); } ).base(), str.end() ); +} + +std::string trimRight( std::string str ) +{ + trimRightInPlace( str ); + return str; +} + +void trimInPlace( std::string &str ) +{ + trimLeftInPlace( str ); + trimRightInPlace( str ); +} + +std::string trim( std::string str ) +{ + trimInPlace( str ); + return str; +} + +void trimLeftInPlace( std::string &str, const std::string &characters ) +{ + str.erase( str.begin(), std::find_if( str.begin(), str.end(), [characters]( std::string::value_type ch ) { return characters.find( ch ) == std::string::npos; } ) ); +} + +std::string trimLeft( std::string str, const std::string &characters ) +{ + trimLeftInPlace( str, characters ); + return str; +} + +void trimRightInPlace( std::string &str, const std::string &characters ) +{ + str.erase( std::find_if( str.rbegin(), str.rend(), [characters]( std::string::value_type ch ) { return characters.find( ch ) == std::string::npos; } ).base(), str.end() ); +} + +std::string trimRight( std::string str, const std::string &characters ) +{ + trimRightInPlace( str, characters ); + return str; +} + +void trimInPlace( std::string &str, const std::string &characters ) +{ + trimLeftInPlace( str, characters ); + trimRightInPlace( str, characters ); +} + +std::string trim( std::string str, const std::string &characters ) +{ + trimInPlace( str, characters ); + return str; +} + +void filterInPlace( std::string &str, const std::string &characters ) +{ + str.erase( std::remove_if( str.begin(), str.end(), [characters]( char c ) { return characters.find( c ) != std::string::npos; } ), str.end() ); +} + +std::string filter( std::string str, const std::string &characters ) +{ + filterInPlace( str, characters ); + return str; +} + +char charToLower( const char c ) +{ + if( c >= 'A' && c <= 'Z' ) + return char( c + 32 ); + return c; +} + +char charToUpper( const char c ) +{ + if( c >= 'a' && c <= 'z' ) + return char( c - 32 ); + return c; +} + +void toLowerInPlace( std::string &str ) +{ + std::transform( str.begin(), str.end(), str.begin(), []( unsigned char c ) { return std::tolower( c ); } ); +} + +std::string toLower( std::string str ) +{ + toLowerInPlace( str ); + return str; +} + +void toUpperInPlace( std::string &str ) +{ + std::transform( str.begin(), str.end(), str.begin(), []( unsigned char c ) { return std::toupper( c ); } ); +} + +std::string toUpper( std::string str ) +{ + toUpperInPlace( str ); + return str; +} + +void findReplaceInPlace( std::string &str, const std::string &find, const std::string &replace ) +{ + auto pos = str.find( find ); + while( pos != std::string::npos ) { + str.replace( pos, find.length(), replace ); + pos = str.find( find, pos + replace.length() ); + } +} + +std::string findReplace( std::string str, const std::string &find, const std::string &replace ) +{ + findReplaceInPlace( str, find, replace ); + return str; +} + +bool isWhiteSpace( char c ) +{ + return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f'; +} + +bool isDigit( char c ) +{ + return !( c < '0' || c > '9' ); +} + +bool isHexDigit( char c ) +{ + c = charToLower( c ); + return isDigit( c ) || c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f'; +} + +bool isAlpha( char c ) +{ + c = charToLower( c ); + return !( c < 'a' || c > 'z' ); +} + +bool isNumeric( char c ) +{ + return isDigit( c ) || c == '.' || c == '-' || c == 'e' || c == 'E' || c == '+'; +} + +std::string valueToString( int value ) +{ + return std::to_string( value ); +} + +std::string valueToString( unsigned value ) +{ + return std::to_string( value ); +} + +std::string valueToString( long value ) +{ + return std::to_string( value ); +} + +std::string valueToString( unsigned long value ) +{ + return std::to_string( value ); +} + +std::string valueToString( long long value ) +{ + return std::to_string( value ); +} + +std::string valueToString( unsigned long long value ) +{ + return std::to_string( value ); +} + +std::string valueToString( float value ) +{ + std::string str = std::to_string( value ); + trimRightInPlace( str, "0.," ); + return str; +} + +std::string valueToString( float value, int precision ) +{ + std::ostringstream str; + str << std::fixed << std::setprecision( precision ) << value; + return str.str(); +} + +std::string valueToString( double value ) +{ + std::string str = std::to_string( value ); + trimRightInPlace( str, "0.," ); + return str; +} + +std::string valueToString( double value, int precision ) +{ + std::ostringstream str; + str << std::fixed << std::setprecision( precision ) << value; + return str.str(); } void sleep( float milliseconds )