/*
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