|
CLAM-Development
1.3
|
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 <iostream> 00028 #include "Assert.hxx" 00029 00030 namespace CLAM { 00031 00032 template<class T> 00033 class PhantomBuffer 00034 { 00035 public: 00036 PhantomBuffer(); 00037 T* Read(unsigned int pos, unsigned int size); 00038 00044 void Touch(unsigned int pos, unsigned int size); 00045 00051 void Write(unsigned int pos, unsigned int size,const T* data); 00052 00053 unsigned LogicalSize() const {return mLogicalSize;} 00054 00055 unsigned int PhantomSize() const { return mBuffer.size() - mLogicalSize; } 00056 00057 void Resize(unsigned int size, 00058 unsigned int phantom, 00059 unsigned int insert_pos); 00060 00067 void FulfilsInvariant() const; 00068 00069 private: 00074 void UpdatePhantom(unsigned int pos, unsigned int size); 00079 void UpdateBeginning(unsigned int pos, unsigned int size); 00080 00081 unsigned int AllocatedSize() const 00082 { 00083 return mBuffer.size(); 00084 } 00085 00086 00087 // attributes 00088 std::vector<T> mBuffer; 00089 unsigned mLogicalSize; 00090 }; 00091 00092 00093 template<class T> 00094 PhantomBuffer<T>::PhantomBuffer() 00095 : mLogicalSize(0) 00096 {} 00097 00098 00099 template<class T> 00100 void PhantomBuffer<T>::UpdatePhantom(unsigned int pos, unsigned int size) 00101 { 00102 CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(), 00103 "PhantomBuffer::UpdatePhantom():" 00104 "Requested region falls outside phantom zone"); 00105 unsigned int s,d; 00106 for (s=pos, d=mLogicalSize+pos; s<pos+size; s++, d++) 00107 mBuffer[d] = mBuffer[s]; 00108 } 00109 00110 template<class T> 00111 void PhantomBuffer<T>::UpdateBeginning(unsigned int pos, unsigned int size) 00112 { 00113 CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(), 00114 "PhantomBuffer::UpdateBeginning():" 00115 "Requested region falls outside beginning zone"); 00116 unsigned int s,d; 00117 for (d=pos, s=mLogicalSize+pos; d<size; d++, s++) 00118 mBuffer[d] = mBuffer[s]; 00119 } 00120 00121 00122 template<class T> 00123 void PhantomBuffer<T>::Resize(unsigned int newLogicalSize, unsigned int newPhantomSize, unsigned int insertionPos) 00124 { 00125 CLAM_ASSERT(insertionPos <= LogicalSize(), 00126 "PhantomBuffer::Resize(): " 00127 "Insertion position can not be greater than previous size."); 00128 CLAM_ASSERT(newPhantomSize <= newLogicalSize, 00129 "PhantomBuffer::Resize(): Phantom Size can not be greater than size."); 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
1.7.6.1