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