summaryrefslogtreecommitdiff
path: root/platform/android/src/gson
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/src/gson')
-rw-r--r--platform/android/src/gson/json_array.cpp40
-rw-r--r--platform/android/src/gson/json_array.hpp25
-rw-r--r--platform/android/src/gson/json_element.cpp62
-rw-r--r--platform/android/src/gson/json_element.hpp33
-rw-r--r--platform/android/src/gson/json_object.cpp64
-rw-r--r--platform/android/src/gson/json_object.hpp11
-rw-r--r--platform/android/src/gson/json_primitive.cpp66
-rw-r--r--platform/android/src/gson/json_primitive.hpp39
8 files changed, 339 insertions, 1 deletions
diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp
new file mode 100644
index 0000000000..d91e323ac9
--- /dev/null
+++ b/platform/android/src/gson/json_array.cpp
@@ -0,0 +1,40 @@
+#include "json_array.hpp"
+
+#include "json_element.hpp"
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv &env, jni::Object<JsonArray> jsonArray) {
+ std::vector<mapbox::geometry::value> values;
+
+ if (jsonArray) {
+ static auto getMethod = JsonArray::javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get");
+ static auto sizeMethod = JsonArray::javaClass.GetMethod<jni::jint ()>(env, "size");
+
+ int size = jsonArray.Call(env, sizeMethod);
+ values.reserve(uint(size));
+
+ for (int i = 0; i < size; i++) {
+ auto entry = jsonArray.Call(env, getMethod, i);
+ if (entry) {
+ values.push_back(JsonElement::convert(env, entry));
+ }
+ jni::DeleteLocalRef(env, entry);
+ }
+ }
+
+ return values;
+}
+
+void JsonArray::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<JsonArray>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<JsonArray> JsonArray::javaClass;
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp
new file mode 100644
index 0000000000..8571ad5dba
--- /dev/null
+++ b/platform/android/src/gson/json_array.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <mapbox/geometry.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+class JsonArray : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "com/google/gson/JsonArray"; };
+
+ static std::vector<mapbox::geometry::value> convert(JNIEnv&, jni::Object<JsonArray>);
+
+ static jni::Class<JsonArray> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp
new file mode 100644
index 0000000000..060b1e0fe2
--- /dev/null
+++ b/platform/android/src/gson/json_element.cpp
@@ -0,0 +1,62 @@
+#include "json_element.hpp"
+
+#include "json_array.hpp"
+#include "json_object.hpp"
+#include "json_primitive.hpp"
+
+#include <mapbox/geometry/feature.hpp>
+#include <mapbox/variant.hpp>
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object<JsonElement> jsonElement) {
+ mapbox::geometry::value value;
+
+ if (jsonElement) {
+ if (isJsonPrimitive(env, jsonElement)) {
+ auto primitive = JsonPrimitive::convert(env, jni::Cast(env, jsonElement, JsonPrimitive::javaClass));
+ value = mapbox::util::apply_visitor([](auto t) { return mapbox::geometry::value { t }; }, primitive);
+ } else if (isJsonObject(env, jsonElement)) {
+ mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, jsonElement, JsonObject::javaClass));
+ value = mapbox::util::recursive_wrapper<std::unordered_map<std::string, mapbox::geometry::value>> { map } ;
+ } else if (isJsonArray(env, jsonElement)) {
+ value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass));
+ } else {
+ value = mapbox::geometry::null_value;
+ }
+ }
+ return value;
+}
+
+bool JsonElement::isJsonObject(JNIEnv& env, jni::Object<JsonElement> jsonElement) {
+ static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonObject");
+ return jsonElement.Call(env, method);
+}
+
+bool JsonElement::isJsonArray(JNIEnv& env, jni::Object<JsonElement> jsonElement) {
+ static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonArray");
+ return jsonElement.Call(env, method);
+}
+
+bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object<JsonElement> jsonElement) {
+ static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive");
+ return jsonElement.Call(env, method);
+}
+
+bool JsonElement::isJsonNull(JNIEnv& env, jni::Object<JsonElement> jsonElement) {
+ static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonNull");
+ return jsonElement.Call(env, method);
+}
+
+void JsonElement::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<JsonElement>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<JsonElement> JsonElement::javaClass;
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp
new file mode 100644
index 0000000000..7619350617
--- /dev/null
+++ b/platform/android/src/gson/json_element.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mapbox/geometry.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+class JsonElement : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "com/google/gson/JsonElement"; };
+
+ static mapbox::geometry::value convert(JNIEnv&, jni::Object<JsonElement>);
+
+ static bool isJsonObject(JNIEnv&, jni::Object<JsonElement>);
+
+ static bool isJsonArray(JNIEnv&, jni::Object<JsonElement>);
+
+ static bool isJsonPrimitive(JNIEnv&, jni::Object<JsonElement>);
+
+ static bool isJsonNull(JNIEnv&, jni::Object<JsonElement>);
+
+ static jni::Class<JsonElement> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp
new file mode 100644
index 0000000000..a704dae9dd
--- /dev/null
+++ b/platform/android/src/gson/json_object.cpp
@@ -0,0 +1,64 @@
+#include "json_object.hpp"
+
+#include "json_element.hpp"
+
+#include "../java/util.hpp"
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+
+template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
+static void iterateEntrySet(jni::JNIEnv& env, jni::Object<JsonObject> jsonObject, F callback) {
+ // Get Set<Map.Entry<String, JsonElement>>
+ static auto method = JsonObject::javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet");
+ auto entrySet = jsonObject.Call(env, method);
+ jni::Array<jni::Object<java::util::Map::Entry>> entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, entrySet);
+
+ size_t size = entryArray.Length(env);
+ for (size_t i = 0; i < size; i++) {
+ auto entry = entryArray.Get(env, i);
+ if (entry) {
+ // Convert
+ auto jKey = java::util::Map::Entry::getKey<jni::ObjectTag>(env, entry);
+ auto jKeyString = jni::String(reinterpret_cast<jni::jstring*>(jKey.Get()));
+ auto jValue = java::util::Map::Entry::getValue<gson::JsonElement>(env, entry);
+
+ // Callback
+ callback(jKeyString, jValue);
+
+ // Cleanup
+ // Skip jKey as it points to the same as jKeyString
+ jni::DeleteLocalRef(env, jKeyString);
+ jni::DeleteLocalRef(env, jValue);
+ }
+ jni::DeleteLocalRef(env, entry);
+ }
+
+ jni::DeleteLocalRef(env, entrySet);
+ jni::DeleteLocalRef(env, entryArray);
+}
+
+mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object<JsonObject> jsonObject) {
+ mapbox::geometry::property_map map;
+
+ if (jsonObject) {
+ iterateEntrySet(env, jsonObject, [&map, &env](jni::String jId, jni::Object<gson::JsonElement> jsonElement) {
+ map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement);
+ });
+ }
+
+ return map;
+}
+
+void JsonObject::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<JsonObject>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<JsonObject> JsonObject::javaClass;
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp
index a7de0b1978..aba8e40415 100644
--- a/platform/android/src/gson/json_object.hpp
+++ b/platform/android/src/gson/json_object.hpp
@@ -1,16 +1,25 @@
#pragma once
+#include <mapbox/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include <jni/jni.hpp>
+
namespace mbgl {
namespace android {
+namespace gson {
class JsonObject : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
-};
+ static mapbox::geometry::property_map convert(JNIEnv&, jni::Object<JsonObject>);
+ static jni::Class<JsonObject> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+} // namespace gson
} // namespace android
} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp
new file mode 100644
index 0000000000..58d0b45fe7
--- /dev/null
+++ b/platform/android/src/gson/json_primitive.cpp
@@ -0,0 +1,66 @@
+#include "json_primitive.hpp"
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ value value;
+ if (jsonPrimitive) {
+ if (isBoolean(env, jsonPrimitive)) {
+ value = getAsBoolean(env, jsonPrimitive);
+ } else if (isNumber(env, jsonPrimitive)) {
+ //TODO: how to differentiate types here?
+ value = getAsDouble(env, jsonPrimitive);
+ } else if (isString(env, jsonPrimitive)) {
+ value = getAsString(env, jsonPrimitive);
+ } else {
+ value = mapbox::geometry::null_value;
+ }
+ }
+ return value;
+}
+
+bool JsonPrimitive::isBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isBoolean");
+ return jsonPrimitive.Call(env, method);
+}
+
+bool JsonPrimitive::isString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isString");
+ return jsonPrimitive.Call(env, method);
+}
+
+bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isNumber");
+ return jsonPrimitive.Call(env, method);
+}
+
+bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean");
+ return jsonPrimitive.Call(env, method);
+}
+
+std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::String ()>(env, "getAsString");
+ auto jString = jsonPrimitive.Call(env, method);
+ auto string = jni::Make<std::string>(env, jString);
+ jni::DeleteLocalRef(env, jString);
+ return string;
+}
+
+double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) {
+ static auto method = JsonPrimitive::javaClass.GetMethod<jni::jdouble ()>(env, "getAsDouble");
+ return jsonPrimitive.Call(env, method);
+}
+
+void JsonPrimitive::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<JsonPrimitive>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<JsonPrimitive> JsonPrimitive::javaClass;
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp
new file mode 100644
index 0000000000..5fc8a2b485
--- /dev/null
+++ b/platform/android/src/gson/json_primitive.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mapbox/geometry.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+namespace gson {
+
+class JsonPrimitive : private mbgl::util::noncopyable {
+public:
+ using value = mapbox::util::variant<mapbox::geometry::null_value_t, bool, uint64_t, int64_t, double, std::string>;
+
+ static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
+
+ static value convert(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static bool isBoolean(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static bool isString(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static bool isNumber(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static bool getAsBoolean(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static std::string getAsString(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static double getAsDouble(JNIEnv&, jni::Object<JsonPrimitive>);
+
+ static jni::Class<JsonPrimitive> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+} // namespace gson
+} // namespace android
+} // namespace mbgl \ No newline at end of file