blob: f0b2909dce9330f79a0e99725bc14629a78515ec [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
Vasu Nori8b0dd7d2010-05-18 11:54:31 -07004 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007 *
Vasu Nori8b0dd7d2010-05-18 11:54:31 -07008 * http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009 *
Vasu Nori8b0dd7d2010-05-18 11:54:31 -070010 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014 * 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
Mathias Agopiand1f74d02010-01-29 16:54:04 -080024#include <binder/IMemory.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025#include <utils/RefBase.h>
26
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027#define DEFAULT_WINDOW_SIZE 4096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028#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
56namespace android {
57
58typedef struct
59{
60 uint32_t numRows;
61 uint32_t numColumns;
62} window_header_t;
63
64typedef struct
65{
66 uint32_t offset;
67} row_slot_t;
68
69typedef 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 Nori8b0dd7d2010-05-18 11:54:31 -070082#define FIELD_TYPE_NULL 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083#define FIELD_TYPE_INTEGER 1
84#define FIELD_TYPE_FLOAT 2
85#define FIELD_TYPE_STRING 3
86#define FIELD_TYPE_BLOB 4
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087
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 */
96class CursorWindow
97{
98public:
99 CursorWindow(size_t maxSize);
100 CursorWindow(){}
Mathias Agopiand1f74d02010-01-29 16:54:04 -0800101 bool setMemory(const sp<IMemory>&);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 ~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 Nori8b0dd7d2010-05-18 11:54:31 -0700172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 /**
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
184private:
185 uint8_t * mData;
186 size_t mSize;
187 size_t mMaxSize;
188 window_header_t * mHeader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 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