diff options
author | David Robillard <d@drobilla.net> | 2018-06-16 10:26:47 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:08 -0500 |
commit | 8fb8b922fb7575d7aed2f2184a02586b56ba873a (patch) | |
tree | 06ea3a48cefb5cb221359b17911380460e68e7c8 /bindings/cpp/include/serd/detail/Copyable.hpp | |
parent | 74ddf7934336f16dcdce688333040d82972817fc (diff) | |
download | serd-8fb8b922fb7575d7aed2f2184a02586b56ba873a.tar.gz serd-8fb8b922fb7575d7aed2f2184a02586b56ba873a.tar.bz2 serd-8fb8b922fb7575d7aed2f2184a02586b56ba873a.zip |
[WIP] Add C++ bindings
Diffstat (limited to 'bindings/cpp/include/serd/detail/Copyable.hpp')
-rw-r--r-- | bindings/cpp/include/serd/detail/Copyable.hpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/bindings/cpp/include/serd/detail/Copyable.hpp b/bindings/cpp/include/serd/detail/Copyable.hpp new file mode 100644 index 00000000..5a5b5cde --- /dev/null +++ b/bindings/cpp/include/serd/detail/Copyable.hpp @@ -0,0 +1,106 @@ +// Copyright 2019-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef SERD_DETAIL_COPYABLE_HPP +#define SERD_DETAIL_COPYABLE_HPP + +// IWYU pragma: no_include "serd/serd.h" + +#include "serd/detail/Wrapper.hpp" + +#include <cstddef> +#include <memory> +#include <type_traits> +#include <utility> + +namespace serd { +namespace detail { + +/** + @addtogroup serdpp_detail + @{ +*/ + +/// Copy function for an allocator-managed C object +template<class T> +using CopyFunc = Mutable<T>* (*)(ZixAllocator*, const T*); + +/// Equality comparison function for C objects +template<class T> +using EqualsFunc = bool (*)(const T*, const T*); + +template<class T, CopyFunc<T> copy_func> +typename std::enable_if_t<std::is_const<T>::value, T>* +copy_cobj(const T* ptr) +{ + return ptr; // Constant wrapper, do not copy +} + +template<class T, CopyFunc<T> copy_func> +typename std::enable_if_t<!std::is_const<T>::value, T>* +copy_cobj(const T* ptr) +{ + return ptr ? copy_func(nullptr, ptr) : nullptr; // Mutable wrapper, copy +} + +/** + Generic wrapper for a "basic" copyable object. + + This wraps objects with simple ownership semantics where a const pointer is + never owned, and a mutable pointer is owned. This has no space overhead + compared to a raw pointer since the ownership is encoded in the type. +*/ +template<class T, class Deleter, CopyFunc<T> copy, EqualsFunc<T> equals> +class Copyable : public Wrapper<T, Deleter> +{ +public: + using Base = Wrapper<T, Deleter>; + + explicit Copyable(T* ptr) + : Base{ptr} + {} + + Copyable(const Copyable& wrapper) + : Base(copy_cobj<T, copy>(wrapper.cobj())) + {} + + template<class U, class UDeleter> + explicit Copyable(const Copyable<U, UDeleter, copy, equals>& wrapper) + : Base(copy_cobj<T, copy>(wrapper.cobj())) + {} + + Copyable(Copyable&&) noexcept = default; + Copyable& operator=(Copyable&&) noexcept = default; + + ~Copyable() noexcept = default; + + Copyable& operator=(const Copyable& wrapper) + { + if (&wrapper != this) { + this->_ptr = + std::unique_ptr<T, Deleter>(copy_cobj<T, copy>(wrapper.cobj())); + } + return *this; + } + + template<class U, class UDeleter, Mutable<T>* UCopy(ZixAllocator*, const T*)> + bool operator==(const Copyable<U, UDeleter, UCopy, equals>& wrapper) const + { + return equals(this->cobj(), wrapper.cobj()); + } + + template<class U, class UDeleter, Mutable<T>* UCopy(ZixAllocator*, const T*)> + bool operator!=(const Copyable<U, UDeleter, UCopy, equals>& wrapper) const + { + return !operator==(wrapper); + } +}; + +/** + @} +*/ + +} // namespace detail +} // namespace serd + +#endif // SERD_DETAIL_COPYABLE_HPP |