/* Please see LICENSE-CPOL.html in the root directory for the licencing of this file. Originally by: cppnow Link: http://www.codeproject.com/KB/cpp/smallptr.aspx */ #ifndef __SMALL_PTR_H__ #define __SMALL_PTR_H__ //#include #include #include #include "singleton.hpp" //#include //#include #ifdef _MSC_VER #include #else #include #endif //_MSC_VER #define is_n_aligned(T, N) ((sizeof(T) % (N)) == 0) #ifdef WIN32 # ifdef WIN64 # define USE64 # else # define USE32 # endif #endif #ifdef __GNUG__ # if defined(__amd64__) || defined(__x86_64__) # define USE64 # elif defined(__i386__) # define USE32 # endif #endif #include class bad_alignment : public std::exception { public: bad_alignment(const char *const& w) {} }; class bad_segment : public std::exception { public: bad_segment(const char *const& w) {} }; class sptr_base { protected: static const uint32_t ALIGNMENT_BITS = 2; static const uint32_t ALIGNMENT = (1< lock(_m); for (i = 0; i < s; ++i) if (_seg_map[i] == p) return i; i = _segs++; if (_segs > ALIGNMENT) { //throw bad_segment("Segment out of range"); exit(-1); } _seg_map[i] = p; return i; } }; template class sptr : public sptr_base { public: typedef TYPE type; typedef TYPE* native_pointer_type; typedef const TYPE* const_native_pointer_type; sptr() throw() : _ptr(0) {} // Copy constructor sptr(const sptr& o) throw() : _ptr(o._ptr) { } // Copy from a related pointer type // Although just copying _ptr would be more efficient - it may // also be wrong - e.g. multiple inheritence template sptr(const sptr& o) : _ptr(encode(static_cast(o.get()))) { } template sptr(const O* p) : _ptr(encode(static_cast(p))) { } sptr& operator=(const sptr& o) throw() { _ptr = o._ptr; return *this; } template sptr& operator=(const sptr& o) { _ptr = encode(static_cast(o.get())); return *this; } private: inline uint32_t encode(const_native_pointer_type ptr) const { #ifdef USE64 uintptr_t p = reinterpret_cast(ptr); if ((p & ALIGNMENT_MASK) != 0) { //throw bad_alignment("Pointer is not aligned"); exit(-1); } return (uint32_t)(ptr2seg(p) + p); #else // 32 bit machine return reinterpret_cast(ptr); #endif } inline native_pointer_type decode(uint32_t e) const { #ifdef USE64 uintptr_t el = e; uintptr_t ptr = (_seg_map[el & ALIGNMENT_MASK] + el) & ~ALIGNMENT_MASK; return reinterpret_cast(ptr); #else return reinterpret_cast(e); #endif } void check_alignment() const { //BOOST_STATIC_ASSERT(is_n_aligned(TYPE, ALIGNMENT)); } void inc_sptr(uint32_t& e, uintptr_t offset = 1) { check_alignment(); #ifdef USE64 uintptr_t el = e; uintptr_t seg = el & ALIGNMENT_MASK; el += offset*ALIGNMENT; // check for overflow if (el > 0xFFFFFFFFULL) return encode(decode(e)+1); e = (uint32_t)el; #else e+= (uint32_t)offset; #endif } void dec_sptr(uint32_t& e, size_t offset = 1) { check_alignment(); #ifdef USE64 uintptr_t el = e; // uintptr_t seg = el & ALIGNMENT_MASK; e-= offset*ALIGNMENT; // check for underflow if (el > 0xFFFFFFFFULL) return encode(decode(e)-1); e = (uint32_t)el; #else e -= (uint32_t)offset; #endif } public: TYPE* get() const throw() { return decode(_ptr); } // Pointer operators TYPE& operator*() { return *decode(_ptr); } const TYPE& operator*() const { return *decode(_ptr); } TYPE* operator->() { return decode(_ptr); } const TYPE* operator->() const { return decode(_ptr); } template bool operator==(const sptr& o) const { return o._ptr == this->_ptr; } operator TYPE*() const { return get(); } sptr& operator++( ) { inc_sptr(_ptr); return *this; } sptr operator++( int ) { sptr p = *this; inc_sptr(_ptr); return p; } sptr& operator--( ) { dec_sptr(_ptr); return *this; } sptr operator--( int ) { sptr p = *this; dec_sptr(_ptr); return p; } sptr& operator+=(size_t offset) { inc_sptr(_ptr, offset); return *this; } sptr& operator-=(size_t offset) { dec_sptr(_ptr, offset); return *this; } private: uint32_t _ptr; }; #endif