00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _PHANTOM_BUFFER_H
00023 #define _PHANTOM_BUFFER_H
00024
00025
00026 #include <vector>
00027 #include "Assert.hxx"
00028
00029 namespace CLAM {
00030
00031 template<class T>
00032 class PhantomBuffer
00033 {
00034 public:
00035 PhantomBuffer();
00036 T* Read(unsigned int pos, unsigned int size);
00037
00043 void Touch(unsigned int pos, unsigned int size);
00044
00050 void Write(unsigned int pos, unsigned int size,const T* data);
00051
00052 unsigned LogicalSize() const {return mLogicalSize;}
00053
00054 unsigned int PhantomSize() const { return mBuffer.size() - mLogicalSize; }
00055
00056 void Resize(unsigned int size,
00057 unsigned int phantom,
00058 unsigned int insert_pos);
00059
00066 void FulfilsInvariant() const;
00067
00068 private:
00073 void UpdatePhantom(unsigned int pos, unsigned int size);
00078 void UpdateBeginning(unsigned int pos, unsigned int size);
00079
00080 unsigned int AllocatedSize() const
00081 {
00082 return mBuffer.size();
00083 }
00084
00085
00086
00087 std::vector<T> mBuffer;
00088 unsigned mLogicalSize;
00089 };
00090
00091
00092 template<class T>
00093 PhantomBuffer<T>::PhantomBuffer()
00094 : mLogicalSize(0)
00095 {}
00096
00097
00098 template<class T>
00099 void PhantomBuffer<T>::UpdatePhantom(unsigned int pos, unsigned int size)
00100 {
00101 CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(),
00102 "PhantomBuffer::UpdatePhantom():"
00103 "Requested region falls outside phantom zone");
00104 unsigned int s,d;
00105 for (s=pos, d=mLogicalSize+pos; s<pos+size; s++, d++)
00106 mBuffer[d] = mBuffer[s];
00107 }
00108
00109 template<class T>
00110 void PhantomBuffer<T>::UpdateBeginning(unsigned int pos, unsigned int size)
00111 {
00112 CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(),
00113 "PhantomBuffer::UpdateBeginning():"
00114 "Requested region falls outside beginning zone");
00115 unsigned int s,d;
00116 for (d=pos, s=mLogicalSize+pos; d<size; d++, s++)
00117 mBuffer[d] = mBuffer[s];
00118 }
00119
00120
00121 template<class T>
00122 void PhantomBuffer<T>::Resize(unsigned int newLogicalSize, unsigned int newPhantomSize, unsigned int insertionPos)
00123 {
00124 CLAM_ASSERT(insertionPos <= LogicalSize(),
00125 "PhantomBuffer::Resize(): "
00126 "Insertion position can not be greater than previous size.");
00127 CLAM_ASSERT(newPhantomSize <= newLogicalSize,
00128 "PhantomBuffer::Resize(): Phantom Size can not be greater than size.");
00129
00130
00131 if ( newLogicalSize <= LogicalSize() )
00132 return;
00133
00134 CLAM_ASSERT(newPhantomSize >= PhantomSize(),
00135 "PhantomBuffer::Resize(): PhantomSize can not be decreased.");
00136
00137 unsigned int logicalElementsToInsert = newLogicalSize - LogicalSize();
00138 unsigned int phantomElementsToInsert = newPhantomSize - PhantomSize();
00139
00140 typename std::vector<T>::iterator it = mBuffer.begin();
00141 it += insertionPos;
00142 mBuffer.insert(it, logicalElementsToInsert, T());
00143
00144 mBuffer.insert( mBuffer.end(), phantomElementsToInsert, T());
00145
00146
00147 mLogicalSize = newLogicalSize;
00148 }
00149
00150
00151 template<class T>
00152 T* PhantomBuffer<T>::Read(unsigned int pos, unsigned int size)
00153 {
00154 CLAM_DEBUG_ASSERT( (pos+size-1) <= ( AllocatedSize() ),
00155 "PhantomBuffer::Read(): Position outside bounds");
00156 return &mBuffer[pos];
00157 }
00158
00159
00160 template<class T>
00161 void PhantomBuffer<T>::Touch(unsigned int pos, unsigned int size)
00162 {
00163 CLAM_DEBUG_ASSERT( (pos+size) <= ( AllocatedSize() ),
00164 "PhantomBuffer::Write(): Position outside bounds");
00165 unsigned int writen_area_end = pos+size;
00166
00167 if (writen_area_end > mLogicalSize)
00168 {
00169 unsigned int update_start;
00170 if (mLogicalSize > pos)
00171 update_start = 0;
00172 else
00173 update_start = pos-mLogicalSize;
00174 UpdateBeginning(update_start, writen_area_end - mLogicalSize - update_start);
00175 }
00176 else if ( pos < PhantomSize() )
00177 {
00178 int update_end;
00179 if (PhantomSize() < writen_area_end )
00180 update_end = PhantomSize();
00181 else
00182 update_end = writen_area_end;
00183 UpdatePhantom(pos,update_end-pos);
00184 }
00185 }
00186
00187
00188 template<class T>
00189 void PhantomBuffer<T>::Write(unsigned int pos, unsigned int size,const T* data)
00190 {
00191 CLAM_DEBUG_ASSERT( (pos+size) <= ( AllocatedSize() ),
00192 "PhantomBuffer::Write(): Position outside bounds");
00193 unsigned int s,d;
00194
00195 for (s=0, d=pos; s<size; s++, d++)
00196 mBuffer[d] = data[s];
00197 Touch(pos,size);
00198 }
00199
00200
00201 template<class T>
00202 void PhantomBuffer<T>::FulfilsInvariant() const
00203 {
00204 CLAM_ASSERT(mBuffer.size() == AllocatedSize(),
00205 "PhantomBuffer<T>::FulfilsInvariant(): "
00206 "internal vector size unconsistency");
00207 CLAM_ASSERT(PhantomSize() <= mLogicalSize,
00208 "PhantomBuffer<T>::FulfilsInvariant(): "
00209 "Phantom size biger than logical size");
00210 unsigned int i;
00211 for (i=0; i<PhantomSize(); i++)
00212 CLAM_ASSERT(mBuffer[i] == mBuffer[i+mLogicalSize],
00213 "PhantomBuffer<T>::FulfilsInvariant(): "
00214 "Phantom data is unconsistent!");
00215
00216 }
00217
00218 }
00219
00220 #endif
00221