#line 1 "/user/cvsspst/ees1cg/RAVL/RAVL-0.7/Core/Container/Buffer/RBfAcc.hh" // This file is part of RAVL, Recognition And Vision Library // Copyright (C) 2001, University of Surrey // This code may be redistributed under the terms of the GNU Lesser // General Public License (LGPL). See the lgpl.licence file for details or // see http://www.gnu.org/copyleft/lesser.html // file-header-ends-here #ifndef RAVL_RBFACC_HEADER #define RAVL_RBFACC_HEADER ////////////////////////////////////////////////////////////////////////// //! file="Ravl/Core/Container/Buffer/RBfAcc.hh" //! lib=RavlCore //! userlevel=Develop //! author="Radek Marik" //! docentry="Ravl.Core.Arrays.Buffer" //! rcsid="$Id: RBfAcc.hh,v 1.12 2002/07/07 21:41:12 craftit Exp $" //! date="26/2/1997" //! example=exRBfAcc.cc #include "Ravl/BufferAccess.hh" #include "Ravl/Assert.hh" #include "Ravl/IndexRange1d.hh" #include "Ravl/Types.hh" namespace RavlN { class BinOStreamC; class BinIStreamC; //: Basic access to buffer with limited range // The class RangeBufferAccessC enables to random indexed access to // a sequentially organised continous part of memory called buffer. // The access functions check if an accessed element is valid only in // debug mode. template class RangeBufferAccessC : public BufferAccessC { public: typedef DataT ElementT; // Constructors, copies, assigment, and destructor // ----------------------------------------------- inline RangeBufferAccessC(DataT * bp = 0, const IndexRangeC & r = 0); //: Creates an access to a buffer pointed by the pointer 'bp'. // If 'bp' is 0, the access is not valid. // 'bp' Is assumed to point to the r.Min() element of the array. inline RangeBufferAccessC(const IndexRangeC & r,DataT * bp); //: Creates an access to a buffer pointed by the pointer 'bp'. // Where bp has already had r.LCol() subtracted from it. // This is has been introduced to allow a bug fix in the class // ImageC. inline RangeBufferAccessC(const BufferAccessC & bp, const IndexRangeC & r); //: Creates an access to a buffer referenced by 'bp' with range 'r'. // the first element in 'bp' will be moved to offset 'r.Min()'. inline RangeBufferAccessC(const IndexRangeC & r,const BufferAccessC & bp); //: Creates an access to a buffer referenced by 'bp' with range 'r'. // This assumes 'bp' has already been shifted so range 'r' will index // valid elements. inline RangeBufferAccessC(const RangeBufferAccessC & ba); //: Creates a new access to 'ba'. inline RangeBufferAccessC(const RangeBufferAccessC & ba, const IndexRangeC & r); //: Creates a new access to 'ba' limited by range 'r'. inline const RangeBufferAccessC & operator=(DataT * bp); //: Changes the reference element to the element pointed by 'bp'. // Access to the object // -------------------- //inline const BufferAccessC & Access(void) const; // Returns this object. inline DataT * DataStart() { return ReferenceElm() + range.Min().V(); } //: Returns the address of the first element of the buffer. inline const DataT * DataStart() const { return ReferenceElm() + range.Min().V(); } //: Returns the address of the first element of the buffer. inline SizeT Size() const { return range.Size(); } // Returns the number of elements of the array. inline const IndexRangeC & Range() const { return range; } // Returns the usable range of indeces expressed by this object. inline IndexC IMin() const { return range.Min(); } // Returns the minimum index of the range of this access. inline IndexC IMax() const { return range.Max(); } // Returns the maximum index of the range of this access. inline const DataT & operator[](IndexC i) const; // Read-only access to the ('i'+1)-th element of the buffer. inline DataT & operator[](IndexC i); // Read-write access to the ('i'+1)-th element of the buffer. inline const RangeBufferAccessC & RAccess(void) const; // Returns this object. // Logical functions // ----------------- inline bool IsEmpty() const { return range.IsEmpty(); } // Returns TRUE if the size of the array is zero. inline bool Contains(IndexC i) const { return range.Contains(i); } // Returns TRUE if the array contains an item with the index 'i'. inline bool IsOverlapping(const RangeBufferAccessC & acc) const { return range.IsOverlapping(acc.range); } // Returns TRUE if this access has an item with the same index as // an item of the access 'acc'. // Modifications of the access // --------------------------- inline const RangeBufferAccessC & operator+=(SizeT i); // Changes indeces of the access to be 'i' units higher. inline RangeBufferAccessC operator+(SizeT i) const; // Creates the new access object with the indeces 'i' units higher // than those used in this access object. inline const IndexRangeC & ShrinkHigh(SizeT k) { return range.ShrinkHigh(k); } //: Changes the number of elements by subtracting the last 'k' elements. inline void ShiftIndexes(IndexC offset); //: All indexes of the items will be changed by 'offset'. // The range will be shifted by -offset. inline void SetSubRange(IndexC newMin, IndexC newMax) { range.ClipBy(IndexRangeC(newMin, newMax)); } //: Constrain the indexs that can be accessed from the array. // The range of indexes of this array will be constrained to cover // the index range at most. inline const RangeBufferAccessC & Swap(RangeBufferAccessC & a); // Exchanges the contents of this buffer with buffer 'a'. inline void Swap(IndexC i1, IndexC i2); // Exchanges the contents of elements with indeces 'i1' and 'i2'. inline void Attach(const RangeBufferAccessC & b); // Changes this buffer access to have the same access rights as 'b'. inline void Attach(const BufferAccessC & b, const IndexRangeC & r); // Changes this buffer access to have the access rights as 'b' limited // by range 'r'. so the first element in 'b' is accessed at 'r.Min()'. RangeBufferAccessC BufferFrom(IndexC first); //: Get an access for this buffer starting from the 'first' element to the end of the buffer. RangeBufferAccessC BufferFrom(IndexC first,UIntT len); //: Get an access for this buffer starting from the 'first' element for 'len' elements. // An error will be generated if the requested buffer isn't contains within this one. // Modifications of the buffer contents // ------------------------------------ void Fill(const DataT & d); //: Fill the buffer with the value 'd'. void Reverse(); //: Reverse the order of elements in this array in place. bool operator==(const RangeBufferAccessC &ba) const { return (buff == ba.buff) && (range == ba.range); } //: Are two accesses the same ? protected: // Copy // ---- RangeBufferAccessC Copy(void) const; // Returns a physical copy of this access pointing to the physical // copy of the accessed buffer in the range accessible by this access. // The new copy is necessary to attach to reference counted buffer // or to delete at the end of the life of this object. IndexRangeC range; // Information on the limits of the buffer }; ///////////////////////////////////////////////////////////////////////////// //: Wrtie buffer to stream. // NB. This size of the buffer is NOT written. template ostream &operator<<(ostream &out,const RangeBufferAccessC &dat) { const DataT *at = dat.DataStart(); const DataT *endOfRow = &at[dat.Size()]; if(dat.Size() == 0) return out; out << *at; at++; for(;at != endOfRow;at++) out << ' ' << *at; return out; } //: Read buffer from stream. // NB. The buffer must be pre-allocated. template istream &operator>>(istream &strm,RangeBufferAccessC &dat) { DataT *at = dat.DataStart(); DataT *endOfRow = &at[dat.Size()]; for(;at != endOfRow;at++) strm >> *at; return strm; } //: Wrtie buffer to stream. // NB. This size of the buffer is NOT written. template BinOStreamC &operator<<(BinOStreamC &out,const RangeBufferAccessC &dat) { const DataT *at = dat.DataStart(); const DataT *endOfRow = &at[dat.Size()]; if(dat.Size() == 0) return out; for(;at != endOfRow;at++) out << *at; return out; } //: Read buffer from stream. // NB. The buffer must be pre-allocated. template BinIStreamC &operator>>(BinIStreamC &strm,RangeBufferAccessC &dat) { DataT *at = dat.DataStart(); DataT *endOfRow = &at[dat.Size()]; for(;at != endOfRow;at++) strm >> *at; return strm; } template inline RangeBufferAccessC::RangeBufferAccessC(DataT * bp, const IndexRangeC & r) : BufferAccessC(bp - r.Min().V()), range(r) {} template inline RangeBufferAccessC::RangeBufferAccessC( const IndexRangeC & r, DataT * bp) : BufferAccessC(bp), range(r) {} template inline RangeBufferAccessC::RangeBufferAccessC(const BufferAccessC & bp, const IndexRangeC & r) : BufferAccessC(const_cast &>(bp) - r.Min().V()), range(r) {} template inline RangeBufferAccessC::RangeBufferAccessC(const IndexRangeC & r,const BufferAccessC & bp) : BufferAccessC(const_cast &>(bp)), range(r) {} template inline RangeBufferAccessC::RangeBufferAccessC(const RangeBufferAccessC & ba) : BufferAccessC(ba), range(ba.range) {} template inline RangeBufferAccessC::RangeBufferAccessC(const RangeBufferAccessC & ba, const IndexRangeC & r) : BufferAccessC(ba), range(r) { #if RAVL_CHECK if ((!r.In(ba.Range()) && (r.Size() > 0)) || !ba.Range().Contains(r.Min())) IssueError(__FILE__,__LINE__,"Index range %d to %d out of range %d - %d ", r.Min().V(),r.Max().V(),ba.Range().Min().V(),ba.Range().Max().V()); #endif } /////////////////////////////////////////////////////////// template inline const RangeBufferAccessC & RangeBufferAccessC::operator=(DataT * bp) { ((BufferAccessC &) *this) = bp; return *this; } template inline const DataT &RangeBufferAccessC::operator[](IndexC i) const { #if RAVL_CHECK if (!Contains(i)) IssueError(__FILE__,__LINE__,"Index %d out of range %d - %d ", i.V(),Range().Min().V(),Range().Max().V()); #endif return BufferAccessC::operator[](i); } template inline DataT & RangeBufferAccessC::operator[](IndexC i) { #if RAVL_CHECK if (!Contains(i)) IssueError(__FILE__,__LINE__,"Index %d out of range %d - %d ", i.V(),Range().Min().V(),Range().Max().V()); #endif return BufferAccessC::operator[](i); } template inline const RangeBufferAccessC & RangeBufferAccessC::RAccess(void) const { return *this; } template inline const RangeBufferAccessC &RangeBufferAccessC::Swap(RangeBufferAccessC & a) { DataT *tmp(buff); buff = a.buff; a.buff = tmp; range.Swap(a.range); return *this; } template inline void RangeBufferAccessC::Swap(IndexC i1, IndexC i2) { DataT d = (*this)[i1]; (*this)[i1] = (*this)[i2]; (*this)[i2] = d; } template inline void RangeBufferAccessC::Attach(const RangeBufferAccessC & b) { *this=b; } template inline void RangeBufferAccessC::Attach(const BufferAccessC & b, const IndexRangeC & r) { ((BufferAccessC &)(*this)) = b - r.Min(); range=r; } template inline const RangeBufferAccessC &RangeBufferAccessC::operator+=(SizeT i) { buff -= i; range += i; return *this; } template inline RangeBufferAccessC RangeBufferAccessC::operator+(SizeT i) const { return RangeBufferAccessC(buff - i, range + i); } template inline void RangeBufferAccessC::ShiftIndexes(IndexC offset) { ((BufferAccessC &) *this) += offset.V(); range -= offset.V(); } template RangeBufferAccessC RangeBufferAccessC::Copy(void) const { if (IsEmpty()) return RangeBufferAccessC(); DataT * bp = new DataT[Size()]; RangeBufferAccessC b(bp, range); const DataT *at = DataStart(); DataT *at2 = b.DataStart(); const DataT *endOfRow = &at[range.Size()]; for(;at != endOfRow;at++,at2++) *at2 = *at; return b; } template void RangeBufferAccessC::Fill(const DataT & d) { DataT *at = DataStart(); DataT *endOfRow = &at[range.Size()]; for(;at != endOfRow;at++) *at = d; } template void RangeBufferAccessC::Reverse() { DataT *at = &((*this)[IMin()]); DataT *end = &((*this)[IMax()]); DataT tmp; for(;at < end;at++,end--) { tmp = *at; *at = *end; *end = tmp; } } template RangeBufferAccessC RangeBufferAccessC::BufferFrom(IndexC first) { RavlAssert(Range().Contains(first)); return RangeBufferAccessC(&((*this)[first]),IndexRangeC(first,Range().Max())); } template RangeBufferAccessC RangeBufferAccessC::BufferFrom(IndexC first,UIntT len) { RavlAssert(Range().Contains(first) && Range().Contains((first + len) - 1)); return RangeBufferAccessC(&((*this)[first]),IndexRangeC(first,(first+len)-1)); } } #endif