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_ENCODER_H 17 #define DATA_ENCODER_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 struct MemBlock { 30 size_t blockSize; 31 unsigned char data[0]; 32 }; 33 34 class DataEncoder { 35 public: 36 DataEncoder(); 37 ~DataEncoder(); 38 39 /** 40 * Delete copy constructor/assignment to avoid misuse. 41 */ 42 DataEncoder(const DataEncoder &other) = delete; 43 DataEncoder& operator=(const DataEncoder &other) = delete; 44 45 /** 46 * Initializes memory for encoding data. 47 * 48 * @param [in] sz The size of the data which needs to be encoded. 49 * @return Return 0 if initialize successfully, returns a non-zero value otherwise. 50 */ 51 int Init(size_t sz = INIT_BUFFER_SIZE); 52 53 /** 54 * Encodes arguments. 55 * 56 * Please note, 57 * 1. the allowed input args contains: 58 * - basic data types(int, double, boolean etc.), fix length arrays and structs containing them only. 59 * - std::string 60 * 61 * otherwise you should implement your own version of encoding/decoding 62 * for pointers / struct containing pointers / struct containing std:string. 63 * Specifically, you should instantiate template function (@link DataEncoder::EncodeOneParameter) 64 * and (@link DataDecoder::DecodeOneParameter). 65 * 66 * 2. class and container are not supported or tested. 67 * 68 * @param [in] arg argument need to be serialized. Receive any number of input. 69 * @return Return 0 if encode successfully, returns a non-zero value otherwise. 70 */ 71 template<typename Type, typename... Types> RecursiveEncode(const Type & arg,const Types &...args)72 int RecursiveEncode(const Type &arg, const Types &...args) 73 { 74 int retCode = EncodeOneParameter<Type>(arg); 75 if (retCode != RETCODE_SUCCESS) { 76 return retCode; 77 } 78 return RecursiveEncode(args...); 79 } 80 81 /** 82 * Returns serialized data. 83 * 84 * Please note, 85 * 1. the memory in dataInfo should be released manually by the caller, 86 * recommend to use guard macro immediately after ProcessEncode. 87 * e.g. 88 * MallocPointerGuard<unsigned char> dataInfoGuard(dataInfo.data); 89 * 90 * @param [out] dataInfo The serialized data. 91 * @return Return 0 if get data successfully, returns a non-zero value otherwise. 92 */ 93 int GetSerializedData(DataInfo &dataInfo); 94 95 private: 96 /** 97 * Ensure left memory length is bigger than incSize, otherwise expand it. 98 * 99 * @param [in] incSize Size to check. 100 * @return Return false if remaining memory is less than incSize, returns true otherwise. 101 */ 102 bool Ensure(const size_t incSize); 103 104 /** 105 * Write the data into the buffer. if the data size exceeds the buffer size, it will extend the buffer first. 106 * instantiate it for your own data type if needed. 107 * 108 * @param [in] val The data that needs to be encoded. 109 * @return Returns 0 if the data has been written into the buffer successfully, otherwise, it will return -1. 110 */ 111 template<typename T> EncodeOneParameter(const T & val)112 int EncodeOneParameter(const T &val) 113 { 114 if (!allocSuccess_) { 115 return RETCODE_FAILURE; 116 } 117 118 size_t len = sizeof(T); 119 // on gcc, sizeof(T) is 0 when on gcc when T is defined as 0 length array. 120 // but it may not apply to other compilers. 121 // try a better type definition to avoid ambiguity. 122 if (len == 0) { 123 HILOGE("[Encdec]sizeof(T) is 0."); 124 return RETCODE_FAILURE; 125 } 126 if (!Ensure(len)) { 127 HILOGE("[Encdec]ReallocBuffer failed."); 128 return RETCODE_FAILURE; 129 } 130 131 // assign value without memory alignment cause crash 132 // so use memcpy_s to make sure success. 133 if (memcpy_s(buffer_->data + pos_, len, &val, sizeof(val)) != EOK) { 134 HILOGE("[Encdec]memcpy_s failed."); 135 return RETCODE_FAILURE; 136 } 137 pos_ += len; 138 return RETCODE_SUCCESS; 139 } 140 141 bool ReallocBuffer(const size_t newSize); 142 143 /** 144 * it offers a terminal call for RecursiveEncode. 145 * 146 * @return Returns 0. 147 */ RecursiveEncode()148 int RecursiveEncode() 149 { 150 return RETCODE_SUCCESS; 151 } 152 153 private: 154 static constexpr size_t INIT_BUFFER_SIZE = 256U; 155 156 MemBlock *buffer_ {nullptr}; 157 size_t pos_ {0}; 158 bool allocSuccess_ {false}; 159 }; 160 161 /** 162 * Decode std::string. It's a instantiation of template function (@link DataDecoder::DecodeOneParameter). 163 * 164 * @param [in] val The data that needs to be encoded. 165 * @return Returns 0 if the data has been written into the buffer successfully, otherwise, it will return -1. 166 */ 167 template<> 168 int DataEncoder::EncodeOneParameter(const std::string &val); 169 } // namespace AI 170 } // namespace OHOS 171 172 #endif // DATA_ENCODER_H 173