android_database_CursorWindow.cpp revision d84e1ce0b535128f03416145554fb405f9fade3e
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> 34d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey#include "android_os_Parcel.h" 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h" 36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.h" 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic struct { 413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID data; 423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID sizeCopied; 433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} gCharArrayBufferClassInfo; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring gEmptyString; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwExceptionWithRowCol(JNIEnv* env, jint row, jint column) { 483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("Couldn't read row %d, col %d from CursorWindow. " 503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "Make sure the Cursor is initialized correctly before accessing data from it.", 513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown row, column); 523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwUnknownTypeException(JNIEnv * env, jint type) { 563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("UNKNOWN type %d", type); 583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 615e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brownstatic jint nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { 620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 name; 635a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 645a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown name.setTo(nameStr); 655a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown env->ReleaseStringUTFChars(nameObj, nameStr); 660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 685e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown status_t status = CursorWindow::create(name, cursorWindowSize, &window); 690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 703762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.", 710cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown name.string(), cursorWindowSize, status); 723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeEmpty: window = %p", window); 763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return reinterpret_cast<jint>(window); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatic jint nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { 800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = CursorWindow::createFromParcel(parcel, &window); 840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 853762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not create CursorWindow from Parcel due to error %d.", status); 863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p", 903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->getNumRows(), window->getNumColumns(), window); 913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return reinterpret_cast<jint>(window); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) { 953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (window) { 973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Closing window %p", window); 983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown delete window; 993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 1003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 102650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brownstatic jstring nativeGetName(JNIEnv* env, jclass clazz, jint windowPtr) { 103650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 104650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown return env->NewStringUTF(window->name().string()); 105650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown} 106650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown 1070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatic void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr, 1080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jobject parcelObj) { 1093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->writeToParcel(parcel); 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 msg; 1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown msg.appendFormat("Could not write CursorWindow to Parcel due to error %d.", status); 1160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jniThrowRuntimeException(env, msg.string()); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeClear(JNIEnv * env, jclass clazz, jint windowPtr) { 1213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Clearing window %p", window); 1230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->clear(); 1240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Could not clear window. error=%d", status); 1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetNumRows(JNIEnv* env, jclass clazz, jint windowPtr) { 1303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getNumRows(); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeSetNumColumns(JNIEnv* env, jclass clazz, jint windowPtr, 1353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint columnNum) { 1363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->setNumColumns(columnNum); 1380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativeAllocRow(JNIEnv* env, jclass clazz, jint windowPtr) { 1423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->allocRow(); 1440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeFreeLastRow(JNIEnv* env, jclass clazz, jint windowPtr) { 1483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->freeLastRow(); 1503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jint nativeGetType(JNIEnv* env, jclass clazz, jint windowPtr, 1533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 159aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // FIXME: This is really broken but we have CTS tests that depend 160aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // on this legacy behavior. 161aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown //throwExceptionWithRowCol(env, row, column); 1620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return CursorWindow::FIELD_TYPE_NULL; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1640cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return window->getFieldSlotType(fieldSlot); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jint windowPtr, 1683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 1790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) { 1800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t size; 1810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* value = window->getFieldSlotValueBlob(fieldSlot, &size); 1823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray byteArray = env->NewByteArray(size); 183e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori if (!byteArray) { 1843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ExceptionClear(); 185e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori throw_sqlite3_exception(env, "Native could not create new byte[]"); 186e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori return NULL; 187e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori } 1880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->SetByteArrayRegion(byteArray, 0, size, static_cast<const jbyte*>(value)); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return byteArray; 1900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 1913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob "); 1920cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 1933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob "); 1940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do nothing 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring nativeGetString(JNIEnv* env, jclass clazz, jint windowPtr, 2033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 2043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 2083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 2140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 2150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull <= 1) { 218715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return gEmptyString; 219715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown } 220715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Convert to UTF-16 here instead of calling NewStringUTF. NewStringUTF 221715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // doesn't like UTF-8 strings with high codepoints. It actually expects 222715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Modified UTF-8 with encoded surrogate pairs. 2230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String16 utf16(value, sizeIncludingNull - 1); 224715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size()); 2250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 2263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 2273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%lld", value); 2293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 2313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 2323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 2343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2350cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jcharArray allocCharArrayBuffer(JNIEnv* env, jobject bufferObj, size_t size) { 2473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = jcharArray(env->GetObjectField(bufferObj, 2483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gCharArrayBufferClassInfo.data)); 2493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj && size) { 2503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = env->GetArrayLength(dataObj); 2513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size_t(capacity) < size) { 2523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->DeleteLocalRef(dataObj); 2533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = NULL; 2543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!dataObj) { 2573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = size; 2583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (capacity < 64) { 2593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown capacity = 64; 2603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = env->NewCharArray(capacity); // might throw OOM 2623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetObjectField(bufferObj, gCharArrayBufferClassInfo.data, dataObj); 2643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return dataObj; 2673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBufferUTF(JNIEnv* env, jobject bufferObj, 2703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* str, size_t len) { 2713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown ssize_t size = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str), len); 2723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size < 0) { 2733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown size = 0; // invalid UTF8 string 2743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, size); 2763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size) { 2783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL)); 279d0ff68da6a606602235fb8749473999e3d1bde53Jeff Brown utf8_to_utf16_no_null_terminator(reinterpret_cast<const uint8_t*>(str), len, 2803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown reinterpret_cast<char16_t*>(data)); 2813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(dataObj, data, 0); 2823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, size); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void clearCharArrayBuffer(JNIEnv* env, jobject bufferObj) { 2883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, 0); 2893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, 0); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 29303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana 2943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void nativeCopyStringToBuffer(JNIEnv* env, jclass clazz, jint windowPtr, 2953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column, jobject bufferObj) { 2963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Copying string for %d,%d from %p", row, column, window); 2983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 2990cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 3070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull > 1) { 3100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fillCharArrayBufferUTF(env, bufferObj, value, sizeIncludingNull - 1); 3113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 3163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%lld", value); 3183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 3213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 3233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jlong nativeGetLong(JNIEnv* env, jclass clazz, jint windowPtr, 3343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting long for %d,%d from %p", row, column, window); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueLong(fieldSlot); 3470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtoll(value, NULL, 0) : 0L; 3510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jlong(window->getFieldSlotValueDouble(fieldSlot)); 3530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "Unable to convert BLOB to long"); 3573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 3633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jint windowPtr, 3653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); 3683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3760cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueDouble(fieldSlot); 3780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtod(value, NULL) : 0.0; 3820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jdouble(window->getFieldSlotValueLong(fieldSlot)); 3840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to double"); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutBlob(JNIEnv* env, jclass clazz, jint windowPtr, 3963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray valueObj, jint row, jint column) { 3973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize len = env->GetArrayLength(valueObj); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown void* value = env->GetPrimitiveArrayCritical(valueObj, NULL); 4010cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putBlob(row, column, value, len); 4023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT); 4033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 4040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put blob. error=%d", status); 4060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return false; 4070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 4080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is BLOB with %u bytes", row, column, len); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutString(JNIEnv* env, jclass clazz, jint windowPtr, 4143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jstring valueObj, jint row, jint column) { 4153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull = env->GetStringUTFLength(valueObj) + 1; 4183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* valueStr = env->GetStringUTFChars(valueObj, NULL); 4193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!valueStr) { 4200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("value can't be transferred to UTFChars"); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putString(row, column, valueStr, sizeIncludingNull); 4240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->ReleaseStringUTFChars(valueObj, valueStr); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put string. error=%d", status); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", row, column, sizeIncludingNull); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutLong(JNIEnv* env, jclass clazz, jint windowPtr, 4363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jlong value, jint row, jint column) { 4373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putLong(row, column, value); 4390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put long. error=%d", status); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4453bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", row, column, value); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutDouble(JNIEnv* env, jclass clazz, jint windowPtr, 4503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jdouble value, jint row, jint column) { 4513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putDouble(row, column, value); 4530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put double. error=%d", status); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", row, column, value); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jboolean nativePutNull(JNIEnv* env, jclass clazz, jint windowPtr, 4643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 4653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putNull(row, column); 4670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put null. error=%d", status); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is NULL", row, column); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown /* name, signature, funcPtr */ 4805e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown { "nativeCreate", "(Ljava/lang/String;I)I", 4810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreate }, 4820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I", 4830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreateFromParcel }, 4843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeDispose", "(I)V", 4853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeDispose }, 4860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown { "nativeWriteToParcel", "(ILandroid/os/Parcel;)V", 4870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeWriteToParcel }, 488650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown { "nativeGetName", "(I)Ljava/lang/String;", 489650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown (void*)nativeGetName }, 4903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeClear", "(I)V", 4913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeClear }, 4923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetNumRows", "(I)I", 4933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetNumRows }, 4943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeSetNumColumns", "(II)Z", 4953bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeSetNumColumns }, 4963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeAllocRow", "(I)Z", 4973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeAllocRow }, 4983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeFreeLastRow", "(I)V", 4993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeFreeLastRow }, 5003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetType", "(III)I", 5013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetType }, 5023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetBlob", "(III)[B", 5033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetBlob }, 5043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetString", "(III)Ljava/lang/String;", 5053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetString }, 5063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetLong", "(III)J", 5073bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetLong }, 5083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeGetDouble", "(III)D", 5093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetDouble }, 5103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativeCopyStringToBuffer", "(IIILandroid/database/CharArrayBuffer;)V", 5113bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeCopyStringToBuffer }, 5123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutBlob", "(I[BII)Z", 5133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutBlob }, 5143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutString", "(ILjava/lang/String;II)Z", 5153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutString }, 5163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutLong", "(IJII)Z", 5173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutLong }, 5183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutDouble", "(IDII)Z", 5193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutDouble }, 5203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown { "nativePutNull", "(III)Z", 5213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutNull }, 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define FIND_CLASS(var, className) \ 5253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->FindClass(className); \ 5263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); 5273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 5293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 5303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 5313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_CursorWindow(JNIEnv * env) 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 5353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown FIND_CLASS(clazz, "android/database/CharArrayBuffer"); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.data, clazz, 5383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "data", "[C"); 5393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.sizeCopied, clazz, 5403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "sizeCopied", "I"); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gEmptyString = jstring(env->NewGlobalRef(env->NewStringUTF(""))); 5433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(!gEmptyString, "Unable to create empty string"); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/database/CursorWindow", 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sMethods, NELEM(sMethods)); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 550