/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "json_flatten_parser.h" #include #include #include #include #include #include namespace OHOS { namespace HiviewDFX { namespace { struct Initializer { Initializer() { JsonFlattenParser::Initialize(); } }; } uint8_t JsonFlattenParser::charFilter[JsonFlattenParser::CHAR_RANGE] { 0 }; void JsonFlattenParser::Initialize() { for (char c = '0'; c <= '9'; c++) { charFilter[static_cast(c)] = NUMBER_FLAG; } charFilter[static_cast('-')] = NUMBER_FLAG; charFilter[static_cast('+')] = NUMBER_FLAG; charFilter[static_cast('.')] = NUMBER_FLAG; charFilter[static_cast('"')] = STRING_FLAG; charFilter[static_cast('{')] = BRACKET_FLAG; charFilter[static_cast('[')] = BRACKET_FLAG; } JsonFlattenParser::JsonFlattenParser(const std::string& json) { static Initializer initialize; Parse(json); } void JsonFlattenParser::Parse(const std::string& json) { curPos = 0; kvList.clear(); while (curPos < json.length()) { if (charFilter[static_cast(json[curPos])] != STRING_FLAG) { ++curPos; continue; } std::string key = ParseKey(json); std::string val = ParseValue(json); kvList.emplace_back(key, val); } } std::string JsonFlattenParser::Print(PrintKvHandler handler) { std::string json = "{"; if (!kvList.empty()) { for (size_t i = 0; i < kvList.size() - 1; i++) { json += (handler(kvList[i]) + ","); } json += handler(kvList.back()); } json += "}"; return json; } std::string JsonFlattenParser::ParseKey(const std::string& json) { std::string key; ++curPos; // eat left quotation while (curPos < json.length()) { if (charFilter[static_cast(json[curPos])] == STRING_FLAG) { break; } key.push_back(json[curPos]); ++curPos; } ++curPos; // eat right quotation return key; } std::string JsonFlattenParser::ParseValue(const std::string& json) { std::string value; bool valueParsed = false; while (curPos < json.length()) { int charCode = static_cast(json[curPos]); switch (charFilter[charCode]) { case BRACKET_FLAG: value = ParseBrackets(json, json[curPos]); valueParsed = true; break; case NUMBER_FLAG: value = ParseNumer(json); valueParsed = true; break; case STRING_FLAG: value = ParseString(json); valueParsed = true; break; default: ++curPos; valueParsed = false; break; } if (valueParsed) { break; } } return value; } std::string JsonFlattenParser::ParseNumer(const std::string& json) { std::string number; while (curPos < json.length()) { if (charFilter[static_cast(json[curPos])] != NUMBER_FLAG) { break; } number.push_back(json[curPos]); ++curPos; } return number; } std::string JsonFlattenParser::ParseString(const std::string& json) { std::string txt; txt.push_back(json[curPos++]); while (curPos < json.length()) { if (charFilter[static_cast(json[curPos])] == STRING_FLAG && json[curPos - 1] != '\\') { break; } txt.push_back(json[curPos]); ++curPos; } txt.push_back(json[curPos++]); return txt; } std::string JsonFlattenParser::ParseBrackets(const std::string& json, char leftBracket) { std::string val; char rightBracket = leftBracket + 2; // 2: '[' + 2 = ']', '{' + 2 = '}' int counter = 1; val.push_back(json[curPos++]); while (curPos < json.length()) { if (json[curPos] == leftBracket) { ++counter; } else if (json[curPos] == rightBracket) { --counter; if (counter == 0) { break; } } val.push_back(json[curPos++]); } val.push_back(json[curPos++]); return val; } } // namespace HiviewDFX } // namespace OHOS