xref: /aosp_15_r20/external/angle/src/common/serializer/JsonSerializer.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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