| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2006 The Android Open Source Project | 
|  | 3 | * | 
| Vasu Nori | e733497 | 2010-05-18 11:54:31 -0700 | [diff] [blame] | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 7 | * | 
| Vasu Nori | e733497 | 2010-05-18 11:54:31 -0700 | [diff] [blame] | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 9 | * | 
| Vasu Nori | e733497 | 2010-05-18 11:54:31 -0700 | [diff] [blame] | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #ifndef _ANDROID__DATABASE_WINDOW_H | 
|  | 18 | #define _ANDROID__DATABASE_WINDOW_H | 
|  | 19 |  | 
|  | 20 | #include <cutils/log.h> | 
|  | 21 | #include <stddef.h> | 
|  | 22 | #include <stdint.h> | 
|  | 23 |  | 
|  | 24 | #include <binder/IMemory.h> | 
|  | 25 | #include <utils/RefBase.h> | 
|  | 26 |  | 
|  | 27 | #define DEFAULT_WINDOW_SIZE 4096 | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 28 | #define WINDOW_ALLOCATION_SIZE 4096 | 
|  | 29 |  | 
|  | 30 | #define ROW_SLOT_CHUNK_NUM_ROWS 16 | 
|  | 31 |  | 
|  | 32 | // Row slots are allocated in chunks of ROW_SLOT_CHUNK_NUM_ROWS, | 
|  | 33 | // with an offset after the rows that points to the next chunk | 
|  | 34 | #define ROW_SLOT_CHUNK_SIZE ((ROW_SLOT_CHUNK_NUM_ROWS * sizeof(row_slot_t)) + sizeof(uint32_t)) | 
|  | 35 |  | 
|  | 36 |  | 
|  | 37 | #if LOG_NDEBUG | 
|  | 38 |  | 
|  | 39 | #define IF_LOG_WINDOW() if (false) | 
|  | 40 | #define LOG_WINDOW(...) | 
|  | 41 |  | 
|  | 42 | #else | 
|  | 43 |  | 
|  | 44 | #define IF_LOG_WINDOW() IF_LOG(LOG_DEBUG, "CursorWindow") | 
|  | 45 | #define LOG_WINDOW(...) LOG(LOG_DEBUG, "CursorWindow", __VA_ARGS__) | 
|  | 46 |  | 
|  | 47 | #endif | 
|  | 48 |  | 
|  | 49 |  | 
|  | 50 | // When defined to true strings are stored as UTF8, otherwise they're UTF16 | 
|  | 51 | #define WINDOW_STORAGE_UTF8 1 | 
|  | 52 |  | 
|  | 53 | // When defined to true numberic values are stored inline in the field_slot_t, otherwise they're allocated in the window | 
|  | 54 | #define WINDOW_STORAGE_INLINE_NUMERICS 1 | 
|  | 55 |  | 
|  | 56 | namespace android { | 
|  | 57 |  | 
|  | 58 | typedef struct | 
|  | 59 | { | 
|  | 60 | uint32_t numRows; | 
|  | 61 | uint32_t numColumns; | 
|  | 62 | } window_header_t; | 
|  | 63 |  | 
|  | 64 | typedef struct | 
|  | 65 | { | 
|  | 66 | uint32_t offset; | 
|  | 67 | } row_slot_t; | 
|  | 68 |  | 
|  | 69 | typedef struct | 
|  | 70 | { | 
|  | 71 | uint8_t type; | 
|  | 72 | union { | 
|  | 73 | double d; | 
|  | 74 | int64_t l; | 
|  | 75 | struct { | 
|  | 76 | uint32_t offset; | 
|  | 77 | uint32_t size; | 
|  | 78 | } buffer; | 
|  | 79 | } data; | 
|  | 80 | } __attribute__((packed)) field_slot_t; | 
|  | 81 |  | 
| Vasu Nori | e733497 | 2010-05-18 11:54:31 -0700 | [diff] [blame] | 82 | #define FIELD_TYPE_NULL 0 | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 83 | #define FIELD_TYPE_INTEGER 1 | 
|  | 84 | #define FIELD_TYPE_FLOAT 2 | 
|  | 85 | #define FIELD_TYPE_STRING 3 | 
|  | 86 | #define FIELD_TYPE_BLOB 4 | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 87 |  | 
|  | 88 | /** | 
|  | 89 | * This class stores a set of rows from a database in a buffer. The begining of the | 
|  | 90 | * window has first chunk of row_slot_ts, which are offsets to the row directory, followed by | 
|  | 91 | * an offset to the next chunk in a linked-list of additional chunk of row_slot_ts in case | 
|  | 92 | * the pre-allocated chunk isn't big enough to refer to all rows. Each row directory has a | 
|  | 93 | * field_slot_t per column, which has the size, offset, and type of the data for that field. | 
|  | 94 | * Note that the data types come from sqlite3.h. | 
|  | 95 | */ | 
|  | 96 | class CursorWindow | 
|  | 97 | { | 
|  | 98 | public: | 
|  | 99 | CursorWindow(size_t maxSize); | 
|  | 100 | CursorWindow(){} | 
|  | 101 | bool                setMemory(const sp<IMemory>&); | 
|  | 102 | ~CursorWindow(); | 
|  | 103 |  | 
|  | 104 | bool                initBuffer(bool localOnly); | 
|  | 105 | sp<IMemory>         getMemory() {return mMemory;} | 
|  | 106 |  | 
|  | 107 | size_t              size() {return mSize;} | 
|  | 108 | uint8_t *           data() {return mData;} | 
|  | 109 | uint32_t            getNumRows() {return mHeader->numRows;} | 
|  | 110 | uint32_t            getNumColumns() {return mHeader->numColumns;} | 
|  | 111 | void                freeLastRow() { | 
|  | 112 | if (mHeader->numRows > 0) { | 
|  | 113 | mHeader->numRows--; | 
|  | 114 | } | 
|  | 115 | } | 
|  | 116 | bool                setNumColumns(uint32_t numColumns) | 
|  | 117 | { | 
|  | 118 | uint32_t cur = mHeader->numColumns; | 
|  | 119 | if (cur > 0 && cur != numColumns) { | 
|  | 120 | LOGE("Trying to go from %d columns to %d", cur, numColumns); | 
|  | 121 | return false; | 
|  | 122 | } | 
|  | 123 | mHeader->numColumns = numColumns; | 
|  | 124 | return true; | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | int32_t             freeSpace(); | 
|  | 128 |  | 
|  | 129 | void                clear(); | 
|  | 130 |  | 
|  | 131 | /** | 
|  | 132 | * Allocate a row slot and its directory. The returned | 
|  | 133 | * pointer points to the begining of the row's directory | 
|  | 134 | * or NULL if there wasn't room. The directory is | 
|  | 135 | * initialied with NULL entries for each field. | 
|  | 136 | */ | 
|  | 137 | field_slot_t *      allocRow(); | 
|  | 138 |  | 
|  | 139 | /** | 
|  | 140 | * Allocate a portion of the window. Returns the offset | 
|  | 141 | * of the allocation, or 0 if there isn't enough space. | 
|  | 142 | * If aligned is true, the allocation gets 4 byte alignment. | 
|  | 143 | */ | 
|  | 144 | uint32_t            alloc(size_t size, bool aligned = false); | 
|  | 145 |  | 
|  | 146 | uint32_t            read_field_slot(int row, int column, field_slot_t * slot); | 
|  | 147 |  | 
|  | 148 | /** | 
|  | 149 | * Copy data into the window at the given offset. | 
|  | 150 | */ | 
|  | 151 | void                copyIn(uint32_t offset, uint8_t const * data, size_t size); | 
|  | 152 | void                copyIn(uint32_t offset, int64_t data); | 
|  | 153 | void                copyIn(uint32_t offset, double data); | 
|  | 154 |  | 
|  | 155 | void                copyOut(uint32_t offset, uint8_t * data, size_t size); | 
|  | 156 | int64_t             copyOutLong(uint32_t offset); | 
|  | 157 | double              copyOutDouble(uint32_t offset); | 
|  | 158 |  | 
|  | 159 | bool                putLong(unsigned int row, unsigned int col, int64_t value); | 
|  | 160 | bool                putDouble(unsigned int row, unsigned int col, double value); | 
|  | 161 | bool                putNull(unsigned int row, unsigned int col); | 
|  | 162 |  | 
|  | 163 | bool                getLong(unsigned int row, unsigned int col, int64_t * valueOut); | 
|  | 164 | bool                getDouble(unsigned int row, unsigned int col, double * valueOut); | 
|  | 165 | bool                getNull(unsigned int row, unsigned int col, bool * valueOut); | 
|  | 166 |  | 
|  | 167 | uint8_t *           offsetToPtr(uint32_t offset) {return mData + offset;} | 
|  | 168 |  | 
|  | 169 | row_slot_t *        allocRowSlot(); | 
|  | 170 |  | 
|  | 171 | row_slot_t *        getRowSlot(int row); | 
| Vasu Nori | e733497 | 2010-05-18 11:54:31 -0700 | [diff] [blame] | 172 |  | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 173 | /** | 
|  | 174 | * return NULL if Failed to find rowSlot or | 
|  | 175 | * Invalid rowSlot | 
|  | 176 | */ | 
|  | 177 | field_slot_t *      getFieldSlotWithCheck(int row, int column); | 
|  | 178 | field_slot_t *      getFieldSlot(int row, int column) | 
|  | 179 | { | 
|  | 180 | int fieldDirOffset = getRowSlot(row)->offset; | 
|  | 181 | return ((field_slot_t *)offsetToPtr(fieldDirOffset)) + column; | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | private: | 
|  | 185 | uint8_t * mData; | 
|  | 186 | size_t mSize; | 
|  | 187 | size_t mMaxSize; | 
|  | 188 | window_header_t * mHeader; | 
|  | 189 | sp<IMemory> mMemory; | 
|  | 190 |  | 
|  | 191 | /** | 
|  | 192 | * Offset of the lowest unused data byte in the array. | 
|  | 193 | */ | 
|  | 194 | uint32_t mFreeOffset; | 
|  | 195 | }; | 
|  | 196 |  | 
|  | 197 | }; // namespace android | 
|  | 198 |  | 
|  | 199 | #endif |