// Copyright 2019-2021 David Robillard // SPDX-License-Identifier: ISC #ifndef SERD_DETAIL_WRAPPER_HPP #define SERD_DETAIL_WRAPPER_HPP // IWYU pragma: no_include "serd/serd.h" #include #include #include #include namespace serd { /// Utility template for a mutable type which removes const if necessary template class Optional; /// Detail namespace namespace detail { /** @defgroup serdpp_detail API Details Internal C++ wrapper details that should not be used directly by clients. @ingroup serdpp @{ */ /// Utility template for a mutable type which removes const if necessary template using Mutable = typename std::remove_const_t; /// Generic C++ wrapper for a C object template class Wrapper { public: using CType = T; explicit Wrapper(T* ptr) : _ptr{ptr, Deleter{}} {} Wrapper(T* ptr, Deleter deleter) : _ptr{ptr, std::move(deleter)} {} explicit Wrapper(std::unique_ptr ptr) : _ptr{std::move(ptr)} {} Wrapper(Wrapper&&) noexcept = default; Wrapper& operator=(Wrapper&&) noexcept = default; Wrapper(const Wrapper&) = delete; Wrapper& operator=(const Wrapper&) = delete; ~Wrapper() = default; /// Return a pointer to the underlying C object T* cobj() { return _ptr.get(); } /// Return a pointer to the underlying C object const T* cobj() const { return _ptr.get(); } protected: friend class Optional; explicit Wrapper(std::nullptr_t) : _ptr{nullptr} {} void reset() { _ptr.reset(); } std::unique_ptr _ptr; }; /// Free function for an object that can free itself template using StandaloneFreeFunc = void(Mutable*); /// Free function for an object managed via an allocator template using AllocatedFreeFunc = void(ZixAllocator*, Mutable*); /** Simple overhead-free deleter for a C object. Can be used with const or mutable pointers, but only mutable pointers will be freed. In other words, mutability implies ownership, and this can not handle unowned mutable pointers. @ingroup serdpp_detail */ template free> struct StandaloneDeleter { template::value>> void operator()(Mutable* const ptr) { free(ptr); } template::value>> void operator()(const T*) {} }; /** Simple overhead-free deleter for a C object. Can be used with const or mutable pointers, but only mutable pointers will be freed. In other words, mutability implies ownership, and this can not handle unowned mutable pointers. @ingroup serdpp_detail */ template free> struct AllocatedDeleter { template::value>> void operator()(Mutable* const ptr) { free(nullptr, ptr); } template::value>> void operator()(const T*) {} }; /** @} */ } // namespace detail } // namespace serd #endif // SERD_DETAIL_WRAPPER_HPP