1/*
2 * Copyright (c) 2021 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 "base/json/json_util.h"
17
18#include "cJSON.h"
19
20namespace OHOS::Ace {
21
22JsonValue::JsonValue(JsonObject* object) : object_(object) {}
23
24JsonValue::JsonValue(JsonObject* object, bool isRoot) : object_(object), isRoot_(isRoot) {}
25
26JsonValue::~JsonValue()
27{
28    if (object_ != nullptr && isRoot_) {
29        cJSON_Delete(object_);
30    }
31    object_ = nullptr;
32}
33
34bool JsonValue::IsBool() const
35{
36    return cJSON_IsBool(object_);
37}
38
39bool JsonValue::IsNumber() const
40{
41    return cJSON_IsNumber(object_);
42}
43
44bool JsonValue::IsString() const
45{
46    return cJSON_IsString(object_);
47}
48
49bool JsonValue::IsArray() const
50{
51    return cJSON_IsArray(object_);
52}
53
54bool JsonValue::IsObject() const
55{
56    return cJSON_IsObject(object_);
57}
58
59bool JsonValue::IsValid() const
60{
61    return (object_ != nullptr) && !cJSON_IsInvalid(object_);
62}
63
64bool JsonValue::IsNull() const
65{
66    return (object_ == nullptr) || cJSON_IsNull(object_);
67}
68
69bool JsonValue::Contains(const std::string& key) const
70{
71    return cJSON_HasObjectItem(object_, key.c_str());
72}
73
74bool JsonValue::GetBool() const
75{
76    return cJSON_IsTrue(object_) != 0;
77}
78
79bool JsonValue::GetBool(const std::string& key, bool defaultValue) const
80{
81    if (Contains(key) && GetValue(key)->IsBool()) {
82        return GetValue(key)->GetBool();
83    }
84    return defaultValue;
85}
86
87int32_t JsonValue::GetInt() const
88{
89    return static_cast<int32_t>((object_ == nullptr) ? 0 : object_->valuedouble);
90}
91
92uint32_t JsonValue::GetUInt() const
93{
94    return static_cast<uint32_t>((object_ == nullptr) ? 0 : object_->valuedouble);
95}
96
97int64_t JsonValue::GetInt64() const
98{
99    return static_cast<int64_t>((object_ == nullptr) ? 0 : object_->valuedouble);
100}
101
102double JsonValue::GetDouble() const
103{
104    return (object_ == nullptr) ? 0.0 : object_->valuedouble;
105}
106
107double JsonValue::GetDouble(const std::string& key, double defaultVal) const
108{
109    auto value = GetValue(key);
110    if (value && value->IsNumber()) {
111        return value->GetDouble();
112    }
113    return defaultVal;
114}
115
116std::string JsonValue::GetString() const
117{
118    return ((object_ == nullptr) || (object_->valuestring == nullptr)) ? "" : std::string(object_->valuestring);
119}
120
121std::unique_ptr<JsonValue> JsonValue::GetNext() const
122{
123    if (object_ == nullptr) {
124        return std::make_unique<JsonValue>(nullptr);
125    }
126    return std::make_unique<JsonValue>(object_->next);
127}
128
129std::unique_ptr<JsonValue> JsonValue::GetChild() const
130{
131    if (object_ == nullptr) {
132        return std::make_unique<JsonValue>(nullptr);
133    }
134    return std::make_unique<JsonValue>(object_->child);
135}
136
137std::string JsonValue::GetKey() const
138{
139    return ((object_ == nullptr) || (object_->string == nullptr)) ? "" : std::string(object_->string);
140}
141std::unique_ptr<JsonValue> JsonValue::GetValue(const std::string& key) const
142{
143    return std::make_unique<JsonValue>(cJSON_GetObjectItem(object_, key.c_str()));
144}
145
146std::unique_ptr<JsonValue> JsonValue::GetObject(const std::string& key) const
147{
148    if (Contains(key) && GetValue(key)->IsObject()) {
149        return GetValue(key);
150    }
151    return std::make_unique<JsonValue>();
152}
153
154int32_t JsonValue::GetArraySize() const
155{
156    return cJSON_GetArraySize(object_);
157}
158
159std::unique_ptr<JsonValue> JsonValue::GetArrayItem(int32_t index) const
160{
161    return std::make_unique<JsonValue>(cJSON_GetArrayItem(object_, index));
162}
163
164bool JsonValue::Put(const char* key, const char* value)
165{
166    if (!value || !key) {
167        return false;
168    }
169
170    cJSON* child = cJSON_CreateString(value);
171    if (child == nullptr) {
172        return false;
173    }
174    cJSON_AddItemToObject(object_, key, child);
175    return true;
176}
177
178bool JsonValue::PutFixedAttr(const char* key, const char* value,
179    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
180{
181    if (filter.CheckFixedAttr(attr)) {
182        return Put(key, value);
183    }
184    return false;
185}
186
187bool JsonValue::PutExtAttr(const char* key, const char* value, const NG::InspectorFilter& filter)
188{
189    if (filter.CheckExtAttr(key)) {
190        return Put(key, value);
191    }
192    return false;
193}
194
195const JsonObject* JsonValue::GetJsonObject() const
196{
197    return object_;
198}
199
200bool JsonValue::Put(const char* key, const std::unique_ptr<JsonValue>& value)
201{
202    if (!value || !key) {
203        return false;
204    }
205    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
206    if (jsonObject == nullptr) {
207        return false;
208    }
209
210    cJSON_AddItemToObject(object_, key, jsonObject);
211    return true;
212}
213
214bool JsonValue::PutFixedAttr(const char* key, const std::unique_ptr<JsonValue>& value,
215    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
216{
217    if (filter.CheckFixedAttr(attr)) {
218        return Put(key, value);
219    }
220    return false;
221}
222
223bool JsonValue::PutExtAttr(const char* key, const std::unique_ptr<JsonValue>& value,
224    const NG::InspectorFilter& filter)
225{
226    if (filter.CheckExtAttr(key)) {
227        return Put(key, value);
228    }
229    return false;
230}
231
232// add item to array
233bool JsonValue::Put(const std::unique_ptr<JsonValue>& value)
234{
235    if (!value) {
236        return false;
237    }
238    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
239    if (jsonObject == nullptr) {
240        return false;
241    }
242
243    cJSON_AddItemToArray(object_, jsonObject);
244    return true;
245}
246
247bool JsonValue::Put(const char* key, size_t value)
248{
249    if (key == nullptr) {
250        return false;
251    }
252
253    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
254    if (child == nullptr) {
255        return false;
256    }
257    cJSON_AddItemToObject(object_, key, child);
258    return true;
259}
260
261bool JsonValue::PutFixedAttr(const char* key, size_t value,
262    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
263{
264    if (filter.CheckFixedAttr(attr)) {
265        return Put(key, value);
266    }
267    return false;
268}
269
270bool JsonValue::PutExtAttr(const char* key, size_t value, const NG::InspectorFilter& filter)
271{
272    if (filter.CheckExtAttr(key)) {
273        return Put(key, value);
274    }
275    return false;
276}
277
278bool JsonValue::Put(const char* key, int32_t value)
279{
280    if (key == nullptr) {
281        return false;
282    }
283
284    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
285    if (child == nullptr) {
286        return false;
287    }
288    cJSON_AddItemToObject(object_, key, child);
289    return true;
290}
291
292bool JsonValue::PutFixedAttr(const char* key, int32_t value,
293    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
294{
295    if (filter.CheckFixedAttr(attr)) {
296        return Put(key, value);
297    }
298    return false;
299}
300
301bool JsonValue::PutExtAttr(const char* key, int32_t value, const NG::InspectorFilter& filter)
302{
303    if (filter.CheckExtAttr(key)) {
304        return Put(key, value);
305    }
306    return false;
307}
308
309bool JsonValue::Put(const char* key, int64_t value)
310{
311    return Put(key, static_cast<double>(value));
312}
313
314bool JsonValue::PutFixedAttr(const char* key, int64_t value,
315    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
316{
317    if (filter.CheckFixedAttr(attr)) {
318        return Put(key, value);
319    }
320    return false;
321}
322
323bool JsonValue::PutExtAttr(const char* key, int64_t value, const NG::InspectorFilter& filter)
324{
325    if (filter.CheckExtAttr(key)) {
326        return Put(key, value);
327    }
328    return false;
329}
330
331bool JsonValue::Put(const char* key, double value)
332{
333    if (key == nullptr) {
334        return false;
335    }
336
337    cJSON* child = cJSON_CreateNumber(value);
338    if (child == nullptr) {
339        return false;
340    }
341    cJSON_AddItemToObject(object_, key, child);
342    return true;
343}
344
345bool JsonValue::PutFixedAttr(const char* key, double value,
346    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
347{
348    if (filter.CheckFixedAttr(attr)) {
349        return Put(key, value);
350    }
351    return false;
352}
353
354bool JsonValue::PutExtAttr(const char* key, double value, const NG::InspectorFilter& filter)
355{
356    if (filter.CheckExtAttr(key)) {
357        return Put(key, value);
358    }
359    return false;
360}
361
362JsonObject* JsonValue::ReleaseJsonObject()
363{
364    if (!isRoot_) {
365        return nullptr;
366    }
367    JsonObject* object = object_;
368    object_ = nullptr;
369    return object;
370}
371
372bool JsonValue::PutRef(const char* key, std::unique_ptr<JsonValue>&& value)
373{
374    if (key == nullptr || value == nullptr) {
375        return false;
376    }
377    /*
378    * If value is root, it controls the lifecycle of JsonObject, we can just move it into current object
379    * Else we need to copy the JsonObject and put the new object in current object
380    */
381    if (value->isRoot_) {
382        cJSON_AddItemToObject(object_, key, value->ReleaseJsonObject());
383        return true;
384    } else {
385        std::unique_ptr<JsonValue> lValue = std::move(value);
386        return Put(key, lValue);
387    }
388}
389
390bool JsonValue::PutRef(std::unique_ptr<JsonValue>&& value)
391{
392    if (value == nullptr) {
393        return false;
394    }
395    /*
396    * If value is root, it controls the lifecycle of JsonObject, we can just move it into current object
397    * Else we need to copy the JsonObject and put the new object in current object
398    */
399    if (value->isRoot_) {
400        cJSON_AddItemToArray(object_, value->ReleaseJsonObject());
401        return true;
402    } else {
403        std::unique_ptr<JsonValue> lValue = std::move(value);
404        return Put(lValue);
405    }
406}
407
408bool JsonValue::Replace(const char* key, double value)
409{
410    if (key == nullptr) {
411        return false;
412    }
413
414    cJSON* child = cJSON_CreateNumber(value);
415    if (child == nullptr) {
416        return false;
417    }
418    if (!cJSON_ReplaceItemInObject(object_, key, child)) {
419        cJSON_Delete(child);
420        return false;
421    }
422    return true;
423}
424
425bool JsonValue::Put(const char* key, bool value)
426{
427    if (key == nullptr) {
428        return false;
429    }
430
431    cJSON* child = cJSON_CreateBool(value);
432    if (child == nullptr) {
433        return false;
434    }
435    cJSON_AddItemToObject(object_, key, child);
436    return true;
437}
438
439bool JsonValue::PutFixedAttr(const char* key, bool value,
440    const NG::InspectorFilter& filter, NG::FixedAttrBit attr)
441{
442    if (filter.CheckFixedAttr(attr)) {
443        return Put(key, value);
444    }
445    return false;
446}
447
448bool JsonValue::PutExtAttr(const char* key, bool value, const NG::InspectorFilter& filter)
449{
450    if (filter.CheckExtAttr(key)) {
451        return Put(key, value);
452    }
453    return false;
454}
455
456bool JsonValue::Replace(const char* key, bool value)
457{
458    if (key == nullptr) {
459        return false;
460    }
461
462    cJSON* child = cJSON_CreateBool(value);
463    if (child == nullptr) {
464        return false;
465    }
466    if (!cJSON_ReplaceItemInObject(object_, key, child)) {
467        cJSON_Delete(child);
468        return false;
469    }
470    return true;
471}
472
473bool JsonValue::Replace(const char* key, const char* value)
474{
475    if ((value == nullptr) || (key == nullptr)) {
476        return false;
477    }
478
479    cJSON* child = cJSON_CreateString(value);
480    if (child == nullptr) {
481        return false;
482    }
483    if (!cJSON_ReplaceItemInObject(object_, key, child)) {
484        cJSON_Delete(child);
485        return false;
486    }
487    return true;
488}
489
490bool JsonValue::Replace(const char* key, int32_t value)
491{
492    if (key == nullptr) {
493        return false;
494    }
495
496    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
497    if (child == nullptr) {
498        return false;
499    }
500    if (!cJSON_ReplaceItemInObject(object_, key, child)) {
501        cJSON_Delete(child);
502        return false;
503    }
504    return true;
505}
506
507bool JsonValue::Replace(const char* key, const std::unique_ptr<JsonValue>& value)
508{
509    if ((value == nullptr) || (key == nullptr)) {
510        return false;
511    }
512    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
513    if (jsonObject == nullptr) {
514        return false;
515    }
516
517    if (!cJSON_ReplaceItemInObject(object_, key, jsonObject)) {
518        cJSON_Delete(jsonObject);
519        return false;
520    }
521    return true;
522}
523
524bool JsonValue::Delete(const char* key)
525{
526    if (key == nullptr) {
527        return false;
528    }
529    cJSON_DeleteItemFromObject(object_, key);
530    return true;
531}
532
533std::string JsonValue::ToString()
534{
535    std::string result;
536    if (!object_) {
537        return result;
538    }
539
540    // It is null-terminated.
541    char* unformatted = cJSON_PrintUnformatted(object_);
542    if (unformatted != nullptr) {
543        result = unformatted;
544        cJSON_free(unformatted);
545    }
546    return result;
547}
548
549std::string JsonValue::GetString(const std::string& key, const std::string& defaultVal) const
550{
551    auto value = GetValue(key);
552    if (value && value->IsString()) {
553        return value->GetString();
554    }
555    return defaultVal;
556}
557
558int32_t JsonValue::GetInt(const std::string& key, int32_t defaultVal) const
559{
560    auto value = GetValue(key);
561    if (value && value->IsNumber()) {
562        return value->GetInt();
563    }
564    return defaultVal;
565}
566
567uint32_t JsonValue::GetUInt(const std::string& key, uint32_t defaultVal) const
568{
569    auto value = GetValue(key);
570    if (value && value->IsNumber()) {
571        return value->GetUInt();
572    }
573    return defaultVal;
574}
575
576int64_t JsonValue::GetInt64(const std::string& key, int64_t defaultVal) const
577{
578    auto value = GetValue(key);
579    if (value && value->IsNumber()) {
580        return value->GetInt64();
581    }
582    return defaultVal;
583}
584
585std::unique_ptr<JsonValue> JsonUtil::ParseJsonData(const char* data, const char** parseEnd)
586{
587    return std::make_unique<JsonValue>(cJSON_ParseWithOpts(data, parseEnd, true), true);
588}
589
590std::unique_ptr<JsonValue> JsonUtil::ParseJsonString(const std::string& content, const char** parseEnd)
591{
592    return ParseJsonData(content.c_str(), parseEnd);
593}
594
595std::unique_ptr<JsonValue> JsonUtil::Create(bool isRoot)
596{
597    return std::make_unique<JsonValue>(cJSON_CreateObject(), isRoot);
598}
599
600std::unique_ptr<JsonValue> JsonUtil::CreateArray(bool isRoot)
601{
602    return std::make_unique<JsonValue>(cJSON_CreateArray(), isRoot);
603}
604
605} // namespace OHOS::Ace
606