1 /*
2 * Copyright (C) 2022 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 #include "property.h"
16 #include "media_log.h"
17 #include "mtp_packet_tools.h"
18 using namespace std;
19 namespace OHOS {
20 namespace Media {
21 static const std::map<uint32_t, std::string> FormMap = {
22     { Property::Form::None, "None" },
23     { Property::Form::Range, "Range" },
24     { Property::Form::Enum, "Enum" },
25     { Property::Form::DateTime, "DateTime" },
26 };
27 
Value()28 Property::Value::Value()
29 {
30     bin_.ui128[OFFSET_0] = 0;
31     bin_.ui128[OFFSET_1] = 0;
32     bin_.ui128[OFFSET_2] = 0;
33     bin_.ui128[OFFSET_3] = 0;
34 }
35 
Dump(uint32_t valueType)36 void Property::Value::Dump(uint32_t valueType)
37 {
38     MEDIA_DEBUG_LOG("%{private}s", ToString(valueType).c_str());
39 }
40 
ToString(uint32_t valueType)41 std::string Property::Value::ToString(uint32_t valueType)
42 {
43     std::string outStr;
44     if (StrToString(valueType, outStr)) {
45         return outStr;
46     }
47 
48     if (BinToString(valueType, outStr)) {
49         return outStr;
50     }
51 
52     outStr.assign("unknown type ");
53     outStr.append(std::to_string(valueType));
54     return outStr;
55 }
56 
BinToString(uint32_t valueType, std::string &outStr)57 bool Property::Value::BinToString(uint32_t valueType, std::string &outStr)
58 {
59     std::string valueStr;
60 
61     bool res = false;
62     if (valueType == MTP_TYPE_INT8_CODE) {
63         res = MtpPacketTool::Int8ToString(bin_.i8, valueStr);
64     } else if (valueType == MTP_TYPE_UINT8_CODE) {
65         res = MtpPacketTool::UInt8ToString(bin_.ui8, valueStr);
66     } else if (valueType == MTP_TYPE_INT16_CODE) {
67         res = MtpPacketTool::Int16ToString(bin_.i16, valueStr);
68     } else if (valueType == MTP_TYPE_UINT16_CODE) {
69         res = MtpPacketTool::UInt16ToString(bin_.ui16, valueStr);
70     } else if (valueType == MTP_TYPE_INT32_CODE) {
71         res = MtpPacketTool::Int32ToString(bin_.i32, valueStr);
72     } else if (valueType == MTP_TYPE_UINT32_CODE) {
73         res = MtpPacketTool::UInt32ToString(bin_.ui32, valueStr);
74     } else if (valueType == MTP_TYPE_INT64_CODE) {
75         res = MtpPacketTool::Int64ToString(bin_.i64, valueStr);
76     } else if (valueType == MTP_TYPE_UINT64_CODE) {
77         res = MtpPacketTool::UInt64ToString(bin_.ui64, valueStr);
78     } else if (valueType == MTP_TYPE_INT128_CODE) {
79         res = MtpPacketTool::Int128ToString(bin_.i128, valueStr);
80     } else if (valueType == MTP_TYPE_UINT128_CODE) {
81         res = MtpPacketTool::UInt128ToString(bin_.ui128, valueStr);
82     } else {
83         return false;
84     }
85 
86     if (!res) {
87         outStr.assign("bin_={}");
88         return true;
89     }
90 
91     outStr.assign("bin_={");
92     outStr.append("type=");
93     outStr.append(MtpPacketTool::GetDataTypeName(valueType));
94     outStr.append(", ");
95     outStr.append(valueStr);
96     outStr.append("}");
97     return true;
98 }
99 
StrToString(uint32_t valueType, std::string &outStr)100 bool Property::Value::StrToString(uint32_t valueType, std::string &outStr)
101 {
102     if (valueType != MTP_TYPE_STRING_CODE) {
103         return false;
104     }
105 
106     outStr.assign("str={");
107     if (str_ == nullptr) {
108         outStr.append("nullptr");
109     } else {
110         outStr.append(MtpPacketTool::StrToString(*str_));
111     }
112     outStr.append("}");
113 
114     return true;
115 }
116 
Property()117 Property::Property()
118 {
119     defaultValue = std::make_shared<Value>();
120     currentValue = std::make_shared<Value>();
121     minValue = std::make_shared<Value>();
122     maxValue = std::make_shared<Value>();
123     stepSize = std::make_shared<Value>();
124 }
125 
Property(uint16_t propCode, uint16_t propType, bool propWriteable, int value)126 Property::Property(uint16_t propCode, uint16_t propType, bool propWriteable, int value)
127     : code_(propCode), type_(propType), writeable_(propWriteable)
128 {
129     defaultValue = std::make_shared<Value>();
130     currentValue = std::make_shared<Value>();
131     minValue = std::make_shared<Value>();
132     maxValue = std::make_shared<Value>();
133     stepSize = std::make_shared<Value>();
134 
135     if (value) {
136         switch (type_) {
137             case MTP_TYPE_INT8_CODE:
138                 defaultValue->bin_.i8 = static_cast<int8_t>(value);
139                 break;
140             case MTP_TYPE_UINT8_CODE:
141                 defaultValue->bin_.ui8 = static_cast<uint8_t>(value);
142                 break;
143             case MTP_TYPE_INT16_CODE:
144                 defaultValue->bin_.i16 = static_cast<int16_t>(value);
145                 break;
146             case MTP_TYPE_UINT16_CODE:
147                 defaultValue->bin_.ui16 = static_cast<uint16_t>(value);
148                 break;
149             case MTP_TYPE_INT32_CODE:
150                 defaultValue->bin_.i32 = static_cast<int32_t>(value);
151                 break;
152             case MTP_TYPE_UINT32_CODE:
153                 defaultValue->bin_.ui32 = static_cast<uint32_t>(value);
154                 break;
155             case MTP_TYPE_INT64_CODE:
156                 defaultValue->bin_.i64 = static_cast<int64_t>(value);
157                 break;
158             case MTP_TYPE_UINT64_CODE:
159                 defaultValue->bin_.ui64 = static_cast<uint64_t>(value);
160                 break;
161             default:
162                 MEDIA_ERR_LOG("Property::Property unknown type %{private}u", type_);
163                 break;
164         }
165     }
166 }
167 
~Property()168 Property::~Property()
169 {
170 }
171 
GetPropertyCode() const172 uint16_t Property::GetPropertyCode() const
173 {
174     return code_;
175 }
176 
GetDataType() const177 uint16_t Property::GetDataType() const
178 {
179     return type_;
180 }
181 
Read(const std::vector<uint8_t> &buffer, size_t &offset)182 bool Property::Read(const std::vector<uint8_t> &buffer, size_t &offset)
183 {
184     if (!MtpPacketTool::GetUInt16(buffer, offset, code_)) {
185         MEDIA_ERR_LOG("Property::read code error");
186         return false;
187     }
188     if (!MtpPacketTool::GetUInt16(buffer, offset, type_)) {
189         MEDIA_ERR_LOG("Property::read type error");
190         return false;
191     }
192     uint8_t tmpVar = 0;
193     if (!MtpPacketTool::GetUInt8(buffer, offset, tmpVar)) {
194         MEDIA_ERR_LOG("Property::read tmpVar error");
195         return false;
196     }
197     writeable_ = (tmpVar == 1);
198     if (!ReadValueData(buffer, offset)) {
199         MEDIA_ERR_LOG("Property::read valuedata error");
200         return false;
201     }
202     bool deviceProp = IsDeviceProperty();
203     if (!deviceProp) {
204         if (!MtpPacketTool::GetUInt32(buffer, offset, groupCode_)) {
205             MEDIA_ERR_LOG("Property::read group error");
206             return false;
207         }
208     }
209     if (!ReadFormData(buffer, offset)) {
210         MEDIA_ERR_LOG("Property::read formdata error");
211         return false;
212     }
213     return true;
214 }
215 
Write(std::vector<uint8_t> &buffer)216 void Property::Write(std::vector<uint8_t> &buffer)
217 {
218     MtpPacketTool::PutUInt16(buffer, code_);
219     MtpPacketTool::PutUInt16(buffer, type_);
220     MtpPacketTool::PutUInt8(buffer, writeable_ ? 1 : 0);
221 
222     WriteValueData(buffer);
223 
224     bool deviceProp = IsDeviceProperty();
225     MEDIA_DEBUG_LOG("Property::write deviceProp=%{private}u", deviceProp);
226     if (!deviceProp) {
227         MtpPacketTool::PutUInt32(buffer, groupCode_);
228     }
229 
230     WriteFormData(buffer);
231 }
232 
SetDefaultValue(const std::shared_ptr<std::string> &str)233 void Property::SetDefaultValue(const std::shared_ptr<std::string> &str)
234 {
235     defaultValue->str_ = str;
236 }
237 
SetCurrentValue(const std::shared_ptr<std::string> &str)238 void Property::SetCurrentValue(const std::shared_ptr<std::string> &str)
239 {
240     currentValue->str_ = str;
241 }
242 
GetCurrentValue()243 const std::shared_ptr<Property::Value> Property::GetCurrentValue()
244 {
245     return currentValue;
246 }
247 
SetFormRange(int min, int max, int step)248 void Property::SetFormRange(int min, int max, int step)
249 {
250     formFlag_ = Form::Range;
251     switch (type_) {
252         case MTP_TYPE_INT8_CODE:
253             minValue->bin_.i8 = static_cast<int8_t>(min);
254             maxValue->bin_.i8 = static_cast<int8_t>(max);
255             stepSize->bin_.i8 = static_cast<int8_t>(step);
256             break;
257         case MTP_TYPE_UINT8_CODE:
258             minValue->bin_.ui8 = static_cast<uint8_t>(min);
259             maxValue->bin_.ui8 = static_cast<uint8_t>(max);
260             stepSize->bin_.ui8 = static_cast<uint8_t>(step);
261             break;
262         case MTP_TYPE_INT16_CODE:
263             minValue->bin_.i16 = static_cast<int16_t>(min);
264             maxValue->bin_.i16 = static_cast<int16_t>(max);
265             stepSize->bin_.i16 = static_cast<int16_t>(step);
266             break;
267         case MTP_TYPE_UINT16_CODE:
268             minValue->bin_.ui16 = static_cast<uint16_t>(min);
269             maxValue->bin_.ui16 = static_cast<uint16_t>(max);
270             stepSize->bin_.ui16 = static_cast<uint16_t>(step);
271             break;
272         case MTP_TYPE_INT32_CODE:
273             minValue->bin_.i32 = static_cast<int32_t>(min);
274             maxValue->bin_.i32 = static_cast<int32_t>(max);
275             stepSize->bin_.i32 = static_cast<int32_t>(step);
276             break;
277         case MTP_TYPE_UINT32_CODE:
278             minValue->bin_.ui32 = static_cast<uint32_t>(min);
279             maxValue->bin_.ui32 = static_cast<uint32_t>(max);
280             stepSize->bin_.ui32 = static_cast<uint32_t>(step);
281             break;
282         case MTP_TYPE_INT64_CODE:
283             minValue->bin_.i64 = static_cast<int64_t>(min);
284             maxValue->bin_.i64 = static_cast<int64_t>(max);
285             stepSize->bin_.i64 = static_cast<int64_t>(step);
286             break;
287         case MTP_TYPE_UINT64_CODE:
288             minValue->bin_.ui64 = static_cast<uint64_t>(min);
289             maxValue->bin_.ui64 = static_cast<uint64_t>(max);
290             stepSize->bin_.ui64 = static_cast<uint64_t>(step);
291             break;
292         default:
293             MEDIA_ERR_LOG("Property::setFormRange unsupported type %{private}u", type_);
294             break;
295     }
296 }
297 
SetFormEnum(const std::vector<int> &values)298 void Property::SetFormEnum(const std::vector<int> &values)
299 {
300     formFlag_ = Form::Enum;
301     enumValues = std::make_shared<std::vector<Value>>();
302 
303     Value v;
304     for (auto value : values) {
305         switch (type_) {
306             case MTP_TYPE_INT8_CODE:
307                 v.bin_.i8 = static_cast<int8_t>(value);
308                 break;
309             case MTP_TYPE_UINT8_CODE:
310                 v.bin_.ui8 = static_cast<uint8_t>(value);
311                 break;
312             case MTP_TYPE_INT16_CODE:
313                 v.bin_.i16 = static_cast<int16_t>(value);
314                 break;
315             case MTP_TYPE_UINT16_CODE:
316                 v.bin_.ui16 = static_cast<uint16_t>(value);
317                 break;
318             case MTP_TYPE_INT32_CODE:
319                 v.bin_.i32 = static_cast<int32_t>(value);
320                 break;
321             case MTP_TYPE_UINT32_CODE:
322                 v.bin_.ui32 = static_cast<uint32_t>(value);
323                 break;
324             case MTP_TYPE_INT64_CODE:
325                 v.bin_.i64 = static_cast<int64_t>(value);
326                 break;
327             case MTP_TYPE_UINT64_CODE:
328                 v.bin_.ui64 = static_cast<uint64_t>(value);
329                 break;
330             default:
331                 MEDIA_ERR_LOG("Property::setFormEnum unsupported type %{private}u", type_);
332                 break;
333         }
334         enumValues->push_back(v);
335     }
336 }
337 
SetFormDateTime()338 void Property::SetFormDateTime()
339 {
340     formFlag_ = Form::DateTime;
341 }
342 
IsDeviceProperty() const343 bool Property::IsDeviceProperty() const
344 {
345     // bit values defined by protocol, check if code is device property
346     return (((code_ & 0xF000) == 0x5000) || ((code_ & 0xF800) == 0xD000));
347 }
348 
IsArrayType() const349 bool Property::IsArrayType() const
350 {
351     return ((type_ >= MTP_DEVICE_PROP_DESC_TYPE_AINT8) && (type_ <= MTP_DEVICE_PROP_DESC_TYPE_AUINT128));
352 }
353 
ReadValueData(const std::vector<uint8_t> &buffer, size_t &offset)354 bool Property::ReadValueData(const std::vector<uint8_t> &buffer, size_t &offset)
355 {
356     bool deviceProp = IsDeviceProperty();
357     switch (type_) {
358         case MTP_TYPE_AINT8_CODE:
359         case MTP_TYPE_AUINT8_CODE:
360         case MTP_TYPE_AINT16_CODE:
361         case MTP_TYPE_AUINT16_CODE:
362         case MTP_TYPE_AINT32_CODE:
363         case MTP_TYPE_AUINT32_CODE:
364         case MTP_TYPE_AINT64_CODE:
365         case MTP_TYPE_AUINT64_CODE:
366         case MTP_TYPE_AINT128_CODE:
367         case MTP_TYPE_AUINT128_CODE: {
368             if (!ReadArrayValues(buffer, offset, defaultValues)) {
369                 MEDIA_ERR_LOG("Property::readValueData defaultValues error");
370                 return false;
371             }
372             if (deviceProp) {
373                 if (!ReadArrayValues(buffer, offset, currentValues)) {
374                     MEDIA_ERR_LOG("Property::readValueData currentValues error");
375                     return false;
376                 }
377             }
378             break;
379         }
380         default: {
381             if (!ReadValue(buffer, offset, *defaultValue)) {
382                 MEDIA_ERR_LOG("Property::readValueData defaultValue error");
383                 return false;
384             }
385             if (deviceProp) {
386                 if (!ReadValue(buffer, offset, *currentValue)) {
387                     MEDIA_ERR_LOG("Property::readValueData currentValues error");
388                     return false;
389                 }
390             }
391         }
392     }
393     return true;
394 }
395 
ReadFormData(const std::vector<uint8_t> &buffer, size_t &offset)396 bool Property::ReadFormData(const std::vector<uint8_t> &buffer, size_t &offset)
397 {
398     if (!MtpPacketTool::GetUInt8(buffer, offset, formFlag_)) {
399         MEDIA_ERR_LOG("Property::readFormData flag error");
400         return false;
401     }
402 
403     if (formFlag_ == Form::Range) {
404         if (!ReadValue(buffer, offset, *minValue)) {
405             MEDIA_ERR_LOG("Property::readFormData minValue error");
406             return false;
407         }
408         if (!ReadValue(buffer, offset, *maxValue)) {
409             MEDIA_ERR_LOG("Property::readFormData maxValue error");
410             return false;
411         }
412         if (!ReadValue(buffer, offset, *stepSize)) {
413             MEDIA_ERR_LOG("Property::readFormData stepSize error");
414             return false;
415         }
416     } else if (formFlag_ == Form::Enum) {
417         uint16_t len = 0;
418         if (!MtpPacketTool::GetUInt16(buffer, offset, len)) {
419             MEDIA_ERR_LOG("Property::readFormData len error");
420             return false;
421         }
422         enumValues = std::make_shared<std::vector<Value>>();
423         Value value;
424         for (int i = 0; i < len; i++) {
425             if (!ReadValue(buffer, offset, value)) {
426                 MEDIA_ERR_LOG("Property::readFormData i=%{private}u", i);
427                 return false;
428             }
429             enumValues->push_back(value);
430         }
431     }
432 
433     return true;
434 }
435 
WriteValueData(std::vector<uint8_t> &buffer)436 void Property::WriteValueData(std::vector<uint8_t> &buffer)
437 {
438     switch (type_) {
439         case MTP_TYPE_AINT8_CODE:
440         case MTP_TYPE_AUINT8_CODE:
441         case MTP_TYPE_AINT16_CODE:
442         case MTP_TYPE_AUINT16_CODE:
443         case MTP_TYPE_AINT32_CODE:
444         case MTP_TYPE_AUINT32_CODE:
445         case MTP_TYPE_AINT64_CODE:
446         case MTP_TYPE_AUINT64_CODE:
447         case MTP_TYPE_AINT128_CODE:
448         case MTP_TYPE_AUINT128_CODE: {
449             WriteArrayValues(buffer, defaultValues);
450             if (IsDeviceProperty()) {
451                 WriteArrayValues(buffer, currentValues);
452             }
453             break;
454         }
455         default: {
456             WriteValue(buffer, *defaultValue);
457             if (IsDeviceProperty()) {
458                 WriteValue(buffer, *currentValue);
459             }
460         }
461     }
462 }
463 
WriteFormData(std::vector<uint8_t> &buffer)464 void Property::WriteFormData(std::vector<uint8_t> &buffer)
465 {
466     MtpPacketTool::PutUInt8(buffer, formFlag_);
467     if (formFlag_ == Form::Range) {
468         WriteValue(buffer, *minValue);
469         WriteValue(buffer, *maxValue);
470         WriteValue(buffer, *stepSize);
471     } else if (formFlag_ == Form::Enum) {
472         uint32_t valueSum = (enumValues == nullptr) ? 0 : enumValues->size();
473         MtpPacketTool::PutUInt16(buffer, valueSum);
474         for (uint32_t i = 0; i < valueSum; i++) {
475             WriteValue(buffer, (*enumValues)[i]);
476         }
477     }
478 }
479 
ReadValue(const std::vector<uint8_t> &buffer, size_t &offset, Value &value)480 bool Property::ReadValue(const std::vector<uint8_t> &buffer, size_t &offset, Value &value)
481 {
482     switch (type_) {
483         case MTP_TYPE_INT8_CODE:
484         case MTP_TYPE_AINT8_CODE:
485             if (!MtpPacketTool::GetInt8(buffer, offset, value.bin_.i8)) {
486                 return false;
487             }
488             break;
489         case MTP_TYPE_UINT8_CODE:
490         case MTP_TYPE_AUINT8_CODE:
491             if (!MtpPacketTool::GetUInt8(buffer, offset, value.bin_.ui8)) {
492                 return false;
493             }
494             break;
495         case MTP_TYPE_INT16_CODE:
496         case MTP_TYPE_AINT16_CODE:
497             if (!MtpPacketTool::GetInt16(buffer, offset, value.bin_.i16)) {
498                 return false;
499             }
500             break;
501         case MTP_TYPE_UINT16_CODE:
502         case MTP_TYPE_AUINT16_CODE:
503             if (!MtpPacketTool::GetUInt16(buffer, offset, value.bin_.ui16)) {
504                 return false;
505             }
506             break;
507         case MTP_TYPE_INT32_CODE:
508         case MTP_TYPE_AINT32_CODE:
509             if (!MtpPacketTool::GetInt32(buffer, offset, value.bin_.i32)) {
510                 return false;
511             }
512             break;
513         case MTP_TYPE_UINT32_CODE:
514         case MTP_TYPE_AUINT32_CODE:
515             if (!MtpPacketTool::GetUInt32(buffer, offset, value.bin_.ui32)) {
516                 return false;
517             }
518             break;
519         default: {
520             if (!ReadValueEx(buffer, offset, value)) {
521                 return false;
522             }
523             break;
524         }
525     }
526     return true;
527 }
528 
ReadValueEx(const std::vector<uint8_t> &buffer, size_t &offset, Value &value)529 bool Property::ReadValueEx(const std::vector<uint8_t> &buffer, size_t &offset, Value &value)
530 {
531     switch (type_) {
532         case MTP_TYPE_INT64_CODE:
533         case MTP_TYPE_AINT64_CODE: {
534             if (!MtpPacketTool::GetInt64(buffer, offset, value.bin_.i64)) {
535                 return false;
536             }
537             break;
538         }
539         case MTP_TYPE_UINT64_CODE:
540         case MTP_TYPE_AUINT64_CODE: {
541             if (!MtpPacketTool::GetUInt64(buffer, offset, value.bin_.ui64)) {
542                 return false;
543             }
544             break;
545         }
546         case MTP_TYPE_INT128_CODE:
547         case MTP_TYPE_AINT128_CODE: {
548             if (!MtpPacketTool::GetInt128(buffer, offset, value.bin_.i128)) {
549                 return false;
550             }
551             break;
552         }
553         case MTP_TYPE_UINT128_CODE:
554         case MTP_TYPE_AUINT128_CODE: {
555             if (!MtpPacketTool::GetUInt128(buffer, offset, value.bin_.ui128)) {
556                 return false;
557             }
558             break;
559         }
560         case MTP_TYPE_STRING_CODE: {
561             std::string str;
562             if (!MtpPacketTool::GetString(buffer, offset, str)) {
563                 return false;
564             }
565             value.str_ = std::make_shared<std::string>(str);
566             break;
567         }
568         default:
569             MEDIA_ERR_LOG("unknown type %{private}u in Property::ReadValue", type_);
570             return false;
571     }
572     return true;
573 }
574 
WriteValue(std::vector<uint8_t> &buffer, const Value &value)575 void Property::WriteValue(std::vector<uint8_t> &buffer, const Value &value)
576 {
577     switch (type_) {
578         case MTP_TYPE_INT8_CODE:
579         case MTP_TYPE_AINT8_CODE:
580             MtpPacketTool::PutUInt8(buffer, static_cast<uint8_t>(value.bin_.i8));
581             break;
582         case MTP_TYPE_UINT8_CODE:
583         case MTP_TYPE_AUINT8_CODE:
584             MtpPacketTool::PutUInt8(buffer, value.bin_.ui8);
585             break;
586         case MTP_TYPE_INT16_CODE:
587         case MTP_TYPE_AINT16_CODE:
588             MtpPacketTool::PutUInt16(buffer, static_cast<uint16_t>(value.bin_.i16));
589             break;
590         case MTP_TYPE_UINT16_CODE:
591         case MTP_TYPE_AUINT16_CODE:
592             MtpPacketTool::PutUInt16(buffer, value.bin_.ui16);
593             break;
594         case MTP_TYPE_INT32_CODE:
595         case MTP_TYPE_AINT32_CODE:
596             MtpPacketTool::PutUInt32(buffer, static_cast<uint32_t>(value.bin_.i32));
597             break;
598         case MTP_TYPE_UINT32_CODE:
599         case MTP_TYPE_AUINT32_CODE:
600             MtpPacketTool::PutUInt32(buffer, value.bin_.ui32);
601             break;
602         default: {
603             WriteValueEx(buffer, value);
604             break;
605         }
606     }
607 }
608 
WriteValueEx(std::vector<uint8_t> &buffer, const Value &value)609 void Property::WriteValueEx(std::vector<uint8_t> &buffer, const Value &value)
610 {
611     switch (type_) {
612         case MTP_TYPE_INT64_CODE:
613         case MTP_TYPE_AINT64_CODE:
614             MtpPacketTool::PutUInt64(buffer, static_cast<uint64_t>(value.bin_.i64));
615             break;
616         case MTP_TYPE_UINT64_CODE:
617         case MTP_TYPE_AUINT64_CODE:
618             MtpPacketTool::PutUInt64(buffer, value.bin_.ui64);
619             break;
620         case MTP_TYPE_INT128_CODE:
621         case MTP_TYPE_AINT128_CODE:
622             MtpPacketTool::PutInt128(buffer, value.bin_.i128);
623             break;
624         case MTP_TYPE_UINT128_CODE:
625         case MTP_TYPE_AUINT128_CODE:
626             MtpPacketTool::PutUInt128(buffer, value.bin_.ui128);
627             break;
628         case MTP_TYPE_STRING_CODE:
629             if (value.str_ == nullptr) {
630                 MtpPacketTool::PutUInt8(buffer, 0);
631             } else {
632                 MtpPacketTool::PutString(buffer, *(value.str_));
633             }
634             break;
635         default:
636             MEDIA_ERR_LOG("Property::writeValue unknown type %{private}u", type_);
637     }
638 }
639 
ReadArrayValues(const std::vector<uint8_t> &buffer, size_t &offset, std::shared_ptr<std::vector<Value>> &values)640 bool Property::ReadArrayValues(const std::vector<uint8_t> &buffer, size_t &offset,
641     std::shared_ptr<std::vector<Value>> &values)
642 {
643     uint32_t length = 0;
644     if (!MtpPacketTool::GetUInt32(buffer, offset, length)) {
645         return false;
646     }
647 
648     if (length == 0 || (length >= (INT32_MAX / sizeof(Value)))) {
649         return false;
650     }
651 
652     if (values == nullptr) {
653         values = std::make_shared<std::vector<Value>>();
654     }
655     values->clear();
656 
657     for (uint32_t i = 0; i < length; i++) {
658         Value value;
659         if (!ReadValue(buffer, offset, value)) {
660             return false;
661         }
662         values->push_back(value);
663     }
664 
665     return true;
666 }
667 
WriteArrayValues(std::vector<uint8_t> &buffer, const std::shared_ptr<std::vector<Value>> &values)668 void Property::WriteArrayValues(std::vector<uint8_t> &buffer,
669     const std::shared_ptr<std::vector<Value>> &values)
670 {
671     uint32_t valueSum = (values == nullptr) ? 0 : values->size();
672     MtpPacketTool::PutUInt32(buffer, valueSum);
673     for (uint32_t i = 0; i < valueSum; i++) {
674         WriteValue(buffer, (*values)[i]);
675     }
676 }
677 
Dump()678 void Property::Dump()
679 {
680     int indent = 1;
681     std::string indentStr = MtpPacketTool::GetIndentBlank(indent);
682 
683     MEDIA_DEBUG_LOG("handle=%{private}x", handle_);
684     MEDIA_DEBUG_LOG("### Property {property=%{private}s(%{private}x)} begin ###",
685         MtpPacketTool::GetObjectPropName(code_).c_str(), code_);
686     MEDIA_DEBUG_LOG("%{private}stype=[%{private}s](%{private}x)}, writeable_=%{private}d",
687         indentStr.c_str(), MtpPacketTool::GetDataTypeName(type_).c_str(), type_, writeable_);
688 
689     if (!IsArrayType()) {
690         DumpValue(indent, defaultValue, "defaultValue");
691         DumpValue(indent, currentValue, "currentValue");
692     } else {
693         DumpValues(indent, defaultValues, "defaultValues");
694         DumpValues(indent, currentValues, "currentValues");
695     }
696 
697     MEDIA_DEBUG_LOG("%{private}sgroupCode=%{private}u", indentStr.c_str(), groupCode_);
698     DumpForm(indent);
699     MEDIA_DEBUG_LOG("+++ Property end +++");
700 }
701 
DumpValue(uint8_t indent, const std::shared_ptr<Value> &value, const std::string &name)702 void Property::DumpValue(uint8_t indent, const std::shared_ptr<Value> &value, const std::string &name)
703 {
704     std::string indentStr = MtpPacketTool::GetIndentBlank(indent);
705 
706     MEDIA_DEBUG_LOG("%{private}s%{private}s=%{private}s", indentStr.c_str(), name.c_str(),
707         (value == nullptr) ? "nullptr" : value->ToString(type_).c_str());
708 }
709 
DumpValues(uint8_t indent, const std::shared_ptr<std::vector<Value>> &values, const std::string &name)710 void Property::DumpValues(uint8_t indent, const std::shared_ptr<std::vector<Value>> &values, const std::string &name)
711 {
712     std::string indentStr = MtpPacketTool::GetIndentBlank(indent);
713 
714     if (values == nullptr) {
715         MEDIA_DEBUG_LOG("%{private}s%{private}s=nullptr", indentStr.c_str(), name.c_str());
716     } else {
717         std::string indentStr2 = MtpPacketTool::GetIndentBlank(indent + 1);
718         for (auto &v : (*values)) {
719             MEDIA_DEBUG_LOG("%{private}s%{private}s", indentStr2.c_str(), v.ToString(type_).c_str());
720         }
721         MEDIA_DEBUG_LOG("%{private}s--- value end ---", indentStr.c_str());
722     }
723 }
724 
DumpForm(uint8_t indent)725 void Property::DumpForm(uint8_t indent)
726 {
727     std::string indentStr = MtpPacketTool::GetIndentBlank(indent);
728 
729     MEDIA_DEBUG_LOG("%{private}sformFlag=%{private}s(%{private}u)",
730         indentStr.c_str(), MtpPacketTool::CodeToStrByMap(formFlag_, FormMap).c_str(), formFlag_);
731 
732     if (formFlag_ == Form::Range) {
733         DumpValue(indent + 1, minValue, "minValue");
734         DumpValue(indent + 1, maxValue, "maxValue");
735         DumpValue(indent + 1, stepSize, "stepSize");
736     } else if (formFlag_ == Form::Enum) {
737         DumpValues(indent + 1, enumValues, "enumValues");
738     } else if (formFlag_ == Form::DateTime) {
739         MEDIA_DEBUG_LOG("Form::DateTime");
740     } else {
741         MEDIA_DEBUG_LOG("unknow type");
742     }
743 }
744 } // namespace Media
745 } // namespace OHOS