/* * Copyright (C) 2007-2023 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #ifndef BU_SPTR_H #define BU_SPTR_H #include #include namespace Bu { template class SPtr; template< typename Tb, typename Ta > SPtr SPtrCast( SPtr src ); /** *@ingroup Containers */ template class SPtr { template friend SPtr SPtrCast( SPtr pt ); public: SPtr() : pRefCnt( NULL ), pData( NULL ) { } ~SPtr() { decCount(); } SPtr( const SPtr &src ) : pRefCnt( src.pRefCnt ), pData( src.pData ) { if( pRefCnt ) (*pRefCnt) += 1; } SPtr( T *pSrc ) : pRefCnt( NULL ), pData( pSrc ) { if( pData ) { pRefCnt = new int32_t; (*pRefCnt) = 1; } } /** * Get the number of references to this pointer. *@returns (int32_t) The number of references to this pointer. */ int32_t getRefCount() const { return *pRefCnt; } void clear() { decCount(); pRefCnt = NULL; pData = NULL; } /** * Pointer access operator. *@returns (const T *) */ const T *operator->() const { return pData; } /** * Dereference operator. *@returns (const T &) The value at the end of the pointer. */ const T &operator*() const { return *pData; } /** * Pointer access operator. *@returns (T *) */ T *operator->() { return pData; } /** * Dereference operator. *@returns (T &) The value at the end of the pointer. */ T &operator*() { return *pData; } /** * Assignment operator. *@param src (const SPtr &) */ SPtr operator=( const SPtr &src ) { decCount(); pRefCnt = src.pRefCnt; pData = src.pData; if( pRefCnt ) (*pRefCnt) += 1; return *this; } /** * Assignment operator. *@param src (const SPtr &) */ const SPtr operator=( const SPtr &src ) const { decCount(); pRefCnt = src.pRefCnt; pData = src.pData; if( pRefCnt ) (*pRefCnt) += 1; return *this; } /** * Equals comparison operator. *@param src (const SPtr &) The SPtr to compare to. *@returns (bool) Are the equal? */ bool operator==( const SPtr &src ) const { return pData == src.pData; } /** * Equals comparison operator. *@param src (const T *) The pointer to compare to. *@returns (bool) Are the equal? */ bool operator==( const T *src ) const { return pData == src; } /** * Not equals comparison operator. *@param src (const SPtr &) The SPtr to compare to. *@returns (bool) Are the equal? */ bool operator!=( const SPtr &src ) const { return !(pData == src.pData); } /** * Not equals comparison operator. *@param src (const T *) The pointer to compare to. *@returns (bool) Are the equal? */ bool operator!=( const T *src ) const { return !(pData == src); } /** * Boolean cast operator. Do we have a pointer? */ operator bool() const { return pRefCnt != NULL; } /** * Do we have a pointer? *@returns (bool) Do we have a pointer? */ bool isSet() const { return pRefCnt != NULL; } private: void decCount() const { if( pRefCnt ) { (*pRefCnt) -= 1; //printf("Decrementing ref-count to %d\n", *pRefCnt ); if( (*pRefCnt) == 0 ) { delete pRefCnt; delete pData; pRefCnt = NULL; pData = NULL; } } } mutable int32_t *pRefCnt; mutable T *pData; }; template< typename Tb, typename Ta > SPtr SPtrCast( SPtr src ) { SPtr ret; ret.pRefCnt = src.pRefCnt; ret.pData = dynamic_cast(src.pData); if( ret.pRefCnt ) (*(ret.pRefCnt)) += 1; return ret; } } #endif