1 // 2 // Copyright 2021 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // JsonSerializer.h: Implementation of a JSON based serializer 7 // 8 9 #ifndef COMMON_JSONSERIALIZER_H_ 10 #define COMMON_JSONSERIALIZER_H_ 11 12 #include "common/angleutils.h" 13 14 #if !defined(ANGLE_HAS_RAPIDJSON) 15 # error RapidJSON must be available to build this file. 16 #endif // !defined(ANGLE_HAS_RAPIDJSON) 17 18 #include <rapidjson/document.h> 19 20 #include <map> 21 #include <memory> 22 #include <sstream> 23 #include <stack> 24 #include <type_traits> 25 26 namespace angle 27 { 28 29 // Rapidjson has problems picking the right AddMember template for long 30 // integer types, so let's just make these values use 64 bit variants 31 template <typename T> 32 struct StoreAs 33 { 34 using Type = T; 35 }; 36 37 template <> 38 struct StoreAs<unsigned long> 39 { 40 using Type = uint64_t; 41 }; 42 43 template <> 44 struct StoreAs<signed long> 45 { 46 using Type = int64_t; 47 }; 48 49 class JsonSerializer : public angle::NonCopyable 50 { 51 public: 52 JsonSerializer(); 53 ~JsonSerializer(); 54 55 void addCString(const std::string &name, const char *value); 56 57 void addString(const std::string &name, const std::string &value); 58 59 void addBlob(const std::string &name, const uint8_t *value, size_t length); 60 void addBlobWithMax(const std::string &name, 61 const uint8_t *value, 62 size_t length, 63 size_t maxSerializedLength); 64 65 void startGroup(const std::string &name); 66 67 void endGroup(); 68 69 template <typename T> 70 void addScalar(const std::string &name, T value) 71 { 72 typename StoreAs<T>::Type v = value; 73 addValue(name, rapidjson::Value(v)); 74 } 75 76 template <typename Vector> 77 void addVector(const std::string &name, const Vector &value) 78 { 79 rapidjson::Value arr(rapidjson::kArrayType); 80 arr.SetArray(); 81 82 for (typename StoreAs<typename Vector::value_type>::Type v : value) 83 { 84 arr.PushBack(v, mAllocator); 85 } 86 87 addValue(name, std::move(arr)); 88 } 89 90 template <typename T> 91 void addVectorAsHash(const std::string &name, const std::vector<T> &value) 92 { 93 if (!value.empty()) 94 { 95 addBlob(name, reinterpret_cast<const uint8_t *>(&value[0]), value.size() * sizeof(T)); 96 } 97 else 98 { 99 addCString(name, "null"); 100 } 101 } 102 103 void addVectorOfStrings(const std::string &name, const std::vector<std::string> &value); 104 105 void addBool(const std::string &name, bool value); 106 107 void addHexValue(const std::string &name, int value); 108 109 const char *data(); 110 111 std::vector<uint8_t> getData(); 112 113 size_t length(); 114 115 private: 116 using SortedValueGroup = std::multimap<std::string, rapidjson::Value>; 117 118 rapidjson::Value makeValueGroup(SortedValueGroup &group); 119 void addValue(const std::string &name, rapidjson::Value &&value); 120 121 void ensureEndDocument(); 122 123 using ValuePointer = std::unique_ptr<rapidjson::Value>; 124 125 rapidjson::Document mDoc; 126 rapidjson::Document::AllocatorType &mAllocator; 127 std::stack<std::string> mGroupNameStack; 128 std::stack<SortedValueGroup> mGroupValueStack; 129 std::string mResult; 130 }; 131 132 } // namespace angle 133 134 #endif // COMMON_JSONSERIALIZER_H_ 135