android_database_CursorWindow.cpp revision 715311fa5aeb39fd0904209e1428a3656c721c3d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 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
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h>
273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#include <utils/Unicode.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
332807df89af680e46cb35ee0035bb10b42d3136a2Mike Lockwood#include "binder/CursorWindow.h"
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "sqlite3_exception.h"
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h"
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic struct {
403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jfieldID data;
413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jfieldID sizeCopied;
423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} gCharArrayBufferClassInfo;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring gEmptyString;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwExceptionWithRowCol(JNIEnv* env, jint row, jint column) {
473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    String8 msg;
483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    msg.appendFormat("Couldn't read row %d, col %d from CursorWindow.  "
493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            "Make sure the Cursor is initialized correctly before accessing data from it.",
503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            row, column);
513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jniThrowException(env, "java/lang/IllegalStateException", msg.string());
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwUnknownTypeException(JNIEnv * env, jint type) {
553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    String8 msg;
563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    msg.appendFormat("UNKNOWN type %d", type);
573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jniThrowException(env, "java/lang/IllegalStateException", msg.string());
583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeInitializeEmpty(JNIEnv* env, jclass clazz,
613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint cursorWindowSize, jboolean localOnly) {
623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = new CursorWindow(cursorWindowSize);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!window) {
643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!window->initBuffer(localOnly)) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete window;
683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("nativeInitializeEmpty: window = %p", window);
723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return reinterpret_cast<jint>(window);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeInitializeFromBinder(JNIEnv* env, jclass clazz, jobject binderObj) {
763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    sp<IMemory> memory = interface_cast<IMemory>(ibinderForJavaObject(env, binderObj));
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (memory == NULL) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException", "Couldn't get native binder");
793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = new CursorWindow();
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!window) {
843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!window->setMemory(memory)) {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete window;
883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p",
923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            window->getNumRows(), window->getNumColumns(), window);
933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return reinterpret_cast<jint>(window);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) {
973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (window) {
993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        LOG_WINDOW("Closing window %p", window);
1003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        delete window;
1013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
1023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
1033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
1043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jobject nativeGetBinder(JNIEnv * env, jclass clazz, jint windowPtr) {
1053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (window) {
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<IMemory> memory = window->getMemory();
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (memory != NULL) {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<IBinder> binder = memory->asBinder();
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return javaObjectForIBinder(env, binder);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeClear(JNIEnv * env, jclass clazz, jint windowPtr) {
1173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Clearing window %p", window);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    window->clear();
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetNumRows(JNIEnv* env, jclass clazz, jint windowPtr) {
1233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return window->getNumRows();
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeSetNumColumns(JNIEnv* env, jclass clazz, jint windowPtr,
1283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint columnNum) {
1293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return window->setNumColumns(columnNum);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeAllocRow(JNIEnv* env, jclass clazz, jint windowPtr) {
1343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return window->allocRow() != NULL;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeFreeLastRow(JNIEnv* env, jclass clazz, jint windowPtr) {
1393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    window->freeLastRow();
1413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetType(JNIEnv* env, jclass clazz, jint windowPtr,
1443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
1453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window);
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
1493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
150aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown        // FIXME: This is really broken but we have CTS tests that depend
151aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown        // on this legacy behavior.
152aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown        //throwExceptionWithRowCol(env, row, column);
153aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown        return FIELD_TYPE_NULL;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return fieldSlot->type;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jint windowPtr,
1593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
1603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window);
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
1643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throwExceptionWithRowCol(env, row, column);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint8_t type = fieldSlot->type;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == FIELD_TYPE_BLOB || type == FIELD_TYPE_STRING) {
1713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        uint32_t size = fieldSlot->data.buffer.size;
1723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jbyteArray byteArray = env->NewByteArray(size);
173e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori        if (!byteArray) {
1743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            env->ExceptionClear();
175e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori            throw_sqlite3_exception(env, "Native could not create new byte[]");
176e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori            return NULL;
177e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori        }
1783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->SetByteArrayRegion(byteArray, 0, size,
1793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                reinterpret_cast<jbyte*>(window->offsetToPtr(fieldSlot->data.buffer.offset)));
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return byteArray;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_INTEGER) {
1823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob ");
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_FLOAT) {
1843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob ");
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_NULL) {
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do nothing
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwUnknownTypeException(env, type);
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NULL;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring nativeGetString(JNIEnv* env, jclass clazz, jint windowPtr,
1943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
1953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
1963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Getting string for %d,%d from %p", row, column, window);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
1993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throwExceptionWithRowCol(env, row, column);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint8_t type = fieldSlot->type;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == FIELD_TYPE_STRING) {
2063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        uint32_t size = fieldSlot->data.buffer.size;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
208715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        if (size <= 1) {
209715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown            return gEmptyString;
210715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        }
211715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        // Convert to UTF-16 here instead of calling NewStringUTF.  NewStringUTF
212715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        // doesn't like UTF-8 strings with high codepoints.  It actually expects
213715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        // Modified UTF-8 with encoded surrogate pairs.
214715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        String16 utf16(window->getFieldSlotValueString(fieldSlot), size - 1);
215715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown        return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size());
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
2173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        size_t chars = size / sizeof(char16_t);
2183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return chars ? env->NewString(reinterpret_cast<jchar*>(
2193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                window->getFieldSlotValueString(fieldSlot)), chars)
2203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                : gEmptyString;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_INTEGER) {
2233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        int64_t value = window->getFieldSlotValueLong(fieldSlot);
2243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        char buf[32];
2253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        snprintf(buf, sizeof(buf), "%lld", value);
2263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return env->NewStringUTF(buf);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_FLOAT) {
2283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        double value = window->getFieldSlotValueDouble(fieldSlot);
2293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        char buf[32];
2303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        snprintf(buf, sizeof(buf), "%g", value);
2313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return env->NewStringUTF(buf);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_NULL) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_BLOB) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw_sqlite3_exception(env, "Unable to convert BLOB to string");
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwUnknownTypeException(env, type);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jcharArray allocCharArrayBuffer(JNIEnv* env, jobject bufferObj, size_t size) {
2443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jcharArray dataObj = jcharArray(env->GetObjectField(bufferObj,
2453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            gCharArrayBufferClassInfo.data));
2463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (dataObj && size) {
2473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jsize capacity = env->GetArrayLength(dataObj);
2483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (size_t(capacity) < size) {
2493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            env->DeleteLocalRef(dataObj);
2503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            dataObj = NULL;
2513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
2523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
2533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!dataObj) {
2543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jsize capacity = size;
2553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (capacity < 64) {
2563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            capacity = 64;
2573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
2583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        dataObj = env->NewCharArray(capacity); // might throw OOM
2593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (dataObj) {
2603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            env->SetObjectField(bufferObj, gCharArrayBufferClassInfo.data, dataObj);
2613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
2623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
2633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    return dataObj;
2643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBufferUTF(JNIEnv* env, jobject bufferObj,
2673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        const char* str, size_t len) {
2683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    ssize_t size = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str), len);
2693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (size < 0) {
2703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        size = 0; // invalid UTF8 string
2713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
2723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, size);
2733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (dataObj) {
2743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (size) {
2753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL));
276d0ff68da6a606602235fb8749473999e3d1bde53Jeff Brown            utf8_to_utf16_no_null_terminator(reinterpret_cast<const uint8_t*>(str), len,
2773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                    reinterpret_cast<char16_t*>(data));
2783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            env->ReleasePrimitiveArrayCritical(dataObj, data, 0);
2793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
2803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, size);
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#if !WINDOW_STORAGE_UTF8
2853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBuffer(JNIEnv* env, jobject bufferObj,
2863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        const char16_t* str, size_t len) {
2873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, len);
2883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (dataObj) {
2893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (len) {
2903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL));
2913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            memcpy(data, str, len * sizeof(jchar));
2923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            env->ReleasePrimitiveArrayCritical(dataObj, data, 0);
2933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
2943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, len);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#endif
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void clearCharArrayBuffer(JNIEnv* env, jobject bufferObj) {
3003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, 0);
3013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (dataObj) {
3023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, 0);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
30503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana
3063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeCopyStringToBuffer(JNIEnv* env, jclass clazz, jint windowPtr,
3073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column, jobject bufferObj) {
3083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
3093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Copying string for %d,%d from %p", row, column, window);
3103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
3123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
3133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwExceptionWithRowCol(env, row, column);
3143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint8_t type = fieldSlot->type;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == FIELD_TYPE_STRING) {
3193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        uint32_t size = fieldSlot->data.buffer.size;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
3213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (size > 1) {
3223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            fillCharArrayBufferUTF(env, bufferObj,
3233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                    window->getFieldSlotValueString(fieldSlot), size - 1);
3243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        } else {
3253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            clearCharArrayBuffer(env, bufferObj);
3263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
3283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        size_t chars = size / sizeof(char16_t);
3293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        if (chars) {
3303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            fillCharArrayBuffer(env, bufferObj,
3313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                    window->getFieldSlotValueString(fieldSlot), chars);
3323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        } else {
3333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            clearCharArrayBuffer(env, bufferObj);
33403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        }
3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#endif
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_INTEGER) {
3373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        int64_t value = window->getFieldSlotValueLong(fieldSlot);
3383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        char buf[32];
3393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        snprintf(buf, sizeof(buf), "%lld", value);
3403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf));
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_FLOAT) {
3423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        double value = window->getFieldSlotValueDouble(fieldSlot);
3433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        char buf[32];
3443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        snprintf(buf, sizeof(buf), "%g", value);
3453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf));
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_NULL) {
3473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        clearCharArrayBuffer(env, bufferObj);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_BLOB) {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw_sqlite3_exception(env, "Unable to convert BLOB to string");
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwUnknownTypeException(env, type);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jlong nativeGetLong(JNIEnv* env, jclass clazz, jint windowPtr,
3563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
3573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
3583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Getting long for %d,%d from %p", row, column, window);
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
3613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
3623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwExceptionWithRowCol(env, row, column);
3633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
3643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
3653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint8_t type = fieldSlot->type;
3673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (type == FIELD_TYPE_INTEGER) {
3683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return window->getFieldSlotValueLong(fieldSlot);
3693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    } else if (type == FIELD_TYPE_STRING) {
3703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        uint32_t size = fieldSlot->data.buffer.size;
3713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#if WINDOW_STORAGE_UTF8
3723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return size > 1 ? strtoll(window->getFieldSlotValueString(fieldSlot), NULL, 0) : 0L;
3733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#else
3743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        size_t chars = size / sizeof(char16_t);
3753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return chars ? strtoll(String8(window->getFieldSlotValueString(fieldSlot), chars)
3763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                .string(), NULL, 0) : 0L;
3773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#endif
3783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    } else if (type == FIELD_TYPE_FLOAT) {
3793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return jlong(window->getFieldSlotValueDouble(fieldSlot));
3803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    } else if (type == FIELD_TYPE_NULL) {
3813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
3823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    } else if (type == FIELD_TYPE_BLOB) {
3833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throw_sqlite3_exception(env, "Unable to convert BLOB to long");
3843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
3853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    } else {
3863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwUnknownTypeException(env, type);
3873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return 0;
3883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    }
3893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown}
3903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jint windowPtr,
3923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
3933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
3943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("Getting double for %d,%d from %p", row, column, window);
3953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t* fieldSlot = window->getFieldSlotWithCheck(row, column);
3973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!fieldSlot) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throwExceptionWithRowCol(env, row, column);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0.0;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint8_t type = fieldSlot->type;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == FIELD_TYPE_FLOAT) {
4043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return window->getFieldSlotValueDouble(fieldSlot);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_STRING) {
4063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        uint32_t size = fieldSlot->data.buffer.size;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
4083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return size > 1 ? strtod(window->getFieldSlotValueString(fieldSlot), NULL) : 0.0;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
4103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        size_t chars = size / sizeof(char16_t);
4113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return chars ? strtod(String8(window->getFieldSlotValueString(fieldSlot), chars)
4123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown                .string(), NULL) : 0.0;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_INTEGER) {
4153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        return jdouble(window->getFieldSlotValueLong(fieldSlot));
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_NULL) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0.0;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == FIELD_TYPE_BLOB) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw_sqlite3_exception(env, "Unable to convert BLOB to double");
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0.0;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        throwUnknownTypeException(env, type);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0.0;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutBlob(JNIEnv* env, jclass clazz, jint windowPtr,
4283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jbyteArray valueObj, jint row, jint column) {
4293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
4303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t * fieldSlot = window->getFieldSlotWithCheck(row, column);
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fieldSlot == NULL) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW(" getFieldSlotWithCheck error ");
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    jsize len = env->GetArrayLength(valueObj);
4373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint32_t offset = window->alloc(len);
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!offset) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW("Failed allocating %u bytes", len);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    void* value = env->GetPrimitiveArrayCritical(valueObj, NULL);
4443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    window->copyIn(offset, static_cast<const uint8_t*>(value), len);
4453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT);
4463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fieldSlot->type = FIELD_TYPE_BLOB;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fieldSlot->data.buffer.offset = offset;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fieldSlot->data.buffer.size = len;
4503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("%d,%d is BLOB with %u bytes @ %d", row, column, len, offset);
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutString(JNIEnv* env, jclass clazz, jint windowPtr,
4553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jstring valueObj, jint row, jint column) {
4563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
4573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    field_slot_t * fieldSlot = window->getFieldSlotWithCheck(row, column);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fieldSlot == NULL) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW(" getFieldSlotWithCheck error ");
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
4643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    size_t size = env->GetStringUTFLength(valueObj) + 1;
4653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    const char* valueStr = env->GetStringUTFChars(valueObj, NULL);
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
4673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    size_t size = env->GetStringLength(valueObj) * sizeof(jchar);
4683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    const jchar* valueStr = env->GetStringChars(valueObj, NULL);
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
4703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!valueStr) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW("value can't be transfer to UTFChars");
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    uint32_t offset = window->alloc(size);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!offset) {
4773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        LOG_WINDOW("Failed allocating %u bytes", size);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
4793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->ReleaseStringUTFChars(valueObj, valueStr);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
4813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        env->ReleaseStringChars(valueObj, valueStr);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    window->copyIn(offset, reinterpret_cast<const uint8_t*>(valueStr), size);
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8
4893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    env->ReleaseStringUTFChars(valueObj, valueStr);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
4913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    env->ReleaseStringChars(valueObj, valueStr);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    fieldSlot->type = FIELD_TYPE_STRING;
4953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    fieldSlot->data.buffer.offset = offset;
4963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    fieldSlot->data.buffer.size = size;
4973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("%d,%d is TEXT with %u bytes @ %d", row, column, size, offset);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutLong(JNIEnv* env, jclass clazz, jint windowPtr,
5023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jlong value, jint row, jint column) {
5033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
5043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!window->putLong(row, column, value)) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW(" getFieldSlotWithCheck error ");
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("%d,%d is INTEGER 0x%016llx", row, column, value);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutDouble(JNIEnv* env, jclass clazz, jint windowPtr,
5143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jdouble value, jint row, jint column) {
5153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
5163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!window->putDouble(row, column, value)) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW(" getFieldSlotWithCheck error ");
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("%d,%d is FLOAT %lf", row, column, value);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutNull(JNIEnv* env, jclass clazz, jint windowPtr,
5263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        jint row, jint column) {
5273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
5283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    if (!window->putNull(row, column)) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_WINDOW(" getFieldSlotWithCheck error ");
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_WINDOW("%d,%d is NULL", row, column);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] =
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    /* name, signature, funcPtr */
5403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeInitializeEmpty", "(IZ)I",
5413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeInitializeEmpty },
5423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeInitializeFromBinder", "(Landroid/os/IBinder;)I",
5433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeInitializeFromBinder },
5443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeDispose", "(I)V",
5453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeDispose },
5463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetBinder", "(I)Landroid/os/IBinder;",
5473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetBinder },
5483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeClear", "(I)V",
5493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeClear },
5503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetNumRows", "(I)I",
5513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetNumRows },
5523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeSetNumColumns", "(II)Z",
5533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeSetNumColumns },
5543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeAllocRow", "(I)Z",
5553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeAllocRow },
5563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeFreeLastRow", "(I)V",
5573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeFreeLastRow },
5583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetType", "(III)I",
5593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetType },
5603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetBlob", "(III)[B",
5613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetBlob },
5623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetString", "(III)Ljava/lang/String;",
5633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetString },
5643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetLong", "(III)J",
5653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetLong },
5663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeGetDouble", "(III)D",
5673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeGetDouble },
5683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativeCopyStringToBuffer", "(IIILandroid/database/CharArrayBuffer;)V",
5693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativeCopyStringToBuffer },
5703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativePutBlob", "(I[BII)Z",
5713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativePutBlob },
5723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativePutString", "(ILjava/lang/String;II)Z",
5733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativePutString },
5743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativePutLong", "(IJII)Z",
5753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativePutLong },
5763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativePutDouble", "(IDII)Z",
5773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativePutDouble },
5783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    { "nativePutNull", "(III)Z",
5793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            (void*)nativePutNull },
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define FIND_CLASS(var, className) \
5833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        var = env->FindClass(className); \
5843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className);
5853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
5863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
5873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
5883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
5893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_CursorWindow(JNIEnv * env)
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass clazz;
5933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    FIND_CLASS(clazz, "android/database/CharArrayBuffer");
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    GET_FIELD_ID(gCharArrayBufferClassInfo.data, clazz,
5963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            "data", "[C");
5973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    GET_FIELD_ID(gCharArrayBufferClassInfo.sizeCopied, clazz,
5983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown            "sizeCopied", "I");
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    gEmptyString = jstring(env->NewGlobalRef(env->NewStringUTF("")));
6013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown    LOG_FATAL_IF(!gEmptyString, "Unable to create empty string");
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return AndroidRuntime::registerNativeMethods(env, "android/database/CursorWindow",
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sMethods, NELEM(sMethods));
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android
608