diff --git a/renderdoc/android/android.cpp b/renderdoc/android/android.cpp index 5cdab768b..40ae93f5b 100644 --- a/renderdoc/android/android.cpp +++ b/renderdoc/android/android.cpp @@ -247,9 +247,9 @@ ReplayStatus InstallRenderDocServer(const std::string &deviceID) } // Check known paths for RenderDoc server - std::string libPath; + rdcstr libPath; FileIO::GetLibraryFilename(libPath); - std::string libDir = get_dirname(FileIO::GetFullPathname(libPath)); + rdcstr libDir = get_dirname(FileIO::GetFullPathname(libPath)); std::vector paths; @@ -955,8 +955,7 @@ ExecuteResult AndroidRemoteServer::ExecuteAndInject(const char *a, const char *w std::string packageAndActivity = a && a[0] ? a : ""; std::string intentArgs = c && c[0] ? c : ""; - // we spin up a thread to Ping() every second, since StartAndroidPackageForCapture can block - // for a long time. + // we spin up a thread to Ping() every second, since starting a package can block for a long time. volatile int32_t done = 0; Threading::ThreadHandle pingThread = Threading::CreateThread([&done, this]() { bool ok = true; diff --git a/renderdoc/android/android.h b/renderdoc/android/android.h index 815b4329c..d14abab95 100644 --- a/renderdoc/android/android.h +++ b/renderdoc/android/android.h @@ -33,8 +33,6 @@ namespace Android bool IsHostADB(const char *hostname); std::string GetPackageName(const std::string &packageAndActivity); std::string GetActivityName(const std::string &packageAndActivity); -ExecuteResult StartAndroidPackageForCapture(const char *host, const char *packageAndActivity, - const char *intentArgs, const CaptureOptions &opts); void ResetCaptureSettings(const std::string &deviceID); void ExtractDeviceIDAndIndex(const std::string &hostname, int &index, std::string &deviceID); Process::ProcessResult adbExecCommand(const std::string &deviceID, const std::string &args, diff --git a/renderdoc/android/android_manifest.cpp b/renderdoc/android/android_manifest.cpp index a743382e1..9203b2376 100644 --- a/renderdoc/android/android_manifest.cpp +++ b/renderdoc/android/android_manifest.cpp @@ -64,11 +64,11 @@ std::string GetStringPoolValue(ResStringPool_header *stringpool, ResStringPool_r len |= *(str++); } - std::wstring wstr; + rdcwstr wstr(len); // wchar_t isn't always 2 bytes, so we iterate over the uint16_t and cast. for(uint32_t i = 0; i < len; i++) - wstr.push_back(wchar_t(str[i])); + wstr[i] = wchar_t(str[i]); return StringFormat::Wide2UTF8(wstr); } @@ -115,27 +115,20 @@ void ShiftStringPoolValue(Res_value &val, uint32_t insertedLocation) } template -void InsertBytes(std::vector &bytes, byte *pos, const T &data) +void InsertBytes(bytebuf &bytes, byte *pos, const T &data) { - byte *start = &bytes[0]; byte *byteData = (byte *)&data; - size_t offs = pos - start; - - bytes.insert(bytes.begin() + offs, byteData, byteData + sizeof(T)); + bytes.insert(pos - &bytes[0], byteData, sizeof(T)); } template <> -void InsertBytes(std::vector &bytes, byte *pos, const std::vector &data) +void InsertBytes(bytebuf &bytes, byte *pos, const bytebuf &data) { - byte *start = &bytes[0]; - - size_t offs = pos - start; - - bytes.insert(bytes.begin() + offs, data.begin(), data.end()); + bytes.insert(pos - &bytes[0], data); } -bool PatchManifest(std::vector &manifestBytes) +bool PatchManifest(bytebuf &manifestBytes) { // Whether to insert a new string & resource ID at the start or end of the resource map table. I // can't find anything that indicates there is any required ordering to these, so either should be @@ -508,15 +501,15 @@ bool PatchManifest(std::vector &manifestBytes) // insert the string, with length prefix and trailing NULL if(stringpool->flags & ResStringPool_header::UTF8_FLAG) { - std::vector bytes = {0xA, 0xA, 'd', 'e', 'b', 'u', 'g', 'g', 'a', 'b', 'l', 'e', 0}; + bytebuf bytes = {0xA, 0xA, 'd', 'e', 'b', 'u', 'g', 'g', 'a', 'b', 'l', 'e', 0}; shift = (uint32_t)bytes.size(); InsertBytes(manifestBytes, stringData + stringOffsets[insertIdx], bytes); } else { - std::vector bytes = {0xA, 0x0, 'd', 0, 'e', 0, 'b', 0, 'u', 0, 'g', 0, - 'g', 0, 'a', 0, 'b', 0, 'l', 0, 'e', 0, 0, 0}; + bytebuf bytes = {0xA, 0x0, 'd', 0, 'e', 0, 'b', 0, 'u', 0, 'g', 0, + 'g', 0, 'a', 0, 'b', 0, 'l', 0, 'e', 0, 0, 0}; shift = (uint32_t)bytes.size(); InsertBytes(manifestBytes, stringData + stringOffsets[insertIdx], bytes); diff --git a/renderdoc/android/android_patch.cpp b/renderdoc/android/android_patch.cpp index 1d4b09910..fcc8a0390 100644 --- a/renderdoc/android/android_patch.cpp +++ b/renderdoc/android/android_patch.cpp @@ -79,7 +79,7 @@ bool RemoveAPKSignature(const std::string &apk) return true; } -bool ExtractAndRemoveManifest(const std::string &apk, std::vector &manifest) +bool ExtractAndRemoveManifest(const std::string &apk, bytebuf &manifest) { // pull out the manifest with miniz mz_zip_archive zip; @@ -103,7 +103,7 @@ bool ExtractAndRemoveManifest(const std::string &apk, std::vector &manifes RDCLOG("Got manifest of %zu bytes", sz); - manifest.insert(manifest.begin(), buf, buf + sz); + manifest = bytebuf(buf, sz); break; } } @@ -140,13 +140,12 @@ bool ExtractAndRemoveManifest(const std::string &apk, std::vector &manifes return true; } -bool AddManifestToAPK(const std::string &apk, const std::string &tmpDir, - const std::vector &manifest) +bool AddManifestToAPK(const std::string &apk, const std::string &tmpDir, const bytebuf &manifest) { std::string aapt = getToolPath(ToolDir::BuildTools, "aapt", false); // write the manifest to disk - FileIO::dump((tmpDir + "AndroidManifest.xml").c_str(), manifest.data(), manifest.size()); + FileIO::WriteAll((tmpDir + "AndroidManifest.xml").c_str(), manifest); // run aapt to add the manifest Process::ProcessResult result = @@ -538,7 +537,7 @@ extern "C" RENDERDOC_API AndroidFlags RENDERDOC_CC RENDERDOC_MakeDebuggablePacka std::string tmpDir = FileIO::GetTempFolderFilename(); std::string origAPK(tmpDir + package + ".orig.apk"); std::string alignedAPK(origAPK + ".aligned.apk"); - std::vector manifest; + bytebuf manifest; // Try the following steps, bailing if anything fails if(!Android::PullAPK(deviceID, pkgPath, origAPK)) diff --git a/renderdoc/android/android_tools.cpp b/renderdoc/android/android_tools.cpp index 14a6ce535..4bcc46a93 100644 --- a/renderdoc/android/android_tools.cpp +++ b/renderdoc/android/android_tools.cpp @@ -79,7 +79,8 @@ std::string getToolInSDK(ToolDir subdir, const std::string &jdkroot, const std:: // otherwise we need to find the build-tools versioned folder toolpath = sdkroot + "/build-tools/"; - std::vector paths = FileIO::GetFilesInDirectory(toolpath.c_str()); + rdcarray paths; + FileIO::GetFilesInDirectory(toolpath.c_str(), paths); if(paths.empty()) break; @@ -275,9 +276,9 @@ std::string getToolPath(ToolDir subdir, const std::string &toolname, bool checkE // finally try to locate it in our own distributed android subfolder { - std::string libpath; + rdcstr libpath; FileIO::GetLibraryFilename(libpath); - std::string libdir = get_dirname(FileIO::GetFullPathname(libpath)); + rdcstr libdir = get_dirname(FileIO::GetFullPathname(libpath)); toolpath = libdir + "/plugins/android/" + toolname; if(toolExists(toolpath)) diff --git a/renderdoc/android/android_utils.h b/renderdoc/android/android_utils.h index f9c2778d0..8f9b0a865 100644 --- a/renderdoc/android/android_utils.h +++ b/renderdoc/android/android_utils.h @@ -24,6 +24,7 @@ #pragma once +#include "api/replay/stringise.h" #include "android.h" // internal functions, shouldn't be used outside the android implementation - anything public goes @@ -69,7 +70,7 @@ std::vector GetSupportedABIs(const std::string &deviceID); std::string GetRenderDocPackageForABI(ABI abi, char sep = '.'); std::string GetPathForPackage(const std::string &deviceID, const std::string &packageName); -bool PatchManifest(std::vector &manifest); +bool PatchManifest(bytebuf &manifest); }; DECLARE_REFLECTION_ENUM(Android::ABI); diff --git a/renderdoc/common/common.cpp b/renderdoc/common/common.cpp index d5cb8a527..82749b93f 100644 --- a/renderdoc/common/common.cpp +++ b/renderdoc/common/common.cpp @@ -318,12 +318,11 @@ void rdclog_filename(const char *filename) if(logfileHandle && previous.c_str()) { - std::vector previousContents; - FileIO::slurp(previous.c_str(), previousContents); + rdcstr previousContents; + FileIO::ReadAll(previous.c_str(), previousContents); if(!previousContents.empty()) - FileIO::logfile_append(logfileHandle, (const char *)&previousContents[0], - previousContents.size()); + FileIO::logfile_append(logfileHandle, previousContents.c_str(), previousContents.size()); FileIO::Delete(previous.c_str()); } diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 3e456b409..152f35568 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -378,7 +378,7 @@ void RenderDoc::Initialise() // set default capture log - useful for when hooks aren't setup // through the UI (and a log file isn't set manually) { - std::string capture_filename; + rdcstr capture_filename; const char *base = "RenderDoc_app"; if(IsReplayApp()) @@ -427,14 +427,14 @@ void RenderDoc::Initialise() m_ExHandler = NULL; { - std::string curFile; + rdcstr curFile; FileIO::GetExecutableFilename(curFile); - std::string f = strlower(curFile); + rdcstr f = strlower(curFile); // only create crash handler when we're not in renderdoccmd.exe (to prevent infinite loop as // the crash handler itself launches renderdoccmd.exe) - if(f.find("renderdoccmd.exe") == std::string::npos) + if(!f.contains("renderdoccmd.exe")) { RecreateCrashHandler(); } diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index ca631bd21..21ac306a5 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -621,9 +621,9 @@ private: FrameTimer m_FrameTimer; - std::string m_LoggingFilename; + rdcstr m_LoggingFilename; - std::string m_Target; + rdcstr m_Target; std::string m_CaptureFileTemplate; std::string m_CurrentLogFile; CaptureOptions m_Options; diff --git a/renderdoc/core/plugins.cpp b/renderdoc/core/plugins.cpp index 1fc10a7f4..b9600ca6d 100644 --- a/renderdoc/core/plugins.cpp +++ b/renderdoc/core/plugins.cpp @@ -30,7 +30,7 @@ std::string LocatePluginFile(const std::string &path, const std::string &fileNam { std::string ret; - std::string libpath; + rdcstr libpath; FileIO::GetLibraryFilename(libpath); libpath = get_dirname(libpath); diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index 5d6e59116..3776dc504 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -347,7 +347,8 @@ static void ActiveRemoteClientThread(ClientThread *threadData, reader.EndChunk(); - std::vector files = FileIO::GetFilesInDirectory(path.c_str()); + rdcarray files; + FileIO::GetFilesInDirectory(path.c_str(), files); { WRITE_DATA_SCOPE(); @@ -376,8 +377,8 @@ static void ActiveRemoteClientThread(ClientThread *threadData, } else if(type == eRemoteServer_CopyCaptureToRemote) { - std::string path; - std::string dummy, dummy2; + rdcstr path; + rdcstr dummy, dummy2; FileIO::GetDefaultFiles("remotecopy", path, dummy, dummy2); RDCLOG("Copying file to local path '%s'.", path.c_str()); @@ -843,8 +844,11 @@ static void ActiveRemoteClientThread(ClientThread *threadData, if(threadData->allowExecution) { - ret = Process::LaunchAndInjectIntoProcess(app.c_str(), workingDir.c_str(), cmdLine.c_str(), - env, "", opts, false); + rdcpair status = Process::LaunchAndInjectIntoProcess( + app.c_str(), workingDir.c_str(), cmdLine.c_str(), env, "", opts, false); + + ret.status = status.first; + ret.ident = status.second; } else { diff --git a/renderdoc/data/embedded_files.h b/renderdoc/data/embedded_files.h index b0808a6c7..4c4ad0f3b 100644 --- a/renderdoc/data/embedded_files.h +++ b/renderdoc/data/embedded_files.h @@ -25,6 +25,8 @@ #pragma once +#include "common/common.h" + #define DECLARE_EMBED(filename) \ extern unsigned char CONCAT(data_, filename)[]; \ extern int CONCAT(CONCAT(data_, filename), _len); diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index c833251a5..f493c50c0 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -207,7 +207,7 @@ inline std::string GetDebugName(T *pObj) if(SUCCEEDED(hr)) { size /= 2; // Convert from bytes read to wide char count - std::wstring sName(tmpBuf, size); + rdcwstr sName(tmpBuf, size); return StringFormat::Wide2UTF8(sName); } } diff --git a/renderdoc/driver/d3d11/d3d11_context.h b/renderdoc/driver/d3d11/d3d11_context.h index e8efa1005..1319e5c4b 100644 --- a/renderdoc/driver/d3d11/d3d11_context.h +++ b/renderdoc/driver/d3d11/d3d11_context.h @@ -200,7 +200,7 @@ private: ANNOT_ENDEVENT } m_Type; uint32_t m_Col; - std::wstring m_Name; + rdcstr m_Name; }; std::vector m_AnnotationQueue; Threading::CriticalSection m_AnnotLock; diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 3c19bbae1..01a9887f6 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -194,7 +194,7 @@ void WrappedID3D11DeviceContext::ThreadSafe_SetMarker(uint32_t col, const wchar_ Annotation annot; annot.m_Type = Annotation::ANNOT_SETMARKER; annot.m_Col = col; - annot.m_Name = name; + annot.m_Name = StringFormat::Wide2UTF8(name); { SCOPED_LOCK(m_AnnotLock); @@ -207,7 +207,7 @@ int WrappedID3D11DeviceContext::ThreadSafe_BeginEvent(uint32_t col, const wchar_ Annotation annot; annot.m_Type = Annotation::ANNOT_BEGINEVENT; annot.m_Col = col; - annot.m_Name = name; + annot.m_Name = StringFormat::Wide2UTF8(name); { SCOPED_LOCK(m_AnnotLock); @@ -259,8 +259,12 @@ void WrappedID3D11DeviceContext::DrainAnnotationQueue() switch(a.m_Type) { - case Annotation::ANNOT_SETMARKER: SetMarker(a.m_Col, a.m_Name.c_str()); break; - case Annotation::ANNOT_BEGINEVENT: PushMarker(a.m_Col, a.m_Name.c_str()); break; + case Annotation::ANNOT_SETMARKER: + SetMarker(a.m_Col, StringFormat::UTF82Wide(a.m_Name).c_str()); + break; + case Annotation::ANNOT_BEGINEVENT: + PushMarker(a.m_Col, StringFormat::UTF82Wide(a.m_Name).c_str()); + break; case Annotation::ANNOT_ENDEVENT: PopMarker(); break; } } diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 198507013..a7681bd8b 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -304,7 +304,7 @@ public: else if(guid == WKPDID_D3DDebugObjectNameW) { const wchar_t *pStrData = (const wchar_t *)pData; - std::wstring wName(pStrData, DataSize / 2); + rdcwstr wName(pStrData, DataSize / 2); std::string sName = StringFormat::Wide2UTF8(wName); m_pDevice->SetResourceName(this, sName.c_str()); } diff --git a/renderdoc/driver/d3d12/d3d12_command_list.h b/renderdoc/driver/d3d12/d3d12_command_list.h index 555474b95..0f33e734b 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list.h +++ b/renderdoc/driver/d3d12/d3d12_command_list.h @@ -217,7 +217,7 @@ public: } else if(guid == WKPDID_D3DDebugObjectNameW) { - std::wstring wName((const wchar_t *)pData, DataSize / 2); + rdcwstr wName((const wchar_t *)pData, DataSize / 2); std::string sName = StringFormat::Wide2UTF8(wName); m_pDevice->SetName(this, sName.c_str()); } diff --git a/renderdoc/driver/d3d12/d3d12_command_queue.h b/renderdoc/driver/d3d12/d3d12_command_queue.h index 1e21c6d9c..fb5a97e0c 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue.h +++ b/renderdoc/driver/d3d12/d3d12_command_queue.h @@ -247,7 +247,7 @@ public: } else if(guid == WKPDID_D3DDebugObjectNameW) { - std::wstring wName((const wchar_t *)pData, DataSize / 2); + rdcwstr wName((const wchar_t *)pData, DataSize / 2); std::string sName = StringFormat::Wide2UTF8(wName); m_pDevice->SetName(this, sName.c_str()); } diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index 1b1b6b49a..469a5d957 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -59,9 +59,8 @@ void D3D12MarkerRegion::Begin(ID3D12GraphicsCommandList *list, const std::string // Some debuggers (but not all) will assume the event string is null-terminated, and // display one less character than specified by the size. Append a space to pad the // output without visibly changing the event marker for other debuggers. - std::wstring text = StringFormat::UTF82Wide(marker); - text.append(L" "); - UINT size = (UINT)text.size() * sizeof(wchar_t); + rdcwstr text = StringFormat::UTF82Wide(marker + " "); + UINT size = (UINT)text.length() * sizeof(wchar_t); list->BeginEvent(0, text.c_str(), size); } } @@ -70,9 +69,8 @@ void D3D12MarkerRegion::Begin(ID3D12CommandQueue *queue, const std::string &mark { if(queue) { - std::wstring text = StringFormat::UTF82Wide(marker); - text.append(L" "); - UINT size = (UINT)text.size() * sizeof(wchar_t); + rdcwstr text = StringFormat::UTF82Wide(marker + " "); + UINT size = (UINT)text.length() * sizeof(wchar_t); queue->BeginEvent(0, text.c_str(), size); } } @@ -81,9 +79,8 @@ void D3D12MarkerRegion::Set(ID3D12GraphicsCommandList *list, const std::string & { if(list) { - std::wstring text = StringFormat::UTF82Wide(marker); - text.append(L" "); - UINT size = (UINT)text.size() * sizeof(wchar_t); + rdcwstr text = StringFormat::UTF82Wide(marker + " "); + UINT size = (UINT)text.length() * sizeof(wchar_t); list->SetMarker(0, text.c_str(), size); } } @@ -92,9 +89,8 @@ void D3D12MarkerRegion::Set(ID3D12CommandQueue *queue, const std::string &marker { if(queue) { - std::wstring text = StringFormat::UTF82Wide(marker); - text.append(L" "); - UINT size = (UINT)text.size() * sizeof(wchar_t); + rdcwstr text = StringFormat::UTF82Wide(marker + " "); + UINT size = (UINT)text.length() * sizeof(wchar_t); queue->SetMarker(0, text.c_str(), size); } } @@ -693,16 +689,16 @@ const UINT64 *PIX3DecodeStringParam(const UINT64 *pData, std::string &DecodedStr if(isANSI) { const char *c = (const char *)pData; - UINT formatStringByteCount = UINT(strlen((const char *)pData)); - DecodedString = std::string(c, c + formatStringByteCount); - totalStringBytes = formatStringByteCount + 1; + UINT formatStringCharCount = UINT(strlen((const char *)pData)); + DecodedString = std::string(c, c + formatStringCharCount); + totalStringBytes = formatStringCharCount + 1; } else { const wchar_t *w = (const wchar_t *)pData; - UINT formatStringByteCount = UINT(wcslen((const wchar_t *)pData)); - DecodedString = StringFormat::Wide2UTF8(std::wstring(w, w + formatStringByteCount)); - totalStringBytes = (formatStringByteCount + 1) * sizeof(wchar_t); + UINT formatStringCharCount = UINT(wcslen((const wchar_t *)pData)); + DecodedString = StringFormat::Wide2UTF8(rdcwstr(w, formatStringCharCount)); + totalStringBytes = (formatStringCharCount + 1) * sizeof(wchar_t); } UINT64 byteChunks = ((totalStringBytes + copyChunkSize - 1) / copyChunkSize) * copyChunkSize; diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index a3d26974c..a47e46f63 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -80,7 +80,7 @@ inline std::string DecodeMarkerString(UINT Metadata, const void *pData, UINT Siz if(Metadata == PIX_EVENT_UNICODE_VERSION) { const wchar_t *w = (const wchar_t *)pData; - MarkerText = StringFormat::Wide2UTF8(std::wstring(w, w + Size / sizeof(wchar_t))); + MarkerText = StringFormat::Wide2UTF8(rdcwstr(w, Size / sizeof(wchar_t))); if(!MarkerText.empty() && (MarkerText.back() == ' ' || MarkerText.back() == 0)) MarkerText.pop_back(); } diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 53979c2f3..06eeb4877 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -568,8 +568,7 @@ std::string D3D12Replay::DisassembleShader(ResourceId pipeline, const ShaderRefl if(!strncmp((char *)iter, "SetName(this, sName.c_str()); } diff --git a/renderdoc/driver/dxgi/dxgi_common.cpp b/renderdoc/driver/dxgi/dxgi_common.cpp index b63386f49..d45889d26 100644 --- a/renderdoc/driver/dxgi/dxgi_common.cpp +++ b/renderdoc/driver/dxgi/dxgi_common.cpp @@ -1645,8 +1645,7 @@ static std::string GetDeviceProperty(HDEVINFO devs, PSP_DEVINFO_DATA data, const RDCASSERTEQUAL((uint32_t)type, DEVPROP_TYPE_STRING); - std::wstring string; - string.resize(bufSize); + rdcwstr string(bufSize); BOOL success = SetupDiGetDevicePropertyW(devs, data, key, &type, (PBYTE)string.data(), bufSize, &bufSize, 0); @@ -1670,7 +1669,7 @@ static uint32_t HexToInt(char hex) std::string GetDriverVersion(DXGI_ADAPTER_DESC &desc) { - std::string device = StringFormat::Wide2UTF8(desc.Description); + std::string device = StringFormat::Wide2UTF8(rdcwstr(desc.Description)); // fixed GUID for graphics drivers, from // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx @@ -2803,10 +2802,10 @@ void DoSerialise(SerialiserType &ser, DXGI_ADAPTER_DESC &el) if(ser.IsReading()) { - std::wstring wdesc = StringFormat::UTF82Wide(Description); + rdcwstr wdesc = StringFormat::UTF82Wide(Description); RDCEraseEl(el.Description); - memcpy(el.Description, wdesc.data(), - RDCMIN(wdesc.size(), ARRAY_COUNT(el.Description) - 1) * sizeof(WCHAR)); + memcpy(el.Description, wdesc.c_str(), + RDCMIN(wdesc.length(), ARRAY_COUNT(el.Description) - 1) * sizeof(WCHAR)); } } diff --git a/renderdoc/driver/gl/egl_platform.cpp b/renderdoc/driver/gl/egl_platform.cpp index ef612efca..e0df6d6fd 100644 --- a/renderdoc/driver/gl/egl_platform.cpp +++ b/renderdoc/driver/gl/egl_platform.cpp @@ -37,7 +37,7 @@ static void *GetEGLHandle() // has put it there. if(libEGL == "libEGL.dll") { - std::string libpath; + rdcstr libpath; FileIO::GetLibraryFilename(libpath); libpath = get_dirname(libpath); diff --git a/renderdoc/driver/ihv/amd/amd_isa.cpp b/renderdoc/driver/ihv/amd/amd_isa.cpp index d7c3c9893..e74771a4e 100644 --- a/renderdoc/driver/ihv/amd/amd_isa.cpp +++ b/renderdoc/driver/ihv/amd/amd_isa.cpp @@ -186,7 +186,7 @@ std::string DisassembleSPIRV(ShaderStage stage, const bytebuf &shaderBytes, cons tempPath.c_str(), stageName, tempPath.c_str(), stageName, tempPath.c_str(), stageName, tempPath.c_str(), stageName, tempPath.c_str(), tempPath.c_str()); - FileIO::dump(inPath.c_str(), shaderBytes.data(), shaderBytes.size()); + FileIO::WriteAll(inPath.c_str(), shaderBytes); // try to locate the amdspv relative to our running program std::string amdspv = LocatePluginFile(pluginPath, amdspv_name); @@ -204,29 +204,24 @@ std::string DisassembleSPIRV(ShaderStage stage, const bytebuf &shaderBytes, cons FileIO::Delete(StringFormat::Fmt("%sout.log", tempPath.c_str()).c_str()); FileIO::Delete(StringFormat::Fmt("%sout.bin", tempPath.c_str()).c_str()); - std::string ret; + rdcstr ret; if(amdil) { - std::vector data; - FileIO::slurp(StringFormat::Fmt("%sout.il", tempPath.c_str()).c_str(), data); - - ret = std::string(data.data(), data.data() + data.size()); + FileIO::ReadAll(StringFormat::Fmt("%sout.il", tempPath.c_str()).c_str(), ret); } else { - std::vector data; - FileIO::slurp(StringFormat::Fmt("%sout.txt", tempPath.c_str()).c_str(), data); - - ret = std::string(data.data(), data.data() + data.size()); + FileIO::ReadAll(StringFormat::Fmt("%sout.txt", tempPath.c_str()).c_str(), ret); std::string statsfile = StringFormat::Fmt("%sstats.txt", tempPath.c_str()); if(FileIO::exists(statsfile.c_str())) { - FileIO::slurp(statsfile.c_str(), data); + rdcstr stats; + FileIO::ReadAll(statsfile.c_str(), stats); - ret += std::string(data.data(), data.data() + data.size()); + ret += "\n\n" + stats; } } @@ -234,9 +229,9 @@ std::string DisassembleSPIRV(ShaderStage stage, const bytebuf &shaderBytes, cons FileIO::Delete(StringFormat::Fmt("%sout.txt", tempPath.c_str()).c_str()); FileIO::Delete(StringFormat::Fmt("%sstats.txt", tempPath.c_str()).c_str()); - std::string header = StringFormat::Fmt("; Disassembly for %s\n\n", target.c_str()); + rdcstr header = StringFormat::Fmt("; Disassembly for %s\n\n", target.c_str()); - ret.insert(ret.begin(), header.begin(), header.end()); + ret.insert(0, header.begin(), header.size()); return ret; } @@ -362,7 +357,7 @@ std::string DisassembleGLSL(ShaderStage stage, const bytebuf &shaderBytes, const if(!found) return "; Invalid ISA Target specified"; - FileIO::dump(inPath.c_str(), shaderBytes.data(), shaderBytes.size()); + FileIO::WriteAll(inPath.c_str(), shaderBytes); // try to locate the amdspv relative to our running program std::string vc = LocatePluginFile(pluginPath, virtualcontext_name); @@ -380,30 +375,28 @@ std::string DisassembleGLSL(ShaderStage stage, const bytebuf &shaderBytes, const FileIO::Delete(inPath.c_str()); FileIO::Delete(binPath.c_str()); - std::string ret; + rdcstr ret; { - std::vector data; - FileIO::slurp(outPath.c_str(), data); - ret = std::string(data.data(), data.data() + data.size()); + FileIO::ReadAll(outPath.c_str(), ret); while(ret.back() == '\0') ret.pop_back(); if(FileIO::exists(statsPath.c_str())) { - FileIO::slurp(statsPath.c_str(), data); - ret += "\n\n"; - ret += std::string(data.data(), data.data() + data.size()); + rdcstr stats; + FileIO::ReadAll(statsPath.c_str(), stats); + ret += "\n\n" + stats; } } FileIO::Delete(outPath.c_str()); FileIO::Delete(statsPath.c_str()); - std::string header = StringFormat::Fmt("; Disassembly for %s\n\n", target.c_str()); + rdcstr header = StringFormat::Fmt("; Disassembly for %s\n\n", target.c_str()); - ret.insert(ret.begin(), header.begin(), header.end()); + ret.insert(0, header.begin(), header.size()); return ret; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_common.h b/renderdoc/driver/shaders/dxbc/dxbc_common.h index c0d3eae9a..de5fd7616 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_common.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_common.h @@ -24,6 +24,10 @@ #pragma once +#include +#include +#include + namespace DXBC { struct CountOffset diff --git a/renderdoc/driver/shaders/dxbc/dxbc_compile.cpp b/renderdoc/driver/shaders/dxbc/dxbc_compile.cpp index a8e895a24..932647023 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_compile.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_compile.cpp @@ -60,12 +60,10 @@ HMODULE GetD3DCompiler() // we'll have to loadlibrary the version that ships with // RenderDoc. - std::string dllFile; + rdcstr dllFile; FileIO::GetLibraryFilename(dllFile); - std::string dll = get_dirname(dllFile) + "/d3dcompiler_47.dll"; + rdcstr dll = get_dirname(dllFile) + "/d3dcompiler_47.dll"; - ret = LoadLibraryW(StringFormat::UTF82Wide(dll.c_str()).c_str()); - - return ret; + return LoadLibraryW(StringFormat::UTF82Wide(dll.c_str()).data()); } diff --git a/renderdoc/driver/vulkan/vk_layer.cpp b/renderdoc/driver/vulkan/vk_layer.cpp index c4eb42b06..1aff577f1 100644 --- a/renderdoc/driver/vulkan/vk_layer.cpp +++ b/renderdoc/driver/vulkan/vk_layer.cpp @@ -61,9 +61,9 @@ class VulkanHook : LibraryHook #if ENABLED(RDOC_WIN32) // on windows support self-hosted capture by checking our filename and tweaking the env var we // set - std::string module_name; + rdcstr module_name; FileIO::GetLibraryFilename(module_name); - module_name = strupper(get_basename(module_name.substr(0, module_name.rfind('.')))); + module_name = strupper(strip_extension(get_basename(module_name))); if(module_name != "RENDERDOC") { Process::RegisterEnvironmentModification(EnvironmentModification( diff --git a/renderdoc/driver/vulkan/vk_posix.cpp b/renderdoc/driver/vulkan/vk_posix.cpp index 25ed5f632..06c0542ec 100644 --- a/renderdoc/driver/vulkan/vk_posix.cpp +++ b/renderdoc/driver/vulkan/vk_posix.cpp @@ -417,7 +417,7 @@ bool VulkanReplay::CheckVulkanLayer(VulkanLayerFlags &flags, std::vectorlpUniversalName); - jsonWide = nameInfo->lpUniversalName; + jsonPath = StringFormat::Wide2UTF8(nameInfo->lpUniversalName); } else { @@ -216,11 +216,11 @@ std::wstring GetJSONPath(bool wow6432) } if(wow6432) - jsonWide += L"\\x86"; + jsonPath += "\\x86"; - jsonWide += L"\\renderdoc.json"; + jsonPath += "\\renderdoc.json"; - return jsonWide; + return jsonPath; } static HKEY GetImplicitLayersKey(bool writeable, bool wow6432) @@ -256,8 +256,8 @@ static HKEY GetImplicitLayersKey(bool writeable, bool wow6432) return key; } -bool ProcessImplicitLayersKey(HKEY key, const std::wstring &path, - std::vector *otherJSONs, bool deleteOthers) +bool ProcessImplicitLayersKey(HKEY key, const rdcstr &path, std::vector *otherJSONs, + bool deleteOthers) { bool thisRegistered = false; @@ -267,8 +267,8 @@ bool ProcessImplicitLayersKey(HKEY key, const std::wstring &path, LONG ret = RegEnumValueW(key, idx++, name, &nameSize, NULL, NULL, NULL, NULL); - std::wstring myJSON = path; - for(size_t i = 0; i < myJSON.size(); i++) + rdcwstr myJSON = StringFormat::UTF82Wide(path); + for(size_t i = 0; i < myJSON.length(); i++) myJSON[i] = towlower(myJSON[i]); while(ret == ERROR_SUCCESS) @@ -302,12 +302,12 @@ bool ProcessImplicitLayersKey(HKEY key, const std::wstring &path, bool VulkanReplay::CheckVulkanLayer(VulkanLayerFlags &flags, std::vector &myJSONs, std::vector &otherJSONs) { - std::wstring normalPath = GetJSONPath(false); - myJSONs.push_back(StringFormat::Wide2UTF8(normalPath)); + rdcstr normalPath = GetJSONPath(false); + myJSONs.push_back(normalPath); #if ENABLED(RDOC_X64) - std::wstring wow6432Path = GetJSONPath(true); - myJSONs.push_back(StringFormat::Wide2UTF8(wow6432Path)); + rdcstr wow6432Path = GetJSONPath(true); + myJSONs.push_back(wow6432Path); #endif HKEY key = GetImplicitLayersKey(false, false); @@ -365,14 +365,15 @@ void VulkanReplay::InstallVulkanLayer(bool systemLevel) if(key) { - std::wstring path = GetJSONPath(false); + rdcstr path = GetJSONPath(false); // this function will delete all non-matching renderdoc.json values, and return true if our own // is registered bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true); if(!thisRegistered) - RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero)); + RegSetValueExW(key, StringFormat::UTF82Wide(path).c_str(), 0, REG_DWORD, (const BYTE *)&zero, + sizeof(zero)); RegCloseKey(key); } @@ -384,14 +385,15 @@ void VulkanReplay::InstallVulkanLayer(bool systemLevel) if(key) { - std::wstring path = GetJSONPath(true); + rdcstr path = GetJSONPath(true); // this function will delete all non-matching renderdoc.json values, and return true if our // own is registered bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true); if(!thisRegistered) - RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero)); + RegSetValueExW(key, StringFormat::UTF82Wide(path).c_str(), 0, REG_DWORD, + (const BYTE *)&zero, sizeof(zero)); RegCloseKey(key); } diff --git a/renderdoc/os/os_specific.cpp b/renderdoc/os/os_specific.cpp index 518ad01f3..94fca1b6a 100644 --- a/renderdoc/os/os_specific.cpp +++ b/renderdoc/os/os_specific.cpp @@ -24,7 +24,7 @@ ******************************************************************************/ #include "os/os_specific.h" -#include +#include "api/replay/control_types.h" #include "strings/string_utils.h" int utf8printf(char *buf, size_t bufsize, const char *fmt, va_list args); @@ -53,7 +53,7 @@ int vsnprintf(char *str, size_t bufSize, const char *format, va_list args) return ::utf8printf(str, bufSize, format, args); } -std::string Fmt(const char *format, ...) +rdcstr Fmt(const char *format, ...) { va_list args; va_start(args, format); @@ -63,74 +63,19 @@ std::string Fmt(const char *format, ...) int size = StringFormat::vsnprintf(NULL, 0, format, args2); - char *buf = new char[size + 1]; - StringFormat::vsnprintf(buf, size + 1, format, args); - buf[size] = 0; + rdcstr ret; + ret.resize(size); + StringFormat::vsnprintf(ret.data(), size + 1, format, args); va_end(args); va_end(args2); - std::string ret = buf; - - delete[] buf; - return ret; } -int Wide2UTF8(wchar_t chr, char mbchr[4]) -{ - // U+00000 -> U+00007F 1 byte 0xxxxxxx - // U+00080 -> U+0007FF 2 bytes 110xxxxx 10xxxxxx - // U+00800 -> U+00FFFF 3 bytes 1110xxxx 10xxxxxx 10xxxxxx - // U+10000 -> U+1FFFFF 4 bytes 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - // upcast to uint32_t, so we do the same processing on windows where - // sizeof(wchar_t) == 2 - uint32_t wc = (uint32_t)chr; - - if(wc > 0x10FFFF) - wc = 0xFFFD; // replacement character - - if(wc <= 0x7f) - { - mbchr[0] = (char)wc; - return 1; - } - else if(wc <= 0x7ff) - { - mbchr[1] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[0] = 0xC0 | (char)(wc & 0x1f); - return 2; - } - else if(wc <= 0xffff) - { - mbchr[2] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[1] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[0] = 0xE0 | (char)(wc & 0x0f); - wc >>= 4; - return 3; - } - else - { - // invalid codepoints above 0x10FFFF were replaced above - mbchr[3] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[2] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[1] = 0x80 | (char)(wc & 0x3f); - wc >>= 6; - mbchr[0] = 0xF0 | (char)(wc & 0x07); - wc >>= 3; - return 4; - } -} - }; // namespace StringFormat -std::string Callstack::AddressDetails::formattedString(const char *commonPath) +rdcstr Callstack::AddressDetails::formattedString(const char *commonPath) { char fmt[512] = {0}; @@ -138,8 +83,8 @@ std::string Callstack::AddressDetails::formattedString(const char *commonPath) if(commonPath) { - std::string common = strlower(std::string(commonPath)); - std::string fn = strlower(filename.substr(0, common.length())); + rdcstr common = strlower(rdcstr(commonPath)); + rdcstr fn = strlower(filename.substr(0, common.length())); if(common == fn) { @@ -155,9 +100,9 @@ std::string Callstack::AddressDetails::formattedString(const char *commonPath) return fmt; } -std::string OSUtility::MakeMachineIdentString(uint64_t ident) +rdcstr OSUtility::MakeMachineIdentString(uint64_t ident) { - std::string ret = ""; + rdcstr ret = ""; if(ident & MachineIdent_Windows) ret += "Windows "; @@ -204,7 +149,7 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") { SECTION("GetLibraryFilename") { - std::string libPath; + rdcstr libPath; FileIO::GetLibraryFilename(libPath); CHECK_FALSE(libPath.empty()); } @@ -237,7 +182,7 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") var = Process::GetEnvVariable("__renderdoc__unit_test_var"); CHECK(var); - CHECK(var == std::string("test_value")); + CHECK(var == rdcstr("test_value")); Process::RegisterEnvironmentModification(mod); Process::ApplyEnvironmentModification(); @@ -245,7 +190,7 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") var = Process::GetEnvVariable("__renderdoc__unit_test_var"); CHECK(var); - CHECK(var == std::string("test_value;test_value")); + CHECK(var == rdcstr("test_value;test_value")); mod.sep = EnvSep::Colon; @@ -255,7 +200,7 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") var = Process::GetEnvVariable("__renderdoc__unit_test_var"); CHECK(var); - CHECK(var == std::string("test_value;test_value:test_value")); + CHECK(var == rdcstr("test_value;test_value:test_value")); mod.value = "prepend"; mod.sep = EnvSep::SemiColon; @@ -267,7 +212,7 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") var = Process::GetEnvVariable("__renderdoc__unit_test_var"); CHECK(var); - CHECK(var == std::string("prepend;test_value;test_value:test_value")); + CHECK(var == rdcstr("prepend;test_value;test_value:test_value")); mod.value = "reset"; mod.sep = EnvSep::SemiColon; @@ -279,7 +224,26 @@ TEST_CASE("Test OS-specific functions", "[osspecific]") var = Process::GetEnvVariable("__renderdoc__unit_test_var"); CHECK(var); - CHECK(var == std::string("reset")); + CHECK(var == rdcstr("reset")); + }; + + SECTION("UTF-8 to wide conversion") + { + const rdcstr s = "ελληνικά"; + + rdcwstr ws = StringFormat::UTF82Wide(s); + + CHECK(ws.length() == 8); + CHECK(ws[0] == L'\x3b5'); + CHECK(ws[ws.length() - 1] == L'\x3ac'); + CHECK(ws[ws.length()] == L'\0'); + + rdcstr s2 = StringFormat::Wide2UTF8(ws); + + CHECK(s == s2); + + CHECK(StringFormat::UTF82Wide(rdcstr()).length() == 0); + CHECK(StringFormat::UTF82Wide(rdcstr()).c_str()[0] == 0); }; SECTION("Timing") diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index f2136a91c..47be87bde 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -35,17 +35,21 @@ #include #include #include -#include -#include -#include -#include "api/replay/renderdoc_replay.h" -#include "common/common.h" +#include "api/replay/rdcarray.h" +#include "api/replay/rdcpair.h" +#include "api/replay/rdcstr.h" +#include "common/globalconfig.h" struct CaptureOptions; +struct EnvironmentModification; +struct PathEntry; +enum class WindowingSystem : uint32_t; +enum class ReplayStatus : uint32_t; +typedef std::function RENDERDOC_ProgressCallback; namespace Process { -void RegisterEnvironmentModification(EnvironmentModification modif); +void RegisterEnvironmentModification(const EnvironmentModification &modif); void ApplyEnvironmentModification(); @@ -58,9 +62,10 @@ bool StartGlobalHook(const char *pathmatch, const char *capturefile, const Captu bool IsGlobalHookActive(); void StopGlobalHook(); -ExecuteResult InjectIntoProcess(uint32_t pid, const rdcarray &env, - const char *capturefile, const CaptureOptions &opts, - bool waitForExit); +rdcpair InjectIntoProcess(uint32_t pid, + const rdcarray &env, + const char *capturefile, + const CaptureOptions &opts, bool waitForExit); struct ProcessResult { rdcstr strStdout, strStderror; @@ -70,10 +75,10 @@ uint32_t LaunchProcess(const char *app, const char *workingDir, const char *cmdL ProcessResult *result = NULL); uint32_t LaunchScript(const char *script, const char *workingDir, const char *args, bool internal, ProcessResult *result = NULL); -ExecuteResult LaunchAndInjectIntoProcess(const char *app, const char *workingDir, const char *cmdLine, - const rdcarray &env, - const char *capturefile, const CaptureOptions &opts, - bool waitForExit); +rdcpair LaunchAndInjectIntoProcess( + const char *app, const char *workingDir, const char *cmdLine, + const rdcarray &env, const char *capturefile, + const CaptureOptions &opts, bool waitForExit); bool IsModuleLoaded(const char *module); void *LoadModule(const char *module); void *GetFunctionAddress(void *module, const char *function); @@ -239,11 +244,11 @@ public: struct AddressDetails { AddressDetails() : line(0) {} - std::string function; - std::string filename; + rdcstr function; + rdcstr filename; uint32_t line; - std::string formattedString(const char *commonPath = NULL); + rdcstr formattedString(const char *commonPath = NULL); }; class StackResolver @@ -265,28 +270,28 @@ bool GetLoadedModules(byte *buf, size_t &size); namespace FileIO { -void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, - std::string &logging_filename, std::string &target); -std::string GetHomeFolderFilename(); -std::string GetAppFolderFilename(const std::string &filename); -std::string GetTempFolderFilename(); -std::string GetReplayAppFilename(); +void GetDefaultFiles(const char *logBaseName, rdcstr &capture_filename, rdcstr &logging_filename, + rdcstr &target); +rdcstr GetHomeFolderFilename(); +rdcstr GetAppFolderFilename(const rdcstr &filename); +rdcstr GetTempFolderFilename(); +rdcstr GetReplayAppFilename(); -void CreateParentDirectory(const std::string &filename); +void CreateParentDirectory(const rdcstr &filename); -bool IsRelativePath(const std::string &path); -std::string GetFullPathname(const std::string &filename); -std::string FindFileInPath(const std::string &fileName); +bool IsRelativePath(const rdcstr &path); +rdcstr GetFullPathname(const rdcstr &filename); +rdcstr FindFileInPath(const rdcstr &fileName); -void GetExecutableFilename(std::string &selfName); -void GetLibraryFilename(std::string &selfName); +void GetExecutableFilename(rdcstr &selfName); +void GetLibraryFilename(rdcstr &selfName); -uint64_t GetModifiedTimestamp(const std::string &filename); +uint64_t GetModifiedTimestamp(const rdcstr &filename); bool Copy(const char *from, const char *to, bool allowOverwrite); bool Move(const char *from, const char *to, bool allowOverwrite); void Delete(const char *path); -std::vector GetFilesInDirectory(const char *path); +void GetFilesInDirectory(const char *path, rdcarray &entries); FILE *fopen(const char *filename, const char *mode); @@ -295,7 +300,7 @@ size_t fwrite(const void *buf, size_t elementSize, size_t count, FILE *f); bool exists(const char *filename); -std::string ErrorString(); +rdcstr ErrorString(); uint64_t ftell64(FILE *f); void fseek64(FILE *f, uint64_t offset, int origin); @@ -317,10 +322,10 @@ void logfile_close(LogFileHandle *logHandle, const char *deleteFilename); // read the whole logfile into memory. This may race with processes writing, but it will read the // whole of the file at some point. Useful since normal file reading may fail on the shared logfile -std::string logfile_readall(const char *filename); +rdcstr logfile_readall(const char *filename); // utility functions -inline bool dump(const char *filename, const void *buffer, size_t size) +inline bool WriteAll(const char *filename, const void *buffer, size_t size) { FILE *f = FileIO::fopen(filename, "wb"); if(f == NULL) @@ -333,7 +338,20 @@ inline bool dump(const char *filename, const void *buffer, size_t size) return numWritten == size; } -inline bool slurp(const char *filename, std::vector &buffer) +template +bool WriteAll(const char *filename, const rdcarray &buffer) +{ + return WriteAll(filename, buffer.data(), buffer.size()); +} + +template +bool WriteAll(const char *filename, const rdcstr &buffer) +{ + return WriteAll(filename, buffer.c_str(), buffer.length()); +} + +template +bool ReadAll(const char *filename, rdcarray &buffer) { FILE *f = FileIO::fopen(filename, "rb"); if(f == NULL) @@ -343,14 +361,33 @@ inline bool slurp(const char *filename, std::vector &buffer) uint64_t size = ftell64(f); FileIO::fseek64(f, 0, SEEK_SET); - buffer.resize((size_t)size); + buffer.resize((size_t)size / sizeof(T)); - size_t numRead = FileIO::fread(&buffer[0], 1, buffer.size(), f); + size_t numRead = FileIO::fread(&buffer[0], sizeof(T), buffer.size(), f); FileIO::fclose(f); return numRead == buffer.size(); } + +inline bool ReadAll(const char *filename, rdcstr &str) +{ + FILE *f = FileIO::fopen(filename, "rb"); + if(f == NULL) + return false; + + FileIO::fseek64(f, 0, SEEK_END); + uint64_t size = ftell64(f); + FileIO::fseek64(f, 0, SEEK_SET); + + str.resize((size_t)size); + + size_t numRead = FileIO::fread(&str[0], 1, str.size(), f); + + FileIO::fclose(f); + + return numRead == str.size(); +} }; namespace Keyboard @@ -362,13 +399,45 @@ bool GetKeyState(int key); bool PlatformHasKeyInput(); }; +// simple container for passing around temporary wide strings. We leave it immutable and manually +// add the trailing NULL. These are used as rarely as possible but still needed for interacting with +// windows/D3D APIs. +struct rdcwstr : private rdcarray +{ + rdcwstr() : rdcarray() {} + rdcwstr(const wchar_t *str, size_t N) : rdcarray(str, N) + { + // push null terminator + rdcarray::push_back(0); + } + rdcwstr(const wchar_t *str) + { + while(*str) + { + rdcarray::push_back(*str); + str++; + } + // push null terminator + rdcarray::push_back(0); + } + template + rdcwstr(const wchar_t (&el)[N]) : rdcwstr(&el[0]) + { + } + rdcwstr(size_t N) { resize(N + 1); } + wchar_t *data() { return rdcarray::data(); } + const wchar_t *c_str() const { return rdcarray::data(); } + using rdcarray::operator[]; + size_t length() const { return rdcarray::size() - 1; } +}; + // implemented per-platform namespace StringFormat { void sntimef(time_t utcTime, char *str, size_t bufSize, const char *format); -std::string Wide2UTF8(const std::wstring &s); -std::wstring UTF82Wide(const std::string &s); +rdcstr Wide2UTF8(const rdcwstr &str); +rdcwstr UTF82Wide(const rdcstr &s); void Shutdown(); }; @@ -382,9 +451,7 @@ int snprintf(char *str, size_t bufSize, const char *format, ...); void sntimef(char *str, size_t bufSize, const char *format); -std::string Fmt(const char *format, ...); - -int Wide2UTF8(wchar_t chr, char mbchr[4]); +rdcstr Fmt(const char *format, ...); }; namespace OSUtility @@ -434,7 +501,7 @@ enum MachineIdentBits }; uint64_t GetMachineIdent(); -std::string MakeMachineIdentString(uint64_t ident); +rdcstr MakeMachineIdentString(uint64_t ident); }; namespace Bits @@ -448,7 +515,7 @@ inline uint64_t CountLeadingZeroes(uint64_t value); // must #define: // __PRETTY_FUNCTION_SIGNATURE__ - undecorated function signature // GetEmbeddedResource(name_with_underscores_ext) - function/inline that returns the given file in a -// std::string +// rdcstr // OS_DEBUG_BREAK() - instruction that debugbreaks the debugger - define instead of function to // preserve callstacks // EndianSwapXX() for XX = 16, 32, 64 diff --git a/renderdoc/os/posix/android/android_hook.cpp b/renderdoc/os/posix/android/android_hook.cpp index d006520de..c14811094 100644 --- a/renderdoc/os/posix/android/android_hook.cpp +++ b/renderdoc/os/posix/android/android_hook.cpp @@ -86,20 +86,20 @@ public: funchook_map[hook.function] = hook; } - void AddLibHook(const std::string &name) + void AddLibHook(const rdcstr &name) { SCOPED_LOCK(lock); - if(std::find(libhooks.begin(), libhooks.end(), name) == libhooks.end()) + if(libhooks.contains(name)) libhooks.push_back(name); } - void AddHookCallback(const std::string &name, FunctionLoadCallback callback) + void AddHookCallback(const rdcstr &name, FunctionLoadCallback callback) { SCOPED_LOCK(lock); hookcallbacks[name].push_back(callback); } - std::vector GetFunctionHooks() + rdcarray GetFunctionHooks() { SCOPED_LOCK(lock); return funchooks; @@ -113,30 +113,30 @@ public: funchook_map.clear(); } - std::vector GetLibHooks() + rdcarray GetLibHooks() { SCOPED_LOCK(lock); return libhooks; } - std::map> GetHookCallbacks() + std::map> GetHookCallbacks() { SCOPED_LOCK(lock); return hookcallbacks; } - FunctionHook GetFunctionHook(const std::string &name) + FunctionHook GetFunctionHook(const rdcstr &name) { SCOPED_LOCK(lock); return funchook_map[name]; } - bool IsLibHook(const std::string &path) + bool IsLibHook(const rdcstr &path) { SCOPED_LOCK(lock); - for(const std::string &filename : libhooks) + for(const rdcstr &filename : libhooks) { - if(path.find(filename) != std::string::npos) + if(path.contains(filename)) { HOOK_DEBUG_PRINT("Intercepting and returning ourselves for %s (matches %s)", path.c_str(), filename.c_str()); @@ -150,7 +150,7 @@ public: bool IsLibHook(void *handle) { SCOPED_LOCK(lock); - for(const std::string &lib : libhooks) + for(const rdcstr &lib : libhooks) { void *libHandle = dlopen(lib.c_str(), RTLD_NOLOAD); HOOK_DEBUG_PRINT("%s is %p", lib.c_str(), libHandle); @@ -168,15 +168,15 @@ public: return ret; } - bool IsHooked(const std::string &soname) + bool IsHooked(const rdcstr &soname) { SCOPED_LOCK(lock); if(hooked_soname_already.find(soname) != hooked_soname_already.end()) return true; // above will be absolute path, allow substring matches - for(const std::string &fn : hooked_soname_already) - if(soname.find(fn) != std::string::npos) + for(const rdcstr &fn : hooked_soname_already) + if(soname.contains(fn)) return true; return false; @@ -188,21 +188,21 @@ public: hooked_handle_already.insert(handle); } - void SetHooked(const std::string &soname) + void SetHooked(const rdcstr &soname) { SCOPED_LOCK(lock); hooked_soname_already.insert(soname); } private: - std::set hooked_soname_already; + std::set hooked_soname_already; std::set hooked_handle_already; - std::vector funchooks; - std::map funchook_map; - std::vector libhooks; + rdcarray funchooks; + std::map funchook_map; + rdcarray libhooks; - std::map> hookcallbacks; + std::map> hookcallbacks; Threading::CriticalSection lock; }; @@ -222,7 +222,7 @@ void *intercept_dlopen(const char *filename, int flag) // We need to intercept requests for our own library, because the android loader makes the // completely ridiculous decision to load multiple copies of the same library into a process if // it's dlopen'd with different paths. This obviously breaks with our hook install. - if(strstr(filename, RENDERDOC_ANDROID_LIBRARY) || GetHookInfo().IsLibHook(std::string(filename))) + if(strstr(filename, RENDERDOC_ANDROID_LIBRARY) || GetHookInfo().IsLibHook(rdcstr(filename))) { HOOK_DEBUG_PRINT("Intercepting dlopen for %s", filename); return dlopen(RENDERDOC_ANDROID_LIBRARY, flag); @@ -240,7 +240,7 @@ static int dl_iterate_callback(struct dl_phdr_info *info, size_t size, void *dat HOOK_DEBUG_PRINT("Skipping NULL entry!"); return 0; } - std::string soname = info->dlpi_name; + rdcstr soname = info->dlpi_name; if(GetHookInfo().IsHooked(soname)) return 0; @@ -432,7 +432,7 @@ uint64_t suppressTLS = 0; void process_dlopen(const char *filename, int flag) { - if(filename && !GetHookInfo().IsHooked(std::string(filename))) + if(filename && !GetHookInfo().IsHooked(rdcstr(filename))) { HOOK_DEBUG_PRINT("iterating after %s", filename); dl_iterate_phdr(dl_iterate_callback, NULL); @@ -569,20 +569,20 @@ void PatchHookedFunctions() LibraryHooks::RegisterLibraryHook("/system/lib/libhwgl.so", NULL); #endif - std::vector libs = GetHookInfo().GetLibHooks(); - std::vector funchooks = GetHookInfo().GetFunctionHooks(); + rdcarray libs = GetHookInfo().GetLibHooks(); + rdcarray funchooks = GetHookInfo().GetFunctionHooks(); // we just leak this void *intercept = InitializeInterceptor(); - std::set fallbacklibs; + std::set fallbacklibs; std::set fallbackhooks; - for(const std::string &lib : libs) + for(const rdcstr &lib : libs) { void *handle = dlopen(lib.c_str(), RTLD_NOW); - bool huawei = lib.find("libhwgl.so") != std::string::npos; + bool huawei = lib.contains("libhwgl.so"); if(!handle) { @@ -653,7 +653,7 @@ void PatchHookedFunctions() // This is just a minimal setup to intercept that one function. GetHookInfo().ClearHooks(); - for(const std::string &l : fallbacklibs) + for(const rdcstr &l : fallbacklibs) { RDCLOG("Falling back to PLT hooking for %s", l.c_str()); GetHookInfo().AddLibHook(l); @@ -721,8 +721,8 @@ void LibraryHooks::EndHookRegistration() // ensure we load all libraries we can immediately, so they are immediately hooked and don't get // loaded later. - std::vector libs = GetHookInfo().GetLibHooks(); - for(const std::string &lib : libs) + rdcarray libs = GetHookInfo().GetLibHooks(); + for(const rdcstr &lib : libs) { void *handle = dlopen(lib.c_str(), RTLD_GLOBAL); HOOK_DEBUG_PRINT("%s: %p", lib.c_str(), handle); @@ -745,8 +745,8 @@ void LibraryHooks::EndHookRegistration() // have. If we have interceptor-lib this will only be for functions that failed to generate a // trampoline and we're PLT hooking - without interceptor-lib this will be all functions, but it // will allow us to control the order/priority. - std::vector libraryHooks = GetHookInfo().GetLibHooks(); - std::vector functionHooks = GetHookInfo().GetFunctionHooks(); + rdcarray libraryHooks = GetHookInfo().GetLibHooks(); + rdcarray functionHooks = GetHookInfo().GetFunctionHooks(); RDCLOG("Fetching %zu original function pointers over %zu libraries", functionHooks.size(), libraryHooks.size()); @@ -769,9 +769,8 @@ void LibraryHooks::EndHookRegistration() // call the callbacks for any libraries that loaded now. If the library wasn't loaded above then // it can't be loaded, since we only hook system libraries. - std::map> callbacks = - GetHookInfo().GetHookCallbacks(); - for(const std::pair> &cb : callbacks) + std::map> callbacks = GetHookInfo().GetHookCallbacks(); + for(const std::pair> &cb : callbacks) { void *handle = dlopen(cb.first.c_str(), RTLD_GLOBAL); if(handle) diff --git a/renderdoc/os/posix/android/android_process.cpp b/renderdoc/os/posix/android/android_process.cpp index 92436c4bf..67b2b583e 100644 --- a/renderdoc/os/posix/android/android_process.cpp +++ b/renderdoc/os/posix/android/android_process.cpp @@ -37,7 +37,7 @@ int GetIdentPort(pid_t childPid) { int ret = 0; - std::string procfile = StringFormat::Fmt("/proc/%d/net/unix", (int)childPid); + rdcstr procfile = StringFormat::Fmt("/proc/%d/net/unix", (int)childPid); // try for a little while for the /proc entry to appear for(int retry = 0; retry < 10; retry++) diff --git a/renderdoc/os/posix/android/android_stringio.cpp b/renderdoc/os/posix/android/android_stringio.cpp index e85351387..9941b6dff 100644 --- a/renderdoc/os/posix/android/android_stringio.cpp +++ b/renderdoc/os/posix/android/android_stringio.cpp @@ -56,25 +56,25 @@ bool GetKeyState(int key) namespace FileIO { -std::string GetTempRootPath() +rdcstr GetTempRootPath() { // Save captures in the app's private /sdcard directory, which doesnt require // WRITE_EXTERNAL_STORAGE permissions. There is no security enforced here, // so the replay server can load it as it has READ_EXTERNAL_STORAGE. // This is the same as returned by getExternalFilesDir(). It might possibly change in the future. - std::string package; + rdcstr package; GetExecutableFilename(package); return "/sdcard/Android/data/" + package + "/files"; } -std::string GetAppFolderFilename(const std::string &filename) +rdcstr GetAppFolderFilename(const rdcstr &filename) { - return GetTempRootPath() + std::string("/") + filename; + return GetTempRootPath() + rdcstr("/") + filename; } // For RenderDoc's apk, this returns our package name // For other APKs, we use it to get the writable temp directory. -void GetExecutableFilename(std::string &selfName) +void GetExecutableFilename(rdcstr &selfName) { char buf[4096]; snprintf(buf, sizeof(buf), "/proc/%u/cmdline", getpid()); @@ -91,12 +91,12 @@ void GetExecutableFilename(std::string &selfName) } // Strip any process name from cmdline (android:process) - std::string cmdline = buf; - std::string filename = cmdline.substr(0, cmdline.find(":")); + rdcstr cmdline = buf; + rdcstr filename = cmdline.substr(0, cmdline.find(":")); selfName = filename; } -void GetLibraryFilename(std::string &selfName) +void GetLibraryFilename(rdcstr &selfName) { RDCERR("GetLibraryFilename is not defined on Android"); GetExecutableFilename(selfName); @@ -105,13 +105,13 @@ void GetLibraryFilename(std::string &selfName) namespace StringFormat { -std::string Wide2UTF8(const std::wstring &s) +rdcstr Wide2UTF8(const rdcwstr &s) { RDCFATAL("Converting wide strings to UTF-8 is not supported on Android!"); return ""; } -std::wstring UTF82Wide(const std::string &s) +rdcwstr UTF82Wide(const rdcstr &s) { RDCFATAL("Converting UTF-8 to wide strings is not supported on Android!"); return L""; diff --git a/renderdoc/os/posix/apple/apple_hook.cpp b/renderdoc/os/posix/apple/apple_hook.cpp index db9965390..e51256a64 100644 --- a/renderdoc/os/posix/apple/apple_hook.cpp +++ b/renderdoc/os/posix/apple/apple_hook.cpp @@ -34,16 +34,16 @@ Threading::CriticalSection libLock; -static std::map> libraryCallbacks; -static std::set libraryHooks; -static std::vector functionHooks; +static std::map> libraryCallbacks; +static std::set libraryHooks; +static rdcarray functionHooks; static std::set libraryHandles; void *interposed_dlopen(const char *filename, int flag) { void *handle = dlopen(filename, flag); - std::string baseFilename = filename ? get_basename(std::string(filename)) : ""; + rdcstr baseFilename = filename ? get_basename(rdcstr(filename)) : ""; { SCOPED_LOCK(libLock); @@ -104,7 +104,7 @@ void LibraryHooks::EndHookRegistration() // them for the dyld interposing) for(auto it = libraryCallbacks.begin(); it != libraryCallbacks.end(); ++it) { - std::string libName = it->first; + rdcstr libName = it->first; void *handle = dlopen(libName.c_str(), RTLD_NOW | RTLD_GLOBAL); if(handle) @@ -149,7 +149,7 @@ void LibraryHooks::RegisterLibraryHook(char const *name, FunctionLoadCallback cb SCOPED_LOCK(libLock); // we match by basename for library hooks - libraryHooks.insert(get_basename(std::string(name))); + libraryHooks.insert(get_basename(rdcstr(name))); if(cb) libraryCallbacks[name].push_back(cb); diff --git a/renderdoc/os/posix/apple/apple_process.cpp b/renderdoc/os/posix/apple/apple_process.cpp index 964b7260e..dccd84a47 100644 --- a/renderdoc/os/posix/apple/apple_process.cpp +++ b/renderdoc/os/posix/apple/apple_process.cpp @@ -34,7 +34,7 @@ char **GetCurrentEnvironment() return *_NSGetEnviron(); } -std::string execcmd(const char *cmd) +rdcstr execcmd(const char *cmd) { FILE *pipe = popen(cmd, "r"); @@ -43,7 +43,7 @@ std::string execcmd(const char *cmd) char buffer[128]; - std::string result = ""; + rdcstr result = ""; while(!feof(pipe)) { @@ -63,8 +63,8 @@ bool isNewline(char c) int GetIdentPort(pid_t childPid) { - std::string lsof = StringFormat::Fmt("lsof -p %d -a -i 4 -F n", (int)childPid); - std::string result; + rdcstr lsof = StringFormat::Fmt("lsof -p %d -a -i 4 -F n", (int)childPid); + rdcstr result; uint32_t wait = 1; for(int i = 0; i < 10; ++i) { @@ -85,7 +85,7 @@ int GetIdentPort(pid_t childPid) // // n*: - std::string parseResult(result); + rdcstr parseResult(result); const size_t len = parseResult.length(); if(parseResult[0] == 'p') { @@ -107,8 +107,8 @@ int GetIdentPort(pid_t childPid) const char *netString("n*:"); while(i < len) { - const size_t netStart = parseResult.find(netString, i); - if(netStart != std::string::npos) + const int netStart = parseResult.find(netString, i); + if(netStart >= 0) { tokenStart = netStart + strlen(netString); i = tokenStart; diff --git a/renderdoc/os/posix/apple/apple_stringio.cpp b/renderdoc/os/posix/apple/apple_stringio.cpp index a063d2856..011028041 100644 --- a/renderdoc/os/posix/apple/apple_stringio.cpp +++ b/renderdoc/os/posix/apple/apple_stringio.cpp @@ -61,31 +61,31 @@ bool GetKeyState(int key) namespace FileIO { -std::string GetTempRootPath() +rdcstr GetTempRootPath() { return "/tmp"; } -std::string GetAppFolderFilename(const std::string &filename) +rdcstr GetAppFolderFilename(const rdcstr &filename) { passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; - std::string ret = std::string(homedir) + "/.renderdoc/"; + rdcstr ret = rdcstr(homedir) + "/.renderdoc/"; mkdir(ret.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); return ret + filename; } -void GetExecutableFilename(std::string &selfName) +void GetExecutableFilename(rdcstr &selfName) { char path[512] = {0}; uint32_t pathSize = (uint32_t)sizeof(path); if(_NSGetExecutablePath(path, &pathSize) == 0) { - selfName = std::string(path); + selfName = rdcstr(path); } else { @@ -94,7 +94,7 @@ void GetExecutableFilename(std::string &selfName) memset(allocPath, 0, pathSize); if(_NSGetExecutablePath(path, &pathSize) == 0) { - selfName = std::string(path); + selfName = rdcstr(path); } else { @@ -110,12 +110,12 @@ void GetExecutableFilename(std::string &selfName) readlink(selfName.c_str(), path, 511); if(path[0] != 0) - selfName = std::string(path); + selfName = rdcstr(path); } int LibraryLocator = 42; -void GetLibraryFilename(std::string &selfName) +void GetLibraryFilename(rdcstr &selfName) { Dl_info info; if(dladdr(&LibraryLocator, &info)) @@ -154,13 +154,13 @@ void Shutdown() iconvUTF82Wide = (iconv_t)-1; } -std::string Wide2UTF8(const std::wstring &s) +rdcstr Wide2UTF8(const rdcwstr &s) { // include room for null terminator, assuming unicode input (not ucs) // utf-8 characters can be max 4 bytes. size_t len = (s.length() + 1) * 4; - std::vector charBuffer(len); + rdcarray charBuffer(len); size_t ret; @@ -195,16 +195,16 @@ std::string Wide2UTF8(const std::wstring &s) // convert to string from null-terminated string - utf-8 never contains // 0 bytes before the null terminator, and this way we don't care if // charBuffer is larger than the string - return std::string(&charBuffer[0]); + return rdcstr(&charBuffer[0]); } -std::wstring UTF82Wide(const std::string &s) +rdcwstr UTF82Wide(const rdcstr &s) { // include room for null terminator, for ascii input we need at least as many output chars as // input. size_t len = s.length() + 1; - std::vector wcharBuffer(len); + rdcarray wcharBuffer(len); size_t ret; @@ -237,7 +237,7 @@ std::wstring UTF82Wide(const std::string &s) } // convert to string from null-terminated string - return std::wstring(&wcharBuffer[0]); + return rdcwstr(&wcharBuffer[0]); } }; diff --git a/renderdoc/os/posix/ggp/ggp_callstack.cpp b/renderdoc/os/posix/ggp/ggp_callstack.cpp index 0379f3458..a7df649c5 100644 --- a/renderdoc/os/posix/ggp/ggp_callstack.cpp +++ b/renderdoc/os/posix/ggp/ggp_callstack.cpp @@ -151,7 +151,7 @@ struct LookupModule class GgpResolver : public Callstack::StackResolver { public: - GgpResolver(std::vector modules) { m_Modules = modules; } + GgpResolver(rdcarray modules) { m_Modules = modules; } Callstack::AddressDetails GetAddr(uint64_t addr) { EnsureCached(addr); @@ -178,8 +178,7 @@ private: if(addr >= m_Modules[i].base && addr < m_Modules[i].end) { uint64_t relative = addr - m_Modules[i].base + m_Modules[i].offset; - std::string cmd = - StringFormat::Fmt("addr2line -fCe \"%s\" 0x%llx", m_Modules[i].path, relative); + rdcstr cmd = StringFormat::Fmt("addr2line -fCe \"%s\" 0x%llx", m_Modules[i].path, relative); FILE *f = ::popen(cmd.c_str(), "r"); @@ -226,7 +225,7 @@ private: } } - std::vector m_Modules; + rdcarray m_Modules; std::map m_Cache; }; @@ -247,7 +246,7 @@ StackResolver *MakeResolver(byte *moduleDB, size_t DBSize, RENDERDOC_ProgressCal char *search = start; char *dbend = (char *)(moduleDB + DBSize); - std::vector modules; + rdcarray modules; while(search && search < dbend) { diff --git a/renderdoc/os/posix/ggp/ggp_process.cpp b/renderdoc/os/posix/ggp/ggp_process.cpp index 6894deda5..a6fc1da7d 100644 --- a/renderdoc/os/posix/ggp/ggp_process.cpp +++ b/renderdoc/os/posix/ggp/ggp_process.cpp @@ -38,17 +38,18 @@ char **GetCurrentEnvironment() return environ; } -std::vector getSockets(pid_t childPid) +rdcarray getSockets(pid_t childPid) { - std::vector sockets; - std::string dirPath = StringFormat::Fmt("/proc/%d/fd", (int)childPid); - std::vector files = FileIO::GetFilesInDirectory(dirPath.c_str()); + rdcarray sockets; + rdcstr dirPath = StringFormat::Fmt("/proc/%d/fd", (int)childPid); + rdcarray files; + FileIO::GetFilesInDirectory(dirPath.c_str(), files); if(files.empty()) return sockets; for(const PathEntry &file : files) { - std::string target = StringFormat::Fmt("%s/%s", dirPath.c_str(), file.filename.c_str()); + rdcstr target = StringFormat::Fmt("%s/%s", dirPath.c_str(), file.filename.c_str()); char linkname[1024]; ssize_t length = readlink(target.c_str(), linkname, 1023); if(length == -1) @@ -67,7 +68,7 @@ int GetIdentPort(pid_t childPid) { int ret = 0; - std::string procfile = StringFormat::Fmt("/proc/%d/net/tcp", (int)childPid); + rdcstr procfile = StringFormat::Fmt("/proc/%d/net/tcp", (int)childPid); int waitTime = INITIAL_WAIT_TIME; @@ -87,7 +88,7 @@ int GetIdentPort(pid_t childPid) continue; } - std::vector sockets = getSockets(childPid); + rdcarray sockets = getSockets(childPid); // read through the proc file to check for an open listen socket while(ret == 0 && !feof(f)) @@ -107,8 +108,7 @@ int GetIdentPort(pid_t childPid) // find open listen socket on 0.0.0.0:port if(num == 4 && hexip == 0 && hexport >= RenderDoc_FirstTargetControlPort && - hexport <= RenderDoc_LastTargetControlPort && - std::find(sockets.begin(), sockets.end(), inode) != sockets.end()) + hexport <= RenderDoc_LastTargetControlPort && sockets.contains(inode)) { ret = hexport; } diff --git a/renderdoc/os/posix/ggp/ggp_stringio.cpp b/renderdoc/os/posix/ggp/ggp_stringio.cpp index 3c169348a..8d45f8f75 100644 --- a/renderdoc/os/posix/ggp/ggp_stringio.cpp +++ b/renderdoc/os/posix/ggp/ggp_stringio.cpp @@ -64,12 +64,12 @@ bool GetKeyState(int key) namespace FileIO { -std::string GetTempRootPath() +rdcstr GetTempRootPath() { return "/tmp"; } -std::string GetAppFolderFilename(const std::string &filename) +rdcstr GetAppFolderFilename(const rdcstr &filename) { const char *homedir = NULL; if(getenv("HOME") != NULL) @@ -83,29 +83,29 @@ std::string GetAppFolderFilename(const std::string &filename) homedir = getpwuid(getuid())->pw_dir; } - std::string ret = std::string(homedir) + "/.renderdoc/"; + rdcstr ret = rdcstr(homedir) + "/.renderdoc/"; mkdir(ret.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); return ret + filename; } -void GetExecutableFilename(std::string &selfName) +void GetExecutableFilename(rdcstr &selfName) { char path[512] = {0}; readlink("/proc/self/exe", path, 511); - selfName = std::string(path); + selfName = rdcstr(path); } int LibraryLocator = 42; -void GetLibraryFilename(std::string &selfName) +void GetLibraryFilename(rdcstr &selfName) { // this is a hack, but the only reliable way to find the absolute path to the library. // dladdr would be fine but it returns the wrong result for symbols in the library - std::string librenderdoc_path; + rdcstr librenderdoc_path; FILE *f = fopen("/proc/self/maps", "r"); @@ -180,7 +180,7 @@ void GetLibraryFilename(std::string &selfName) char *end = strchr(c, '\n'); if(end) - librenderdoc_path = std::string(c, end - c); + librenderdoc_path = rdcstr(c, end - c); } delete[] map_string; @@ -223,13 +223,13 @@ void Shutdown() iconvUTF82Wide = (iconv_t)-1; } -std::string Wide2UTF8(const std::wstring &s) +rdcstr Wide2UTF8(const rdcwstr &s) { // include room for null terminator, assuming unicode input (not ucs) // utf-8 characters can be max 4 bytes. size_t len = (s.length() + 1) * 4; - std::vector charBuffer(len); + rdcarray charBuffer(len); size_t ret; @@ -264,16 +264,16 @@ std::string Wide2UTF8(const std::wstring &s) // convert to string from null-terminated string - utf-8 never contains // 0 bytes before the null terminator, and this way we don't care if // charBuffer is larger than the string - return std::string(&charBuffer[0]); + return rdcstr(&charBuffer[0]); } -std::wstring UTF82Wide(const std::string &s) +rdcwstr UTF82Wide(const rdcstr &s) { // include room for null terminator, for ascii input we need at least as many output chars as // input. size_t len = s.length() + 1; - std::vector wcharBuffer(len); + rdcarray wcharBuffer(len); size_t ret; @@ -306,7 +306,7 @@ std::wstring UTF82Wide(const std::string &s) } // convert to string from null-terminated string - return std::wstring(&wcharBuffer[0]); + return rdcwstr(&wcharBuffer[0]); } }; diff --git a/renderdoc/os/posix/linux/linux_callstack.cpp b/renderdoc/os/posix/linux/linux_callstack.cpp index f60cf651d..d11013abf 100644 --- a/renderdoc/os/posix/linux/linux_callstack.cpp +++ b/renderdoc/os/posix/linux/linux_callstack.cpp @@ -155,7 +155,7 @@ struct LookupModule class LinuxResolver : public Callstack::StackResolver { public: - LinuxResolver(std::vector modules) { m_Modules = modules; } + LinuxResolver(rdcarray modules) { m_Modules = modules; } Callstack::AddressDetails GetAddr(uint64_t addr) { EnsureCached(addr); @@ -182,8 +182,7 @@ private: if(addr >= m_Modules[i].base && addr < m_Modules[i].end) { uint64_t relative = addr - m_Modules[i].base + m_Modules[i].offset; - std::string cmd = - StringFormat::Fmt("addr2line -fCe \"%s\" 0x%llx", m_Modules[i].path, relative); + rdcstr cmd = StringFormat::Fmt("addr2line -fCe \"%s\" 0x%llx", m_Modules[i].path, relative); FILE *f = ::popen(cmd.c_str(), "r"); @@ -230,7 +229,7 @@ private: } } - std::vector m_Modules; + rdcarray m_Modules; std::map m_Cache; }; @@ -251,7 +250,7 @@ StackResolver *MakeResolver(byte *moduleDB, size_t DBSize, RENDERDOC_ProgressCal char *search = start; char *dbend = (char *)(moduleDB + DBSize); - std::vector modules; + rdcarray modules; while(search && search < dbend) { diff --git a/renderdoc/os/posix/linux/linux_hook.cpp b/renderdoc/os/posix/linux/linux_hook.cpp index 262afbdcb..a438cf93e 100644 --- a/renderdoc/os/posix/linux/linux_hook.cpp +++ b/renderdoc/os/posix/linux/linux_hook.cpp @@ -35,9 +35,9 @@ Threading::CriticalSection libLock; -static std::map> libraryCallbacks; -static std::vector libraryHooks; -static std::vector functionHooks; +static std::map> libraryCallbacks; +static rdcarray libraryHooks; +static rdcarray functionHooks; void *intercept_dlopen(const char *filename, int flag, void *ret); void plthook_lib(void *handle); @@ -148,7 +148,7 @@ static void CheckLoadedLibraries() // them and call callbacks. for(auto it = libraryHooks.begin(); it != libraryHooks.end(); ++it) { - std::string libName = *it; + rdcstr libName = *it; void *handle = realdlopen(libName.c_str(), RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); if(handle) @@ -159,7 +159,7 @@ static void CheckLoadedLibraries() *hook.orig = dlsym(handle, hook.function.c_str()); } - std::vector callbacks; + rdcarray callbacks; // don't call callbacks again if the library is dlopen'd again libraryCallbacks[libName].swap(callbacks); @@ -185,11 +185,11 @@ void *intercept_dlopen(const char *filename, int flag, void *ret) if(flag & RTLD_DEEPBIND) plthook_lib(ret); - std::string base = get_basename(filename); + rdcstr base = get_basename(filename); for(auto it = libraryHooks.begin(); it != libraryHooks.end(); ++it) { - const std::string &libName = *it; + const rdcstr &libName = *it; if(*it == base) { RDCDEBUG("Redirecting dlopen to ourselves for %s", filename); @@ -200,7 +200,7 @@ void *intercept_dlopen(const char *filename, int flag, void *ret) *hook.orig = dlsym(ret, hook.function.c_str()); } - std::vector callbacks; + rdcarray callbacks; // don't call callbacks again if the library is dlopen'd again libraryCallbacks[libName].swap(callbacks); @@ -259,7 +259,7 @@ void LibraryHooks::RegisterLibraryHook(char const *name, FunctionLoadCallback cb { SCOPED_LOCK(libLock); - if(std::find(libraryHooks.begin(), libraryHooks.end(), name) == libraryHooks.end()) + if(libraryHooks.contains(name)) libraryHooks.push_back(name); if(cb) diff --git a/renderdoc/os/posix/linux/linux_process.cpp b/renderdoc/os/posix/linux/linux_process.cpp index 534d2c405..de3a79e50 100644 --- a/renderdoc/os/posix/linux/linux_process.cpp +++ b/renderdoc/os/posix/linux/linux_process.cpp @@ -38,17 +38,18 @@ char **GetCurrentEnvironment() return environ; } -std::vector getSockets(pid_t childPid) +rdcarray getSockets(pid_t childPid) { - std::vector sockets; - std::string dirPath = StringFormat::Fmt("/proc/%d/fd", (int)childPid); - std::vector files = FileIO::GetFilesInDirectory(dirPath.c_str()); + rdcarray sockets; + rdcstr dirPath = StringFormat::Fmt("/proc/%d/fd", (int)childPid); + rdcarray files; + FileIO::GetFilesInDirectory(dirPath.c_str(), files); if(files.empty()) return sockets; for(const PathEntry &file : files) { - std::string target = StringFormat::Fmt("%s/%s", dirPath.c_str(), file.filename.c_str()); + rdcstr target = StringFormat::Fmt("%s/%s", dirPath.c_str(), file.filename.c_str()); char linkname[1024]; ssize_t length = readlink(target.c_str(), linkname, 1023); if(length == -1) @@ -67,7 +68,7 @@ int GetIdentPort(pid_t childPid) { int ret = 0; - std::string procfile = StringFormat::Fmt("/proc/%d/net/tcp", (int)childPid); + rdcstr procfile = StringFormat::Fmt("/proc/%d/net/tcp", (int)childPid); int waitTime = INITIAL_WAIT_TIME; @@ -87,7 +88,7 @@ int GetIdentPort(pid_t childPid) continue; } - std::vector sockets = getSockets(childPid); + rdcarray sockets = getSockets(childPid); // read through the proc file to check for an open listen socket while(ret == 0 && !feof(f)) @@ -107,8 +108,7 @@ int GetIdentPort(pid_t childPid) // find open listen socket on 0.0.0.0:port if(num == 4 && hexip == 0 && hexport >= RenderDoc_FirstTargetControlPort && - hexport <= RenderDoc_LastTargetControlPort && - std::find(sockets.begin(), sockets.end(), inode) != sockets.end()) + hexport <= RenderDoc_LastTargetControlPort && sockets.contains(inode)) { ret = hexport; } diff --git a/renderdoc/os/posix/linux/linux_stringio.cpp b/renderdoc/os/posix/linux/linux_stringio.cpp index 412e91730..4793f4f66 100644 --- a/renderdoc/os/posix/linux/linux_stringio.cpp +++ b/renderdoc/os/posix/linux/linux_stringio.cpp @@ -547,39 +547,39 @@ bool GetKeyState(int key) namespace FileIO { -std::string GetTempRootPath() +rdcstr GetTempRootPath() { return "/tmp"; } -std::string GetAppFolderFilename(const std::string &filename) +rdcstr GetAppFolderFilename(const rdcstr &filename) { passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; - std::string ret = std::string(homedir) + "/.renderdoc/"; + rdcstr ret = rdcstr(homedir) + "/.renderdoc/"; mkdir(ret.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); return ret + filename; } -void GetExecutableFilename(std::string &selfName) +void GetExecutableFilename(rdcstr &selfName) { char path[512] = {0}; readlink("/proc/self/exe", path, 511); - selfName = std::string(path); + selfName = rdcstr(path); } int LibraryLocator = 42; -void GetLibraryFilename(std::string &selfName) +void GetLibraryFilename(rdcstr &selfName) { // this is a hack, but the only reliable way to find the absolute path to the library. // dladdr would be fine but it returns the wrong result for symbols in the library - std::string librenderdoc_path; + rdcstr librenderdoc_path; FILE *f = fopen("/proc/self/maps", "r"); @@ -654,7 +654,7 @@ void GetLibraryFilename(std::string &selfName) char *end = strchr(c, '\n'); if(end) - librenderdoc_path = std::string(c, end - c); + librenderdoc_path = rdcstr(c, end - c); } delete[] map_string; @@ -697,13 +697,13 @@ void Shutdown() iconvUTF82Wide = (iconv_t)-1; } -std::string Wide2UTF8(const std::wstring &s) +rdcstr Wide2UTF8(const rdcwstr &s) { // include room for null terminator, assuming unicode input (not ucs) // utf-8 characters can be max 4 bytes. size_t len = (s.length() + 1) * 4; - std::vector charBuffer(len); + rdcarray charBuffer(len); size_t ret; @@ -738,16 +738,16 @@ std::string Wide2UTF8(const std::wstring &s) // convert to string from null-terminated string - utf-8 never contains // 0 bytes before the null terminator, and this way we don't care if // charBuffer is larger than the string - return std::string(&charBuffer[0]); + return rdcstr(&charBuffer[0]); } -std::wstring UTF82Wide(const std::string &s) +rdcwstr UTF82Wide(const rdcstr &s) { // include room for null terminator, for ascii input we need at least as many output chars as // input. size_t len = s.length() + 1; - std::vector wcharBuffer(len); + rdcarray wcharBuffer(len); size_t ret; @@ -780,7 +780,7 @@ std::wstring UTF82Wide(const std::string &s) } // convert to string from null-terminated string - return std::wstring(&wcharBuffer[0]); + return rdcwstr(&wcharBuffer[0]); } }; diff --git a/renderdoc/os/posix/posix_libentry.cpp b/renderdoc/os/posix/posix_libentry.cpp index 7ef7be0d0..9fb6f0f90 100644 --- a/renderdoc/os/posix/posix_libentry.cpp +++ b/renderdoc/os/posix/posix_libentry.cpp @@ -63,7 +63,7 @@ void library_loaded() RenderDoc::Inst().SetCaptureFileTemplate(capturefile); } - std::string curfile; + rdcstr curfile; FileIO::GetExecutableFilename(curfile); RDCLOG("Loading into %s", curfile.c_str()); diff --git a/renderdoc/os/posix/posix_network.cpp b/renderdoc/os/posix/posix_network.cpp index 00844ad92..3d6471ae5 100644 --- a/renderdoc/os/posix/posix_network.cpp +++ b/renderdoc/os/posix/posix_network.cpp @@ -41,7 +41,7 @@ #include "posix_network.h" // because strerror_r is a complete mess... -static std::string errno_string(int err) +static rdcstr errno_string(int err) { switch(err) { diff --git a/renderdoc/os/posix/posix_process.cpp b/renderdoc/os/posix/posix_process.cpp index cedd496d9..0f8cb2ecc 100644 --- a/renderdoc/os/posix/posix_process.cpp +++ b/renderdoc/os/posix/posix_process.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "api/app/renderdoc_app.h" #include "common/threading.h" #include "os/os_specific.h" @@ -224,19 +225,19 @@ static void SetupZombieCollectionHandler() namespace FileIO { void ReleaseFDAfterFork(); -std::string FindFileInPath(const std::string &fileName); +rdcstr FindFileInPath(const rdcstr &fileName); }; -static const std::string GetAbsoluteAppPathFromName(const std::string &appName) +static const rdcstr GetAbsoluteAppPathFromName(const rdcstr &appName) { - std::string appPath; + rdcstr appPath; // If the application name contains a slash character convert it to an absolute path and return it - if(appName.find("/") != std::string::npos) + if(appName.contains("/")) { char realpathBuffer[PATH_MAX]; - std::string appDir = get_dirname(appName); - std::string appBasename = get_basename(appName); + rdcstr appDir = get_dirname(appName); + rdcstr appBasename = get_basename(appName); realpath(appDir.c_str(), realpathBuffer); appPath = realpathBuffer; appPath += "/" + appBasename; @@ -247,15 +248,15 @@ static const std::string GetAbsoluteAppPathFromName(const std::string &appName) return FileIO::FindFileInPath(appName); } -static std::vector &GetEnvModifications() +static rdcarray &GetEnvModifications() { - static std::vector envCallbacks; + static rdcarray envCallbacks; return envCallbacks; } -static std::map EnvStringToEnvMap(const char **envstring) +static std::map EnvStringToEnvMap(const char **envstring) { - std::map ret; + std::map ret; const char **e = envstring; @@ -269,11 +270,8 @@ static std::map EnvStringToEnvMap(const char **envstri continue; } - std::string name; - std::string value; - - name.assign(*e, equals); - value = equals + 1; + rdcstr name = rdcstr(*e, equals - *e); + rdcstr value = equals + 1; ret[name] = value; @@ -330,7 +328,7 @@ static rdcstr shellExpand(const rdcstr &in) return path; } -void Process::RegisterEnvironmentModification(EnvironmentModification modif) +void Process::RegisterEnvironmentModification(const EnvironmentModification &modif) { GetEnvModifications().push_back(modif); } @@ -346,15 +344,14 @@ void Process::ApplyEnvironmentModification() { // turn environment string to a UTF-8 map char **currentEnvironment = GetCurrentEnvironment(); - std::map currentEnv = - EnvStringToEnvMap((const char **)currentEnvironment); - std::vector &modifications = GetEnvModifications(); + std::map currentEnv = EnvStringToEnvMap((const char **)currentEnvironment); + rdcarray &modifications = GetEnvModifications(); for(size_t i = 0; i < modifications.size(); i++) { EnvironmentModification &m = modifications[i]; - std::string value = currentEnv[m.name.c_str()]; + rdcstr value = currentEnv[m.name.c_str()]; switch(m.mod) { @@ -375,7 +372,7 @@ void Process::ApplyEnvironmentModification() { if(!value.empty()) { - std::string prep = m.value; + rdcstr prep = m.value; if(m.sep == EnvSep::Platform || m.sep == EnvSep::Colon) prep += ":"; else if(m.sep == EnvSep::SemiColon) @@ -426,7 +423,7 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd #if ENABLED(RDOC_APPLE) if(appName.size() > 5 && appName.rfind(".app") == appName.size() - 4) { - std::string realAppName = appName + "/Contents/MacOS/" + get_basename(appName); + rdcstr realAppName = appName + "/Contents/MacOS/" + get_basename(appName); realAppName.erase(realAppName.size() - 4); if(FileIO::exists(realAppName.c_str())) @@ -466,7 +463,7 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd c = cmdLine; - std::string a; + rdcstr a; argc = 0; // current argument we're fetching @@ -559,7 +556,7 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd } } - const std::string appPath(GetAbsoluteAppPathFromName(appName)); + const rdcstr appPath(GetAbsoluteAppPathFromName(appName)); pid_t childPid = 0; @@ -624,9 +621,9 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd return childPid; } -ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray &env, - const char *logfile, const CaptureOptions &opts, - bool waitForExit) +rdcpair Process::InjectIntoProcess( + uint32_t pid, const rdcarray &env, const char *logfile, + const CaptureOptions &opts, bool waitForExit) { RDCUNIMPLEMENTED("Injecting into already running processes on linux"); return {ReplayStatus::InjectionFailed, 0}; @@ -667,14 +664,14 @@ uint32_t Process::LaunchProcess(const char *app, const char *workingDir, const c { stdoutRead = read(stdoutPipe[0], chBuf, sizeof(chBuf)); if(stdoutRead > 0) - result->strStdout += std::string(chBuf, stdoutRead); + result->strStdout += rdcstr(chBuf, stdoutRead); } while(stdoutRead > 0); do { stderrRead = read(stderrPipe[0], chBuf, sizeof(chBuf)); if(stderrRead > 0) - result->strStderror += std::string(chBuf, stderrRead); + result->strStderror += rdcstr(chBuf, stderrRead); } while(stderrRead > 0); } @@ -691,16 +688,15 @@ uint32_t Process::LaunchScript(const char *script, const char *workingDir, const bool internal, ProcessResult *result) { // Change parameters to invoke command interpreter - std::string args = "-lc \"" + std::string(script) + " " + std::string(argList) + "\""; + rdcstr args = "-lc \"" + rdcstr(script) + " " + rdcstr(argList) + "\""; return LaunchProcess("bash", workingDir, args.c_str(), internal, result); } -ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *workingDir, - const char *cmdLine, - const rdcarray &envList, - const char *capturefile, - const CaptureOptions &opts, bool waitForExit) +rdcpair Process::LaunchAndInjectIntoProcess( + const char *app, const char *workingDir, const char *cmdLine, + const rdcarray &envList, const char *capturefile, + const CaptureOptions &opts, bool waitForExit) { if(app == NULL || app[0] == 0) { @@ -710,8 +706,8 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w // turn environment string to a UTF-8 map char **currentEnvironment = GetCurrentEnvironment(); - std::map env = EnvStringToEnvMap((const char **)currentEnvironment); - std::vector modifications = GetEnvModifications(); + std::map env = EnvStringToEnvMap((const char **)currentEnvironment); + rdcarray modifications = GetEnvModifications(); for(const EnvironmentModification &e : envList) modifications.push_back(e); @@ -719,7 +715,7 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w if(capturefile == NULL) capturefile = ""; - std::string binpath, libpath, ownlibpath; + rdcstr binpath, libpath, ownlibpath; { FileIO::GetExecutableFilename(binpath); binpath = get_dirname(binpath); @@ -738,14 +734,14 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w FileIO::GetLibraryFilename(ownlibpath); ownlibpath = get_dirname(ownlibpath); - std::string libfile = "librenderdoc" LIB_SUFFIX; + rdcstr libfile = "librenderdoc" LIB_SUFFIX; // on macOS, the path must be absolute #if ENABLED(RDOC_APPLE) libfile = libpath + "/" + libfile; #endif - std::string optstr = opts.EncodeAsString(); + rdcstr optstr = opts.EncodeAsString(); modifications.push_back( EnvironmentModification(EnvMod::Append, EnvSep::Platform, LIB_PATH_ENV_VAR, binpath.c_str())); @@ -766,7 +762,7 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w { EnvironmentModification &m = modifications[i]; - std::string &value = env[m.name.c_str()]; + rdcstr &value = env[m.name.c_str()]; switch(m.mod) { @@ -807,7 +803,7 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w int i = 0; for(auto it = env.begin(); it != env.end(); it++) { - std::string envline = it->first + "=" + it->second; + rdcstr envline = it->first + "=" + it->second; envp[i] = new char[envline.size() + 1]; memcpy(envp[i], envline.c_str(), envline.size() + 1); i++; diff --git a/renderdoc/os/posix/posix_specific.h b/renderdoc/os/posix/posix_specific.h index 9ef98743f..50cb7ca5f 100644 --- a/renderdoc/os/posix/posix_specific.h +++ b/renderdoc/os/posix/posix_specific.h @@ -71,7 +71,7 @@ struct EmbeddedResourceType EmbeddedResourceType(const unsigned char *b, int l) : base(b), len(l) {} const unsigned char *base; int len; - std::string Get() const { return std::string(base, base + len); } + rdcstr Get() const { return rdcstr((char *)base, (size_t)len); } }; #define EmbeddedResource(filename) \ diff --git a/renderdoc/os/posix/posix_stringio.cpp b/renderdoc/os/posix/posix_stringio.cpp index 7e7caf87b..28b732949 100644 --- a/renderdoc/os/posix/posix_stringio.cpp +++ b/renderdoc/os/posix/posix_stringio.cpp @@ -47,9 +47,9 @@ static int soLocator = 0; namespace FileIO { // in posix/.../..._stringio.cpp -std::string GetTempRootPath(); +rdcstr GetTempRootPath(); -std::string GetHomeFolderFilename() +rdcstr GetHomeFolderFilename() { passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; @@ -57,14 +57,14 @@ std::string GetHomeFolderFilename() return homedir; } -std::string GetTempFolderFilename() +rdcstr GetTempFolderFilename() { return GetTempRootPath() + "/"; } -void CreateParentDirectory(const std::string &filename) +void CreateParentDirectory(const rdcstr &filename) { - std::string fn = get_dirname(filename); + rdcstr fn = get_dirname(filename); // want trailing slash so that we create all directories fn.push_back('/'); @@ -72,9 +72,9 @@ void CreateParentDirectory(const std::string &filename) if(fn[0] != '/') return; - size_t offs = fn.find('/', 1); + int offs = fn.find('/', 1); - while(offs != std::string::npos) + while(offs >= 0) { // create directory path from 0 to offs by NULLing the // / at offs, mkdir, then set it back @@ -82,11 +82,11 @@ void CreateParentDirectory(const std::string &filename) mkdir(fn.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); fn[offs] = '/'; - offs = fn.find_first_of('/', offs + 1); + offs = fn.find('/', offs + 1); } } -bool IsRelativePath(const std::string &path) +bool IsRelativePath(const rdcstr &path) { if(path.empty()) return false; @@ -94,17 +94,17 @@ bool IsRelativePath(const std::string &path) return path.front() != '/'; } -std::string GetFullPathname(const std::string &filename) +rdcstr GetFullPathname(const rdcstr &filename) { char path[PATH_MAX + 1] = {0}; realpath(filename.c_str(), path); - return std::string(path); + return rdcstr(path); } -std::string FindFileInPath(const std::string &fileName) +rdcstr FindFileInPath(const rdcstr &fileName) { - std::string filePath; + rdcstr filePath; // Search the PATH directory list for the application (like shell which) to get the absolute path // Return "" if no exectuable found in the PATH list @@ -120,7 +120,7 @@ std::string FindFileInPath(const std::string &fileName) const char *path = strtok(localPath, pathSeparator); while(path) { - std::string testPath(path); + rdcstr testPath(path); testPath += "/" + fileName; if(!access(testPath.c_str(), X_OK)) { @@ -134,14 +134,14 @@ std::string FindFileInPath(const std::string &fileName) return filePath; } -std::string GetReplayAppFilename() +rdcstr GetReplayAppFilename() { // look up the shared object's path via dladdr Dl_info info; dladdr((void *)&soLocator, &info); - std::string path = info.dli_fname ? info.dli_fname : ""; + rdcstr path = info.dli_fname ? info.dli_fname : ""; path = get_dirname(path); - std::string replay = path + "/qrenderdoc"; + rdcstr replay = path + "/qrenderdoc"; FILE *f = FileIO::fopen(replay.c_str(), "r"); if(f) @@ -188,10 +188,10 @@ std::string GetReplayAppFilename() return "qrenderdoc"; } -void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, - std::string &logging_filename, std::string &target) +void GetDefaultFiles(const char *logBaseName, rdcstr &capture_filename, rdcstr &logging_filename, + rdcstr &target) { - std::string path; + rdcstr path; GetExecutableFilename(path); const char *mod = strrchr(path.c_str(), '/'); @@ -202,7 +202,7 @@ void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, else mod = "unknown"; - target = std::string(mod); + target = rdcstr(mod); time_t t = time(NULL); tm now = *localtime(&t); @@ -226,7 +226,7 @@ void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, temp_folder, mod, 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min); - capture_filename = std::string(temp_filename); + capture_filename = rdcstr(temp_filename); snprintf(temp_filename, sizeof(temp_filename) - 1, "%s/RenderDoc/%s_%04d.%02d.%02d_%02d.%02d.%02d.log", temp_folder, logBaseName, @@ -235,12 +235,12 @@ void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, // set by UI when launching programs so all logging goes to the same file char *logfile_override = getenv("RENDERDOC_DEBUG_LOG_FILE"); if(logfile_override) - logging_filename = std::string(logfile_override); + logging_filename = rdcstr(logfile_override); else - logging_filename = std::string(temp_filename); + logging_filename = rdcstr(temp_filename); } -uint64_t GetModifiedTimestamp(const std::string &filename) +uint64_t GetModifiedTimestamp(const rdcstr &filename) { struct ::stat st; int res = stat(filename.c_str(), &st); @@ -318,9 +318,9 @@ void Delete(const char *path) unlink(path); } -std::vector GetFilesInDirectory(const char *path) +void GetFilesInDirectory(const char *path, rdcarray &ret) { - std::vector ret; + ret.clear(); DIR *d = opendir(path); @@ -334,7 +334,7 @@ std::vector GetFilesInDirectory(const char *path) flags = PathProperty::ErrorAccessDenied; ret.push_back(PathEntry(path, flags)); - return ret; + return; } dirent *ent = NULL; @@ -350,7 +350,7 @@ std::vector GetFilesInDirectory(const char *path) if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; - std::string fullpath = path; + rdcstr fullpath = path; fullpath += '/'; fullpath += ent->d_name; @@ -383,8 +383,6 @@ std::vector GetFilesInDirectory(const char *path) // don't care if we hit an error or enumerated all files, just finish closedir(d); - - return ret; } FILE *fopen(const char *filename, const char *mode) @@ -392,7 +390,7 @@ FILE *fopen(const char *filename, const char *mode) return ::fopen(filename, mode); } -std::string ErrorString() +rdcstr ErrorString() { int err = errno; @@ -462,11 +460,11 @@ void ReleaseFDAfterFork() close(log); } -std::string logfile_readall(const char *filename) +rdcstr logfile_readall(const char *filename) { FILE *f = FileIO::fopen(filename, "r"); - std::string ret; + rdcstr ret; if(f == NULL) return ret; diff --git a/renderdoc/os/posix/posix_threading.cpp b/renderdoc/os/posix/posix_threading.cpp index 6dfed8090..f8a79e799 100644 --- a/renderdoc/os/posix/posix_threading.cpp +++ b/renderdoc/os/posix/posix_threading.cpp @@ -181,11 +181,11 @@ int64_t nextTLSSlot = 0; struct TLSData { - std::vector data; + rdcarray data; }; static CriticalSection *m_TLSListLock = NULL; -static std::vector *m_TLSList = NULL; +static rdcarray *m_TLSList = NULL; void Init() { @@ -194,7 +194,7 @@ void Init() RDCFATAL("Can't allocate OS TLS slot"); m_TLSListLock = new CriticalSection(); - m_TLSList = new std::vector(); + m_TLSList = new rdcarray(); CacheDebuggerPresent(); } diff --git a/renderdoc/os/win32/sys_win32_hooks.cpp b/renderdoc/os/win32/sys_win32_hooks.cpp index e9c7a6c55..abbfa824b 100644 --- a/renderdoc/os/win32/sys_win32_hooks.cpp +++ b/renderdoc/os/win32/sys_win32_hooks.cpp @@ -268,20 +268,18 @@ private: // ourselves. if(lpApplicationName) { - std::string app = strlower(StringFormat::Wide2UTF8(lpApplicationName)); + rdcstr app = strlower(StringFormat::Wide2UTF8(lpApplicationName)); - if(app.find("renderdoccmd.exe") != std::string::npos || - app.find("qrenderdoc.exe") != std::string::npos) + if(app.contains("renderdoccmd.exe") || app.contains("qrenderdoc.exe")) { inject = false; } } if(lpCommandLine) { - std::string cmd = strlower(StringFormat::Wide2UTF8(lpCommandLine)); + rdcstr cmd = strlower(StringFormat::Wide2UTF8(lpCommandLine)); - if(cmd.find("renderdoccmd.exe") != std::string::npos || - cmd.find("qrenderdoc.exe") != std::string::npos) + if(cmd.contains("renderdoccmd.exe") || cmd.contains("qrenderdoc.exe")) { inject = false; } diff --git a/renderdoc/os/win32/win32_callstack.cpp b/renderdoc/os/win32/win32_callstack.cpp index b7da84681..ca0299da9 100644 --- a/renderdoc/os/win32/win32_callstack.cpp +++ b/renderdoc/os/win32/win32_callstack.cpp @@ -44,8 +44,8 @@ struct AddrInfo { - std::string funcName; - std::string fileName; + rdcstr funcName; + rdcstr fileName; unsigned long lineNum = 0; }; @@ -73,50 +73,45 @@ namespace DIA2 { struct Module { - Module(IDiaDataSource *src, IDiaSession *sess) : pSource(src), pSession(sess) {} + Module(IDiaDataSource *src = NULL, IDiaSession *sess = NULL) : pSource(src), pSession(sess) {} IDiaDataSource *pSource; IDiaSession *pSession; }; -std::vector modules; +rdcarray modules; -std::wstring GetSymSearchPath() +rdcwstr GetSymSearchPath() { PWSTR appDataPath; SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND, NULL, &appDataPath); - std::wstring appdata = appDataPath; + rdcwstr appdata = appDataPath; CoTaskMemFree(appDataPath); std::wstring sympath = L".;"; - sympath += appdata; + sympath += appdata.c_str(); sympath += L"\\renderdoc\\symbols;SRV*"; - sympath += appdata; + sympath += appdata.c_str(); sympath += L"\\renderdoc\\symbols\\symsrv*http://msdl.microsoft.com/download/symbols"; - return sympath; + return sympath.c_str(); } -std::string LookupModule(const std::string &modName, GUID guid, DWORD age) +rdcstr LookupModule(const rdcstr &modName, GUID guid, DWORD age) { - std::string ret = modName; + rdcstr ret = modName; - std::string pdbName = get_basename(ret); + rdcstr pdbName = get_basename(ret); - if(pdbName.find(".pdb") == std::string::npos && pdbName.find(".PDB") == std::string::npos) + if(pdbName.find(".pdb") == -1 && pdbName.find(".PDB") == -1) { - size_t offs = pdbName.find_last_of('.'); - - if(offs != std::string::npos) - { - pdbName.erase(offs + 1); - pdbName += "pdb"; - } + if(pdbName.contains('.')) + pdbName = strip_extension(pdbName) + ".pdb"; } if(dynSymFindFileInPathW != NULL) { - std::wstring sympath = GetSymSearchPath(); + rdcwstr sympath = GetSymSearchPath(); wchar_t path[MAX_PATH + 1] = {0}; BOOL found = dynSymFindFileInPathW(GetCurrentProcess(), sympath.c_str(), @@ -132,7 +127,7 @@ std::string LookupModule(const std::string &modName, GUID guid, DWORD age) return ret; } -std::wstring msdiapath = L"msdia140.dll"; +rdcwstr msdiapath = L"msdia140.dll"; HRESULT MakeDiaDataSource(IDiaDataSource **source) { @@ -187,7 +182,7 @@ HRESULT MakeDiaDataSource(IDiaDataSource **source) return S_OK; } -uint32_t GetModule(const std::wstring &pdbName, GUID guid, DWORD age) +uint32_t GetModule(const rdcwstr &pdbName, GUID guid, DWORD age) { Module m(NULL, NULL); @@ -307,12 +302,12 @@ AddrInfo GetAddr(uint32_t module, uint64_t addr) { ret.funcName = StringFormat::Wide2UTF8(file); - size_t voidoffs = ret.funcName.find("(void)"); + int voidoffs = ret.funcName.find("(void)"); // remove stupid (void) for empty parameters - if(voidoffs != std::string::npos) + if(voidoffs >= 0) { - ret.funcName.erase(voidoffs + 1); + ret.funcName.erase(voidoffs + 1, ~0U); ret.funcName.push_back(')'); } } @@ -411,7 +406,7 @@ private: void Collect(); - std::vector m_AddrStack; + rdcarray m_AddrStack; }; class Win32CallstackResolver : public Callstack::StackResolver @@ -423,20 +418,20 @@ public: Callstack::AddressDetails GetAddr(uint64_t addr); private: - std::string pdbBrowse(std::string startingPoint); + rdcstr pdbBrowse(rdcstr startingPoint); struct Module { - std::string name; + rdcstr name; DWORD64 base; DWORD size; uint32_t moduleId; }; - std::vector pdbRememberedPaths; + rdcarray pdbRememberedPaths; rdcarray pdbIgnores; - std::vector modules; + rdcarray modules; char pipeMessageBuf[2048]; }; @@ -656,7 +651,7 @@ BOOL CALLBACK EnumModule(PCWSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext void Win32Callstack::Collect() { - std::vector stack32; + rdcarray stack32; stack32.resize(64); @@ -667,7 +662,7 @@ void Win32Callstack::Collect() while(!stack32.empty() && (uint64_t)stack32[0] >= (uint64_t)renderdocBase && (uint64_t)stack32[0] <= (uint64_t)renderdocBase + renderdocSize) { - stack32.erase(stack32.begin()); + stack32.erase(0, 1); } m_AddrStack.resize(stack32.size()); @@ -699,7 +694,7 @@ Win32Callstack::~Win32Callstack() { } -std::string Win32CallstackResolver::pdbBrowse(std::string startingPoint) +rdcstr Win32CallstackResolver::pdbBrowse(rdcstr startingPoint) { OPENFILENAMEW ofn; RDCEraseMem(&ofn, sizeof(ofn)); @@ -726,7 +721,7 @@ std::string Win32CallstackResolver::pdbBrowse(std::string startingPoint) Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, RENDERDOC_ProgressCallback progress) { - std::wstring configPath = StringFormat::UTF82Wide(FileIO::GetAppFolderFilename("config.ini")); + rdcwstr configPath = StringFormat::UTF82Wide(FileIO::GetAppFolderFilename("config.ini")); { FILE *f = NULL; _wfopen_s(&f, configPath.c_str(), L"a"); @@ -872,7 +867,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, m.size = chunk->size; m.moduleId = 0; - if(find(pdbIgnores.begin(), pdbIgnores.end(), m.name) != pdbIgnores.end()) + if(pdbIgnores.contains(m.name)) { RDCWARN("Not attempting to get symbols for %ls", m.name.c_str()); @@ -882,7 +877,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, // get default pdb (this also looks up symbol server etc) // Always done in unicode - std::string defaultPdb = DIA2::LookupModule(m.name, chunk->guid, chunk->age); + rdcstr defaultPdb = DIA2::LookupModule(m.name, chunk->guid, chunk->age); // strip newline if(defaultPdb != "" && defaultPdb[defaultPdb.length() - 1] == '\n') @@ -895,8 +890,8 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, { defaultPdb = strlower(get_basename(m.name)); - size_t it = defaultPdb.find(".dll"); - if(it != std::string::npos) + int it = defaultPdb.find(".dll"); + if(it >= 0) { defaultPdb[it + 1] = 'p'; defaultPdb[it + 2] = 'd'; @@ -904,7 +899,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, } it = defaultPdb.find(".exe"); - if(it != std::string::npos) + if(it >= 0) { defaultPdb[it + 1] = 'p'; defaultPdb[it + 2] = 'd'; @@ -913,7 +908,7 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, failed = true; } - std::string pdbName = defaultPdb; + rdcstr pdbName = defaultPdb; int fallbackIdx = -1; @@ -933,9 +928,8 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, pdbName = get_dirname(defaultPdb) + "\\" + get_basename(defaultPdb); // prompt for new pdbName, unless it's renderdoc or dbghelp - if(pdbName.find("renderdoc.") != std::wstring::npos || - pdbName.find("dbghelp.") != std::wstring::npos || - pdbName.find("symsrv.") != std::wstring::npos) + if(pdbName.contains("renderdoc.") || pdbName.contains("dbghelp.") || + pdbName.contains("symsrv.")) pdbName = ""; else pdbName = pdbBrowse(pdbName); @@ -958,12 +952,9 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, { if(fallbackIdx >= (int)pdbRememberedPaths.size()) { - std::string dir = get_dirname(pdbName); - if(find(pdbRememberedPaths.begin(), pdbRememberedPaths.end(), dir) == - pdbRememberedPaths.end()) - { + rdcstr dir = get_dirname(pdbName); + if(!pdbRememberedPaths.contains(dir)) pdbRememberedPaths.push_back(dir); - } } } } @@ -977,13 +968,11 @@ Win32CallstackResolver::Win32CallstackResolver(byte *moduleDB, size_t DBSize, // silently ignore renderdoc.dll, dbghelp.dll, and symsrv.dll without asking to permanently // ignore - if(m.name.find("renderdoc.") != std::wstring::npos || - m.name.find("dbghelp.") != std::wstring::npos || - m.name.find("symsrv.") != std::wstring::npos) + if(m.name.contains("renderdoc.") || m.name.contains("dbghelp.") || m.name.contains("symsrv.")) continue; - std::string text = StringFormat::Fmt("Do you want to permanently ignore this file?\nPath: %s", - m.name.c_str()); + rdcstr text = StringFormat::Fmt("Do you want to permanently ignore this file?\nPath: %s", + m.name.c_str()); int ret = MessageBoxA(NULL, text.c_str(), "Ignore this pdb?", MB_YESNO); @@ -1044,11 +1033,11 @@ Callstack::AddressDetails Win32CallstackResolver::GetAddr(DWORD64 addr) info.funcName = StringFormat::Fmt("%s+0x%08llx", info.funcName.c_str(), addr - base); - size_t offs = info.funcName.find(".pdb"); + int offs = info.funcName.find(".pdb"); - if(offs != std::string::npos) + if(offs >= 0) { - info.funcName.erase(offs + 1); + info.funcName.erase(offs + 1, ~0U); if(i == 0) info.funcName += "exe"; diff --git a/renderdoc/os/win32/win32_hook.cpp b/renderdoc/os/win32/win32_hook.cpp index 4705c7e0a..722d70693 100644 --- a/renderdoc/os/win32/win32_hook.cpp +++ b/renderdoc/os/win32/win32_hook.cpp @@ -32,6 +32,7 @@ #include #include #include +#include "common/common.h" #include "common/threading.h" #include "hooks/hooks.h" #include "os/os_specific.h" @@ -90,11 +91,11 @@ struct DllHookset bool hooksfetched = false; // if we have multiple copies of the dll loaded (unlikely), the other module handles will be // stored here - std::vector altmodules; - std::vector FunctionHooks; + rdcarray altmodules; + rdcarray FunctionHooks; DWORD OrdinalBase = 0; - std::vector OrdinalNames; - std::vector Callbacks; + rdcarray OrdinalNames; + rdcarray Callbacks; Threading::CriticalSection ordinallock; void FetchOrdinalNames() @@ -157,12 +158,12 @@ struct CachedHookData RDCEraseEl(lowername); } - std::map DllHooks; + std::map DllHooks; HMODULE ownmodule; Threading::CriticalSection lock; char lowername[512]; - std::set ignores; + std::set ignores; bool missedOrdinals; @@ -242,7 +243,7 @@ struct CachedHookData DWORD err = GetLastError(); char *slash = strrchr(filename, L'\\'); - std::string basename = slash ? strlower(std::string(slash + 1)) : ""; + rdcstr basename = slash ? strlower(rdcstr(slash + 1)) : ""; if(err == 0 && basename == it->first) { @@ -596,7 +597,7 @@ static void HookAllModules() } } - std::vector callbacks; + rdcarray callbacks; // don't call callbacks next time callbacks.swap(it->second.Callbacks); @@ -627,10 +628,13 @@ static bool IsAPISet(const wchar_t *filename) static bool IsAPISet(const char *filename) { - std::wstring wfn; + size_t len = strlen(filename); + rdcwstr wfn(len); + // assume ASCII not UTF, just upcast plainly to wchar_t - while(*filename) - wfn.push_back(wchar_t(*filename++)); + for(size_t i = 0; i < len; i++) + wfn[i] = wchar_t(filename[i]); + return IsAPISet(wfn.c_str()); } @@ -825,17 +829,17 @@ void LibraryHooks::RegisterFunctionHook(const char *libraryName, const FunctionH return; } } - s_HookData->DllHooks[strlower(std::string(libraryName))].FunctionHooks.push_back(hook); + s_HookData->DllHooks[strlower(rdcstr(libraryName))].FunctionHooks.push_back(hook); } void LibraryHooks::RegisterLibraryHook(const char *libraryName, FunctionLoadCallback loadedCallback) { - s_HookData->DllHooks[strlower(std::string(libraryName))].Callbacks.push_back(loadedCallback); + s_HookData->DllHooks[strlower(rdcstr(libraryName))].Callbacks.push_back(loadedCallback); } void LibraryHooks::IgnoreLibrary(const char *libraryName) { - std::string lowername = libraryName; + rdcstr lowername = libraryName; for(size_t i = 0; i < lowername.size(); i++) lowername[i] = (char)tolower(lowername[i]); diff --git a/renderdoc/os/win32/win32_libentry.cpp b/renderdoc/os/win32/win32_libentry.cpp index 5cc276eaa..258314f24 100644 --- a/renderdoc/os/win32/win32_libentry.cpp +++ b/renderdoc/os/win32/win32_libentry.cpp @@ -36,7 +36,7 @@ static BOOL add_hooks() wchar_t curFile[512]; GetModuleFileNameW(NULL, curFile, 512); - std::string f = get_basename(strlower(StringFormat::Wide2UTF8(curFile))); + rdcstr f = get_basename(strlower(StringFormat::Wide2UTF8(curFile))); // bail immediately if we're in a system process. We don't want to hook, log, anything - // this instance is being used for a shell extension. diff --git a/renderdoc/os/win32/win32_network.cpp b/renderdoc/os/win32/win32_network.cpp index c9bcc2132..ec7826a3f 100644 --- a/renderdoc/os/win32/win32_network.cpp +++ b/renderdoc/os/win32/win32_network.cpp @@ -25,6 +25,7 @@ #include #include +#include "common/common.h" #include "os/os_specific.h" #ifndef WSA_FLAG_NO_HANDLE_INHERIT @@ -35,7 +36,7 @@ #define WSA_FLAG_OVERLAPPED 0x01 #endif -static std::string wsaerr_string(int err) +static rdcstr wsaerr_string(int err) { switch(err) { @@ -407,7 +408,7 @@ Socket *CreateClientSocket(const char *host, uint16_t port, int timeoutMS) hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - std::wstring whost = StringFormat::UTF82Wide(std::string(host)); + rdcwstr whost = StringFormat::UTF82Wide(rdcstr(host)); addrinfoW *addrResult = NULL; int res = GetAddrInfoW(whost.c_str(), portwstr, &hints, &addrResult); diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index a37d2f712..04ce0ace1 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -34,31 +34,18 @@ #include "os/os_specific.h" #include "strings/string_utils.h" -// add wstring strlower overload since we don't want to always be converting to/from wchars. -static std::wstring strlower(std::wstring in) +static rdcarray &GetEnvModifications() { - std::wstring ret; - ret.resize(in.size()); - for(size_t i = 0; i < ret.size(); i++) - ret[i] = towlower(in[i]); - return ret; -} - -static std::vector &GetEnvModifications() -{ - static std::vector envCallbacks; + static rdcarray envCallbacks; return envCallbacks; } struct InsensitiveComparison { - bool operator()(const std::wstring &a, const std::wstring &b) const - { - return strlower(a) < strlower(b); - } + bool operator()(const rdcstr &a, const rdcstr &b) const { return strlower(a) < strlower(b); } }; -typedef std::map EnvMap; +typedef std::map EnvMap; static EnvMap EnvStringToEnvMap(const wchar_t *envstring) { @@ -70,41 +57,34 @@ static EnvMap EnvStringToEnvMap(const wchar_t *envstring) { const wchar_t *equals = wcschr(e, L'='); - std::wstring name; - std::wstring value; + rdcstr name = StringFormat::Wide2UTF8(rdcwstr(e, equals - e)); + rdcstr value = StringFormat::Wide2UTF8(equals + 1); - name.assign(e, equals); - value = equals + 1; + ret[name] = value; - ret[name] = StringFormat::Wide2UTF8(value); - - e += name.size(); // jump to = - e++; // advance past it - e += value.size(); // jump to \0 - e++; // advance past it + // jump to \0 and past it + e += wcslen(e) + 1; } return ret; } -void Process::RegisterEnvironmentModification(EnvironmentModification modif) +void Process::RegisterEnvironmentModification(const EnvironmentModification &modif) { GetEnvModifications().push_back(modif); } static void ApplyEnvModifications(EnvMap &envValues, - const std::vector &modifications, + const rdcarray &modifications, bool setToSystem) { for(size_t i = 0; i < modifications.size(); i++) { const EnvironmentModification &m = modifications[i]; - std::wstring name = StringFormat::UTF82Wide(m.name.c_str()); + rdcstr value; - std::string value; - - auto it = envValues.find(name); + auto it = envValues.find(m.name); if(it != envValues.end()) value = it->second; @@ -127,7 +107,7 @@ static void ApplyEnvModifications(EnvMap &envValues, { if(!value.empty()) { - std::string prep = m.value; + rdcstr prep = m.value; if(m.sep == EnvSep::Platform || m.sep == EnvSep::SemiColon) prep += ";"; else if(m.sep == EnvSep::Colon) @@ -142,10 +122,11 @@ static void ApplyEnvModifications(EnvMap &envValues, } } - envValues[name] = value; + envValues[m.name] = value; if(setToSystem) - SetEnvironmentVariableW(name.c_str(), StringFormat::UTF82Wide(value).c_str()); + SetEnvironmentVariableW(StringFormat::UTF82Wide(m.name).c_str(), + StringFormat::UTF82Wide(value).c_str()); } } @@ -160,7 +141,7 @@ void Process::ApplyEnvironmentModification() LPWCH envStrings = GetEnvironmentStringsW(); EnvMap envValues = EnvStringToEnvMap(envStrings); FreeEnvironmentStringsW(envStrings); - std::vector &modifications = GetEnvModifications(); + rdcarray &modifications = GetEnvModifications(); ApplyEnvModifications(envValues, modifications, true); @@ -262,7 +243,7 @@ extern "C" __declspec(dllexport) void __cdecl INTERNAL_ApplyEnvMods(void *ignore Process::ApplyEnvironmentModification(); } -void InjectDLL(HANDLE hProcess, std::wstring libName) +void InjectDLL(HANDLE hProcess, rdcwstr libName) { wchar_t dllPath[MAX_PATH + 1] = {0}; wcscpy_s(dllPath, libName.c_str()); @@ -309,11 +290,11 @@ void InjectDLL(HANDLE hProcess, std::wstring libName) } } -uintptr_t FindRemoteDLL(DWORD pid, std::wstring libName) +uintptr_t FindRemoteDLL(DWORD pid, rdcstr libName) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; - libName = strlower(libName); + rdcwstr wlibName = StringFormat::UTF82Wide(strlower(libName)); // up to 10 retries for(int i = 0; i < 10; i++) @@ -375,7 +356,7 @@ uintptr_t FindRemoteDLL(DWORD pid, std::wstring libName) numModules++; - if(wcsstr(modnameLower, libName.c_str()) == modnameLower) + if(wcsstr(modnameLower, wlibName.c_str()) == modnameLower) { ret = (uintptr_t)me32.modBaseAddr; } @@ -399,7 +380,7 @@ uintptr_t FindRemoteDLL(DWORD pid, std::wstring libName) } else { - RDCERR("Couldn't find module '%ls' among %d modules", libName.c_str(), numModules); + RDCERR("Couldn't find module '%s' among %d modules", libName.c_str(), numModules); } if(h) @@ -462,25 +443,25 @@ static PROCESS_INFORMATION RunProcess(const char *app, const char *workingDir, c pSec.nLength = sizeof(pSec); tSec.nLength = sizeof(tSec); - std::wstring workdir = L""; + rdcwstr workdir = L""; if(workingDir != NULL && workingDir[0] != 0) - workdir = StringFormat::UTF82Wide(std::string(workingDir)); + workdir = StringFormat::UTF82Wide(workingDir); else - workdir = StringFormat::UTF82Wide(get_dirname(std::string(app))); + workdir = StringFormat::UTF82Wide(get_dirname(app)); wchar_t *paramsAlloc = NULL; - std::wstring wapp = StringFormat::UTF82Wide(std::string(app)); + rdcwstr wapp = StringFormat::UTF82Wide(app); // CreateProcessW can modify the params, need space. size_t len = wapp.length() + 10; - std::wstring wcmd = L""; + rdcwstr wcmd = L""; if(cmdLine != NULL && cmdLine[0] != 0) { - wcmd = StringFormat::UTF82Wide(std::string(cmdLine)); + wcmd = StringFormat::UTF82Wide(rdcstr(cmdLine)); len += wcmd.length(); } @@ -539,15 +520,13 @@ static PROCESS_INFORMATION RunProcess(const char *app, const char *workingDir, c EnvMap envValues = EnvStringToEnvMap(envStrings); FreeEnvironmentStringsW(envStrings); - std::vector envMods; - envMods.insert(envMods.begin(), env.begin(), env.end()); - ApplyEnvModifications(envValues, envMods, false); + ApplyEnvModifications(envValues, env, false); for(auto it = envValues.begin(); it != envValues.end(); ++it) { - envString += it->first; + envString += StringFormat::UTF82Wide(it->first).c_str(); envString += L"="; - envString += StringFormat::UTF82Wide(it->second); + envString += StringFormat::UTF82Wide(it->second).c_str(); envString.push_back(0); } } @@ -578,11 +557,11 @@ static PROCESS_INFORMATION RunProcess(const char *app, const char *workingDir, c return pi; } -ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray &env, - const char *capturefile, const CaptureOptions &opts, - bool waitForExit) +rdcpair Process::InjectIntoProcess( + uint32_t pid, const rdcarray &env, const char *capturefile, + const CaptureOptions &opts, bool waitForExit) { - std::wstring wcapturefile = capturefile == NULL ? L"" : StringFormat::UTF82Wide(capturefile); + rdcwstr wcapturefile = capturefile == NULL ? L"" : StringFormat::UTF82Wide(capturefile); HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | @@ -829,12 +808,12 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarray result = {ReplayStatus::Succeeded, 0}; if(loc == 0) { RDCERR("Can't locate " STRINGIZE(RDOC_DLL_FILE) ".dll in remote PID %d", pid); - result.status = ReplayStatus::InjectionFailed; + result.first = ReplayStatus::InjectionFailed; } else { @@ -966,7 +945,7 @@ ExecuteResult Process::InjectIntoProcess(uint32_t pid, const rdcarraystrStdout += s; if(!success && !dwOutputRead) @@ -1054,7 +1033,7 @@ uint32_t Process::LaunchProcess(const char *app, const char *workingDir, const c for(;;) { success = ReadFile(hChildStdError_Rd, chBuf, sizeof(chBuf), &dwErrorRead, NULL); - s = std::string(chBuf, dwErrorRead); + s = rdcstr(chBuf, dwErrorRead); result->strStderror += s; if(!success && !dwErrorRead) @@ -1078,16 +1057,15 @@ uint32_t Process::LaunchScript(const char *script, const char *workingDir, const bool internal, ProcessResult *result) { // Change parameters to invoke command interpreter - std::string args = "/C " + std::string(script) + " " + std::string(argList); + rdcstr args = "/C " + rdcstr(script) + " " + rdcstr(argList); return LaunchProcess("cmd.exe", workingDir, args.c_str(), internal, result); } -ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *workingDir, - const char *cmdLine, - const rdcarray &env, - const char *capturefile, - const CaptureOptions &opts, bool waitForExit) +rdcpair Process::LaunchAndInjectIntoProcess( + const char *app, const char *workingDir, const char *cmdLine, + const rdcarray &env, const char *capturefile, + const CaptureOptions &opts, bool waitForExit) { void *func = GetProcAddress(GetModuleHandleA(STRINGIZE(RDOC_DLL_FILE) ".dll"), "INTERNAL_SetCaptureFile"); @@ -1104,13 +1082,14 @@ ExecuteResult Process::LaunchAndInjectIntoProcess(const char *app, const char *w if(pi.dwProcessId == 0) return {ReplayStatus::InjectionFailed, 0}; - ExecuteResult ret = InjectIntoProcess(pi.dwProcessId, {}, capturefile, opts, false); + rdcpair ret = + InjectIntoProcess(pi.dwProcessId, {}, capturefile, opts, false); CloseHandle(pi.hProcess); ResumeThread(pi.hThread); ResumeThread(pi.hThread); - if(ret.ident == 0 || ret.status != ReplayStatus::Succeeded) + if(ret.second == 0 || ret.first != ReplayStatus::Succeeded) { CloseHandle(pi.hThread); return ret; @@ -1142,7 +1121,7 @@ struct GlobalHookData { HANDLE pipe = NULL; DWORD appinitEnabled = 0; - std::wstring appinitDLLs; + rdcwstr appinitDLLs; } dataNative, dataWow32; volatile int32_t finished = 0; @@ -1169,8 +1148,8 @@ static bool HandleRegError(HKEY keyNative, HKEY keyWow32, LSTATUS ret, const cha } // function to backup the previous settings for AppInit, then enable it and write our own paths. -bool BackupAndChangeRegistry(GlobalHookData &hookdata, const std::wstring &shimpathWow32, - const std::wstring &shimpathNative) +bool BackupAndChangeRegistry(GlobalHookData &hookdata, const rdcstr &shimpathWow32, + const rdcstr &shimpathNative) { HKEY keyNative = NULL; HKEY keyWow32 = NULL; @@ -1204,9 +1183,9 @@ bool BackupAndChangeRegistry(GlobalHookData &hookdata, const std::wstring &shimp ret = RegGetValueW(keyNative, NULL, L"AppInit_DLLs", RRF_RT_ANY, NULL, NULL, &sz); if(ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS) { - hookdata.dataNative.appinitDLLs.resize(sz / sizeof(wchar_t)); + hookdata.dataNative.appinitDLLs = rdcwstr(sz / sizeof(wchar_t)); ret = RegGetValueW(keyNative, NULL, L"AppInit_DLLs", RRF_RT_ANY, NULL, - (void *)&hookdata.dataNative.appinitDLLs[0], &sz); + hookdata.dataNative.appinitDLLs.data(), &sz); } REG_CHECK("Could not fetch AppInit_DLLs"); @@ -1214,12 +1193,12 @@ bool BackupAndChangeRegistry(GlobalHookData &hookdata, const std::wstring &shimp ret = RegSetValueExA(keyNative, "LoadAppInit_DLLs", 0, REG_DWORD, (const BYTE *)&one, sizeof(one)); REG_CHECK("Could not set LoadAppInit_DLLs"); - std::wstring shortpath; - shortpath = shimpathNative; - GetShortPathNameW(shimpathNative.c_str(), (wchar_t *)&shortpath[0], (DWORD)shortpath.size()); + rdcwstr shortpath(shimpathNative.size()); + GetShortPathNameW(StringFormat::UTF82Wide(shimpathNative).c_str(), shortpath.data(), + (DWORD)shortpath.length()); ret = RegSetValueExW(keyNative, L"AppInit_DLLs", 0, REG_SZ, (const BYTE *)shortpath.data(), - DWORD(shortpath.size() * sizeof(wchar_t))); + DWORD(shortpath.length() * sizeof(wchar_t))); REG_CHECK("Could not set AppInit_DLLs"); // if we're doing Wow32, repeat the process for those keys @@ -1234,20 +1213,21 @@ bool BackupAndChangeRegistry(GlobalHookData &hookdata, const std::wstring &shimp ret = RegGetValueW(keyWow32, NULL, L"AppInit_DLLs", RRF_RT_ANY, NULL, NULL, &sz); if(ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS) { - hookdata.dataWow32.appinitDLLs.resize(sz / sizeof(wchar_t)); + hookdata.dataWow32.appinitDLLs = rdcwstr(sz / sizeof(wchar_t)); ret = RegGetValueW(keyWow32, NULL, L"AppInit_DLLs", RRF_RT_ANY, NULL, - (void *)&hookdata.dataWow32.appinitDLLs[0], &sz); + hookdata.dataWow32.appinitDLLs.data(), &sz); } REG_CHECK("Could not fetch AppInit_DLLs"); ret = RegSetValueExA(keyWow32, "LoadAppInit_DLLs", 0, REG_DWORD, (const BYTE *)&one, sizeof(one)); REG_CHECK("Could not set LoadAppInit_DLLs"); - shortpath = shimpathWow32; - GetShortPathNameW(shimpathWow32.c_str(), &shortpath[0], (DWORD)shortpath.size()); + shortpath = rdcwstr(shimpathWow32.size()); + GetShortPathNameW(StringFormat::UTF82Wide(shimpathWow32).c_str(), shortpath.data(), + (DWORD)shortpath.length()); ret = RegSetValueExW(keyWow32, L"AppInit_DLLs", 0, REG_SZ, (const BYTE *)shortpath.data(), - DWORD(shortpath.size() * sizeof(wchar_t))); + DWORD(shortpath.length() * sizeof(wchar_t))); REG_CHECK("Could not set AppInit_DLLs"); } @@ -1340,8 +1320,8 @@ void RestoreRegistry(const GlobalHookData &hookdata) REG_CHECK("Could not set LoadAppInit_DLLs"); ret = RegSetValueExW(keyNative, L"AppInit_DLLs", 0, REG_SZ, - (const BYTE *)hookdata.dataNative.appinitDLLs.data(), - DWORD(hookdata.dataNative.appinitDLLs.size() * sizeof(wchar_t))); + (const BYTE *)hookdata.dataNative.appinitDLLs.c_str(), + DWORD(hookdata.dataNative.appinitDLLs.length() * sizeof(wchar_t))); REG_CHECK("Could not set AppInit_DLLs"); // if we opened it, restore the Wow32 values as well @@ -1353,8 +1333,8 @@ void RestoreRegistry(const GlobalHookData &hookdata) REG_CHECK("Could not set LoadAppInit_DLLs"); ret = RegSetValueExW(keyWow32, L"AppInit_DLLs", 0, REG_SZ, - (const BYTE *)hookdata.dataWow32.appinitDLLs.data(), - DWORD(hookdata.dataWow32.appinitDLLs.size() * sizeof(wchar_t))); + (const BYTE *)hookdata.dataWow32.appinitDLLs.c_str(), + DWORD(hookdata.dataWow32.appinitDLLs.length() * sizeof(wchar_t))); REG_CHECK("Could not set AppInit_DLLs"); } } @@ -1396,83 +1376,57 @@ bool Process::StartGlobalHook(const char *pathmatch, const char *capturefile, if(pathmatch == NULL) return false; - wchar_t renderdocPath[MAX_PATH] = {0}; - GetModuleFileNameW(GetModuleHandleA(STRINGIZE(RDOC_DLL_FILE) ".dll"), &renderdocPath[0], - MAX_PATH - 1); + rdcstr renderdocPath; + FileIO::GetLibraryFilename(renderdocPath); - wchar_t *slash = wcsrchr(renderdocPath, L'\\'); - - if(slash) - *slash = 0; - else - slash = renderdocPath + wcslen(renderdocPath); + renderdocPath = get_basename(renderdocPath); // the native renderdoccmd.exe is always next to the dll. Wow32 will be somewhere else - std::wstring cmdpathNative = renderdocPath; - cmdpathNative += L"\\renderdoccmd.exe"; - std::wstring cmdpathWow32; + rdcstr cmdpathNative = renderdocPath + "\\renderdoccmd.exe"; + rdcstr cmdpathWow32; - std::wstring shimpathNative = renderdocPath; - std::wstring shimpathWow32; + rdcstr shimpathNative = renderdocPath; + rdcstr shimpathWow32; #if ENABLED(RDOC_X64) // native shim is just renderdocshim64.dll - *slash = 0; - wcscat_s(renderdocPath, L"\\renderdocshim64.dll"); - shimpathNative = renderdocPath; + shimpathNative = renderdocPath + "\\renderdocshim64.dll"; // if it looks like we're in the development environment, look for the alternate bitness in the // corresponding folder - const wchar_t *devLocation = wcsstr(renderdocPath, L"\\x64\\Development\\"); - if(devLocation) + int devLocation = renderdocPath.find("\\x64\\Development\\"); + if(devLocation >= 0) { - size_t idx = devLocation - renderdocPath; + renderdocPath[devLocation] = 0; - renderdocPath[idx] = 0; - - shimpathWow32 = renderdocPath; - shimpathWow32 += L"\\Win32\\Development\\renderdocshim32.dll"; - - cmdpathWow32 = renderdocPath; - cmdpathWow32 += L"\\Win32\\Development\\renderdoccmd.exe"; + shimpathWow32 = renderdocPath + "\\Win32\\Development\\renderdocshim32.dll"; + cmdpathWow32 = renderdocPath + "\\Win32\\Development\\renderdoccmd.exe"; } - - if(!devLocation) + else { - devLocation = wcsstr(renderdocPath, L"\\x64\\Release\\"); + devLocation = renderdocPath.find("\\x64\\Release\\"); - if(devLocation) + if(devLocation >= 0) { - size_t idx = devLocation - renderdocPath; + renderdocPath[devLocation] = 0; - renderdocPath[idx] = 0; - - shimpathWow32 = renderdocPath; - shimpathWow32 += L"\\Win32\\Release\\renderdocshim32.dll"; - - cmdpathWow32 = renderdocPath; - cmdpathWow32 += L"\\Win32\\Release\\renderdoccmd.exe"; + shimpathWow32 = renderdocPath + "\\Win32\\Release\\renderdocshim32.dll"; + cmdpathWow32 = renderdocPath + "\\Win32\\Release\\renderdoccmd.exe"; } } // if we're not in the dev environment, assume it's under a x86\ subfolder - if(!devLocation) + if(devLocation < 0) { - *slash = 0; - shimpathWow32 = renderdocPath; - shimpathWow32 += L"\\x86\\renderdocshim32.dll"; - - cmdpathWow32 = renderdocPath; - cmdpathWow32 += L"\\x86\\renderdoccmd.exe"; + shimpathWow32 = renderdocPath + "\\x86\\renderdocshim32.dll"; + cmdpathWow32 = renderdocPath + "\\x86\\renderdoccmd.exe"; } #else // nothing fancy to do here for 32-bit, just point the shim next to our dll. - *slash = 0; - wcscat_s(renderdocPath, L"\\renderdocshim32.dll"); - shimpathNative = renderdocPath; + shimpathNative = renderdocPath + "\\renderdocshim32.dll"; #endif @@ -1493,26 +1447,16 @@ bool Process::StartGlobalHook(const char *pathmatch, const char *capturefile, si.cb = sizeof(si); - std::wstring paramsAlloc; - paramsAlloc.resize(2048); - // serialise to string with two chars per byte - std::string optstr = opts.EncodeAsString(); + rdcstr optstr = opts.EncodeAsString(); + rdcstr debugLogfile = RDCGETLOGFILE(); - std::wstring wcapturefile = - capturefile == NULL ? L"" : StringFormat::UTF82Wide(std::string(capturefile)); - std::wstring wpathmatch = StringFormat::UTF82Wide(std::string(pathmatch)); + rdcstr params = StringFormat::Fmt( + "\"%s\" globalhook --match \"%s\" --capfile \"%s\" --debuglog \"%s\" --capopts \"%s\"", + cmdpathNative.c_str(), pathmatch, capturefile ? capturefile : "", debugLogfile.c_str(), + optstr.c_str()); - std::string debugLogfile = RDCGETLOGFILE(); - std::wstring wdebugLogfile = StringFormat::UTF82Wide(debugLogfile); - - _snwprintf_s(¶msAlloc[0], 2047, 2047, - L"\"%ls\" globalhook --match \"%ls\" --capfile \"%ls\" --debuglog \"%ls\" " - L"--capopts \"%hs\"", - cmdpathNative.c_str(), wpathmatch.c_str(), wcapturefile.c_str(), - wdebugLogfile.c_str(), optstr.c_str()); - - paramsAlloc[2047] = 0; + rdcwstr paramsAlloc = StringFormat::UTF82Wide(params); // we'll be setting stdin si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; @@ -1575,13 +1519,12 @@ bool Process::StartGlobalHook(const char *pathmatch, const char *capturefile, // repeat the process for the Wow32 renderdoccmd #if ENABLED(RDOC_X64) - _snwprintf_s(¶msAlloc[0], 2047, 2047, - L"\"%ls\" globalhook --match \"%ls\" --capfile \"%ls\" --debuglog \"%ls\" " - L"--capopts \"%hs\"", - cmdpathWow32.c_str(), wpathmatch.c_str(), wcapturefile.c_str(), - wdebugLogfile.c_str(), optstr.c_str()); + params = StringFormat::Fmt( + "\"%s\" globalhook --match \"%s\" --capfile \"%s\" --debuglog \"%s\" --capopts \"%s\"", + cmdpathWow32.c_str(), pathmatch, capturefile ? capturefile : "", debugLogfile.c_str(), + optstr.c_str()); - paramsAlloc[2047] = 0; + paramsAlloc = StringFormat::UTF82Wide(params); { SECURITY_ATTRIBUTES pipeSec; diff --git a/renderdoc/os/win32/win32_shellext.cpp b/renderdoc/os/win32/win32_shellext.cpp index ed8f0d0d1..d57e500bf 100644 --- a/renderdoc/os/win32/win32_shellext.cpp +++ b/renderdoc/os/win32/win32_shellext.cpp @@ -117,7 +117,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream RDCDEBUG("RDCThumbnailProvider Initialize read %d bytes from file", numRead); - std::vector captureHeader(buf, buf + numRead); + bytebuf captureHeader(buf, numRead); delete[] buf; @@ -146,7 +146,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream return S_OK; } - void STDMETHODCALLTYPE ReadLegacyCaptureThumb(std::vector &captureHeader) + void STDMETHODCALLTYPE ReadLegacyCaptureThumb(rdcarray &captureHeader) { // we want to support old capture files, so we decode the thumbnail by hand here with the // old header. @@ -232,7 +232,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream // eSectionFlag_LZ4Compressed if(sectionFlags & 0x2) { - std::vector uncompressed; + rdcarray uncompressed; LZ4_streamDecode_t lZ4Decomp = {}; LZ4_setStreamDecode(&lZ4Decomp, NULL, 0); diff --git a/renderdoc/os/win32/win32_specific.h b/renderdoc/os/win32/win32_specific.h index 691ebf70f..e79d4ed0a 100644 --- a/renderdoc/os/win32/win32_specific.h +++ b/renderdoc/os/win32/win32_specific.h @@ -50,7 +50,7 @@ #define EmbeddedResource(filename) CONCAT(RESOURCE_, filename) #define GetEmbeddedResource(filename) GetDynamicEmbeddedResource(EmbeddedResource(filename)) -std::string GetDynamicEmbeddedResource(int resource); +rdcstr GetDynamicEmbeddedResource(int resource); namespace OSUtility { diff --git a/renderdoc/os/win32/win32_stringio.cpp b/renderdoc/os/win32/win32_stringio.cpp index 4eded4a13..0a2d9c6e8 100644 --- a/renderdoc/os/win32/win32_stringio.cpp +++ b/renderdoc/os/win32/win32_stringio.cpp @@ -32,13 +32,14 @@ #include #include #include "api/app/renderdoc_app.h" +#include "common/common.h" #include "os/os_specific.h" #include "strings/string_utils.h" // gives us an address to identify this dll with static int dllLocator = 0; -std::string GetDynamicEmbeddedResource(int resource) +rdcstr GetDynamicEmbeddedResource(int resource) { HMODULE mod = NULL; GetModuleHandleExA( @@ -60,7 +61,7 @@ std::string GetDynamicEmbeddedResource(int resource) const char *resData = (const char *)LockResource(data); if(resData) - return std::string(resData, resData + resSize); + return rdcstr(resData, resSize); } return ""; @@ -159,44 +160,43 @@ bool GetKeyState(int key) namespace FileIO { -void GetExecutableFilename(std::string &selfName) +void GetExecutableFilename(rdcstr &selfName) { wchar_t curFile[512] = {0}; GetModuleFileNameW(NULL, curFile, 511); - selfName = StringFormat::Wide2UTF8(std::wstring(curFile)); + selfName = StringFormat::Wide2UTF8(curFile); } -void GetLibraryFilename(std::string &selfName) +void GetLibraryFilename(rdcstr &selfName) { wchar_t curFile[512] = {0}; GetModuleFileNameW(GetModuleHandleA(STRINGIZE(RDOC_DLL_FILE) ".dll"), curFile, 511); - selfName = StringFormat::Wide2UTF8(std::wstring(curFile)); + selfName = StringFormat::Wide2UTF8(curFile); } -bool IsRelativePath(const std::string &path) +bool IsRelativePath(const rdcstr &path) { if(path.empty()) return false; - std::wstring wpath = StringFormat::UTF82Wide(path.c_str()); - return PathIsRelativeW(wpath.c_str()) != 0; + return PathIsRelativeW(StringFormat::UTF82Wide(path).c_str()) != 0; } -std::string GetFullPathname(const std::string &filename) +rdcstr GetFullPathname(const rdcstr &filename) { - std::wstring wfn = StringFormat::UTF82Wide(filename); + rdcwstr wfn = StringFormat::UTF82Wide(filename); wchar_t path[512] = {0}; GetFullPathNameW(wfn.c_str(), ARRAY_COUNT(path) - 1, path, NULL); - return StringFormat::Wide2UTF8(std::wstring(path)); + return StringFormat::Wide2UTF8(path); } -std::string FindFileInPath(const std::string &file) +rdcstr FindFileInPath(const rdcstr &file) { - std::string filePath; + rdcstr filePath; // Search the PATH directory list for the application (like shell where) to get the absolute path // Return "" if no exectuable found in the PATH list @@ -208,14 +208,14 @@ std::string FindFileInPath(const std::string &file) char *next = NULL; const char *pathSeparator = ";"; const char *path = strtok_s(envPath, pathSeparator, &next); - std::wstring fileName = StringFormat::UTF82Wide(file); + rdcwstr fileName = StringFormat::UTF82Wide(file); while(path) { - std::wstring testPath = StringFormat::UTF82Wide(path); + rdcwstr testPath = StringFormat::UTF82Wide(path); // Check for the following extensions. If fileName already has one, they will be ignored. - std::vector extensions; + rdcarray extensions; extensions.push_back(L".exe"); extensions.push_back(L".bat"); @@ -225,7 +225,7 @@ std::string FindFileInPath(const std::string &file) if(SearchPathW(testPath.c_str(), fileName.c_str(), extensions[i].c_str(), ARRAY_COUNT(foundPath) - 1, foundPath, NULL) != 0) { - filePath = StringFormat::Wide2UTF8(std::wstring(foundPath)); + filePath = StringFormat::Wide2UTF8(foundPath); break; } } @@ -236,48 +236,43 @@ std::string FindFileInPath(const std::string &file) return filePath; } -void CreateParentDirectory(const std::string &filename) +void CreateParentDirectory(const rdcstr &filename) { - std::wstring wfn = StringFormat::UTF82Wide(get_dirname(filename)); + rdcstr dirname = get_dirname(filename); // This function needs \\s not /s. So stupid! - for(size_t i = 0; i < wfn.size(); i++) - if(wfn[i] == L'/') - wfn[i] = L'\\'; + for(size_t i = 0; i < dirname.size(); i++) + if(dirname[i] == L'/') + dirname[i] = L'\\'; - // Remove trailing \\s - size_t trailingSeperatorPos = wfn.find_last_of(L'\\'); - while(trailingSeperatorPos == wfn.length() - 1) - { - wfn.erase(trailingSeperatorPos); - trailingSeperatorPos = wfn.find_last_of(L'\\'); - } + // remove trailing \\s + while(dirname.back() == '\\') + dirname.pop_back(); // Find all directories we need to create - std::vector directoriesToCreate; - while(!wfn.empty()) + rdcarray directoriesToCreate; + while(!dirname.empty()) { - DWORD fileAttributes = GetFileAttributesW(wfn.c_str()); + DWORD fileAttributes = GetFileAttributesW(StringFormat::UTF82Wide(dirname).c_str()); if(fileAttributes != INVALID_FILE_ATTRIBUTES) break; - directoriesToCreate.push_back(wfn); + directoriesToCreate.push_back(dirname); - size_t seperatorPos = wfn.find_last_of(L'\\'); - if(seperatorPos == std::string::npos) - break; - else - wfn = wfn.substr(0, seperatorPos); + dirname = get_dirname(dirname); + + while(dirname.back() == '\\') + dirname.pop_back(); } // Create the directories in reverse order for(ptrdiff_t i = directoriesToCreate.size() - 1; i >= 0; i--) { - CreateDirectoryW(directoriesToCreate[i].c_str(), NULL); + CreateDirectoryW(StringFormat::UTF82Wide(directoriesToCreate[i]).c_str(), NULL); } } -std::string GetReplayAppFilename() +rdcstr GetReplayAppFilename() { HMODULE hModule = NULL; GetModuleHandleEx( @@ -286,9 +281,9 @@ std::string GetReplayAppFilename() wchar_t curFile[512] = {0}; GetModuleFileNameW(hModule, curFile, 511); - std::string path = StringFormat::Wide2UTF8(std::wstring(curFile)); + rdcstr path = StringFormat::Wide2UTF8(curFile); path = get_dirname(path); - std::string exe = path + "/qrenderdoc.exe"; + rdcstr exe = path + "/qrenderdoc.exe"; FILE *f = FileIO::fopen(exe.c_str(), "rb"); if(f) @@ -320,14 +315,14 @@ std::string GetReplayAppFilename() if(type == REG_EXPAND_SZ || type == REG_SZ) { - return StringFormat::Wide2UTF8(std::wstring(curFile)); + return StringFormat::Wide2UTF8(curFile); } return ""; } -void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, - std::string &logging_filename, std::string &target) +void GetDefaultFiles(const char *logBaseName, rdcstr &capture_filename, rdcstr &logging_filename, + rdcstr &target) { wchar_t temp_filename[MAX_PATH]; @@ -349,7 +344,7 @@ void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, mod++; // now points to base filename without extension - target = StringFormat::Wide2UTF8(std::wstring(mod)); + target = StringFormat::Wide2UTF8(mod); time_t t = time(NULL); tm now; @@ -360,33 +355,35 @@ void GetDefaultFiles(const char *logBaseName, std::string &capture_filename, wsprintf(filename_start, L"RenderDoc\\%ls_%04d.%02d.%02d_%02d.%02d.rdc", mod, 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min); - capture_filename = StringFormat::Wide2UTF8(std::wstring(temp_filename)); + capture_filename = StringFormat::Wide2UTF8(temp_filename); *filename_start = 0; - std::wstring wbase = StringFormat::UTF82Wide(std::string(logBaseName)); + rdcwstr wbase = StringFormat::UTF82Wide(logBaseName); wsprintf(filename_start, L"RenderDoc\\%ls_%04d.%02d.%02d_%02d.%02d.%02d.log", wbase.c_str(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); - logging_filename = StringFormat::Wide2UTF8(std::wstring(temp_filename)); + logging_filename = StringFormat::Wide2UTF8(temp_filename); } -std::string GetHomeFolderFilename() +rdcstr GetHomeFolderFilename() { PWSTR docsPath; SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND, NULL, &docsPath); - std::wstring documents = docsPath; + rdcwstr documents = docsPath; CoTaskMemFree(docsPath); - if(documents[documents.size() - 1] == '/' || documents[documents.size() - 1] == '\\') - documents.pop_back(); + rdcstr ret = StringFormat::Wide2UTF8(documents); - return StringFormat::Wide2UTF8(documents); + while(ret.back() == '/' || ret.back() == '\\') + ret.pop_back(); + + return ret; } -std::string GetAppFolderFilename(const std::string &filename) +rdcstr GetAppFolderFilename(const rdcstr &filename) { PWSTR appDataPath = NULL; HRESULT hr = SHGetKnownFolderPath( @@ -394,32 +391,31 @@ std::string GetAppFolderFilename(const std::string &filename) if(appDataPath == NULL || FAILED(hr)) return ""; - std::wstring appdata = appDataPath; + rdcstr ret = StringFormat::Wide2UTF8(appDataPath); CoTaskMemFree(appDataPath); - if(appdata[appdata.size() - 1] == '/' || appdata[appdata.size() - 1] == '\\') - appdata.pop_back(); + while(ret.back() == '/' || ret.back() == '\\') + ret.pop_back(); - appdata += L"\\renderdoc\\"; + ret += "\\renderdoc\\" + filename; - CreateDirectoryW(appdata.c_str(), NULL); + CreateParentDirectory(ret); - std::string ret = StringFormat::Wide2UTF8(appdata) + filename; return ret; } -std::string GetTempFolderFilename() +rdcstr GetTempFolderFilename() { wchar_t temp_filename[MAX_PATH]; GetTempPathW(MAX_PATH, temp_filename); - return StringFormat::Wide2UTF8(std::wstring(temp_filename)); + return StringFormat::Wide2UTF8(temp_filename); } -uint64_t GetModifiedTimestamp(const std::string &filename) +uint64_t GetModifiedTimestamp(const rdcstr &filename) { - std::wstring wfn = StringFormat::UTF82Wide(filename); + rdcwstr wfn = StringFormat::UTF82Wide(filename); struct __stat64 st; int res = _wstat64(wfn.c_str(), &st); @@ -434,16 +430,16 @@ uint64_t GetModifiedTimestamp(const std::string &filename) bool Copy(const char *from, const char *to, bool allowOverwrite) { - std::wstring wfrom = StringFormat::UTF82Wide(std::string(from)); - std::wstring wto = StringFormat::UTF82Wide(std::string(to)); + rdcwstr wfrom = StringFormat::UTF82Wide(from); + rdcwstr wto = StringFormat::UTF82Wide(to); return ::CopyFileW(wfrom.c_str(), wto.c_str(), allowOverwrite == false) != 0; } bool Move(const char *from, const char *to, bool allowOverwrite) { - std::wstring wfrom = StringFormat::UTF82Wide(std::string(from)); - std::wstring wto = StringFormat::UTF82Wide(std::string(to)); + rdcwstr wfrom = StringFormat::UTF82Wide(from); + rdcwstr wto = StringFormat::UTF82Wide(to); if(exists(to)) { @@ -458,13 +454,13 @@ bool Move(const char *from, const char *to, bool allowOverwrite) void Delete(const char *path) { - std::wstring wpath = StringFormat::UTF82Wide(std::string(path)); + rdcwstr wpath = StringFormat::UTF82Wide(path); ::DeleteFileW(wpath.c_str()); } -std::vector GetFilesInDirectory(const char *path) +void GetFilesInDirectory(const char *path, rdcarray &ret) { - std::vector ret; + ret.clear(); if(path[0] == '/' && path[1] == 0) { @@ -476,17 +472,17 @@ std::vector GetFilesInDirectory(const char *path) if(driveMask & mask) { - std::string fn = "A:/"; + rdcstr fn = "A:/"; fn[0] = char('A' + i); ret.push_back(PathEntry(fn.c_str(), PathProperty::Directory)); } } - return ret; + return; } - std::string pathstr = path; + rdcstr pathstr = path; // normalise path to windows style for(size_t i = 0; i < pathstr.size(); i++) @@ -500,7 +496,7 @@ std::vector GetFilesInDirectory(const char *path) // append '\*' to do the search we want pathstr += "\\*"; - std::wstring wpath = StringFormat::UTF82Wide(pathstr); + rdcwstr wpath = StringFormat::UTF82Wide(pathstr); WIN32_FIND_DATAW findData = {}; HANDLE find = FindFirstFileW(wpath.c_str(), &findData); @@ -517,7 +513,7 @@ std::vector GetFilesInDirectory(const char *path) flags = PathProperty::ErrorAccessDenied; ret.push_back(PathEntry(path, flags)); - return ret; + return; } do @@ -567,14 +563,12 @@ std::vector GetFilesInDirectory(const char *path) // don't care if we hit an error or enumerated all files, just finish FindClose(find); - - return ret; } FILE *fopen(const char *filename, const char *mode) { - std::wstring wfn = StringFormat::UTF82Wide(std::string(filename)); - std::wstring wmode = StringFormat::UTF82Wide(std::string(mode)); + rdcwstr wfn = StringFormat::UTF82Wide(filename); + rdcwstr wmode = StringFormat::UTF82Wide(mode); FILE *ret = NULL; ::_wfopen_s(&ret, wfn.c_str(), wmode.c_str()); @@ -583,7 +577,7 @@ FILE *fopen(const char *filename, const char *mode) bool exists(const char *filename) { - std::wstring wfn = StringFormat::UTF82Wide(filename); + rdcwstr wfn = StringFormat::UTF82Wide(filename); struct __stat64 st; int res = _wstat64(wfn.c_str(), &st); @@ -591,7 +585,7 @@ bool exists(const char *filename) return (res == 0); } -std::string ErrorString() +rdcstr ErrorString() { int err = errno; @@ -644,13 +638,13 @@ int fclose(FILE *f) LogFileHandle *logfile_open(const char *filename) { - std::wstring wfn = StringFormat::UTF82Wide(std::string(filename)); + rdcwstr wfn = StringFormat::UTF82Wide(filename); return (LogFileHandle *)CreateFileW(wfn.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } -static std::string logfile_readall_fallback(const wchar_t *filename) +static rdcstr logfile_readall_fallback(const wchar_t *filename) { // if CreateFile/ReadFile failed, fall back and try regular stdio FILE *f = NULL; @@ -663,7 +657,7 @@ static std::string logfile_readall_fallback(const wchar_t *filename) if(filesize > 10) { - std::string ret; + rdcstr ret; ret.resize((size_t)filesize); size_t numRead = ::fread(&ret[0], 1, (size_t)filesize, f); @@ -680,16 +674,16 @@ static std::string logfile_readall_fallback(const wchar_t *filename) return ""; } -std::string logfile_readall(const char *filename) +rdcstr logfile_readall(const char *filename) { if(!exists(filename)) return StringFormat::Fmt("Logfile '%s' doesn't exist", filename); - std::wstring wfn = StringFormat::UTF82Wide(std::string(filename)); + rdcwstr wfn = StringFormat::UTF82Wide(filename); HANDLE h = CreateFileW(wfn.c_str(), FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - std::string ret; + rdcstr ret; if(h == INVALID_HANDLE_VALUE) { @@ -741,7 +735,7 @@ void logfile_close(LogFileHandle *logHandle, const char *deleteFilename) { // we can just try to delete the file. If it's open elsewhere in another process, the delete // will fail. - std::wstring wpath = StringFormat::UTF82Wide(std::string(deleteFilename)); + rdcwstr wpath = StringFormat::UTF82Wide(deleteFilename); ::DeleteFileW(wpath.c_str()); } } @@ -756,11 +750,11 @@ void sntimef(time_t utcTime, char *str, size_t bufSize, const char *format) wchar_t *buf = new wchar_t[bufSize + 1]; buf[bufSize] = 0; - std::wstring wfmt = StringFormat::UTF82Wide(std::string(format)); + rdcwstr wfmt = StringFormat::UTF82Wide(format); wcsftime(buf, bufSize, wfmt.c_str(), &tmv); - std::string result = StringFormat::Wide2UTF8(std::wstring(buf)); + rdcstr result = StringFormat::Wide2UTF8(buf); delete[] buf; @@ -775,14 +769,14 @@ void Shutdown() { } -std::string Wide2UTF8(const std::wstring &s) +rdcstr Wide2UTF8(const rdcwstr &s) { int bytes_required = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); if(bytes_required == 0) return ""; - std::string ret; + rdcstr ret; ret.resize(bytes_required); int res = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, &ret[0], bytes_required, NULL, NULL); @@ -802,20 +796,20 @@ std::string Wide2UTF8(const std::wstring &s) return ret; } -std::wstring UTF82Wide(const std::string &s) +rdcwstr UTF82Wide(const rdcstr &s) { int chars_required = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); + // chars_required includes the NULL terminator + chars_required--; + if(chars_required == 0) return L""; - std::wstring ret; - ret.resize(chars_required); + rdcwstr ret(chars_required); - int res = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, &ret[0], chars_required); - - if(ret.back() == 0) - ret.pop_back(); + // the buffer has an extra wchar_t for the null terminator + int res = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, &ret[0], chars_required + 1); if(res == 0) { @@ -834,7 +828,7 @@ namespace OSUtility { void WriteOutput(int channel, const char *str) { - std::wstring wstr = StringFormat::UTF82Wide(std::string(str)); + rdcwstr wstr = StringFormat::UTF82Wide(str); if(channel == OSUtility::Output_DebugMon) OutputDebugStringW(wstr.c_str()); diff --git a/renderdoc/os/win32/win32_threading.cpp b/renderdoc/os/win32/win32_threading.cpp index 5fccaa7f4..af6213f7f 100644 --- a/renderdoc/os/win32/win32_threading.cpp +++ b/renderdoc/os/win32/win32_threading.cpp @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include "common/common.h" #include "os/os_specific.h" double Timing::GetTickFrequency() @@ -175,11 +176,11 @@ int64_t nextTLSSlot = 0; struct TLSData { - std::vector data; + rdcarray data; }; static CriticalSection *m_TLSListLock = NULL; -static std::vector *m_TLSList = NULL; +static rdcarray *m_TLSList = NULL; void Init() { @@ -188,7 +189,7 @@ void Init() RDCFATAL("Can't allocate OS TLS slot"); m_TLSListLock = new CriticalSection(); - m_TLSList = new std::vector(); + m_TLSList = new rdcarray(); } void Shutdown() diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index a0ecfc39e..134849dbe 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -333,8 +333,13 @@ RENDERDOC_ExecuteAndInject(const char *app, const char *workingDir, const char * const rdcarray &env, const char *capturefile, const CaptureOptions &opts, bool waitForExit) { - return Process::LaunchAndInjectIntoProcess(app, workingDir, cmdLine, env, capturefile, opts, - waitForExit != 0); + rdcpair status = Process::LaunchAndInjectIntoProcess( + app, workingDir, cmdLine, env, capturefile, opts, waitForExit != 0); + + ExecuteResult ret; + ret.status = status.first; + ret.ident = status.second; + return ret; } extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetDefaultCaptureOptions(CaptureOptions *opts) @@ -368,7 +373,13 @@ extern "C" RENDERDOC_API ExecuteResult RENDERDOC_CC RENDERDOC_InjectIntoProcess(uint32_t pid, const rdcarray &env, const char *capturefile, const CaptureOptions &opts, bool waitForExit) { - return Process::InjectIntoProcess(pid, env, capturefile, opts, waitForExit != 0); + rdcpair status = + Process::InjectIntoProcess(pid, env, capturefile, opts, waitForExit != 0); + + ExecuteResult ret; + ret.status = status.first; + ret.ident = status.second; + return ret; } extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_FreeArrayMem(void *mem) @@ -865,13 +876,13 @@ extern "C" RENDERDOC_API int RENDERDOC_CC RENDERDOC_RunFunctionalTests(int pytho return 1; #endif - std::string libPath; + rdcstr libPath; FileIO::GetLibraryFilename(libPath); libPath = get_dirname(libPath); - std::string modulePath = libPath + moduledir; + rdcstr modulePath = libPath + moduledir; - std::string moduleFilename = modulePath + "/" + modulename; + rdcstr moduleFilename = modulePath + "/" + modulename; if(!FileIO::exists(moduleFilename.c_str())) { @@ -923,29 +934,28 @@ extern "C" RENDERDOC_API int RENDERDOC_CC RENDERDOC_RunFunctionalTests(int pytho return 1; } - std::vector wideArgs(args.size()); + rdcarray wideArgs(args.size()); for(size_t i = 0; i < args.size(); i++) wideArgs[i] = StringFormat::UTF82Wide(args[i]); // insert fake arguments to point at the script and our modules - wideArgs.insert(wideArgs.begin(), - { - L"python", - // specify script path - StringFormat::UTF82Wide(scriptPath), - // specify native library path - L"--renderdoc", StringFormat::UTF82Wide(libPath), - // specify python module path - L"--pyrenderdoc", StringFormat::UTF82Wide(modulePath), - // force in-process as we can't fork out to python to pass args - L"--in-process", - }); + wideArgs.insert(0, { + L"python", + // specify script path + StringFormat::UTF82Wide(scriptPath), + // specify native library path + L"--renderdoc", StringFormat::UTF82Wide(libPath), + // specify python module path + L"--pyrenderdoc", StringFormat::UTF82Wide(modulePath), + // force in-process as we can't fork out to python to pass args + L"--in-process", + }); - std::vector wideArgStrings(wideArgs.size()); + rdcarray wideArgStrings(wideArgs.size()); for(size_t i = 0; i < wideArgs.size(); i++) - wideArgStrings[i] = &wideArgs[i][0]; + wideArgStrings[i] = wideArgs[i].data(); return mainFunc((int)wideArgStrings.size(), wideArgStrings.data()); } diff --git a/renderdoc/serialise/rdcfile.cpp b/renderdoc/serialise/rdcfile.cpp index d3b3c1738..54421cc06 100644 --- a/renderdoc/serialise/rdcfile.cpp +++ b/renderdoc/serialise/rdcfile.cpp @@ -288,7 +288,7 @@ void RDCFile::Open(const char *path) Init(reader); } -void RDCFile::Open(const std::vector &buffer) +void RDCFile::Open(const bytebuf &buffer) { m_Buffer = buffer; m_File = NULL; diff --git a/renderdoc/serialise/rdcfile.h b/renderdoc/serialise/rdcfile.h index 2959d0767..147845827 100644 --- a/renderdoc/serialise/rdcfile.h +++ b/renderdoc/serialise/rdcfile.h @@ -72,7 +72,7 @@ public: // opens an existing file for read and/or modification. Error if file doesn't exist void Open(const char *filename); - void Open(const std::vector &buffer); + void Open(const bytebuf &buffer); bool CopyFileTo(const char *filename); @@ -105,7 +105,7 @@ private: FILE *m_File = NULL; std::string m_Filename; - std::vector m_Buffer; + bytebuf m_Buffer; SectionProperties m_CurrentWritingProps; diff --git a/renderdoc/serialise/streamio.cpp b/renderdoc/serialise/streamio.cpp index b10e4e1a2..f3c8ae2ee 100644 --- a/renderdoc/serialise/streamio.cpp +++ b/renderdoc/serialise/streamio.cpp @@ -51,7 +51,7 @@ StreamReader::StreamReader(const byte *buffer, uint64_t bufferSize) m_Ownership = Ownership::Nothing; } -StreamReader::StreamReader(const std::vector &buffer) +StreamReader::StreamReader(const bytebuf &buffer) { m_InputSize = m_BufferSize = buffer.size(); m_BufferHead = m_BufferBase = AllocAlignedBuffer(m_BufferSize); diff --git a/renderdoc/serialise/streamio.h b/renderdoc/serialise/streamio.h index 2dfceb789..8ee00fa87 100644 --- a/renderdoc/serialise/streamio.h +++ b/renderdoc/serialise/streamio.h @@ -81,7 +81,7 @@ public: StreamReader(StreamInvalidType); StreamReader(StreamDummyType); StreamReader(const byte *buffer, uint64_t bufferSize); - StreamReader(const std::vector &buffer); + StreamReader(const bytebuf &buffer); StreamReader(Network::Socket *sock, Ownership own); StreamReader(FILE *file, uint64_t fileSize, Ownership own); diff --git a/renderdoc/strings/string_utils.cpp b/renderdoc/strings/string_utils.cpp index aec632cd3..cb5f4b3c3 100644 --- a/renderdoc/strings/string_utils.cpp +++ b/renderdoc/strings/string_utils.cpp @@ -125,6 +125,22 @@ rdcstr get_dirname(const rdcstr &path) return base.substr(0, offset); } +rdcstr strip_extension(const rdcstr &path) +{ + if(path.empty()) + return path; + + size_t offs = path.size() - 1; + + while(offs > 0 && path[offs] != '.') + offs--; + + if(offs == 0 && path[offs] != '.') + return path; + + return path.substr(0, offs); +} + void split(const rdcstr &in, rdcarray &out, const char sep) { if(in.empty()) @@ -264,6 +280,18 @@ TEST_CASE("String manipulation", "[string]") CHECK(get_dirname("C:\\windows\\path/mixed/slashes\\foo") == "C:\\windows\\path/mixed/slashes"); }; + SECTION("strip_extension") + { + CHECK(strip_extension("foo.exe") == "foo"); + CHECK(strip_extension("foo.exe.zip") == "foo.exe"); + CHECK(strip_extension("foo..exe") == "foo."); + CHECK(strip_extension("foo") == "foo"); + CHECK(strip_extension("") == ""); + CHECK(strip_extension(".exe") == ""); + CHECK(strip_extension(".config.txt") == ".config"); + CHECK(strip_extension("bar/foo.exe") == "bar/foo"); + }; + SECTION("strupper") { CHECK(strupper("foobar") == "FOOBAR"); diff --git a/renderdoc/strings/string_utils.h b/renderdoc/strings/string_utils.h index 587e25ec8..8a557513c 100644 --- a/renderdoc/strings/string_utils.h +++ b/renderdoc/strings/string_utils.h @@ -35,6 +35,7 @@ uint32_t strhash(const char *str, uint32_t existingHash = 5381); rdcstr get_basename(const rdcstr &path); rdcstr get_dirname(const rdcstr &path); +rdcstr strip_extension(const rdcstr &path); void split(const rdcstr &in, rdcarray &out, const char sep); void merge(const rdcarray &in, rdcstr &out, const char sep); diff --git a/renderdoc/strings/utf8printf.cpp b/renderdoc/strings/utf8printf.cpp index 0a1002be5..18f009438 100644 --- a/renderdoc/strings/utf8printf.cpp +++ b/renderdoc/strings/utf8printf.cpp @@ -27,6 +27,57 @@ // grisu2 double-to-string function, returns number of digits written to digits array int grisu2(uint64_t mantissa, int exponent, char digits[18], int &kout); +static int wchar2multibyte(wchar_t chr, char mbchr[4]) +{ + // U+00000 -> U+00007F 1 byte 0xxxxxxx + // U+00080 -> U+0007FF 2 bytes 110xxxxx 10xxxxxx + // U+00800 -> U+00FFFF 3 bytes 1110xxxx 10xxxxxx 10xxxxxx + // U+10000 -> U+1FFFFF 4 bytes 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + // upcast to uint32_t, so we do the same processing on windows where + // sizeof(wchar_t) == 2 + uint32_t wc = (uint32_t)chr; + + if(wc > 0x10FFFF) + wc = 0xFFFD; // replacement character + + if(wc <= 0x7f) + { + mbchr[0] = (char)wc; + return 1; + } + else if(wc <= 0x7ff) + { + mbchr[1] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[0] = 0xC0 | (char)(wc & 0x1f); + return 2; + } + else if(wc <= 0xffff) + { + mbchr[2] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[1] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[0] = 0xE0 | (char)(wc & 0x0f); + wc >>= 4; + return 3; + } + else + { + // invalid codepoints above 0x10FFFF were replaced above + mbchr[3] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[2] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[1] = 0x80 | (char)(wc & 0x3f); + wc >>= 6; + mbchr[0] = 0xF0 | (char)(wc & 0x07); + wc >>= 3; + return 4; + } +} + /////////////////////////////////////////////////////////////////////////////// // functions for appending to output (handling running out of buffer space) @@ -922,7 +973,7 @@ void formatargument(char type, void *rawarg, FormatterParams formatter, char *&o // convert single wide character to UTF-8 sequence, at most // 4 characters char mbchr[4]; - int seqlen = StringFormat::Wide2UTF8(chr, mbchr); + int seqlen = wchar2multibyte(chr, mbchr); appendstring(output, actualsize, end, mbchr, seqlen); } else @@ -954,7 +1005,7 @@ void formatargument(char type, void *rawarg, FormatterParams formatter, char *&o len = RDCMIN(len, precision); // convert the substring to UTF-8 - std::string str = StringFormat::Wide2UTF8(std::wstring(ws, ws + len)); + rdcstr str = StringFormat::Wide2UTF8(rdcwstr(ws, len)); // add left padding, if necessary if(formatter.Width != FormatterParams::NoWidth && len < width && @@ -1449,11 +1500,11 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") RDCCOMPILE_ASSERT(sizeof(bufa) == sizeof(ref), "ref is mis-sized for test"); { - INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + INFO("bufa is '" << rdcstr(bufa) << "', ref is '" << ref << "'"); CHECK(memcmp(bufa, ref, sizeof(ref)) == 0); } { - INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + INFO("bufb is '" << rdcstr(bufb) << "', ref is '" << ref << "'"); CHECK(memcmp(bufb, ref, sizeof(ref)) == 0); } @@ -1461,7 +1512,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") { memset(bufa, 'a', sizeof(bufa)); a = utf8printf_wrapper(bufa, sizeof(bufa), "%d foo", largenum); - INFO("bufa is '" << std::string(bufa) << "'"); + INFO("bufa is '" << rdcstr(bufa) << "'"); CHECK(memcmp(bufa, ref, sizeof(ref)) == 0); } }; @@ -1486,11 +1537,11 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufb), "ref is mis-sized for test"); { - INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + INFO("bufa is '" << rdcstr(bufa) << "', ref is '" << ref << "'"); CHECK(memcmp(bufa, ref, sizeof(ref)) == 0); } { - INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + INFO("bufb is '" << rdcstr(bufb) << "', ref is '" << ref << "'"); CHECK(memcmp(bufb, ref, sizeof(ref)) == 0); } }; @@ -1515,11 +1566,11 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufb), "ref is mis-sized for test"); { - INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + INFO("bufa is '" << rdcstr(bufa) << "', ref is '" << ref << "'"); CHECK(memcmp(bufa, ref, sizeof(ref)) == 0); } { - INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + INFO("bufb is '" << rdcstr(bufb) << "', ref is '" << ref << "'"); CHECK(memcmp(bufb, ref, sizeof(ref)) == 0); } }; @@ -1545,15 +1596,15 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") refb[19] = 'b'; { - INFO("bufa is '" << std::string(bufa) << "', refa is '" << refa << "'"); - INFO("bufa+12 is '" << std::string(bufa + 12, bufa + 20) << "', refa+12 is '" - << std::string(refa + 12, refa + 20) << "'"); + INFO("bufa is '" << rdcstr(bufa) << "', refa is '" << refa << "'"); + INFO("bufa+12 is '" << rdcstr(bufa + 12, 8) << "', refa+12 is '" << rdcstr(refa + 12, 8) + << "'"); CHECK(memcmp(bufa, refa, sizeof(refa)) == 0); } { - INFO("bufb is '" << std::string(bufb) << "', refb is '" << refb << "'"); - INFO("bufb+12 is '" << std::string(bufb + 12, bufb + 20) << "', refb+12 is '" - << std::string(refb + 12, refb + 20) << "'"); + INFO("bufb is '" << rdcstr(bufb) << "', refb is '" << refb << "'"); + INFO("bufb+12 is '" << rdcstr(bufb + 12, 8) << "', refb+12 is '" << rdcstr(refb + 12, 8) + << "'"); CHECK(memcmp(bufb, refb, sizeof(refb)) == 0); } }; @@ -1570,8 +1621,8 @@ TEST_CASE("utf8printf standard string formatters", "[utf8printf]") CHECK(StringFormat::Fmt("%lc", wc) == "á"); }; - const std::string s = "ελληνικά"; - const std::wstring ws = L"\x3b5\x3bb\x3bb\x3b7\x3bd\x3b9\x3ba\x3ac"; + const rdcstr s = "ελληνικά"; + const rdcwstr ws = L"\x3b5\x3bb\x3bb\x3b7\x3bd\x3b9\x3ba\x3ac"; SECTION("Basic strings") {