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