summaryrefslogtreecommitdiff
path: root/libs/samba/src/main/cpp/jni.cpp
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2024-07-22 23:06:16 +0200
committerJoel Klinghed <the_jk@spawned.biz>2024-07-23 00:04:58 +0200
commit09bc93ed756361d396890c389b01315cdb5e32fd (patch)
tree3a2718a2b5a3584a489d009a532526239f6b45a5 /libs/samba/src/main/cpp/jni.cpp
parent42564c71cfb70c28831c662a3b6bf4084e079353 (diff)
Add initial code for samba implementation based on libsmb2
Diffstat (limited to 'libs/samba/src/main/cpp/jni.cpp')
-rw-r--r--libs/samba/src/main/cpp/jni.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/libs/samba/src/main/cpp/jni.cpp b/libs/samba/src/main/cpp/jni.cpp
new file mode 100644
index 0000000..be13df7
--- /dev/null
+++ b/libs/samba/src/main/cpp/jni.cpp
@@ -0,0 +1,100 @@
+#include "jni.hpp"
+
+#include <android/log.h>
+
+namespace {
+
+JavaVM *g_vm;
+
+const char *_jni_error(jint err) {
+ switch (err) {
+ case JNI_OK:
+ return "OK";
+ case JNI_ERR:
+ return "Unknown error";
+ case JNI_EDETACHED:
+ return "Thread detached from the VM";
+ case JNI_EVERSION:
+ return "JNI version error";
+ case JNI_ENOMEM:
+ return "Not enough memory";
+ case JNI_EEXIST:
+ return "VM already created";
+ case JNI_EINVAL:
+ return "Invalid arguments";
+ default:
+ return "Unexpected error";
+ }
+}
+
+} // namespace
+
+namespace jni {
+
+namespace internal {
+
+void _abort_if_not_ok(const char *file, int line, jint ret) {
+ if (ret == JNI_OK) [[likely]] return;
+ __android_log_assert(nullptr, "jni", "JNI error: %s", _jni_error(ret));
+}
+
+void _abort_with_exception(const char* file, int line, JNIEnv* env) {
+ auto throwable = jni::ExceptionOccurred(env);
+ env->ExceptionClear();
+ if (throwable) {
+ auto throwable_class = jni::FindClass(env, "java/lang/Throwable");
+ if (throwable_class) {
+ auto throwable_toString = env->GetMethodID(throwable_class.get(),
+ "toString",
+ "()Ljava/lang/String;");
+ if (throwable_toString) {
+ auto description = jni::CallObjectMethod<jstring>(env, throwable,
+ throwable_toString);
+ auto str = jni::StringToUTF8(env, description);
+ __android_log_assert(nullptr, "jni", "JNI error: %s", str.c_str());
+ }
+ }
+ env->ExceptionClear();
+ __android_log_assert(nullptr, "jni",
+ "Unexpected NULL but no exception");
+ }
+}
+
+} // namespace internal
+
+JNIEnv* AttachCurrentThread() {
+ JNIEnv* env;
+ auto ret = g_vm->AttachCurrentThread(&env, nullptr);
+ ABORT_IF_NOT_OK(ret);
+ return env;
+}
+
+JNIEnv* OnLoad(JavaVM* vm) {
+ void* v_env;
+ auto ret = vm->GetEnv(&v_env, JNI_VERSION);
+ ABORT_IF_NOT_OK(ret);
+ return reinterpret_cast<JNIEnv*>(v_env);
+}
+
+LocalRef<jclass> FindClass(JNIEnv *env, const char *name) {
+ return {env, env->FindClass(name)};
+}
+
+LocalRef<jthrowable> ExceptionOccurred(JNIEnv* env) {
+ return {env, env->ExceptionOccurred()};
+}
+
+std::string StringToUTF8(JNIEnv* env, const Ref<jstring>& str) {
+ if (!str) return "null";
+ auto len = env->GetStringUTFLength(str.get());
+ std::string ret(len, ' ');
+ env->GetStringUTFRegion(str.get(), 0, len, ret.data());
+ // This returns modified UTF-8 encoding, don't care.
+ return ret;
+}
+
+LocalRef<jstring> UTF8ToString(JNIEnv* env, const std::string& str) {
+ return {env, env->NewStringUTF(str.c_str())};
+}
+
+} // namespace jni