diff options
Diffstat (limited to '')
-rw-r--r-- | src/rocksdb/java/rocksjni/slice.cc | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/src/rocksdb/java/rocksjni/slice.cc b/src/rocksdb/java/rocksjni/slice.cc new file mode 100644 index 00000000..e617cde2 --- /dev/null +++ b/src/rocksdb/java/rocksjni/slice.cc @@ -0,0 +1,356 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). +// +// This file implements the "bridge" between Java and C++ for +// rocksdb::Slice. + +#include <jni.h> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include "include/org_rocksdb_AbstractSlice.h" +#include "include/org_rocksdb_DirectSlice.h" +#include "include/org_rocksdb_Slice.h" +#include "rocksdb/slice.h" +#include "rocksjni/portal.h" + +// <editor-fold desc="org.rocksdb.AbstractSlice> + +/* + * Class: org_rocksdb_AbstractSlice + * Method: createNewSliceFromString + * Signature: (Ljava/lang/String;)J + */ +jlong Java_org_rocksdb_AbstractSlice_createNewSliceFromString(JNIEnv* env, + jclass /*jcls*/, + jstring jstr) { + const auto* str = env->GetStringUTFChars(jstr, nullptr); + if (str == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + + const size_t len = strlen(str); + + // NOTE: buf will be deleted in the + // Java_org_rocksdb_Slice_disposeInternalBuf or + // or Java_org_rocksdb_DirectSlice_disposeInternalBuf methods + char* buf = new char[len + 1]; + memcpy(buf, str, len); + buf[len] = 0; + env->ReleaseStringUTFChars(jstr, str); + + const auto* slice = new rocksdb::Slice(buf); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: size0 + * Signature: (J)I + */ +jint Java_org_rocksdb_AbstractSlice_size0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return static_cast<jint>(slice->size()); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: empty0 + * Signature: (J)Z + */ +jboolean Java_org_rocksdb_AbstractSlice_empty0(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return slice->empty(); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: toString0 + * Signature: (JZ)Ljava/lang/String; + */ +jstring Java_org_rocksdb_AbstractSlice_toString0(JNIEnv* env, jobject /*jobj*/, + jlong handle, jboolean hex) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const std::string s = slice->ToString(hex); + return env->NewStringUTF(s.c_str()); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: compare0 + * Signature: (JJ)I; + */ +jint Java_org_rocksdb_AbstractSlice_compare0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jlong otherHandle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const auto* otherSlice = reinterpret_cast<rocksdb::Slice*>(otherHandle); + return slice->compare(*otherSlice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: startsWith0 + * Signature: (JJ)Z; + */ +jboolean Java_org_rocksdb_AbstractSlice_startsWith0(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle, + jlong otherHandle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const auto* otherSlice = reinterpret_cast<rocksdb::Slice*>(otherHandle); + return slice->starts_with(*otherSlice); +} + +/* + * Class: org_rocksdb_AbstractSlice + * Method: disposeInternal + * Signature: (J)V + */ +void Java_org_rocksdb_AbstractSlice_disposeInternal(JNIEnv* /*env*/, + jobject /*jobj*/, + jlong handle) { + delete reinterpret_cast<rocksdb::Slice*>(handle); +} + +// </editor-fold> + +// <editor-fold desc="org.rocksdb.Slice> + +/* + * Class: org_rocksdb_Slice + * Method: createNewSlice0 + * Signature: ([BI)J + */ +jlong Java_org_rocksdb_Slice_createNewSlice0(JNIEnv* env, jclass /*jcls*/, + jbyteArray data, jint offset) { + const jsize dataSize = env->GetArrayLength(data); + const int len = dataSize - offset; + + // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf + // method + jbyte* buf = new jbyte[len]; + env->GetByteArrayRegion(data, offset, len, buf); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + return 0; + } + + const auto* slice = new rocksdb::Slice((const char*)buf, len); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_Slice + * Method: createNewSlice1 + * Signature: ([B)J + */ +jlong Java_org_rocksdb_Slice_createNewSlice1(JNIEnv* env, jclass /*jcls*/, + jbyteArray data) { + jbyte* ptrData = env->GetByteArrayElements(data, nullptr); + if (ptrData == nullptr) { + // exception thrown: OutOfMemoryError + return 0; + } + const int len = env->GetArrayLength(data) + 1; + + // NOTE: buf will be deleted in the Java_org_rocksdb_Slice_disposeInternalBuf + // method + char* buf = new char[len]; + memcpy(buf, ptrData, len - 1); + buf[len - 1] = '\0'; + + const auto* slice = new rocksdb::Slice(buf, len - 1); + + env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT); + + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_Slice + * Method: data0 + * Signature: (J)[B + */ +jbyteArray Java_org_rocksdb_Slice_data0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const jsize len = static_cast<jsize>(slice->size()); + const jbyteArray data = env->NewByteArray(len); + if (data == nullptr) { + // exception thrown: OutOfMemoryError + return nullptr; + } + + env->SetByteArrayRegion( + data, 0, len, + const_cast<jbyte*>(reinterpret_cast<const jbyte*>(slice->data()))); + if (env->ExceptionCheck()) { + // exception thrown: ArrayIndexOutOfBoundsException + env->DeleteLocalRef(data); + return nullptr; + } + + return data; +} + +/* + * Class: org_rocksdb_Slice + * Method: clear0 + * Signature: (JZJ)V + */ +void Java_org_rocksdb_Slice_clear0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jboolean shouldRelease, + jlong internalBufferOffset) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + if (shouldRelease == JNI_TRUE) { + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; + } + slice->clear(); +} + +/* + * Class: org_rocksdb_Slice + * Method: removePrefix0 + * Signature: (JI)V + */ +void Java_org_rocksdb_Slice_removePrefix0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jint length) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + slice->remove_prefix(length); +} + +/* + * Class: org_rocksdb_Slice + * Method: disposeInternalBuf + * Signature: (JJ)V + */ +void Java_org_rocksdb_Slice_disposeInternalBuf(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle, + jlong internalBufferOffset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; +} + +// </editor-fold> + +// <editor-fold desc="org.rocksdb.DirectSlice> + +/* + * Class: org_rocksdb_DirectSlice + * Method: createNewDirectSlice0 + * Signature: (Ljava/nio/ByteBuffer;I)J + */ +jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice0(JNIEnv* env, + jclass /*jcls*/, + jobject data, + jint length) { + assert(data != nullptr); + void* data_addr = env->GetDirectBufferAddress(data); + if (data_addr == nullptr) { + // error: memory region is undefined, given object is not a direct + // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM + rocksdb::IllegalArgumentExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Could not access DirectBuffer")); + return 0; + } + + const auto* ptrData = reinterpret_cast<char*>(data_addr); + const auto* slice = new rocksdb::Slice(ptrData, length); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: createNewDirectSlice1 + * Signature: (Ljava/nio/ByteBuffer;)J + */ +jlong Java_org_rocksdb_DirectSlice_createNewDirectSlice1(JNIEnv* env, + jclass /*jcls*/, + jobject data) { + void* data_addr = env->GetDirectBufferAddress(data); + if (data_addr == nullptr) { + // error: memory region is undefined, given object is not a direct + // java.nio.Buffer, or JNI access to direct buffers is not supported by JVM + rocksdb::IllegalArgumentExceptionJni::ThrowNew( + env, rocksdb::Status::InvalidArgument("Could not access DirectBuffer")); + return 0; + } + + const auto* ptrData = reinterpret_cast<char*>(data_addr); + const auto* slice = new rocksdb::Slice(ptrData); + return reinterpret_cast<jlong>(slice); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: data0 + * Signature: (J)Ljava/lang/Object; + */ +jobject Java_org_rocksdb_DirectSlice_data0(JNIEnv* env, jobject /*jobj*/, + jlong handle) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return env->NewDirectByteBuffer(const_cast<char*>(slice->data()), + slice->size()); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: get0 + * Signature: (JI)B + */ +jbyte Java_org_rocksdb_DirectSlice_get0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jint offset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + return (*slice)[offset]; +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: clear0 + * Signature: (JZJ)V + */ +void Java_org_rocksdb_DirectSlice_clear0(JNIEnv* /*env*/, jobject /*jobj*/, + jlong handle, jboolean shouldRelease, + jlong internalBufferOffset) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + if (shouldRelease == JNI_TRUE) { + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; + } + slice->clear(); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: removePrefix0 + * Signature: (JI)V + */ +void Java_org_rocksdb_DirectSlice_removePrefix0(JNIEnv* /*env*/, + jobject /*jobj*/, jlong handle, + jint length) { + auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + slice->remove_prefix(length); +} + +/* + * Class: org_rocksdb_DirectSlice + * Method: disposeInternalBuf + * Signature: (JJ)V + */ +void Java_org_rocksdb_DirectSlice_disposeInternalBuf( + JNIEnv* /*env*/, jobject /*jobj*/, jlong handle, + jlong internalBufferOffset) { + const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle); + const char* buf = slice->data_ - internalBufferOffset; + delete[] buf; +} + +// </editor-fold> |