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