e5c7ed2ce4b3c29df81450206165df23186edb74
[platform/core/security/vist.git] / src / osquery / utils / json / json.h
1 /**
2  *  Copyright (c) 2014-present, Facebook, Inc.
3  *  All rights reserved.
4  *
5  *  This source code is licensed in accordance with the terms specified in
6  *  the LICENSE file found in the root directory of this source tree.
7  */
8
9 #pragma once
10
11 #include <cstddef>
12
13 #include <osquery/utils/only_movable.h>
14 #include <osquery/utils/status/status.h>
15 #include <osquery/utils/system/system.h>
16
17 #ifdef WIN32
18 #pragma warning(push, 3)
19 #pragma warning(disable : 4715)
20 #endif
21
22 #include <rapidjson/document.h>
23 #include <rapidjson/error/en.h>
24 #include <rapidjson/stringbuffer.h>
25 #include <rapidjson/writer.h>
26
27 #ifdef WIN32
28 #pragma warning(pop)
29 #endif
30
31 namespace osquery {
32 /**
33  * @brief This provides a small wrapper around constructing JSON objects.
34  *
35  * Constructing RapidJSON objects can be slightly tricky. In our original
36  * refactoring we found several opportunities to leak memory and cause faults.
37  * This was mostly causes by setting allocators incorrectly.
38  */
39 class JSON : private only_movable {
40  private:
41   explicit JSON(rapidjson::Type type);
42
43  public:
44   JSON();
45   JSON(JSON&&) = default;
46   JSON& operator=(JSON&&) = default;
47
48   /// Create a JSON wrapper for an Object (map).
49   static JSON newObject();
50
51   /// Create a JSON wrapper for an Array (list).
52   static JSON newArray();
53
54   /// Create a JSON wrapper from an existing value.
55   static JSON newFromValue(const rapidjson::Value& value);
56
57  public:
58   /// Make a JSON object (map).
59   rapidjson::Document getObject() const;
60
61   /// Make a JSON array (list).
62   rapidjson::Document getArray() const;
63
64   /// Add a JSON object or array to a list.
65   void push(rapidjson::Value& value);
66
67   /// Add a JSON object or array to a list.
68   void push(rapidjson::Value& value, rapidjson::Value& arr);
69
70   /// Add a size_t to a JSON array.
71   void push(size_t value);
72
73   /// Add a size_t to a JSON array.
74   void push(size_t value, rapidjson::Value& arr);
75
76   /// Add a copy of a string to a JSON array.
77   void pushCopy(const std::string& value);
78
79   /// Add a reference to a string to a JSON array.
80   void pushCopy(const std::string& value, rapidjson::Value& arr);
81
82   /**
83    * @brief Add a string value to a JSON object by copying the contents.
84    *
85    * This will add the key and value to an input document. If the key exists
86    * the value will be replaced.
87    * The input document must be an object type.
88    */
89   void addCopy(const std::string& key,
90                const std::string& value,
91                rapidjson::Value& obj);
92
93   /**
94    * @brief Add a string value to a JSON object by copying the contents.
95    *
96    * This will add the key and value to the JSON document. If the key exists
97    * the value will be replaced.
98    * The document must be an object type.
99    */
100   void addCopy(const std::string& key, const std::string& value);
101
102   /**
103    * @brief Add a string value to a JSON object by referencing the contents.
104    *
105    * The string value must live longer than the document's use.
106    *
107    * This will add the key and value to an input document. If the key exists
108    * the value will be replaced.
109    * The input document must be an object type.
110    */
111   void addRef(const std::string& key,
112               const std::string& value,
113               rapidjson::Value& obj);
114
115   /**
116    * @brief Add a string value to a JSON object by referencing the contents.
117    *
118    * The string value must live longer than the document's use.
119    *
120    * This will add the key and value to the JSON document. If the key exists
121    * the value will be replaced.
122    * The input document must be an object type.
123    */
124   void addRef(const std::string& key, const std::string& value);
125
126   /**
127    * @brief Add a string value to a JSON object by copying the contents.
128    *
129    * This is basically and alias for addCopy()
130    *
131    * This will add the key and value to an input document. If the key exists
132    * the value will be replaced.
133    * The input document must be an object type.
134    */
135   void add(const std::string& key,
136            const std::string& value,
137            rapidjson::Value& obj);
138
139   /**
140    * @brief Add a string value to a JSON object by copying the contents.
141    *
142    * This is basically and alias for addCopy().
143    *
144    * This will add the key and value to the JSON document. If the key exists
145    * the value will be replaced.
146    * The document must be an object type.
147    */
148   void add(const std::string& key, const std::string& value);
149
150   /**
151    * @brief Add a char* value to a JSON object by copying the contents.
152    *
153    * This will add the key and value to an input document. If the key exists
154    * the value will be replaced.
155    * The input document must be an object type.
156    */
157   void add(const std::string& key, const char* value, rapidjson::Value& obj);
158
159   /**
160    * @brief Add a char* value to a JSON object by copying the contents.
161    *
162    * This will add the key and value to the JSON document. If the key exists
163    * the value will be replaced.
164    * The document must be an object type.
165    */
166   void add(const std::string& key, const char* value);
167
168   /**
169    * @brief Add a int value to a JSON object by copying the contents.
170    *
171    * This will add the key and value to an input document. If the key exists
172    * the value will be replaced.
173    * The input document must be an object type.
174    */
175   void add(const std::string& key, int value, rapidjson::Value& obj);
176
177   /**
178    * @brief Add a int value to a JSON object by copying the contents.
179    *
180    * This will add the key and value to the JSON document. If the key exists
181    * the value will be replaced.
182    * The document must be an object type.
183    */
184   void add(const std::string& key, int value);
185
186   /**
187    * @brief Add a long value to a JSON object by copying the contents.
188    *
189    * This will add the key and value to an input document. If the key exists
190    * the value will be replaced.
191    * The input document must be an object type.
192    */
193   void add(const std::string& key, long value, rapidjson::Value& obj);
194
195   /**
196    * @brief Add a long value to a JSON object by copying the contents.
197    *
198    * This will add the key and value to the JSON document. If the key exists
199    * the value will be replaced.
200    * The document must be an object type.
201    */
202   void add(const std::string& key, long value);
203
204   /**
205    * @brief Add a long long to a JSON object by copying the
206    * contents.
207    *
208    * This will add the key and value to an input document. If the key exists
209    * the value will be replaced.
210    * The input document must be an object type.
211    */
212   void add(const std::string& key, long long value, rapidjson::Value& obj);
213   /**
214    * @brief Add a long long to a JSON object by copying the
215    * contents.
216    *
217    * This will add the key and value to the JSON document. If the key exists
218    * the value will be replaced.
219    * The document must be an object type.
220    */
221   void add(const std::string& key, long long value);
222
223   /**
224    * @brief Add an unsigned int value to a JSON object by copying the contents.
225    *
226    * This will add the key and value to an input document. If the key exists
227    * the value will be replaced.
228    * The input document must be an object type.
229    */
230   void add(const std::string& key, unsigned int value, rapidjson::Value& obj);
231
232   /**
233    * @brief Add an unsigned int value to a JSON object by copying the contents.
234    *
235    * This will add the key and value to the JSON document. If the key exists
236    * the value will be replaced.
237    * The document must be an object type.
238    */
239   void add(const std::string& key, unsigned int value);
240
241   /**
242    * @brief Add an unsigned long value to a JSON object by copying the contents.
243    *
244    * This will add the key and value to an input document. If the key exists
245    * the value will be replaced.
246    * The input document must be an object type.
247    */
248   void add(const std::string& key, unsigned long value, rapidjson::Value& obj);
249
250   /**
251    * @brief Add an unsigned long value to a JSON object by copying the contents.
252    *
253    * This will add the key and value to the JSON document. If the key exists
254    * the value will be replaced.
255    * The document must be an object type.
256    */
257   void add(const std::string& key, unsigned long value);
258
259   /**
260    * @brief Add an unsigned long long to a JSON object by copying the
261    * contents.
262    *
263    * This will add the key and value to an input document. If the key exists
264    * the value will be replaced.
265    * The input document must be an object type.
266    */
267   void add(const std::string& key,
268            unsigned long long value,
269            rapidjson::Value& obj);
270   /**
271    * @brief Add an unsigned long long to a JSON object by copying the
272    * contents.
273    *
274    * This will add the key and value to the JSON document. If the key exists
275    * the value will be replaced.
276    * The document must be an object type.
277    */
278   void add(const std::string& key, unsigned long long value);
279
280   /**
281    * @brief Add a double value to a JSON object by copying the contents.
282    *
283    * This will add the key and value to an input document. If the key exists
284    * the value will be replaced.
285    * The input document must be an object type.
286    */
287   void add(const std::string& key, double value, rapidjson::Value& obj);
288   /**
289    * @brief Add an double value to a JSON object by copying the contents.
290    *
291    * This will add the key and value to the JSON document. If the key exists
292    * the value will be replaced.
293    * The document must be an object type.
294    */
295   void add(const std::string& key, double value);
296
297   /**
298    * @brief Add a bool value to a JSON object by copying the contents.
299    *
300    * This will add the key and value to an input document. If the key exists
301    * the value will be replaced.
302    * The input document must be an object type.
303    */
304   void add(const std::string& key, bool value, rapidjson::Value& obj);
305
306   /**
307    * @brief Add a bool value to a JSON object by copying the contents.
308    *
309    * This will add the key and value to the JSON document. If the key exists
310    * the value will be replaced.
311    * The document must be an object type.
312    */
313   void add(const std::string& key, bool value);
314
315   /// Add a JSON document as a member.
316   void add(const std::string& key, const rapidjson::Value& value);
317
318   /// Add a JSON document as a member of another document.
319   void add(const std::string& key,
320            const rapidjson::Value& value,
321            rapidjson::Value& obj);
322
323   /**
324    * @brief Copy a JSON object/array into the document.
325    *
326    * The type of the base document may change, be careful.
327    */
328   void copyFrom(const rapidjson::Value& value, rapidjson::Value& target);
329
330   /**
331    * @brief Copy a JSON object/array into the document.
332    *
333    * The type of the base document may change, be careful.
334    */
335   void copyFrom(const rapidjson::Value& value);
336
337   /// Convert this document to a JSON string.
338   Status toString(std::string& str) const;
339
340   /// Helper to convert a string into JSON.
341   Status fromString(const std::string& str);
342
343   /// Merge members of source into target, must both be objects.
344   void mergeObject(rapidjson::Value& target_obj, rapidjson::Value& source_obj);
345
346   void mergeArray(rapidjson::Value& target_arr, rapidjson::Value& source_arr);
347
348   /// Access the internal document containing the allocator.
349   rapidjson::Document& doc();
350
351   /// Access the internal document containing the allocator.
352   const rapidjson::Document& doc() const;
353
354  public:
355   /// Get the value as a 'size' or 0.
356   static size_t valueToSize(const rapidjson::Value& value);
357
358   /// Get the value as a 'bool' or false.
359   static bool valueToBool(const rapidjson::Value& value);
360
361  private:
362   rapidjson::Document doc_;
363   decltype(rapidjson::kObjectType) type_;
364 };
365 } // namespace osquery