blob: 5e645cceea2d21dd3271c7eb3ea0b3c8a637e409 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2007 The Android Open Source Project
3 *
Mark Salyzyn00adb862014-03-19 11:00:06 -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 *
Mark Salyzyn00adb862014-03-19 11:00:06 -07008 * http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009 *
Mark Salyzyn00adb862014-03-19 11:00:06 -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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017#define LOG_TAG "CursorWindow"
18
Mathias Agopian49d2b182012-02-27 18:11:20 -080019#include <androidfw/CursorWindow.h>
Jeff Brown0cde89f2011-10-10 14:50:10 -070020
Todd Frederick7e8b93a2024-10-16 02:10:02 +000021#include <sys/mman.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
Todd Frederick7e8b93a2024-10-16 02:10:02 +000023#include "android-base/logging.h"
24#include "cutils/ashmem.h"
Michael Hoisiee28dd9f2024-03-12 18:15:14 +000025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026namespace android {
27
Jeff Sharkey539fdff2020-09-23 21:43:23 -060028/**
29 * By default windows are lightweight inline allocations of this size;
30 * they're only inflated to ashmem regions when more space is needed.
31 */
32static constexpr const size_t kInlineSize = 16384;
33
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060034static constexpr const size_t kSlotShift = 4;
35static constexpr const size_t kSlotSizeBytes = 1 << kSlotShift;
36
37CursorWindow::CursorWindow() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038}
39
Jeff Brown0cde89f2011-10-10 14:50:10 -070040CursorWindow::~CursorWindow() {
Jeff Sharkey539fdff2020-09-23 21:43:23 -060041 if (mAshmemFd != -1) {
Todd Frederick7e8b93a2024-10-16 02:10:02 +000042 ::munmap(mData, mSize);
Jeff Sharkey539fdff2020-09-23 21:43:23 -060043 ::close(mAshmemFd);
44 } else {
45 free(mData);
46 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047}
48
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060049status_t CursorWindow::create(const String8 &name, size_t inflatedSize, CursorWindow **outWindow) {
50 *outWindow = nullptr;
Jeff Sharkey539fdff2020-09-23 21:43:23 -060051
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060052 CursorWindow* window = new CursorWindow();
53 if (!window) goto fail;
Jeff Sharkey539fdff2020-09-23 21:43:23 -060054
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060055 window->mName = name;
56 window->mSize = std::min(kInlineSize, inflatedSize);
57 window->mInflatedSize = inflatedSize;
58 window->mData = malloc(window->mSize);
59 if (!window->mData) goto fail;
60 window->mReadOnly = false;
61
62 window->clear();
63 window->updateSlotsData();
64
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060065 *outWindow = window;
66 return OK;
67
68fail:
69 LOG(ERROR) << "Failed create";
70fail_silent:
Jeff Sharkey539fdff2020-09-23 21:43:23 -060071 delete window;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060072 return UNKNOWN_ERROR;
Jeff Sharkey539fdff2020-09-23 21:43:23 -060073}
74
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060075status_t CursorWindow::maybeInflate() {
76 int ashmemFd = 0;
77 void* newData = nullptr;
78
79 // Bail early when we can't expand any further
80 if (mReadOnly || mSize == mInflatedSize) {
81 return INVALID_OPERATION;
82 }
Jeff Sharkey539fdff2020-09-23 21:43:23 -060083
Jeff Brown0cde89f2011-10-10 14:50:10 -070084 String8 ashmemName("CursorWindow: ");
Jeff Sharkey539fdff2020-09-23 21:43:23 -060085 ashmemName.append(mName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
Tomasz Wasilczykd2a69832023-08-10 23:54:44 +000087 ashmemFd = ashmem_create_region(ashmemName.c_str(), mInflatedSize);
Jeff Brown0cde89f2011-10-10 14:50:10 -070088 if (ashmemFd < 0) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060089 PLOG(ERROR) << "Failed ashmem_create_region";
90 goto fail_silent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -060092
93 if (ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE) < 0) {
94 PLOG(ERROR) << "Failed ashmem_set_prot_region";
95 goto fail_silent;
96 }
97
Todd Frederick7e8b93a2024-10-16 02:10:02 +000098 newData = ::mmap(nullptr, mInflatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);
99 if (newData == MAP_FAILED) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600100 PLOG(ERROR) << "Failed mmap";
101 goto fail_silent;
102 }
103
104 if (ashmem_set_prot_region(ashmemFd, PROT_READ) < 0) {
105 PLOG(ERROR) << "Failed ashmem_set_prot_region";
106 goto fail_silent;
107 }
108
109 {
110 // Migrate existing contents into new ashmem region
Lee Shombertc7e15902023-05-19 15:52:00 -0700111 uint32_t slotsSize = sizeOfSlots();
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600112 uint32_t newSlotsOffset = mInflatedSize - slotsSize;
113 memcpy(static_cast<uint8_t*>(newData),
114 static_cast<uint8_t*>(mData), mAllocOffset);
115 memcpy(static_cast<uint8_t*>(newData) + newSlotsOffset,
116 static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
117
118 free(mData);
119 mAshmemFd = ashmemFd;
120 mData = newData;
121 mSize = mInflatedSize;
122 mSlotsOffset = newSlotsOffset;
123
124 updateSlotsData();
125 }
126
127 LOG(DEBUG) << "Inflated: " << this->toString();
128 return OK;
129
130fail:
131 LOG(ERROR) << "Failed maybeInflate";
132fail_silent:
Todd Frederick7e8b93a2024-10-16 02:10:02 +0000133 ::munmap(newData, mInflatedSize);
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600134 ::close(ashmemFd);
135 return UNKNOWN_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136}
137
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600138status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outWindow) {
139 *outWindow = nullptr;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700140
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600141 CursorWindow* window = new CursorWindow();
142 if (!window) goto fail;
143
144 if (parcel->readString8(&window->mName)) goto fail;
145 if (parcel->readUint32(&window->mNumRows)) goto fail;
146 if (parcel->readUint32(&window->mNumColumns)) goto fail;
147 if (parcel->readUint32(&window->mSize)) goto fail;
148
149 if ((window->mNumRows * window->mNumColumns * kSlotSizeBytes) > window->mSize) {
150 LOG(ERROR) << "Unexpected size " << window->mSize << " for " << window->mNumRows
151 << " rows and " << window->mNumColumns << " columns";
152 goto fail_silent;
153 }
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600154
155 bool isAshmem;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600156 if (parcel->readBool(&isAshmem)) goto fail;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600157 if (isAshmem) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600158 window->mAshmemFd = parcel->readFileDescriptor();
159 if (window->mAshmemFd < 0) {
160 LOG(ERROR) << "Failed readFileDescriptor";
161 goto fail_silent;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700162 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600163
164 window->mAshmemFd = ::fcntl(window->mAshmemFd, F_DUPFD_CLOEXEC, 0);
165 if (window->mAshmemFd < 0) {
166 PLOG(ERROR) << "Failed F_DUPFD_CLOEXEC";
167 goto fail_silent;
168 }
169
Todd Frederick7e8b93a2024-10-16 02:10:02 +0000170 window->mData = ::mmap(nullptr, window->mSize, PROT_READ, MAP_SHARED, window->mAshmemFd, 0);
171 if (window->mData == MAP_FAILED) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600172 PLOG(ERROR) << "Failed mmap";
173 goto fail_silent;
174 }
175 } else {
176 window->mAshmemFd = -1;
177
178 if (window->mSize > kInlineSize) {
179 LOG(ERROR) << "Unexpected size " << window->mSize << " for inline window";
180 goto fail_silent;
181 }
182
183 window->mData = malloc(window->mSize);
184 if (!window->mData) goto fail;
185
186 if (parcel->read(window->mData, window->mSize)) goto fail;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600189 // We just came from a remote source, so we're read-only
190 // and we can't inflate ourselves
191 window->mInflatedSize = window->mSize;
192 window->mReadOnly = true;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600193
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600194 window->updateSlotsData();
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600195
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600196 LOG(DEBUG) << "Created from parcel: " << window->toString();
197 *outWindow = window;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600198 return OK;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600199
200fail:
201 LOG(ERROR) << "Failed createFromParcel";
202fail_silent:
203 delete window;
204 return UNKNOWN_ERROR;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600205}
206
Jeff Brown0cde89f2011-10-10 14:50:10 -0700207status_t CursorWindow::writeToParcel(Parcel* parcel) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600208 LOG(DEBUG) << "Writing to parcel: " << this->toString();
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600209
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600210 if (parcel->writeString8(mName)) goto fail;
211 if (parcel->writeUint32(mNumRows)) goto fail;
212 if (parcel->writeUint32(mNumColumns)) goto fail;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600213 if (mAshmemFd != -1) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600214 if (parcel->writeUint32(mSize)) goto fail;
215 if (parcel->writeBool(true)) goto fail;
216 if (parcel->writeDupFileDescriptor(mAshmemFd)) goto fail;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600217 } else {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600218 // Since we know we're going to be read-only on the remote side,
Lee Shombertc7e15902023-05-19 15:52:00 -0700219 // we can compact ourselves on the wire.
220 size_t slotsSize = sizeOfSlots();
221 size_t compactedSize = sizeInUse();
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600222 if (parcel->writeUint32(compactedSize)) goto fail;
223 if (parcel->writeBool(false)) goto fail;
224 void* dest = parcel->writeInplace(compactedSize);
225 if (!dest) goto fail;
226 memcpy(static_cast<uint8_t*>(dest),
227 static_cast<uint8_t*>(mData), mAllocOffset);
228 memcpy(static_cast<uint8_t*>(dest) + compactedSize - slotsSize,
229 static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
Jeff Brown0cde89f2011-10-10 14:50:10 -0700230 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600231 return OK;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600232
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600233fail:
234 LOG(ERROR) << "Failed writeToParcel";
235fail_silent:
236 return UNKNOWN_ERROR;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700237}
238
239status_t CursorWindow::clear() {
240 if (mReadOnly) {
241 return INVALID_OPERATION;
242 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600243 mAllocOffset = 0;
244 mSlotsOffset = mSize;
245 mNumRows = 0;
246 mNumColumns = 0;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700247 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248}
249
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600250void CursorWindow::updateSlotsData() {
Jeff Sharkey256da5a2020-10-13 09:40:52 -0600251 mSlotsStart = static_cast<uint8_t*>(mData) + mSize - kSlotSizeBytes;
252 mSlotsEnd = static_cast<uint8_t*>(mData) + mSlotsOffset;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600253}
254
255void* CursorWindow::offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
256 if (offset > mSize) {
257 LOG(ERROR) << "Offset " << offset
258 << " out of bounds, max value " << mSize;
259 return nullptr;
260 }
261 if (offset + bufferSize > mSize) {
262 LOG(ERROR) << "End offset " << (offset + bufferSize)
263 << " out of bounds, max value " << mSize;
264 return nullptr;
265 }
266 return static_cast<uint8_t*>(mData) + offset;
267}
268
269uint32_t CursorWindow::offsetFromPtr(void* ptr) {
270 return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData);
271}
272
Jeff Brown0cde89f2011-10-10 14:50:10 -0700273status_t CursorWindow::setNumColumns(uint32_t numColumns) {
274 if (mReadOnly) {
275 return INVALID_OPERATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600277 uint32_t cur = mNumColumns;
278 if ((cur > 0 || mNumRows > 0) && cur != numColumns) {
279 LOG(ERROR) << "Trying to go from " << cur << " columns to " << numColumns;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700280 return INVALID_OPERATION;
281 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600282 mNumColumns = numColumns;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700283 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284}
285
Jeff Brown0cde89f2011-10-10 14:50:10 -0700286status_t CursorWindow::allocRow() {
287 if (mReadOnly) {
288 return INVALID_OPERATION;
289 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600290 size_t size = mNumColumns * kSlotSizeBytes;
Jeff Sharkeyb2bbdaa2020-10-20 13:19:04 -0600291 int32_t newOffset = mSlotsOffset - size;
292 if (newOffset < (int32_t) mAllocOffset) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600293 maybeInflate();
294 newOffset = mSlotsOffset - size;
Jeff Sharkeyb2bbdaa2020-10-20 13:19:04 -0600295 if (newOffset < (int32_t) mAllocOffset) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600296 return NO_MEMORY;
297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600299 memset(offsetToPtr(newOffset), 0, size);
300 mSlotsOffset = newOffset;
Jeff Sharkey256da5a2020-10-13 09:40:52 -0600301 updateSlotsData();
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600302 mNumRows++;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700303 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304}
305
Jeff Brown0cde89f2011-10-10 14:50:10 -0700306status_t CursorWindow::freeLastRow() {
307 if (mReadOnly) {
308 return INVALID_OPERATION;
309 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600310 size_t size = mNumColumns * kSlotSizeBytes;
Jeff Sharkeyb2bbdaa2020-10-20 13:19:04 -0600311 size_t newOffset = mSlotsOffset + size;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600312 if (newOffset > mSize) {
313 return NO_MEMORY;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700314 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600315 mSlotsOffset = newOffset;
Jeff Sharkey256da5a2020-10-13 09:40:52 -0600316 updateSlotsData();
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600317 mNumRows--;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700318 return OK;
319}
320
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600321status_t CursorWindow::alloc(size_t size, uint32_t* outOffset) {
322 if (mReadOnly) {
323 return INVALID_OPERATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600325 size_t alignedSize = (size + 3) & ~3;
Jeff Sharkeyb2bbdaa2020-10-20 13:19:04 -0600326 size_t newOffset = mAllocOffset + alignedSize;
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600327 if (newOffset > mSlotsOffset) {
328 maybeInflate();
329 newOffset = mAllocOffset + alignedSize;
330 if (newOffset > mSlotsOffset) {
331 return NO_MEMORY;
Jeff Sharkey539fdff2020-09-23 21:43:23 -0600332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600334 *outOffset = mAllocOffset;
335 mAllocOffset = newOffset;
336 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337}
338
Jeff Brown0cde89f2011-10-10 14:50:10 -0700339CursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) {
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600340 // This is carefully tuned to use as few cycles as
341 // possible, since this is an extremely hot code path;
342 // see CursorWindow_bench.cpp for more details
Jeff Sharkey256da5a2020-10-13 09:40:52 -0600343 void *result = static_cast<uint8_t*>(mSlotsStart)
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600344 - (((row * mNumColumns) + column) << kSlotShift);
Jeff Sharkeyb2bbdaa2020-10-20 13:19:04 -0600345 if (result < mSlotsEnd || result > mSlotsStart || column >= mNumColumns) {
Jeff Sharkey256da5a2020-10-13 09:40:52 -0600346 LOG(ERROR) << "Failed to read row " << row << ", column " << column
347 << " from a window with " << mNumRows << " rows, " << mNumColumns << " columns";
348 return nullptr;
349 } else {
350 return static_cast<FieldSlot*>(result);
351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352}
353
Jeff Brown0cde89f2011-10-10 14:50:10 -0700354status_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) {
355 return putBlobOrString(row, column, value, size, FIELD_TYPE_BLOB);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356}
357
Jeff Brown0cde89f2011-10-10 14:50:10 -0700358status_t CursorWindow::putString(uint32_t row, uint32_t column, const char* value,
359 size_t sizeIncludingNull) {
360 return putBlobOrString(row, column, value, sizeIncludingNull, FIELD_TYPE_STRING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361}
362
Jeff Brown0cde89f2011-10-10 14:50:10 -0700363status_t CursorWindow::putBlobOrString(uint32_t row, uint32_t column,
364 const void* value, size_t size, int32_t type) {
365 if (mReadOnly) {
366 return INVALID_OPERATION;
367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368
Jeff Brown0cde89f2011-10-10 14:50:10 -0700369 FieldSlot* fieldSlot = getFieldSlot(row, column);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 if (!fieldSlot) {
Jeff Brown0cde89f2011-10-10 14:50:10 -0700371 return BAD_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 }
373
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600374 uint32_t offset;
375 if (alloc(size, &offset)) {
Jeff Brown0cde89f2011-10-10 14:50:10 -0700376 return NO_MEMORY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
378
Jeff Brown0cde89f2011-10-10 14:50:10 -0700379 memcpy(offsetToPtr(offset), value, size);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380
Jeff Sharkeyae2d88a2020-09-26 18:57:32 -0600381 fieldSlot = getFieldSlot(row, column);
Jeff Brown0cde89f2011-10-10 14:50:10 -0700382 fieldSlot->type = type;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 fieldSlot->data.buffer.offset = offset;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700384 fieldSlot->data.buffer.size = size;
385 return OK;
386}
387
388status_t CursorWindow::putLong(uint32_t row, uint32_t column, int64_t value) {
389 if (mReadOnly) {
390 return INVALID_OPERATION;
391 }
392
393 FieldSlot* fieldSlot = getFieldSlot(row, column);
394 if (!fieldSlot) {
395 return BAD_VALUE;
396 }
397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 fieldSlot->type = FIELD_TYPE_INTEGER;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700399 fieldSlot->data.l = value;
400 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401}
402
Jeff Brown0cde89f2011-10-10 14:50:10 -0700403status_t CursorWindow::putDouble(uint32_t row, uint32_t column, double value) {
404 if (mReadOnly) {
405 return INVALID_OPERATION;
406 }
407
408 FieldSlot* fieldSlot = getFieldSlot(row, column);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 if (!fieldSlot) {
Jeff Brown0cde89f2011-10-10 14:50:10 -0700410 return BAD_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 }
412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 fieldSlot->type = FIELD_TYPE_FLOAT;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700414 fieldSlot->data.d = value;
415 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416}
417
Jeff Brown0cde89f2011-10-10 14:50:10 -0700418status_t CursorWindow::putNull(uint32_t row, uint32_t column) {
419 if (mReadOnly) {
420 return INVALID_OPERATION;
421 }
422
423 FieldSlot* fieldSlot = getFieldSlot(row, column);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 if (!fieldSlot) {
Jeff Brown0cde89f2011-10-10 14:50:10 -0700425 return BAD_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 }
427
428 fieldSlot->type = FIELD_TYPE_NULL;
429 fieldSlot->data.buffer.offset = 0;
430 fieldSlot->data.buffer.size = 0;
Jeff Brown0cde89f2011-10-10 14:50:10 -0700431 return OK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432}
433
434}; // namespace android