forked from xournalpp/xournalpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create RAII wrappers for C libraries
* CLibrarySPtr: A smart pointer class for ref-counting C objects (cairo_t, cairo_surface_t, GObject, poppler stuff...) * CairoSaveGuard: RAII wrapper for cairo_save/cairo_restore.
- Loading branch information
Showing
5 changed files
with
499 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Xournal++ | ||
* | ||
* RAII smart pointers for C library classes | ||
* | ||
* @author Xournal++ Team | ||
* https://github.com/xournalpp/xournalpp | ||
* | ||
* @license GNU GPLv2 or later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <utility> | ||
|
||
namespace xoj::util { | ||
/** | ||
* @brief Simple template class for RAII smart pointer (aimed at Cairo/GTK/Poppler ref-counting classes) | ||
* @param T The wrapper will store a pointer of type T | ||
* @param H Handler class containing at least | ||
* static T* ref(T*): | ||
* static void unref(T*); | ||
* static T* adopt(T*); // What to do to a pointer when we adopt an instance (typically the identity) | ||
* and optionally (for floating refs) | ||
* static T* ref_sink(T*); | ||
*/ | ||
template <typename T, class H> | ||
class CLibrariesSPtr { | ||
public: | ||
CLibrariesSPtr() = default; | ||
|
||
using handler_type = H; | ||
|
||
private: | ||
static auto safeRef(T* ptr) -> T* { return ptr ? H::ref(ptr) : ptr; } | ||
static auto safeUnref(T* ptr) -> void { | ||
if (ptr) { | ||
H::unref(ptr); | ||
} | ||
} | ||
static auto safeSinkRef(T* ptr) -> T* { return ptr ? H::sink_ref(ptr) : ptr; } | ||
static auto safeReset(T*& ptr, T* val) -> void { safeUnref(std::exchange(ptr, val)); } | ||
|
||
public: | ||
~CLibrariesSPtr() { safeUnref(p); } | ||
|
||
CLibrariesSPtr(const CLibrariesSPtr& other) { p = safeRef(other.p); } | ||
CLibrariesSPtr(CLibrariesSPtr&& other) { p = std::exchange(other.p, nullptr); } | ||
|
||
CLibrariesSPtr& operator=(const CLibrariesSPtr& other) { | ||
if (this != &other) { | ||
safeReset(p, safeRef(other.p)); | ||
} | ||
return *this; | ||
} | ||
CLibrariesSPtr& operator=(CLibrariesSPtr&& other) { | ||
if (this != &other) { | ||
safeReset(p, std::exchange(other.p, nullptr)); | ||
} | ||
return *this; | ||
} | ||
|
||
constexpr static struct Adopt { | ||
} adopt = Adopt(); | ||
constexpr static struct Ref { | ||
} ref = Ref(); | ||
constexpr static struct RefSink { | ||
} refsink = RefSink(); | ||
|
||
CLibrariesSPtr(T* p, Adopt = adopt): p(H::adopt(p)) {} | ||
CLibrariesSPtr(T* p, Ref): p(safeRef(p)) {} | ||
CLibrariesSPtr(T* p, RefSink): p(safeSinkRef(p)) {} | ||
|
||
void reset(T* other = nullptr, Adopt = adopt) { safeReset(p, other); } | ||
void reset(T* other, Ref) { safeReset(p, safeRef(other)); } | ||
void reset(T* other, RefSink) { safeReset(p, safeRefSink(other)); } | ||
|
||
operator bool() const { return p != nullptr; } | ||
|
||
T* get() { return p; } | ||
const T* get() const { return p; } | ||
|
||
T* release() { return std::exchange(p, nullptr); } | ||
|
||
T* operator->() { return p; } | ||
const T* operator->() const { return p; } | ||
|
||
void swap(CLibrariesSPtr& other) { std::swap(p, other.p); } | ||
|
||
private: | ||
T* p = nullptr; | ||
}; | ||
}; // namespace xoj::util | ||
|
||
namespace std { | ||
template <typename T, class H> | ||
void swap(xoj::util::CLibrariesSPtr<T, H>& first, xoj::util::CLibrariesSPtr<T, H>& second) { | ||
first.swap(second); | ||
} | ||
}; // namespace std |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Xournal++ | ||
* | ||
* RAII wrappers for C library classes | ||
* | ||
* @author Xournal++ Team | ||
* https://github.com/xournalpp/xournalpp | ||
* | ||
* @license GNU GPLv2 or later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <utility> | ||
|
||
#include <cairo.h> | ||
|
||
#include "CLibrariesSPtr.h" | ||
|
||
namespace xoj::util { | ||
|
||
inline namespace raii { | ||
namespace specialization { | ||
|
||
template <typename T> // Todo(cpp20): replace with std:identity() | ||
constexpr auto identity = [](T* p) { return p; }; | ||
|
||
class CairoHandler { | ||
public: | ||
constexpr static auto ref = cairo_reference; | ||
constexpr static auto unref = cairo_destroy; | ||
constexpr static auto adopt = identity<cairo_t>; | ||
}; | ||
|
||
class CairoSurfaceHandler { | ||
public: | ||
constexpr static auto ref = cairo_surface_reference; | ||
constexpr static auto unref = cairo_surface_destroy; | ||
constexpr static auto adopt = identity<cairo_surface_t>; | ||
}; | ||
}; // namespace specialization | ||
|
||
using CairoSPtr = CLibrariesSPtr<cairo_t, raii::specialization::CairoHandler>; | ||
using CairoSurfaceSPtr = CLibrariesSPtr<cairo_surface_t, raii::specialization::CairoSurfaceHandler>; | ||
|
||
/** | ||
* @brief cairo_save(cr)/cairo_restore(cr) RAII implementation | ||
*/ | ||
class CairoSaveGuard { | ||
public: | ||
CairoSaveGuard() = delete; | ||
CairoSaveGuard(cairo_t* cr): cr(cr) { cairo_save(cr); } | ||
~CairoSaveGuard() { cairo_restore(cr); } | ||
|
||
CairoSaveGuard(const CairoSaveGuard&) = delete; | ||
CairoSaveGuard(CairoSaveGuard&&) = delete; | ||
CairoSaveGuard& operator=(const CairoSaveGuard&) = delete; | ||
CairoSaveGuard& operator=(CairoSaveGuard&&) = delete; | ||
|
||
private: | ||
cairo_t* cr; | ||
}; | ||
|
||
}; // namespace raii | ||
}; // namespace xoj::util |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Xournal++ | ||
* | ||
* RAII wrappers for C library classes | ||
* | ||
* @author Xournal++ Team | ||
* https://github.com/xournalpp/xournalpp | ||
* | ||
* @license GNU GPLv2 or later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <utility> | ||
|
||
#include <glib-object.h> | ||
#include <gtk/gtk.h> | ||
|
||
#include "CLibrariesSPtr.h" | ||
|
||
namespace xoj::util { | ||
|
||
inline namespace raii { | ||
namespace specialization { | ||
|
||
template <class object_type> | ||
class GObjectHandler { | ||
public: | ||
static object_type* ref(object_type* p) { return static_cast<object_type*>(g_object_ref(p)); } | ||
constexpr static auto unref = g_object_unref; | ||
static object_type* ref_sink(object_type* p) { return static_cast<object_type*>(g_object_ref_sink(p)); } | ||
static object_type* adopt(object_type* p) { | ||
#if (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 70)) | ||
return static_cast<object_type*>(g_object_take_ref(p)); | ||
#else | ||
return g_object_is_floating(p) ? static_cast<object_type*>(g_object_ref_sink(p)) : p; | ||
#endif | ||
} | ||
}; | ||
}; // namespace specialization | ||
|
||
using WidgetSPtr = CLibrariesSPtr<GtkWidget, raii::specialization::GObjectHandler<GtkWidget>>; | ||
}; // namespace raii | ||
}; // namespace xoj::util |
Oops, something went wrong.