1/*
2 * Copyright (c) 2023 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 "softbus_adapter_json.h"
17
18#include <vector>
19
20#include "comm_log.h"
21#include "nlohmann/json.hpp"
22#include "securec.h"
23#include "softbus_adapter_mem.h"
24
25
26JsonObj *JSON_CreateObject(void)
27{
28    JsonObj *obj = new (std::nothrow) JsonObj();
29    if (obj == nullptr) {
30        COMM_LOGE(COMM_ADAPTER, "new JsonObj fail");
31        return nullptr;
32    }
33    nlohmann::json *json = new (std::nothrow) nlohmann::json();
34    if (json == nullptr) {
35        COMM_LOGE(COMM_ADAPTER, "new nlohmann fail");
36        delete obj;
37        obj = nullptr;
38        return nullptr;
39    }
40    obj->context = reinterpret_cast<void *>(json);
41    return obj;
42}
43
44void JSON_Delete(JsonObj *obj)
45{
46    if (obj == nullptr) {
47        return;
48    }
49    if (obj->context != nullptr) {
50        nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
51        if (json != nullptr) {
52            delete json;
53        }
54        obj->context = nullptr;
55    }
56    delete obj;
57    obj = nullptr;
58}
59
60void JSON_Free(void *obj)
61{
62    if (obj != nullptr) {
63        SoftBusFree(obj);
64    }
65}
66
67char *JSON_PrintUnformatted(const JsonObj *obj)
68{
69    if (obj == nullptr) {
70        COMM_LOGE(COMM_ADAPTER, "invalid param");
71        return nullptr;
72    }
73    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
74    if (json == nullptr) {
75        COMM_LOGE(COMM_ADAPTER, "invaild json param");
76        return nullptr;
77    }
78    std::string jsonString = json->dump();
79
80    char *result = (char *)SoftBusCalloc(jsonString.length() + 1); /* 1 for '\0' */
81    if (result == nullptr) {
82        COMM_LOGE(COMM_ADAPTER, "malloc array fail");
83        return nullptr;
84    }
85    if (strcpy_s(result, jsonString.length() + 1, jsonString.c_str()) != EOK) {
86        COMM_LOGE(COMM_ADAPTER, "strcpy json string fail");
87        SoftBusFree(result);
88        return nullptr;
89    }
90    return result;
91}
92
93JsonObj *JSON_Parse(const char *str, uint32_t len)
94{
95    JsonObj *obj = JSON_CreateObject();
96    if (obj == nullptr) {
97        COMM_LOGE(COMM_ADAPTER, "create json object fail");
98        return nullptr;
99    }
100    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
101    if (json == nullptr) {
102        JSON_Delete(obj);
103        COMM_LOGE(COMM_ADAPTER, "cast json fail");
104        return nullptr;
105    }
106    std::string jsonString(str, len);
107    nlohmann::json entity = nlohmann::json::parse(jsonString, nullptr, false);
108    if (entity.is_discarded()) {
109        JSON_Delete(obj);
110        COMM_LOGE(COMM_ADAPTER, "parse json fail");
111        return nullptr;
112    }
113    for (auto &item : entity.items()) {
114        (*json)[item.key()] = item.value();
115    }
116    return obj;
117}
118
119bool JSON_AddBoolToObject(JsonObj *obj, const char *key, bool value)
120{
121    if (obj == nullptr || key == nullptr) {
122        COMM_LOGE(COMM_ADAPTER, "invalid param");
123        return false;
124    }
125    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
126    if (json == nullptr) {
127        COMM_LOGE(COMM_ADAPTER, "invaild json param");
128        return false;
129    }
130    (*json)[key] = value;
131    return true;
132}
133
134bool JSON_GetBoolFromOject(const JsonObj *obj, const char *key, bool *value)
135{
136    if (obj == nullptr || key == nullptr || value == nullptr) {
137        COMM_LOGE(COMM_ADAPTER, "invalid param");
138        return false;
139    }
140    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
141    if (json == nullptr) {
142        COMM_LOGE(COMM_ADAPTER, "invaild json param");
143        return false;
144    }
145    nlohmann::json item = (*json)[key];
146    if (!item.is_boolean()) {
147        COMM_LOGE(COMM_ADAPTER, "Cannot find or invalid key. key=%{public}s", key);
148        return false;
149    }
150    *value = item.get<bool>();
151    return true;
152}
153
154template <typename Integer>
155static bool JSON_AddIntegerToObject(JsonObj *obj, const char *key, Integer num)
156{
157    if (obj == nullptr || key == nullptr) {
158        COMM_LOGE(COMM_ADAPTER, "invalid param");
159        return false;
160    }
161    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
162    if (json == nullptr) {
163        COMM_LOGE(COMM_ADAPTER, "invaild json param");
164        return false;
165    }
166    (*json)[key] = num;
167    return true;
168}
169
170template <typename Integer>
171static bool JSON_GetIntegerFromObject(const JsonObj *obj, const char *key, Integer &value)
172{
173    if (obj == nullptr || key == nullptr) {
174        COMM_LOGE(COMM_ADAPTER, "invalid param");
175        return false;
176    }
177    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
178    if (json == nullptr) {
179        COMM_LOGE(COMM_ADAPTER, "invaild json param");
180        return false;
181    }
182    nlohmann::json item = (*json)[key];
183    if (!item.is_number()) {
184        COMM_LOGE(COMM_ADAPTER, "Cannot find or invalid key. key=%{public}s", key);
185        return false;
186    }
187    value = item.get<Integer>();
188    return true;
189}
190
191bool JSON_AddInt16ToObject(JsonObj *obj, const char *key, int16_t value)
192{
193    return JSON_AddIntegerToObject(obj, key, value);
194}
195
196bool JSON_GetInt16FromOject(const JsonObj *obj, const char *key, int16_t *value)
197{
198    if (value == nullptr) {
199        COMM_LOGE(COMM_ADAPTER, "invalid param");
200        return false;
201    }
202    return JSON_GetIntegerFromObject(obj, key, *value);
203}
204
205bool JSON_AddInt32ToObject(JsonObj *obj, const char *key, int32_t value)
206{
207    return JSON_AddIntegerToObject(obj, key, value);
208}
209
210bool JSON_GetInt32FromOject(const JsonObj *obj, const char *key, int32_t *value)
211{
212    if (value == nullptr) {
213        COMM_LOGE(COMM_ADAPTER, "invalid param");
214        return false;
215    }
216    return JSON_GetIntegerFromObject(obj, key, *value);
217}
218
219bool JSON_AddInt64ToObject(JsonObj *obj, const char *key, int64_t value)
220{
221    return JSON_AddIntegerToObject(obj, key, value);
222}
223
224bool JSON_GetInt64FromOject(const JsonObj *obj, const char *key, int64_t *value)
225{
226    if (value == nullptr) {
227        COMM_LOGE(COMM_ADAPTER, "invalid param");
228        return false;
229    }
230    return JSON_GetIntegerFromObject(obj, key, *value);
231}
232
233bool JSON_AddStringToObject(JsonObj *obj, const char *key, const char *value)
234{
235    if (obj == nullptr || key == nullptr || value == nullptr) {
236        COMM_LOGE(COMM_ADAPTER, "invalid param");
237        return false;
238    }
239    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
240    if (json == nullptr) {
241        COMM_LOGE(COMM_ADAPTER, "invaild json param");
242        return false;
243    }
244    (*json)[key] = std::string(value);
245    return true;
246}
247
248bool JSON_GetStringFromOject(const JsonObj *obj, const char *key, char *value, uint32_t size)
249{
250    if (obj == nullptr || key == nullptr || value == nullptr) {
251        COMM_LOGE(COMM_ADAPTER, "invalid param");
252        return false;
253    }
254    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
255    if (json == nullptr) {
256        COMM_LOGE(COMM_ADAPTER, "invaild json param");
257        return false;
258    }
259    nlohmann::json item = (*json)[key];
260    if (!item.is_string()) {
261        COMM_LOGD(COMM_ADAPTER, "cannot find or invalid key. key=%{public}s", key);
262        return false;
263    }
264    std::string valueString = item.get<std::string>();
265    if (strcpy_s(value, size, valueString.c_str()) != EOK) {
266        COMM_LOGE(COMM_ADAPTER, "strcpy value err, key=%{public}s, size=%{public}u, value=%{public}s",
267            key, size, valueString.c_str());
268        return false;
269    }
270    return true;
271}
272
273bool JSON_AddStringArrayToObject(JsonObj *obj, const char *key, const char **value, int32_t len)
274{
275    if (value == nullptr || obj == nullptr || key == nullptr || len <= 0) {
276        COMM_LOGE(COMM_ADAPTER, "input invalid");
277        return false;
278    }
279    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
280    if (json == nullptr) {
281        COMM_LOGE(COMM_ADAPTER, "invaild json param");
282        return false;
283    }
284    nlohmann::json valueStringArray = nlohmann::json::array();
285    for (int32_t i = 0; i < len; i++) {
286        valueStringArray.push_back(value[i]);
287    }
288    (*json)[key] = valueStringArray;
289    return true;
290}
291
292bool JSON_GetStringArrayFromOject(const JsonObj *obj, const char *key, char **value, int32_t *len)
293{
294    if (value == nullptr || obj == nullptr || key == nullptr || len == nullptr || *len <= 0) {
295        COMM_LOGE(COMM_ADAPTER, "input invalid");
296        return false;
297    }
298    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
299    if (json == nullptr) {
300        COMM_LOGE(COMM_ADAPTER, "invaild json param");
301        return false;
302    }
303    nlohmann::json item = (*json)[key];
304    if (!item.is_array()) {
305        COMM_LOGE(COMM_ADAPTER, "cannot find or invalid key. key=%{public}s", key);
306        return false;
307    }
308    if ((unsigned long)(*len) < (unsigned long)item.size()) {
309        COMM_LOGE(COMM_ADAPTER, "item size invalid, size=%{public}lu.", (unsigned long)item.size());
310        return false;
311    }
312    int32_t i = 0;
313    for (nlohmann::json::iterator it = item.begin(); it != item.end(); ++it) {
314        std::string str = it.value().get<std::string>();
315        const char *valueString = str.c_str();
316        uint32_t valueLen = strlen(valueString) + 1;
317        value[i] = reinterpret_cast<char *>(SoftBusCalloc(valueLen));
318        if (value[i] == nullptr) {
319            return false;
320        }
321        if (strcpy_s(value[i], valueLen, valueString) != EOK) {
322            COMM_LOGE(COMM_ADAPTER, "strcpy value err. key=%{public}s, value=%{public}s", key, valueString);
323            return false;
324        }
325        i++;
326    }
327    *len = item.size();
328    return true;
329}
330
331bool JSON_AddBytesToObject(JsonObj *obj, const char *key, uint8_t *value, uint32_t size)
332{
333    if (obj == nullptr || key == nullptr || value == nullptr || size == 0) {
334        COMM_LOGE(COMM_ADAPTER, "input invalid");
335        return false;
336    }
337    std::vector<uint8_t> bytes(value, value + size);
338    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
339    if (json == nullptr) {
340        COMM_LOGE(COMM_ADAPTER, "invalid json param");
341        return false;
342    }
343    (*json)[key] = bytes;
344    return true;
345}
346
347bool JSON_GetBytesFromObject(const JsonObj *obj, const char *key, uint8_t *value, uint32_t bufLen, uint32_t *size)
348{
349    if (obj == nullptr || key == nullptr || value == nullptr || bufLen == 0 || size == nullptr) {
350        COMM_LOGE(COMM_ADAPTER, "input invalid");
351        return false;
352    }
353    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
354    if (json == nullptr) {
355        COMM_LOGE(COMM_ADAPTER, "invaild json param");
356        return false;
357    }
358    if (json->count(key) <= 0) {
359        COMM_LOGE(COMM_ADAPTER, "key does not exist");
360        return false;
361    }
362    std::vector<uint8_t> bytes = (*json)[key];
363    if (bufLen < bytes.size()) {
364        COMM_LOGE(COMM_ADAPTER, "item size invalid, size=%{public}zu", bytes.size());
365        return false;
366    }
367    if (memcpy_s(value, bufLen, bytes.data(), bytes.size()) != EOK) {
368        COMM_LOGE(COMM_ADAPTER, "memcpy fail");
369        return false;
370    }
371    *size = bytes.size();
372    return true;
373}
374
375bool JSON_IsArrayExist(const JsonObj *obj, const char *key)
376{
377    if (obj == nullptr || key == nullptr) {
378        COMM_LOGE(COMM_ADAPTER, "input invalid");
379        return false;
380    }
381    nlohmann::json *json = reinterpret_cast<nlohmann::json *>(obj->context);
382    if (json == nullptr) {
383        COMM_LOGE(COMM_ADAPTER, "invaild json param");
384        return false;
385    }
386    if (!json->contains(key)) {
387        COMM_LOGW(COMM_ADAPTER, "key does not exist");
388        return false;
389    }
390    nlohmann::json item = (*json)[key];
391    return item.is_array();
392}