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