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