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 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;
}