| 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 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 24 | #include <binder/Parcel.h> | 
 | 25 | #include <utils/String8.h> | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 26 |  | 
 | 27 | #if LOG_NDEBUG | 
 | 28 |  | 
 | 29 | #define IF_LOG_WINDOW() if (false) | 
 | 30 | #define LOG_WINDOW(...) | 
 | 31 |  | 
 | 32 | #else | 
 | 33 |  | 
 | 34 | #define IF_LOG_WINDOW() IF_LOG(LOG_DEBUG, "CursorWindow") | 
 | 35 | #define LOG_WINDOW(...) LOG(LOG_DEBUG, "CursorWindow", __VA_ARGS__) | 
 | 36 |  | 
 | 37 | #endif | 
 | 38 |  | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 39 | namespace android { | 
 | 40 |  | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 41 | /** | 
 | 42 |  * This class stores a set of rows from a database in a buffer. The begining of the | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 43 |  * window has first chunk of RowSlots, which are offsets to the row directory, followed by | 
 | 44 |  * an offset to the next chunk in a linked-list of additional chunk of RowSlots in case | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 45 |  * the pre-allocated chunk isn't big enough to refer to all rows. Each row directory has a | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 46 |  * FieldSlot per column, which has the size, offset, and type of the data for that field. | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 47 |  * Note that the data types come from sqlite3.h. | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 48 |  * | 
 | 49 |  * Strings are stored in UTF-8. | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 50 |  */ | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 51 | class CursorWindow { | 
 | 52 |     CursorWindow(const String8& name, int ashmemFd, | 
 | 53 |             void* data, size_t size, bool readOnly); | 
 | 54 |  | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 55 | public: | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 56 |     /* Field types. */ | 
 | 57 |     enum { | 
 | 58 |         FIELD_TYPE_NULL = 0, | 
 | 59 |         FIELD_TYPE_INTEGER = 1, | 
 | 60 |         FIELD_TYPE_FLOAT = 2, | 
 | 61 |         FIELD_TYPE_STRING = 3, | 
 | 62 |         FIELD_TYPE_BLOB = 4, | 
 | 63 |     }; | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 64 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 65 |     /* Opaque type that describes a field slot. */ | 
 | 66 |     struct FieldSlot { | 
 | 67 |     private: | 
 | 68 |         int32_t type; | 
 | 69 |         union { | 
 | 70 |             double d; | 
 | 71 |             int64_t l; | 
 | 72 |             struct { | 
 | 73 |                 uint32_t offset; | 
 | 74 |                 uint32_t size; | 
 | 75 |             } buffer; | 
 | 76 |         } data; | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 77 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 78 |         friend class CursorWindow; | 
 | 79 |     } __attribute((packed)); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 80 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 81 |     ~CursorWindow(); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 82 |  | 
| Jeff Brown | 3e2fb70 | 2011-10-12 15:41:34 -0700 | [diff] [blame] | 83 |     static status_t create(const String8& name, size_t size, CursorWindow** outCursorWindow); | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 84 |     static status_t createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 85 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 86 |     status_t writeToParcel(Parcel* parcel); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 87 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 88 |     inline String8 name() { return mName; } | 
 | 89 |     inline size_t size() { return mSize; } | 
 | 90 |     inline size_t freeSpace() { return mSize - mHeader->freeOffset; } | 
 | 91 |     inline uint32_t getNumRows() { return mHeader->numRows; } | 
 | 92 |     inline uint32_t getNumColumns() { return mHeader->numColumns; } | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 93 |  | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 94 |     status_t clear(); | 
 | 95 |     status_t setNumColumns(uint32_t numColumns); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 96 |  | 
 | 97 |     /** | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 98 |      * Allocate a row slot and its directory. | 
 | 99 |      * The row is initialized will null entries for each field. | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 100 |      */ | 
| Jeff Brown | ec4e006 | 2011-10-10 14:50:10 -0700 | [diff] [blame] | 101 |     status_t allocRow(); | 
 | 102 |     status_t freeLastRow(); | 
 | 103 |  | 
 | 104 |     status_t putBlob(uint32_t row, uint32_t column, const void* value, size_t size); | 
 | 105 |     status_t putString(uint32_t row, uint32_t column, const char* value, size_t sizeIncludingNull); | 
 | 106 |     status_t putLong(uint32_t row, uint32_t column, int64_t value); | 
 | 107 |     status_t putDouble(uint32_t row, uint32_t column, double value); | 
 | 108 |     status_t putNull(uint32_t row, uint32_t column); | 
 | 109 |  | 
 | 110 |     /** | 
 | 111 |      * Gets the field slot at the specified row and column. | 
 | 112 |      * Returns null if the requested row or column is not in the window. | 
 | 113 |      */ | 
 | 114 |     FieldSlot* getFieldSlot(uint32_t row, uint32_t column); | 
 | 115 |  | 
 | 116 |     inline int32_t getFieldSlotType(FieldSlot* fieldSlot) { | 
 | 117 |         return fieldSlot->type; | 
 | 118 |     } | 
 | 119 |  | 
 | 120 |     inline int64_t getFieldSlotValueLong(FieldSlot* fieldSlot) { | 
 | 121 |         return fieldSlot->data.l; | 
 | 122 |     } | 
 | 123 |  | 
 | 124 |     inline double getFieldSlotValueDouble(FieldSlot* fieldSlot) { | 
 | 125 |         return fieldSlot->data.d; | 
 | 126 |     } | 
 | 127 |  | 
 | 128 |     inline const char* getFieldSlotValueString(FieldSlot* fieldSlot, | 
 | 129 |             size_t* outSizeIncludingNull) { | 
 | 130 |         *outSizeIncludingNull = fieldSlot->data.buffer.size; | 
 | 131 |         return static_cast<char*>(offsetToPtr(fieldSlot->data.buffer.offset)); | 
 | 132 |     } | 
 | 133 |  | 
 | 134 |     inline const void* getFieldSlotValueBlob(FieldSlot* fieldSlot, size_t* outSize) { | 
 | 135 |         *outSize = fieldSlot->data.buffer.size; | 
 | 136 |         return offsetToPtr(fieldSlot->data.buffer.offset); | 
 | 137 |     } | 
 | 138 |  | 
 | 139 | private: | 
 | 140 |     static const size_t ROW_SLOT_CHUNK_NUM_ROWS = 100; | 
 | 141 |  | 
 | 142 |     struct Header { | 
 | 143 |         // Offset of the lowest unused byte in the window. | 
 | 144 |         uint32_t freeOffset; | 
 | 145 |  | 
 | 146 |         // Offset of the first row slot chunk. | 
 | 147 |         uint32_t firstChunkOffset; | 
 | 148 |  | 
 | 149 |         uint32_t numRows; | 
 | 150 |         uint32_t numColumns; | 
 | 151 |     }; | 
 | 152 |  | 
 | 153 |     struct RowSlot { | 
 | 154 |         uint32_t offset; | 
 | 155 |     }; | 
 | 156 |  | 
 | 157 |     struct RowSlotChunk { | 
 | 158 |         RowSlot slots[ROW_SLOT_CHUNK_NUM_ROWS]; | 
 | 159 |         uint32_t nextChunkOffset; | 
 | 160 |     }; | 
 | 161 |  | 
 | 162 |     String8 mName; | 
 | 163 |     int mAshmemFd; | 
 | 164 |     void* mData; | 
 | 165 |     size_t mSize; | 
 | 166 |     bool mReadOnly; | 
 | 167 |     Header* mHeader; | 
 | 168 |  | 
 | 169 |     inline void* offsetToPtr(uint32_t offset) { | 
 | 170 |         return static_cast<uint8_t*>(mData) + offset; | 
 | 171 |     } | 
 | 172 |  | 
 | 173 |     inline uint32_t offsetFromPtr(void* ptr) { | 
 | 174 |         return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData); | 
 | 175 |     } | 
 | 176 |  | 
 | 177 |     /** | 
 | 178 |      * Allocate a portion of the window. Returns the offset | 
 | 179 |      * of the allocation, or 0 if there isn't enough space. | 
 | 180 |      * If aligned is true, the allocation gets 4 byte alignment. | 
 | 181 |      */ | 
 | 182 |     uint32_t alloc(size_t size, bool aligned = false); | 
 | 183 |  | 
 | 184 |     RowSlot* getRowSlot(uint32_t row); | 
 | 185 |     RowSlot* allocRowSlot(); | 
 | 186 |  | 
 | 187 |     status_t putBlobOrString(uint32_t row, uint32_t column, | 
 | 188 |             const void* value, size_t size, int32_t type); | 
| Mike Lockwood | 244a765 | 2010-05-27 17:04:23 -0400 | [diff] [blame] | 189 | }; | 
 | 190 |  | 
 | 191 | }; // namespace android | 
 | 192 |  | 
 | 193 | #endif |