From 8eb46f671523307fee8f40c7842eced33fcceddb Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 15 Jan 2018 16:47:24 +0300 Subject: [PATCH] Improve Java binding. GitOrigin-RevId: ec10cb32f546a1249f4fe5f309eaff7488c31182 --- CMakeLists.txt | 29 +++++++- td/generate/tl_writer_java.cpp | 2 +- td/generate/tl_writer_jni_cpp.cpp | 114 ++++++----------------------- td/telegram/DeviceTokenManager.cpp | 5 +- td/tl/tl_jni_object.cpp | 63 +++++++++++++--- td/tl/tl_jni_object.h | 72 +++++++++++++++++- td/tl/tl_json.h | 4 - 7 files changed, 176 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 757d43385..80079e947 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -547,6 +547,15 @@ target_include_directories(tdcore PUBLIC $) +set(BIGOBJ) if (WIN32 OR CYGWIN) if (MSVC) - target_compile_options(tdcore PUBLIC "/bigobj") + set(BIGOBJ "/bigobj") elseif (GCC) - target_compile_options(tdcore PUBLIC "-Wa,-mbig-obj") + set(BIGOBJ "-Wa,-mbig-obj") endif() endif() +if (BIGOBJ) + target_compile_options(tdc PUBLIC ${BIGOBJ}) + target_compile_options(tdcore PUBLIC ${BIGOBJ}) + target_compile_options(tdclient PUBLIC ${BIGOBJ}) + target_compile_options(tdjson PUBLIC ${BIGOBJ}) + target_compile_options(tdjson_static PUBLIC ${BIGOBJ}) +endif() if (EMSCRIPTEN) set(TD_EMSCRIPTEN_SRC td/telegram/td_emscripten.cpp) @@ -660,6 +682,9 @@ install(FILES ${TD_JSON_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/td/telegram/tdjson_ install(FILES td/telegram/Client.h td/telegram/Log.h DESTINATION include/td/telegram) install(FILES td/tl/TlObject.h DESTINATION include/td/tl) install(FILES ${TL_TD_AUTO_INCLUDES}/td/telegram/td_api.h ${TL_TD_AUTO_INCLUDES}/td/telegram/td_api.hpp DESTINATION include/td/telegram) +if (TD_API_JAVA_PACKAGE) + install(FILES td/tl/tl_jni_object.h DESTINATION include/td/tl) +endif() include(CMakePackageConfigHelpers) write_basic_package_version_file("TdConfigVersion.cmake" diff --git a/td/generate/tl_writer_java.cpp b/td/generate/tl_writer_java.cpp index 0a681ca8b..1a2449e6e 100644 --- a/td/generate/tl_writer_java.cpp +++ b/td/generate/tl_writer_java.cpp @@ -449,7 +449,7 @@ std::string TD_TL_writer_java::gen_store_function_begin(const std::string &store " protected " + storer_name + " appendLine(" + storer_name + " s, int shift) {\n" - " s.append('\\n');\n" + " s.append(System.lineSeparator());\n" " for (int i = 0; i < shift; i++) {\n" " s.append(' ');\n" " }\n" diff --git a/td/generate/tl_writer_jni_cpp.cpp b/td/generate/tl_writer_jni_cpp.cpp index f7e1020e3..31de1bddc 100644 --- a/td/generate/tl_writer_jni_cpp.cpp +++ b/td/generate/tl_writer_jni_cpp.cpp @@ -77,113 +77,44 @@ std::string TD_TL_writer_jni_cpp::gen_vector_fetch(std::string field_name, const int parser_type) const { std::string vector_type = gen_type_name(t); - std::string type; - std::string Type; - if (vector_type == "bool") { assert(false); // TODO } + std::string fetch_object = "jni::fetch_object(env, p, " + field_name + "fieldID)"; + std::string array_type; if (vector_type == "std::int32_t") { - type = "int"; - Type = "Int"; + array_type = "jintArray"; } if (vector_type == "std::int64_t") { - type = "long"; - Type = "Long"; + array_type = "jlongArray"; } if (vector_type == "double") { - type = "double"; - Type = "Double"; + array_type = "jdoubleArray"; } - std::string res_begin; - std::string res_end; - std::string fetch_object; - if (field_name.empty()) { - res_begin = "({ std::vector<" + vector_type + "> res_tmp_; "; - field_name = "res_tmp_"; - res_end = " std::move(res_tmp_); })"; - fetch_object = "p; "; - } else { - fetch_object = "jni::fetch_object(env, p, " + field_name + "fieldID); "; - } - std::string resize_vector; - if (!type.empty()) { - resize_vector = field_name + ".resize(length_tmp_); "; - } else { - resize_vector = field_name + ".reserve(length_tmp_); "; + if (!array_type.empty()) { + return "jni::fetch_vector(env, (" + array_type + ")" + fetch_object + ");"; } - std::string res; - if (!type.empty()) { - res = - "{ " - "j" + - type + "Array arr_tmp_ = (j" + type + "Array)" + fetch_object + - "if (arr_tmp_) { " - "jsize length_tmp_ = env->GetArrayLength(arr_tmp_); " + - resize_vector + "env->Get" + Type + "ArrayRegion(arr_tmp_, 0, length_tmp_, reinterpret_cast(&" + field_name + - "[0])); " - "env->DeleteLocalRef(arr_tmp_); " - "} }"; - } else if (vector_type == string_type) { - res = - "{ " - "jobjectArray arr_tmp_ = (jobjectArray)" + - fetch_object + - "if (arr_tmp_) { " - "jsize length_tmp_ = env->GetArrayLength(arr_tmp_); " + - resize_vector + - "for (jsize i_tmp_ = 0; i_tmp_ < length_tmp_; i_tmp_++) { " - "jstring str_tmp_ = (jstring)env->GetObjectArrayElement(arr_tmp_, i_tmp_); " + - field_name + - ".push_back(jni::from_jstring(env, str_tmp_)); " - "env->DeleteLocalRef(str_tmp_); " - "} " - "env->DeleteLocalRef(arr_tmp_); " - "} }"; + std::string template_type; + if (vector_type == string_type) { + template_type = "std::string"; } else if (vector_type.compare(0, 11, "std::vector") == 0) { const tl::tl_tree_type *child = static_cast(t->children[0]); - - res = - "{ " - "jobjectArray arr_tmp_ = (jobjectArray)" + - fetch_object + - "if (arr_tmp_) { " - "jsize length_tmp_ = env->GetArrayLength(arr_tmp_); " + - resize_vector + - "for (jsize i_tmp_ = 0; i_tmp_ < length_tmp_; i_tmp_++) { " - "jobject p = env->GetObjectArrayElement(arr_tmp_, i_tmp_); " + - field_name + ".push_back(" + gen_vector_fetch("", child, vars, parser_type) + - "); " - "if (p) { env->DeleteLocalRef(p); " - "} } " - "env->DeleteLocalRef(arr_tmp_); " - "} }"; + template_type = gen_type_name(child); + if (template_type.compare(0, 10, "object_ptr") == 0) { + template_type = gen_main_class_name(child->type); + } + template_type = "std::vector<" + template_type + ">"; } else if (vector_type == bytes_type) { std::fprintf(stderr, "Vector of Bytes is not supported\n"); assert(false); } else { assert(vector_type.compare(0, 10, "object_ptr") == 0); - res = - "{ " - "jobjectArray arr_tmp_ = (jobjectArray)" + - fetch_object + - "if (arr_tmp_) { " - "jsize length_tmp_ = env->GetArrayLength(arr_tmp_); " + - resize_vector + - "for (jsize i_tmp_ = 0; i_tmp_ < length_tmp_; i_tmp_++) { " - "jobject o_ = env->GetObjectArrayElement(arr_tmp_, i_tmp_); " + - field_name + ".push_back(" + gen_main_class_name(t->type) + - "::fetch(env, o_)); " - "if (o_) { env->DeleteLocalRef(o_); " - "} } " - "env->DeleteLocalRef(arr_tmp_); " - "} }"; + template_type = gen_main_class_name(t->type); } - return res_begin + res + res_end; + return "jni::FetchVector<" + template_type + ">::fetch(env, (jobjectArray)" + fetch_object + ");"; } std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type, @@ -229,7 +160,7 @@ std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name, } if (name == "Bool") { - res = "env->GetBooleanField(p, " + field_name + "fieldID)"; + res = "(env->GetBooleanField(p, " + field_name + "fieldID) != 0)"; } else if (name == "Int32") { res = "env->GetIntField(p, " + field_name + "fieldID)"; } else if (name == "Int53" || name == "Int64") { @@ -242,13 +173,13 @@ std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name, res = "jni::from_bytes(env, (jbyteArray)jni::fetch_object(env, p, " + field_name + "fieldID))"; } else if (name == "Vector") { const tl::tl_tree_type *child = static_cast(tree_type->children[0]); - return gen_vector_fetch(field_name, child, vars, parser_type); + res = gen_vector_fetch(field_name, child, vars, parser_type); } else { if (field_name == "") { return gen_main_class_name(tree_type->type) + "::fetch(env, p)"; } - res = "({jobject jobject_tmp_ = jni::fetch_object(env, p, " + field_name + "fieldID); " + - gen_main_class_name(tree_type->type) + "::fetch(env, jobject_tmp_);})"; + res = "jni::fetch_tl_object<" + gen_main_class_name(tree_type->type) + ">(env, jni::fetch_object(env, p, " + + field_name + "fieldID));"; } return res_begin + res; } @@ -523,7 +454,8 @@ std::string TD_TL_writer_jni_cpp::gen_store_function_begin(const std::string &st "void " + class_name + "::store(" + storer_name + " &s" + std::string(storer_type <= 0 ? "" : ", const char *field_name") + ") const {\n" + - (storer_type <= 0 ? " if (!(s = env->AllocObject(Class))) { return; }\n" + (storer_type <= 0 ? " s = env->AllocObject(Class);\n" + " if (!s) { return; }\n" : " if (!LOG_IS_STRIPPED(ERROR)) {\n" " s.store_class_begin(field_name, \"" + get_pretty_class_name(class_name) + "\");\n"); diff --git a/td/telegram/DeviceTokenManager.cpp b/td/telegram/DeviceTokenManager.cpp index 608483ae3..e4a8df0e8 100644 --- a/td/telegram/DeviceTokenManager.cpp +++ b/td/telegram/DeviceTokenManager.cpp @@ -17,6 +17,7 @@ #include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/Status.h" +#include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" #include @@ -245,8 +246,8 @@ void DeviceTokenManager::loop() { net_query = G()->net_query_creator().create( create_storer(telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids)))); } else { - net_query = G()->net_query_creator().create(create_storer( - telegram_api::account_registerDevice(token_type, info.token, info.is_app_sandbox, std::move(other_user_ids)))); + net_query = G()->net_query_creator().create(create_storer(telegram_api::account_registerDevice( + token_type, info.token, info.is_app_sandbox, std::move(other_user_ids)))); } info.net_query_id = net_query->id(); G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type)); diff --git a/td/tl/tl_jni_object.cpp b/td/tl/tl_jni_object.cpp index 88a3b9495..a4846c625 100644 --- a/td/tl/tl_jni_object.cpp +++ b/td/tl/tl_jni_object.cpp @@ -32,7 +32,7 @@ jmethodID DoubleGetValueMethodID; jclass get_jclass(JNIEnv *env, const char *class_name) { jclass clazz = env->FindClass(class_name); if (!clazz) { - LOG(INFO, "Can't find class [%s]", class_name); + LOG(INFO) << "Can't find class [" << class_name << "]"; env->ExceptionClear(); return clazz; } @@ -41,7 +41,7 @@ jclass get_jclass(JNIEnv *env, const char *class_name) { env->DeleteLocalRef(clazz); if (!clazz_global) { - LOG(ERROR, "Can't create global reference to [%s]", class_name); + LOG(ERROR) << "Can't create global reference to [" << class_name << "]"; env->FatalError("Can't create global reference"); } @@ -55,7 +55,7 @@ jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name, const char return res; } - LOG(ERROR, "Can't find method %s %s", name, sig); + LOG(ERROR) << "Can't find method [" << name << "] with signature [" << sig << "]"; env->FatalError("Can't find method"); } return nullptr; @@ -68,7 +68,7 @@ jfieldID get_field_id(JNIEnv *env, jclass clazz, const char *name, const char *s return res; } - LOG(ERROR, "Can't find field name=(%s) sig=(%s)", name, sig); + LOG(ERROR) << "Can't find field [" << name << "] with signature [" << sig << "]"; env->FatalError("Can't find field"); return 0; } @@ -229,8 +229,10 @@ std::string from_bytes(JNIEnv *env, jbyteArray arr) { std::string b; if (arr != nullptr) { jsize length = env->GetArrayLength(arr); - b.resize(narrow_cast(length)); - env->GetByteArrayRegion(arr, 0, length, reinterpret_cast(&b[0])); + if (length != 0) { + b.resize(narrow_cast(length)); + env->GetByteArrayRegion(arr, 0, length, reinterpret_cast(&b[0])); + } env->DeleteLocalRef(arr); } return b; @@ -240,7 +242,7 @@ jbyteArray to_bytes(JNIEnv *env, const std::string &b) { static_assert(sizeof(char) == sizeof(jbyte), "Mismatched jbyte size"); jsize length = narrow_cast(b.size()); jbyteArray arr = env->NewByteArray(length); - if (arr != nullptr) { + if (arr != nullptr && length != 0) { env->SetByteArrayRegion(arr, 0, length, reinterpret_cast(b.data())); } return arr; @@ -250,7 +252,7 @@ jintArray store_vector(JNIEnv *env, const std::vector &v) { static_assert(sizeof(std::int32_t) == sizeof(jint), "Mismatched jint size"); jsize length = narrow_cast(v.size()); jintArray arr = env->NewIntArray(length); - if (arr) { + if (arr != nullptr && length != 0) { env->SetIntArrayRegion(arr, 0, length, reinterpret_cast(&v[0])); } return arr; @@ -260,7 +262,7 @@ jlongArray store_vector(JNIEnv *env, const std::vector &v) { static_assert(sizeof(std::int64_t) == sizeof(jlong), "Mismatched jlong size"); jsize length = narrow_cast(v.size()); jlongArray arr = env->NewLongArray(length); - if (arr) { + if (arr != nullptr && length != 0) { env->SetLongArrayRegion(arr, 0, length, reinterpret_cast(&v[0])); } return arr; @@ -270,7 +272,7 @@ jdoubleArray store_vector(JNIEnv *env, const std::vector &v) { static_assert(sizeof(double) == sizeof(jdouble), "Mismatched jdouble size"); jsize length = narrow_cast(v.size()); jdoubleArray arr = env->NewDoubleArray(length); - if (arr) { + if (arr != nullptr && length != 0) { env->SetDoubleArrayRegion(arr, 0, length, reinterpret_cast(&v[0])); } return arr; @@ -279,7 +281,7 @@ jdoubleArray store_vector(JNIEnv *env, const std::vector &v) { jobjectArray store_vector(JNIEnv *env, const std::vector &v) { jsize length = narrow_cast(v.size()); jobjectArray arr = env->NewObjectArray(length, StringClass, 0); - if (arr) { + if (arr != nullptr) { for (jsize i = 0; i < length; i++) { jstring str = to_jstring(env, v[i]); if (str) { @@ -291,5 +293,44 @@ jobjectArray store_vector(JNIEnv *env, const std::vector &v) { return arr; } +std::vector fetch_vector(JNIEnv *env, jintArray arr) { + std::vector result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + if (length != 0) { + result.resize(length); + env->GetIntArrayRegion(arr, 0, length, reinterpret_cast(&result[0])); + } + env->DeleteLocalRef(arr); + } + return result; +} + +std::vector fetch_vector(JNIEnv *env, jlongArray arr) { + std::vector result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + if (length != 0) { + result.resize(length); + env->GetLongArrayRegion(arr, 0, length, reinterpret_cast(&result[0])); + } + env->DeleteLocalRef(arr); + } + return result; +} + +std::vector fetch_vector(JNIEnv *env, jdoubleArray arr) { + std::vector result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + if (length != 0) { + result.resize(length); + env->GetDoubleArrayRegion(arr, 0, length, reinterpret_cast(&result[0])); + } + env->DeleteLocalRef(arr); + } + return result; +} + } // namespace jni } // namespace td diff --git a/td/tl/tl_jni_object.h b/td/tl/tl_jni_object.h index 17549740a..da83e8405 100644 --- a/td/tl/tl_jni_object.h +++ b/td/tl/tl_jni_object.h @@ -74,7 +74,7 @@ template jobjectArray store_vector(JNIEnv *env, const std::vector &v) { jint length = static_cast(v.size()); jobjectArray arr = env->NewObjectArray(length, T::element_type::Class, jobject()); - if (arr) { + if (arr != nullptr) { for (jint i = 0; i < length; i++) { if (v[i] != nullptr) { jobject stored_object; @@ -114,7 +114,7 @@ template jobjectArray store_vector(JNIEnv *env, const std::vector> &v) { jint length = static_cast(v.size()); jobjectArray arr = env->NewObjectArray(length, get_array_class::get(), 0); - if (arr) { + if (arr != nullptr) { for (jint i = 0; i < length; i++) { auto stored_array = store_vector(env, v[i]); if (stored_array) { @@ -126,5 +126,73 @@ jobjectArray store_vector(JNIEnv *env, const std::vector> &v) { return arr; } +template +auto fetch_tl_object(JNIEnv *env, jobject obj) { + decltype(T::fetch(env, obj)) result; + if (obj != nullptr) { + result = T::fetch(env, obj); + env->DeleteLocalRef(obj); + } + return result; +} + +std::vector fetch_vector(JNIEnv *env, jintArray arr); + +std::vector fetch_vector(JNIEnv *env, jlongArray arr); + +std::vector fetch_vector(JNIEnv *env, jdoubleArray arr); + +template +struct FetchVector { + static auto fetch(JNIEnv *env, jobjectArray arr) { + std::vector(env, jobject()))> result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + result.reserve(length); + for (jsize i = 0; i < length; i++) { + result.push_back(fetch_tl_object(env, env->GetObjectArrayElement(arr, i))); + } + env->DeleteLocalRef(arr); + } + return result; + } +}; + +template <> +struct FetchVector { + static std::vector fetch(JNIEnv *env, jobjectArray arr) { + std::vector result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + result.reserve(length); + for (jsize i = 0; i < length; i++) { + jstring str = (jstring)env->GetObjectArrayElement(arr, i); + result.push_back(jni::from_jstring(env, str)); + if (str) { + env->DeleteLocalRef(str); + } + } + env->DeleteLocalRef(arr); + } + return result; + } +}; + +template +struct FetchVector> { + static auto fetch(JNIEnv *env, jobjectArray arr) { + std::vector::fetch(env, jobjectArray()))> result; + if (arr != nullptr) { + jsize length = env->GetArrayLength(arr); + result.reserve(length); + for (jsize i = 0; i < length; i++) { + result.push_back(FetchVector::fetch(env, (jobjectArray)env->GetObjectArrayElement(arr, i))); + } + env->DeleteLocalRef(arr); + } + return result; + } +}; + } // namespace jni } // namespace td diff --git a/td/tl/tl_json.h b/td/tl/tl_json.h index 22b7b347e..e407bfba1 100644 --- a/td/tl/tl_json.h +++ b/td/tl/tl_json.h @@ -165,10 +165,6 @@ class DowncastHelper : public T { int32 get_id() const override { return constructor_; } - void store(TlStorerUnsafe &s) const override { - } - void store(TlStorerCalcLength &s) const override { - } void store(TlStorerToString &s, const char *field_name) const override { }