[gjs: 2/18] jsapi-util: Add back support for C++ objects and arrays to GjsAutoPointer
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 2/18] jsapi-util: Add back support for C++ objects and arrays to GjsAutoPointer
- Date: Fri, 20 Nov 2020 01:52:03 +0000 (UTC)
commit 84d1fc4669d8dffe7dc0f847e557e2c3f2f5f051
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Tue Sep 29 21:35:50 2020 +0200
jsapi-util: Add back support for C++ objects and arrays to GjsAutoPointer
As per moving away from std::unique_ptr we lost support for C++ native
objects, even this may be optional (as we can just use stl containers
for that), it's still nice to have.
So add it back and include tests.
gjs/jsapi-util.h | 47 +++++++++++++++++++++++++++++------
test/gjs-test-jsapi-utils.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 95 insertions(+), 9 deletions(-)
---
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 43d855ac..0f342283 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -39,11 +39,16 @@ struct GjsAutoTakeOwnership {};
template <typename T, typename F = void, void (*free_func)(F*) = free,
F* (*ref_func)(F*) = nullptr>
struct GjsAutoPointer {
- using Ptr = std::add_pointer_t<T>;
- using ConstPtr = std::add_pointer_t<std::add_const_t<T>>;
+ using Tp =
+ std::conditional_t<std::is_array_v<T>, std::remove_extent_t<T>, T>;
+ using Ptr = std::add_pointer_t<Tp>;
+ using ConstPtr = std::add_pointer_t<std::add_const_t<Tp>>;
constexpr GjsAutoPointer(Ptr ptr = nullptr) // NOLINT(runtime/explicit)
: m_ptr(ptr) {}
+ template <typename U = T,
+ typename std::enable_if_t<std::is_array_v<U>, int> = 0>
+ explicit constexpr GjsAutoPointer(Tp ptr[]) : m_ptr(ptr) {}
constexpr GjsAutoPointer(Ptr ptr, const GjsAutoTakeOwnership&)
: GjsAutoPointer(ptr) {
// FIXME: should use if constexpr (...), but that doesn't work with
@@ -68,9 +73,18 @@ struct GjsAutoPointer {
return *this;
}
- constexpr T operator*() const { return *m_ptr; }
- constexpr Ptr operator->() { return m_ptr; }
- constexpr ConstPtr operator->() const { return m_ptr; }
+ template <typename U = T>
+ constexpr std::enable_if_t<!std::is_array_v<U>, Ptr> operator->() {
+ return m_ptr;
+ }
+
+ template <typename U = T>
+ constexpr std::enable_if_t<!std::is_array_v<U>, ConstPtr> operator->()
+ const {
+ return m_ptr;
+ }
+
+ constexpr Tp operator*() const { return *m_ptr; }
constexpr operator Ptr() { return m_ptr; }
constexpr operator Ptr() const { return m_ptr; }
constexpr operator ConstPtr() const { return m_ptr; }
@@ -90,8 +104,12 @@ struct GjsAutoPointer {
auto ffunc = free_func;
Ptr old_ptr = m_ptr;
m_ptr = ptr;
- if (old_ptr && ffunc)
- ffunc(old_ptr);
+ if (old_ptr && ffunc) {
+ if constexpr (std::is_array_v<T>)
+ ffunc(reinterpret_cast<T*>(old_ptr));
+ else
+ ffunc(old_ptr);
+ }
}
constexpr void swap(GjsAutoPointer& other) {
@@ -102,7 +120,9 @@ struct GjsAutoPointer {
reset();
}
- [[nodiscard]] constexpr Ptr copy() const {
+ template <typename U = T>
+ [[nodiscard]] constexpr std::enable_if_t<!std::is_array_v<U>, Ptr> copy()
+ const {
// FIXME: Should use std::enable_if_t<ref_func != nullptr, Ptr>
if (!m_ptr)
return nullptr;
@@ -136,6 +156,17 @@ using GjsAutoStrv = GjsAutoPointer<char*, char*, g_strfreev>;
template <typename T>
using GjsAutoUnref = GjsAutoPointer<T, void, g_object_unref, g_object_ref>;
+template <typename V, typename T>
+constexpr void GjsAutoPointerDeleter(T v) {
+ if constexpr (std::is_array_v<V>)
+ delete[] v;
+ else
+ delete v;
+}
+
+template <typename T>
+using GjsAutoCppPointer = GjsAutoPointer<T, T, GjsAutoPointerDeleter<T>>;
+
template <typename T = GTypeClass>
struct GjsAutoTypeClass : GjsAutoPointer<T, void, &g_type_class_unref> {
GjsAutoTypeClass(gpointer ptr = nullptr) // NOLINT(runtime/explicit)
diff --git a/test/gjs-test-jsapi-utils.cpp b/test/gjs-test-jsapi-utils.cpp
index 8d8f51f1..3ba49a15 100644
--- a/test/gjs-test-jsapi-utils.cpp
+++ b/test/gjs-test-jsapi-utils.cpp
@@ -92,6 +92,58 @@ static void test_gjs_autopointer_dtor() {
g_object_unref(ptr);
}
+static void test_gjs_autopointer_dtor_cpp() {
+ bool deleted = false;
+ auto dtor_callback = [&deleted] { deleted = true; };
+
+ struct TestStruct {
+ explicit TestStruct(decltype(dtor_callback) cb) : _delete_cb(cb) {}
+ ~TestStruct() { _delete_cb(); }
+
+ decltype(dtor_callback) _delete_cb;
+ };
+
+ g_assert_false(deleted);
+
+ {
+ auto* ptr = new TestStruct(dtor_callback);
+ GjsAutoCppPointer<TestStruct> autoptr(ptr);
+ g_assert(ptr == autoptr);
+ }
+
+ g_assert_true(deleted);
+}
+
+static void test_gjs_autopointer_dtor_cpp_array() {
+ unsigned deleted = 0;
+ auto dtor_callback = [&deleted] { deleted++; };
+
+ struct TestStruct {
+ TestStruct(decltype(dtor_callback) cb) // NOLINT(runtime/explicit)
+ : _delete_cb(cb) {}
+ ~TestStruct() { _delete_cb(); }
+
+ int val = 5;
+ decltype(dtor_callback) _delete_cb;
+ };
+
+ g_assert_cmpint(deleted, ==, 0);
+
+ {
+ // using GjsAutoCppPointer1 = GjsAutoPointer<TestStruct[], TestStruct[],
+ // GjsAutoPointerDeleter<TestStruct[]>>;
+
+ TestStruct* ptrs =
+ new TestStruct[3]{dtor_callback, dtor_callback, dtor_callback};
+ GjsAutoCppPointer<TestStruct[]> autoptr(ptrs);
+ g_assert_cmpint(autoptr[0].val, ==, 5);
+ g_assert_cmpint(autoptr[1].val, ==, 5);
+ g_assert_cmpint(autoptr[2].val, ==, 5);
+ }
+
+ g_assert_cmpuint(deleted, ==, 3);
+}
+
static void test_gjs_autopointer_dtor_take_ownership() {
auto* ptr = gjs_test_object_new();
g_assert_nonnull(ptr);
@@ -406,7 +458,10 @@ void gjs_test_add_tests_for_jsapi_utils(void) {
g_test_add_func(
"/gjs/jsapi-utils/gjs-autopointer/destructor/take_ownership",
test_gjs_autopointer_dtor_take_ownership);
-
+ g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/destructor/c++",
+ test_gjs_autopointer_dtor_cpp);
+ g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/destructor/c++-array",
+ test_gjs_autopointer_dtor_cpp_array);
g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/assign",
test_gjs_autopointer_assign_operator);
g_test_add_func(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]