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 #ifndef DATA_DECODER_H 17 #define DATA_DECODER_H 18 19 #include <string> 20 21 #include "securec.h" 22 23 #include "protocol/retcode_inner/aie_retcode_inner.h" 24 #include "protocol/struct_definition/aie_info_define.h" 25 #include "utils/log/aie_log.h" 26 27 namespace OHOS { 28 namespace AI { 29 class DataDecoder { 30 public: DataDecoder(const DataInfo dataInfo)31 explicit DataDecoder(const DataInfo dataInfo) : buffer_(dataInfo.data), size_(dataInfo.length), pos_(0) 32 { 33 } 34 35 ~DataDecoder() = default; 36 37 /** 38 * Delete copy constructor/assignment to avoid misuse. 39 */ 40 DataDecoder(const DataDecoder &other) = delete; 41 DataDecoder& operator=(const DataDecoder &other) = delete; 42 43 /** 44 * Decode all arguments in the DataInfo. 45 * 46 * Please note, 47 * 1. the arguments' order in decoder and encoder process should match strictly. 48 * 2. if decoding a pointer, the caller should allocate the memory first and handle the release. 49 * 50 * @param [out] arg argument need to be unserialized. Receive any number of arguments. 51 * @return Return 0 if decode successfully, returns a non-zero value otherwise. 52 */ 53 template<typename Type, typename... Types> RecursiveDecode(Type & arg,Types &...args)54 int RecursiveDecode(Type &arg, Types &...args) 55 { 56 int retCode = DecodeOneParameter<Type>(arg); 57 if (retCode != RETCODE_SUCCESS) { 58 return retCode; 59 } 60 return RecursiveDecode(args...); 61 } 62 63 /** 64 * Check whether the decode data size matches the original data when decoding ends. 65 * It should be called after all data have been decoded. 66 * 67 * @return Returns true if decode data size matches, return false if decode data length fails to match. 68 */ CheckDataEnd()69 bool CheckDataEnd() 70 { 71 size_t dataSize = 0; 72 if (DecodeOneParameter(dataSize) != RETCODE_SUCCESS) { 73 return false; 74 } 75 if ((pos_ != size_) || (pos_ != dataSize + sizeof(dataSize))) { 76 HILOGE("[Encdec]Decoded length[%zu], encoded length[%zu], whole length[%zu] don't match.", 77 pos_, dataSize, size_); 78 HILOGE("[Encdec]Possible reason: the caller doesn't include the specialized "\ 79 "EncodeOneParameter/DecoderOneParameter function."); 80 return false; 81 } 82 return true; 83 } 84 85 private: 86 /** 87 * Decode the data buffer based on the data type that was transferred in. 88 * instantiate it for your own data type if needed. 89 * 90 * @param [out] val It provides a data type, the function will decode by it. 91 * @return Returns 0 if decode successful, otherwise it failed. 92 */ 93 template<typename T> DecodeOneParameter(T & val)94 int DecodeOneParameter(T &val) 95 { 96 // sizeof(T) is 0 when on gcc when T is defined as 0 length array. 97 // but it may not apply to other compilers. 98 // try a better type definition to avoid ambiguity. 99 if (sizeof(T) == 0) { 100 HILOGE("[Encdec]sizeof(T) is 0."); 101 return RETCODE_FAILURE; 102 } 103 if (!Ensure(sizeof(T))) { 104 HILOGE("[Encdec]Memory read out of boundary"); 105 return RETCODE_FAILURE; 106 } 107 108 // assign value without memory alignment cause crash 109 // so use memcpy_s to make sure success. 110 if (memcpy_s(&val, sizeof(val), buffer_ + pos_, sizeof(val)) != EOK) { 111 HILOGE("[Encdec]memcpy_s failed"); 112 return RETCODE_FAILURE; 113 } 114 pos_ += sizeof(T); 115 return RETCODE_SUCCESS; 116 } 117 118 /** 119 * To make sure that passed in data type will not exceed the original data buffer 120 * 121 * @return Return 1 if the size of data buffer is enough for decoding, otherwise it returns 0. 122 */ Ensure(const size_t size)123 inline bool Ensure(const size_t size) const 124 { 125 return (size <= size_ && (pos_ + size) <= size_); 126 } 127 128 /** 129 * it offers a terminal call for RecursiveEncode. 130 * 131 * @return Returns 0. 132 */ RecursiveDecode()133 int RecursiveDecode() 134 { 135 return RETCODE_SUCCESS; 136 } 137 138 private: 139 unsigned char *buffer_ {nullptr}; 140 size_t size_ {0}; 141 size_t pos_ {0}; 142 }; 143 144 /** 145 * Encode std::string. It's a instantiation of template function (@link DataEncoder::EncodeOneParameter). 146 * 147 * @param [out] val The data that needs to be encoded. 148 * @return Returns 0 if the data has been written into the buffer successfully, otherwise, it will return -1. 149 */ 150 template<> 151 int DataDecoder::DecodeOneParameter(std::string &val); 152 } // namespace AI 153 } // namespace OHOS 154 155 #endif // DATA_DECODER_H 156