1212#include < chrono>
1313#include < filesystem>
1414#include < fstream>
15+ #include < nlohmann/json.hpp>
1516#include < sstream>
1617
1718namespace fs = std::filesystem;
@@ -20,31 +21,6 @@ namespace renderdoc::core {
2021
2122namespace {
2223
23- // Escape a string for JSON output (handles quotes, backslashes, control chars).
24- std::string jsonEscape (const std::string& s) {
25- std::string out;
26- out.reserve (s.size () + 8 );
27- for (char c : s) {
28- switch (c) {
29- case ' "' : out += " \\\" " ; break ;
30- case ' \\ ' : out += " \\\\ " ; break ;
31- case ' \n ' : out += " \\ n" ; break ;
32- case ' \r ' : out += " \\ r" ; break ;
33- case ' \t ' : out += " \\ t" ; break ;
34- default :
35- if (static_cast <unsigned char >(c) < 0x20 ) {
36- char buf[8 ];
37- snprintf (buf, sizeof (buf), " \\ u%04x" , static_cast <unsigned >(c));
38- out += buf;
39- } else {
40- out += c;
41- }
42- break ;
43- }
44- }
45- return out;
46- }
47-
4824// Map ShaderStage to a short string for filenames.
4925std::string stageToFileSuffix (ShaderStage stage) {
5026 switch (stage) {
@@ -64,9 +40,6 @@ SnapshotResult exportSnapshot(Session& session, uint32_t eventId,
6440 const std::string& outputDir,
6541 std::function<std::string(const PipelineState&)> pipelineSerializer) {
6642 auto * ctrl = session.controller ();
67- if (!ctrl)
68- throw CoreError (CoreError::Code::NoCaptureOpen,
69- " No capture is open. Call open_capture first." );
7043
7144 ctrl->SetFrameEvent (eventId, true );
7245
@@ -180,42 +153,28 @@ SnapshotResult exportSnapshot(Session& session, uint32_t eventId,
180153 }
181154 }
182155
183- // 5. Write manifest.json (hand-crafted, no nlohmann::json dependency) .
156+ // 5. Write manifest.json.
184157 {
185158 auto now = std::chrono::system_clock::now ();
186159 auto epoch = std::chrono::duration_cast<std::chrono::seconds>(
187160 now.time_since_epoch ()).count ();
188161
189- std::ostringstream manifest;
190- manifest << " {\n " ;
191- manifest << " \" eventId\" : " << eventId << " ,\n " ;
192- manifest << " \" timestamp\" : " << epoch << " ,\n " ;
193- manifest << " \" files\" : [" ;
194-
195- for (size_t i = 0 ; i < result.files .size (); i++) {
196- if (i > 0 ) manifest << " ," ;
197- // Use just the filename, not the full path.
198- std::string fname = fs::path (result.files [i]).filename ().string ();
199- manifest << " \n \" " << jsonEscape (fname) << " \" " ;
200- }
201-
202- manifest << " \n ]" ;
162+ nlohmann::json manifest;
163+ manifest[" eventId" ] = eventId;
164+ manifest[" timestamp" ] = epoch;
203165
204- if (!result.errors .empty ()) {
205- manifest << " ,\n \" errors\" : [" ;
206- for (size_t i = 0 ; i < result.errors .size (); i++) {
207- if (i > 0 ) manifest << " ," ;
208- manifest << " \n \" " << jsonEscape (result.errors [i]) << " \" " ;
209- }
210- manifest << " \n ]" ;
211- }
166+ auto filesArr = nlohmann::json::array ();
167+ for (const auto & f : result.files )
168+ filesArr.push_back (fs::path (f).filename ().string ());
169+ manifest[" files" ] = filesArr;
212170
213- manifest << " \n }\n " ;
171+ if (!result.errors .empty ())
172+ manifest[" errors" ] = result.errors ;
214173
215174 std::string manifestPath = (fs::path (outputDir) / " manifest.json" ).string ();
216175 std::ofstream ofs (manifestPath);
217176 if (ofs) {
218- ofs << manifest.str ( );
177+ ofs << manifest.dump ( 2 );
219178 ofs.close ();
220179 result.manifestPath = manifestPath;
221180 result.files .push_back (manifestPath);
0 commit comments