/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SHARED_BLOCK_H #define SHARED_BLOCK_H #include <cinttypes> #include <string> #include <ashmem.h> #include "message_parcel.h" #include "parcel.h" #include "securec.h" namespace OHOS { namespace AppDataFwk { static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF; /** * This class stores a set of rows from a database in a buffer, * which is used as the set of query result. */ class SharedBlock { public: /* Cell Unit types. */ enum { CELL_UNIT_TYPE_NULL = 0, CELL_UNIT_TYPE_INTEGER = 1, CELL_UNIT_TYPE_FLOAT = 2, CELL_UNIT_TYPE_STRING = 3, CELL_UNIT_TYPE_BLOB = 4, }; /* SharedBlock error types. */ enum { SHARED_BLOCK_OK = 0, SHARED_BLOCK_BAD_VALUE = 1, SHARED_BLOCK_NO_MEMORY = 2, SHARED_BLOCK_INVALID_OPERATION = 3, SHARED_BLOCK_ASHMEM_ERROR = 4, SHARED_BLOCK_SET_PORT_ERROR = 5, }; /* Cell Unit */ struct CellUnit { int32_t type; union { double doubleValue; int64_t longValue; struct { uint32_t offset; uint32_t size; } stringOrBlobValue; } cell; } __attribute((packed)); /** * SharedBlock constructor. */ SharedBlock(const std::string &name, sptr<Ashmem> ashmem, size_t size, bool readOnly); /** * SharedBlock constructor. */ ~SharedBlock(); /** * Init current shared block. */ bool Init(); /** * Create a shared block. */ static int Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock); /** * Clear current shared block. */ int Clear(); /** * Set a shared block column. */ int SetColumnNum(uint32_t numColumns); /** * Allocate a row unit and its directory. */ int AllocRow(); /** * Release the value of the last row. */ int FreeLastRow(); /** * Put blob data to the shared block. */ int PutBlob(uint32_t row, uint32_t column, const void *value, size_t Size); /** * Put string data to the shared block. */ int PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull); /** * Put long data to the shared block. */ int PutLong(uint32_t row, uint32_t column, int64_t value); /** * Put Double data to the shared block. */ int PutDouble(uint32_t row, uint32_t column, double value); /** * Put Null data to the shared block. */ int PutNull(uint32_t row, uint32_t column); /** * Gets the cell unit at the specified row and column. */ CellUnit *GetCellUnit(uint32_t row, uint32_t column); /** * Get string type data from cell unit. */ const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull) { *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size; return static_cast<char *>( OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size)); } /** * Get blob type data from cell unit. */ const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize) { *outSize = cellUnit->cell.stringOrBlobValue.size; return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size); } /** * The mHeader of the current result set. */ const void *GetHeader() { return mHeader; } /** * Size of the used byte in the block. */ size_t GetUsedBytes() { return mHeader->unusedOffset; } /** * The name of the current result set. */ std::string Name() { return mName; } /** * The size of the current result set. */ size_t Size() { return mSize; } /** * The row number of the current result set. */ uint32_t GetRowNum() { return mHeader->rowNums; } /** * The column number of the current result set. */ uint32_t GetColumnNum() { return mHeader->columnNums; } int WriteMessageParcel(MessageParcel &parcel); static int ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block); /** * Write raw data in block. */ size_t SetRawData(const void *rawData, size_t size); /** * The fd of shared memory */ int GetFd() { if (ashmem_ == nullptr) { return -1; } return ashmem_->GetAshmemFd(); } uint32_t GetStartPos() { return mHeader->startPos_; } uint32_t GetLastPos() { return mHeader->lastPos_; } uint32_t GetBlockPos() { return mHeader->blockPos_; } void SetStartPos(uint32_t startPos) { mHeader->startPos_ = startPos; } void SetLastPos(uint32_t lastPos) { mHeader->lastPos_ = lastPos; } void SetBlockPos(uint32_t blockPos) { mHeader->blockPos_ = blockPos; } private: std::string mName; sptr<Ashmem> ashmem_; void *mData; size_t mSize; bool mReadOnly; static const size_t ROW_OFFSETS_NUM = 100; /** * Default setting for SQLITE_MAX_COLUMN is 2000. * We can set it at compile time to as large as 32767 */ static const size_t COL_MAX_NUM = 32767; struct SharedBlockHeader { /* Offset of the lowest unused byte in the block. */ uint32_t unusedOffset; /* Offset of the first row group. */ uint32_t firstRowGroupOffset; /* Row numbers of the row group block. */ uint32_t rowNums; /* Column numbers of the row group block. */ uint32_t columnNums; /* start position of the current block. */ uint32_t startPos_; /* last position of the current block. */ uint32_t lastPos_; /* current position of the current block. */ uint32_t blockPos_; }; struct RowGroupHeader { uint32_t rowOffsets[ROW_OFFSETS_NUM]; uint32_t nextGroupOffset; }; SharedBlockHeader *mHeader; /** * Allocate a portion of the block. Returns the offset of the allocation. * Returns 0 if there isn't enough space. */ uint32_t Alloc(size_t size, bool aligned = false); inline uint32_t *GetRowOffset(uint32_t row); uint32_t *AllocRowOffset(); int PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type); static int CreateSharedBlock(const std::string &name, size_t size, sptr<Ashmem> ashmem, SharedBlock *&outSharedBlock); uint32_t OffsetFromPtr(void *ptr); inline void *OffsetToPtr(uint32_t offset, uint32_t bufferSize = 0) { if (offset >= mSize) { return nullptr; } if (offset + bufferSize > mSize) { return nullptr; } return static_cast<uint8_t *>(mData) + offset; } /** * Convert utf8 string to utf16. */ static std::u16string ToUtf16(const std::string& str); /** * Convert utf16 string to utf8. */ static std::string ToUtf8(const std::u16string& str16); }; } // namespace AppDataFwk } // namespace OHOS #endif