1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci
16fb299fa2Sopenharmony_ci#include "json_node.h"
17fb299fa2Sopenharmony_ci
18fb299fa2Sopenharmony_ci#include "log/log.h"
19fb299fa2Sopenharmony_ci#include "utils.h"
20fb299fa2Sopenharmony_ci
21fb299fa2Sopenharmony_cinamespace Updater {
22fb299fa2Sopenharmony_cinamespace {
23fb299fa2Sopenharmony_ciinline const std::unordered_map<uint16_t, NodeType> &GetJsonTypeMap()
24fb299fa2Sopenharmony_ci{
25fb299fa2Sopenharmony_ci    static const std::unordered_map<uint16_t, NodeType> jsonTypeMap {
26fb299fa2Sopenharmony_ci        { cJSON_Object, NodeType::OBJECT }, { cJSON_Array, NodeType::ARRAY }, { cJSON_Number, NodeType::INT },
27fb299fa2Sopenharmony_ci        { cJSON_String, NodeType::STRING }, { cJSON_False, NodeType::BOOL },  { cJSON_True, NodeType::BOOL },
28fb299fa2Sopenharmony_ci        { cJSON_NULL, NodeType::NUL },
29fb299fa2Sopenharmony_ci    };
30fb299fa2Sopenharmony_ci    return jsonTypeMap;
31fb299fa2Sopenharmony_ci}
32fb299fa2Sopenharmony_ci}  // namespace
33fb299fa2Sopenharmony_ci
34fb299fa2Sopenharmony_ciJsonNode::JsonNode() : type_ {NodeType::UNKNOWN}
35fb299fa2Sopenharmony_ci{
36fb299fa2Sopenharmony_ci}
37fb299fa2Sopenharmony_ci
38fb299fa2Sopenharmony_ciJsonNode::JsonNode(const std::string &str, bool needDelete) : JsonNode(cJSON_Parse(str.c_str()), needDelete)
39fb299fa2Sopenharmony_ci{
40fb299fa2Sopenharmony_ci}
41fb299fa2Sopenharmony_ci
42fb299fa2Sopenharmony_ciJsonNode::JsonNode(const Fs::path &path)
43fb299fa2Sopenharmony_ci{
44fb299fa2Sopenharmony_ci    std::string realPath {};
45fb299fa2Sopenharmony_ci    if (!Utils::PathToRealPath(path, realPath)) {
46fb299fa2Sopenharmony_ci        return;
47fb299fa2Sopenharmony_ci    }
48fb299fa2Sopenharmony_ci
49fb299fa2Sopenharmony_ci    std::ifstream ifs(realPath);
50fb299fa2Sopenharmony_ci    if (!ifs.is_open()) {
51fb299fa2Sopenharmony_ci        LOG(ERROR) << realPath << " not exist";
52fb299fa2Sopenharmony_ci        return;
53fb299fa2Sopenharmony_ci    }
54fb299fa2Sopenharmony_ci
55fb299fa2Sopenharmony_ci    // get root node
56fb299fa2Sopenharmony_ci    std::string content {std::istreambuf_iterator<char> {ifs}, {}};
57fb299fa2Sopenharmony_ci    cJSON *root = cJSON_Parse(content.c_str());
58fb299fa2Sopenharmony_ci    if (root == nullptr || cJSON_IsInvalid(root)) {
59fb299fa2Sopenharmony_ci        cJSON_Delete(root);
60fb299fa2Sopenharmony_ci        LOG(ERROR) << path << " contained json invalid";
61fb299fa2Sopenharmony_ci        return;
62fb299fa2Sopenharmony_ci    }
63fb299fa2Sopenharmony_ci
64fb299fa2Sopenharmony_ci    Init(root, true);
65fb299fa2Sopenharmony_ci}
66fb299fa2Sopenharmony_ci
67fb299fa2Sopenharmony_ciJsonNode::JsonNode(const cJSON *root, bool needDelete)
68fb299fa2Sopenharmony_ci{
69fb299fa2Sopenharmony_ci    if (root != nullptr && !cJSON_IsInvalid(root)) {
70fb299fa2Sopenharmony_ci        Init(root, needDelete);
71fb299fa2Sopenharmony_ci        return;
72fb299fa2Sopenharmony_ci    }
73fb299fa2Sopenharmony_ci    LOG(ERROR) << "root is not valid";
74fb299fa2Sopenharmony_ci    type_ = NodeType::UNKNOWN;
75fb299fa2Sopenharmony_ci}
76fb299fa2Sopenharmony_ci
77fb299fa2Sopenharmony_ci
78fb299fa2Sopenharmony_civoid JsonNode::Init(const cJSON *root, bool needDelete)
79fb299fa2Sopenharmony_ci{
80fb299fa2Sopenharmony_ci    if (auto it = GetJsonTypeMap().find(root->type); it != GetJsonTypeMap().end()) {
81fb299fa2Sopenharmony_ci        type_ = it->second;
82fb299fa2Sopenharmony_ci    }
83fb299fa2Sopenharmony_ci    Parse(root);
84fb299fa2Sopenharmony_ci    if (needDelete) {
85fb299fa2Sopenharmony_ci        cJSON_Delete(const_cast<cJSON *>(root));
86fb299fa2Sopenharmony_ci    }
87fb299fa2Sopenharmony_ci}
88fb299fa2Sopenharmony_ci
89fb299fa2Sopenharmony_civoid JsonNode::Parse(const cJSON *root)
90fb299fa2Sopenharmony_ci{
91fb299fa2Sopenharmony_ci    cJSON *element {};
92fb299fa2Sopenharmony_ci    size_ = 1;
93fb299fa2Sopenharmony_ci    switch (type_) {
94fb299fa2Sopenharmony_ci        case NodeType::OBJECT: {
95fb299fa2Sopenharmony_ci            innerObj_ = std::make_optional<NodeMap>();
96fb299fa2Sopenharmony_ci            auto &optNodeMap = std::get<std::optional<NodeMap>>(innerObj_);
97fb299fa2Sopenharmony_ci            cJSON_ArrayForEach(element, root)
98fb299fa2Sopenharmony_ci            {
99fb299fa2Sopenharmony_ci                std::unique_ptr<JsonNode> uPtr = std::make_unique<JsonNode>(element, false);
100fb299fa2Sopenharmony_ci                innerNodesList_.push_back(*uPtr);
101fb299fa2Sopenharmony_ci                (*optNodeMap).emplace(element->string, std::move(uPtr));
102fb299fa2Sopenharmony_ci            }
103fb299fa2Sopenharmony_ci            size_ = static_cast<int>(innerNodesList_.size());
104fb299fa2Sopenharmony_ci            break;
105fb299fa2Sopenharmony_ci        }
106fb299fa2Sopenharmony_ci        case NodeType::ARRAY: {
107fb299fa2Sopenharmony_ci            innerObj_ = std::make_optional<NodeVec>();
108fb299fa2Sopenharmony_ci            auto &optNodeVec = std::get<std::optional<NodeVec>>(innerObj_);
109fb299fa2Sopenharmony_ci            cJSON_ArrayForEach(element, root)
110fb299fa2Sopenharmony_ci            {
111fb299fa2Sopenharmony_ci                std::unique_ptr<JsonNode> uPtr = std::make_unique<JsonNode>(element, false);
112fb299fa2Sopenharmony_ci                innerNodesList_.push_back(*uPtr);
113fb299fa2Sopenharmony_ci                (*optNodeVec).push_back(std::move(uPtr));
114fb299fa2Sopenharmony_ci            }
115fb299fa2Sopenharmony_ci            size_ = static_cast<int>(innerNodesList_.size());
116fb299fa2Sopenharmony_ci            break;
117fb299fa2Sopenharmony_ci        }
118fb299fa2Sopenharmony_ci        case NodeType::INT:
119fb299fa2Sopenharmony_ci            innerObj_ = std::make_optional<int>(root->valueint);
120fb299fa2Sopenharmony_ci            innerNodesList_.push_back(*this);
121fb299fa2Sopenharmony_ci            break;
122fb299fa2Sopenharmony_ci        case NodeType::STRING:
123fb299fa2Sopenharmony_ci            innerObj_ = std::make_optional<std::string>(root->valuestring);
124fb299fa2Sopenharmony_ci            innerNodesList_.push_back(*this);
125fb299fa2Sopenharmony_ci            break;
126fb299fa2Sopenharmony_ci        case NodeType::BOOL:
127fb299fa2Sopenharmony_ci            innerObj_ = std::make_optional<bool>(root->type == cJSON_True);
128fb299fa2Sopenharmony_ci            innerNodesList_.push_back(*this);
129fb299fa2Sopenharmony_ci            break;
130fb299fa2Sopenharmony_ci        case NodeType::NUL:
131fb299fa2Sopenharmony_ci            break;
132fb299fa2Sopenharmony_ci        default:
133fb299fa2Sopenharmony_ci            LOG(ERROR) << "unknown node type";
134fb299fa2Sopenharmony_ci            break;
135fb299fa2Sopenharmony_ci    }
136fb299fa2Sopenharmony_ci    if (root->string) {
137fb299fa2Sopenharmony_ci        key_ = root->string;
138fb299fa2Sopenharmony_ci    }
139fb299fa2Sopenharmony_ci}
140fb299fa2Sopenharmony_ci
141fb299fa2Sopenharmony_ciJsonNode::~JsonNode() = default;
142fb299fa2Sopenharmony_ci
143fb299fa2Sopenharmony_ciJsonNode &JsonNode::operator[](int idx)
144fb299fa2Sopenharmony_ci{
145fb299fa2Sopenharmony_ci    return GetNodeByIdx(innerObj_, size_, idx);
146fb299fa2Sopenharmony_ci}
147fb299fa2Sopenharmony_ci
148fb299fa2Sopenharmony_ciJsonNode &JsonNode::operator[](const std::string &key)
149fb299fa2Sopenharmony_ci{
150fb299fa2Sopenharmony_ci    return GetNodeByKey(innerObj_, key);
151fb299fa2Sopenharmony_ci}
152fb299fa2Sopenharmony_ci
153fb299fa2Sopenharmony_ciconst JsonNode &JsonNode::operator[](int idx) const
154fb299fa2Sopenharmony_ci{
155fb299fa2Sopenharmony_ci    return GetNodeByIdx(innerObj_, size_, idx);
156fb299fa2Sopenharmony_ci}
157fb299fa2Sopenharmony_ci
158fb299fa2Sopenharmony_ciconst JsonNode &JsonNode::operator[](const std::string &key) const
159fb299fa2Sopenharmony_ci{
160fb299fa2Sopenharmony_ci    return GetNodeByKey(innerObj_, key);
161fb299fa2Sopenharmony_ci}
162fb299fa2Sopenharmony_ci
163fb299fa2Sopenharmony_cistd::list<std::reference_wrapper<JsonNode>>::const_iterator JsonNode::begin() const
164fb299fa2Sopenharmony_ci{
165fb299fa2Sopenharmony_ci    return innerNodesList_.cbegin();
166fb299fa2Sopenharmony_ci}
167fb299fa2Sopenharmony_ci
168fb299fa2Sopenharmony_cistd::list<std::reference_wrapper<JsonNode>>::const_iterator JsonNode::end() const
169fb299fa2Sopenharmony_ci{
170fb299fa2Sopenharmony_ci    return innerNodesList_.cend();
171fb299fa2Sopenharmony_ci}
172fb299fa2Sopenharmony_ci}  // namespace Updater