android_database_CursorWindow.cpp revision 49d2b1864c3dfec6faff74d67cb2527a8f1af5a8
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 3349d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h" 35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.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 605e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brownstatic jint nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { 610cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 name; 625a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 635a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown name.setTo(nameStr); 645a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown env->ReleaseStringUTFChars(nameObj, nameStr); 650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 675e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown status_t status = CursorWindow::create(name, cursorWindowSize, &window); 680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.", 700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown name.string(), cursorWindowSize, status); 713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeEmpty: window = %p", window); 753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return reinterpret_cast<jint>(window); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatic jint nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { 790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = CursorWindow::createFromParcel(parcel, &window); 830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not create CursorWindow from Parcel due to error %d.", status); 853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p", 893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->getNumRows(), window->getNumColumns(), window); 903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return reinterpret_cast<jint>(window); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) { 943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (window) { 963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Closing window %p", window); 973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown delete window; 983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 101650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brownstatic jstring nativeGetName(JNIEnv* env, jclass clazz, jint windowPtr) { 102650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 103650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown return env->NewStringUTF(window->name().string()); 104650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown} 105650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown 1060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatic void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr, 1070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jobject parcelObj) { 1083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->writeToParcel(parcel); 1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 msg; 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown msg.appendFormat("Could not write CursorWindow to Parcel due to error %d.", status); 1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jniThrowRuntimeException(env, msg.string()); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeClear(JNIEnv * env, jclass clazz, jint windowPtr) { 1203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Clearing window %p", window); 1220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->clear(); 1230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Could not clear window. error=%d", status); 1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetNumRows(JNIEnv* env, jclass clazz, jint windowPtr) { 1293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getNumRows(); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeSetNumColumns(JNIEnv* env, jclass clazz, jint windowPtr, 1343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint columnNum) { 1353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->setNumColumns(columnNum); 1370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeAllocRow(JNIEnv* env, jclass clazz, jint windowPtr) { 1413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->allocRow(); 1430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeFreeLastRow(JNIEnv* env, jclass clazz, jint windowPtr) { 1473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->freeLastRow(); 1493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetType(JNIEnv* env, jclass clazz, jint windowPtr, 1523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 158aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // FIXME: This is really broken but we have CTS tests that depend 159aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // on this legacy behavior. 160aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown //throwExceptionWithRowCol(env, row, column); 1610cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return CursorWindow::FIELD_TYPE_NULL; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return window->getFieldSlotType(fieldSlot); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jint windowPtr, 1673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1710cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1770cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 1780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) { 1790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t size; 1800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* value = window->getFieldSlotValueBlob(fieldSlot, &size); 1813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray byteArray = env->NewByteArray(size); 182e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori if (!byteArray) { 1833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ExceptionClear(); 184e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori throw_sqlite3_exception(env, "Native could not create new byte[]"); 185e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori return NULL; 186e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori } 1870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->SetByteArrayRegion(byteArray, 0, size, static_cast<const jbyte*>(value)); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return byteArray; 1890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 1903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob "); 1910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 1923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob "); 1930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do nothing 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring nativeGetString(JNIEnv* env, jclass clazz, jint windowPtr, 2023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 2033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 2073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 2130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 2140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 2150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull <= 1) { 217715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return gEmptyString; 218715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown } 219715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Convert to UTF-16 here instead of calling NewStringUTF. NewStringUTF 220715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // doesn't like UTF-8 strings with high codepoints. It actually expects 221715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Modified UTF-8 with encoded surrogate pairs. 2220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String16 utf16(value, sizeIncludingNull - 1); 223715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size()); 2240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 2253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 2263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%lld", value); 2283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 2303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 2313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 2333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jcharArray allocCharArrayBuffer(JNIEnv* env, jobject bufferObj, size_t size) { 2463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = jcharArray(env->GetObjectField(bufferObj, 2473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gCharArrayBufferClassInfo.data)); 2483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj && size) { 2493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = env->GetArrayLength(dataObj); 2503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size_t(capacity) < size) { 2513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->DeleteLocalRef(dataObj); 2523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = NULL; 2533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!dataObj) { 2563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = size; 2573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (capacity < 64) { 2583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown capacity = 64; 2593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = env->NewCharArray(capacity); // might throw OOM 2613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetObjectField(bufferObj, gCharArrayBufferClassInfo.data, dataObj); 2633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return dataObj; 2663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBufferUTF(JNIEnv* env, jobject bufferObj, 2693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* str, size_t len) { 2703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown ssize_t size = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str), len); 2713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size < 0) { 2723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown size = 0; // invalid UTF8 string 2733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, size); 2753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size) { 2773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL)); 278d0ff68da6a606602235fb8749473999e3d1bde53Jeff Brown utf8_to_utf16_no_null_terminator(reinterpret_cast<const uint8_t*>(str), len, 2793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown reinterpret_cast<char16_t*>(data)); 2803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(dataObj, data, 0); 2813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, size); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void clearCharArrayBuffer(JNIEnv* env, jobject bufferObj) { 2873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, 0); 2883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, 0); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 29203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana 2933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeCopyStringToBuffer(JNIEnv* env, jclass clazz, jint windowPtr, 2943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column, jobject bufferObj) { 2953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Copying string for %d,%d from %p", row, column, window); 2973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 2980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 2993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 3060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull > 1) { 3090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fillCharArrayBufferUTF(env, bufferObj, value, sizeIncludingNull - 1); 3103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 3153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%lld", value); 3173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 3203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 3223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jlong nativeGetLong(JNIEnv* env, jclass clazz, jint windowPtr, 3333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting long for %d,%d from %p", row, column, window); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueLong(fieldSlot); 3460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtoll(value, NULL, 0) : 0L; 3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jlong(window->getFieldSlotValueDouble(fieldSlot)); 3520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "Unable to convert BLOB to long"); 3563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 3623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jint windowPtr, 3643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); 3673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueDouble(fieldSlot); 3770cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtod(value, NULL) : 0.0; 3810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jdouble(window->getFieldSlotValueLong(fieldSlot)); 3830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to double"); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutBlob(JNIEnv* env, jclass clazz, jint windowPtr, 3953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray valueObj, jint row, jint column) { 3963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize len = env->GetArrayLength(valueObj); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown void* value = env->GetPrimitiveArrayCritical(valueObj, NULL); 4000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putBlob(row, column, value, len); 4013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT); 4023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 4030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put blob. error=%d", status); 4050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return false; 4060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 4070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is BLOB with %u bytes", row, column, len); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutString(JNIEnv* env, jclass clazz, jint windowPtr, 4133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jstring valueObj, jint row, jint column) { 4143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull = env->GetStringUTFLength(valueObj) + 1; 4173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* valueStr = env->GetStringUTFChars(valueObj, NULL); 4183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!valueStr) { 4190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("value can't be transferred to UTFChars"); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putString(row, column, valueStr, sizeIncludingNull); 4230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->ReleaseStringUTFChars(valueObj, valueStr); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put string. error=%d", status); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", row, column, sizeIncludingNull); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutLong(JNIEnv* env, jclass clazz, jint windowPtr, 4353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jlong value, jint row, jint column) { 4363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putLong(row, column, value); 4380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put long. error=%d", status); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", row, column, value); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutDouble(JNIEnv* env, jclass clazz, jint windowPtr, 4493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jdouble value, jint row, jint column) { 4503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putDouble(row, column, value); 4520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put double. error=%d", status); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", row, column, value); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutNull(JNIEnv* env, jclass clazz, jint windowPtr, 4633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 4643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putNull(row, column); 4660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put null. error=%d", status); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is NULL", row, column); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown /* name, signature, funcPtr */ 4795e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown { "nativeCreate", "(Ljava/lang/String;I)I", 4800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreate }, 4810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I", 4820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreateFromParcel }, 4833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeDispose", "(I)V", 4843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeDispose }, 4850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown { "nativeWriteToParcel", "(ILandroid/os/Parcel;)V", 4860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeWriteToParcel }, 487650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown { "nativeGetName", "(I)Ljava/lang/String;", 488650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown (void*)nativeGetName }, 4893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeClear", "(I)V", 4903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeClear }, 4913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetNumRows", "(I)I", 4923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetNumRows }, 4933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeSetNumColumns", "(II)Z", 4943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeSetNumColumns }, 4953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeAllocRow", "(I)Z", 4963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeAllocRow }, 4973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeFreeLastRow", "(I)V", 4983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeFreeLastRow }, 4993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetType", "(III)I", 5003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetType }, 5013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetBlob", "(III)[B", 5023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetBlob }, 5033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetString", "(III)Ljava/lang/String;", 5043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetString }, 5053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetLong", "(III)J", 5063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetLong }, 5073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetDouble", "(III)D", 5083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetDouble }, 5093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeCopyStringToBuffer", "(IIILandroid/database/CharArrayBuffer;)V", 5103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeCopyStringToBuffer }, 5113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutBlob", "(I[BII)Z", 5123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutBlob }, 5133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutString", "(ILjava/lang/String;II)Z", 5143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutString }, 5153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutLong", "(IJII)Z", 5163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutLong }, 5173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutDouble", "(IDII)Z", 5183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutDouble }, 5193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutNull", "(III)Z", 5203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutNull }, 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define FIND_CLASS(var, className) \ 5243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->FindClass(className); \ 5253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); 5263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 5283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 5293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 5303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_CursorWindow(JNIEnv * env) 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 5343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown FIND_CLASS(clazz, "android/database/CharArrayBuffer"); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.data, clazz, 5373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "data", "[C"); 5383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.sizeCopied, clazz, 5393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "sizeCopied", "I"); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gEmptyString = jstring(env->NewGlobalRef(env->NewStringUTF(""))); 5423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(!gEmptyString, "Unable to create empty string"); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/database/CursorWindow", 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sMethods, NELEM(sMethods)); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 549