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