diff options
author | Marco Trevisan (TreviƱo) <mail@3v1n0.net> | 2020-05-18 16:41:46 +0200 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2020-10-12 20:02:52 -0700 |
commit | e531302968dee2087352d141292f5983c82ac7de (patch) | |
tree | b96f67f3b7fb3f51155201198dd5f99f3e7b53c1 | |
parent | 641e62160fb067101fb5b50dc1c5929a26143faa (diff) | |
download | gjs-e531302968dee2087352d141292f5983c82ac7de.tar.gz |
arg: Implement gjs_array_to_strv using the auto-array
Even in this case we can just implement this using a specialized
implementaiton of js_value_to_c.
However, since the array contains new strings we also need to templatize
the array allocation and free functions, so that we memzero it and we deeply
free it in case we handle a GStrv.
As per this, only set the last element to NULL on non-string arrays
-rw-r--r-- | gi/arg-types-inl.h | 5 | ||||
-rw-r--r-- | gi/arg.cpp | 51 | ||||
-rw-r--r-- | gi/js-value-inl.h | 13 |
3 files changed, 39 insertions, 30 deletions
diff --git a/gi/arg-types-inl.h b/gi/arg-types-inl.h index 8f9e0952..ceb2d0f9 100644 --- a/gi/arg-types-inl.h +++ b/gi/arg-types-inl.h @@ -97,4 +97,9 @@ constexpr inline const char* static_type_name<GValue>() { return "GValue"; } +template <> +inline const char* static_type_name<char*>() { + return "string"; +} + } // namespace Gjs @@ -685,6 +685,24 @@ _Pragma("GCC diagnostic pop") return true; } +template <typename T> +[[nodiscard]] constexpr T* array_allocate(size_t length) { + if constexpr (std::is_same_v<T, char*>) + return g_new0(char*, length); + + auto* array = g_new(T, length); + array[length - 1] = {0}; + return array; +} + +template <typename T> +constexpr void array_free_func(T* array) { + if constexpr (std::is_same_v<T, char*>) + g_strfreev(array); + else + g_free(array); +} + template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID> GJS_JSAPI_RETURN_CONVENTION static bool gjs_array_to_auto_array( JSContext* cx, JS::Value array_value, size_t length, void** arr_p) { @@ -692,8 +710,8 @@ GJS_JSAPI_RETURN_CONVENTION static bool gjs_array_to_auto_array( JS::RootedValue elem(cx); // Add one so we're always zero terminated - GjsAutoPointer<T, void, g_free> result = g_new(T, length + 1); - result[length] = {0}; + GjsAutoPointer<T, T, array_free_func<T>> result = + array_allocate<T>(length + 1); for (size_t i = 0; i < length; ++i) { elem = JS::UndefinedValue(); @@ -757,34 +775,7 @@ gjs_array_to_strv(JSContext *context, unsigned int length, void **arr_p) { - char **result; - guint32 i; - JS::RootedObject array(context, array_value.toObjectOrNull()); - JS::RootedValue elem(context); - - result = g_new0(char *, length+1); - - for (i = 0; i < length; ++i) { - elem = JS::UndefinedValue(); - if (!JS_GetElement(context, array, i, &elem)) { - g_free(result); - gjs_throw(context, - "Missing array element %u", - i); - return false; - } - - JS::UniqueChars tmp_result = gjs_string_to_utf8(context, elem); - if (!tmp_result) { - g_strfreev(result); - return false; - } - result[i] = g_strdup(tmp_result.get()); - } - - *arr_p = result; - - return true; + return gjs_array_to_auto_array<char*>(context, array_value, length, arr_p); } GJS_JSAPI_RETURN_CONVENTION diff --git a/gi/js-value-inl.h b/gi/js-value-inl.h index 77c0aab0..03c0bb19 100644 --- a/gi/js-value-inl.h +++ b/gi/js-value-inl.h @@ -13,6 +13,7 @@ #include "gi/gtype.h" #include "gi/value.h" +#include "gjs/jsapi-util.h" #include "gjs/macros.h" namespace Gjs { @@ -172,6 +173,18 @@ GJS_JSAPI_RETURN_CONVENTION inline bool js_value_to_c( return gjs_value_to_g_value(cx, value, out); } +template <> +GJS_JSAPI_RETURN_CONVENTION inline bool js_value_to_c( + JSContext* cx, const JS::HandleValue& value, char** out) { + JS::UniqueChars tmp_result = gjs_string_to_utf8(cx, value); + + if (!tmp_result) + return false; + + *out = g_strdup(tmp_result.get()); + return true; +} + template <typename WantedType, typename T> GJS_JSAPI_RETURN_CONVENTION inline bool js_value_to_c_checked( JSContext* cx, const JS::HandleValue& value, T* out, bool* out_of_range) { |