1 /* 2 * Copyright (c) 2023 The Khronos Group Inc. 3 * Copyright (c) 2023 Valve Corporation 4 * Copyright (c) 2023 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Charles Giessen <charles@lunarg.com> 26 */ 27 28 #pragma once 29 30 #include <cstdint> 31 #include <stack> 32 #include <string> 33 34 // Utility class to simplify the writing of JSON manifest files 35 36 struct JsonWriter { 37 std::string output; 38 39 // the bool represents whether an object has been written & a comma is needed 40 std::stack<bool> stack; 41 StartObjectJsonWriter42 void StartObject() { 43 CommaAndNewLine(); 44 Indent(); 45 output += "{"; 46 stack.push(false); 47 } StartKeyedObjectJsonWriter48 void StartKeyedObject(std::string const& key) { 49 CommaAndNewLine(); 50 Indent(); 51 output += "\"" + key + "\": {"; 52 stack.push(false); 53 } EndObjectJsonWriter54 void EndObject() { 55 stack.pop(); 56 output += "\n"; 57 Indent(); 58 output += "}"; 59 } StartKeyedArrayJsonWriter60 void StartKeyedArray(std::string const& key) { 61 CommaAndNewLine(); 62 Indent(); 63 output += "\"" + key + "\": ["; 64 stack.push(false); 65 } StartArrayJsonWriter66 void StartArray() { 67 CommaAndNewLine(); 68 Indent(); 69 output += "["; 70 stack.push(false); 71 } EndArrayJsonWriter72 void EndArray() { 73 stack.pop(); 74 output += "\n"; 75 Indent(); 76 output += "]"; 77 } 78 AddKeyedStringJsonWriter79 void AddKeyedString(std::string const& key, std::string const& value) { 80 CommaAndNewLine(); 81 Indent(); 82 output += "\"" + key + "\": \"" + escape(value) + "\""; 83 } AddStringJsonWriter84 void AddString(std::string const& value) { 85 CommaAndNewLine(); 86 Indent(); 87 output += "\"" + escape(value) + "\""; 88 } 89 #if defined(WIN32) AddKeyedStringJsonWriter90 void AddKeyedString(std::string const& key, std::wstring const& value) { 91 CommaAndNewLine(); 92 Indent(); 93 output += "\"" + key + "\": \"" + escape(narrow(value)) + "\""; 94 } AddStringJsonWriter95 void AddString(std::wstring const& value) { 96 CommaAndNewLine(); 97 Indent(); 98 output += "\"" + escape(narrow(value)) + "\""; 99 } 100 #endif 101 AddKeyedBoolJsonWriter102 void AddKeyedBool(std::string const& key, bool value) { 103 CommaAndNewLine(); 104 Indent(); 105 output += "\"" + key + "\": " + (value ? "true" : "false"); 106 } AddBoolJsonWriter107 void AddBool(bool value) { 108 CommaAndNewLine(); 109 Indent(); 110 output += std::string(value ? "true" : "false"); 111 } 112 113 // Json doesn't allow `\` in strings, it must be escaped. Thus we have to convert '\\' to '\\\\' in strings escapeJsonWriter114 static std::string escape(std::string const& in_path) { 115 std::string out; 116 for (auto& c : in_path) { 117 if (c == '\\') 118 out += "\\\\"; 119 else 120 out += c; 121 } 122 return out; 123 } escapeJsonWriter124 static std::string escape(std::filesystem::path const& in_path) { return escape(narrow(in_path.native())); } 125 126 private: CommaAndNewLineJsonWriter127 void CommaAndNewLine() { 128 if (stack.size() > 0) { 129 if (stack.top() == false) { 130 stack.top() = true; 131 } else { 132 output += ","; 133 } 134 output += "\n"; 135 } 136 } IndentJsonWriter137 void Indent() { 138 for (uint32_t i = 0; i < stack.size(); i++) { 139 output += '\t'; 140 } 141 } 142 }; 143