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 "json_helper.h"
17 
18 #include "cJSON.h"
19 #include "effect_log.h"
20 
21 namespace OHOS {
22 namespace Media {
23 namespace Effect {
24 
25 namespace {
26 #define EFFECT_JSON_FALSE_RETURN(cond)                                                                  \
27     do {                                                                                                \
28         if (!(cond)) {                                                                                  \
29             EFFECT_LOGE("[%{public}s:%{public}d] Effect json cond false!", __FUNCTION__, __LINE__);     \
30             return false;                                                                               \
31         }                                                                                               \
32     } while (0)
33 
34 #define EFFECT_JSON_FALSE_RETURN_WITH_WORK(cond, work)                                                  \
35     do {                                                                                                \
36         if (!(cond)) {                                                                                  \
37             EFFECT_LOGE("[%{public}s:%{public}d] Effect json cond false!", __FUNCTION__, __LINE__);     \
38             work;                                                                                       \
39             return false;                                                                               \
40         }                                                                                               \
41     } while (0)
42 }
43 
EffectJson(Json * json,bool isRoot)44 EffectJson::EffectJson(Json *json, bool isRoot) : json_(json), isRoot_(isRoot) {}
45 
~EffectJson()46 EffectJson::~EffectJson()
47 {
48     if (json_ != nullptr && isRoot_) {
49         cJSON_Delete(json_);
50     }
51     json_ = nullptr;
52 }
53 
IsBool() const54 bool EffectJson::IsBool() const
55 {
56     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
57     return static_cast<bool>(cJSON_IsBool(json_));
58 }
59 
IsNumber() const60 bool EffectJson::IsNumber() const
61 {
62     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
63     return static_cast<bool>(cJSON_IsNumber(json_));
64 }
65 
IsString() const66 bool EffectJson::IsString() const
67 {
68     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
69     return static_cast<bool>(cJSON_IsString(json_));
70 }
71 
IsArray() const72 bool EffectJson::IsArray() const
73 {
74     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
75     return static_cast<bool>(cJSON_IsArray(json_));
76 }
77 
IsObject() const78 bool EffectJson::IsObject() const
79 {
80     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
81     return static_cast<bool>(cJSON_IsObject(json_));
82 }
83 
IsValid() const84 bool EffectJson::IsValid() const
85 {
86     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
87     return !static_cast<bool>(cJSON_IsInvalid(json_));
88 }
89 
IsNull() const90 bool EffectJson::IsNull() const
91 {
92     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
93     return static_cast<bool>(cJSON_IsNull(json_));
94 }
95 
HasElement(const std::string & key) const96 bool EffectJson::HasElement(const std::string &key) const
97 {
98     EFFECT_JSON_FALSE_RETURN(json_ != nullptr);
99     return static_cast<bool>(cJSON_HasObjectItem(json_, key.c_str()));
100 }
101 
GetElement(const std::string & key)102 EffectJsonPtr EffectJson::GetElement(const std::string &key)
103 {
104     if (!HasElement(key)) {
105         return nullptr;
106     }
107     cJSON *element = cJSON_GetObjectItemCaseSensitive(json_, key.c_str());
108     return std::make_shared<EffectJson>(element, false);
109 }
110 
GetInt()111 int32_t EffectJson::GetInt()
112 {
113     if (!IsNumber()) {
114         return 0;
115     }
116     return static_cast<int32_t>(cJSON_GetNumberValue(json_));
117 }
118 
GetInt(const std::string & key,int32_t defaultValue)119 int32_t EffectJson::GetInt(const std::string &key, int32_t defaultValue)
120 {
121     auto element = GetElement(key);
122     if (element == nullptr || element->IsNull() || !element->IsNumber()) {
123         return defaultValue;
124     }
125 
126     return element->GetInt();
127 }
128 
GetUInt()129 uint32_t EffectJson::GetUInt()
130 {
131     if (!IsNumber()) {
132         return 0;
133     }
134     return static_cast<int32_t>(cJSON_GetNumberValue(json_));
135 }
136 
GetUInt(const std::string & key,uint32_t defaultValue)137 uint32_t EffectJson::GetUInt(const std::string &key, uint32_t defaultValue)
138 {
139     auto element = GetElement(key);
140     if (element == nullptr || element->IsNull() || !element->IsNumber()) {
141         return defaultValue;
142     }
143 
144     return element->GetUInt();
145 }
146 
GetFloat()147 float EffectJson::GetFloat()
148 {
149     if (!IsNumber()) {
150         return 0.0f;
151     }
152     return static_cast<float>(cJSON_GetNumberValue(json_));
153 }
154 
GetFloat(const std::string & key,float defaultValue)155 float EffectJson::GetFloat(const std::string &key, float defaultValue)
156 {
157     auto element = GetElement(key);
158     if (element == nullptr || element->IsNull() || !element->IsNumber()) {
159         return defaultValue;
160     }
161 
162     return element->GetFloat();
163 }
164 
GetDouble()165 double EffectJson::GetDouble()
166 {
167     if (!IsNumber()) {
168         return 0;
169     }
170     return cJSON_GetNumberValue(json_);
171 }
172 
GetDouble(const std::string & key,double defaultValue)173 double EffectJson::GetDouble(const std::string &key, double defaultValue)
174 {
175     auto element = GetElement(key);
176     if (element == nullptr || element->IsNull() || !element->IsNumber()) {
177         return defaultValue;
178     }
179 
180     return element->GetDouble();
181 }
182 
GetBool()183 bool EffectJson::GetBool()
184 {
185     if (!IsBool()) {
186         return false;
187     }
188     return static_cast<bool>(cJSON_IsTrue(json_));
189 }
190 
GetBool(const std::string & key,bool defaultValue)191 bool EffectJson::GetBool(const std::string &key, bool defaultValue)
192 {
193     auto element = GetElement(key);
194     if (element == nullptr || element->IsNull() || !element->IsBool()) {
195         return defaultValue;
196     }
197 
198     return element->GetBool();
199 }
200 
GetString()201 std::string EffectJson::GetString()
202 {
203     if (!IsString()) {
204         return "";
205     }
206     return cJSON_GetStringValue(json_);
207 }
208 
GetString(const std::string & key,const std::string & defaultValue)209 std::string EffectJson::GetString(const std::string &key, const std::string &defaultValue)
210 {
211     auto element = GetElement(key);
212     if (element == nullptr || element->IsNull() || !element->IsString()) {
213         return defaultValue;
214     }
215 
216     return element->GetString();
217 }
218 
GetArray()219 std::vector<EffectJsonPtr> EffectJson::GetArray()
220 {
221     std::vector<EffectJsonPtr> elements;
222     if (!IsArray()) {
223         return elements;
224     }
225 
226     cJSON *element = nullptr;
227     cJSON_ArrayForEach(element, json_) {
228         elements.push_back(std::make_shared<EffectJson>(element, false));
229     }
230     return elements;
231 }
232 
GetArray(const std::string & key)233 std::vector<EffectJsonPtr> EffectJson::GetArray(const std::string &key)
234 {
235     std::vector<EffectJsonPtr> elements;
236     auto element = GetElement(key);
237     if (element == nullptr || element->IsNull() || !element->IsArray()) {
238         return elements;
239     }
240 
241     return element->GetArray();
242 }
243 
DeleteJson(cJSON * json,bool isAllowDelete=true)244 void DeleteJson(cJSON *json, bool isAllowDelete = true)
245 {
246     if (isAllowDelete && json != nullptr) {
247         cJSON_Delete(json);
248     }
249 }
250 
Put(const std::string & key,Json * json,bool isAllowDelete)251 bool EffectJson::Put(const std::string &key, Json *json, bool isAllowDelete)
252 {
253     EFFECT_JSON_FALSE_RETURN(json != nullptr && json_ != nullptr);
254 
255     bool res = static_cast<bool>(cJSON_AddItemToObject(json_, key.c_str(), json));
256     EFFECT_JSON_FALSE_RETURN_WITH_WORK(res, DeleteJson(json, isAllowDelete));
257     return true;
258 }
259 
Put(const std::string & key,EffectJsonPtr & json)260 bool EffectJson::Put(const std::string &key, EffectJsonPtr &json)
261 {
262     EFFECT_JSON_FALSE_RETURN(json != nullptr && json->json_ != nullptr);
263 
264     cJSON *jsonObject = json->json_;
265     bool isAllowDelete = false;
266     if (json->isRoot_) {
267         jsonObject = cJSON_Duplicate(json->json_, true);
268         isAllowDelete = true;
269     }
270     return Put(key, jsonObject, isAllowDelete);
271 }
272 
Put(const std::string & key,int32_t value)273 bool EffectJson::Put(const std::string &key, int32_t value)
274 {
275     return Put(key, static_cast<double>(value));
276 }
277 
Put(const std::string & key,uint32_t value)278 bool EffectJson::Put(const std::string &key, uint32_t value)
279 {
280     return Put(key, static_cast<double>(value));
281 }
282 
Put(const std::string & key,float value)283 bool EffectJson::Put(const std::string &key, float value)
284 {
285     return Put(key, static_cast<double>(value));
286 }
287 
Put(const std::string & key,double value)288 bool EffectJson::Put(const std::string &key, double value)
289 {
290     cJSON *child = cJSON_CreateNumber(value);
291     return Put(key, child);
292 }
293 
Put(const std::string & key,bool value)294 bool EffectJson::Put(const std::string &key, bool value)
295 {
296     cJSON *child = cJSON_CreateBool(value);
297     return Put(key, child);
298 }
299 
Put(const std::string & key,const std::string & value)300 bool EffectJson::Put(const std::string &key, const std::string &value)
301 {
302     cJSON *child = cJSON_CreateString(value.c_str());
303     return Put(key, child);
304 }
305 
Put(const std::string & key,const char * value)306 bool EffectJson::Put(const std::string &key, const char *value)
307 {
308     EFFECT_JSON_FALSE_RETURN(value != nullptr);
309     cJSON *child = cJSON_CreateString(value);
310     return Put(key, child);
311 }
312 
Add(Json * json,bool isAllowDelete) const313 bool EffectJson::Add(Json *json, bool isAllowDelete) const
314 {
315     EFFECT_JSON_FALSE_RETURN(json != nullptr && json_ != nullptr);
316 
317     bool res = static_cast<bool>(cJSON_AddItemToArray(json_, json));
318     EFFECT_JSON_FALSE_RETURN_WITH_WORK(res, DeleteJson(json, isAllowDelete));
319     return true;
320 }
321 
Add(EffectJsonPtr & json) const322 bool EffectJson::Add(EffectJsonPtr &json) const
323 {
324     EFFECT_JSON_FALSE_RETURN(json != nullptr && json->json_ != nullptr);
325 
326     cJSON *jsonObject = json->json_;
327     bool isAllowDelete = false;
328     if (json->isRoot_) {
329         jsonObject = cJSON_Duplicate(json->json_, true);
330         isAllowDelete = true;
331     }
332     return Add(jsonObject, isAllowDelete);
333 }
334 
Add(int32_t value) const335 bool EffectJson::Add(int32_t value) const
336 {
337     return Add(static_cast<double>(value));
338 }
339 
Add(uint32_t value) const340 bool EffectJson::Add(uint32_t value) const
341 {
342     return Add(static_cast<double>(value));
343 }
344 
Add(float value) const345 bool EffectJson::Add(float value) const
346 {
347     return Add(static_cast<double>(value));
348 }
349 
Add(double value) const350 bool EffectJson::Add(double value) const
351 {
352     EFFECT_JSON_FALSE_RETURN(IsArray());
353 
354     cJSON *child = cJSON_CreateNumber(value);
355     return Add(child);
356 }
357 
Add(bool value) const358 bool EffectJson::Add(bool value) const
359 {
360     EFFECT_JSON_FALSE_RETURN(IsArray());
361 
362     cJSON *child = cJSON_CreateBool(value);
363     return Add(child);
364 }
365 
Add(const std::string & value) const366 bool EffectJson::Add(const std::string &value) const
367 {
368     EFFECT_JSON_FALSE_RETURN(IsArray());
369 
370     cJSON *child = cJSON_CreateString(value.c_str());
371     return Add(child);
372 }
373 
Add(const char * value) const374 bool EffectJson::Add(const char *value) const
375 {
376     EFFECT_JSON_FALSE_RETURN(IsArray());
377     EFFECT_JSON_FALSE_RETURN(value != nullptr);
378 
379     cJSON *child = cJSON_CreateString(value);
380     return Add(child);
381 }
382 
Replace(const std::string & key,Json * json,bool jsonObject)383 bool EffectJson::Replace(const std::string &key, Json *json, bool jsonObject)
384 {
385     EFFECT_JSON_FALSE_RETURN(json != nullptr && json_ != nullptr);
386 
387     bool res =
388         static_cast<bool>(cJSON_ReplaceItemInObjectCaseSensitive(json_, key.c_str(), json));
389     EFFECT_JSON_FALSE_RETURN_WITH_WORK(res, DeleteJson(json, jsonObject));
390     return true;
391 }
392 
Replace(const std::string & key,EffectJsonPtr & json)393 bool EffectJson::Replace(const std::string &key, EffectJsonPtr &json)
394 {
395     EFFECT_JSON_FALSE_RETURN(json != nullptr && json->json_ != nullptr);
396 
397     cJSON *jsonObject = json->json_;
398     bool isAllowDelete = false;
399     if (json->isRoot_) {
400         jsonObject = cJSON_Duplicate(json->json_, true);
401         isAllowDelete = true;
402     }
403     return Replace(key, jsonObject, isAllowDelete);
404 }
405 
Replace(const std::string & key,int32_t value)406 bool EffectJson::Replace(const std::string &key, int32_t value)
407 {
408     return Replace(key, static_cast<double>(value));
409 }
410 
Replace(const std::string & key,uint32_t value)411 bool EffectJson::Replace(const std::string &key, uint32_t value)
412 {
413     return Replace(key, static_cast<double>(value));
414 }
415 
Replace(const std::string & key,float value)416 bool EffectJson::Replace(const std::string &key, float value)
417 {
418     return Replace(key, static_cast<double>(value));
419 }
420 
Replace(const std::string & key,double value)421 bool EffectJson::Replace(const std::string &key, double value)
422 {
423     cJSON *child = cJSON_CreateNumber(value);
424     return Replace(key, child);
425 }
426 
Replace(const std::string & key,bool value)427 bool EffectJson::Replace(const std::string &key, bool value)
428 {
429     cJSON *child = cJSON_CreateBool(value);
430     return Replace(key, child);
431 }
432 
Replace(const std::string & key,const std::string & value)433 bool EffectJson::Replace(const std::string &key, const std::string &value)
434 {
435     cJSON *child = cJSON_CreateString(value.c_str());
436     return Replace(key, child);
437 }
438 
Replace(const std::string & key,const char * value)439 bool EffectJson::Replace(const std::string &key, const char *value)
440 {
441     EFFECT_JSON_FALSE_RETURN(value != nullptr);
442     cJSON *child = cJSON_CreateString(value);
443     return Replace(key, child);
444 }
445 
ToString() const446 std::string EffectJson::ToString() const
447 {
448     std::string ret;
449     if (json_ == nullptr) {
450         return ret;
451     }
452     char *jsonData = cJSON_PrintUnformatted(json_);
453     if (jsonData != nullptr) {
454         ret = jsonData;
455         cJSON_free(jsonData);
456     }
457     return ret;
458 }
459 
ParseJsonData(const std::string & data)460 EffectJsonPtr JsonHelper::ParseJsonData(const std::string &data)
461 {
462     cJSON *json = cJSON_Parse(data.c_str());
463     return std::make_shared<EffectJson>(json);
464 }
465 
CreateObject(bool isRoot)466 EffectJsonPtr JsonHelper::CreateObject(bool isRoot)
467 {
468     cJSON *json = cJSON_CreateObject();
469     return std::make_shared<EffectJson>(json, isRoot);
470 }
471 
CreateArray(bool isRoot)472 EffectJsonPtr JsonHelper::CreateArray(bool isRoot)
473 {
474     cJSON *json = cJSON_CreateArray();
475     return std::make_shared<EffectJson>(json, isRoot);
476 }
477 
478 } // namespace Effect
479 } // namespace Media
480 } // namespace OHOS