#ifndef SDV_PTR_H #define SDV_PTR_H #include #include #include #include "iterator.h" #ifndef DONT_LOAD_CORE_TYPES #include "../interfaces/core_types.h" #endif namespace sdv { // Forward declaration template class pointer; /** * @brief Managed pointer class. * @details Buffer management class. There are two versions of buffer management, fixed buffer management (nFixedSize template * parameter larger than 0) and dynamic buffer management (nFixedSize template parameter is 0). The fixed buffer management * contains a fixed memory allocation of the amount of elements (capacity) and manages the size within this buffer. Copies of * this pointer class will copy the buffer as well. The dynamic buffer behaves like a shared pointer. Copies of the pointer class will * copy the pointer, but not the content. The lifetime of the content is managed through reference counter. The functions of * this class are similar to the functions of the std::shared_ptr class. * @tparam T Type to use for the buffer allocation. * @tparam nFixedSize Size of the fixed size buffer or 0 for a dynamic sized buffer. */ template class pointer { public: /** * @brief The element type of this pointer. */ using element_type = T; /** * @brief The size of this pointer allocation element in bytes. */ static const size_t size_bytes = nFixedSize * sizeof(T); /** * @brief The size of this pointer allocation in bytes aligned to 64-bits. */ static const size_t aligned_size_bytes = nFixedSize * sizeof(T) + ((nFixedSize * sizeof(T) % 8) ? (8 - nFixedSize * sizeof(T) % 8) : 0); /** * @brief Default constructor */ pointer() noexcept; /** * @brief Copy constructor of same pointer type. * @param[in] rptr Reference to the pointer to copy. */ pointer(const pointer& rptr); /** * @brief Copy constructor of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to copy. */ template pointer(const pointer& rptr); /** * @brief Move constructor of same pointer type. * @param[in] rptr Reference to the pointer to copy. */ pointer(pointer&& rptr); /** * @brief Move constructor of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to copy. */ template pointer(pointer&& rptr); /** * @brief Destructor */ ~pointer(); /** * @brief Assignment operator of same pointer type. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ pointer& operator=(const pointer& rptr); /** * @brief Assignment operator of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ template pointer& operator=(const pointer& rptr); /** * @brief Move operator of same pointer type. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ pointer& operator=(pointer&& rptr); /** * @brief Move operator of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ template pointer& operator=(pointer&& rptr); /** * @brief Reduces the reference count and if zero deletes the allocation. Clears the pointer. */ void reset(); /** * @brief Swaps this pointer with the provided pointer. * tparam nFixedSizeRight The fixed size of the provided pointer. * @param[in] rptr Reference to the provided pointer to swap with. */ template void swap(pointer& rptr); /** * @brief Get access to the underlying buffer. * @return Pointer to the buffer. */ element_type* get() const noexcept; /** * @brief Get a reference to the pointer. * @return Reference to the value. */ T& operator*() const; /** * @brief Get a reference to the pointer. * @return Pointer to the value. */ T* operator->() const; /** * @brief Get the indexed value of the pointer. * @param[in] nIndex Index to request the value of. * @return Reference to the indexed value. */ element_type& operator[](size_t nIndex) const; /** * @brief Return whether a pointer is assigned. * @return Returns 'true' when a pointer is assigned; 'false' otherwise. */ operator bool() const noexcept; /** * @brief Return the amount of elements allocated for this pointer. * @return The size of the pointer. */ size_t size() const noexcept; /** * @brief Resize the pointer. * @param[in] nSize Size of the new pointer. */ void resize(size_t nSize); /** * @brief Return the capacity (in amount of elements) this buffer can hold. * @return The capacity of the buffer pointed to by this pointer. */ size_t capacity() const noexcept; private: uint32_t m_uiSize = 0; ///< Amount of elements allocated. uint32_t m_uiReserved = 0; ///< Reserved for alignment purposes. union { T m_rgtData[nFixedSize] = {}; ///< The size of the buffer. uint8_t m_rguiBuffer[aligned_size_bytes]; ///< The buffer aligned to 64 bits. }; }; namespace internal { /// @cond DOXYGEN_IGNORE // Forward declaration interface IInternalMemAlloc; template pointer make_ptr(IInternalMemAlloc* pAllocator, size_t nSize = 1); /// @endcond } /** * @brief Create a pointer class using the allocator and allocating the memory with the given size. * @tparam T Type to use for the allocation. * @param[in] nSize Size to allocate (in elements). * @return The pointer class. */ template pointer make_ptr(size_t nSize = 1); /** * @brief Specialization for dynamic sized buffer management. * @tparam T Type to use for the buffer allocation. */ template class pointer { friend pointer internal::make_ptr(internal::IInternalMemAlloc* pAllocator, size_t nSize /*= 1*/); friend pointer make_ptr(size_t); public: /** * @brief The element type of this pointer. */ using element_type = T; /** * @brief Default constructor */ pointer() noexcept; /** * @brief Copy constructor of same pointer type. * @param[in] rptr Reference to the pointer to copy. */ pointer(const pointer& rptr); /** * @brief Copy constructor of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to copy. */ template pointer(const pointer& rptr); /** * @brief Move constructor * @param[in] rptr Reference to the pointer to move. */ pointer(pointer&& rptr) noexcept; /** * @brief Move constructor of other pointer types. * @tparam nFixedSize2 The fixed size of the provided pointer. * @param[in] rptr Reference to the pointer to copy. */ template pointer(const pointer&& rptr); /** * @brief Destructor */ ~pointer(); /** * @brief Assignment operator of same pointer type. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ pointer& operator=(const pointer& rptr); /** * @brief Assignment operator of other pointer types. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ template pointer& operator=(const pointer& rptr); /** * @brief Move operator of same pointer type. * @param[in] rptr Reference to the pointer to move. * @return Reference to this pointer. */ pointer& operator=(pointer&& rptr) noexcept; /** * @brief Move operator of other pointer types. * @param[in] rptr Reference to the pointer to assign. * @return Reference to this pointer. */ template pointer& operator=(pointer&& rptr); protected: /** * @brief Attach an uint8_t buffer. * @param[in] rptrBuffer Reference to the pointer to attach. */ void attach(pointer&& rptrBuffer); /** * @brief Detach the uint8_t buffer. * @return Reference to the pointer to detach. */ pointer&& detach(); public: /** * @brief Reduces the reference count and if zero deletes the allocation. Clears the pointer. */ void reset(); /** * @brief Swaps this pointer with the provided pointer. * tparam nFixedSizeRight The fixed size of the provided pointer. * @param[in] rptr Reference to the provided pointer to swap with. */ template void swap(pointer& rptr); /** * @brief Get access to the underlying buffer. * @return Pointer to the buffer. */ element_type* get() const noexcept; /** * @brief Get a reference to the pointer. * @return Reference to the value. */ T& operator*() const; /** * @brief Get a reference to the pointer. * @return Pointer to the value. */ T* operator->() const; /** * @brief Get the indexed value of the pointer. * @param[in] nIndex Index to request the value of. * @return Reference to the indexed value. */ element_type& operator[](size_t nIndex) const; /** * @brief Return whether a pointer is assigned. * @return Returns 'true' when a pointer is assigned; 'false' otherwise. */ operator bool() const noexcept; /** * @brief Return the amount of elements allocated for this pointer. * @return The size of the pointer. */ size_t size() const noexcept; /** * @brief Resize the pointer. * @attention A call to this function is not synchronized with other functions. * @param[in] nSize Size of the new pointer. */ void resize(size_t nSize); /** * @brief Return the capacity (in amount of elements) this buffer can hold. * @return The capacity of the buffer pointed to by this pointer. */ size_t capacity() const noexcept; /** * @brief Get reference count on current shares. * @return Reference count. */ size_t ref_count() const noexcept; private: /** * @brief The internal data structure holding the pointer information. */ struct SAllocation { internal::IInternalMemAlloc* pAllocator = nullptr; ///< Pointer to the memory allocator. T* pData = nullptr; ///< Pointer to the data. uint32_t uiSize = 0; ///< Amount of bytes allocated. std::atomic_uint32_t uiRefCnt = 0; ///< Reference count. }; SAllocation* m_psAllocation = nullptr; ///< Actual pointer to the allocation }; /** * @brief Swap two pointers. * @tparam T Type to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the first pointer. * @param[in] rptrRight Reference to the second pointer. */ template void swap(pointer& rptrLeft, pointer& rptrRight); /** * @brief Compare two pointers for equality. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when both pointers are equal; false when not. */ template bool operator==(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare two pointers for inequality. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when both pointers are not equal; false when not. */ template bool operator!=(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare whether one pointer is smaller than another pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when the left pointer is smaller than the right pointer; false when not. */ template bool operator<(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare whether one pointer is smaller than or equal to another pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when the left pointer is smaller than or equal to the right pointer; false when not. */ template bool operator<=(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare whether one pointer is larger than another pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when the left pointer is larger than the right pointer; false when not. */ template bool operator>(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare whether one pointer is larger than or equal to another pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] rptrRight Reference to the right pointer. * @return Returns 'true' when the left pointer is larger than or equal to the right pointer; false when not. */ template bool operator>=(const pointer& rptrLeft, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is equal too NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer equals NULL; 'false' when not. */ template bool operator==(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the right pointer is equal too NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the right pointer equals NULL; 'false' when not. */ template bool operator==(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is not equal too NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer does not equal to NULL; 'false' when not. */ template bool operator!=(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the right pointer is not equal too NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the right pointer does not equal to NULL; 'false' when not. */ template bool operator!=(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is smaller than NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer is smaller than NULL; 'false' when not. */ template bool operator<(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the NULL is smaller than the left pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if NULL is smaller than the left pointer; 'false' when not. */ template bool operator<(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is smaller than or equal to NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer is smaller than or equal to NULL; 'false' when not. */ template bool operator<=(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the NULL is smaller than or equal to the left pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if NULL is smaller than or equal to the left pointer; 'false' when not. */ template bool operator<=(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is larger than NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer is larger than NULL; 'false' when not. */ template bool operator>(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the NULL is larger than the left pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if NULL is larger than the left pointer; 'false' when not. */ template bool operator>(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Compare whether the left pointer is smaller than or equal to NULL. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeLeft The fixed size of the left pointer. * @param[in] rptrLeft Reference to the left pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if the left pointer is smaller than or equal to NULL; 'false' when not. */ template bool operator>=(const pointer& rptrLeft, std::nullptr_t pNull) noexcept; /** * @brief Compare whether the NULL is smaller than or equal to the left pointer. * @tparam T Type of the pointer to use as a base. * @tparam nFixedSizeRight The fixed size of the right pointer. * @param[in] rptrRight Reference to the right pointer. * @param[in] pNull Pointer to a nullptr. * @return Returns 'true' if NULL is smaller than or equal to the left pointer; 'false' when not. */ template bool operator>=(std::nullptr_t pNull, const pointer& rptrRight) noexcept; /** * @brief Stream the value of a the pointer to an output stream. * @tparam T Type of pointer. * @tparam U Character type of output stream. * @tparam V Character traits of output stream. * @tparam nFixedSize The fixed size of the pointer. * @param[in] rstream Reference to the stream. * @param[in] rptr Reference to the pointer. * @return Reference to the stream. */ template std::basic_ostream& operator<<(std::basic_ostream& rstream, const pointer& rptr); /** * @brief C++ library stream support - reading from stream. * @tparam TTraits Character traits of the stream buffer. * @param[in, out] pStreamBuf Pointer to the stream buffer to read from. * @return Pointer object created from the stream buffer. */ template > pointer from_stream(std::basic_streambuf* pStreamBuf); /** * @brief C++ library stream support - writing to stream. * @tparam TTraits Character traits of the stream buffer. * @param[in] rptr Reference to the pointer to write to the stream. * @param[in, out] pStreamBuf Pointer to the stream buffer to write to. */ template > void to_stream(const pointer& rptr, std::basic_streambuf* pStreamBuf); /** * @brief For the uint8_t pointer a specific cast operation exists. * @attention Use with care. There is no guarantee that the pointer corresponds to the layout of the requested type. If * possible use serialization instead. * @tparam T Type to cast to. T must be a standard-layout-type. * @param[in] rptr Reference to the pointer containing the data buffer. * @param[in] nOffset Offset the type starts. * @return Returns a casted pointer if the buffer is large enough (offset + sizeof(T)); NULL otherwise. */ template T* cast(pointer& rptr, size_t nOffset = 0); /** * @brief For the uint8_t pointer a specific cast operation exists. * @attention Use with care. There is no guarantee that the pointer corresponds to the layout of the requested type. If * possible use serialization instead. * @tparam T Type to cast to. T must be a standard-layout-type. * @param[in] rptr Reference to the pointer containing the data buffer. * @param[in] nOffset Offset the type starts. * @return Returns a casted pointer if the buffer is large enough (offset + sizeof(T)); NULL otherwise. */ template const T* cast(const pointer& rptr, size_t nOffset = 0); } // namespace sdv #include "pointer.inl" #endif // !defined SDV_PTR_H