1/*
2 * Copyright (c) 2024 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 "serializable.h"
17
18namespace OHOS {
19namespace MiscServices {
20bool Serializable::Unmarshall(const std::string &content)
21{
22    auto root = cJSON_Parse(content.c_str());
23    if (root == NULL) {
24        IMSA_HILOGE("%{public}s: parse failed!", content.c_str());
25        return false;
26    }
27    auto ret = Unmarshal(root);
28    cJSON_Delete(root);
29    return ret;
30}
31
32bool Serializable::Marshall(std::string &content) const
33{
34    cJSON *root = cJSON_CreateObject();
35    if (root == NULL) {
36        return false;
37    }
38    auto ret = Marshal(root);
39    if (!ret) {
40        cJSON_Delete(root);
41        return false;
42    }
43    auto str = cJSON_PrintUnformatted(root);
44    if (str == NULL) {
45        cJSON_Delete(root);
46        return false;
47    }
48    content = str;
49    cJSON_Delete(root);
50    cJSON_free(str);
51    return true;
52}
53
54bool Serializable::GetValue(cJSON *node, const std::string &name, std::string &value)
55{
56    auto subNode = GetSubNode(node, name);
57    if (subNode == nullptr || !cJSON_IsString(subNode)) {
58        IMSA_HILOGD("%{public}s not string!", name.c_str());
59        return false;
60    }
61    value = subNode->valuestring;
62    return true;
63}
64
65bool Serializable::GetValue(cJSON *node, const std::string &name, int32_t &value)
66{
67    auto subNode = GetSubNode(node, name);
68    if (subNode == nullptr || !cJSON_IsNumber(subNode)) {
69        IMSA_HILOGD("%{public}s not number!", name.c_str());
70        return false;
71    }
72    value = subNode->valueint;
73    return true;
74}
75
76bool Serializable::GetValue(cJSON *node, const std::string &name, uint32_t &value)
77{
78    auto subNode = GetSubNode(node, name);
79    if (!cJSON_IsNumber(subNode)) {
80        IMSA_HILOGD("%{public}s not number", name.c_str());
81        return false;
82    }
83    // Make sure it's not negative
84    if (subNode->valueint < 0) {
85        IMSA_HILOGD("%{public}s is negative", name.c_str());
86        return false;
87    }
88    value = static_cast<uint32_t>(subNode->valueint);
89    return true;
90}
91
92bool Serializable::GetValue(cJSON *node, const std::string &name, bool &value)
93{
94    auto subNode = GetSubNode(node, name);
95    if (subNode == nullptr || !cJSON_IsBool(subNode)) {
96        IMSA_HILOGD("%{public}s not bool", name.c_str());
97        return false;
98    }
99    value = subNode->type == cJSON_True;
100    return true;
101}
102
103bool Serializable::GetValue(cJSON *node, const std::string &name, Serializable &value)
104{
105    auto object = GetSubNode(node, name);
106    if (object == nullptr || !cJSON_IsObject(object)) {
107        IMSA_HILOGD("%{public}s not object", name.c_str());
108        return false;
109    }
110    return value.Unmarshal(object);
111}
112
113bool Serializable::SetValue(cJSON *node, const std::string &name, const std::string &value)
114{
115    auto item = cJSON_AddStringToObject(node, name.c_str(), value.c_str());
116    return item != NULL;
117}
118
119bool Serializable::SetValue(cJSON *node, const std::string &name, const int32_t &value)
120{
121    auto item = cJSON_AddNumberToObject(node, name.c_str(), value);
122    return item != NULL;
123}
124
125cJSON *Serializable::GetSubNode(cJSON *node, const std::string &name)
126{
127    if (name.empty()) {
128        IMSA_HILOGD("end node.");
129        return node;
130    }
131    if (!cJSON_IsObject(node)) {
132        IMSA_HILOGD("not object, name:%{public}s", name.c_str());
133        return nullptr;
134    }
135    if (!cJSON_HasObjectItem(node, name.c_str())) {
136        IMSA_HILOGD("subNode: %{public}s not contain.", name.c_str());
137        return nullptr;
138    }
139    return cJSON_GetObjectItem(node, name.c_str());
140}
141} // namespace MiscServices
142} // namespace OHOS