From 594a1ba33acefccf786a6fa4c0f9d869b963237a Mon Sep 17 00:00:00 2001 From: Billiard26 Date: Wed, 10 Nov 2010 04:12:31 +0000 Subject: [PATCH] StringUtil cleanup. Nothing seems broken. git-svn-id: http://dolphin-emu.googlecode.com/svn/trunk@6367 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/FileUtil.cpp | 1 - Source/Core/Common/Src/IniFile.cpp | 10 +- Source/Core/Common/Src/MemoryUtil.cpp | 2 +- Source/Core/Common/Src/StringUtil.cpp | 747 +++++++-------------- Source/Core/Common/Src/StringUtil.h | 69 +- Source/Core/Core/Src/ActionReplay.cpp | 8 +- Source/Core/Core/Src/CoreRerecording.cpp | 2 +- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp | 2 +- .../Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 2 +- Source/Core/Core/Src/PatchEngine.cpp | 18 +- Source/Core/DebuggerWX/Src/BreakpointWindow.cpp | 2 +- Source/Core/DebuggerWX/Src/MemoryWindow.cpp | 4 +- Source/Core/DebuggerWX/Src/RegisterView.cpp | 2 +- Source/Core/DiscIO/Src/FileMonitor.cpp | 2 +- Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp | 4 +- Source/Core/DolphinWX/Src/FrameAui.cpp | 10 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 2 - Source/Core/DolphinWX/Src/ISOProperties.cpp | 4 +- Source/Core/VideoCommon/Src/HiresTextures.cpp | 2 - Source/UnitTests/UnitTests.cpp | 32 + 20 files changed, 352 insertions(+), 573 deletions(-) rewrite Source/Core/Common/Src/StringUtil.cpp (66%) diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 9e8e2ac4c..bf57fbdd1 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -180,7 +180,6 @@ bool CreateFullPath(const char *fullPath) // safety check to ensure we have good dir seperators std::string strFullPath(fullPath); - NormalizeDirSep(&strFullPath); const char *position = strFullPath.c_str(); while (true) { diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index 85a88bc7f..83001574d 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -181,7 +181,7 @@ bool IniFile::Section::Get(const char* key, int* value, int defaultValue) { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParseInt(temp.c_str(), value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -191,7 +191,7 @@ bool IniFile::Section::Get(const char* key, u32* value, u32 defaultValue) { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParseUInt(temp.c_str(), value)) + if (retval && TryParse(temp, value)) return true; *value = defaultValue; return false; @@ -201,7 +201,7 @@ bool IniFile::Section::Get(const char* key, bool* value, bool defaultValue) { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParseBool(temp.c_str(), value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -211,7 +211,7 @@ bool IniFile::Section::Get(const char* key, float* value, float defaultValue) { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParseFloat(temp.c_str(), value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -221,7 +221,7 @@ bool IniFile::Section::Get(const char* key, double* value, double defaultValue) { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParseDouble(temp.c_str(), value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index 68b9f6f0f..f23165597 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -140,7 +140,7 @@ std::string MemUsage() if (NULL == hProcess) return "MemUsage Error"; if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) - Ret = StringFromFormat("%s K", ThS((int)(pmc.WorkingSetSize / 1024), true, 7).c_str()); + Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str()); CloseHandle(hProcess); return Ret; diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp dissimilarity index 66% index 7926939f2..7264085ac 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -1,498 +1,249 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include -#include - -#include "Common.h" -#include "CommonPaths.h" -#include "StringUtil.h" - -// faster than sscanf -bool AsciiToHex(const char* _szValue, u32& result) -{ - char *endptr = NULL; - u32 value = strtoul(_szValue,&endptr,16); - if (!endptr || *endptr != '\0') - return false; - result = value; - return true; -} - -// Convert AB to it's ascii table entry numbers 0x4142 -u32 Ascii2Hex(std::string _Text) -{ - // Reset the return value zero - u32 Result = 0; - - // Max 32-bit values are supported - size_t Length = _Text.length(); - if (Length > 4) - Length = 4; - - for (int i = 0; i < (int)Length; i++) - { - // Add up the values, for example RSPE becomes, 0x52000000, then 0x52530000 and so on - Result += _Text.c_str()[i] << ((Length - 1 - i) * 8); - } - // Return the value - return Result; -} - -// Convert it back again -std::string Hex2Ascii(u32 _Text) -{ - // Create temporary storate - char Result[5]; // need space for the final \0 - // Go through the four characters - sprintf(Result, "%c%c%c%c", _Text >> 24, _Text >> 16, _Text >> 8, _Text); - // Return the string - std::string StrResult = Result; - return StrResult; -} - -bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) -{ - int writtenCount = vsnprintf(out, outsize, format, args); - - if (writtenCount > 0 && writtenCount < outsize) - { - out[writtenCount] = '\0'; - return true; - } - else - { - out[outsize - 1] = '\0'; - return false; - } -} - -// Expensive! -void ToStringFromFormat(std::string* out, const char* format, ...) -{ - int writtenCount = -1; - int newSize = (int)strlen(format) + 4; - char *buf = 0; - va_list args; - while (writtenCount < 0) - { - delete [] buf; - buf = new char[newSize + 1]; - - va_start(args, format); - writtenCount = vsnprintf(buf, newSize, format, args); - va_end(args); - if (writtenCount >= (int)newSize) { - writtenCount = -1; - } - // ARGH! vsnprintf does no longer return -1 on truncation in newer libc! - // WORKAROUND! let's fake the old behaviour (even though it's less efficient). - // TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :( -// if (writtenCount >= (int)newSize) -// writtenCount = -1; - newSize *= 2; - } - - buf[writtenCount] = '\0'; - *out = buf; - delete[] buf; -} - -std::wstring StringFromFormat(const wchar_t* format, ...) -{ - int writtenCount = -1; - int newSize = (int)wcslen(format) + 4; - wchar_t *buf = 0; - va_list args; - while (writtenCount < 0) - { - delete [] buf; - buf = new wchar_t[newSize + 1]; - - va_start(args, format); - writtenCount = vswprintf(buf, newSize, format, args); - va_end(args); - if (writtenCount >= (int)newSize) { - writtenCount = -1; - } - // ARGH! vsnprintf does no longer return -1 on truncation in newer libc! - // WORKAROUND! let's fake the old behaviour (even though it's less efficient). - // TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :( -// if (writtenCount >= (int)newSize) -// writtenCount = -1; - newSize *= 2; - } - - buf[writtenCount] = '\0'; - std::wstring temp = buf; - delete[] buf; - return temp; -} -std::string StringFromFormat(const char* format, ...) -{ - int writtenCount = -1; - int newSize = (int)strlen(format) + 4; - char *buf = 0; - va_list args; - while (writtenCount < 0) - { - delete [] buf; - buf = new char[newSize + 1]; - - va_start(args, format); - writtenCount = vsnprintf(buf, newSize, format, args); - va_end(args); - if (writtenCount >= (int)newSize) { - writtenCount = -1; - } - // ARGH! vsnprintf does no longer return -1 on truncation in newer libc! - // WORKAROUND! let's fake the old behaviour (even though it's less efficient). - // TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :( -// if (writtenCount >= (int)newSize) -// writtenCount = -1; - newSize *= 2; - } - - buf[writtenCount] = '\0'; - std::string temp = buf; - delete[] buf; - return temp; -} - -// For Debugging. Read out an u8 array. -std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len, bool Spaces) -{ - std::string Tmp, Spc; - if (Spaces) Spc = " "; else Spc = ""; - for (u32 i = 0; i < size; i++) - { - Tmp += StringFromFormat("%02x%s", data[i + offset], Spc.c_str()); - if(i > 1 && (i + 1) % line_len == 0) Tmp.append("\n"); // break long lines - } - return Tmp; -} - -// Turns " hej " into "hej". Also handles tabs. -std::string StripSpaces(const std::string &str) -{ - std::string s = str; - int i; - for (i = 0; i < (int)s.size(); i++) - { - if ((s[i] != ' ') && (s[i] != 9)) - { - break; - } - } - - s = s.substr(i); - - for (i = (int)s.size() - 1; i > 0; i--) - { - if ((s[i] != ' ') && (s[i] != 9)) - { - break; - } - } - - return s.substr(0, i + 1); -} - -// "\"hello\"" is turned to "hello" -// This one assumes that the string has already been space stripped in both -// ends, as done by StripSpaces above, for example. -std::string StripQuotes(const std::string& s) -{ - if ((s[0] == '\"') && (s[s.size() - 1] == '\"')) - return s.substr(1, s.size() - 2); - else - return s; -} - -// "\"hello\"" is turned to "hello" -// This one assumes that the string has already been space stripped in both -// ends, as done by StripSpaces above, for example. -std::string StripNewline(const std::string& s) -{ - if (!s.size()) - return s; - else if (s[s.size() - 1] == '\n') - return s.substr(0, s.size() - 1); - else - return s; -} - -bool TryParseInt(const char* str, int* outVal) -{ - char *endptr = NULL; - int value = strtol(str,&endptr,10); - if (!endptr || *endptr != '\0') - return false; - *outVal = value; - return true; -} - -bool TryParseBool(const char* str, bool* output) -{ - if ((str[0] == '1') || !strcasecmp(str, "true")) - { - *output = true; - return true; - } - else if (str[0] == '0' || !strcasecmp(str, "false")) - { - *output = false; - return true; - } - return false; -} - -bool TryParseFloat(const char* str, float *output) -{ - float d_val; - if (sscanf(str, "%f", &d_val) == 1) - { - *output = (float)d_val; - return true; - } - else - { - return false; - } -} - -bool TryParseDouble(const char* str, double *output) -{ - return sscanf(str, "%lf", output) == 1; -} - -std::string StringFromInt(int value) -{ - char temp[16]; - sprintf(temp, "%i", value); - return std::string(temp); -} - -std::string StringFromBool(bool value) -{ - return value ? "True" : "False"; -} - -#ifdef _WIN32 -bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) -{ - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - - if (_splitpath_s(full_path.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT) == 0) - { - if (_pPath) - { - *_pPath = std::string(drive) + std::string(dir); - } - - if (_pFilename != 0) - { - *_pFilename = fname; - } - - if (_pExtension != 0) - { - *_pExtension = ext; - } - - return true; - } - - return false; -} - - -#else -bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) -{ - size_t last_slash = full_path.rfind('/'); - - if (last_slash == std::string::npos) - { - return false; // FIXME return the filename - } - - size_t last_dot = full_path.rfind('.'); - - if ((last_dot == std::string::npos) || (last_dot < last_slash)) - { - return false; // FIXME why missing . is critical? - } - - if (_pPath) - { - *_pPath = full_path.substr(0, last_slash + 1); - } - - if (_pFilename) - { - *_pFilename = full_path.substr(last_slash + 1, last_dot - (last_slash + 1)); - } - - if (_pExtension) - { - *_pExtension = full_path.substr(last_dot + 1); - _pExtension->insert(0, "."); - } - else if (_pFilename) - { - *_pFilename += full_path.substr(last_dot); - } - - return true; -} -#endif - - -void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename) -{ - _CompleteFilename = _Path; - - // check for seperator - if (_CompleteFilename[_CompleteFilename.size() - 1] != DIR_SEP_CHR) - { -#ifdef _WIN32 - if (_CompleteFilename[_CompleteFilename.size() - 1] != '\\') -#endif - _CompleteFilename += DIR_SEP_CHR; - } - - // add the filename - _CompleteFilename += _Filename; -} - - -void SplitString(const std::string& str, const std::string& delim, std::vector& output) -{ - output.clear(); - - size_t offset = 0; - size_t delimIndex = 0; - - delimIndex = str.find(delim, offset); - - while (delimIndex != std::string::npos) - { - output.push_back(str.substr(offset, delimIndex - offset)); - offset += delimIndex - offset + delim.length(); - delimIndex = str.find(delim, offset); - } - - output.push_back(str.substr(offset)); -} - - -bool TryParseUInt(const std::string& str, u32* output) -{ - char *endptr = NULL; - u32 value = strtoul(str.c_str(),&endptr,0); - if (!endptr || *endptr != '\0') - return false; - *output = value; - return true; -} - -int ChooseStringFrom(const char* str, const char* * items) -{ - int i = 0; - while (items[i] != 0) - { - if (!strcmp(str, items[i])) - return i; - i++; - } - return -1; -} - - -// Thousand separator. Turns 12345678 into 12,345,678 -std::string ThS(int Integer, bool Unsigned, int Spaces) -{ - // Create storage space - char cbuf[20]; - // Determine treatment of signed or unsigned - if(Unsigned) sprintf(cbuf, "%u", Integer); else sprintf(cbuf, "%i", Integer); - - std::string Sbuf = cbuf; - for (u32 i = 0; i < Sbuf.length(); ++i) - { - if((i & 3) == 3) - { - Sbuf.insert(Sbuf.length() - i, ","); - } - } - - // Spaces - std::string Spc = ""; - for (int i = 0; i < (int)(Spaces - Sbuf.length()); i++) Spc += " "; - return Spc + Sbuf; -} - -void NormalizeDirSep(std::string* str) -{ -#ifdef _WIN32 - int i; - while ((i = (int)str->find_first_of('\\')) >= 0) - { - str->replace(i, 1, DIR_SEP); - } -#endif -} - -std::string TabsToSpaces(int tab_size, const std::string &in) -{ - std::string out; - int len = 0; - // First, compute the size of the new string. - for (unsigned i = 0; i < in.size(); i++) - { - if (in[i] == '\t') - len += tab_size; - else - len += 1; - } - out.resize(len); - int out_ctr = 0; - for (unsigned i = 0; i < in.size(); i++) - { - if (in[i] == '\t') - { - for (int j = 0; j < tab_size; j++) - out[out_ctr++] = ' '; - } - else - { - out[out_ctr++] = in[i]; - } - } - return out; -} - -std::string PathToFilename(std::string Path) -{ - std::string Name, Ending; - SplitPath(Path, 0, &Name, &Ending); - return Name + Ending; -} +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include + +#include "Common.h" +#include "CommonPaths.h" +#include "StringUtil.h" + +// faster than sscanf +bool AsciiToHex(const char* _szValue, u32& result) +{ + char *endptr = NULL; + const u32 value = strtoul(_szValue, &endptr, 16); + + if (!endptr || *endptr) + return false; + + result = value; + return true; +} + +bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) +{ + int writtenCount = vsnprintf(out, outsize, format, args); + + if (writtenCount > 0 && writtenCount < outsize) + { + out[writtenCount] = '\0'; + return true; + } + else + { + out[outsize - 1] = '\0'; + return false; + } +} + +std::string StringFromFormat(const char* format, ...) +{ + int writtenCount = -1; + size_t newSize = strlen(format) + 4; + char *buf = NULL; + va_list args; + while (writtenCount < 0) + { + delete[] buf; + buf = new char[newSize + 1]; + + va_start(args, format); + writtenCount = vsnprintf(buf, newSize, format, args); + va_end(args); + + if (writtenCount >= (int)newSize) + writtenCount = -1; + + // ARGH! vsnprintf does no longer return -1 on truncation in newer libc! + // WORKAROUND! let's fake the old behaviour (even though it's less efficient). + // TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :( +// if (writtenCount >= (int)newSize) +// writtenCount = -1; + newSize *= 2; + } + + buf[writtenCount] = '\0'; + std::string temp = buf; + delete[] buf; + return temp; +} + +// For Debugging. Read out an u8 array. +std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces) +{ + std::ostringstream oss; + oss << std::setfill('0') << std::hex; + + for (int line = 0; size; ++data, --size) + { + oss << std::setw(2) << (int)*data; + + if (line_len == ++line) + { + oss << '\n'; + line = 0; + } + else if (spaces) + oss << ' '; + } + + return oss.str(); +} + +// Turns " hej " into "hej". Also handles tabs. +std::string StripSpaces(const std::string &str) +{ + const size_t s = str.find_first_not_of(" \t\r\n"); + + if (str.npos != s) + return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); + else + return ""; +} + +// "\"hello\"" is turned to "hello" +// This one assumes that the string has already been space stripped in both +// ends, as done by StripSpaces above, for example. +std::string StripQuotes(const std::string& s) +{ + if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) + return s.substr(1, s.size() - 2); + else + return s; +} + +// "\"hello\"" is turned to "hello" +// This one assumes that the string has already been space stripped in both +// ends, as done by StripSpaces above, for example. +std::string StripNewline(const std::string& s) +{ + if (s.size() && '\n' == *s.rbegin()) + return s.substr(0, s.size() - 1); + else + return s; +} + +bool TryParse(const std::string &str, u32 *const output) +{ + char *endptr = NULL; + u32 value = strtoul(str.c_str(), &endptr, 0); + + if (!endptr || *endptr) + return false; + + *output = value; + return true; +} + +bool TryParse(const std::string &str, bool *const output) +{ + if ('1' == str[0] || !stricmp("true", str.c_str())) + *output = true; + else if ('0' == str[0] || !stricmp("false", str.c_str())) + *output = false; + else + return false; + + return true; +} + +std::string StringFromInt(int value) +{ + char temp[16]; + sprintf(temp, "%i", value); + return temp; +} + +std::string StringFromBool(bool value) +{ + return value ? "True" : "False"; +} + +bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) +{ + if (full_path.empty()) + return false; + + size_t dir_end = full_path.find_last_of("/" + // windows needs the : included for something like just "C:" to be considered a directory +#ifdef _WIN32 + ":" +#endif + ); + if (std::string::npos == dir_end) + dir_end = 0; + else + dir_end += 1; + + size_t fname_end = full_path.rfind('.'); + if (fname_end < dir_end || std::string::npos == fname_end) + fname_end = full_path.size(); + + if (_pPath) + *_pPath = full_path.substr(0, dir_end); + + if (_pFilename) + *_pFilename = full_path.substr(dir_end, fname_end - dir_end); + + if (_pExtension) + *_pExtension = full_path.substr(fname_end); + + return true; +} + +std::string PathToFilename(const std::string &Path) +{ + std::string Name, Ending; + SplitPath(Path, 0, &Name, &Ending); + return Name + Ending; +} + +void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename) +{ + _CompleteFilename = _Path; + + // check for seperator + if (DIR_SEP_CHR != *_CompleteFilename.rbegin()) + _CompleteFilename += DIR_SEP_CHR; + + // add the filename + _CompleteFilename += _Filename; +} + +void SplitString(const std::string& str, const char delim, std::vector& output) +{ + std::istringstream iss(str); + output.resize(1); + + while (std::getline(iss, *output.rbegin(), delim)) + output.push_back(""); + + output.pop_back(); +} + +std::string TabsToSpaces(int tab_size, const std::string &in) +{ + const std::string spaces(tab_size, ' '); + std::string out(in); + + size_t i = 0; + while (out.npos != (i = out.find('\t'))) + out.replace(i, 1, spaces); + + return out; +} diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index 9868c30df..e3502eaa6 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -22,22 +22,15 @@ #include #include +#include +#include #include "Common.h" -std::wstring StringFromFormat(const wchar_t* format, ...); std::string StringFromFormat(const char* format, ...); -void ToStringFromFormat(std::string* out, const char* format, ...); - -// WARNING - only call once with a set of args! -void StringFromFormatV(std::string* out, const char* format, va_list args); // Cheap! bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args); -// Good -std::string ArrayToString(const u8 *data, u32 size, u32 offset = 0, int line_len = 20, bool Spaces = true); - - template inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...) { @@ -47,49 +40,57 @@ inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...) va_end(args); } -std::wstring StripSpaces(const std::wstring &s); -std::wstring StripQuotes(const std::wstring &s); -//std::wstring StripNewline(const std::string &s); -// Thousand separator. Turns 12345678 into 12,345,678 -//std::wstring ThS(int a, bool b = true, int Spaces = 0); +// Good +std::string ArrayToString(const u8 *data, u32 size, int line_len = 20, bool spaces = true); + std::string StripSpaces(const std::string &s); std::string StripQuotes(const std::string &s); std::string StripNewline(const std::string &s); + // Thousand separator. Turns 12345678 into 12,345,678 -std::string ThS(int a, bool b = true, int Spaces = 0); +template +std::string ThousandSeparate(I value, int spaces = 0) +{ + std::ostringstream oss; + oss.imbue(std::locale("")); + oss << std::setw(spaces) << value; + + return oss.str(); +} -std::wstring StringFromIntW(int value); -std::wstring StringFromBoolW(bool value); std::string StringFromInt(int value); std::string StringFromBool(bool value); -bool TryParseInt(const wchar_t* str, int* outVal); -bool TryParseBool(const wchar_t* str, bool* output); -bool TryParseUInt(const std::wstring& str, u32* output); -bool TryParseInt(const char* str, int* outVal); -bool TryParseBool(const char* str, bool* output); -bool TryParseUInt(const std::string& str, u32* output); -bool TryParseFloat(const char* str, float *output); -bool TryParseDouble(const char* str, double *output); +bool TryParse(const std::string &str, bool *output); +bool TryParse(const std::string &str, u32 *output); +template +bool TryParse(const std::string &str, N *const output) +{ + std::istringstream iss(str); + + N tmp = 0; + if (iss >> tmp) + { + *output = tmp; + return true; + } + else + return false; +} // TODO: kill this bool AsciiToHex(const char* _szValue, u32& result); -u32 Ascii2Hex(std::string _Text); -std::string Hex2Ascii(u32 _Text); std::string TabsToSpaces(int tab_size, const std::string &in); -void SplitString(const std::string& str, const std::string& delim, std::vector& output); -int ChooseStringFrom(const char* str, const char* * items); - +void SplitString(const std::string& str, char delim, std::vector& output); -// "C:\Windows\winhelp.exe" to "C:\Windows\", "winhelp", "exe" +// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe" bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension); -// "C:\Windows\winhelp.exe" to "winhelp.exe" -std::string PathToFilename(std::string Path); +// "C:/Windows/winhelp.exe" to "winhelp.exe" +std::string PathToFilename(const std::string &Path); void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename); -void NormalizeDirSep(std::string* str); #endif // _STRINGUTIL_H_ diff --git a/Source/Core/Core/Src/ActionReplay.cpp b/Source/Core/Core/Src/ActionReplay.cpp index 4ab9ee62f..1ceac4cc1 100644 --- a/Source/Core/Core/Src/ActionReplay.cpp +++ b/Source/Core/Core/Src/ActionReplay.cpp @@ -184,14 +184,14 @@ void LoadCodes(IniFile &ini, bool forceLoad) continue; } - SplitString(line, " ", pieces); + SplitString(line, ' ', pieces); // Check if the AR code is decrypted if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) { AREntry op; - bool success_addr = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); - bool success_val = TryParseUInt(std::string("0x") + pieces[1], &op.value); + bool success_addr = TryParse(std::string("0x") + pieces[0], &op.cmd_addr); + bool success_val = TryParse(std::string("0x") + pieces[1], &op.value); if (!(success_addr | success_val)) { PanicAlert("Action Replay Error: invalid AR code line: %s", line.c_str()); if (!success_addr) PanicAlert("The address is invalid"); @@ -202,7 +202,7 @@ void LoadCodes(IniFile &ini, bool forceLoad) } else { - SplitString(line, "-", pieces); + SplitString(line, '-', pieces); if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 && pieces[2].size() == 5) { // Encrypted AR code diff --git a/Source/Core/Core/Src/CoreRerecording.cpp b/Source/Core/Core/Src/CoreRerecording.cpp index f544a5515..351963f31 100644 --- a/Source/Core/Core/Src/CoreRerecording.cpp +++ b/Source/Core/Core/Src/CoreRerecording.cpp @@ -213,7 +213,7 @@ void FrameStepOnOff() void WriteStatus() { std::string TmpStr = "Time: " + ReRecTimer.GetTimeElapsedFormatted(); - TmpStr += StringFromFormat(" Frame: %s", ThS(g_FrameCounter).c_str()); + TmpStr += StringFromFormat(" Frame: %s", ThousandSeparate(g_FrameCounter).c_str()); // The FPS is the total average since the game was booted TmpStr += StringFromFormat(" FPS: %i", (g_FrameCounter * 1000) / ReRecTimer.GetTimeElapsed()); TmpStr += StringFromFormat(" FrameStep: %s", g_FrameStep ? "On" : "Off"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp index 1481be2c8..ba8224dcb 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp @@ -197,7 +197,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), 0, _BufferOutSize); INFO_LOG(WII_IPC_DVD, "DVDLowReadDiskID %s", - ArrayToString(Memory::GetPointer(_BufferOut), _BufferOutSize, 0, _BufferOutSize).c_str()); + ArrayToString(Memory::GetPointer(_BufferOut), _BufferOutSize, _BufferOutSize).c_str()); } break; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 3c4c01b8a..e8ca0a037 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -895,7 +895,7 @@ namespace Core INFO_LOG(WIIMOTE, "===================="); INFO_LOG(WIIMOTE, "Callback_WiimoteInterruptChannel: (Wiimote: #%i)", _number); - DEBUG_LOG(WIIMOTE, " Data: %s", ArrayToString(pData, _Size, 0, 50).c_str()); + DEBUG_LOG(WIIMOTE, " Data: %s", ArrayToString(pData, _Size, 50).c_str()); DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID); s_Usb->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size); diff --git a/Source/Core/Core/Src/PatchEngine.cpp b/Source/Core/Core/Src/PatchEngine.cpp index 29328c419..1d82d20e1 100644 --- a/Source/Core/Core/Src/PatchEngine.cpp +++ b/Source/Core/Core/Src/PatchEngine.cpp @@ -30,6 +30,8 @@ #include #include #include +#include + #include "StringUtil.h" #include "PatchEngine.h" #include "HW/Memmap.h" @@ -48,7 +50,6 @@ const char *PatchTypeStrings[] = "byte", "word", "dword", - 0 }; std::vector onFrame; @@ -88,14 +89,15 @@ void LoadPatchSection(const char *section, std::vector &patches, IniFile line.at(loc) = ':'; std::vector items; - SplitString(line, ":", items); + SplitString(line, ':', items); if (items.size() >= 3) { PatchEntry pE; bool success = true; - success = success && TryParseUInt(items[0], &pE.address); - success = success && TryParseUInt(items[2], &pE.value); - pE.type = (PatchType)ChooseStringFrom(items[1].c_str(), PatchTypeStrings); - success = success && (pE.type != (PatchType)-1); + success &= TryParse(items[0], &pE.address); + success &= TryParse(items[2], &pE.value); + + pE.type = PatchType(std::find(PatchTypeStrings, PatchTypeStrings + 3, items[1]) - PatchTypeStrings); + success &= (pE.type != (PatchType)3); if (success) currentPatch.entries.push_back(pE); } @@ -131,8 +133,8 @@ static void LoadSpeedhacks(const char *section, std::map &hacks, IniFi u32 address; u32 cycles; bool success = true; - success = success && TryParseUInt(std::string(key.c_str()), &address); - success = success && TryParseUInt(value, &cycles); + success &= TryParse(key, &address); + success &= TryParse(value, &cycles); if (success) { speedHacks[address] = (int)cycles; } diff --git a/Source/Core/DebuggerWX/Src/BreakpointWindow.cpp b/Source/Core/DebuggerWX/Src/BreakpointWindow.cpp index d8a1c3b43..ffa2ffaf9 100644 --- a/Source/Core/DebuggerWX/Src/BreakpointWindow.cpp +++ b/Source/Core/DebuggerWX/Src/BreakpointWindow.cpp @@ -195,7 +195,7 @@ void CBreakPointWindow::OnAddMemoryCheckMany() { std::string line = StripSpaces(*iter); std::vector pieces; - SplitString(line, " ", pieces); // split string + SplitString(line, ' ', pieces); // split string TMemCheck MemCheck; u32 sAddress = 0; diff --git a/Source/Core/DebuggerWX/Src/MemoryWindow.cpp b/Source/Core/DebuggerWX/Src/MemoryWindow.cpp index 995aee74d..933bd12f3 100644 --- a/Source/Core/DebuggerWX/Src/MemoryWindow.cpp +++ b/Source/Core/DebuggerWX/Src/MemoryWindow.cpp @@ -157,13 +157,13 @@ void CMemoryWindow::SetMemoryValue(wxCommandEvent& event) u32 addr; u32 val; - if (!TryParseUInt(std::string("0x") + str_addr, &addr)) + if (!TryParse(std::string("0x") + str_addr, &addr)) { PanicAlert("Invalid Address: %s", str_addr.c_str()); return; } - if (!TryParseUInt(std::string("0x") + str_val, &val)) + if (!TryParse(std::string("0x") + str_val, &val)) { PanicAlert("Invalid Value: %s", str_val.c_str()); return; diff --git a/Source/Core/DebuggerWX/Src/RegisterView.cpp b/Source/Core/DebuggerWX/Src/RegisterView.cpp index 8edbdf479..52e5e3a9b 100644 --- a/Source/Core/DebuggerWX/Src/RegisterView.cpp +++ b/Source/Core/DebuggerWX/Src/RegisterView.cpp @@ -90,7 +90,7 @@ static void SetSpecialRegValue(int reg, u32 value) { void CRegTable::SetValue(int row, int col, const wxString& strNewVal) { u32 newVal = 0; - if (TryParseUInt(std::string(strNewVal.mb_str()), &newVal)) + if (TryParse(std::string(strNewVal.mb_str()), &newVal)) { if (row < 32) { if (col == 1) diff --git a/Source/Core/DiscIO/Src/FileMonitor.cpp b/Source/Core/DiscIO/Src/FileMonitor.cpp index ba95f0609..c05bd3f22 100644 --- a/Source/Core/DiscIO/Src/FileMonitor.cpp +++ b/Source/Core/DiscIO/Src/FileMonitor.cpp @@ -103,7 +103,7 @@ void CheckFile(std::string File, u64 Size) if (CurrentFile == File) return; if (Size > 0) Size = (Size / 1000); - std::string Str = StringFromFormat("%s kB %s", ThS(Size, true, 7).c_str(), File.c_str()); + std::string Str = StringFromFormat("%s kB %s", ThousandSeparate(Size, 7).c_str(), File.c_str()); if (ShowSound(File)) { NOTICE_LOG(FILEMON, Str.c_str()); diff --git a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp index 146324b1f..fcd2a52ec 100644 --- a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp @@ -112,7 +112,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) std::vector pieces; std::string line_str = cheatValues.substr(line, cheatValues.find('\n', line) - line); - SplitString(line_str, " ", pieces); + SplitString(line_str, ' ', pieces); if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) { @@ -123,7 +123,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) } else { - SplitString(line_str, "-", pieces); + SplitString(line_str, '-', pieces); if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 && pieces[2].size() == 5) { diff --git a/Source/Core/DolphinWX/Src/FrameAui.cpp b/Source/Core/DolphinWX/Src/FrameAui.cpp index 86649273b..aed79b482 100644 --- a/Source/Core/DolphinWX/Src/FrameAui.cpp +++ b/Source/Core/DolphinWX/Src/FrameAui.cpp @@ -811,7 +811,7 @@ void CFrame::LoadIniPerspectives() ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); ini.Get("Perspectives", "Perspectives", &_Perspectives, "Perspective 1"); ini.Get("Perspectives", "Active", &ActivePerspective, 0); - SplitString(_Perspectives, ",", VPerspectives); + SplitString(_Perspectives, ',', VPerspectives); for (u32 i = 0; i < VPerspectives.size(); i++) { @@ -833,17 +833,17 @@ void CFrame::LoadIniPerspectives() Tmp.Perspective = wxString::FromAscii(_Perspective.c_str()); - SplitString(_Width, ",", _SWidth); - SplitString(_Height, ",", _SHeight); + SplitString(_Width, ',', _SWidth); + SplitString(_Height, ',', _SHeight); for (u32 j = 0; j < _SWidth.size(); j++) { int _Tmp; - if (TryParseInt(_SWidth[j].c_str(), &_Tmp)) Tmp.Width.push_back(_Tmp); + if (TryParse(_SWidth[j].c_str(), &_Tmp)) Tmp.Width.push_back(_Tmp); } for (u32 j = 0; j < _SHeight.size(); j++) { int _Tmp; - if (TryParseInt(_SHeight[j].c_str(), &_Tmp)) Tmp.Height.push_back(_Tmp); + if (TryParse(_SHeight[j].c_str(), &_Tmp)) Tmp.Height.push_back(_Tmp); } Perspectives.push_back(Tmp); } diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index c0b01c5d7..485b7a42d 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -542,10 +542,8 @@ void CGameListCtrl::ScanForISOs() if (FST_Temp.children.at(j).isDirectory) { bool duplicate = false; - NormalizeDirSep(&(FST_Temp.children.at(j).physicalName)); for (u32 k = 0; k < Directories.size(); k++) { - NormalizeDirSep(&Directories.at(k)); if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0) { diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 5f427e77d..7ecda54a7 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -1138,9 +1138,7 @@ void CISOProperties::PatchList_Save() for (std::vector::const_iterator iter2 = onFrame_it->entries.begin(); iter2 != onFrame_it->entries.end(); ++iter2) { - std::string temp; - - ToStringFromFormat(&temp, "0x%08X:%s:0x%08X", iter2->address, PatchEngine::PatchTypeStrings[iter2->type], iter2->value); + std::string temp = StringFromFormat("0x%08X:%s:0x%08X", iter2->address, PatchEngine::PatchTypeStrings[iter2->type], iter2->value); lines.push_back(temp); } ++index; diff --git a/Source/Core/VideoCommon/Src/HiresTextures.cpp b/Source/Core/VideoCommon/Src/HiresTextures.cpp index d584895b5..3d70cfcc1 100644 --- a/Source/Core/VideoCommon/Src/HiresTextures.cpp +++ b/Source/Core/VideoCommon/Src/HiresTextures.cpp @@ -49,10 +49,8 @@ void Init(const char *gameCode) if (FST_Temp.children.at(j).isDirectory) { bool duplicate = false; - NormalizeDirSep(&(FST_Temp.children.at(j).physicalName)); for (u32 k = 0; k < Directories.size(); k++) { - NormalizeDirSep(&Directories.at(k)); if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0) { duplicate = true; diff --git a/Source/UnitTests/UnitTests.cpp b/Source/UnitTests/UnitTests.cpp index c732ea3d1..e2a1975c5 100644 --- a/Source/UnitTests/UnitTests.cpp +++ b/Source/UnitTests/UnitTests.cpp @@ -93,11 +93,43 @@ void MathTests() void StringTests() { EXPECT_EQ(StripSpaces(" abc "), "abc"); + EXPECT_EQ(StripNewline(" abc \n"), " abc "); EXPECT_EQ(StripNewline(" abc \n "), " abc \n "); + EXPECT_EQ(StripQuotes("\"abc\""), "abc"); EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" "); + EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b"); + EXPECT_EQ(ThousandSeparate(1234567, 15), " 1,234,567"); + + int i = 7; + EXPECT_EQ(false, TryParse("FF", &i)); + EXPECT_EQ(7, i); + EXPECT_EQ(true, TryParse("22", &i)); + EXPECT_EQ(22, i); + + std::vector strs; + SplitString("blah,foo,bar", ',', strs); + + EXPECT_EQ(3, strs.size()); + EXPECT_EQ("bar", strs[2]); + + std::string path, fname, ext; + SplitPath("C:/some/path/test.jpg", &path, &fname, &ext); + EXPECT_EQ("C:/some/path/", path); + EXPECT_EQ("test", fname); + EXPECT_EQ(".jpg", ext); + + SplitPath("C:/so.me/path/", &path, &fname, &ext); + EXPECT_EQ("C:/so.me/path/", path); + EXPECT_EQ("", fname); + EXPECT_EQ("", ext); + + SplitPath("test.file.jpg", &path, &fname, &ext); + EXPECT_EQ("", path); + EXPECT_EQ("test.file", fname); + EXPECT_EQ(".jpg", ext); } -- 2.11.4.GIT