static jbyteArray getBlob_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; if (type == FIELD_TYPE_BLOB || type == FIELD_TYPE_STRING) { jbyteArray byteArray = env->NewByteArray(field.data.buffer.size); LOG_ASSERT(byteArray, "Native could not create new byte[]"); env->SetByteArrayRegion(byteArray, 0, field.data.buffer.size, (const jbyte*)window->offsetToPtr(field.data.buffer.offset)); return byteArray; } else if (type == FIELD_TYPE_INTEGER) { throw_sqlite3_exception(env, "INTEGER data in getBlob_native "); } else if (type == FIELD_TYPE_FLOAT) { throw_sqlite3_exception(env, "FLOAT data in getBlob_native "); } else if (type == FIELD_TYPE_NULL) { // do nothing } else { throwUnknowTypeException(env, type); } return NULL; }
static jstring getString_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { #if WINDOW_STORAGE_UTF8 // Pass size - 1 since the UTF8 is null terminated and we don't want a null terminator on the UTF16 string String16 utf16((char const *)window->offsetToPtr(field.data.buffer.offset), size - 1); return env->NewString((jchar const *)utf16.string(), utf16.size()); #else return env->NewString((jchar const *)window->offsetToPtr(field.data.buffer.offset), size / 2); #endif } else { return env->NewStringUTF(""); } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%lld", value); return env->NewStringUTF(buf); } return NULL; } else if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { char buf[32]; //selete the print way by code to impove the precision if (((value > 0.0001) && (value < 1000000)) || ((value < -0.0001) && (value > -1000000))) snprintf(buf, sizeof(buf), "%lf", value); else snprintf(buf, sizeof(buf), "%e", value); return env->NewStringUTF(buf); } return NULL; } else if (type == FIELD_TYPE_NULL) { return NULL; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); return NULL; } else { throwUnknowTypeException(env, type); return NULL; } }
static jdouble getDouble_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return 0.0; } uint8_t type = field.type; if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { return value; } return 0.0; } else if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { #if WINDOW_STORAGE_UTF8 return strtod((char const *)window->offsetToPtr(field.data.buffer.offset), NULL); #else String8 ascii((char16_t *) window->offsetToPtr(field.data.buffer.offset), size / 2); char const * str = ascii.string(); return strtod(str, NULL); #endif } else { return 0.0; } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { return (double) value; } return 0.0; } else if (type == FIELD_TYPE_NULL) { return 0.0; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to double"); return 0.0; } else { throwUnknowTypeException(env, type); return 0.0; } }
static jdouble getDouble_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return 0.0; } uint8_t type = field.type; if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { return value; } return 0.0; } else if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { double result; jstring data = env->NewString((const jchar*)window->offsetToPtr(field.data.buffer.offset), (jsize)size); const char* utf8data = env->GetStringUTFChars(data, NULL); result = strtod(utf8data, NULL); if(utf8data) env->ReleaseStringUTFChars(data, utf8data); if(data) env->DeleteLocalRef(data); return result; } else { return 0.0; } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { return (double) value; } return 0.0; } else if (type == FIELD_TYPE_NULL) { return 0.0; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to double"); return 0.0; } else { throwUnknowTypeException(env, type); return 0.0; } }
static jboolean isFloat_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Checking if column is a float for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } return field.type == FIELD_TYPE_FLOAT; }
static jint getType_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting type for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } return field.type; }
static jstring getString_native(JNIEnv* env, jobject object, jint row, jint column) { int i; int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; jint size = (jint)field.data.buffer.size; if (type == FIELD_TYPE_NULL) { return NULL; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); return NULL; } else if (type == FIELD_TYPE_STRING) { jchar * buf = (jchar *)window->offsetToPtr(field.data.buffer.offset); jclass strClass = env->FindClass("java/lang/String"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jstring encoding = env->NewStringUTF("UTF-16LE"); jbyteArray bytes = env->NewByteArray(size); env->SetByteArrayRegion(bytes, 0, size, (jbyte*)buf); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%lld", value); return env->NewStringUTF((const char*)buf); } return NULL; } else if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%g", value); return env->NewStringUTF(buf); } return NULL; } }
static jcharArray copyStringToBuffer_native(JNIEnv* env, jobject object, jint row, jint column, jint bufferSize, jobject buf) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Copying string for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { jniThrowException(env, "java/lang/IllegalStateException", "Unable to get field slot"); return NULL; } jcharArray buffer = (jcharArray)env->GetObjectField(buf, gBufferField); if (buffer == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "buf should not be null"); return NULL; } jchar* dst = env->GetCharArrayElements(buffer, NULL); uint8_t type = field.type; uint32_t sizeCopied = 0; jcharArray newArray = NULL; if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { #if WINDOW_STORAGE_UTF8 // Pass size - 1 since the UTF8 is null terminated and we don't want a null terminator on the UTF16 string String16 utf16((char const *)window->offsetToPtr(field.data.buffer.offset), size - 1); int32_t strSize = utf16.size(); if (strSize > bufferSize || dst == NULL) { newArray = env->NewCharArray(strSize); env->SetCharArrayRegion(newArray, 0, strSize, (jchar const *)utf16.string()); } else { memcpy(dst, (jchar const *)utf16.string(), strSize * 2); } sizeCopied = strSize; #else sizeCopied = size/2 + size % 2; if (size > bufferSize * 2 || dst == NULL) { newArray = env->NewCharArray(sizeCopied); memcpy(newArray, (jchar const *)window->offsetToPtr(field.data.buffer.offset), size); } else { memcpy(dst, (jchar const *)window->offsetToPtr(field.data.buffer.offset), size); } #endif } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { char buf[32]; int len; snprintf(buf, sizeof(buf), "%lld", value); jchar* dst = env->GetCharArrayElements(buffer, NULL); sizeCopied = charToJchar(buf, dst, bufferSize); } } else if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { char tempbuf[32]; snprintf(tempbuf, sizeof(tempbuf), "%g", value); jchar* dst = env->GetCharArrayElements(buffer, NULL); sizeCopied = charToJchar(tempbuf, dst, bufferSize); } } else if (type == FIELD_TYPE_NULL) { } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); } else { LOGE("Unknown field type %d", type); throw_sqlite3_exception(env, "UNKNOWN type in copyStringToBuffer_native()"); } SET_SIZE_COPIED(env, buf, sizeCopied); env->ReleaseCharArrayElements(buffer, dst, JNI_OK); return newArray; }