mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-30 11:21:01 +00:00
Switch string_utils to use rdc types
This commit is contained in:
Vendored
+18
-16
@@ -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<TestCase> m_testcases;
|
||||
rdcarray<TestCase> 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)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "android.h"
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#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<std::string> lines;
|
||||
rdcarray<rdcstr> 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<rdcstr> EnumerateDevices()
|
||||
{
|
||||
rdcarray<rdcstr> ret;
|
||||
|
||||
std::string adbStdout = Android::adbExecCommand("", "devices", ".", true).strStdout;
|
||||
rdcstr adbStdout = Android::adbExecCommand("", "devices", ".", true).strStdout;
|
||||
|
||||
std::vector<std::string> lines;
|
||||
rdcarray<rdcstr> lines;
|
||||
split(adbStdout, lines, '\n');
|
||||
for(const std::string &line : lines)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
rdcarray<rdcstr> 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<std::string> lines;
|
||||
rdcarray<rdcstr> lines;
|
||||
split(adbStdout, lines, '\n');
|
||||
|
||||
std::vector<PathEntry> 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<std::string> packages;
|
||||
rdcarray<rdcstr> packages;
|
||||
split(packagesOutput, packages, '\n');
|
||||
|
||||
std::vector<Android::ABI> 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())
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <sstream>
|
||||
#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<rdcstr> 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<byte> &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<byte> &manifes
|
||||
RDCDEBUG("Removing AndroidManifest.xml");
|
||||
execCommand(aapt, "remove \"" + apk + "\" AndroidManifest.xml");
|
||||
|
||||
std::string fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout;
|
||||
std::vector<std::string> files;
|
||||
rdcstr fileList = execCommand(aapt, "list \"" + apk + "\"").strStdout;
|
||||
rdcarray<rdcstr> 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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "android_utils.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include "core/core.h"
|
||||
#include "strings/string_utils.h"
|
||||
|
||||
@@ -110,7 +109,7 @@ ABI GetABI(const std::string &abiName)
|
||||
|
||||
std::vector<ABI> 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<std::string> lines;
|
||||
rdcarray<rdcstr> 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<std::string> lines;
|
||||
rdcarray<rdcstr> 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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "remote_server.h"
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#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<rdcstr> 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.");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -314,7 +314,7 @@ private:
|
||||
D3D11ShaderCache *m_ShaderCache = NULL;
|
||||
D3D11ResourceManager *m_ResourceManager = NULL;
|
||||
|
||||
std::vector<std::string> m_ShaderSearchPaths;
|
||||
rdcarray<rdcstr> m_ShaderSearchPaths;
|
||||
|
||||
D3D11InitParams m_InitParams;
|
||||
uint64_t m_SectionVersion;
|
||||
@@ -455,7 +455,7 @@ public:
|
||||
return m_LayoutDescs[layout];
|
||||
}
|
||||
|
||||
std::vector<std::string> *GetShaderDebugInfoSearchPaths() { return &m_ShaderSearchPaths; }
|
||||
rdcarray<rdcstr> *GetShaderDebugInfoSearchPaths() { return &m_ShaderSearchPaths; }
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_CaptureScope(SerialiserType &ser);
|
||||
|
||||
|
||||
@@ -956,7 +956,7 @@ public:
|
||||
ResourceId m_ID;
|
||||
|
||||
std::string m_DebugInfoPath;
|
||||
std::vector<std::string> *m_DebugInfoSearchPaths;
|
||||
rdcarray<rdcstr> *m_DebugInfoSearchPaths;
|
||||
|
||||
std::vector<byte> m_Bytecode;
|
||||
|
||||
|
||||
@@ -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<std::string> extlist;
|
||||
rdcarray<rdcstr> extlist;
|
||||
split(extstr, extlist, ' ');
|
||||
|
||||
for(const std::string &e : extlist)
|
||||
for(const rdcstr &e : extlist)
|
||||
CheckExtFromString(e.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1352,7 +1352,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
|
||||
GL.glEnable(eGL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
std::vector<std::string> implExts;
|
||||
rdcarray<rdcstr> 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)
|
||||
{
|
||||
|
||||
@@ -420,8 +420,8 @@ private:
|
||||
float CharAspect;
|
||||
|
||||
// extensions
|
||||
std::vector<std::string> glExts;
|
||||
std::string glExtsString;
|
||||
rdcarray<rdcstr> glExts;
|
||||
rdcstr glExtsString;
|
||||
|
||||
// state
|
||||
GLResourceRecord *m_BufferRecord[16];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1225,9 +1225,9 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
{
|
||||
m_DXBCByteCode->SetDebugInfo(m_DebugInfo);
|
||||
|
||||
std::vector<std::vector<std::string>> fileLines;
|
||||
rdcarray<rdcarray<rdcstr>> fileLines;
|
||||
|
||||
std::vector<std::string> fileNames;
|
||||
rdcarray<rdcstr> 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<std::string> srclines;
|
||||
std::vector<std::string> *dstFile =
|
||||
rdcarray<rdcstr> srclines;
|
||||
rdcarray<rdcstr> *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<std::string>());
|
||||
fileLines.push_back(rdcarray<rdcstr>());
|
||||
|
||||
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);
|
||||
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
|
||||
virtual uint32_t GetShaderCompileFlags() const = 0;
|
||||
|
||||
std::vector<rdcpair<std::string, std::string> > Files; // <filename, source>
|
||||
rdcarray<rdcpair<rdcstr, rdcstr>> Files; // <filename, source>
|
||||
|
||||
virtual void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const = 0;
|
||||
|
||||
|
||||
@@ -502,7 +502,7 @@ void Program::MakeDisassemblyString()
|
||||
|
||||
size_t debugInst = 0;
|
||||
|
||||
std::vector<std::vector<std::string>> fileLines;
|
||||
rdcarray<rdcarray<rdcstr>> fileLines;
|
||||
|
||||
// generate fileLines by splitting each file in the debug info
|
||||
if(m_DebugInfo)
|
||||
@@ -555,7 +555,7 @@ void Program::MakeDisassemblyString()
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> &lines = fileLines[lineInfo.fileIndex];
|
||||
rdcarray<rdcstr> &lines = fileLines[lineInfo.fileIndex];
|
||||
|
||||
int32_t lineIdx = RDCMIN(lineInfo.lineStart, (uint32_t)lines.size() - 1);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -1693,39 +1693,40 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
|
||||
delete[] pages;
|
||||
|
||||
// save the filenames in their original order
|
||||
std::vector<std::string> filenames;
|
||||
rdcarray<rdcstr> 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<std::string, std::string> &a,
|
||||
const rdcpair<std::string, std::string> &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<rdcstr, rdcstr> &a, const rdcpair<rdcstr, rdcstr> &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<std::string, int32_t> remapping;
|
||||
std::map<rdcstr, int32_t> remapping;
|
||||
for(size_t i = 0; i < Files.size(); i++)
|
||||
remapping[Files[i].first] = (int32_t)i;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ ExecuteResult InjectIntoProcess(uint32_t pid, const rdcarray<EnvironmentModifica
|
||||
bool waitForExit);
|
||||
struct ProcessResult
|
||||
{
|
||||
std::string strStdout, strStderror;
|
||||
rdcstr strStdout, strStderror;
|
||||
int retCode;
|
||||
};
|
||||
uint32_t LaunchProcess(const char *app, const char *workingDir, const char *cmdLine, bool internal,
|
||||
@@ -297,8 +297,6 @@ bool exists(const char *filename);
|
||||
|
||||
std::string ErrorString();
|
||||
|
||||
std::string getline(FILE *f);
|
||||
|
||||
uint64_t ftell64(FILE *f);
|
||||
void fseek64(FILE *f, uint64_t offset, int origin);
|
||||
|
||||
|
||||
@@ -148,9 +148,9 @@ const char *Process::GetEnvVariable(const char *name)
|
||||
StringFormat::Fmt("debug.rdoc.%s variable_is_not_set", name).c_str(), true,
|
||||
&result);
|
||||
|
||||
static std::string settingsOutput;
|
||||
static rdcstr settingsOutput;
|
||||
|
||||
settingsOutput = trim(result.strStdout);
|
||||
settingsOutput = result.strStdout.trimmed();
|
||||
|
||||
if(settingsOutput == "variable_is_not_set")
|
||||
return NULL;
|
||||
|
||||
@@ -283,30 +283,30 @@ static std::map<std::string, std::string> 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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -435,7 +435,7 @@ private:
|
||||
};
|
||||
|
||||
std::vector<std::string> pdbRememberedPaths;
|
||||
std::vector<std::string> pdbIgnores;
|
||||
rdcarray<rdcstr> pdbIgnores;
|
||||
std::vector<Module> 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());
|
||||
|
||||
@@ -855,8 +855,8 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray<Environmen
|
||||
|
||||
for(const EnvironmentModification &e : env)
|
||||
{
|
||||
std::string name = trim(e.name.c_str());
|
||||
std::string value = e.value.c_str();
|
||||
rdcstr name = e.name.trimmed();
|
||||
rdcstr value = e.value;
|
||||
|
||||
if(name == "")
|
||||
break;
|
||||
@@ -882,16 +882,22 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray<Environmen
|
||||
cmdWithEnv += L" ";
|
||||
|
||||
// escape the parameters
|
||||
for(auto it = name.begin(); it != name.end(); ++it)
|
||||
for(size_t it = 0; it < name.size(); it++)
|
||||
{
|
||||
if(*it == '"')
|
||||
it = name.insert(it, '\\') + 1;
|
||||
if(name[it] == '"')
|
||||
{
|
||||
name.insert(it, '\\');
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto it = value.begin(); it != value.end(); ++it)
|
||||
for(size_t it = 0; it < value.size(); it++)
|
||||
{
|
||||
if(*it == '"')
|
||||
it = value.insert(it, '\\') + 1;
|
||||
if(value[it] == '"')
|
||||
{
|
||||
value.insert(it, '\\');
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
if(name.back() == '\\')
|
||||
@@ -975,8 +981,8 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray<Environmen
|
||||
{
|
||||
for(const EnvironmentModification &e : env)
|
||||
{
|
||||
std::string name = trim(e.name.c_str());
|
||||
std::string value = e.value.c_str();
|
||||
rdcstr name = e.name.trimmed();
|
||||
rdcstr value = e.value;
|
||||
EnvMod mod = e.mod;
|
||||
EnvSep sep = e.sep;
|
||||
|
||||
|
||||
@@ -602,26 +602,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);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "string_utils.h"
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <wctype.h>
|
||||
#include <algorithm>
|
||||
#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<std::string> &out, const char sep)
|
||||
void split(const rdcstr &in, rdcarray<rdcstr> &out, const char sep)
|
||||
{
|
||||
if(in.empty())
|
||||
return;
|
||||
@@ -158,20 +133,21 @@ void split(const std::string &in, std::vector<std::string> &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<std::string> &out, const char sep)
|
||||
out.push_back(in.substr(begin));
|
||||
}
|
||||
|
||||
void merge(const std::vector<std::string> &in, std::string &out, const char sep)
|
||||
void merge(const rdcarray<rdcstr> &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<std::string> &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<std::string> vec;
|
||||
rdcarray<rdcstr> 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<std::string> vec;
|
||||
rdcarray<rdcstr> 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<std::string> vec;
|
||||
rdcarray<rdcstr> 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<std::string> vec;
|
||||
rdcarray<rdcstr> 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<std::string> vec;
|
||||
std::string str;
|
||||
rdcarray<rdcstr> vec;
|
||||
rdcstr str;
|
||||
|
||||
merge(vec, str, ' ');
|
||||
CHECK(str == "");
|
||||
@@ -393,10 +356,10 @@ TEST_CASE("String manipulation", "[string]")
|
||||
|
||||
SECTION("degenerate cases")
|
||||
{
|
||||
std::vector<std::string> vec;
|
||||
std::string str;
|
||||
rdcarray<rdcstr> vec;
|
||||
rdcstr str;
|
||||
|
||||
split(std::string(), vec, ',');
|
||||
split(rdcstr(), vec, ',');
|
||||
|
||||
REQUIRE(vec.empty());
|
||||
|
||||
|
||||
@@ -25,22 +25,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#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<std::string> &out, const char sep);
|
||||
void merge(const std::vector<std::string> &in, std::string &out, const char sep);
|
||||
void split(const rdcstr &in, rdcarray<rdcstr> &out, const char sep);
|
||||
void merge(const rdcarray<rdcstr> &in, rdcstr &out, const char sep);
|
||||
|
||||
Reference in New Issue
Block a user