19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006-2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 400adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 500adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * you may not use this file except in compliance with the License. 600adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 800adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1000adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * Unless required by applicable law or agreed to in writing, software 1100adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 1200adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1300adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "CursorWindow" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h> 219d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <binder/Parcel.h> 229d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <utils/Log.h> 230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown#include <cutils/ashmem.h> 250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown#include <sys/mman.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 330cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::CursorWindow(const String8& name, int ashmemFd, 340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown void* data, size_t size, bool readOnly) : 350cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mName(name), mAshmemFd(ashmemFd), mData(data), mSize(size), mReadOnly(readOnly) { 360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader = static_cast<Header*>(mData); 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 390cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::~CursorWindow() { 400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ::munmap(mData, mSize); 410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ::close(mAshmemFd); 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 445e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brownstatus_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) { 450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 ashmemName("CursorWindow: "); 460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ashmemName.append(name); 470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t result; 490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int ashmemFd = ashmem_create_region(ashmemName.string(), size); 500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (ashmemFd < 0) { 510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = -errno; 520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else { 530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE); 540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (result >= 0) { 550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0); 560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (data == MAP_FAILED) { 570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = -errno; 580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else { 590cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = ashmem_set_prot_region(ashmemFd, PROT_READ); 600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (result >= 0) { 610cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window = new CursorWindow(name, ashmemFd, 620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown data, size, false /*readOnly*/); 630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = window->clear(); 640cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!result) { 650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Created new CursorWindow: freeOffset=%d, " 660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown "numRows=%d, numColumns=%d, mSize=%d, mData=%p", 670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->freeOffset, 680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->numRows, 690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->numColumns, 700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mSize, window->mData); 710cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown *outCursorWindow = window; 720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 730cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown delete window; 750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 770cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ::munmap(data, size); 780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ::close(ashmemFd); 800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown *outCursorWindow = NULL; 820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return result; 830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown} 840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) { 860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 name = parcel->readString8(); 870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t result; 890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int ashmemFd = parcel->readFileDescriptor(); 900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (ashmemFd == int(BAD_TYPE)) { 910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = BAD_TYPE; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ssize_t size = ashmem_get_size_region(ashmemFd); 940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (size < 0) { 950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = UNKNOWN_ERROR; 960cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else { 970cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int dupAshmemFd = ::dup(ashmemFd); 980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (dupAshmemFd < 0) { 990cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = -errno; 1000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else { 10145e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov // the size of the ashmem descriptor can be modified between ashmem_get_size_region 10245e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov // call and mmap, so we'll check again immediately after memory is mapped 1030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0); 1040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (data == MAP_FAILED) { 1050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown result = -errno; 10645e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov } else if (ashmem_get_size_region(dupAshmemFd) != size) { 10745e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov ::munmap(data, size); 10845e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov result = BAD_VALUE; 1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else { 1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window = new CursorWindow(name, dupAshmemFd, 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown data, size, true /*readOnly*/); 1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Created CursorWindow from parcel: freeOffset=%d, " 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown "numRows=%d, numColumns=%d, mSize=%d, mData=%p", 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->freeOffset, 1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->numRows, 1160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mHeader->numColumns, 1170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown window->mSize, window->mData); 1180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown *outCursorWindow = window; 1190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 1200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown ::close(dupAshmemFd); 1220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown *outCursorWindow = NULL; 1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return result; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::writeToParcel(Parcel* parcel) { 1300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = parcel->writeString8(mName); 1310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!status) { 1320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = parcel->writeDupFileDescriptor(mAshmemFd); 1330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::clear() { 1380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 1390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 1400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->freeOffset = sizeof(Header) + sizeof(RowSlotChunk); 1430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->firstChunkOffset = sizeof(Header); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeader->numRows = 0; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeader->numColumns = 0; 1460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown RowSlotChunk* firstChunk = static_cast<RowSlotChunk*>(offsetToPtr(mHeader->firstChunkOffset)); 1480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown firstChunk->nextChunkOffset = 0; 1490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::setNumColumns(uint32_t numColumns) { 1530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 1540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 1550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t cur = mHeader->numColumns; 1580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if ((cur > 0 || mHeader->numRows > 0) && cur != numColumns) { 1593762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Trying to go from %d columns to %d", cur, numColumns); 1600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->numColumns = numColumns; 1630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::allocRow() { 1670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 1680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 1690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill in the row slot 1720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown RowSlot* rowSlot = allocRowSlot(); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowSlot == NULL) { 1740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return NO_MEMORY; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Allocate the slots for the field directory 1780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t fieldDirSize = mHeader->numColumns * sizeof(FieldSlot); 1790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t fieldDirOffset = alloc(fieldDirSize, true /*aligned*/); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fieldDirOffset) { 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeader->numRows--; 1820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("The row failed, so back out the new row accounting " 1830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown "from allocRowSlot %d", mHeader->numRows); 1840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return NO_MEMORY; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset)); 1870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown memset(fieldDir, 0, fieldDirSize); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n", 1900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->numRows - 1, offsetFromPtr(rowSlot), fieldDirSize, fieldDirOffset); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowSlot->offset = fieldDirOffset; 1920cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 1930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown} 1940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::freeLastRow() { 1960cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 1970cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 1980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mHeader->numRows > 0) { 2010cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->numRows--; 2020cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 2030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownuint32_t CursorWindow::alloc(size_t size, bool aligned) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t padding; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (aligned) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 4 byte alignment 2100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown padding = (~mHeader->freeOffset + 1) & 3; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project padding = 0; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t offset = mHeader->freeOffset + padding; 2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t nextFreeOffset = offset + size; 2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (nextFreeOffset > mSize) { 218f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat ALOGW("Window is full: requested allocation %zu bytes, " 219f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat "free space %zu bytes, window size %zu bytes", 2200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size, freeSpace(), mSize); 2210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return 0; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->freeOffset = nextFreeOffset; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return offset; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2280cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::RowSlot* CursorWindow::getRowSlot(uint32_t row) { 2290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t chunkPos = row; 2300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown RowSlotChunk* chunk = static_cast<RowSlotChunk*>( 2310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown offsetToPtr(mHeader->firstChunkOffset)); 2320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown while (chunkPos >= ROW_SLOT_CHUNK_NUM_ROWS) { 2330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset)); 2340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return &chunk->slots[chunkPos]; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2390cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::RowSlot* CursorWindow::allocRowSlot() { 2400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t chunkPos = mHeader->numRows; 2410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown RowSlotChunk* chunk = static_cast<RowSlotChunk*>( 2420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown offsetToPtr(mHeader->firstChunkOffset)); 2430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown while (chunkPos > ROW_SLOT_CHUNK_NUM_ROWS) { 2440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset)); 2450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS; 2460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 2470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (chunkPos == ROW_SLOT_CHUNK_NUM_ROWS) { 2480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!chunk->nextChunkOffset) { 2490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunk->nextChunkOffset = alloc(sizeof(RowSlotChunk), true /*aligned*/); 2500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!chunk->nextChunkOffset) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset)); 2550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunk->nextChunkOffset = 0; 2560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown chunkPos = 0; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown mHeader->numRows += 1; 2590cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return &chunk->slots[chunkPos]; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2620cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) { 2630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (row >= mHeader->numRows || column >= mHeader->numColumns) { 2643762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Failed to read row %d, column %d from a CursorWindow which " 2650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown "has %d rows, %d columns.", 2660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown row, column, mHeader->numRows, mHeader->numColumns); 2670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return NULL; 2680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 2690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown RowSlot* rowSlot = getRowSlot(row); 2700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!rowSlot) { 2713762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Failed to find rowSlot for row %d.", row); 2720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return NULL; 2730cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 2740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(rowSlot->offset)); 2750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return &fieldDir[column]; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) { 2790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return putBlobOrString(row, column, value, size, FIELD_TYPE_BLOB); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putString(uint32_t row, uint32_t column, const char* value, 2830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull) { 2840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return putBlobOrString(row, column, value, sizeIncludingNull, FIELD_TYPE_STRING); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putBlobOrString(uint32_t row, uint32_t column, 2880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* value, size_t size, int32_t type) { 2890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 2900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 2910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldSlot = getFieldSlot(row, column); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fieldSlot) { 2950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return BAD_VALUE; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown uint32_t offset = alloc(size); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!offset) { 3000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return NO_MEMORY; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown memcpy(offsetToPtr(offset), value, size); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->type = type; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->data.buffer.offset = offset; 3070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->data.buffer.size = size; 3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putLong(uint32_t row, uint32_t column, int64_t value) { 3120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 3130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldSlot = getFieldSlot(row, column); 3170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!fieldSlot) { 3180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return BAD_VALUE; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->type = FIELD_TYPE_INTEGER; 3220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->data.l = value; 3230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putDouble(uint32_t row, uint32_t column, double value) { 3270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 3280cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldSlot = getFieldSlot(row, column); 3320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (!fieldSlot) { 3330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return BAD_VALUE; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->type = FIELD_TYPE_FLOAT; 3370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->data.d = value; 3380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putNull(uint32_t row, uint32_t column) { 3420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (mReadOnly) { 3430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return INVALID_OPERATION; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown FieldSlot* fieldSlot = getFieldSlot(row, column); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fieldSlot) { 3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return BAD_VALUE; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 3510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->type = FIELD_TYPE_NULL; 3520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->data.buffer.offset = 0; 3530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fieldSlot->data.buffer.size = 0; 3540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return OK; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android 358