CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 // attributes 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 //TODO update phantom 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 } // namespace CLAM 00219 00220 #endif 00221