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
18 namespace OHOS {
19 namespace MiscServices {
Unmarshall(const std::string & content)20 bool 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
Marshall(std::string & content) const32 bool 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
GetValue(cJSON * node,const std::string & name,std::string & value)54 bool 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
GetValue(cJSON * node,const std::string & name,int32_t & value)65 bool 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 // LCOV_EXCL_START
GetValue(cJSON * node,const std::string & name,uint32_t & value)76 bool 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
GetValue(cJSON * node,const std::string & name,bool & value)92 bool 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 // LCOV_EXCL_STOP
GetValue(cJSON * node,const std::string & name,Serializable & value)103 bool 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 // LCOV_EXCL_START
GetValue(cJSON * node,const std::string & name,std::vector<std::vector<std::string>> & values)113 bool Serializable::GetValue(cJSON *node, const std::string &name, std::vector<std::vector<std::string>> &values)
114 {
115 auto arrNode = GetSubNode(node, name);
116 if (arrNode == nullptr || !cJSON_IsArray(arrNode)) {
117 IMSA_HILOGD("%{public}s not array", name.c_str());
118 return false;
119 }
120 auto arrLen = cJSON_GetArraySize(arrNode);
121 for (auto i = 0; i < arrLen; i++) {
122 auto subArrNode = cJSON_GetArrayItem(arrNode, i);
123 if (subArrNode == nullptr || !cJSON_IsArray(subArrNode)) {
124 continue;
125 }
126 std::vector<std::string> subStringArr;
127 auto subArrLen = cJSON_GetArraySize(subArrNode);
128 for (auto j = 0; j < subArrLen; j++) {
129 auto strNode = cJSON_GetArrayItem(subArrNode, j);
130 if (strNode == nullptr || !cJSON_IsString(strNode)) {
131 continue;
132 }
133 subStringArr.push_back(strNode->valuestring);
134 }
135 values.push_back(subStringArr);
136 }
137 return true;
138 }
139 // LCOV_EXCL_STOP
SetValue(cJSON * node,const std::string & name,const std::string & value)140 bool Serializable::SetValue(cJSON *node, const std::string &name, const std::string &value)
141 {
142 auto item = cJSON_AddStringToObject(node, name.c_str(), value.c_str());
143 return item != NULL;
144 }
145
SetValue(cJSON * node,const std::string & name,const int32_t & value)146 bool Serializable::SetValue(cJSON *node, const std::string &name, const int32_t &value)
147 {
148 auto item = cJSON_AddNumberToObject(node, name.c_str(), value);
149 return item != NULL;
150 }
151
SetValue(cJSON * node,const std::string & name,const bool & value)152 bool Serializable::SetValue(cJSON *node, const std::string &name, const bool &value)
153 {
154 auto item = cJSON_AddBoolToObject(node, name.c_str(), value);
155 return item != NULL;
156 }
157
SetValue(cJSON * node,const std::string & name,const Serializable & value)158 bool Serializable::SetValue(cJSON *node, const std::string &name, const Serializable &value)
159 {
160 cJSON *item = cJSON_CreateObject();
161 if (item == NULL) {
162 return false;
163 }
164 if (!value.Marshal(item)) {
165 cJSON_Delete(item);
166 return false;
167 }
168 auto ret = cJSON_AddItemToObject(node, name.c_str(), item);
169 if (!ret) {
170 cJSON_Delete(item);
171 }
172 return ret;
173 }
174
SetValue(cJSON * node,const std::string & name,const std::vector<std::string> & values)175 bool Serializable::SetValue(cJSON *node, const std::string &name, const std::vector<std::string> &values)
176 {
177 const char **strArr = new (std::nothrow) const char *[values.size()];
178 if (strArr == nullptr) {
179 return false;
180 }
181 for (size_t i = 0; i < values.size(); i++) {
182 strArr[i] = values[i].c_str();
183 }
184 cJSON *stringArray = cJSON_CreateStringArray(strArr, values.size());
185 if (stringArray == NULL) {
186 delete[] strArr;
187 return false;
188 }
189
190 auto ret = cJSON_AddItemToObject(node, name.c_str(), stringArray);
191 if (!ret) {
192 cJSON_Delete(stringArray);
193 }
194 delete[] strArr;
195 return ret;
196 }
197
SetValue(cJSON * node,const std::string & name,const std::vector<std::vector<std::string>> & values)198 bool Serializable::SetValue(cJSON *node, const std::string &name, const std::vector<std::vector<std::string>> &values)
199 {
200 cJSON *array = cJSON_CreateArray();
201 if (array == NULL) {
202 return false;
203 }
204 for (const auto &value : values) {
205 const char **strArr = new (std::nothrow) const char *[value.size()];
206 if (strArr == nullptr) {
207 continue;
208 }
209 for (size_t i = 0; i < value.size(); i++) {
210 strArr[i] = value[i].c_str();
211 }
212 cJSON *stringArray = cJSON_CreateStringArray(strArr, value.size());
213 if (stringArray == NULL) {
214 delete[] strArr;
215 continue;
216 }
217 auto ret = cJSON_AddItemToArray(array, stringArray);
218 if (!ret) {
219 cJSON_Delete(stringArray);
220 }
221 delete[] strArr;
222 }
223 auto ret = cJSON_AddItemToObject(node, name.c_str(), array);
224 if (!ret) {
225 cJSON_Delete(array);
226 }
227 return ret;
228 }
229
GetSubNode(cJSON * node,const std::string & name)230 cJSON *Serializable::GetSubNode(cJSON *node, const std::string &name)
231 {
232 if (name.empty()) {
233 IMSA_HILOGD("end node.");
234 return node;
235 }
236 if (!cJSON_IsObject(node)) {
237 IMSA_HILOGD("not object, name:%{public}s", name.c_str());
238 return nullptr;
239 }
240 if (!cJSON_HasObjectItem(node, name.c_str())) {
241 IMSA_HILOGD("subNode: %{public}s not contain.", name.c_str());
242 return nullptr;
243 }
244 return cJSON_GetObjectItem(node, name.c_str());
245 }
246 } // namespace MiscServices
247 } // namespace OHOS