[gjs] arg: Implement gjs_array_to_strv using the auto-array



commit e531302968dee2087352d141292f5983c82ac7de
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon May 18 16:41:46 2020 +0200

    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<GValue>() {
     return "GValue";
 }
 
+template <>
+inline const char* static_type_name<char*>() {
+    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 <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) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]