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 "base/json/uobject.h"
17 
18 #include "securec.h"
19 #include "base/log/log_wrapper.h"
20 
21 namespace OHOS {
22 namespace {
23 template<typename T>
HashItem(const std::string & key,const T & value)24 size_t HashItem(const std::string& key, const T& value)
25 {
26     return std::hash<std::string>()(key) + std::hash<T>()(value);
27 }
28 } // namespace
29 
AddItemToObject(const std::string & key,const char * value)30 void UObject::AddItemToObject(const std::string& key, const char* value)
31 {
32     if (value) {
33         stringItems_[key] = value;
34     }
35 }
36 
AddItemToObject(const std::string & key,const std::string & value)37 void UObject::AddItemToObject(const std::string& key, const std::string& value)
38 {
39     stringItems_[key] = value;
40 }
41 
AddItemToObject(const std::string & key,size_t value)42 void UObject::AddItemToObject(const std::string& key, size_t value)
43 {
44     sizetItems_[key] = value;
45 }
46 
AddItemToObject(const std::string & key,int32_t value)47 void UObject::AddItemToObject(const std::string& key, int32_t value)
48 {
49     int32Items_[key] = value;
50 }
51 
AddItemToObject(const std::string & key,int64_t value)52 void UObject::AddItemToObject(const std::string& key, int64_t value)
53 {
54     int64Items_[key] = value;
55 }
56 
AddItemToObject(const std::string & key,double value)57 void UObject::AddItemToObject(const std::string& key, double value)
58 {
59     doubleItems_[key] = value;
60 }
61 
AddItemToObject(const std::string & key,bool value)62 void UObject::AddItemToObject(const std::string& key, bool value)
63 {
64     boolItems_[key] = value;
65 }
66 
AddItemToObject(const std::string & key,const std::shared_ptr<UObject> & value)67 void UObject::AddItemToObject(const std::string& key, const std::shared_ptr<UObject>& value)
68 {
69     if (value) {
70         children_[key] = std::move(value);
71     }
72 }
73 
GetString(const std::string & key) const74 std::string UObject::GetString(const std::string& key) const
75 {
76     auto iter = stringItems_.find(key);
77     if (iter != stringItems_.end()) {
78         return iter->second;
79     }
80     return "";
81 }
82 
GetSizeT(const std::string & key) const83 size_t UObject::GetSizeT(const std::string& key) const
84 {
85     auto sizetIter = sizetItems_.find(key);
86     if (sizetIter != sizetItems_.end()) {
87         return sizetIter->second;
88     }
89     auto doubleIter = doubleItems_.find(key);
90     if (doubleIter != doubleItems_.end()) {
91         return static_cast<size_t>(doubleIter->second);
92     }
93     return 0;
94 }
95 
GetInt32(const std::string & key) const96 int32_t UObject::GetInt32(const std::string& key) const
97 {
98     auto int32Iter = int32Items_.find(key);
99     if (int32Iter != int32Items_.end()) {
100         return int32Iter->second;
101     }
102     auto doubleIter = doubleItems_.find(key);
103     if (doubleIter != doubleItems_.end()) {
104         return static_cast<int32_t>(doubleIter->second);
105     }
106     return 0;
107 }
108 
GetInt64(const std::string & key) const109 int64_t UObject::GetInt64(const std::string& key) const
110 {
111     auto int64Iter = int64Items_.find(key);
112     if (int64Iter != int64Items_.end()) {
113         return int64Iter->second;
114     }
115     auto doubleIter = doubleItems_.find(key);
116     if (doubleIter != doubleItems_.end()) {
117         return static_cast<int64_t>(doubleIter->second);
118     }
119     return 0;
120 }
121 
GetDouble(const std::string & key) const122 double UObject::GetDouble(const std::string& key) const
123 {
124     auto iter = doubleItems_.find(key);
125     if (iter != doubleItems_.end()) {
126         return iter->second;
127     }
128     return 0;
129 }
130 
GetBool(const std::string & key) const131 bool UObject::GetBool(const std::string& key) const
132 {
133     auto iter = boolItems_.find(key);
134     if (iter != boolItems_.end()) {
135         return iter->second;
136     }
137     return false;
138 }
139 
GetObject(const std::string & key) const140 std::shared_ptr<UObject> UObject::GetObject(const std::string& key) const
141 {
142     auto iter = children_.find(key);
143     if (iter != children_.end()) {
144         return iter->second;
145     }
146     return std::make_shared<UObject>();
147 }
148 
Contains(const std::string & key) const149 bool UObject::Contains(const std::string& key) const
150 {
151     return stringItems_.count(key) || sizetItems_.count(key) || int32Items_.count(key) || int64Items_.count(key) ||
152            doubleItems_.count(key) || boolItems_.count(key) || children_.count(key);
153 }
154 
Serialize(char * buffer,int32_t bufferLen)155 void UObject::Serialize(char* buffer, int32_t bufferLen)
156 {
157     if (!buffer) {
158         LOGE("|ERROR| buffer is null");
159         return;
160     }
161 
162     buffer_ = buffer;
163     bufferLen_ = bufferLen;
164     offset_ = 0;
165 
166     for (const auto& item : stringItems_) {
167         WriteKV(item.first, item.second);
168     }
169     for (const auto& item : sizetItems_) {
170         WriteKV(item.first, item.second);
171     }
172     for (const auto& item : int32Items_) {
173         WriteKV(item.first, item.second);
174     }
175     for (const auto& item : int64Items_) {
176         WriteKV(item.first, item.second);
177     }
178     for (const auto& item : doubleItems_) {
179         WriteKV(item.first, item.second);
180     }
181     for (const auto& item : boolItems_) {
182         WriteKV(item.first, item.second);
183     }
184     for (const auto& item : children_) {
185         WriteObj(item.first, item.second);
186     }
187 }
188 
Deserialize(const char * buffer,int32_t bufferLen)189 void UObject::Deserialize(const char* buffer, int32_t bufferLen)
190 {
191     if (!buffer) {
192         LOGE("|ERROR| buffer is null");
193         return;
194     }
195 
196     constBuffer_ = buffer;
197     offset_ = 0;
198 
199     while (offset_ < bufferLen) {
200         ReadKV();
201     }
202 }
203 
Hash()204 size_t UObject::Hash()
205 {
206     hashValue_ = 0;
207 
208     for (const auto& item : stringItems_) {
209         hashValue_ += HashItem(item.first, item.second);
210     }
211     for (const auto& item : sizetItems_) {
212         hashValue_ += HashItem(item.first, item.second);
213     }
214     for (const auto& item : int32Items_) {
215         hashValue_ += HashItem(item.first, item.second);
216     }
217     for (const auto& item : int64Items_) {
218         hashValue_ += HashItem(item.first, item.second);
219     }
220     for (const auto& item : doubleItems_) {
221         hashValue_ += HashItem(item.first, item.second);
222     }
223     for (const auto& item : boolItems_) {
224         hashValue_ += HashItem(item.first, item.second);
225     }
226     for (const auto& item : children_) {
227         hashValue_ += item.second->Hash();
228     }
229 
230     return hashValue_;
231 }
232 
EstimateBufferSize()233 int32_t UObject::EstimateBufferSize()
234 {
235     size_t buffsize = 0;
236 
237     for (auto& item : stringItems_) {
238         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(int32_t) + item.second.length();
239     }
240     for (auto& item : sizetItems_) {
241         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(size_t);
242     }
243     for (auto& item : int32Items_) {
244         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(int32_t);
245     }
246     for (auto& item : int64Items_) {
247         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(int64_t);
248     }
249     for (auto& item : doubleItems_) {
250         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(double);
251     }
252     for (auto& item : boolItems_) {
253         buffsize += sizeof(uint8_t) + sizeof(int32_t) + item.first.length() + sizeof(bool);
254     }
255     for (auto& child : children_) {
256         buffsize += sizeof(uint8_t) + sizeof(int32_t) + child.first.length() + sizeof(int32_t) +
257                     static_cast<size_t>(child.second->EstimateBufferSize());
258     }
259 
260     return static_cast<int32_t>(buffsize);
261 }
262 
WriteChar(char value)263 void UObject::WriteChar(char value)
264 {
265     buffer_[0] = value;
266     offset_++;
267     buffer_++;
268 }
269 
WriteInt32(int32_t value)270 void UObject::WriteInt32(int32_t value)
271 {
272     if (memcpy_s(buffer_, bufferLen_ - offset_, &value, sizeof(int32_t)) != 0) {
273         LOGE("memcpy overflow.");
274         return;
275     }
276     offset_ += static_cast<int32_t>(sizeof(int32_t));
277     buffer_ += sizeof(int32_t);
278 }
279 
WriteSizeT(size_t value)280 void UObject::WriteSizeT(size_t value)
281 {
282     if (memcpy_s(buffer_, bufferLen_ - offset_, &value, sizeof(size_t)) != 0) {
283         LOGE("memcpy overflow.");
284         return;
285     }
286     offset_ += static_cast<int32_t>(sizeof(size_t));
287     buffer_ += sizeof(size_t);
288 }
289 
WriteInt64(int64_t value)290 void UObject::WriteInt64(int64_t value)
291 {
292     if (memcpy_s(buffer_, bufferLen_ - offset_, &value, sizeof(int64_t)) != 0) {
293         LOGE("memcpy overflow.");
294         return;
295     }
296     offset_ += static_cast<int32_t>(sizeof(int64_t));
297     buffer_ += sizeof(int64_t);
298 }
299 
WriteDouble(double value)300 void UObject::WriteDouble(double value)
301 {
302     if (memcpy_s(buffer_, bufferLen_ - offset_, &value, sizeof(double)) != 0) {
303         LOGE("memcpy overflow.");
304         return;
305     }
306     offset_ += static_cast<int32_t>(sizeof(double));
307     buffer_ += sizeof(double);
308 }
309 
WriteString(const std::string & value)310 void UObject::WriteString(const std::string& value)
311 {
312     if (value.empty()) {
313         return;
314     }
315     if (memcpy_s(buffer_, bufferLen_ - offset_, value.c_str(), value.length()) != 0) {
316         LOGE("memcpy overflow.");
317         return;
318     }
319     offset_ += static_cast<int32_t>(value.length());
320     buffer_ += value.length();
321 }
322 
WriteKV(const std::string & key,const std::string & value)323 void UObject::WriteKV(const std::string& key, const std::string& value)
324 {
325     WriteChar(static_cast<char>(ItemType::STRING));
326     WriteInt32(key.length());
327     WriteString(key);
328     WriteInt32(value.length());
329     WriteString(value);
330 }
331 
WriteKV(const std::string & key,size_t value)332 void UObject::WriteKV(const std::string& key, size_t value)
333 {
334     WriteChar(static_cast<char>(ItemType::SIZE_T));
335     WriteInt32(key.length());
336     WriteString(key);
337     WriteSizeT(value);
338 }
339 
WriteKV(const std::string & key,int32_t value)340 void UObject::WriteKV(const std::string& key, int32_t value)
341 {
342     WriteChar(static_cast<char>(ItemType::INT32));
343     WriteInt32(key.length());
344     WriteString(key);
345     WriteInt32(value);
346 }
347 
WriteKV(const std::string & key,int64_t value)348 void UObject::WriteKV(const std::string& key, int64_t value)
349 {
350     WriteChar(static_cast<char>(ItemType::INT64));
351     WriteInt32(key.length());
352     WriteString(key);
353     WriteInt64(value);
354 }
355 
WriteKV(const std::string & key,double value)356 void UObject::WriteKV(const std::string& key, double value)
357 {
358     WriteChar(static_cast<char>(ItemType::DOUBLE));
359     WriteInt32(key.length());
360     WriteString(key);
361     WriteDouble(value);
362 }
363 
WriteKV(const std::string & key,bool value)364 void UObject::WriteKV(const std::string& key, bool value)
365 {
366     WriteChar(static_cast<char>(ItemType::BOOL));
367     WriteInt32(key.length());
368     WriteString(key);
369     WriteChar(value);
370 }
371 
WriteObj(const std::string & key,const std::shared_ptr<UObject> & obj)372 void UObject::WriteObj(const std::string& key, const std::shared_ptr<UObject>& obj)
373 {
374     WriteChar(static_cast<char>(ItemType::UOBJECT));
375     WriteInt32(key.length());
376     WriteString(key);
377     int32_t len = obj->EstimateBufferSize();
378     WriteInt32(len);
379     obj->Serialize(buffer_, len);
380     buffer_ += len;
381     offset_ += len;
382 }
383 
ReadChar()384 char UObject::ReadChar()
385 {
386     char result = constBuffer_[0];
387     offset_++;
388     constBuffer_++;
389     return result;
390 }
391 
ReadInt32()392 int32_t UObject::ReadInt32()
393 {
394     int32_t result;
395     if (memcpy_s(&result, sizeof(int32_t), constBuffer_, sizeof(int32_t)) != 0) {
396         LOGE("memcpy overflow.");
397         return 0;
398     }
399     offset_ += static_cast<int32_t>(sizeof(int32_t));
400     constBuffer_ += sizeof(int32_t);
401     return result;
402 }
403 
ReadInt64()404 int64_t UObject::ReadInt64()
405 {
406     int64_t result;
407     if (memcpy_s(&result, sizeof(int64_t), constBuffer_, sizeof(int64_t)) != 0) {
408         LOGE("memcpy overflow.");
409         return 0;
410     }
411     offset_ += static_cast<int32_t>(sizeof(int64_t));
412     constBuffer_ += sizeof(int64_t);
413     return result;
414 }
415 
ReadSizeT()416 size_t UObject::ReadSizeT()
417 {
418     size_t result;
419     if (memcpy_s(&result, sizeof(size_t), constBuffer_, sizeof(size_t)) != 0) {
420         LOGE("memcpy overflow.");
421         return 0;
422     }
423     offset_ += static_cast<int32_t>(sizeof(size_t));
424     constBuffer_ += sizeof(size_t);
425     return result;
426 }
427 
ReadDouble()428 double UObject::ReadDouble()
429 {
430     double result;
431     if (memcpy_s(&result, sizeof(double), constBuffer_, sizeof(double)) != 0) {
432         LOGE("memcpy overflow.");
433         return 0;
434     }
435     offset_ += static_cast<int32_t>(sizeof(double));
436     constBuffer_ += sizeof(double);
437     return result;
438 }
439 
ReadString(int32_t len)440 std::string UObject::ReadString(int32_t len)
441 {
442     std::string result(constBuffer_, len);
443     offset_ += len;
444     constBuffer_ += len;
445     return result;
446 }
447 
ReadObj(int32_t len)448 std::shared_ptr<UObject> UObject::ReadObj(int32_t len)
449 {
450     std::shared_ptr<UObject> obj = std::make_shared<UObject>();
451     obj->Deserialize(constBuffer_, len);
452     offset_ += len;
453     constBuffer_ += len;
454     return obj;
455 }
456 
ReadKey()457 std::string UObject::ReadKey()
458 {
459     int32_t keyLen = ReadInt32();
460     std::string key = ReadString(keyLen);
461     return key;
462 }
463 
ReadKV()464 void UObject::ReadKV()
465 {
466     ItemType type = static_cast<ItemType>(ReadChar());
467     if (type == ItemType::STRING) {
468         std::string key = ReadKey();
469         int32_t valueLen = ReadInt32();
470         std::string value = ReadString(valueLen);
471         AddItemToObject(key, value);
472     } else if (type == ItemType::SIZE_T) {
473         std::string key = ReadKey();
474         size_t value = ReadSizeT();
475         AddItemToObject(key, value);
476     } else if (type == ItemType::INT32) {
477         std::string key = ReadKey();
478         int32_t value = ReadInt32();
479         AddItemToObject(key, value);
480     } else if (type == ItemType::INT64) {
481         std::string key = ReadKey();
482         int64_t value = ReadInt64();
483         AddItemToObject(key, value);
484     } else if (type == ItemType::DOUBLE) {
485         std::string key = ReadKey();
486         double value = ReadDouble();
487         AddItemToObject(key, value);
488     } else if (type == ItemType::BOOL) {
489         std::string key = ReadKey();
490         bool value = ReadChar();
491         AddItemToObject(key, value);
492     } else if (type == ItemType::UOBJECT) {
493         std::string key = ReadKey();
494         int32_t objLen = ReadInt32();
495         std::shared_ptr<UObject> obj = ReadObj(objLen);
496         AddItemToObject(key, obj);
497     }
498 }
499 } // namespace OHOS
500