From e531302968dee2087352d141292f5983c82ac7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 18 May 2020 16:41:46 +0200 Subject: 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 --- gi/arg-types-inl.h | 5 +++++ gi/arg.cpp | 51 +++++++++++++++++++++------------------------------ 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() { return "GValue"; } +template <> +inline const char* static_type_name() { + return "string"; +} + } // namespace Gjs diff --git a/gi/arg.cpp b/gi/arg.cpp index 17100dbb..5b8e5f76 100644 --- a/gi/arg.cpp +++ b/gi/arg.cpp @@ -685,6 +685,24 @@ _Pragma("GCC diagnostic pop") return true; } +template +[[nodiscard]] constexpr T* array_allocate(size_t length) { + if constexpr (std::is_same_v) + return g_new0(char*, length); + + auto* array = g_new(T, length); + array[length - 1] = {0}; + return array; +} + +template +constexpr void array_free_func(T* array) { + if constexpr (std::is_same_v) + g_strfreev(array); + else + g_free(array); +} + template 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 result = g_new(T, length + 1); - result[length] = {0}; + GjsAutoPointer> result = + array_allocate(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(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 GJS_JSAPI_RETURN_CONVENTION inline bool js_value_to_c_checked( JSContext* cx, const JS::HandleValue& value, T* out, bool* out_of_range) { -- cgit v1.2.1