[gjs] arg: Add an utility header to access to GIArgument union members by type



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

    arg: Add an utility header to access to GIArgument union members by type
    
    Instead of manually picking the GIArgument union value, make possible to
    select the right one using a template type, so that we can avoid
    repeating the same code multiple times in the various template
    functions.
    
    As per this, utilize to avoid repetition in arg template functions

 gi/arg-inl.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gi/arg.cpp   |  22 ++++++------
 2 files changed, 123 insertions(+), 11 deletions(-)
---
diff --git a/gi/arg-inl.h b/gi/arg-inl.h
new file mode 100644
index 00000000..4c97b2b6
--- /dev/null
+++ b/gi/arg-inl.h
@@ -0,0 +1,112 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ *
+ * Copyright (c) 2020 Marco Trevisan <marco trevisan canonical com>
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <type_traits>
+
+#include <girepository.h>
+#include <glib-object.h>  // for GType
+#include <glib.h>         // for gboolean
+
+#include "gjs/macros.h"
+
+template <typename T>
+GJS_USE inline decltype(auto) gjs_g_argument_value(GIArgument* arg,
+                                                   T GIArgument::*member) {
+    return (arg->*member);
+}
+
+/* The tag is needed to disambiguate types such as gboolean and GType
+ * which are in fact typedef's of other generic types.
+ * Setting a tag for a type allows to perform proper specialization. */
+template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
+GJS_USE inline decltype(auto) gjs_g_argument_value(GIArgument* arg) {
+    static_assert(!std::is_arithmetic<T>(), "Missing declaration for type");
+
+    return reinterpret_cast<T>(
+        gjs_g_argument_value(arg, &GIArgument::v_pointer));
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<bool>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_boolean);
+}
+
+template <>
+GJS_USE inline decltype(auto)
+gjs_g_argument_value<gboolean, GI_TYPE_TAG_BOOLEAN>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_boolean);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<int8_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_int8);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<uint8_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_uint8);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<int16_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_int16);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<uint16_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_uint16);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<int32_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_int32);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<uint32_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_uint32);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<int64_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_int64);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<uint64_t>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_uint64);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<GType, GI_TYPE_TAG_GTYPE>(
+    GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_ssize);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<float>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_float);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<double>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_double);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<char*>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_pointer);
+}
+
+template <>
+GJS_USE inline decltype(auto) gjs_g_argument_value<void*>(GIArgument* arg) {
+    return gjs_g_argument_value(arg, &GIArgument::v_pointer);
+}
diff --git a/gi/arg.cpp b/gi/arg.cpp
index ba706021..45d0ad24 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -46,6 +46,7 @@
 #include <jsfriendapi.h>  // for JS_IsUint8Array, JS_GetObjectFunc...
 #include <mozilla/Vector.h>
 
+#include "gi/arg-inl.h"
 #include "gi/arg.h"
 #include "gi/boxed.h"
 #include "gi/foreign.h"
@@ -2444,12 +2445,12 @@ gjs_array_from_g_list (JSContext             *context,
     return true;
 }
 
-template <typename T, T GIArgument::*member>
+template <typename T>
 GJS_JSAPI_RETURN_CONVENTION static bool fill_vector_from_carray(
     JSContext* cx, JS::RootedValueVector& elems,  // NOLINT(runtime/references)
     GITypeInfo* param_info, GIArgument* arg, void* array, size_t length) {
     for (size_t i = 0; i < length; i++) {
-        arg->*member = *(static_cast<T*>(array) + i);
+        gjs_g_argument_value<T>(arg) = *(static_cast<T*>(array) + i);
 
         if (!gjs_value_from_g_argument(cx, elems[i], param_info, arg, true))
             return false;
@@ -2504,9 +2505,9 @@ gjs_array_from_carray_internal (JSContext             *context,
         return false;
     }
 
-#define ITERATE(type)                                             \
-    if (!fill_vector_from_carray<g##type, &GIArgument::v_##type>( \
-            context, elems, param_info, &arg, array, length))     \
+#define ITERATE(type)                                                       \
+    if (!fill_vector_from_carray<g##type>(context, elems, param_info, &arg, \
+                                          array, length))                   \
         return false;
 
     switch (element_type) {
@@ -2688,14 +2689,14 @@ gjs_array_from_boxed_array (JSContext             *context,
                                           param_info, length, data);
 }
 
-template <typename T, T GIArgument::*member>
+template <typename T>
 GJS_JSAPI_RETURN_CONVENTION static bool fill_vector_from_zero_terminated_carray(
     JSContext* cx, JS::RootedValueVector& elems,  // NOLINT(runtime/references)
     GITypeInfo* param_info, GIArgument* arg, void* c_array) {
     T* array = static_cast<T*>(c_array);
 
     for (size_t i = 0; array[i]; i++) {
-        arg->*member = array[i];
+        gjs_g_argument_value<T>(arg) = array[i];
 
         if (!elems.growBy(1)) {
             JS_ReportOutOfMemory(cx);
@@ -2737,10 +2738,9 @@ gjs_array_from_zero_terminated_c_array (JSContext             *context,
 
     JS::RootedValueVector elems(context);
 
-#define ITERATE(type)                                                    \
-    if (!fill_vector_from_zero_terminated_carray<g##type,                \
-                                                 &GIArgument::v_##type>( \
-            context, elems, param_info, &arg, c_array))                  \
+#define ITERATE(type)                                      \
+    if (!fill_vector_from_zero_terminated_carray<g##type>( \
+            context, elems, param_info, &arg, c_array))    \
         return false;
 
     switch (element_type) {


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