#ifndef _INCLUDED_L3_PTR_H #define _INCLUDED_L3_PTR_H // Copyright (C) Krzysztof Bosak, 1998-12-25...2000-12-11 // All rights reserved. // kbosak@box43.pl // http://www.kbosak.prv.pl // *Smart Pointers* #include #include #include "l3_port.h" template class AutoPtr { private: any_type * _ptr; public: inline AutoPtr(): _ptr(NULL) { } inline AutoPtr(any_type * const ptr): _ptr(ptr)// Implicit. { assert(_ptr!=NULL); } inline AutoPtr(const AutoPtr& other)// Implicit. { _ptr=other._ptr; } inline AutoPtr& operator=(const AutoPtr& other) { if(this==&other) { return *this; } _ptr=other._ptr; return *this; } inline AutoPtr& operator=(any_type * const other) { assert(_ptr==NULL); assert(_ptr!=other); if(_ptr==other) { return *this; } _ptr=other; return *this; } inline ~AutoPtr() { delete _ptr; #ifndef NDEBUG _ptr=NULL; #endif } inline bool IsValid() const { return _ptr!=NULL; } inline void Delete() { delete _ptr; _ptr=NULL; } inline any_type& operator*() { assert(_ptr!=NULL); return *_ptr; } inline const any_type& operator*() const { assert(_ptr!=NULL); return *_ptr; } inline any_type* operator->() const { assert(_ptr!=NULL); return _ptr; } inline any_type* get() { assert(_ptr!=NULL); return _ptr; } inline const any_type* get() const { assert(_ptr!=NULL); return _ptr; } }; template class SmartPtr { // SmartPtr pointer can point +/-1 position behind specified range. // While using operator* or operator[] must point exactly within given boundaries. // According to ANSI C++ langage, you can compare pointers pointing to the same array, // and not further than one position after the array boundary. You have been warned! private: any_type * _ptr;// Do not delete this pointer, this is for array access. #ifndef NDEBUG any_type * _base_ptr;// Do not delete this pointer, this is for array checking. int _array_size; #endif public: #ifndef NDEBUG inline SmartPtr(any_type * const ptr, any_type * const base_ptr, int array_size) :_ptr(ptr), _base_ptr(base_ptr), _array_size(array_size) #else inline SmartPtr(any_type * const ptr, any_type * const, int) : _ptr(ptr) #endif { assert(ptr!=NULL); assert(base_ptr!=NULL); assert(array_size>0); assert(ptr>=base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr); #ifndef NDEBUG if(_array_size=_base_ptr); #ifndef NDEBUG if(_array_size(const SmartPtr& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr>ptr._ptr; } inline bool operator>=(const SmartPtr& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr>=ptr._ptr; } inline bool operator<=(const SmartPtr& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr<=ptr._ptr; } inline bool operator==(const SmartPtr& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr==ptr._ptr; } inline bool operator!=(const SmartPtr& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr!=ptr._ptr; } inline const SmartPtr& operator+=(int ptrdiff) { _ptr+=ptrdiff; assert(_ptr>=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size(ptr._ptr+ptrdiff, ptr._base_ptr, ptr._array_size); #else return SmartPtr(ptr._ptr+ptrdiff, 0, 0); #endif } friend inline const SmartPtr operator-(const SmartPtr& ptr, int ptrdiff) { #ifndef NDEBUG return SmartPtr(ptr._ptr-ptrdiff, ptr._base_ptr, ptr._array_size); #else return SmartPtr(ptr._ptr-ptrdiff, 0, 0); #endif } }; template class StructSmartPtr: public SmartPtr { // Extension for data structures. public: inline StructSmartPtr(struct_type * const ptr, struct_type * const base_ptr, int array_size) :SmartPtr(ptr, base_ptr, array_size) { } inline struct_type* operator->() const {// only for complex data types, else warning with MSVC6 (even if unused) assert(_ptr>=_base_ptr); #ifndef NDEBUG if(_array_size class SmartPtrReadOnly { // SmartPtrReadOnly pointer can point +/-1 position behind specified range. // While using operator* or operator[] must point exactly within given boundaries. // According to ANSI C++ langage, you can compare pointers pointing to the same array, // and not further than one position after the array boundary. You have been warned! // Can be used only for reading. protected: const any_type * _ptr;// Do not delete this pointer, this is for array access. #ifndef NDEBUG const any_type *_base_ptr;// Do not delete this pointer, this is for array checking. int _array_size; #endif public: #ifndef NDEBUG inline SmartPtrReadOnly(const any_type * const ptr, const any_type * const base_ptr, int array_size) : _ptr(ptr), _base_ptr(base_ptr), _array_size(array_size) #else inline SmartPtrReadOnly(const any_type * const ptr, const any_type * const, int) : _ptr(ptr) #endif { assert(ptr!=NULL); assert(base_ptr!=NULL); assert(array_size>0); assert(ptr>=base_ptr-1); #ifndef NDEBUG if(array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr); #ifndef NDEBUG if(_array_size=_base_ptr); #ifndef NDEBUG if(_array_size(const SmartPtrReadOnly& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr>ptr._ptr; } inline bool operator>=(const SmartPtrReadOnly& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr>=ptr._ptr; } inline bool operator<=(const SmartPtrReadOnly& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr<=ptr._ptr; } inline bool operator==(const SmartPtrReadOnly& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr==ptr._ptr; } inline bool operator!=(const SmartPtrReadOnly& ptr) const { assert(_base_ptr==ptr._base_ptr); return _ptr!=ptr._ptr; } inline SmartPtrReadOnly& operator+=(int ptrdiff) { _ptr+=ptrdiff; assert(_ptr>=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size=_base_ptr-1);// NuMega DevPartner: ignore this. #ifndef NDEBUG if(_array_size(ptr._ptr+ptrdiff, ptr._base_ptr, ptr._array_size); #else return SmartPtrReadOnly(ptr._ptr+ptrdiff, 0, 0); #endif } friend inline const SmartPtrReadOnly operator-(const SmartPtrReadOnly& ptr, int ptrdiff) { #ifndef NDEBUG return SmartPtrReadOnly(ptr._ptr-ptrdiff, ptr._base_ptr, ptr._array_size); #else return SmartPtrReadOnly(ptr._ptr-ptrdiff, 0, 0); #endif } }; template class StructSmartPtrReadOnly: public SmartPtrReadOnly { // Extension for data structures. public: inline StructSmartPtrReadOnly( const struct_type * const ptr, const struct_type * const base_ptr, int array_size ) :SmartPtrReadOnly(ptr, base_ptr, array_size) { } inline const struct_type* operator->() const {// only for complex data types, else warning with MSVC6 (even if unused) assert(_ptr>=_base_ptr); #ifndef NDEBUG if(_array_size=0); assert(_pointer!=NULL); _pointer[0]=identifier; if(identifier==-1) { _explicitly_initialized=false; } else { _explicitly_initialized=true; } _instances++; } inline ContainerTester(const ContainerTester& src)// Implicit. :_pointer(new int[1]), _explicitly_initialized(src._explicitly_initialized) { assert(&src!=this); assert(_instances>=0); assert(_pointer!=NULL); _pointer[0]=src._pointer[0]; _instances++; } inline virtual ~ContainerTester() { assert(_pointer!=NULL); _pointer[0]=-1; delete[] _pointer; _pointer=reinterpret_cast(-1);// Using completely wrong value for a pointer. Cannot be simply 0 - deleting NULL point can pass unspotted. _instances--; assert(_instances>=0); } inline int Instances() const { return _instances; } inline int Identifier() const { return _pointer[0]; } inline ContainerTester& operator=(const ContainerTester& m)// EXCEPTION NEUTRAL { //assert(this!=&m);// for investigation purposes only, sometimes redundant but helpful //assert(m._explicitly_initialized==true);// very strict rule if(this==&m) { return *this; } _pointer[0]=m._pointer[0]; _explicitly_initialized=true;// m._explicitly_initialized; return *this; } inline ContainerTester& operator=(int identifier)// EXCEPTION NEUTRAL { _pointer[0]=identifier; _explicitly_initialized=true; return *this; } friend bool operator<(const ContainerTester& a, const ContainerTester& b) { assert(a._explicitly_initialized==true); assert(b._explicitly_initialized==true); return a._pointer[0]