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 SHARED_BLOCK_H 17 #define SHARED_BLOCK_H 18 19 #include <cinttypes> 20 21 #include <string> 22 #include <ashmem.h> 23 #include "message_parcel.h" 24 #include "parcel.h" 25 #include "securec.h" 26 27 namespace OHOS { 28 namespace AppDataFwk { 29 static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF; 30 /** 31 * This class stores a set of rows from a database in a buffer, 32 * which is used as the set of query result. 33 */ 34 class SharedBlock { 35 public: 36 /* Cell Unit types. */ 37 enum { 38 CELL_UNIT_TYPE_NULL = 0, 39 CELL_UNIT_TYPE_INTEGER = 1, 40 CELL_UNIT_TYPE_FLOAT = 2, 41 CELL_UNIT_TYPE_STRING = 3, 42 CELL_UNIT_TYPE_BLOB = 4, 43 }; 44 45 /* SharedBlock error types. */ 46 enum { 47 SHARED_BLOCK_OK = 0, 48 SHARED_BLOCK_BAD_VALUE = 1, 49 SHARED_BLOCK_NO_MEMORY = 2, 50 SHARED_BLOCK_INVALID_OPERATION = 3, 51 SHARED_BLOCK_ASHMEM_ERROR = 4, 52 SHARED_BLOCK_SET_PORT_ERROR = 5, 53 }; 54 55 /* Cell Unit */ 56 struct CellUnit { 57 int32_t type; 58 union { 59 double doubleValue; 60 int64_t longValue; 61 struct { 62 uint32_t offset; 63 uint32_t size; 64 } stringOrBlobValue; 65 } cell; 66 } __attribute((packed)); 67 68 /** 69 * SharedBlock constructor. 70 */ 71 SharedBlock(const std::string &name, sptr<Ashmem> ashmem, size_t size, bool readOnly); 72 73 /** 74 * SharedBlock constructor. 75 */ 76 ~SharedBlock(); 77 78 /** 79 * Init current shared block. 80 */ 81 bool Init(); 82 83 /** 84 * Create a shared block. 85 */ 86 static int Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock); 87 88 /** 89 * Clear current shared block. 90 */ 91 int Clear(); 92 93 /** 94 * Set a shared block column. 95 */ 96 int SetColumnNum(uint32_t numColumns); 97 98 /** 99 * Allocate a row unit and its directory. 100 */ 101 int AllocRow(); 102 103 /** 104 * Release the value of the last row. 105 */ 106 int FreeLastRow(); 107 108 /** 109 * Put blob data to the shared block. 110 */ 111 int PutBlob(uint32_t row, uint32_t column, const void *value, size_t Size); 112 113 /** 114 * Put string data to the shared block. 115 */ 116 int PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull); 117 118 /** 119 * Put long data to the shared block. 120 */ 121 int PutLong(uint32_t row, uint32_t column, int64_t value); 122 123 /** 124 * Put Double data to the shared block. 125 */ 126 int PutDouble(uint32_t row, uint32_t column, double value); 127 128 /** 129 * Put Null data to the shared block. 130 */ 131 int PutNull(uint32_t row, uint32_t column); 132 133 /** 134 * Gets the cell unit at the specified row and column. 135 */ 136 CellUnit *GetCellUnit(uint32_t row, uint32_t column); 137 138 /** 139 * Get string type data from cell unit. 140 */ GetCellUnitValueString(CellUnit * cellUnit,size_t * outSizeIncludingNull)141 const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull) 142 { 143 *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size; 144 return static_cast<char *>( 145 OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size)); 146 } 147 148 /** 149 * Get blob type data from cell unit. 150 */ GetCellUnitValueBlob(CellUnit * cellUnit,size_t * outSize)151 const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize) 152 { 153 *outSize = cellUnit->cell.stringOrBlobValue.size; 154 return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size); 155 } 156 157 /** 158 * The mHeader of the current result set. 159 */ GetHeader()160 const void *GetHeader() 161 { 162 return mHeader; 163 } 164 165 /** 166 * Size of the used byte in the block. 167 */ GetUsedBytes()168 size_t GetUsedBytes() 169 { 170 return mHeader->unusedOffset; 171 } 172 173 /** 174 * The name of the current result set. 175 */ Name()176 std::string Name() 177 { 178 return mName; 179 } 180 181 /** 182 * The size of the current result set. 183 */ Size()184 size_t Size() 185 { 186 return mSize; 187 } 188 189 /** 190 * The row number of the current result set. 191 */ GetRowNum()192 uint32_t GetRowNum() 193 { 194 return mHeader->rowNums; 195 } 196 197 /** 198 * The column number of the current result set. 199 */ GetColumnNum()200 uint32_t GetColumnNum() 201 { 202 return mHeader->columnNums; 203 } 204 205 int WriteMessageParcel(MessageParcel &parcel); 206 207 static int ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block); 208 /** 209 * Write raw data in block. 210 */ 211 size_t SetRawData(const void *rawData, size_t size); 212 /** 213 * The fd of shared memory 214 */ GetFd()215 int GetFd() 216 { 217 if (ashmem_ == nullptr) { 218 return -1; 219 } 220 return ashmem_->GetAshmemFd(); 221 } 222 GetStartPos()223 uint32_t GetStartPos() 224 { 225 return mHeader->startPos_; 226 } 227 GetLastPos()228 uint32_t GetLastPos() 229 { 230 return mHeader->lastPos_; 231 } 232 GetBlockPos()233 uint32_t GetBlockPos() 234 { 235 return mHeader->blockPos_; 236 } 237 SetStartPos(uint32_t startPos)238 void SetStartPos(uint32_t startPos) 239 { 240 mHeader->startPos_ = startPos; 241 } 242 SetLastPos(uint32_t lastPos)243 void SetLastPos(uint32_t lastPos) 244 { 245 mHeader->lastPos_ = lastPos; 246 } 247 SetBlockPos(uint32_t blockPos)248 void SetBlockPos(uint32_t blockPos) 249 { 250 mHeader->blockPos_ = blockPos; 251 } 252 253 private: 254 std::string mName; 255 sptr<Ashmem> ashmem_; 256 void *mData; 257 size_t mSize; 258 bool mReadOnly; 259 static const size_t ROW_OFFSETS_NUM = 100; 260 /** 261 * Default setting for SQLITE_MAX_COLUMN is 2000. 262 * We can set it at compile time to as large as 32767 263 */ 264 static const size_t COL_MAX_NUM = 32767; 265 266 struct SharedBlockHeader { 267 /* Offset of the lowest unused byte in the block. */ 268 uint32_t unusedOffset; 269 /* Offset of the first row group. */ 270 uint32_t firstRowGroupOffset; 271 /* Row numbers of the row group block. */ 272 uint32_t rowNums; 273 /* Column numbers of the row group block. */ 274 uint32_t columnNums; 275 /* start position of the current block. */ 276 uint32_t startPos_; 277 /* last position of the current block. */ 278 uint32_t lastPos_; 279 /* current position of the current block. */ 280 uint32_t blockPos_; 281 }; 282 283 struct RowGroupHeader { 284 uint32_t rowOffsets[ROW_OFFSETS_NUM]; 285 uint32_t nextGroupOffset; 286 }; 287 288 SharedBlockHeader *mHeader; 289 290 /** 291 * Allocate a portion of the block. Returns the offset of the allocation. 292 * Returns 0 if there isn't enough space. 293 */ 294 uint32_t Alloc(size_t size, bool aligned = false); 295 296 inline uint32_t *GetRowOffset(uint32_t row); 297 298 uint32_t *AllocRowOffset(); 299 300 int PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type); 301 302 static int CreateSharedBlock(const std::string &name, size_t size, sptr<Ashmem> ashmem, 303 SharedBlock *&outSharedBlock); 304 305 uint32_t OffsetFromPtr(void *ptr); 306 307 inline void *OffsetToPtr(uint32_t offset, uint32_t bufferSize = 0) 308 { 309 if (offset >= mSize) { 310 return nullptr; 311 } 312 if (offset + bufferSize > mSize) { 313 return nullptr; 314 } 315 return static_cast<uint8_t *>(mData) + offset; 316 } 317 318 /** 319 * Convert utf8 string to utf16. 320 */ 321 static std::u16string ToUtf16(const std::string& str); 322 323 /** 324 * Convert utf16 string to utf8. 325 */ 326 static std::string ToUtf8(const std::u16string& str16); 327 }; 328 } // namespace AppDataFwk 329 } // namespace OHOS 330 #endif 331