* 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 <cstddef>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
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<uint8_t>(c)] = NUMBER_FLAG;
}
charFilter[static_cast<uint8_t>('-')] = NUMBER_FLAG;
charFilter[static_cast<uint8_t>('+')] = NUMBER_FLAG;
charFilter[static_cast<uint8_t>('.')] = NUMBER_FLAG;
charFilter[static_cast<uint8_t>('"')] = STRING_FLAG;
charFilter[static_cast<uint8_t>('{')] = BRACKET_FLAG;
charFilter[static_cast<uint8_t>('[')] = 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<uint8_t>(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;
while (curPos < json.length()) {
if (charFilter[static_cast<uint8_t>(json[curPos])] == STRING_FLAG) {
break;
}
key.push_back(json[curPos]);
++curPos;
}
++curPos;
return key;
}
std::string JsonFlattenParser::ParseValue(const std::string& json)
{
std::string value;
bool valueParsed = false;
while (curPos < json.length()) {
int charCode = static_cast<uint8_t>(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<uint8_t>(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<uint8_t>(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;
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;
}
}
}