diff --git a/renderdoc/3rdparty/catch/catch.cpp b/renderdoc/3rdparty/catch/catch.cpp index 65f9d9179..5240616c7 100644 --- a/renderdoc/3rdparty/catch/catch.cpp +++ b/renderdoc/3rdparty/catch/catch.cpp @@ -44,21 +44,21 @@ struct AppVeyorListener : Catch::TestEventListenerBase { using TestEventListenerBase::TestEventListenerBase; // inherit constructor - std::string errorList; + rdcstr errorList; double durationInSeconds = 0.0; struct TestCase { double durationInSeconds; bool passed; - std::string errorList; - std::string name; - std::string filename; + rdcstr errorList; + rdcstr name; + rdcstr filename; - std::string MakeJSON(); + rdcstr MakeJSON(); }; - std::vector m_testcases; + rdcarray m_testcases; virtual bool assertionEnded(Catch::AssertionStats const &assertionStats) override { @@ -153,7 +153,7 @@ struct AppVeyorListener : Catch::TestEventListenerBase if(!sep) return; - std::string hostname = std::string(url, sep); + rdcstr hostname = rdcstr(url, sep - url); url = sep + 1; @@ -169,7 +169,7 @@ struct AppVeyorListener : Catch::TestEventListenerBase if(sock) { - std::string json; + rdcstr json; json += "[\n"; for(size_t i = 0; i < m_testcases.size(); i++) @@ -183,7 +183,7 @@ struct AppVeyorListener : Catch::TestEventListenerBase } json += "]"; - std::string http; + rdcstr http; http += StringFormat::Fmt("POST /api/tests/batch HTTP/1.1\r\n"); http += StringFormat::Fmt("Host: %s\r\n", hostname.c_str()); http += "Connection: close\r\n"; @@ -201,11 +201,11 @@ struct AppVeyorListener : Catch::TestEventListenerBase } }; -static std::string escape(const std::string &input) +static rdcstr escape(const rdcstr &input) { - std::string ret = input; - size_t i = ret.find_first_of("\"\n\\", 0); - while(i != std::string::npos) + rdcstr ret = input; + int i = ret.find_first_of("\"\n\\", 0); + while(i >= 0) { if(ret[i] == '"') ret.replace(i, 1, "\\\""); @@ -220,9 +220,11 @@ static std::string escape(const std::string &input) return ret; } -std::string AppVeyorListener::TestCase::MakeJSON() +rdcstr AppVeyorListener::TestCase::MakeJSON() { - std::string json; + rdcstr json; + + errorList.trim(); return StringFormat::Fmt( R"({ @@ -237,7 +239,7 @@ std::string AppVeyorListener::TestCase::MakeJSON() "StdErr": "" })", escape(name).c_str(), escape(filename).c_str(), passed ? "Passed" : "Failed", - (int)RDCMAX(durationInSeconds * 1000.0, 0.0), escape(trim(errorList)).c_str()); + (int)RDCMAX(durationInSeconds * 1000.0, 0.0), escape(errorList).c_str()); } CATCH_REGISTER_LISTENER(AppVeyorListener) diff --git a/renderdoc/android/android.cpp b/renderdoc/android/android.cpp index c05f11b41..5cdab768b 100644 --- a/renderdoc/android/android.cpp +++ b/renderdoc/android/android.cpp @@ -24,7 +24,6 @@ #include "android.h" #include -#include #include "api/replay/version.h" #include "core/core.h" #include "core/remote_server.h" @@ -78,14 +77,14 @@ std::string GetDefaultActivityForPackage(const std::string &deviceID, const std: return ""; } - std::vector lines; + rdcarray lines; split(activity.strStdout, lines, '\n'); - for(std::string &line : lines) + for(rdcstr &line : lines) { - line = trim(line); + line.trim(); - if(!strncmp(line.c_str(), "name=", 5)) + if(line.beginsWith("name=")) { return line.substr(5); } @@ -108,25 +107,23 @@ std::string GetDefaultActivityForPackage(const std::string &deviceID, const std: size_t numOfLines = lines.size(); const char *intentFilter = "android.intent.action.MAIN:"; - size_t intentFilterSize = strlen(intentFilter); for(size_t idx = 0; idx < numOfLines; idx++) { - std::string line = trim(lines[idx]); - if(!strncmp(line.c_str(), intentFilter, intentFilterSize) && idx + 1 < numOfLines) + lines[idx].trim(); + + if(lines[idx].beginsWith(intentFilter) && idx + 1 < numOfLines) { - std::string activityName = trim(lines[idx + 1]); - size_t startPos = activityName.find("/"); - if(startPos == std::string::npos) + rdcstr activityName = lines[idx + 1].trimmed(); + int startPos = activityName.find('/'); + if(startPos < 0) { RDCWARN("Failed to find default activity"); return ""; } - size_t endPos = activityName.find(" ", startPos + 1); - if(endPos == std::string::npos) - { - endPos = activityName.length(); - } + int endPos = activityName.find(' ', startPos + 1); + if(endPos < 0) + endPos = activityName.count(); return activityName.substr(startPos + 1, endPos - startPos - 1); } } @@ -143,22 +140,24 @@ int GetCurrentPID(const std::string &deviceID, const std::string &packageName) Process::ProcessResult pidOutput = adbExecCommand(deviceID, StringFormat::Fmt("shell ps -A | grep %s", packageName.c_str())); - std::string output = trim(pidOutput.strStdout); - size_t space = output.find_first_of("\t "); + rdcstr &output = pidOutput.strStdout; + + output.trim(); + int space = output.find_first_of("\t "); // if we didn't get a response, try without the -A as some android devices don't support that // parameter - if(output.empty() || output.find(packageName) == std::string::npos || space == std::string::npos) + if(output.empty() || output.find(packageName) == -1 || space == -1) { pidOutput = adbExecCommand(deviceID, StringFormat::Fmt("shell ps | grep %s", packageName.c_str())); - output = trim(pidOutput.strStdout); + output.trim(); space = output.find_first_of("\t "); } // if we still didn't get a response, sleep and try again next time - if(output.empty() || output.find(packageName) == std::string::npos || space == std::string::npos) + if(output.empty() || output.find(packageName) == -1 || space == -1) { Threading::Sleep(200); continue; @@ -190,14 +189,15 @@ bool CheckAndroidServerVersion(const std::string &deviceID, ABI abi) if(dump.empty()) RDCERR("Unable to pm dump %s", packageName.c_str()); - std::string versionCode = trim(GetFirstMatchingLine(dump, "versionCode=")); - std::string versionName = trim(GetFirstMatchingLine(dump, "versionName=")); + rdcstr versionCode = GetFirstMatchingLine(dump, "versionCode=").trimmed(); + rdcstr versionName = GetFirstMatchingLine(dump, "versionName=").trimmed(); // versionCode is not alone in this line, isolate it if(versionCode != "") { - size_t spaceOffset = versionCode.find(' '); - versionCode.erase(spaceOffset); + int32_t spaceOffset = versionCode.find(' '); + if(spaceOffset >= 0) + versionCode.erase(spaceOffset, ~0U); versionCode.erase(0, strlen("versionCode=")); } @@ -260,8 +260,8 @@ ReplayStatus InstallRenderDocServer(const std::string &deviceID) if(FileIO::IsRelativePath(customPath)) customPath = libDir + "/" + customPath; - if(!endswith(customPath, "/")) - customPath += "/"; + if(customPath.back() != '/')) + customPath += '/'; paths.push_back(customPath); #endif @@ -331,8 +331,8 @@ ReplayStatus InstallRenderDocServer(const std::string &deviceID) if(!success) { - RDCLOG("Failed to install APK. stdout: %s, stderr: %s", trim(adbInstall.strStdout).c_str(), - trim(adbInstall.strStderror).c_str()); + RDCLOG("Failed to install APK. stdout: %s, stderr: %s", + adbInstall.strStdout.trimmed().c_str(), adbInstall.strStderror.trimmed().c_str()); RDCLOG("Retrying..."); adbExecCommand(deviceID, "install -r \"" + apk + "\""); @@ -363,7 +363,7 @@ ReplayStatus InstallRenderDocServer(const std::string &deviceID) return ReplayStatus::AndroidAPKInstallFailed; } - size_t lines = adbCheck.strStdout.find('\n') == std::string::npos ? 1 : 2; + size_t lines = adbCheck.strStdout.find('\n') == -1 ? 1 : 2; if(lines != abis.size()) RDCWARN("Installation of some apks failed!"); @@ -416,15 +416,15 @@ rdcarray EnumerateDevices() { rdcarray ret; - std::string adbStdout = Android::adbExecCommand("", "devices", ".", true).strStdout; + rdcstr adbStdout = Android::adbExecCommand("", "devices", ".", true).strStdout; - std::vector lines; + rdcarray lines; split(adbStdout, lines, '\n'); for(const std::string &line : lines) { - std::vector tokens; + rdcarray tokens; split(line, tokens, '\t'); - if(tokens.size() == 2 && trim(tokens[1]) == "device") + if(tokens.size() == 2 && tokens[1].trimmed() == "device") ret.push_back(tokens[0]); } @@ -485,14 +485,13 @@ struct AndroidRemoteServer : public RemoteServer { SCOPED_TIMER("Fetching android packages and activities"); - std::string adbStdout = - Android::adbExecCommand(m_deviceID, "shell pm list packages -3").strStdout; + rdcstr adbStdout = Android::adbExecCommand(m_deviceID, "shell pm list packages -3").strStdout; - std::vector lines; + rdcarray lines; split(adbStdout, lines, '\n'); std::vector packages; - for(const std::string &line : lines) + for(const rdcstr &line : lines) { // hide our own internal packages if(strstr(line.c_str(), "package:org.renderdoc.")) @@ -501,7 +500,7 @@ struct AndroidRemoteServer : public RemoteServer if(!strncmp(line.c_str(), "package:", 8)) { PathEntry pkg; - pkg.filename = trim(line.substr(8)); + pkg.filename = line.substr(8).trimmed(); pkg.size = 0; pkg.lastmod = 0; pkg.flags = PathProperty::Directory; @@ -826,12 +825,12 @@ struct AndroidController : public IDeviceProtocolHandler return; } - std::string packagesOutput = - trim(Android::adbExecCommand(deviceID, - "shell pm list packages " RENDERDOC_ANDROID_PACKAGE_BASE) - .strStdout); + rdcstr packagesOutput = + Android::adbExecCommand(deviceID, + "shell pm list packages " RENDERDOC_ANDROID_PACKAGE_BASE) + .strStdout.trimmed(); - std::vector packages; + rdcarray packages; split(packagesOutput, packages, '\n'); std::vector abis = Android::GetSupportedABIs(deviceID); @@ -1034,10 +1033,9 @@ ExecuteResult AndroidRemoteServer::ExecuteAndInject(const char *a, const char *w std::string installedPath = Android::GetPathForPackage(m_deviceID, packageName); - std::string RDCLib = - trim(Android::adbExecCommand( - m_deviceID, "shell ls " + installedPath + "/lib/*/" RENDERDOC_ANDROID_LIBRARY) - .strStdout); + rdcstr RDCLib = Android::adbExecCommand(m_deviceID, "shell ls " + installedPath + + "/lib/*/" RENDERDOC_ANDROID_LIBRARY) + .strStdout.trimmed(); // some versions of adb/android return the error message on stdout, so try to detect those and // clear the output. @@ -1046,7 +1044,7 @@ ExecuteResult AndroidRemoteServer::ExecuteAndInject(const char *a, const char *w // some versions of adb/android also don't print any error message at all! Look to see if the // wildcard glob is still present. - if(RDCLib.find("/lib/*/" RENDERDOC_ANDROID_LIBRARY) != std::string::npos) + if(RDCLib.find("/lib/*/" RENDERDOC_ANDROID_LIBRARY) >= 0) RDCLib.clear(); if(RDCLib.empty()) diff --git a/renderdoc/android/android_patch.cpp b/renderdoc/android/android_patch.cpp index 025b6d6d7..1d4b09910 100644 --- a/renderdoc/android/android_patch.cpp +++ b/renderdoc/android/android_patch.cpp @@ -22,7 +22,6 @@ * THE SOFTWARE. ******************************************************************************/ -#include #include "3rdparty/miniz/miniz.h" #include "api/replay/version.h" #include "core/core.h" @@ -40,21 +39,22 @@ bool RemoveAPKSignature(const std::string &apk) std::string aapt = getToolPath(ToolDir::BuildTools, "aapt", false); // Get the list of files in META-INF - std::string fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout; + rdcstr fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout; if(fileList.empty()) return false; // Walk through the output. If it starts with META-INF, remove it. uint32_t fileCount = 0; uint32_t matchCount = 0; - std::istringstream contents(fileList); - std::string line; - std::string prefix("META-INF"); - while(std::getline(contents, line)) + + rdcarray lines; + split(fileList, lines, '\n'); + + for(rdcstr &line : lines) { - line = trim(line); + line.trim(); fileCount++; - if(line.compare(0, prefix.size(), prefix) == 0) + if(line.beginsWith("META-INF")) { RDCDEBUG("Match found, removing %s", line.c_str()); execCommand(aapt, "remove \"" + apk + "\" " + line); @@ -66,10 +66,11 @@ bool RemoveAPKSignature(const std::string &apk) // Ensure no hits on second pass through RDCDEBUG("Walk through file list again, ensure signature removed"); fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout; - std::istringstream recheck(fileList); - while(std::getline(recheck, line)) + split(fileList, lines, '\n'); + for(rdcstr &line : lines) { - if(line.compare(0, prefix.size(), prefix) == 0) + line.trim(); + if(line.beginsWith("META-INF")) { RDCERR("Match found, that means removal failed! %s", line.c_str()); return false; @@ -103,6 +104,7 @@ bool ExtractAndRemoveManifest(const std::string &apk, std::vector &manifes RDCLOG("Got manifest of %zu bytes", sz); manifest.insert(manifest.begin(), buf, buf + sz); + break; } } } @@ -121,13 +123,14 @@ bool ExtractAndRemoveManifest(const std::string &apk, std::vector &manifes RDCDEBUG("Removing AndroidManifest.xml"); execCommand(aapt, "remove \"" + apk + "\" AndroidManifest.xml"); - std::string fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout; - std::vector files; + rdcstr fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout; + rdcarray files; split(fileList, files, ' '); - for(const std::string &f : files) + for(rdcstr &f : files) { - if(trim(f) == "AndroidManifest.xml") + f.trim(); + if(f == "AndroidManifest.xml") { RDCERR("AndroidManifest.xml found, that means removal failed!"); return false; @@ -224,6 +227,7 @@ std::string GetAndroidDebugKey() return key; } + bool DebugSignAPK(const std::string &apk, const std::string &workDir) { RDCLOG("Signing with debug key"); @@ -263,19 +267,14 @@ bool DebugSignAPK(const std::string &apk, const std::string &workDir) } // Check for signature - std::string list = execCommand(aapt, "list \"" + apk + "\"").strStdout; + rdcstr list = execCommand(aapt, "list \"" + apk + "\"").strStdout; - // Walk through the output. If it starts with META-INF, we're good - std::istringstream contents(list); - std::string line; - std::string prefix("META-INF"); - while(std::getline(contents, line)) + list.insert(0, '\n'); + + if(list.find("\nMETA-INF") >= 0) { - if(line.compare(0, prefix.size(), prefix) == 0) - { - RDCLOG("Signature found, continuing..."); - return true; - } + RDCLOG("Signature found, continuing..."); + return true; } RDCERR("re-sign of APK failed!"); @@ -439,29 +438,28 @@ bool HasRootAccess(const std::string &deviceID) result = adbExecCommand(deviceID, "root"); - std::string whoami = trim(adbExecCommand(deviceID, "shell whoami").strStdout); + rdcstr whoami = adbExecCommand(deviceID, "shell whoami").strStdout.trimmed(); if(whoami == "root") return true; - std::string checksu = - trim(adbExecCommand(deviceID, "shell test -e /system/xbin/su && echo found").strStdout); + rdcstr checksu = + adbExecCommand(deviceID, "shell test -e /system/xbin/su && echo found").strStdout.trimmed(); if(checksu == "found") return true; return false; } -std::string GetFirstMatchingLine(const std::string &haystack, const std::string &needle) +rdcstr GetFirstMatchingLine(const rdcstr &haystack, const rdcstr &needle) { - size_t needleOffset = haystack.find(needle); + int needleOffset = haystack.find(needle); - if(needleOffset == std::string::npos) - return ""; + if(needleOffset == -1) + return rdcstr(); - size_t nextLine = haystack.find('\n', needleOffset + 1); + int nextLine = haystack.find('\n', needleOffset + 1); - return haystack.substr(needleOffset, - nextLine == std::string::npos ? nextLine : nextLine - needleOffset); + return haystack.substr(needleOffset, nextLine == -1 ? ~0U : size_t(nextLine - needleOffset)); } bool IsDebuggable(const std::string &deviceID, const std::string &packageName) diff --git a/renderdoc/android/android_tools.cpp b/renderdoc/android/android_tools.cpp index 69cad8d38..14a6ce535 100644 --- a/renderdoc/android/android_tools.cpp +++ b/renderdoc/android/android_tools.cpp @@ -354,8 +354,7 @@ void initAdb() Process::ProcessResult res = {}; Process::LaunchProcess(adb.c_str(), workdir.c_str(), "start-server", true, &res); - if(res.strStdout.find("daemon") != std::string::npos || - res.strStderror.find("daemon") != std::string::npos) + if(res.strStdout.find("daemon") >= 0 || res.strStderror.find("daemon") >= 0) { RDCLOG("Started adb server"); } diff --git a/renderdoc/android/android_utils.cpp b/renderdoc/android/android_utils.cpp index 13bd40d4e..485fc4d6a 100644 --- a/renderdoc/android/android_utils.cpp +++ b/renderdoc/android/android_utils.cpp @@ -24,7 +24,6 @@ #include "android_utils.h" #include -#include #include "core/core.h" #include "strings/string_utils.h" @@ -110,7 +109,7 @@ ABI GetABI(const std::string &abiName) std::vector GetSupportedABIs(const std::string &deviceID) { - std::string adbAbi = trim(adbExecCommand(deviceID, "shell getprop ro.product.cpu.abi").strStdout); + rdcstr adbAbi = adbExecCommand(deviceID, "shell getprop ro.product.cpu.abi").strStdout.trimmed(); // these returned lists should be such that the first entry is the 'lowest command denominator' - // typically 32-bit. @@ -145,30 +144,30 @@ std::string GetRenderDocPackageForABI(ABI abi, char sep) std::string GetPathForPackage(const std::string &deviceID, const std::string &packageName) { - std::string pkgPath = trim(adbExecCommand(deviceID, "shell pm path " + packageName).strStdout); + rdcstr pkgPath = adbExecCommand(deviceID, "shell pm path " + packageName).strStdout.trimmed(); // if there are multiple slices, the path will be returned on many lines. Take only the first // line, assuming all of the apks are in the same directory - if(pkgPath.find("\n") != std::string::npos) + if(pkgPath.find("\n") >= 0) { - std::vector lines; + rdcarray lines; split(pkgPath, lines, '\n'); - pkgPath = trim(lines[0]); + pkgPath = lines[0].trimmed(); } - if(pkgPath.empty() || pkgPath.find("package:") != 0 || pkgPath.find("base.apk") == std::string::npos) + if(pkgPath.empty() || pkgPath.find("package:") != 0 || pkgPath.find("base.apk") == -1) return pkgPath; - pkgPath.erase(pkgPath.begin(), pkgPath.begin() + strlen("package:")); - pkgPath.erase(pkgPath.end() - strlen("base.apk"), pkgPath.end()); + pkgPath.erase(0, strlen("package:")); + pkgPath.erase(pkgPath.size() - strlen("base.apk"), ~0U); return pkgPath; } bool IsSupported(std::string deviceID) { - std::string api = - trim(Android::adbExecCommand(deviceID, "shell getprop ro.build.version.sdk").strStdout); + rdcstr api = + Android::adbExecCommand(deviceID, "shell getprop ro.build.version.sdk").strStdout.trimmed(); int apiVersion = atoi(api.c_str()); @@ -186,8 +185,8 @@ bool IsSupported(std::string deviceID) bool SupportsNativeLayers(const rdcstr &deviceID) { - std::string api = - trim(Android::adbExecCommand(deviceID, "shell getprop ro.build.version.sdk").strStdout); + rdcstr api = + Android::adbExecCommand(deviceID, "shell getprop ro.build.version.sdk").strStdout.trimmed(); int apiVersion = atoi(api.c_str()); @@ -203,24 +202,22 @@ std::string DetermineInstalledABI(const std::string &deviceID, const std::string RDCLOG("Checking installed ABI for %s", packageName.c_str()); std::string abi; - std::string dump = adbExecCommand(deviceID, "shell pm dump " + packageName).strStdout; + rdcstr dump = adbExecCommand(deviceID, "shell pm dump " + packageName).strStdout; if(dump.empty()) RDCERR("Unable to pm dump %s", packageName.c_str()); // Walk through the output and look for primaryCpuAbi - std::istringstream contents(dump); - std::string line; - std::string prefix("primaryCpuAbi="); - while(std::getline(contents, line)) + rdcstr prefix = "primaryCpuAbi="; + int offset = dump.find("primaryCpuAbi="); + + if(offset >= 0) { - line = trim(line); - if(line.compare(0, prefix.size(), prefix) == 0) - { - // Extract the abi - abi = line.substr(line.find_last_of("=") + 1); - RDCLOG("primaryCpuAbi found: %s", abi.c_str()); - break; - } + offset = dump.find('=', offset) + 1; + + int newline = dump.find('\n', offset); + + if(newline >= 0) + abi = dump.substr(offset, newline - offset).trimmed(); } if(abi.empty()) @@ -240,10 +237,10 @@ rdcstr GetFriendlyName(const rdcstr &deviceID) // root commands into the log Android::adbExecCommand(deviceID, "root"); - std::string manuf = - trim(Android::adbExecCommand(deviceID, "shell getprop ro.product.manufacturer").strStdout); - std::string model = - trim(Android::adbExecCommand(deviceID, "shell getprop ro.product.model").strStdout); + rdcstr manuf = + Android::adbExecCommand(deviceID, "shell getprop ro.product.manufacturer").strStdout.trimmed(); + rdcstr model = + Android::adbExecCommand(deviceID, "shell getprop ro.product.model").strStdout.trimmed(); std::string combined; @@ -660,25 +657,25 @@ void LogcatThread::Tick() std::string command = StringFormat::Fmt("logcat -t %u -v brief -s renderdoc:* libc:* DEBUG:*", lineBacklog); - std::string logcat = trim(Android::adbExecCommand(deviceID, command, ".", true).strStdout); + rdcstr logcat = Android::adbExecCommand(deviceID, command, ".", true).strStdout.trimmed(); - std::vector lines; + rdcarray lines; split(logcat, lines, '\n'); // remove \n from any lines right now to prevent it breaking further processing - for(std::string &line : lines) + for(rdcstr &line : lines) if(!line.empty() && line.back() == '\r') line.pop_back(); // only do any processing if we had a line last time that we know to start from. if(!lastLogcatLine.empty()) { - auto it = std::find(lines.begin(), lines.end(), lastLogcatLine); + int idx = lines.indexOf(lastLogcatLine); - if(it != lines.end()) + if(idx >= 0) { // remove everything up to and including that line - lines.erase(lines.begin(), it + 1); + lines.erase(0, idx + 1); } else { diff --git a/renderdoc/android/android_utils.h b/renderdoc/android/android_utils.h index 8bc51f5aa..f9c2778d0 100644 --- a/renderdoc/android/android_utils.h +++ b/renderdoc/android/android_utils.h @@ -47,7 +47,7 @@ enum class ToolDir std::string getToolPath(ToolDir subdir, const std::string &toolname, bool checkExist); bool toolExists(const std::string &path); -std::string GetFirstMatchingLine(const std::string &haystack, const std::string &needle); +rdcstr GetFirstMatchingLine(const rdcstr &haystack, const rdcstr &needle); bool IsSupported(std::string deviceID); bool SupportsNativeLayers(const rdcstr &deviceID); diff --git a/renderdoc/common/common.cpp b/renderdoc/common/common.cpp index 0f6bc5cde..d5cb8a527 100644 --- a/renderdoc/common/common.cpp +++ b/renderdoc/common/common.cpp @@ -404,8 +404,8 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje char location[64] = {0}; #if ENABLED(INCLUDE_LOCATION_IN_LOG) - std::string loc; - loc = get_basename(std::string(file)); + rdcstr loc; + loc = get_basename(file); StringFormat::snprintf(location, 63, "% 20s(%4d) - ", loc.c_str(), line); #endif diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index 7baf39117..5d6e59116 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -24,7 +24,6 @@ ******************************************************************************/ #include "remote_server.h" -#include #include #include "android/android.h" #include "api/replay/renderdoc_replay.h" @@ -905,9 +904,25 @@ void RenderDoc::BecomeRemoteServer(const char *listenhost, uint16_t port, FILE *f = FileIO::fopen(FileIO::GetAppFolderFilename("remoteserver.conf").c_str(), "r"); - while(f && !FileIO::feof(f)) + rdcstr configFile; + + if(f) { - std::string line = trim(FileIO::getline(f)); + FileIO::fseek64(f, 0, SEEK_END); + configFile.resize((size_t)FileIO::ftell64(f)); + FileIO::fseek64(f, 0, SEEK_SET); + + FileIO::fread(configFile.data(), 1, configFile.size(), f); + + FileIO::fclose(f); + } + + rdcarray lines; + split(configFile, lines, '\n'); + + for(rdcstr &line : lines) + { + line.trim(); if(line == "") continue; @@ -945,9 +960,6 @@ void RenderDoc::BecomeRemoteServer(const char *listenhost, uint16_t port, RDCLOG("Malformed line '%s'. See documentation for file format.", line.c_str()); } - if(f) - FileIO::fclose(f); - if(listenRanges.empty()) { RDCLOG("No whitelist IP ranges configured - using default private IP ranges."); diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index aa75ee54c..c25c7a399 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -111,8 +111,7 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara D3D11MarkerRegion::device = this; - std::string shaderSearchPathString = - RenderDoc::Inst().GetConfigSetting("shader.debug.searchPaths"); + rdcstr shaderSearchPathString = RenderDoc::Inst().GetConfigSetting("shader.debug.searchPaths"); split(shaderSearchPathString, m_ShaderSearchPaths, ';'); ResourceIDGen::SetReplayResourceIDs(); diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 67d101574..214daf783 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -314,7 +314,7 @@ private: D3D11ShaderCache *m_ShaderCache = NULL; D3D11ResourceManager *m_ResourceManager = NULL; - std::vector m_ShaderSearchPaths; + rdcarray m_ShaderSearchPaths; D3D11InitParams m_InitParams; uint64_t m_SectionVersion; @@ -455,7 +455,7 @@ public: return m_LayoutDescs[layout]; } - std::vector *GetShaderDebugInfoSearchPaths() { return &m_ShaderSearchPaths; } + rdcarray *GetShaderDebugInfoSearchPaths() { return &m_ShaderSearchPaths; } template bool Serialise_CaptureScope(SerialiserType &ser); diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 6a8cae43e..198507013 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -956,7 +956,7 @@ public: ResourceId m_ID; std::string m_DebugInfoPath; - std::vector *m_DebugInfoSearchPaths; + rdcarray *m_DebugInfoSearchPaths; std::vector m_Bytecode; diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index 3e1ccdf24..bcb801fc1 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -437,12 +437,12 @@ void FetchEnabledExtensions() } else if(GL.glGetString) { - std::string extstr = (const char *)GL.glGetString(eGL_EXTENSIONS); + rdcstr extstr = (const char *)GL.glGetString(eGL_EXTENSIONS); - std::vector extlist; + rdcarray extlist; split(extstr, extlist, ' '); - for(const std::string &e : extlist) + for(const rdcstr &e : extlist) CheckExtFromString(e.c_str()); } diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index c566332bc..da798ce8b 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -1352,7 +1352,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) GL.glEnable(eGL_DEBUG_OUTPUT_SYNCHRONOUS); } - std::vector implExts; + rdcarray implExts; int ctxVersion = 0; bool ctxGLES = false; @@ -1370,7 +1370,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) } else if(GL.glGetString) { - std::string implExtString = (const char *)GL.glGetString(eGL_EXTENSIONS); + rdcstr implExtString = (const char *)GL.glGetString(eGL_EXTENSIONS); split(implExtString, implExts, ' '); } @@ -1385,8 +1385,8 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) { for(size_t i = 0, j = 0; i < implExts.size() && j < globalExts.size();) { - const std::string &a = implExts[i]; - const std::string &b = globalExts[j]; + const rdcstr &a = implExts[i]; + const rdcstr &b = globalExts[j]; if(a == b) { diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index ad3e64470..e6a631b42 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -420,8 +420,8 @@ private: float CharAspect; // extensions - std::vector glExts; - std::string glExtsString; + rdcarray glExts; + rdcstr glExtsString; // state GLResourceRecord *m_BufferRecord[16]; diff --git a/renderdoc/driver/ihv/amd/amd_isa.cpp b/renderdoc/driver/ihv/amd/amd_isa.cpp index 067af2c35..d7c3c9893 100644 --- a/renderdoc/driver/ihv/amd/amd_isa.cpp +++ b/renderdoc/driver/ihv/amd/amd_isa.cpp @@ -194,7 +194,7 @@ std::string DisassembleSPIRV(ShaderStage stage, const bytebuf &shaderBytes, cons Process::ProcessResult result = {}; Process::LaunchProcess(amdspv.c_str(), get_dirname(amdspv).c_str(), cmdLine.c_str(), true, &result); - if(result.strStdout.find("SUCCESS") == std::string::npos) + if(result.strStdout.find("SUCCESS") < 0) { return "; Failed to Disassemble - " + result.strStdout; } @@ -370,8 +370,8 @@ std::string DisassembleGLSL(ShaderStage stage, const bytebuf &shaderBytes, const Process::ProcessResult result = {}; Process::LaunchProcess(vc.c_str(), get_dirname(vc).c_str(), cmdLine.c_str(), true, &result); - if(result.retCode != 0 || result.strStdout.find("Error") != std::string::npos || - result.strStdout.empty() || !FileIO::exists(outPath.c_str())) + if(result.retCode != 0 || result.strStdout.find("Error") >= 0 || result.strStdout.empty() || + !FileIO::exists(outPath.c_str())) { return "; Failed to Disassemble - check AMD driver is currently running\n\n; " + result.strStdout; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index cc683cf38..47654f1c4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -1225,9 +1225,9 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength) { m_DXBCByteCode->SetDebugInfo(m_DebugInfo); - std::vector> fileLines; + rdcarray> fileLines; - std::vector fileNames; + rdcarray fileNames; fileLines.resize(m_DebugInfo->Files.size()); fileNames.resize(m_DebugInfo->Files.size()); @@ -1237,8 +1237,8 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength) for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) { - std::vector srclines; - std::vector *dstFile = + rdcarray srclines; + rdcarray *dstFile = &fileLines[i]; // start off writing to the corresponding output file. size_t dstLine = 0; @@ -1386,7 +1386,7 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength) // make a dummy file to write into that won't be used. fileNames.push_back(filename); - fileLines.push_back(std::vector()); + fileLines.push_back(rdcarray()); dstFile = &fileLines.back(); } @@ -1585,8 +1585,10 @@ TEST_CASE("Check DXBC flags are non-overlapping", "[dxbc]") continue; // no argument should be a subset of another argument - std::string arga = trim(a.arg); - std::string argb = trim(b.arg); + rdcstr arga = a.arg; + rdcstr argb = b.arg; + arga.trim(); + argb.trim(); INFO("a: '" << arga << "' b: '" << argb << "'"); CHECK(strstr(arga.c_str(), argb.c_str()) == NULL); CHECK(strstr(argb.c_str(), arga.c_str()) == NULL); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.h b/renderdoc/driver/shaders/dxbc/dxbc_container.h index 57d3f34e4..5f5a72cf3 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.h @@ -120,7 +120,7 @@ public: virtual uint32_t GetShaderCompileFlags() const = 0; - std::vector > Files; // + rdcarray> Files; // virtual void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const = 0; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index 6fb4d6f7d..9f1203c3d 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -502,7 +502,7 @@ void Program::MakeDisassemblyString() size_t debugInst = 0; - std::vector> fileLines; + rdcarray> fileLines; // generate fileLines by splitting each file in the debug info if(m_DebugInfo) @@ -555,7 +555,7 @@ void Program::MakeDisassemblyString() } else { - std::vector &lines = fileLines[lineInfo.fileIndex]; + rdcarray &lines = fileLines[lineInfo.fileIndex]; int32_t lineIdx = RDCMIN(lineInfo.lineStart, (uint32_t)lines.size() - 1); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp index a2a0e6dcf..4a225e3af 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp @@ -85,10 +85,9 @@ SDBGChunk::SDBGChunk(void *data) for(size_t i = 0; i < m_FileHeaders.size(); i++) { - std::string filename = - std::string(asciiDatabase + m_FileHeaders[i].filenameOffset, m_FileHeaders[i].filenameLen); - std::string source = - std::string(asciiDatabase + m_FileHeaders[i].sourceOffset, m_FileHeaders[i].sourceLen); + rdcstr filename = + rdcstr(asciiDatabase + m_FileHeaders[i].filenameOffset, m_FileHeaders[i].filenameLen); + rdcstr source = rdcstr(asciiDatabase + m_FileHeaders[i].sourceOffset, m_FileHeaders[i].sourceLen); this->Files.push_back(make_rdcpair(filename, source)); } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp b/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp index 30b156ee9..f29189c7b 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp @@ -1693,39 +1693,40 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk) delete[] pages; // save the filenames in their original order - std::vector filenames; + rdcarray filenames; filenames.reserve(Files.size()); for(size_t i = 0; i < Files.size(); i++) filenames.push_back(Files[i].first); // Sort files according to the order they come in the Names array, this seems to be more reliable // about placing the main file first. - std::sort(Files.begin(), Files.end(), [&Names](const rdcpair &a, - const rdcpair &b) { - // any entries that aren't found in Names at all (like @cmdline that we add) will be sorted to - // the end. - size_t aIdx = ~0U, bIdx = ~0U; + std::sort(Files.begin(), Files.end(), + [&Names](const rdcpair &a, const rdcpair &b) { + // any entries that aren't found in Names at all (like @cmdline that we add) will be + // sorted to + // the end. + size_t aIdx = ~0U, bIdx = ~0U; - size_t i = 0; - for(auto it = Names.begin(); it != Names.end(); ++it) - { - if(it->second == a.first) - aIdx = i; - if(it->second == b.first) - bIdx = i; + size_t i = 0; + for(auto it = Names.begin(); it != Names.end(); ++it) + { + if(it->second == a.first) + aIdx = i; + if(it->second == b.first) + bIdx = i; - i++; - } + i++; + } - // if neither were found, sort by filename - if(aIdx == bIdx) - return a.first < b.first; + // if neither were found, sort by filename + if(aIdx == bIdx) + return a.first < b.first; - return aIdx < bIdx; - }); + return aIdx < bIdx; + }); // create a map from filename -> index - std::map remapping; + std::map remapping; for(size_t i = 0; i < Files.size(); i++) remapping[Files[i].first] = (int32_t)i; diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index 1e7df27f7..f2136a91c 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -63,7 +63,7 @@ ExecuteResult InjectIntoProcess(uint32_t pid, const rdcarray EnvStringToEnvMap(const char **envstri return ret; } -static std::string shellExpand(const std::string &in) +static rdcstr shellExpand(const rdcstr &in) { - std::string path = trim(in); + rdcstr path = in.trimmed(); // if it begins with ./ then replace with working directory if(path[0] == '.' && path[1] == '/') { char cwd[1024] = {}; getcwd(cwd, 1023); - return std::string(cwd) + path.substr(1); + return rdcstr(cwd) + path.substr(1); } // if it's ~/... then replace with $HOME and return if(path[0] == '~' && path[1] == '/') - return std::string(getenv("HOME")) + path.substr(1); + return rdcstr(getenv("HOME")) + path.substr(1); // if it's ~user/... then use getpwname if(path[0] == '~') { - size_t slash = path.find('/'); + int slash = path.find('/'); - std::string username; + rdcstr username; - if(slash != std::string::npos) + if(slash >= 0) { RDCASSERT(slash > 1); username = path.substr(1, slash - 1); @@ -320,10 +320,10 @@ static std::string shellExpand(const std::string &in) if(pwdata) { - if(slash != std::string::npos) - return std::string(pwdata->pw_dir) + path.substr(slash); + if(slash >= 0) + return rdcstr(pwdata->pw_dir) + path.substr(slash); - return std::string(pwdata->pw_dir); + return rdcstr(pwdata->pw_dir); } } @@ -419,8 +419,8 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd if(!app) return (pid_t)0; - std::string appName = app; - std::string workDir = (workingDir && workingDir[0]) ? workingDir : get_dirname(appName); + rdcstr appName = app; + rdcstr workDir = (workingDir && workingDir[0]) ? workingDir : get_dirname(appName); // handle funky apple .app folders that aren't actually executables #if ENABLED(RDOC_APPLE) diff --git a/renderdoc/os/posix/posix_stringio.cpp b/renderdoc/os/posix/posix_stringio.cpp index 7b3da5abe..7e7caf87b 100644 --- a/renderdoc/os/posix/posix_stringio.cpp +++ b/renderdoc/os/posix/posix_stringio.cpp @@ -403,26 +403,6 @@ std::string ErrorString() return buf; } -std::string getline(FILE *f) -{ - std::string ret; - - while(!FileIO::feof(f)) - { - char c = (char)::fgetc(f); - - if(FileIO::feof(f)) - break; - - if(c != 0 && c != '\n') - ret.push_back(c); - else - break; - } - - return ret; -} - size_t fread(void *buf, size_t elementSize, size_t count, FILE *f) { return ::fread(buf, elementSize, count, f); diff --git a/renderdoc/os/win32/win32_callstack.cpp b/renderdoc/os/win32/win32_callstack.cpp index 7f08a659d..b7da84681 100644 --- a/renderdoc/os/win32/win32_callstack.cpp +++ b/renderdoc/os/win32/win32_callstack.cpp @@ -435,7 +435,7 @@ private: }; std::vector pdbRememberedPaths; - std::vector pdbIgnores; + rdcarray pdbIgnores; std::vector modules; char pipeMessageBuf[2048]; @@ -753,7 +753,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, break; } - std::string ignores = StringFormat::Wide2UTF8(inputBuf); + rdcstr ignores = StringFormat::Wide2UTF8(inputBuf); { DWORD read = @@ -1004,7 +1004,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, } std::sort(pdbIgnores.begin(), pdbIgnores.end()); - pdbIgnores.erase(std::unique(pdbIgnores.begin(), pdbIgnores.end()), pdbIgnores.end()); + pdbIgnores.erase(std::unique(pdbIgnores.begin(), pdbIgnores.end()) - pdbIgnores.begin(), ~0U); merge(pdbIgnores, ignores, ';'); WritePrivateProfileStringW(L"renderdoc", L"ignores", StringFormat::UTF82Wide(ignores).c_str(), configPath.c_str()); diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index 29df2af8a..a37d2f712 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -855,8 +855,8 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray #include -#include #include #include "common/globalconfig.h" #include "os/os_specific.h" @@ -49,93 +48,74 @@ uint32_t strhash(const char *str, uint32_t seed) return hash; } -// since tolower is int -> int, this warns below. make a char -> char alternative -char toclower(char c) +rdcstr strlower(const rdcstr &str) { - return (char)tolower(c); -} - -char tocupper(char c) -{ - return (char)toupper(c); -} - -std::string strlower(const std::string &str) -{ - std::string newstr(str); - std::transform(newstr.begin(), newstr.end(), newstr.begin(), toclower); + rdcstr newstr(str); + for(size_t i = 0; i < newstr.size(); i++) + newstr[i] = (char)tolower(newstr[i]); return newstr; } -std::string strupper(const std::string &str) +rdcstr strupper(const rdcstr &str) { - std::string newstr(str); - std::transform(newstr.begin(), newstr.end(), newstr.begin(), tocupper); + rdcstr newstr(str); + for(size_t i = 0; i < newstr.size(); i++) + newstr[i] = (char)toupper(newstr[i]); return newstr; } -std::string trim(const std::string &str) +static bool ispathsep(char c) { - const char *whitespace = "\t \n\r"; - size_t start = str.find_first_not_of(whitespace); - size_t end = str.find_last_not_of(whitespace); - - // no non-whitespace characters, return the empty string - if(start == std::string::npos) - return ""; - - // searching from the start found something, so searching from the end must have too. - return str.substr(start, end - start + 1); + return c == '\\' || c == '/'; } -bool endswith(const std::string &value, const std::string &ending) +static int get_lastpathsep(const rdcstr &path) { - if(ending.length() > value.length()) - return false; + if(path.empty()) + return -1; - return (0 == value.compare(value.length() - ending.length(), ending.length(), ending)); + size_t offs = path.size() - 1; + + while(offs > 0 && !ispathsep(path[offs])) + offs--; + + if(offs == 0 && !ispathsep(path[0])) + return -1; + + return (int)offs; } -std::string get_basename(const std::string &path) +rdcstr get_basename(const rdcstr &path) { - std::string base = path; + rdcstr base = path; - if(base.length() == 0) + while(!base.empty() && ispathsep(base.back())) + base.pop_back(); + + if(base.empty()) return base; - if(base[base.length() - 1] == '/' || base[base.length() - 1] == '\\') - base.erase(base.size() - 1); + int offset = get_lastpathsep(base); - char pathSep[] = {'\\', '/', 0}; - - size_t offset = base.find_last_of(pathSep); - - if(offset == std::string::npos) + if(offset == -1) return base; return base.substr(offset + 1); } -std::wstring get_basename(const std::wstring &path) +rdcstr get_dirname(const rdcstr &path) { - return StringFormat::UTF82Wide(get_basename(StringFormat::Wide2UTF8(path))); -} + rdcstr base = path; -std::string get_dirname(const std::string &path) -{ - std::string base = path; + while(!base.empty() && ispathsep(base.back())) + base.pop_back(); - if(base.length() == 0) - return base; + if(base.empty()) + return "."; - if(base[base.length() - 1] == '/' || base[base.length() - 1] == '\\') - base.erase(base.size() - 1); + int offset = get_lastpathsep(base); - char pathSep[3] = {'\\', '/', 0}; - - size_t offset = base.find_last_of(pathSep); - - if(offset == std::string::npos) + if(offset == -1) { base.resize(1); base[0] = '.'; @@ -145,12 +125,7 @@ std::string get_dirname(const std::string &path) return base.substr(0, offset); } -std::wstring get_dirname(const std::wstring &path) -{ - return StringFormat::UTF82Wide(get_dirname(StringFormat::Wide2UTF8(path))); -} - -void split(const std::string &in, std::vector &out, const char sep) +void split(const rdcstr &in, rdcarray &out, const char sep) { if(in.empty()) return; @@ -158,20 +133,21 @@ void split(const std::string &in, std::vector &out, const char sep) { size_t numSeps = 0; - size_t offset = in.find(sep); - while(offset != std::string::npos) + int offset = in.find(sep); + while(offset >= 0) { numSeps++; offset = in.find(sep, offset + 1); } out.reserve(numSeps + 1); + out.clear(); } size_t begin = 0; - size_t end = in.find(sep); + int end = in.find(sep); - while(end != std::string::npos) + while(end >= 0) { out.push_back(in.substr(begin, end - begin)); @@ -183,9 +159,9 @@ void split(const std::string &in, std::vector &out, const char sep) out.push_back(in.substr(begin)); } -void merge(const std::vector &in, std::string &out, const char sep) +void merge(const rdcarray &in, rdcstr &out, const char sep) { - out = std::string(); + out = rdcstr(); for(size_t i = 0; i < in.size(); i++) { out += in[i]; @@ -194,18 +170,6 @@ void merge(const std::vector &in, std::string &out, const char sep) } } -std::string removeFromEnd(const std::string &value, const std::string &ending) -{ - size_t pos = value.rfind(ending); - - // Create new string from beginning to pattern - if(std::string::npos != pos) - return value.substr(0, pos); - - // If pattern not found, just return original string - return value; -} - #if ENABLED(ENABLE_UNIT_TESTS) #include "3rdparty/catch/catch.hpp" @@ -259,7 +223,13 @@ TEST_CASE("String manipulation", "[string]") SECTION("basename") { + CHECK(get_basename("") == ""); + CHECK(get_basename("/") == ""); + CHECK(get_basename("/\\//\\") == ""); CHECK(get_basename("foo") == "foo"); + CHECK(get_basename("foo/") == "foo"); + CHECK(get_basename("foo//") == "foo"); + CHECK(get_basename("foo/\\//\\") == "foo"); CHECK(get_basename("/foo") == "foo"); CHECK(get_basename("/dir/foo") == "foo"); CHECK(get_basename("/long/path/dir/foo") == "foo"); @@ -273,8 +243,17 @@ TEST_CASE("String manipulation", "[string]") SECTION("dirname") { + CHECK(get_dirname("") == "."); + CHECK(get_dirname("/") == "."); + CHECK(get_dirname("/\\//\\") == "."); CHECK(get_dirname("foo") == "."); + CHECK(get_dirname("foo/") == "."); + CHECK(get_dirname("foo//") == "."); + CHECK(get_dirname("foo/\\//\\") == "."); CHECK(get_dirname("/foo") == ""); + CHECK(get_dirname("/foo/") == ""); + CHECK(get_dirname("/foo//") == ""); + CHECK(get_dirname("/foo/\\//\\") == ""); CHECK(get_dirname("/dir/foo") == "/dir"); CHECK(get_dirname("/long/path/dir/foo") == "/long/path/dir"); CHECK(get_dirname("relative/long/path/dir/foo") == "relative/long/path/dir"); @@ -292,31 +271,11 @@ TEST_CASE("String manipulation", "[string]") CHECK(strupper("FOOBAR") == "FOOBAR"); }; - SECTION("trim") - { - CHECK(trim(" foo bar ") == "foo bar"); - CHECK(trim(" Foo bar") == "Foo bar"); - CHECK(trim(" Foo\nbar") == "Foo\nbar"); - CHECK(trim("FOO BAR ") == "FOO BAR"); - CHECK(trim("FOO BAR \t\n") == "FOO BAR"); - }; - - SECTION("endswith / removeFromEnd") - { - CHECK(endswith("foobar", "bar")); - CHECK_FALSE(endswith("foobar", "foo")); - CHECK(endswith("foobar", "")); - - CHECK(removeFromEnd("test/foobar", "") == "test/foobar"); - CHECK(removeFromEnd("test/foobar", "foo") == "test/"); - CHECK(removeFromEnd("test/foobar", "bar") == "test/foo"); - }; - SECTION("split by comma") { - std::vector vec; + rdcarray vec; - split(std::string("foo,bar, blah,test"), vec, ','); + split(rdcstr("foo,bar, blah,test"), vec, ','); REQUIRE(vec.size() == 4); CHECK(vec[0] == "foo"); @@ -327,9 +286,9 @@ TEST_CASE("String manipulation", "[string]") SECTION("split by space") { - std::vector vec; + rdcarray vec; - split(std::string("this is a test string for splitting!"), vec, ' '); + split(rdcstr("this is a test string for splitting!"), vec, ' '); REQUIRE(vec.size() == 9); CHECK(vec[0] == "this"); @@ -341,13 +300,17 @@ TEST_CASE("String manipulation", "[string]") CHECK(vec[6] == ""); CHECK(vec[7] == ""); CHECK(vec[8] == "splitting!"); + + split(rdcstr("new test"), vec, ' '); + + CHECK(vec.size() == 2); }; SECTION("split with trailing separator") { - std::vector vec; + rdcarray vec; - split(std::string("foo,,bar, blah,,,test,"), vec, ','); + split(rdcstr("foo,,bar, blah,,,test,"), vec, ','); REQUIRE(vec.size() == 8); CHECK(vec[0] == "foo"); @@ -362,9 +325,9 @@ TEST_CASE("String manipulation", "[string]") SECTION("split with starting separator") { - std::vector vec; + rdcarray vec; - split(std::string(",foo,bar"), vec, ','); + split(rdcstr(",foo,bar"), vec, ','); REQUIRE(vec.size() == 3); CHECK(vec[0] == ""); @@ -374,8 +337,8 @@ TEST_CASE("String manipulation", "[string]") SECTION("merge") { - std::vector vec; - std::string str; + rdcarray vec; + rdcstr str; merge(vec, str, ' '); CHECK(str == ""); @@ -393,10 +356,10 @@ TEST_CASE("String manipulation", "[string]") SECTION("degenerate cases") { - std::vector vec; - std::string str; + rdcarray vec; + rdcstr str; - split(std::string(), vec, ','); + split(rdcstr(), vec, ','); REQUIRE(vec.empty()); diff --git a/renderdoc/strings/string_utils.h b/renderdoc/strings/string_utils.h index 84cc80485..587e25ec8 100644 --- a/renderdoc/strings/string_utils.h +++ b/renderdoc/strings/string_utils.h @@ -25,22 +25,16 @@ #pragma once -#include -#include -#include +#include "api/replay/rdcarray.h" +#include "api/replay/rdcstr.h" -std::string strlower(const std::string &str); -std::string strupper(const std::string &str); - -std::string trim(const std::string &str); -std::string removeFromEnd(const std::string &value, const std::string &ending); +rdcstr strlower(const rdcstr &str); +rdcstr strupper(const rdcstr &str); uint32_t strhash(const char *str, uint32_t existingHash = 5381); -bool endswith(const std::string &value, const std::string &ending); +rdcstr get_basename(const rdcstr &path); +rdcstr get_dirname(const rdcstr &path); -std::string get_basename(const std::string &path); -std::string get_dirname(const std::string &path); - -void split(const std::string &in, std::vector &out, const char sep); -void merge(const std::vector &in, std::string &out, const char sep); +void split(const rdcstr &in, rdcarray &out, const char sep); +void merge(const rdcarray &in, rdcstr &out, const char sep);