• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 LIBANGLE_JSONSERIALIZER_H_
10 #define LIBANGLE_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 startDocument(const std::string &name);
56     void endDocument();
57 
58     void addCString(const std::string &name, const char *value);
59 
60     void addString(const std::string &name, const std::string &value);
61 
62     void addBlob(const std::string &name, const uint8_t *value, size_t length);
63 
64     void startGroup(const std::string &name);
65 
66     void endGroup();
67 
68     const char *data() const;
69 
70     std::vector<uint8_t> getData() const;
71 
72     size_t length() const;
73 
74     template <typename T>
75     void addScalar(const std::string &name, T value)
76     {
77         typename StoreAs<T>::Type v = value;
78         mGroupValueStack.top().insert(std::make_pair(name, rapidjson::Value(v)));
79     }
80 
81     template <typename T>
82     void addVector(const std::string &name, const std::vector<T> &value)
83     {
84         rapidjson::Value array(rapidjson::kArrayType);
85         array.SetArray();
86 
87         for (typename StoreAs<T>::Type v : value)
88             array.PushBack(v, mAllocator);
89 
90         mGroupValueStack.top().insert(std::make_pair(name, std::move(array)));
91     }
92 
93     template <typename T>
94     void addVectorAsHash(const std::string &name, const std::vector<T> &value)
95     {
96         if (!value.empty())
97         {
98             addBlob(name, reinterpret_cast<const uint8_t *>(&value[0]), value.size() * sizeof(T));
99         }
100         else
101         {
102             addCString(name, "null");
103         }
104     }
105 
106     void addVectorOfStrings(const std::string &name, const std::vector<std::string> &value);
107 
108   private:
109     using SortedValueGroup = std::multimap<std::string, rapidjson::Value>;
110 
111     rapidjson::Value makeValueGroup(SortedValueGroup &group);
112 
113     using ValuePointer = std::unique_ptr<rapidjson::Value>;
114 
115     rapidjson::Document mDoc;
116     rapidjson::Document::AllocatorType &mAllocator;
117     std::stack<std::string> mGroupNameStack;
118     std::stack<SortedValueGroup> mGroupValueStack;
119     std::string mResult;
120 };
121 
122 }  // namespace angle
123 
124 #endif  // JSONSERIALIZER_H
125