summaryrefslogtreecommitdiff
path: root/libs/samba/src/main/cpp/jni.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/samba/src/main/cpp/jni.hpp')
-rw-r--r--libs/samba/src/main/cpp/jni.hpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/libs/samba/src/main/cpp/jni.hpp b/libs/samba/src/main/cpp/jni.hpp
new file mode 100644
index 0000000..90ca011
--- /dev/null
+++ b/libs/samba/src/main/cpp/jni.hpp
@@ -0,0 +1,142 @@
+#ifndef CLEVERSYNC_JNI_HPP
+#define CLEVERSYNC_JNI_HPP
+
+#include <jni.h>
+#include <string>
+
+#define ABORT_IF_NOT_OK(x) (::jni::internal::_abort_if_not_ok(__FILE__, __LINE__, (x)))
+#define ABORT_IF_NULL(env, x) (::jni::internal::_abort_if_null(__FILE__, __LINE__, (env), (x)))
+
+namespace jni {
+
+namespace internal {
+
+void _abort_if_not_ok(const char *file, int line, jint ret);
+void _abort_with_exception(const char* file, int line, JNIEnv* env);
+
+} // namespace internal
+
+template<class T>
+class Ref {
+ public:
+ constexpr Ref() : env_(nullptr), ptr_(0) {}
+ Ref(const Ref<T>&) = delete;
+ Ref<T>& operator=(const Ref<T>&) = delete;
+
+ [[nodiscard]] T get() const { return ptr_; }
+ [[nodiscard]] T release() {
+ auto ret = release_to_local();
+ ptr_ = 0;
+ return ret;
+ }
+
+ void reset() {
+ del();
+ ptr_ = 0;
+ }
+
+ explicit operator bool() const { return ptr_ != 0; }
+
+ protected:
+ Ref(JNIEnv* env, T ptr): env_(env), ptr_(ptr) {}
+ virtual ~Ref() = default;
+
+ virtual T release_to_local() = 0;
+ virtual void del() = 0;
+
+ JNIEnv* const env_;
+ T ptr_;
+};
+
+template<class T>
+class LocalRef : public Ref<T> {
+ public:
+ LocalRef(JNIEnv* env, T ptr): Ref<T>(env, ptr) {}
+ ~LocalRef() override { free(); }
+
+ protected:
+ T release_to_local() override { return this->ptr_; }
+ void del() override { free(); }
+
+ private:
+ void free() {
+ if (this->ptr_)
+ this->env_->DeleteLocalRef(this->ptr_);
+ }
+};
+
+template<class T>
+class ParamRef : public Ref<T> {
+ public:
+ ParamRef(JNIEnv* env, T ptr) : Ref<T>(env, ptr) {}
+ ~ParamRef() override = default;
+
+ protected:
+ T release_to_local() override {
+ if (this->ptr_)
+ return static_cast<T>(this->env_->NewLocalRef(static_cast<jobject>(this->ptr_)));
+ return 0;
+ }
+ void del() override {}
+};
+
+template<class T>
+class GlobalRef : public Ref<T> {
+ public:
+ GlobalRef(JNIEnv* env, T ptr) : Ref<T>(env, ptr ? env->NewGlobalRef(ptr) : 0) {}
+ explicit GlobalRef(const Ref<T>& other) : Ref<T>(other.env_, other ? other.env_->NewGlobalRef(other.ptr_) : 0) {}
+
+ ~GlobalRef() override { free(); }
+
+ protected:
+ T release_to_local() override {
+ if (this->ptr_) {
+ auto ret = static_cast<T>(this->env_->NewLocalRef(
+ static_cast<jobject>(this->ptr_)));
+ free();
+ return ret;
+ }
+ return 0;
+ }
+ void del() override { free(); }
+
+ private:
+ void free() {
+ if (this->ptr_)
+ this->env_->DeleteGlobalRef(this->ptr_);
+ }
+};
+
+constexpr jint JNI_VERSION = JNI_VERSION_1_2;
+
+JNIEnv* AttachCurrentThread();
+
+JNIEnv* OnLoad(JavaVM* vm);
+
+LocalRef<jclass> FindClass(JNIEnv *env, const char *name);
+
+LocalRef<jthrowable> ExceptionOccurred(JNIEnv* env);
+
+template<typename Out, typename In>
+LocalRef<Out> CallObjectMethod(JNIEnv* env, const Ref<In>& object, jmethodID method) {
+ return {env, static_cast<Out>(env->CallObjectMethod(object.get(), method))};
+}
+
+std::string StringToUTF8(JNIEnv* env, const Ref<jstring>& str);
+
+LocalRef<jstring> UTF8ToString(JNIEnv* env, const std::string& str);
+
+namespace internal {
+
+template<typename T>
+void _abort_if_null(const char* file, int line, JNIEnv* env, const jni::Ref<T>& ref) {
+ if (ref) [[likely]] return;
+
+ _abort_with_exception(file, line, env);
+}
+
+} // namespace internal
+
+} // namespace jni
+
+#endif // CLEVERSYNC_JNI_HPP