diff --git a/lsplant/src/main/jni/include/utils/jni_helper.hpp b/lsplant/src/main/jni/include/utils/jni_helper.hpp index 4077607..9adf5c6 100644 --- a/lsplant/src/main/jni/include/utils/jni_helper.hpp +++ b/lsplant/src/main/jni/include/utils/jni_helper.hpp @@ -792,11 +792,6 @@ template template struct JArrayUnderlyingTypeHelper; -template <> -struct JArrayUnderlyingTypeHelper { - using Type = ScopedLocalRef; -}; - template <> struct JArrayUnderlyingTypeHelper { using Type = jboolean; @@ -1053,6 +1048,246 @@ private: DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); }; + +class JObjectArrayElement{ +public: + friend class ScopedLocalRef; + explicit JObjectArrayElement(JNIEnv * env, jobjectArray array, int i) : env_(env), array_(array), i_(i) { + item_ = JNI_SafeInvoke(env_, &JNIEnv::GetObjectArrayElement, array_, i_).release(); + } + + ~JObjectArrayElement(){ + if (item_){ + env_->DeleteLocalRef(item_); + } + } + + void reset(int i){ + if (item_){ + env_->DeleteLocalRef(item_); + } + i_ = i; + item_ = JNI_SafeInvoke(env_, &JNIEnv::GetObjectArrayElement, array_, i).release(); + } + + JObjectArrayElement(JObjectArrayElement&& s){ + env_ = s.env_; + array_ = s.array_; + i_ = s.i_; + item_ = s.item_; + s.env_ = nullptr; + s.array_ = nullptr; + s.i_ = -1; + s.item_ = nullptr; + } + + operator jobject(){ + return item_; + } + + JObjectArrayElement &operator=(jobject s) noexcept { + if (item_){ + env_->DeleteLocalRef(item_); + } + JNI_SafeInvoke(env_, &JNIEnv::SetObjectArrayElement, array_, i_, s); + item_ = s; + return *this; + } +private: + JNIEnv *env_; + jobjectArray array_; + int i_; + jobject item_; + DISALLOW_COPY_AND_ASSIGN(JObjectArrayElement); +}; + +template<> +class ScopedLocalRef { + using T = jobjectArray; + + ScopedLocalRef(JNIEnv *env, T local_ref, size_t size,bool modified) noexcept + : env_(env), local_ref_(local_ref), size_(size), modified_(modified) {} + +public: + class Iterator { + friend class ScopedLocalRef; + + Iterator(JObjectArrayElement&& e) : e_(std::move(e)) {} + + JObjectArrayElement e_; + + public: + auto &operator*() { return e_; } + + auto *operator->() { return &e_; } + + Iterator &operator++() { + e_.reset(e_.i_ + 1); + return *this; + } + + Iterator &operator--() { + e_.reset(e_.i_ - 1); + return *this; + } + + Iterator operator++(int) { + return Iterator(JObjectArrayElement(e_.env_, e_.array_, e_.i_ + 1)); + } + + Iterator operator--(int) { + return Iterator(JObjectArrayElement(e_.env_, e_.array_, e_.i_ - 1)); + } + + bool operator==(const Iterator &other) const { return other.e_.i_ == e_.i_; } + + bool operator!=(const Iterator &other) const { return other.e_.i_ != e_.i_; } + }; + +// class ConstIterator { +// friend class ScopedLocalRef; +// +// ConstIterator(int i) : i_(i) { +// item_ = JNI_SafeInvoke(env_, &JNIEnv::GetObjectArrayElement, local_ref_, i); +// } +// +// int i_; +// jobject item_; +// +// public: +// auto &operator*() { return e_; } +// +// auto *operator->() { return &e_; } +// +// ConstIterator &operator++() { +// e_ = std::move(JObjectArrayConstElement(e_.env_, e_.array_, e_.i_ + 1)); +// return *this; +// } +// +// ConstIterator &operator--() { +// e_ = JObjectArrayConstElement(e_.env_, e_.array_, e_.i_ - 1); +// return *this; +// } +// +// ConstIterator operator++(int) { +// return ConstIterator(JObjectArrayConstElement(e_.env_, e_.array_, e_.i_ + 1)); +// } +// +// ConstIterator operator--(int) { +// return ConstIterator(JObjectArrayConstElement(e_.env_, e_.array_, e_.i_ - 1)); +// } +// +// bool operator==(const ConstIterator &other) const { return other.e_.i_ == e_.i_; } +// +// bool operator!=(const ConstIterator &other) const { return other.e_.i_ != e_.i_; } +// }; + + auto begin() { + modified_ = true; + return Iterator(JObjectArrayElement(env_, local_ref_, 0)); + } + + auto end() { + modified_ = true; + return Iterator(JObjectArrayElement(env_, local_ref_, size_)); + } + +// const auto begin() const { return ConstIterator(JObjectArrayConstElement(env_, local_ref_, 0)); } +// +// auto end() const { return ConstIterator(JObjectArrayConstElement(env_, local_ref_, size_)); } +// +// const auto cbegin() const { return ConstIterator(JObjectArrayConstElement(env_, local_ref_, 0)); } +// +// auto cend() const { return ConstIterator(JObjectArrayConstElement(env_, local_ref_, size_)); } + + using BaseType [[maybe_unused]] = T; + + ScopedLocalRef(JNIEnv *env, T local_ref) noexcept: env_(env), local_ref_(nullptr) { + reset(local_ref); + } + + ScopedLocalRef(ScopedLocalRef &&s) noexcept + : ScopedLocalRef(s.env_, s.local_ref_, s.size_, s.modified_) { + s.local_ref_ = nullptr; + s.size_ = 0; + s.modified_ = false; + } + + template + ScopedLocalRef(ScopedLocalRef &&s) noexcept : ScopedLocalRef(s.env_, (T) s.release()) {} + + explicit ScopedLocalRef(JNIEnv *env) noexcept: ScopedLocalRef(env, T{nullptr}) {} + + ~ScopedLocalRef() { env_->DeleteLocalRef(release()); } + + void reset(T ptr = nullptr) { + if (ptr != local_ref_) { + if (local_ref_ != nullptr) { + env_->DeleteLocalRef(local_ref_); + } + local_ref_ = ptr; + size_ = local_ref_ ? env_->GetArrayLength(local_ref_) : 0; + if (!local_ref_) return; + } + } + + [[nodiscard]] T release() { + T localRef = local_ref_; + size_ = 0; + local_ref_ = nullptr; + return localRef; + } + + T get() const { return local_ref_; } + + explicit operator T() const { return local_ref_; } + + JObjectArrayElement operator[](size_t index) { + modified_ = true; + return JObjectArrayElement(env_, local_ref_, index); + } + + const ScopedLocalRef operator[](size_t index) const { + return JNI_SafeInvoke(env_, &JNIEnv::GetObjectArrayElement, local_ref_, index); + } + + void commit() { + modified_ = false; + } + + // We do not expose an empty constructor as it can easily lead to errors + // using common idioms, e.g.: + // ScopedLocalRef<...> ref; + // ref.reset(...); + // Move assignment operator. + ScopedLocalRef &operator=(ScopedLocalRef &&s) noexcept { + env_ = s.env_; + local_ref_ = s.local_ref_; + size_ = s.size_; + modified_ = s.modified_; + s.size_ = 0; + s.modified_ = false; + s.local_ref_ = nullptr; + return *this; + } + + size_t size() const { return size_; } + + operator bool() const { return local_ref_; } + + template + friend + class ScopedLocalRef; + + friend class JUTFString; + +private: + JNIEnv *env_; + T local_ref_; + size_t size_; + bool modified_ = false; + DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); +}; // functions to array template Array>