Skip to content

Commit

Permalink
Reuses container utils for lambda converters (#1591)
Browse files Browse the repository at this point in the history
Signed-off-by: Yauheni Khnykin <[email protected]>
  • Loading branch information
Hsilgos authored May 15, 2024
1 parent 3de8902 commit f04503e
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 319 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,12 @@ internal class JavaGenerator : Generator {

private val UTILS_FILES =
listOf(
"ArrayConversionUtils",
"CppProxyBase",
"FieldAccessMethods",
"JniBase",
"JniCallbackErrorChecking",
"JniCppConversionUtils",
"JniJavaContainers",
"BoxingConversionUtils",
"JniClassCache",
"JniNativeHandle",
Expand All @@ -278,7 +278,7 @@ internal class JavaGenerator : Generator {
"JniThrowNewException",
)
private val UTILS_FILES_HEADER_ONLY =
listOf("JniCallJavaMethod", "JniTemplateMetainfo", "JniTypeId")
listOf("JniCallJavaMethod", "ArrayConversionUtils", "JniTemplateMetainfo", "JniTypeId")

private fun annotationFromOption(option: Pair<String, List<String>>?) = option?.let { JavaImport(option.second, option.first) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
{{/includes}}
{{#ifPredicate model "hasOverloadedLambda"}}
#include "JniCallJavaMethod.h"
#include "JniJavaContainers.h"
{{/ifPredicate}}
#include "JniReference.h"
#include "JniTypeId.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{!!
!
! Copyright (C) 2016-2021 HERE Europe B.V.
! Copyright (C) 2016-2024 HERE Europe B.V.
!
! Licensed under the Apache License, Version 2.0 (the "License");
! you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,65 +32,48 @@ JNIEXPORT std::optional<std::vector<{{resolveName "C++ FQN"}}>> {{resolveName "m

template <typename K, typename Hash>
JniReference<jobject>
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* _env, const std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>& _ninput) {
auto javaClass = find_class(_env, "java/util/HashMap");
auto result = create_object(_env, javaClass);
jmethodID putMethodId = _env->GetMethodID(javaClass.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* const env, const std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>& input)
{
JavaHashMapAdder map_adder{env};

for (const auto& pair : _ninput) {
auto jKey = convert_to_jni(_env, pair.first);
auto jValue = {{resolveName "mangled"}}_convert_to_jni(_env, pair.second);
call_java_method<jobject>(_env, result, putMethodId, jKey, jValue);
for (const auto& pair : input)
{
map_adder.add(convert_to_jni(env, pair.first),
{{resolveName "mangled"}}_convert_to_jni(env, pair.second));
}

return result;
return map_adder.fetch_hash_map();
}

template <typename K, typename Hash>
JniReference<jobject>
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* _env, const std::optional<std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>>& _ninput) {
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* _env, const std::optional<std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>>& _ninput)
{
return _ninput ? {{resolveName "mangled"}}_convert_to_jni(_env, *_ninput) : JniReference<jobject>{};
}

template <typename K, typename Hash>
std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>
{{resolveName "mangled"}}_convert_from_jni(
JNIEnv* _env, const JniReference<jobject>& _jMap, TypeId<std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>>
) {
std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash> _nresult{};
JNIEnv* const env, const JniReference<jobject>& java_map, TypeId<std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash>>)
{
std::unordered_map<K, {{resolveName "C++ FQN"}}, Hash> result{};

if (_env->IsSameObject(_jMap.get(), nullptr)) {
return _nresult;
if (env->IsSameObject(java_map.get(), nullptr))
{
return result;
}

auto javaMapClass = find_class(_env, "java/util/Map");
auto entrySetMethodId = _env->GetMethodID(javaMapClass.get(), "entrySet", "()Ljava/util/Set;");
auto jEntrySet = call_java_method<jobject>(_env, _jMap, entrySetMethodId);

auto javaSetClass = find_class(_env, "java/util/Set");
auto iteratorMethodId = _env->GetMethodID(javaSetClass.get(), "iterator", "()Ljava/util/Iterator;");
auto jIterator = call_java_method<jobject>(_env, jEntrySet, iteratorMethodId);
const JavaMapIterator map_iterator(env, java_map);

auto javaIteratorClass = find_class(_env, "java/util/Iterator");
auto hasNextMethodId = _env->GetMethodID(javaIteratorClass.get(), "hasNext", "()Z");
auto nextMethodId = _env->GetMethodID(javaIteratorClass.get(), "next", "()Ljava/lang/Object;");

auto javaMapEntryClass = find_class(_env, "java/util/Map$Entry");
auto getKeyMethodId = _env->GetMethodID(javaMapEntryClass.get(), "getKey", "()Ljava/lang/Object;");
auto getValueMethodId = _env->GetMethodID(javaMapEntryClass.get(), "getValue", "()Ljava/lang/Object;");

while (call_java_method<jboolean>(_env, jIterator, hasNextMethodId)) {
auto jEntry = call_java_method<jobject>(_env, jIterator, nextMethodId);
auto jKey = call_java_method<jobject>(_env, jEntry, getKeyMethodId);
K nKey = convert_from_jni(_env, jKey, TypeId<K>{});

auto jValue = call_java_method<jobject>(_env, jEntry, getValueMethodId);
auto nValue = {{resolveName "mangled"}}_convert_from_jni(_env, jValue, TypeId<{{resolveName "C++ FQN"}}>{});

_nresult.emplace(std::move(nKey), std::move(nValue));
while(map_iterator.has_next())
{
const auto& key_value = map_iterator.next();
result.emplace(convert_from_jni(env, key_value.first, TypeId<K>{}),
{{resolveName "mangled"}}_convert_from_jni(env, key_value.second, TypeId<{{resolveName "C++ FQN"}}>{}));
}

return _nresult;
return result;
}

template<typename K, typename Hash>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{!!
!
! Copyright (C) 2016-2021 HERE Europe B.V.
! Copyright (C) 2016-2024 HERE Europe B.V.
!
! Licensed under the Apache License, Version 2.0 (the "License");
! you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,17 +31,16 @@ JniReference<jobject>
}

JniReference<jobject>
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* _env, const std::vector<{{resolveName "C++ FQN"}}>& _ninput) {
auto javaClass = find_class(_env, "java/util/ArrayList");
auto result = create_object(_env, javaClass);
jmethodID addMethodId = _env->GetMethodID(javaClass.get(), "add", "(Ljava/lang/Object;)Z");
{{resolveName "mangled"}}_convert_to_jni(JNIEnv* const env, const std::vector<{{resolveName "C++ FQN"}}>& input)
{
JavaArrayListAdder list_appender{env};

for (const auto& element : _ninput) {
auto jElement = {{resolveName "mangled"}}_convert_to_jni(_env, element);
call_java_method<jboolean>(_env, result, addMethodId, jElement);
for (const auto& element : input)
{
list_appender.add({{resolveName "mangled"}}_convert_to_jni(env, element));
}

return result;
return list_appender.fetch_container();
}

JniReference<jobject>
Expand All @@ -50,24 +49,26 @@ JniReference<jobject>
}

std::vector<{{resolveName "C++ FQN"}}>
{{resolveName "mangled"}}_convert_from_jni(JNIEnv* _env, const JniReference<jobject>& _arrayList, TypeId<std::vector<{{resolveName "C++ FQN"}}>>) {
std::vector<{{resolveName "C++ FQN"}}> _nresult{};
if (_env->IsSameObject(_arrayList.get(), nullptr)) {
return _nresult;
{{resolveName "mangled"}}_convert_from_jni(JNIEnv* const env, const JniReference<jobject>& array_list, TypeId<std::vector<{{resolveName "C++ FQN"}}>>) {
std::vector<{{resolveName "C++ FQN"}}> result{};
if (env->IsSameObject(array_list.get(), nullptr))
{
return result;
}

auto javaArrayListClass = find_class(_env, "java/util/List");
auto sizeMethodId = _env->GetMethodID(javaArrayListClass.get(), "size", "()I");
jint length = call_java_method<jint>(_env, _arrayList, sizeMethodId);
_nresult.reserve(length);
const JavaListIterator list_iterator(env, array_list);

const jint length = list_iterator.length();

auto getMethodId = _env->GetMethodID(javaArrayListClass.get(), "get", "(I)Ljava/lang/Object;");
for (jint i = 0; i < length; i++) {
auto javaListItem = call_java_method<jobject>(_env, _arrayList, getMethodId, i);
_nresult.push_back({{resolveName "mangled"}}_convert_from_jni(_env, javaListItem, TypeId<{{resolveName "C++ FQN"}}>{}));
result.reserve(length);

for (jint i = 0; i < length; i++)
{
result.emplace_back({{resolveName "mangled"}}_convert_from_jni(
env, list_iterator.get(array_list, i), TypeId<{{resolveName "C++ FQN"}}>{}));
}

return _nresult;
return result;
}

std::optional<std::vector<{{resolveName "C++ FQN"}}>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "BoxingConversionUtils.h"
#include "JniClassCache.h"
#include "JniCppConversionUtils.h"
#include "JniJavaContainers.h"
#include "JniReference.h"
#include "JniTypeId.h"

Expand Down Expand Up @@ -97,43 +98,6 @@ convert_optional_container_to_jni(JNIEnv* const env, const std::optional<Contain
// Templated functions to create ArrayLists from C++ vectors and vice versa
struct JavaContainer
{
JavaContainer(JNIEnv* const env, const char* class_name) noexcept;
JavaContainer(JNIEnv* const env, JniReference<jclass> container_class, JniReference<jobject> instance) noexcept;
JNIEnv* const env;
const JniReference<jclass> container_class;
JniReference<jobject> instance;
};

class JavaContainerAdder
{
protected:
JavaContainerAdder(JNIEnv* const env,
const char* class_name) noexcept;
JavaContainerAdder(JNIEnv* const env,
JniReference<jclass> container_class,
JniReference<jobject> instance) noexcept;
public:
void add(const JniReference<jobject>& item) noexcept;
JniReference<jobject> fetch_container() noexcept
{
return std::move(m_java_container.instance);
}

private:
JavaContainer m_java_container;
const jmethodID m_add_method_id;
};

class JavaArrayListAdder final : public JavaContainerAdder
{
public:
JavaArrayListAdder(JNIEnv* const env) noexcept;
};

template < typename T >
JniReference<jobject>
convert_to_jni(JNIEnv* const env, const std::vector< T >& input)
Expand All @@ -148,23 +112,6 @@ convert_to_jni(JNIEnv* const env, const std::vector< T >& input)
return list_appender.fetch_container();
}

class JavaListIterator final
{
public:
JavaListIterator(JNIEnv* const env, const JniReference<jobject>& array_list) noexcept;
JniReference<jobject> get(const JniReference<jobject>& array_list, jint index) const noexcept;
jint length() const noexcept
{
return m_length;
}

private:
JNIEnv* const m_env;
const JniReference<jclass> m_list_class;
const jmethodID m_get_method_id;
const jint m_length;
};

template < typename T >
std::vector< T >
convert_from_jni(JNIEnv* const env, const JniReference<jobject>& array_list, TypeId<std::vector< T >>)
Expand Down Expand Up @@ -201,20 +148,6 @@ convert_to_jni_optimized(JNIEnv* const env, const std::vector<std::shared_ptr<T>

// Templated functions to create HashMaps from C++ unordered_maps and vice versa

class JavaHashMapAdder final
{
public:
JavaHashMapAdder(JNIEnv* const env) noexcept;
void add(const JniReference<jobject>& key, const JniReference<jobject>& value) noexcept;
JniReference<jobject> fetch_hash_map() noexcept
{
return std::move(m_java_container.instance);
}
private:
JavaContainer m_java_container;
const jmethodID m_put_method_id;
};

template < typename K, typename V, typename Hash >
JniReference<jobject>
convert_to_jni(JNIEnv* const env, const std::unordered_map< K, V, Hash >& input)
Expand All @@ -229,45 +162,6 @@ convert_to_jni(JNIEnv* const env, const std::unordered_map< K, V, Hash >& input)
return map_adder.fetch_hash_map();
}

class JavaSetIterator final
{
public:
JavaSetIterator(JNIEnv* const env, const JniReference<jobject>& java_set) noexcept;
bool has_next() const noexcept;
JniReference<jobject> next() const noexcept;
private:
JNIEnv* const m_env;
const JniReference<jclass> m_iterator_class;
const JniReference<jobject> m_iterator;
const jmethodID m_has_next_method_id;
const jmethodID m_next_method_id;
};

class JavaMapIterator final
{
public:
JavaMapIterator(JNIEnv* const env, const JniReference<jobject>& java_map) noexcept;
bool has_next() const noexcept
{
return m_set_iterator.has_next();
}

std::pair<JniReference<jobject>, JniReference<jobject>> next() const noexcept;
private:
JNIEnv* const m_env;
const JniReference<jclass> m_map_class;
const JniReference<jclass> m_map_entry_class;
const JavaSetIterator m_set_iterator;

const jmethodID m_get_key_method_id;
const jmethodID m_get_value_method_id;
};

template < typename K, typename V, typename Hash >
::std::unordered_map< K, V, Hash >
convert_from_jni(JNIEnv* const env, const JniReference<jobject>& java_map, TypeId<::std::unordered_map< K, V, Hash >>)
Expand All @@ -285,20 +179,14 @@ convert_from_jni(JNIEnv* const env, const JniReference<jobject>& java_map, TypeI
{
const auto& key_value = map_iterator.next();
result.emplace(convert_from_jni(env, key_value.first, TypeId<K>{}),
convert_from_jni(env, key_value.second, TypeId<V>{}));
convert_from_jni(env, key_value.second, TypeId<V>{}));
}

return result;
}

// Templated functions to create HashSet from C++ unordered_set and vice versa

class JavaHashSetAdder final : public JavaContainerAdder
{
public:
JavaHashSetAdder(JNIEnv* const env) noexcept;
};

template <typename T, typename Hash, typename std::enable_if<!std::is_enum<T>::value, int>::type>
JniReference<jobject>
convert_to_jni(JNIEnv* const env, const std::unordered_set<T, Hash>& input)
Expand All @@ -313,16 +201,6 @@ convert_to_jni(JNIEnv* const env, const std::unordered_set<T, Hash>& input)
return set_adder.fetch_container();
}

class JavaEnumSetAdder final : public JavaContainerAdder
{
public:
JavaEnumSetAdder(JNIEnv* const env, const JniReference<jclass>& element_class) noexcept;
private:
JavaEnumSetAdder(JNIEnv* const env,
std::pair<JniReference<jclass>, JniReference<jobject>> class_and_object) noexcept;
};

template <typename T, typename Hash, typename std::enable_if<std::is_enum<T>::value, int>::type>
JniReference<jobject>
convert_to_jni(JNIEnv* env, const std::unordered_set<T, Hash>& input)
Expand Down
Loading

0 comments on commit f04503e

Please sign in to comment.