1 /*
2  * Copyright (c) 2021-2022 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 "json_flatten_parser.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <functional>
21 #include <iosfwd>
22 #include <string>
23 #include <vector>
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace {
28     struct Initializer {
InitializerOHOS::HiviewDFX::__anon7011a5730110::Initializer29         Initializer()
30         {
31             JsonFlattenParser::Initialize();
32         }
33     };
34 }
35 
36 uint8_t JsonFlattenParser::charFilter[JsonFlattenParser::CHAR_RANGE] { 0 };
37 
Initialize()38 void JsonFlattenParser::Initialize()
39 {
40     for (char c = '0'; c <= '9'; c++) {
41         charFilter[static_cast<uint8_t>(c)] = NUMBER_FLAG;
42     }
43     charFilter[static_cast<uint8_t>('-')] = NUMBER_FLAG;
44     charFilter[static_cast<uint8_t>('+')] = NUMBER_FLAG;
45     charFilter[static_cast<uint8_t>('.')] = NUMBER_FLAG;
46     charFilter[static_cast<uint8_t>('"')] = STRING_FLAG;
47     charFilter[static_cast<uint8_t>('{')] = BRACKET_FLAG;
48     charFilter[static_cast<uint8_t>('[')] = BRACKET_FLAG;
49 }
50 
JsonFlattenParser(const std::string & json)51 JsonFlattenParser::JsonFlattenParser(const std::string& json)
52 {
53     static Initializer initialize;
54     Parse(json);
55 }
56 
Parse(const std::string & json)57 void JsonFlattenParser::Parse(const std::string& json)
58 {
59     curPos = 0;
60     kvList.clear();
61     while (curPos < json.length()) {
62         if (charFilter[static_cast<uint8_t>(json[curPos])] != STRING_FLAG) {
63             ++curPos;
64             continue;
65         }
66         std::string key = ParseKey(json);
67         std::string val = ParseValue(json);
68         kvList.emplace_back(key, val);
69     }
70 }
71 
Print(PrintKvHandler handler)72 std::string JsonFlattenParser::Print(PrintKvHandler handler)
73 {
74     std::string json = "{";
75     if (!kvList.empty()) {
76         for (size_t i = 0; i < kvList.size() - 1; i++) {
77             json += (handler(kvList[i]) + ",");
78         }
79         json += handler(kvList.back());
80     }
81     json += "}";
82     return json;
83 }
84 
ParseKey(const std::string & json)85 std::string JsonFlattenParser::ParseKey(const std::string& json)
86 {
87     std::string key;
88     ++curPos; // eat left quotation
89     while (curPos < json.length()) {
90         if (charFilter[static_cast<uint8_t>(json[curPos])] == STRING_FLAG) {
91             break;
92         }
93         key.push_back(json[curPos]);
94         ++curPos;
95     }
96     ++curPos; // eat right quotation
97     return key;
98 }
99 
ParseValue(const std::string & json)100 std::string JsonFlattenParser::ParseValue(const std::string& json)
101 {
102     std::string value;
103     bool valueParsed = false;
104     while (curPos < json.length()) {
105         int charCode = static_cast<uint8_t>(json[curPos]);
106         switch (charFilter[charCode]) {
107             case BRACKET_FLAG:
108                 value = ParseBrackets(json, json[curPos]);
109                 valueParsed = true;
110                 break;
111             case NUMBER_FLAG:
112                 value = ParseNumer(json);
113                 valueParsed = true;
114                 break;
115             case STRING_FLAG:
116                 value = ParseString(json);
117                 valueParsed = true;
118                 break;
119             default:
120                 ++curPos;
121                 valueParsed = false;
122                 break;
123         }
124         if (valueParsed) {
125             break;
126         }
127     }
128     return value;
129 }
130 
ParseNumer(const std::string & json)131 std::string JsonFlattenParser::ParseNumer(const std::string& json)
132 {
133     std::string number;
134     while (curPos < json.length()) {
135         if (charFilter[static_cast<uint8_t>(json[curPos])] != NUMBER_FLAG) {
136             break;
137         }
138         number.push_back(json[curPos]);
139         ++curPos;
140     }
141     return number;
142 }
143 
ParseString(const std::string & json)144 std::string JsonFlattenParser::ParseString(const std::string& json)
145 {
146     std::string txt;
147     txt.push_back(json[curPos++]);
148     while (curPos < json.length()) {
149         if (charFilter[static_cast<uint8_t>(json[curPos])] == STRING_FLAG &&
150             json[curPos - 1] != '\\') {
151             break;
152         }
153         txt.push_back(json[curPos]);
154         ++curPos;
155     }
156     txt.push_back(json[curPos++]);
157     return txt;
158 }
159 
ParseBrackets(const std::string & json,char leftBracket)160 std::string JsonFlattenParser::ParseBrackets(const std::string& json, char leftBracket)
161 {
162     std::string val;
163     char rightBracket = leftBracket + 2; // 2: '[' + 2 = ']', '{' + 2 = '}'
164     int counter = 1;
165     val.push_back(json[curPos++]);
166     while (curPos < json.length()) {
167         if (json[curPos] == leftBracket) {
168             ++counter;
169         } else if (json[curPos] == rightBracket) {
170             --counter;
171             if (counter == 0) {
172                 break;
173             }
174         }
175         val.push_back(json[curPos++]);
176     }
177     val.push_back(json[curPos++]);
178     return val;
179 }
180 } // namespace HiviewDFX
181 } // namespace OHOS
182