/root/doris/be/src/util/jsonb_utils.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2014, Facebook, Inc. |
3 | | * All rights reserved. |
4 | | * |
5 | | * This source code is licensed under the BSD-style license found in the |
6 | | * LICENSE file in the root directory of this source tree. An additional grant |
7 | | * of patent rights can be found in the PATENTS file in the same directory. |
8 | | * |
9 | | */ |
10 | | |
11 | | /* |
12 | | * This header file defines miscellaneous utility classes. |
13 | | * |
14 | | * @author Tian Xia <tianx@fb.com> |
15 | | * |
16 | | * this file is copied from |
17 | | * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonUtil.h |
18 | | * and modified by Doris |
19 | | */ |
20 | | |
21 | | #ifndef JSONB_JSONBUTIL_H |
22 | | #define JSONB_JSONBUTIL_H |
23 | | |
24 | | #include "common/exception.h" |
25 | | #include "jsonb_document.h" |
26 | | #include "jsonb_stream.h" |
27 | | #include "jsonb_writer.h" |
28 | | |
29 | | namespace doris { |
30 | | |
31 | | #define OUT_BUF_SIZE 1024 |
32 | | |
33 | | /* |
34 | | * JsonbToJson converts an JsonbValue object to a JSON string. |
35 | | */ |
36 | | class JsonbToJson { |
37 | | public: |
38 | 91.3k | JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {} |
39 | | |
40 | | // get json string |
41 | | |
42 | 91.3k | std::string to_json_string(const char* data, size_t size) { |
43 | 91.3k | JsonbDocument* pdoc; |
44 | 91.3k | auto st = doris::JsonbDocument::checkAndCreateDocument(data, size, &pdoc); |
45 | 91.3k | if (!st.ok()) { Branch (45:13): [True: 0, False: 91.3k]
|
46 | 0 | throw Exception(st); |
47 | 0 | } |
48 | 91.3k | return to_json_string(pdoc->getValue()); |
49 | 91.3k | } |
50 | | |
51 | 91.4k | std::string to_json_string(const JsonbValue* val) { |
52 | 91.4k | os_.clear(); |
53 | 91.4k | os_.seekp(0); |
54 | | |
55 | 91.4k | if (val) { Branch (55:13): [True: 91.4k, False: 0]
|
56 | 91.4k | intern_json(val); |
57 | 91.4k | } |
58 | | |
59 | 91.4k | os_.put(0); |
60 | | |
61 | 91.4k | std::string json_string {os_.getBuffer()}; |
62 | 91.4k | return json_string; |
63 | 91.4k | } |
64 | | |
65 | 91.3k | static std::string jsonb_to_json_string(const char* data, size_t size) { |
66 | 91.3k | JsonbToJson jsonb_to_json; |
67 | 91.3k | return jsonb_to_json.to_json_string(data, size); |
68 | 91.3k | } |
69 | | |
70 | | private: |
71 | | // recursively convert JsonbValue |
72 | 4.25M | void intern_json(const JsonbValue* val) { |
73 | 4.25M | switch (val->type()) { |
74 | 88.6k | case JsonbType::T_Null: { Branch (74:9): [True: 88.6k, False: 4.16M]
|
75 | 88.6k | os_.write("null", 4); |
76 | 88.6k | break; |
77 | 0 | } |
78 | 10.7k | case JsonbType::T_True: { Branch (78:9): [True: 10.7k, False: 4.24M]
|
79 | 10.7k | os_.write("true", 4); |
80 | 10.7k | break; |
81 | 0 | } |
82 | 10.7k | case JsonbType::T_False: { Branch (82:9): [True: 10.7k, False: 4.24M]
|
83 | 10.7k | os_.write("false", 5); |
84 | 10.7k | break; |
85 | 0 | } |
86 | 744 | case JsonbType::T_Int8: { Branch (86:9): [True: 744, False: 4.25M]
|
87 | 744 | os_.write(((JsonbInt8Val*)val)->val()); |
88 | 744 | break; |
89 | 0 | } |
90 | 376 | case JsonbType::T_Int16: { Branch (90:9): [True: 376, False: 4.25M]
|
91 | 376 | os_.write(((JsonbInt16Val*)val)->val()); |
92 | 376 | break; |
93 | 0 | } |
94 | 388 | case JsonbType::T_Int32: { Branch (94:9): [True: 388, False: 4.25M]
|
95 | 388 | os_.write(((JsonbInt32Val*)val)->val()); |
96 | 388 | break; |
97 | 0 | } |
98 | 854k | case JsonbType::T_Int64: { Branch (98:9): [True: 854k, False: 3.40M]
|
99 | 854k | os_.write(((JsonbInt64Val*)val)->val()); |
100 | 854k | break; |
101 | 0 | } |
102 | 768k | case JsonbType::T_Double: { Branch (102:9): [True: 768k, False: 3.48M]
|
103 | 768k | os_.write(((JsonbDoubleVal*)val)->val()); |
104 | 768k | break; |
105 | 0 | } |
106 | 0 | case JsonbType::T_Float: { Branch (106:9): [True: 0, False: 4.25M]
|
107 | 0 | os_.write(((JsonbFloatVal*)val)->val()); |
108 | 0 | break; |
109 | 0 | } |
110 | 0 | case JsonbType::T_Int128: { Branch (110:9): [True: 0, False: 4.25M]
|
111 | 0 | os_.write(((JsonbInt128Val*)val)->val()); |
112 | 0 | break; |
113 | 0 | } |
114 | 1.96M | case JsonbType::T_String: { Branch (114:9): [True: 1.96M, False: 2.29M]
|
115 | 1.96M | string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length()); |
116 | 1.96M | break; |
117 | 0 | } |
118 | 0 | case JsonbType::T_Binary: { Branch (118:9): [True: 0, False: 4.25M]
|
119 | 0 | os_.write("\"<BINARY>", 9); |
120 | 0 | os_.write(((JsonbBinaryVal*)val)->getBlob(), ((JsonbBinaryVal*)val)->getBlobLen()); |
121 | 0 | os_.write("<BINARY>\"", 9); |
122 | 0 | break; |
123 | 0 | } |
124 | 249k | case JsonbType::T_Object: { Branch (124:9): [True: 249k, False: 4.00M]
|
125 | 249k | object_to_json((ObjectVal*)val); |
126 | 249k | break; |
127 | 0 | } |
128 | 309k | case JsonbType::T_Array: { Branch (128:9): [True: 309k, False: 3.94M]
|
129 | 309k | array_to_json((ArrayVal*)val); |
130 | 309k | break; |
131 | 0 | } |
132 | 0 | default: Branch (132:9): [True: 0, False: 4.25M]
|
133 | 0 | break; |
134 | 4.25M | } |
135 | 4.25M | } |
136 | | |
137 | 2.71M | void string_to_json(const char* str, size_t len) { |
138 | 2.71M | os_.put('"'); |
139 | 2.71M | if (nullptr == str) { Branch (139:13): [True: 31.2k, False: 2.67M]
|
140 | 31.2k | os_.put('"'); |
141 | 31.2k | return; |
142 | 31.2k | } |
143 | 2.67M | char char_buffer[16]; |
144 | 92.3M | for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) { Branch (144:37): [True: 89.6M, False: 2.67M]
Branch (144:57): [True: 89.6M, False: 288]
|
145 | 89.6M | if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') { Branch (145:17): [True: 89.1M, False: 482k]
Branch (145:45): [True: 88.9M, False: 194k]
Branch (145:61): [True: 88.7M, False: 196k]
|
146 | 88.7M | os_.put(*ptr); |
147 | 88.7M | } else { |
148 | 872k | os_.put('\\'); |
149 | 872k | unsigned char token; |
150 | 872k | switch (token = *ptr) { |
151 | 196k | case '\\': Branch (151:17): [True: 196k, False: 676k]
|
152 | 196k | os_.put('\\'); |
153 | 196k | break; |
154 | 194k | case '\"': Branch (154:17): [True: 194k, False: 678k]
|
155 | 194k | os_.put('\"'); |
156 | 194k | break; |
157 | 96.4k | case '\b': Branch (157:17): [True: 96.4k, False: 776k]
|
158 | 96.4k | os_.put('b'); |
159 | 96.4k | break; |
160 | 96.4k | case '\f': Branch (160:17): [True: 96.4k, False: 776k]
|
161 | 96.4k | os_.put('f'); |
162 | 96.4k | break; |
163 | 96.4k | case '\n': Branch (163:17): [True: 96.4k, False: 776k]
|
164 | 96.4k | os_.put('n'); |
165 | 96.4k | break; |
166 | 96.3k | case '\r': Branch (166:17): [True: 96.3k, False: 776k]
|
167 | 96.3k | os_.put('r'); |
168 | 96.3k | break; |
169 | 96.5k | case '\t': Branch (169:17): [True: 96.5k, False: 776k]
|
170 | 96.5k | os_.put('t'); |
171 | 96.5k | break; |
172 | 0 | default: { Branch (172:17): [True: 0, False: 872k]
|
173 | 0 | int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token); |
174 | 0 | os_.write(char_buffer, char_num); |
175 | 0 | break; |
176 | 0 | } |
177 | 872k | } |
178 | 872k | } |
179 | 89.6M | } |
180 | 2.67M | os_.put('"'); |
181 | 2.67M | } |
182 | | |
183 | | // convert object |
184 | 249k | void object_to_json(const ObjectVal* val) { |
185 | 249k | os_.put('{'); |
186 | | |
187 | 249k | auto iter = val->begin(); |
188 | 249k | auto iter_fence = val->end(); |
189 | | |
190 | 998k | while (iter < iter_fence) { Branch (190:16): [True: 749k, False: 249k]
|
191 | | // write key |
192 | 749k | if (iter->klen()) { Branch (192:17): [True: 717k, False: 31.2k]
|
193 | 717k | string_to_json(iter->getKeyStr(), iter->klen()); |
194 | 717k | } else { |
195 | | // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h |
196 | 31.2k | if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) { Branch (196:21): [True: 31.2k, False: 0]
|
197 | 31.2k | string_to_json(nullptr, 0); |
198 | 31.2k | } else { |
199 | 0 | os_.write(iter->getKeyId()); |
200 | 0 | } |
201 | 31.2k | } |
202 | 749k | os_.put(':'); |
203 | | |
204 | | // convert value |
205 | 749k | intern_json(iter->value()); |
206 | | |
207 | 749k | ++iter; |
208 | 749k | if (iter != iter_fence) { Branch (208:17): [True: 624k, False: 124k]
|
209 | 624k | os_.put(','); |
210 | 624k | } |
211 | 749k | } |
212 | | |
213 | 249k | assert(iter == iter_fence); |
214 | | |
215 | 0 | os_.put('}'); |
216 | 249k | } |
217 | | |
218 | | // convert array to json |
219 | 309k | void array_to_json(const ArrayVal* val) { |
220 | 309k | os_.put('['); |
221 | | |
222 | 309k | auto iter = val->begin(); |
223 | 309k | auto iter_fence = val->end(); |
224 | | |
225 | 3.72M | while (iter != iter_fence) { Branch (225:16): [True: 3.41M, False: 309k]
|
226 | | // convert value |
227 | 3.41M | intern_json((const JsonbValue*)iter); |
228 | 3.41M | ++iter; |
229 | 3.41M | if (iter != iter_fence) { Branch (229:17): [True: 3.10M, False: 309k]
|
230 | 3.10M | os_.put(','); |
231 | 3.10M | } |
232 | 3.41M | } |
233 | | |
234 | 309k | assert(iter == iter_fence); |
235 | | |
236 | 0 | os_.put(']'); |
237 | 309k | } |
238 | | |
239 | | JsonbOutStream os_; |
240 | | char buffer_[OUT_BUF_SIZE]; |
241 | | }; |
242 | | |
243 | | // This class is a utility to create a JsonbValue. |
244 | | template <class OS_TYPE> |
245 | | class JsonbValueCreaterT { |
246 | | public: |
247 | | JsonbValue* operator()(int32_t val) { return operator()((int64_t)val); } |
248 | | |
249 | | JsonbValue* operator()(int64_t val) { |
250 | | writer_.reset(); |
251 | | writer_.writeStartArray(); |
252 | | writer_.writeInt(val); |
253 | | writer_.writeEndArray(); |
254 | | return extractValue(); |
255 | | } |
256 | | JsonbValue* operator()(double val) { |
257 | | writer_.reset(); |
258 | | writer_.writeStartArray(); |
259 | | writer_.writeDouble(val); |
260 | | writer_.writeEndArray(); |
261 | | return extractValue(); |
262 | | } |
263 | | JsonbValue* operator()(const char* str) { return operator()(str, (unsigned int)strlen(str)); } |
264 | | JsonbValue* operator()(const char* str, unsigned int str_len) { |
265 | | writer_.reset(); |
266 | | writer_.writeStartArray(); |
267 | | writer_.writeStartString(); |
268 | | writer_.writeString(str, str_len); |
269 | | writer_.writeEndString(); |
270 | | writer_.writeEndArray(); |
271 | | return extractValue(); |
272 | | } |
273 | | JsonbValue* operator()(bool val) { |
274 | | writer_.reset(); |
275 | | writer_.writeStartArray(); |
276 | | writer_.writeBool(val); |
277 | | writer_.writeEndArray(); |
278 | | return extractValue(); |
279 | | } |
280 | | JsonbValue* operator()() { |
281 | | writer_.reset(); |
282 | | writer_.writeStartArray(); |
283 | | writer_.writeNull(); |
284 | | writer_.writeEndArray(); |
285 | | return extractValue(); |
286 | | } |
287 | | |
288 | | private: |
289 | | JsonbValue* extractValue() { |
290 | | return static_cast<ArrayVal*>( |
291 | | JsonbDocument::createValue(writer_.getOutput()->getBuffer(), |
292 | | (int)writer_.getOutput()->getSize())) |
293 | | ->get(0); |
294 | | } |
295 | | JsonbWriterT<OS_TYPE> writer_; |
296 | | }; |
297 | | using JsonbValueCreater = JsonbValueCreaterT<JsonbOutStream>; |
298 | | } // namespace doris |
299 | | |
300 | | #endif // JSONB_JSONBUTIL_H |