1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "encoded/raw_data_builder_json_parser.h"
17
18 #include <cinttypes>
19 #include <functional>
20 #include <sstream>
21 #include <vector>
22 #include <unordered_map>
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace EventRaw {
27 namespace {
28 constexpr int NUM_MIN_CHAR = static_cast<int>('0');
29 constexpr int NUM_MAX_CHAR = static_cast<int>('9');
30 constexpr int DOUBLE_QUOTA_CHAR = static_cast<int>('"');
31 constexpr int COLON_CHAR = static_cast<int>(':');
32 constexpr int POINT_CHAR = static_cast<int>('.');
33 constexpr int COMMA_CHAR = static_cast<int>(',');
34 constexpr int LEFT_BRACE_CHAR = static_cast<int>('{');
35 constexpr int RIGHT_BRACE_CHAR = static_cast<int>('}');
36 constexpr int LEFT_BRACKET_CHAR = static_cast<int>('[');
37 constexpr int RIGHT_BRACKET_CHAR = static_cast<int>(']');
38 constexpr int MINUS_CHAR = static_cast<int>('-');
39 constexpr int ESCAPE_CHAR = static_cast<int>('\\');
40 constexpr int POSITIVE_CHAR = static_cast<int>('+');
41 constexpr int SICENTIFIC_NOTAITION_CHAR = static_cast<int>('e');
42
43 template<typename T>
TransStrToType(const std::string & str,T & val)44 static void TransStrToType(const std::string& str, T& val)
45 {
46 std::stringstream ss(str);
47 ss >> val;
48 }
49 }
50
RawDataBuilderJsonParser(const std::string & jsonStr)51 RawDataBuilderJsonParser::RawDataBuilderJsonParser(const std::string& jsonStr)
52 {
53 jsonStr_ = jsonStr;
54 builder_ = std::make_shared<RawDataBuilder>();
55 InitNoneStatus();
56 InitRunStatus();
57 InitKeyParseStatus();
58 InitValueParseStatus();
59 InitStringParseStatus();
60 InitDoubleParseStatus();
61 InitIntParseStatus();
62 InitArrayParseSatus();
63 InitStringItemParseStatus();
64 InitDoubleItemParseStatus();
65 InitIntItemParseStatus();
66 InitEscapeCharParseStatus();
67 InitEscapeCharItemParseStatus();
68 }
69
InitNoneStatus()70 void RawDataBuilderJsonParser::InitNoneStatus()
71 {
72 for (int i = 0; i < CHAR_RANGE; ++i) {
73 statusTabs_[STATUS_NONE][i] = STATUS_NONE;
74 }
75 statusTabs_[STATUS_NONE][LEFT_BRACE_CHAR] = STATUS_RUN;
76 }
77
InitRunStatus()78 void RawDataBuilderJsonParser::InitRunStatus()
79 {
80 for (int i = 0; i < CHAR_RANGE; ++i) {
81 statusTabs_[STATUS_RUN][i] = STATUS_RUN;
82 }
83 statusTabs_[STATUS_RUN][DOUBLE_QUOTA_CHAR] = STATUS_KEY_PARSE;
84 statusTabs_[STATUS_RUN][COLON_CHAR] = STATUS_VALUE_PARSE;
85 statusTabs_[STATUS_RUN][RIGHT_BRACE_CHAR] = STATUS_NONE;
86 }
87
InitKeyParseStatus()88 void RawDataBuilderJsonParser::InitKeyParseStatus()
89 {
90 for (int i = 0; i < CHAR_RANGE; ++i) {
91 statusTabs_[STATUS_KEY_PARSE][i] = STATUS_KEY_PARSE;
92 }
93 statusTabs_[STATUS_KEY_PARSE][DOUBLE_QUOTA_CHAR] = STATUS_RUN;
94 }
95
InitValueParseStatus()96 void RawDataBuilderJsonParser::InitValueParseStatus()
97 {
98 for (int i = 0; i < CHAR_RANGE; ++i) {
99 if ((i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) || (i == MINUS_CHAR)) {
100 statusTabs_[STATUS_VALUE_PARSE][i] = STATUS_INT_PARSE;
101 continue;
102 }
103 statusTabs_[STATUS_VALUE_PARSE][i] = STATUS_VALUE_PARSE;
104 }
105 statusTabs_[STATUS_VALUE_PARSE][DOUBLE_QUOTA_CHAR] = STATUS_STRING_PARSE;
106 statusTabs_[STATUS_VALUE_PARSE][POINT_CHAR] = STATUS_DOUBLE_PARSE;
107 statusTabs_[STATUS_VALUE_PARSE][LEFT_BRACKET_CHAR] = STATUS_ARRAY_PARSE;
108 }
109
InitStringParseStatus()110 void RawDataBuilderJsonParser::InitStringParseStatus()
111 {
112 for (int i = 0; i < CHAR_RANGE; ++i) {
113 statusTabs_[STATUS_STRING_PARSE][i] = STATUS_STRING_PARSE;
114 }
115 statusTabs_[STATUS_STRING_PARSE][DOUBLE_QUOTA_CHAR] = STATUS_RUN;
116 statusTabs_[STATUS_STRING_PARSE][ESCAPE_CHAR] = STATUS_ESCAPE_CHAR_PARSE;
117 }
118
InitDoubleParseStatus()119 void RawDataBuilderJsonParser::InitDoubleParseStatus()
120 {
121 for (int i = 0; i < CHAR_RANGE; ++i) {
122 if (i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) {
123 statusTabs_[STATUS_DOUBLE_PARSE][i] = STATUS_DOUBLE_PARSE;
124 continue;
125 }
126 statusTabs_[STATUS_DOUBLE_PARSE][i] = STATUS_NONE;
127 }
128 statusTabs_[STATUS_DOUBLE_PARSE][POSITIVE_CHAR] = STATUS_DOUBLE_PARSE;
129 statusTabs_[STATUS_DOUBLE_PARSE][SICENTIFIC_NOTAITION_CHAR] = STATUS_DOUBLE_PARSE;
130 statusTabs_[STATUS_DOUBLE_PARSE][COMMA_CHAR] = STATUS_RUN;
131 }
132
InitIntParseStatus()133 void RawDataBuilderJsonParser::InitIntParseStatus()
134 {
135 for (int i = 0; i < CHAR_RANGE; ++i) {
136 if (i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) {
137 statusTabs_[STATUS_INT_PARSE][i] = STATUS_INT_PARSE;
138 continue;
139 }
140 statusTabs_[STATUS_INT_PARSE][i] = STATUS_NONE;
141 }
142 statusTabs_[STATUS_INT_PARSE][POINT_CHAR] = STATUS_DOUBLE_PARSE;
143 statusTabs_[STATUS_INT_PARSE][COMMA_CHAR] = STATUS_RUN;
144 }
145
InitArrayParseSatus()146 void RawDataBuilderJsonParser::InitArrayParseSatus()
147 {
148 for (int i = 0; i < CHAR_RANGE; ++i) {
149 if ((i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) || (i == MINUS_CHAR)) {
150 statusTabs_[STATUS_ARRAY_PARSE][i] = STATUS_INT_ITEM_PARSE;
151 continue;
152 }
153 statusTabs_[STATUS_ARRAY_PARSE][i] = STATUS_ARRAY_PARSE;
154 }
155 statusTabs_[STATUS_ARRAY_PARSE][DOUBLE_QUOTA_CHAR] = STATUS_STRING_ITEM_PARSE;
156 statusTabs_[STATUS_ARRAY_PARSE][POINT_CHAR] = STATUS_DOUBLE_ITEM_PARSE;
157 statusTabs_[STATUS_ARRAY_PARSE][RIGHT_BRACKET_CHAR] = STATUS_RUN;
158 statusTabs_[STATUS_ARRAY_PARSE][COMMA_CHAR] = STATUS_ARRAY_PARSE;
159 }
160
InitStringItemParseStatus()161 void RawDataBuilderJsonParser::InitStringItemParseStatus()
162 {
163 for (int i = 0; i < CHAR_RANGE; ++i) {
164 statusTabs_[STATUS_STRING_ITEM_PARSE][i] = STATUS_STRING_ITEM_PARSE;
165 }
166 statusTabs_[STATUS_STRING_ITEM_PARSE][DOUBLE_QUOTA_CHAR] = STATUS_ARRAY_PARSE;
167 statusTabs_[STATUS_STRING_ITEM_PARSE][COMMA_CHAR] = STATUS_ARRAY_PARSE;
168 statusTabs_[STATUS_STRING_ITEM_PARSE][ESCAPE_CHAR] = STATUS_ESCAPE_CHAR_ITEM_PARSE;
169 }
170
InitDoubleItemParseStatus()171 void RawDataBuilderJsonParser::InitDoubleItemParseStatus()
172 {
173 for (int i = 0; i < CHAR_RANGE; ++i) {
174 if (i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) {
175 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][i] = STATUS_DOUBLE_ITEM_PARSE;
176 continue;
177 }
178 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][i] = STATUS_NONE;
179 }
180 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][POSITIVE_CHAR] = STATUS_DOUBLE_ITEM_PARSE;
181 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][SICENTIFIC_NOTAITION_CHAR] = STATUS_DOUBLE_ITEM_PARSE;
182 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][COMMA_CHAR] = STATUS_ARRAY_PARSE;
183 statusTabs_[STATUS_DOUBLE_ITEM_PARSE][RIGHT_BRACKET_CHAR] = STATUS_RUN;
184 }
185
InitIntItemParseStatus()186 void RawDataBuilderJsonParser::InitIntItemParseStatus()
187 {
188 for (int i = 0; i < CHAR_RANGE; ++i) {
189 if (i >= NUM_MIN_CHAR && i <= NUM_MAX_CHAR) {
190 statusTabs_[STATUS_INT_ITEM_PARSE][i] = STATUS_INT_ITEM_PARSE;
191 continue;
192 }
193 statusTabs_[STATUS_INT_ITEM_PARSE][i] = STATUS_NONE;
194 }
195 statusTabs_[STATUS_INT_ITEM_PARSE][COMMA_CHAR] = STATUS_ARRAY_PARSE;
196 statusTabs_[STATUS_INT_ITEM_PARSE][RIGHT_BRACKET_CHAR] = STATUS_RUN;
197 statusTabs_[STATUS_INT_ITEM_PARSE][POINT_CHAR] = STATUS_DOUBLE_ITEM_PARSE;
198 }
199
InitEscapeCharParseStatus()200 void RawDataBuilderJsonParser::InitEscapeCharParseStatus()
201 {
202 for (int i = 0; i < CHAR_RANGE; ++i) {
203 statusTabs_[STATUS_ESCAPE_CHAR_PARSE][i] = STATUS_STRING_PARSE;
204 }
205 statusTabs_[STATUS_ESCAPE_CHAR_PARSE][ESCAPE_CHAR] = STATUS_ESCAPE_CHAR_PARSE;
206 }
207
InitEscapeCharItemParseStatus()208 void RawDataBuilderJsonParser::InitEscapeCharItemParseStatus()
209 {
210 for (int i = 0; i < CHAR_RANGE; ++i) {
211 statusTabs_[STATUS_ESCAPE_CHAR_ITEM_PARSE][i] = STATUS_STRING_ITEM_PARSE;
212 }
213 statusTabs_[STATUS_ESCAPE_CHAR_ITEM_PARSE][ESCAPE_CHAR] = STATUS_ESCAPE_CHAR_ITEM_PARSE;
214 }
215
HandleStatusNone()216 void RawDataBuilderJsonParser::HandleStatusNone()
217 {
218 AppendValueToBuilder();
219 }
220
HandleStatusKeyParse()221 void RawDataBuilderJsonParser::HandleStatusKeyParse()
222 {
223 if (lastStatus_ == STATUS_KEY_PARSE) {
224 key_.append(1, charactor_);
225 return;
226 }
227 AppendValueToBuilder();
228 key_.clear();
229 }
230
HandleStatusRun()231 void RawDataBuilderJsonParser::HandleStatusRun()
232 {
233 if (lastStatus_ == STATUS_STRING_ITEM_PARSE ||
234 lastStatus_ == STATUS_DOUBLE_ITEM_PARSE ||
235 lastStatus_ == STATUS_INT_ITEM_PARSE) {
236 values_.emplace_back(value_);
237 value_.clear();
238 }
239 if (lastStatus_ == STATUS_STRING_PARSE) { // special for parsing empty string value
240 lastValueParseStatus_ = lastStatus_;
241 }
242 if (lastStatus_ == STATUS_ARRAY_PARSE && (lastValueParseStatus_ != STATUS_STRING_ITEM_PARSE)) { // "KEY":[]
243 lastValueParseStatus_ = STATUS_INT_ITEM_PARSE;
244 }
245 }
246
HandleStatusValueParse()247 void RawDataBuilderJsonParser::HandleStatusValueParse()
248 {
249 value_.clear();
250 if (lastStatus_ == STATUS_RUN) {
251 values_.clear();
252 }
253 if (lastStatus_ == STATUS_STRING_ITEM_PARSE ||
254 lastStatus_ == STATUS_DOUBLE_ITEM_PARSE ||
255 lastStatus_ == STATUS_INT_ITEM_PARSE) {
256 values_.emplace_back(value_);
257 value_.clear();
258 }
259 }
260
HandleStatusArrayParse()261 void RawDataBuilderJsonParser::HandleStatusArrayParse()
262 {
263 if (lastStatus_ == STATUS_RUN) {
264 values_.clear();
265 }
266 if (lastStatus_ == STATUS_STRING_ITEM_PARSE ||
267 lastStatus_ == STATUS_DOUBLE_ITEM_PARSE ||
268 lastStatus_ == STATUS_INT_ITEM_PARSE) {
269 values_.emplace_back(value_);
270 value_.clear();
271 }
272 }
273
HandleStatusStringParse()274 void RawDataBuilderJsonParser::HandleStatusStringParse()
275 {
276 lastValueParseStatus_ = status_;
277 if (lastStatus_ != STATUS_STRING_PARSE && lastStatus_ != STATUS_ESCAPE_CHAR_PARSE) {
278 value_.clear();
279 return;
280 }
281 value_.append(1, charactor_);
282 }
283
HandleStatusStringItemParse()284 void RawDataBuilderJsonParser::HandleStatusStringItemParse()
285 {
286 lastValueParseStatus_ = status_;
287 if (lastStatus_ != STATUS_STRING_ITEM_PARSE && lastStatus_ != STATUS_ESCAPE_CHAR_ITEM_PARSE) {
288 value_.clear();
289 return;
290 }
291 value_.append(1, charactor_);
292 }
293
HandleStatusValueAppend()294 void RawDataBuilderJsonParser::HandleStatusValueAppend()
295 {
296 value_.append(1, charactor_);
297 lastValueParseStatus_ = status_;
298 }
299
BuilderAppendStringValue(const std::string & key,const std::string & value)300 void RawDataBuilderJsonParser::BuilderAppendStringValue(const std::string& key, const std::string& value)
301 {
302 if (builder_ == nullptr) {
303 return;
304 }
305 builder_->AppendValue(key, value);
306 }
307
BuilderAppendIntValue(const std::string & key,const std::string & value)308 void RawDataBuilderJsonParser::BuilderAppendIntValue(const std::string& key, const std::string& value)
309 {
310 if (builder_ == nullptr || value.empty()) {
311 return;
312 }
313 if (value.find("-") != std::string::npos) {
314 int64_t i64Value = 0;
315 TransStrToType(value, i64Value);
316 builder_->AppendValue(key, i64Value);
317 return;
318 }
319 uint64_t u64Value = 0;
320 TransStrToType(value, u64Value);
321 builder_->AppendValue(key, u64Value);
322 }
323
BuilderAppendFloatingValue(const std::string & key,const std::string & value)324 void RawDataBuilderJsonParser::BuilderAppendFloatingValue(const std::string& key, const std::string& value)
325 {
326 if (builder_ == nullptr) {
327 return;
328 }
329 double dlValue = 0.0;
330 TransStrToType(value, dlValue);
331 builder_->AppendValue(key, dlValue);
332 }
333
BuilderAppendStringArrayValue(const std::string & key,const std::vector<std::string> & values)334 void RawDataBuilderJsonParser::BuilderAppendStringArrayValue(const std::string& key,
335 const std::vector<std::string>& values)
336 {
337 if (builder_ == nullptr) {
338 return;
339 }
340 builder_->AppendValue(key, values);
341 }
342
BuilderAppendIntArrayValue(const std::string & key,const std::vector<std::string> & values)343 void RawDataBuilderJsonParser::BuilderAppendIntArrayValue(const std::string& key,
344 const std::vector<std::string>& values)
345 {
346 if (builder_ == nullptr) {
347 return;
348 }
349 if (any_of(values.begin(), values.end(), [] (auto& item) {
350 return !item.empty() && item.find(".") != std::string::npos;
351 })) {
352 BuilderAppendFloatingArrayValue(key, values);
353 return;
354 }
355 if (any_of(values.begin(), values.end(), [] (auto& item) {
356 return !item.empty() && item.find("-") != std::string::npos;
357 })) {
358 std::vector<int64_t> i64Values;
359 int64_t i64Value = 0;
360 for (auto value : values) {
361 if (value.empty()) {
362 continue;
363 }
364 TransStrToType(value, i64Value);
365 i64Values.emplace_back(i64Value);
366 }
367 builder_->AppendValue(key, i64Values);
368 return;
369 }
370 std::vector<uint64_t> u64Values;
371 uint64_t u64Value = 0;
372 for (auto value : values) {
373 TransStrToType(value, u64Value);
374 u64Values.emplace_back(u64Value);
375 }
376 builder_->AppendValue(key, u64Values);
377 }
378
BuilderAppendFloatingArrayValue(const std::string & key,const std::vector<std::string> & values)379 void RawDataBuilderJsonParser::BuilderAppendFloatingArrayValue(const std::string& key,
380 const std::vector<std::string>& values)
381 {
382 if (builder_ == nullptr) {
383 return;
384 }
385 std::vector<double> dlValues;
386 double dlValue = 0.0;
387 for (auto value : values) {
388 TransStrToType(value, dlValue);
389 dlValues.emplace_back(dlValue);
390 }
391 builder_->AppendValue(key, dlValues);
392 }
393
AppendValueToBuilder()394 void RawDataBuilderJsonParser::AppendValueToBuilder()
395 {
396 if (key_.empty()) { // ignore any Key-Value with empty key directly
397 return;
398 }
399 std::unordered_map<int, std::function<void(const std::string&, const std::string&)>> valueAppendFuncs = {
400 {STATUS_STRING_PARSE, [this] (const std::string& key, const std::string& value) {
401 return this->BuilderAppendStringValue(key, value);
402 }
403 },
404 {STATUS_INT_PARSE, [this] (const std::string& key, const std::string& value) {
405 return this->BuilderAppendIntValue(key, value);
406 }
407 },
408 {STATUS_DOUBLE_PARSE, [this] (const std::string& key, const std::string& value) {
409 return this->BuilderAppendFloatingValue(key, value);
410 }
411 }
412 };
413 auto valueIter = valueAppendFuncs.find(lastValueParseStatus_);
414 if (valueIter != valueAppendFuncs.end()) {
415 valueIter->second(key_, value_);
416 return;
417 }
418 std::unordered_map<int,
419 std::function<void(const std::string&, const std::vector<std::string>&)>> arrayValueAppendFuncs = {
420 {STATUS_STRING_ITEM_PARSE, [this] (const std::string& key, const std::vector<std::string>& values) {
421 return this->BuilderAppendStringArrayValue(key, values);
422 }
423 },
424 {STATUS_INT_ITEM_PARSE, [this] (const std::string& key, const std::vector<std::string>& values) {
425 return this->BuilderAppendIntArrayValue(key, values);
426 }
427 },
428 {STATUS_DOUBLE_ITEM_PARSE, [this] (const std::string& key, const std::vector<std::string>& values) {
429 return this->BuilderAppendFloatingArrayValue(key, values);
430 }
431 }
432 };
433 auto arrayValueIter = arrayValueAppendFuncs.find(lastValueParseStatus_);
434 if (arrayValueIter != arrayValueAppendFuncs.end()) {
435 arrayValueIter->second(key_, values_);
436 }
437 }
438
InitParamHandlers(std::unordered_map<int,std::function<void ()>> & handlers)439 void RawDataBuilderJsonParser::InitParamHandlers(std::unordered_map<int, std::function<void()>>& handlers)
440 {
441 handlers.emplace(STATUS_NONE, [this] () {
442 this->HandleStatusNone();
443 });
444 handlers.emplace(STATUS_KEY_PARSE, [this] () {
445 this->HandleStatusKeyParse();
446 });
447 handlers.emplace(STATUS_RUN, [this] () {
448 this->HandleStatusRun();
449 });
450 handlers.emplace(STATUS_VALUE_PARSE, [this] () {
451 this->HandleStatusValueParse();
452 });
453 handlers.emplace(STATUS_ARRAY_PARSE, [this] () {
454 this->HandleStatusArrayParse();
455 });
456 handlers.emplace(STATUS_STRING_PARSE, [this] () {
457 this->HandleStatusStringParse();
458 });
459 handlers.emplace(STATUS_STRING_ITEM_PARSE, [this] () {
460 this->HandleStatusStringItemParse();
461 });
462
463 auto statusValueAppendHandler = [this] () {
464 this->HandleStatusValueAppend();
465 };
466 handlers.emplace(STATUS_DOUBLE_PARSE, statusValueAppendHandler);
467 handlers.emplace(STATUS_INT_PARSE, statusValueAppendHandler);
468 handlers.emplace(STATUS_DOUBLE_ITEM_PARSE, statusValueAppendHandler);
469 handlers.emplace(STATUS_INT_ITEM_PARSE, statusValueAppendHandler);
470 handlers.emplace(STATUS_ESCAPE_CHAR_PARSE, statusValueAppendHandler);
471 handlers.emplace(STATUS_ESCAPE_CHAR_ITEM_PARSE, statusValueAppendHandler);
472 }
473
Parse()474 std::shared_ptr<RawDataBuilder> RawDataBuilderJsonParser::Parse()
475 {
476 if (jsonStr_.empty()) {
477 return builder_;
478 }
479 std::unordered_map<int, std::function<void()>> handlers;
480 InitParamHandlers(handlers);
481 for (auto c : jsonStr_) {
482 charactor_ = static_cast<int>(c);
483 status_ = statusTabs_[status_][charactor_];
484 auto iter = handlers.find(status_);
485 if (iter != handlers.end()) {
486 iter->second();
487 }
488 lastStatus_ = status_;
489 }
490 return builder_;
491 }
492 } // namespace EventRaw
493 } // namespace HiviewDFX
494 } // namespace OHOS