[gjs] arg: Use c++ templates instead of a macro to generate hashtable keys
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] arg: Use c++ templates instead of a macro to generate hashtable keys
- Date: Thu, 21 May 2020 05:02:04 +0000 (UTC)
commit 0df7ca27fdf56cadcdc2def98fb08035c020ae52
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Fri May 8 16:03:33 2020 +0200
arg: Use c++ templates instead of a macro to generate hashtable keys
This is more maintainable and we can have static checks.
gi/arg.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 86 insertions(+), 28 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 474c3b91..e30b2fa4 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -28,6 +28,7 @@
#include <cmath> // for std::abs
#include <limits> // for numeric_limits
#include <string>
+#include <type_traits>
#include <girepository.h>
#include <glib-object.h>
@@ -471,6 +472,67 @@ create_hash_table_for_key_type(GITypeInfo *key_param_info)
return g_hash_table_new(NULL, NULL);
}
+template <typename T>
+GJS_JSAPI_RETURN_CONVENTION static inline std::enable_if_t<
+ std::is_integral<T>::value && std::is_signed<T>::value, bool>
+js_value_convert(JSContext* cx, const JS::HandleValue& value, T* out) {
+ return JS::ToInt32(cx, value, out);
+}
+
+template <typename T>
+GJS_JSAPI_RETURN_CONVENTION static inline std::enable_if_t<
+ std::is_integral<T>::value && std::is_unsigned<T>::value, bool>
+js_value_convert(JSContext* cx, const JS::HandleValue& value, T* out) {
+ return JS::ToUint32(cx, value, out);
+}
+
+template <typename IntType, typename Container>
+GJS_JSAPI_RETURN_CONVENTION static bool hashtable_int_key(
+ JSContext* cx, const JS::HandleValue& value, bool* out_of_range,
+ void** pointer_out) {
+ Container i;
+
+ static_assert(std::is_integral<IntType>::value, "Need an integer");
+ static_assert(std::numeric_limits<Container>::max() >=
+ std::numeric_limits<IntType>::max());
+ static_assert(std::numeric_limits<Container>::min() <=
+ std::numeric_limits<IntType>::min());
+
+ if (!js_value_convert<Container>(cx, value, &i))
+ return false;
+
+ if (out_of_range &&
+ (i > static_cast<Container>(std::numeric_limits<IntType>::max()) ||
+ i < static_cast<Container>(std::numeric_limits<IntType>::min())))
+ *out_of_range = true;
+
+ /* Use if constexpr with c++17 */
+ if (std::is_signed<IntType>())
+ *pointer_out = GINT_TO_POINTER(i);
+ else
+ *pointer_out = GUINT_TO_POINTER(i);
+
+ return true;
+}
+
+template <typename IntType>
+GJS_JSAPI_RETURN_CONVENTION static inline std::enable_if_t<
+ std::is_signed<IntType>::value, bool>
+hashtable_int_key(JSContext* cx, const JS::HandleValue& value,
+ bool* out_of_range, void** pointer_out) {
+ return hashtable_int_key<IntType, int32_t>(cx, value, out_of_range,
+ pointer_out);
+}
+
+template <typename IntType>
+GJS_JSAPI_RETURN_CONVENTION static inline std::enable_if_t<
+ std::is_unsigned<IntType>::value, bool>
+hashtable_int_key(JSContext* cx, const JS::HandleValue& value,
+ bool* out_of_range, void** pointer_out) {
+ return hashtable_int_key<IntType, uint32_t>(cx, value, out_of_range,
+ pointer_out);
+}
+
/* Converts a JS::Value to a GHashTable key, stuffing it into @pointer_out if
* possible, otherwise giving the location of an allocated key in @pointer_out.
*/
@@ -508,39 +570,35 @@ value_to_ghashtable_key(JSContext *cx,
}
break;
-#define HANDLE_SIGNED_INT(bits) \
- case GI_TYPE_TAG_INT##bits: { \
- int32_t i; \
- if (!JS::ToInt32(cx, value, &i)) \
- return false; \
- if (i > G_MAXINT##bits || i < G_MININT##bits) \
- out_of_range = true; \
- *pointer_out = GINT_TO_POINTER(i); \
- break; \
- }
+ case GI_TYPE_TAG_INT8:
+ if (!hashtable_int_key<int8_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
- HANDLE_SIGNED_INT(8);
- HANDLE_SIGNED_INT(16);
- HANDLE_SIGNED_INT(32);
+ case GI_TYPE_TAG_INT16:
+ if (!hashtable_int_key<int16_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
-#undef HANDLE_SIGNED_INT
+ case GI_TYPE_TAG_INT32:
+ if (!hashtable_int_key<int32_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
-#define HANDLE_UNSIGNED_INT(bits) \
- case GI_TYPE_TAG_UINT##bits: { \
- uint32_t i; \
- if (!JS::ToUint32(cx, value, &i)) \
- return false; \
- if (i > G_MAXUINT##bits) \
- out_of_range = true; \
- *pointer_out = GUINT_TO_POINTER(i); \
- break; \
- }
+ case GI_TYPE_TAG_UINT8:
+ if (!hashtable_int_key<uint8_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
- HANDLE_UNSIGNED_INT(8);
- HANDLE_UNSIGNED_INT(16);
- HANDLE_UNSIGNED_INT(32);
+ case GI_TYPE_TAG_UINT16:
+ if (!hashtable_int_key<uint16_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
-#undef HANDLE_UNSIGNED_INT
+ case GI_TYPE_TAG_UINT32:
+ if (!hashtable_int_key<uint32_t>(cx, value, &out_of_range, pointer_out))
+ return false;
+ break;
case GI_TYPE_TAG_FILENAME: {
GjsAutoChar cstr;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]