1#pragma once
2
3#include "config_functions.h"
4#if USE_RAPIDJSON
5
6#include <common/StringRef.h>
7#include <Common/Exception.h>
8#include <Core/Types.h>
9
10#include <rapidjson/document.h>
11
12
13namespace DB
14{
15
16/// This class can be used as an argument for the template class FunctionJSON.
17/// It provides ability to parse JSONs using rapidjson library.
18struct RapidJSONParser
19{
20 static constexpr bool need_preallocate = false;
21 void preallocate(size_t) {}
22
23 bool parse(const StringRef & json)
24 {
25 rapidjson::MemoryStream ms(json.data, json.size);
26 rapidjson::EncodedInputStream<rapidjson::UTF8<>, rapidjson::MemoryStream> is(ms);
27 document.ParseStream(is);
28 return !document.HasParseError() && (ms.Tell() == json.size);
29 }
30
31 struct Iterator
32 {
33 public:
34 Iterator() {}
35 Iterator(const rapidjson::Document & document_) : value(&document_) {}
36 Iterator(const Iterator & src)
37 : value(src.value)
38 , is_object_member(src.is_object_member)
39 , current_in_array(src.current_in_array)
40 , end_of_array(src.end_of_array) {}
41
42 Iterator & operator =(const Iterator & src)
43 {
44 value = src.value;
45 is_object_member = src.is_object_member;
46 current_in_array = src.current_in_array;
47 end_of_array = src.end_of_array;
48 return *this;
49 }
50
51 bool isInt64() const { return value->IsInt64(); }
52 bool isUInt64() const { return value->IsUint64(); }
53 bool isDouble() const { return value->IsDouble(); }
54 bool isBool() const { return value->IsBool(); }
55 bool isString() const { return value->IsString(); }
56 bool isArray() const { return value->IsArray(); }
57 bool isObject() const { return value->IsObject(); }
58 bool isNull() const { return value->IsNull(); }
59
60 Int64 getInt64() const { return value->GetInt64(); }
61 UInt64 getUInt64() const { return value->GetUint64(); }
62 double getDouble() const { return value->GetDouble(); }
63 bool getBool() const { return value->GetBool(); }
64 StringRef getString() const { return {value->GetString(), value->GetStringLength()}; }
65
66 size_t sizeOfArray() const { return value->Size(); }
67
68 bool arrayElementByIndex(size_t index)
69 {
70 if (index >= value->Size())
71 return false;
72 setRange(value->Begin() + index, value->End());
73 value = current_in_array++;
74 return true;
75 }
76
77 bool nextArrayElement()
78 {
79 if (current_in_array == end_of_array)
80 return false;
81 value = current_in_array++;
82 return true;
83 }
84
85 size_t sizeOfObject() const { return value->MemberCount(); }
86
87 bool objectMemberByIndex(size_t index)
88 {
89 if (index >= value->MemberCount())
90 return false;
91 setRange(value->MemberBegin() + index, value->MemberEnd());
92 value = &(current_in_object++)->value;
93 return true;
94 }
95
96 bool objectMemberByIndex(size_t index, StringRef & key)
97 {
98 if (index >= value->MemberCount())
99 return false;
100 setRange(value->MemberBegin() + index, value->MemberEnd());
101 key = getKeyImpl(current_in_object);
102 value = &(current_in_object++)->value;
103 return true;
104 }
105
106 bool objectMemberByName(const StringRef & name)
107 {
108 auto it = value->FindMember(name.data);
109 if (it == value->MemberEnd())
110 return false;
111 setRange(it, value->MemberEnd());
112 value = &(current_in_object++)->value;
113 return true;
114 }
115
116 bool nextObjectMember()
117 {
118 if (current_in_object == end_of_object)
119 return false;
120 value = &(current_in_object++)->value;
121 return true;
122 }
123
124 bool nextObjectMember(StringRef & key)
125 {
126 if (current_in_object == end_of_object)
127 return false;
128 key = getKeyImpl(current_in_object);
129 value = &(current_in_object++)->value;
130 return true;
131 }
132
133 bool isObjectMember() const { return is_object_member; }
134
135 StringRef getKey() const
136 {
137 return getKeyImpl(current_in_object - 1);
138 }
139
140 private:
141 void setRange(rapidjson::Value::ConstValueIterator current, rapidjson::Value::ConstValueIterator end)
142 {
143 current_in_array = &*current;
144 end_of_array = &*end;
145 is_object_member = false;
146 }
147
148 void setRange(rapidjson::Value::ConstMemberIterator current, rapidjson::Value::ConstMemberIterator end)
149 {
150 current_in_object = &*current;
151 end_of_object = &*end;
152 is_object_member = true;
153 }
154
155 static StringRef getKeyImpl(const rapidjson::GenericMember<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<>> * member)
156 {
157 const auto & name = member->name;
158 return {name.GetString(), name.GetStringLength()};
159 }
160
161 const rapidjson::Value * value = nullptr;
162 bool is_object_member = false;
163
164 union
165 {
166 const rapidjson::GenericMember<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<>> * current_in_object;
167 const rapidjson::Value * current_in_array;
168 };
169 union
170 {
171 const rapidjson::GenericMember<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<>> * end_of_object;
172 const rapidjson::Value * end_of_array;
173 };
174 };
175
176 Iterator getRoot() { return Iterator{document}; }
177
178 static bool isInt64(const Iterator & it) { return it.isInt64(); }
179 static bool isUInt64(const Iterator & it) { return it.isUInt64(); }
180 static bool isDouble(const Iterator & it) { return it.isDouble(); }
181 static bool isBool(const Iterator & it) { return it.isBool(); }
182 static bool isString(const Iterator & it) { return it.isString(); }
183 static bool isArray(const Iterator & it) { return it.isArray(); }
184 static bool isObject(const Iterator & it) { return it.isObject(); }
185 static bool isNull(const Iterator & it) { return it.isNull(); }
186
187 static Int64 getInt64(const Iterator & it) { return it.getInt64(); }
188 static UInt64 getUInt64(const Iterator & it) { return it.getUInt64(); }
189 static double getDouble(const Iterator & it) { return it.getDouble(); }
190 static bool getBool(const Iterator & it) { return it.getBool(); }
191 static StringRef getString(const Iterator & it) { return it.getString(); }
192
193 static size_t sizeOfArray(const Iterator & it) { return it.sizeOfArray(); }
194 static bool firstArrayElement(Iterator & it) { return it.arrayElementByIndex(0); }
195 static bool arrayElementByIndex(Iterator & it, size_t index) { return it.arrayElementByIndex(index); }
196 static bool nextArrayElement(Iterator & it) { return it.nextArrayElement(); }
197
198 static size_t sizeOfObject(const Iterator & it) { return it.sizeOfObject(); }
199 static bool firstObjectMember(Iterator & it) { return it.objectMemberByIndex(0); }
200 static bool firstObjectMember(Iterator & it, StringRef & first_key) { return it.objectMemberByIndex(0, first_key); }
201 static bool objectMemberByIndex(Iterator & it, size_t index) { return it.objectMemberByIndex(index); }
202 static bool objectMemberByName(Iterator & it, const StringRef & name) { return it.objectMemberByName(name); }
203 static bool nextObjectMember(Iterator & it) { return it.nextObjectMember(); }
204 static bool nextObjectMember(Iterator & it, StringRef & next_key) { return it.nextObjectMember(next_key); }
205 static bool isObjectMember(const Iterator & it) { return it.isObjectMember(); }
206 static StringRef getKey(const Iterator & it) { return it.getKey(); }
207
208private:
209 rapidjson::Document document;
210};
211
212}
213#endif
214