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 59namespace android { 60 61typedef struct 62{ 63 uint32_t numRows; 64 uint32_t numColumns; 65} window_header_t; 66 67typedef struct 68{ 69 uint32_t offset; 70} row_slot_t; 71 72typedef 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 */ 99class CursorWindow 100{ 101public: 102 CursorWindow(size_t maxSize); 103 CursorWindow(){} 104 bool setMemory(const sp<IMemory>&); 105 ~CursorWindow(); 106 107 bool initBuffer(bool localOnly); 108 sp<IMemory> getMemory() {return mMemory;} 109 110 size_t size() {return mSize;} 111 uint8_t * data() {return mData;} 112 uint32_t getNumRows() {return mHeader->numRows;} 113 uint32_t getNumColumns() {return mHeader->numColumns;} 114 void freeLastRow() { 115 if (mHeader->numRows > 0) { 116 mHeader->numRows--; 117 } 118 } 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 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); 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 187private: 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