Commit c2e40a21 authored by Marco Trevisan's avatar Marco Trevisan 🎺 Committed by Philip Chimento

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
parent 670136bc
/* -*- 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);
}
......@@ -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) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment