diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp index 59b14fe2a..b991aa3b9 100644 --- a/include/eepp/core/string.hpp +++ b/include/eepp/core/string.hpp @@ -88,16 +88,22 @@ class EE_API String { static std::string Trim( const std::string & str ); /** Convert the string into upper case string */ - static void ToUpper( std::string & str ); + static void ToUpperInPlace( std::string & str ); - /** Convert the string into lower case string */ - static void ToLower( std::string & str ); + /** Convert a string to lower case */ + static std::string ToUpper( std::string str ); + + /** Convert the reference of a string into lower case string */ + static void ToLowerInPlace( std::string & str ); + + /** Convert a string to lower case */ + static std::string ToLower( std::string str ); /** Convert the string to an std::vector */ static std::vector StringToUint8( const std::string& str ); /** Convert the std::vector to an string */ - static std::string Uint8ToString( const std::vector v ); + static std::string Uint8ToString( const std::vector & v ); /** Insert a char into String on pos (added this function to avoid a bug on String) */ static void InsertChar( String& str, const unsigned int& pos, const Uint32& tchar ); @@ -110,21 +116,24 @@ class EE_API String { static void StrCopy( char * Dst, const char * Src, unsigned int DstSize ); /** Compare two strings from its beginning. - * @param Start String start - * @param Str String to compare - * @return The position of the last char compared ( -1 if fails ) + * @param haystack The string to search in. + * @param needle The searched string. + * @return true if string starts with the substring */ - static Int32 StartsWith( const std::string& Start, const std::string Str ); + static bool StartsWith( const std::string& haystack, const std::string& needle ); /** Compare two strings from its beginning. - * @param Start String start - * @param Str String to compare - * @return The position of the last char compared ( -1 if fails ) + * @param haystack The string to search in. + * @param needle The searched string. + * @return true if string starts with the substring */ - static Int32 StartsWith( const String& Start, const String Str ); + static bool StartsWith( const String& haystack, const String& needle ); - /** Replaces a substring by another string inside a string */ - static void ReplaceSubStr(std::string &target, const std::string& that, const std::string& with ); + /** Replace all occurrences of the search string with the replacement string. */ + static void ReplaceAll( std::string &target, const std::string& that, const std::string& with ); + + /** Replace the first ocurrence of the search string with the replacement string. */ + static void Replace( std::string& target, const std::string& that, const std::string& with ); /** Removes the numbers at the end of the string */ static std::string RemoveNumbersAtEnd( std::string txt ); diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp index f2c1f5f93..b4ea83205 100644 --- a/src/eepp/core/string.cpp +++ b/src/eepp/core/string.cpp @@ -93,7 +93,6 @@ std::vector < std::string > String::Split ( const std::string& str, const Int8& return tmp; } - std::string String::LTrim( const std::string & str ) { std::string::size_type pos1 = str.find_first_not_of(' '); return ( pos1 == std::string::npos ) ? str : str.substr( pos1 ); @@ -105,70 +104,47 @@ std::string String::Trim( const std::string & str ) { return str.substr(pos1 == std::string::npos ? 0 : pos1, pos2 == std::string::npos ? str.length() - 1 : pos2 - pos1 + 1); } -void String::ToUpper( std::string & str ) { +void String::ToUpperInPlace( std::string & str ) { std::transform(str.begin(), str.end(), str.begin(), (int(*)(int)) std::toupper); } -void String::ToLower( std::string & str ) { +std::string String::ToUpper( std::string str ) { + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::toupper(*i)); + return str; +} + +void String::ToLowerInPlace( std::string & str ) { std::transform(str.begin(), str.end(), str.begin(), (int(*)(int)) std::tolower); } +std::string String::ToLower( std::string str ) { + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::tolower(*i)); + return str; +} + std::vector String::StringToUint8( const std::string& str ) { return std::vector( str.begin(), str.end() ); } -std::string String::Uint8ToString( const std::vector v ) { +std::string String::Uint8ToString( const std::vector& v ) { return std::string( v.begin(), v.end() ); } void String::StrCopy( char * Dst, const char * Src, unsigned int DstSize ) { - char * DstEnd = Dst + DstSize - 1; - - while ( Dst < DstEnd && *Src ) { - *Dst = *Src; - Dst++; - Src++; - } - - *Dst = 0; + strncpy( Dst, Src, DstSize ); } -Int32 String::StartsWith( const std::string& Start, const std::string Str ) { - Int32 Pos = -1; - Int32 s = (Int32)Start.size(); - - if ( (Int32)Str.size() >= s ) { - for ( Int32 i = 0; i < s; i++ ) { - if ( Start[i] == Str[i] ) { - Pos = i; - } else { - Pos = -1; - break; - } - } - } - - return Pos; +bool String::StartsWith( const std::string& haystack, const std::string & needle ) { + return needle.length() <= haystack.length() && std::equal(needle.begin(), needle.end(), haystack.begin() ); } -Int32 String::StartsWith( const String& Start, const String Str ) { - Int32 Pos = -1; - - if ( Str.size() >= Start.size() ) { - for ( Uint32 i = 0; i < Start.size(); i++ ) { - if ( Start[i] == Str[i] ) { - Pos = (Int32)i; - } else { - Pos = -1; - break; - } - } - } - - return Pos; +bool String::StartsWith( const String& haystack, const String & needle ) { + return needle.length() <= haystack.length() && std::equal(needle.begin(), needle.end(), haystack.begin() ); } -void String::ReplaceSubStr( std::string &target, const std::string& that, const std::string& with ) { +void String::ReplaceAll( std::string &target, const std::string& that, const std::string& with ) { std::string::size_type pos=0; while( ( pos = target.find( that, pos ) ) != std::string::npos ) { @@ -178,6 +154,15 @@ void String::ReplaceSubStr( std::string &target, const std::string& that, const } } +void String::Replace( std::string& target, const std::string& that, const std::string& with ) { + std::size_t start_pos = target.find( that ); + + if( start_pos == std::string::npos ) + return; + + target.replace( start_pos, that.length(), with ); +} + std::string String::RemoveNumbersAtEnd( std::string txt ) { while ( txt.size() && txt[ txt.size() - 1 ] >= '0' && txt[ txt.size() - 1 ] <= '9' ) { txt.resize( txt.size() - 1 ); diff --git a/src/eepp/graphics/console.cpp b/src/eepp/graphics/console.cpp index 53ea82ee9..16b296c9a 100755 --- a/src/eepp/graphics/console.cpp +++ b/src/eepp/graphics/console.cpp @@ -415,7 +415,7 @@ void Console::PrintCommandsStartingWith( const String& start ) { std::map < String, ConsoleCallback >::iterator it; for ( it = mCallbacks.begin(); it != mCallbacks.end(); it++ ) { - if ( -1 != String::StartsWith( start, it->first ) ) { + if ( String::StartsWith( it->first, start ) ) { cmds.push_back( it->first ); } } @@ -470,7 +470,7 @@ void Console::GetFilesFrom( std::string txt, const Uint32& curPos ) { String res; for ( size_t i = 0; i < files.size(); i++ ) { - if ( !file.size() || -1 != String::StartsWith( file, files[i] ) ) { + if ( !file.size() || String::StartsWith( files[i], file ) ) { res += "\t" + files[i] + "\n"; count++; lasti = i; diff --git a/src/eepp/graphics/shader.cpp b/src/eepp/graphics/shader.cpp index 585d5ad25..7b8123978 100644 --- a/src/eepp/graphics/shader.cpp +++ b/src/eepp/graphics/shader.cpp @@ -155,12 +155,12 @@ void Shader::EnsureVersion() { mSource = "#version 330\nin vec4 gl_Color;\nin vec4 gl_TexCoord[ 1 ];\nout vec4 gl_FragColor;\n" + mSource; } - String::ReplaceSubStr( mSource, "gl_Color" , "dgl_Color" ); - String::ReplaceSubStr( mSource, "gl_TexCoord" , "dgl_TexCoord" ); + String::ReplaceAll( mSource, "gl_Color" , "dgl_Color" ); + String::ReplaceAll( mSource, "gl_TexCoord" , "dgl_TexCoord" ); if ( GLi->Version() == GLv_3CP ) { #ifndef EE_GLES - String::ReplaceSubStr( mSource, "gl_FragColor" , "dgl_FragColor" ); + String::ReplaceAll( mSource, "gl_FragColor" , "dgl_FragColor" ); #endif } } @@ -169,7 +169,7 @@ void Shader::EnsureVersion() { if ( GLi->Version() == GLv_3CP ) { #ifndef EE_GLES - String::ReplaceSubStr( mSource, "texture2D" , "texture" ); + String::ReplaceAll( mSource, "texture2D" , "texture" ); #endif } #endif diff --git a/src/eepp/graphics/textureatlasloader.cpp b/src/eepp/graphics/textureatlasloader.cpp index 087e95af4..bd99ca450 100644 --- a/src/eepp/graphics/textureatlasloader.cpp +++ b/src/eepp/graphics/textureatlasloader.cpp @@ -329,7 +329,7 @@ static bool IsImage( std::string path ) { if ( FileSystem::FileSize( path ) ) { std::string File = path.substr( path.find_last_of("/\\") + 1 ); std::string Ext = File.substr( File.find_last_of(".") + 1 ); - String::ToLower( Ext ); + String::ToLowerInPlace( Ext ); if ( Ext == "png" || Ext == "tga" || diff --git a/src/eepp/network/http.cpp b/src/eepp/network/http.cpp index 45e04a343..8e814547d 100644 --- a/src/eepp/network/http.cpp +++ b/src/eepp/network/http.cpp @@ -8,15 +8,6 @@ using namespace EE::Network::SSL; -namespace { - // Convert a string to lower case - std::string toLower(std::string str) { - for (std::string::iterator i = str.begin(); i != str.end(); ++i) - *i = static_cast(std::tolower(*i)); - return str; - } -} - namespace EE { namespace Network { Http::Request::Request(const std::string& uri, Method method, const std::string& body, bool validateCertificate, bool validateHostname ) : @@ -30,7 +21,7 @@ Http::Request::Request(const std::string& uri, Method method, const std::string& } void Http::Request::SetField(const std::string& field, const std::string& value) { - mFields[toLower(field)] = value; + mFields[String::ToLower(field)] = value; } void Http::Request::SetMethod(Http::Request::Method method) { @@ -107,7 +98,7 @@ std::string Http::Request::Prepare() const { } bool Http::Request::HasField(const std::string& field) const { - return mFields.find(toLower(field)) != mFields.end(); + return mFields.find(String::ToLower(field)) != mFields.end(); } Http::Response::Response() : @@ -118,7 +109,7 @@ Http::Response::Response() : } const std::string& Http::Response::GetField(const std::string& field) const { - FieldTable::const_iterator it = mFields.find(toLower(field)); + FieldTable::const_iterator it = mFields.find(String::ToLower(field)); if (it != mFields.end()) { return it->second; } else { @@ -152,7 +143,7 @@ void Http::Response::Parse(const std::string& data) { if (in >> version) { std::locale loc; if ((version.size() >= 8) && (version[6] == '.') && - (toLower(version.substr(0, 5)) == "http/") && + (String::ToLower(version.substr(0, 5)) == "http/") && std::isdigit(version[5],loc) && std::isdigit(version[7],loc)) { mMajorVersion = version[5] - '0'; mMinorVersion = version[7] - '0'; @@ -184,7 +175,7 @@ void Http::Response::Parse(const std::string& data) { mBody.clear(); // Determine whether the transfer is chunked - if (toLower(GetField("transfer-encoding")) != "chunked") { + if (String::ToLower(GetField("transfer-encoding")) != "chunked") { // Not chunked - everything at once std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(mBody)); } else { @@ -225,7 +216,7 @@ void Http::Response::ParseFields(std::istream &in) { value.erase(value.size() - 1); // Add the field - mFields[toLower(field)] = value; + mFields[String::ToLower(field)] = value; } } } @@ -265,11 +256,11 @@ Http::~Http() { void Http::SetHost(const std::string& host, unsigned short port, bool useSSL) { // Check the protocol - if (toLower(host.substr(0, 7)) == "http://") { + if (String::ToLower(host.substr(0, 7)) == "http://") { // HTTP protocol mHostName = host.substr(7); mPort = (port != 0 ? port : 80); - } else if (toLower(host.substr(0, 8)) == "https://") { + } else if (String::ToLower(host.substr(0, 8)) == "https://") { // HTTPS protocol #ifdef EE_SSL_SUPPORT mIsSSL = true; diff --git a/src/eepp/system/filesystem.cpp b/src/eepp/system/filesystem.cpp index 6cf0b467c..882c6a106 100644 --- a/src/eepp/system/filesystem.cpp +++ b/src/eepp/system/filesystem.cpp @@ -108,7 +108,7 @@ std::string FileSystem::FileExtension( const std::string& filepath, const bool& std::string tstr( filepath.substr( filepath.find_last_of(".") + 1 ) ); if ( lowerExt ) - String::ToLower( tstr ); + String::ToLowerInPlace( tstr ); return tstr; } @@ -128,10 +128,9 @@ std::string FileSystem::FileRemoveFileName( const std::string& filepath ) { void FileSystem::FilePathRemoveProcessPath( std::string& path ) { static std::string ProcessPath = Sys::GetProcessPath(); - Int32 pos = String::StartsWith( ProcessPath, path ); - - if ( -1 != pos && (Uint32)(pos + 1) < path.size() ) - path = path.substr( pos + 1 ); + if ( String::StartsWith( path, ProcessPath ) && ProcessPath.length() < path.size() ) { + path = path.substr( ProcessPath.length() ); + } } diff --git a/src/eepp/ui/tools/textureatlasnew.cpp b/src/eepp/ui/tools/textureatlasnew.cpp index 9812ffda2..5960054ff 100644 --- a/src/eepp/ui/tools/textureatlasnew.cpp +++ b/src/eepp/ui/tools/textureatlasnew.cpp @@ -89,7 +89,7 @@ void TextureAtlasNew::OKClick( const UIEvent * Event ) { if ( MouseEvent->Flags() & EE_BUTTON_LMASK ) { std::string ext( mSaveFileType->Text() ); - String::ToLower( ext ); + String::ToLowerInPlace( ext ); UICommonDialog * TGDialog = mTheme->CreateCommonDialog( NULL, Sizei(), Vector2i(), UI_CONTROL_DEFAULT_FLAGS_CENTERED, UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL, Sizei(), 255, UI_CDL_DEFAULT_FLAGS | CDL_FLAG_SAVE_DIALOG, "*." + ext ); @@ -140,7 +140,7 @@ void TextureAtlasNew::TextureAtlasSave( const UIEvent * Event ) { ext = mSaveFileType->Text(); - String::ToLower( ext ); + String::ToLowerInPlace( ext ); FPath += "." + ext; } diff --git a/src/eepp/window/engine.cpp b/src/eepp/window/engine.cpp index 9752efa82..4d2497736 100755 --- a/src/eepp/window/engine.cpp +++ b/src/eepp/window/engine.cpp @@ -282,7 +282,7 @@ WindowSettings Engine::CreateWindowSettings( IniFile * ini, std::string iniKeyNa std::string Backend = ini->GetValue( iniKeyName, "Backend", "" ); Uint32 WinBackend = GetDefaultBackend(); - String::ToLower( Backend ); + String::ToLowerInPlace( Backend ); if ( "sdl2" == Backend ) WinBackend = WindowBackend::SDL2; else if ( "sdl" == Backend ) WinBackend = WindowBackend::SDL; @@ -325,7 +325,7 @@ ContextSettings Engine::CreateContextSettings( IniFile * ini, std::string iniKey bool VSync = ini->GetValueB( iniKeyName, "VSync", true ); std::string GLVersion = ini->GetValue( iniKeyName, "GLVersion", "0" ); - String::ToLower( GLVersion ); + String::ToLowerInPlace( GLVersion ); EEGL_version GLVer; if ( "3" == GLVersion || "opengl 3" == GLVersion || "gl3" == GLVersion || "opengl3" == GLVersion ) GLVer = GLv_3; diff --git a/src/examples/external_shader/external_shader.cpp b/src/examples/external_shader/external_shader.cpp index fe0caf8c3..256e2804e 100644 --- a/src/examples/external_shader/external_shader.cpp +++ b/src/examples/external_shader/external_shader.cpp @@ -241,7 +241,7 @@ EE_MAIN_FUNC int main (int argc, char * argv []) /// Since fixed-pipeline OpenGL use gl_FrontColor for glColorPointer, we need to replace the color attribute /// This is all to show how it works, in a real world scenario, you will choose to work fixed-pipeline or programmable-pipeline. if ( GLi->Version() == GLv_2 ) { - String::ReplaceSubStr( fs, "gl_FragColor = dgl_Color", "gl_FragColor = gl_FrontColor" ); + String::ReplaceAll( fs, "gl_FragColor = dgl_Color", "gl_FragColor = gl_FrontColor" ); } /// Create the new shader program