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 20853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn#include <inttypes.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h> 283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#include <utils/Unicode.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h> 35d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey#include "android_os_Parcel.h" 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h" 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.h" 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe#include "core_jni_helpers.h" 40987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic struct { 443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID data; 453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID sizeCopied; 463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} gCharArrayBufferClassInfo; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring gEmptyString; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwExceptionWithRowCol(JNIEnv* env, jint row, jint column) { 513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("Couldn't read row %d, col %d from CursorWindow. " 533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "Make sure the Cursor is initialized correctly before accessing data from it.", 543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown row, column); 553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwUnknownTypeException(JNIEnv * env, jint type) { 593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("UNKNOWN type %d", type); 613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 64738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { 650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 name; 665a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 675a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown name.setTo(nameStr); 685a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown env->ReleaseStringUTFChars(nameObj, nameStr); 690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 715e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown status_t status = CursorWindow::create(name, cursorWindowSize, &window); 720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 733762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.", 740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown name.string(), cursorWindowSize, status); 753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeEmpty: window = %p", window); 79738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat return reinterpret_cast<jlong>(window); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { 830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = CursorWindow::createFromParcel(parcel, &window); 870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 883762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not create CursorWindow from Parcel due to error %d.", status); 893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p", 933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->getNumRows(), window->getNumColumns(), window); 94738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat return reinterpret_cast<jlong>(window); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 97738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jclass clazz, jlong windowPtr) { 983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (window) { 1003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Closing window %p", window); 1013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown delete window; 1023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 1033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 105738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jstring nativeGetName(JNIEnv* env, jclass clazz, jlong windowPtr) { 106650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 107650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown return env->NewStringUTF(window->name().string()); 108650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown} 109650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown 110738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jobject parcelObj) { 1123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->writeToParcel(parcel); 1160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 msg; 1180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown msg.appendFormat("Could not write CursorWindow to Parcel due to error %d.", status); 1190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jniThrowRuntimeException(env, msg.string()); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 123738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeClear(JNIEnv * env, jclass clazz, jlong windowPtr) { 1243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Clearing window %p", window); 1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->clear(); 1270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1280cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Could not clear window. error=%d", status); 1290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 132738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jint nativeGetNumRows(JNIEnv* env, jclass clazz, jlong windowPtr) { 1333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getNumRows(); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 137738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativeSetNumColumns(JNIEnv* env, jclass clazz, jlong windowPtr, 1383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint columnNum) { 1393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->setNumColumns(columnNum); 1410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 144738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativeAllocRow(JNIEnv* env, jclass clazz, jlong windowPtr) { 1453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->allocRow(); 1470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 150738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeFreeLastRow(JNIEnv* env, jclass clazz, jlong windowPtr) { 1513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->freeLastRow(); 1533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 155738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jint nativeGetType(JNIEnv* env, jclass clazz, jlong windowPtr, 1563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 162aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // FIXME: This is really broken but we have CTS tests that depend 163aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // on this legacy behavior. 164aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown //throwExceptionWithRowCol(env, row, column); 1650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return CursorWindow::FIELD_TYPE_NULL; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return window->getFieldSlotType(fieldSlot); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 170738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jlong windowPtr, 1713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 1820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) { 1830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t size; 1840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* value = window->getFieldSlotValueBlob(fieldSlot, &size); 1853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray byteArray = env->NewByteArray(size); 186e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori if (!byteArray) { 1873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ExceptionClear(); 188e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori throw_sqlite3_exception(env, "Native could not create new byte[]"); 189e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori return NULL; 190e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori } 1910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->SetByteArrayRegion(byteArray, 0, size, static_cast<const jbyte*>(value)); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return byteArray; 1930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 1943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob "); 1950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 1963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob "); 1970cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do nothing 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jstring nativeGetString(JNIEnv* env, jclass clazz, jlong windowPtr, 2063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 2073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 2113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 2180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 2190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 2200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull <= 1) { 221715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return gEmptyString; 222715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown } 223715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Convert to UTF-16 here instead of calling NewStringUTF. NewStringUTF 224715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // doesn't like UTF-8 strings with high codepoints. It actually expects 225715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Modified UTF-8 with encoded surrogate pairs. 2260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String16 utf16(value, sizeIncludingNull - 1); 227715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size()); 2280cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 2293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 2303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 231853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn snprintf(buf, sizeof(buf), "%" PRId64, value); 2323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 2343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 2353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 2373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jcharArray allocCharArrayBuffer(JNIEnv* env, jobject bufferObj, size_t size) { 2503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = jcharArray(env->GetObjectField(bufferObj, 2513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gCharArrayBufferClassInfo.data)); 2523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj && size) { 2533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = env->GetArrayLength(dataObj); 2543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size_t(capacity) < size) { 2553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->DeleteLocalRef(dataObj); 2563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = NULL; 2573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!dataObj) { 2603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = size; 2613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (capacity < 64) { 2623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown capacity = 64; 2633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = env->NewCharArray(capacity); // might throw OOM 2653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetObjectField(bufferObj, gCharArrayBufferClassInfo.data, dataObj); 2673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return dataObj; 2703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBufferUTF(JNIEnv* env, jobject bufferObj, 2733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* str, size_t len) { 2743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown ssize_t size = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str), len); 2753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size < 0) { 2763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown size = 0; // invalid UTF8 string 2773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, size); 2793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size) { 2813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL)); 282d0ff68da6a606602235fb8749473999e3d1bde53Jeff Brown utf8_to_utf16_no_null_terminator(reinterpret_cast<const uint8_t*>(str), len, 2833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown reinterpret_cast<char16_t*>(data)); 2843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(dataObj, data, 0); 2853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, size); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void clearCharArrayBuffer(JNIEnv* env, jobject bufferObj) { 2913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, 0); 2923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, 0); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 29603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana 297738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeCopyStringToBuffer(JNIEnv* env, jclass clazz, jlong windowPtr, 2983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column, jobject bufferObj) { 2993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Copying string for %d,%d from %p", row, column, window); 3013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3020cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 3100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull > 1) { 3130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fillCharArrayBufferUTF(env, bufferObj, value, sizeIncludingNull - 1); 3143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 3193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 320853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn snprintf(buf, sizeof(buf), "%" PRId64, value); 3213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 3243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 3263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 336738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeGetLong(JNIEnv* env, jclass clazz, jlong windowPtr, 3373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting long for %d,%d from %p", row, column, window); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueLong(fieldSlot); 3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtoll(value, NULL, 0) : 0L; 3540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jlong(window->getFieldSlotValueDouble(fieldSlot)); 3560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "Unable to convert BLOB to long"); 3603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 3663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 367738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jlong windowPtr, 3683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); 3713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueDouble(fieldSlot); 3810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtod(value, NULL) : 0.0; 3850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jdouble(window->getFieldSlotValueLong(fieldSlot)); 3870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to double"); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 398738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutBlob(JNIEnv* env, jclass clazz, jlong windowPtr, 3993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray valueObj, jint row, jint column) { 4003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize len = env->GetArrayLength(valueObj); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown void* value = env->GetPrimitiveArrayCritical(valueObj, NULL); 4040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putBlob(row, column, value, len); 4053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT); 4063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 4070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put blob. error=%d", status); 4090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return false; 4100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 4110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is BLOB with %u bytes", row, column, len); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 416738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutString(JNIEnv* env, jclass clazz, jlong windowPtr, 4173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jstring valueObj, jint row, jint column) { 4183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull = env->GetStringUTFLength(valueObj) + 1; 4213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* valueStr = env->GetStringUTFChars(valueObj, NULL); 4223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!valueStr) { 4230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("value can't be transferred to UTFChars"); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putString(row, column, valueStr, sizeIncludingNull); 4270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->ReleaseStringUTFChars(valueObj, valueStr); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put string. error=%d", status); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", row, column, sizeIncludingNull); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 438738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutLong(JNIEnv* env, jclass clazz, jlong windowPtr, 4393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jlong value, jint row, jint column) { 4403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putLong(row, column, value); 4420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put long. error=%d", status); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", row, column, value); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 452738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutDouble(JNIEnv* env, jclass clazz, jlong windowPtr, 4533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jdouble value, jint row, jint column) { 4543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putDouble(row, column, value); 4560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put double. error=%d", status); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", row, column, value); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 466738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutNull(JNIEnv* env, jclass clazz, jlong windowPtr, 4673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 4683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putNull(row, column); 4700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4710cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put null. error=%d", status); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is NULL", row, column); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod sMethods[] = 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown /* name, signature, funcPtr */ 483738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCreate", "(Ljava/lang/String;I)J", 4840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreate }, 485738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCreateFromParcel", "(Landroid/os/Parcel;)J", 4860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreateFromParcel }, 487738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeDispose", "(J)V", 4883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeDispose }, 489738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V", 4900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeWriteToParcel }, 491738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetName", "(J)Ljava/lang/String;", 492650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown (void*)nativeGetName }, 493738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeClear", "(J)V", 4943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeClear }, 495738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetNumRows", "(J)I", 4963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetNumRows }, 497738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeSetNumColumns", "(JI)Z", 4983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeSetNumColumns }, 499738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeAllocRow", "(J)Z", 5003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeAllocRow }, 501738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeFreeLastRow", "(J)V", 5023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeFreeLastRow }, 503738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetType", "(JII)I", 5043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetType }, 505738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetBlob", "(JII)[B", 5063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetBlob }, 507738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetString", "(JII)Ljava/lang/String;", 5083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetString }, 509738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetLong", "(JII)J", 5103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetLong }, 511738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetDouble", "(JII)D", 5123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetDouble }, 513738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", 5143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeCopyStringToBuffer }, 515738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutBlob", "(J[BII)Z", 5163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutBlob }, 517738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutString", "(JLjava/lang/String;II)Z", 5183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutString }, 519738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutLong", "(JJII)Z", 5203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutLong }, 521738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutDouble", "(JDII)Z", 5223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutDouble }, 523738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutNull", "(JII)Z", 5243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutNull }, 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 527987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampeint register_android_database_CursorWindow(JNIEnv* env) 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 529987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe jclass clazz = FindClassOrDie(env, "android/database/CharArrayBuffer"); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 531987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe gCharArrayBufferClassInfo.data = GetFieldIDOrDie(env, clazz, "data", "[C"); 532987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe gCharArrayBufferClassInfo.sizeCopied = GetFieldIDOrDie(env, clazz, "sizeCopied", "I"); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 534987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe gEmptyString = MakeGlobalRefOrDie(env, env->NewStringUTF("")); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 536987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe return RegisterMethodsOrDie(env, "android/database/CursorWindow", sMethods, NELEM(sMethods)); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 540