19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "CursorWindow" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn#include <inttypes.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h> 283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#include <utils/Unicode.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h> 35d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey#include "android_os_Parcel.h" 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_util_Binder.h" 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.h" 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic struct { 423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID data; 433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jfieldID sizeCopied; 443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} gCharArrayBufferClassInfo; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jstring gEmptyString; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwExceptionWithRowCol(JNIEnv* env, jint row, jint column) { 493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("Couldn't read row %d, col %d from CursorWindow. " 513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "Make sure the Cursor is initialized correctly before accessing data from it.", 523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown row, column); 533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void throwUnknownTypeException(JNIEnv * env, jint type) { 573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown String8 msg; 583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown msg.appendFormat("UNKNOWN type %d", type); 593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", msg.string()); 603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 62738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { 630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 name; 645a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 655a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown name.setTo(nameStr); 665a05c23f3d6a1a895bf5917aacd8bd9a5302ba00Jeff Brown env->ReleaseStringUTFChars(nameObj, nameStr); 670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 695e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown status_t status = CursorWindow::create(name, cursorWindowSize, &window); 700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 713762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.", 720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown name.string(), cursorWindowSize, status); 733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeEmpty: window = %p", window); 77738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat return reinterpret_cast<jlong>(window); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 80738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { 810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow* window; 840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = CursorWindow::createFromParcel(parcel, &window); 850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status || !window) { 863762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not create CursorWindow from Parcel due to error %d.", status); 873bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p", 913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->getNumRows(), window->getNumColumns(), window); 92738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat return reinterpret_cast<jlong>(window); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 95738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jclass clazz, jlong windowPtr) { 963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (window) { 983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Closing window %p", window); 993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown delete window; 1003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 1013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 103738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jstring nativeGetName(JNIEnv* env, jclass clazz, jlong windowPtr) { 104650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 105650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown return env->NewStringUTF(window->name().string()); 106650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown} 107650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown 108738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, 1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jobject parcelObj) { 1103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown Parcel* parcel = parcelForJavaObject(env, parcelObj); 1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->writeToParcel(parcel); 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String8 msg; 1160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown msg.appendFormat("Could not write CursorWindow to Parcel due to error %d.", status); 1170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown jniThrowRuntimeException(env, msg.string()); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeClear(JNIEnv * env, jclass clazz, jlong windowPtr) { 1223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Clearing window %p", window); 1240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->clear(); 1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Could not clear window. error=%d", status); 1270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 130738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jint nativeGetNumRows(JNIEnv* env, jclass clazz, jlong windowPtr) { 1313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getNumRows(); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 135738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativeSetNumColumns(JNIEnv* env, jclass clazz, jlong windowPtr, 1363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint columnNum) { 1373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->setNumColumns(columnNum); 1390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 142738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativeAllocRow(JNIEnv* env, jclass clazz, jlong windowPtr) { 1433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->allocRow(); 1450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return status == OK; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 148738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeFreeLastRow(JNIEnv* env, jclass clazz, jlong windowPtr) { 1493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown window->freeLastRow(); 1513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 153738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jint nativeGetType(JNIEnv* env, jclass clazz, jlong windowPtr, 1543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 160aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // FIXME: This is really broken but we have CTS tests that depend 161aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown // on this legacy behavior. 162aa32c30b81134fc7ebd9408f4757d1dc4410f338Jeff Brown //throwExceptionWithRowCol(env, row, column); 1630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return CursorWindow::FIELD_TYPE_NULL; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return window->getFieldSlotType(fieldSlot); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 168738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jlong windowPtr, 1693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 1703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 1713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1730cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 1743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 1800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) { 1810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t size; 1820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* value = window->getFieldSlotValueBlob(fieldSlot, &size); 1833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray byteArray = env->NewByteArray(size); 184e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori if (!byteArray) { 1853bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ExceptionClear(); 186e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori throw_sqlite3_exception(env, "Native could not create new byte[]"); 187e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori return NULL; 188e6044145bccf30e2b1785eb33a26de6496167986Vasu Nori } 1890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->SetByteArrayRegion(byteArray, 0, size, static_cast<const jbyte*>(value)); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return byteArray; 1910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 1923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob "); 1930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 1943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob "); 1950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do nothing 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 203738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jstring nativeGetString(JNIEnv* env, jclass clazz, jlong windowPtr, 2043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 2053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 2093bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 2150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 2180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull <= 1) { 219715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return gEmptyString; 220715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown } 221715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Convert to UTF-16 here instead of calling NewStringUTF. NewStringUTF 222715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // doesn't like UTF-8 strings with high codepoints. It actually expects 223715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown // Modified UTF-8 with encoded surrogate pairs. 2240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown String16 utf16(value, sizeIncludingNull - 1); 225715311fa5aeb39fd0904209e1428a3656c721c3dJeff Brown return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size()); 2260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 2273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 2283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 229853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn snprintf(buf, sizeof(buf), "%" PRId64, value); 2303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 2323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 2333bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 2343bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 2353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return env->NewStringUTF(buf); 2360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic jcharArray allocCharArrayBuffer(JNIEnv* env, jobject bufferObj, size_t size) { 2483bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = jcharArray(env->GetObjectField(bufferObj, 2493bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gCharArrayBufferClassInfo.data)); 2503bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj && size) { 2513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = env->GetArrayLength(dataObj); 2523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size_t(capacity) < size) { 2533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->DeleteLocalRef(dataObj); 2543bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = NULL; 2553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2563bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!dataObj) { 2583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize capacity = size; 2593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (capacity < 64) { 2603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown capacity = 64; 2613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown dataObj = env->NewCharArray(capacity); // might throw OOM 2633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetObjectField(bufferObj, gCharArrayBufferClassInfo.data, dataObj); 2653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return dataObj; 2683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2703bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void fillCharArrayBufferUTF(JNIEnv* env, jobject bufferObj, 2713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* str, size_t len) { 2723bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown ssize_t size = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str), len); 2733bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size < 0) { 2743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown size = 0; // invalid UTF8 string 2753bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2763bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, size); 2773bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (size) { 2793bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jchar* data = static_cast<jchar*>(env->GetPrimitiveArrayCritical(dataObj, NULL)); 280d0ff68da6a606602235fb8749473999e3d1bde53Jeff Brown utf8_to_utf16_no_null_terminator(reinterpret_cast<const uint8_t*>(str), len, 2813bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown reinterpret_cast<char16_t*>(data)); 2823bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(dataObj, data, 0); 2833bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 2843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, size); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2883bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brownstatic void clearCharArrayBuffer(JNIEnv* env, jobject bufferObj) { 2893bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jcharArray dataObj = allocCharArrayBuffer(env, bufferObj, 0); 2903bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (dataObj) { 2913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->SetIntField(bufferObj, gCharArrayBufferClassInfo.sizeCopied, 0); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2933bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 29403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana 295738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic void nativeCopyStringToBuffer(JNIEnv* env, jclass clazz, jlong windowPtr, 2963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column, jobject bufferObj) { 2973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 2983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Copying string for %d,%d from %p", row, column, window); 2993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3053bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_STRING) { 3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (sizeIncludingNull > 1) { 3110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown fillCharArrayBufferUTF(env, bufferObj, value, sizeIncludingNull - 1); 3123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3133bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown int64_t value = window->getFieldSlotValueLong(fieldSlot); 3173bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 318853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn snprintf(buf, sizeof(buf), "%" PRId64, value); 3193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3213bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown double value = window->getFieldSlotValueDouble(fieldSlot); 3223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown char buf[32]; 3233bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown snprintf(buf, sizeof(buf), "%g", value); 3243bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf)); 3250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown clearCharArrayBuffer(env, bufferObj); 3270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to string"); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 334738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jlong nativeGetLong(JNIEnv* env, jclass clazz, jlong windowPtr, 3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting long for %d,%d from %p", row, column, window); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwExceptionWithRowCol(env, row, column); 3423bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3473bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueLong(fieldSlot); 3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtoll(value, NULL, 0) : 0L; 3520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3533bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jlong(window->getFieldSlotValueDouble(fieldSlot)); 3540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3553bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3573bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throw_sqlite3_exception(env, "Unable to convert BLOB to long"); 3583bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3593bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } else { 3603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3613bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return 0; 3623bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown } 3633bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown} 3643bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 365738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jlong windowPtr, 3663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 3673bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3683bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); 3693bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 3700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); 3713bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!fieldSlot) { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwExceptionWithRowCol(env, row, column); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3760cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown int32_t type = window->getFieldSlotType(fieldSlot); 3770cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (type == CursorWindow::FIELD_TYPE_FLOAT) { 3783bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return window->getFieldSlotValueDouble(fieldSlot); 3790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_STRING) { 3800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull; 3810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); 3820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return sizeIncludingNull > 1 ? strtod(value, NULL) : 0.0; 3830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { 3843bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown return jdouble(window->getFieldSlotValueLong(fieldSlot)); 3850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_NULL) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } else if (type == CursorWindow::FIELD_TYPE_BLOB) { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unable to convert BLOB to double"); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3913bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown throwUnknownTypeException(env, type); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0.0; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 396738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutBlob(JNIEnv* env, jclass clazz, jlong windowPtr, 3973bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jbyteArray valueObj, jint row, jint column) { 3983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 3993bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jsize len = env->GetArrayLength(valueObj); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4013bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown void* value = env->GetPrimitiveArrayCritical(valueObj, NULL); 4020cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putBlob(row, column, value, len); 4033bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT); 4043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 4050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put blob. error=%d", status); 4070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown return false; 4080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown } 4090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is BLOB with %u bytes", row, column, len); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 414738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutString(JNIEnv* env, jclass clazz, jlong windowPtr, 4153bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jstring valueObj, jint row, jint column) { 4163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull = env->GetStringUTFLength(valueObj) + 1; 4193bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown const char* valueStr = env->GetStringUTFChars(valueObj, NULL); 4203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown if (!valueStr) { 4210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("value can't be transferred to UTFChars"); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putString(row, column, valueStr, sizeIncludingNull); 4250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown env->ReleaseStringUTFChars(valueObj, valueStr); 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4280cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put string. error=%d", status); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", row, column, sizeIncludingNull); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 436738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutLong(JNIEnv* env, jclass clazz, jlong windowPtr, 4373bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jlong value, jint row, jint column) { 4383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putLong(row, column, value); 4400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put long. error=%d", status); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4463bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", row, column, value); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 450738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutDouble(JNIEnv* env, jclass clazz, jlong windowPtr, 4513bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jdouble value, jint row, jint column) { 4523bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putDouble(row, column, value); 4540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put double. error=%d", status); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4603bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", row, column, value); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 464738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhatstatic jboolean nativePutNull(JNIEnv* env, jclass clazz, jlong windowPtr, 4653bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown jint row, jint column) { 4663bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 4670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->putNull(row, column); 4680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown 4690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 4700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed to put null. error=%d", status); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4743bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_WINDOW("%d,%d is NULL", row, column); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4803bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown /* name, signature, funcPtr */ 481738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCreate", "(Ljava/lang/String;I)J", 4820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreate }, 483738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCreateFromParcel", "(Landroid/os/Parcel;)J", 4840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeCreateFromParcel }, 485738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeDispose", "(J)V", 4863bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeDispose }, 487738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V", 4880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown (void*)nativeWriteToParcel }, 489738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetName", "(J)Ljava/lang/String;", 490650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown (void*)nativeGetName }, 491738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeClear", "(J)V", 4923bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeClear }, 493738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetNumRows", "(J)I", 4943bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetNumRows }, 495738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeSetNumColumns", "(JI)Z", 4963bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeSetNumColumns }, 497738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeAllocRow", "(J)Z", 4983bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeAllocRow }, 499738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeFreeLastRow", "(J)V", 5003bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeFreeLastRow }, 501738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetType", "(JII)I", 5023bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetType }, 503738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetBlob", "(JII)[B", 5043bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetBlob }, 505738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetString", "(JII)Ljava/lang/String;", 5063bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetString }, 507738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetLong", "(JII)J", 5083bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetLong }, 509738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeGetDouble", "(JII)D", 5103bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeGetDouble }, 511738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", 5123bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativeCopyStringToBuffer }, 513738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutBlob", "(J[BII)Z", 5143bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutBlob }, 515738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutString", "(JLjava/lang/String;II)Z", 5163bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutString }, 517738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutLong", "(JJII)Z", 5183bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutLong }, 519738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutDouble", "(JDII)Z", 5203bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutDouble }, 521738702d28ab7e0e89e3c6e18fd46cc1361917eb9Ashok Bhat { "nativePutNull", "(JII)Z", 5223bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown (void*)nativePutNull }, 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5253bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define FIND_CLASS(var, className) \ 5263bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->FindClass(className); \ 5273bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); 5283bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5293bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 5303bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 5313bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 5323bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_CursorWindow(JNIEnv * env) 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 5363bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown FIND_CLASS(clazz, "android/database/CharArrayBuffer"); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5383bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.data, clazz, 5393bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "data", "[C"); 5403bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown GET_FIELD_ID(gCharArrayBufferClassInfo.sizeCopied, clazz, 5413bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown "sizeCopied", "I"); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5433bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown gEmptyString = jstring(env->NewGlobalRef(env->NewStringUTF(""))); 5443bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown LOG_FATAL_IF(!gEmptyString, "Unable to create empty string"); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/database/CursorWindow", 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sMethods, NELEM(sMethods)); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 551