CLAM-Development  1.4.0
PhantomBuffer.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef _PHANTOM_BUFFER_H
23 #define _PHANTOM_BUFFER_H
24 
25 
26 #include <vector>
27 #include <iostream>
28 #include "Assert.hxx"
29 
30 namespace CLAM {
31 
32  template<class T>
34  {
35  public:
36  PhantomBuffer();
37  T* Read(unsigned int pos, unsigned int size);
38 
44  void Touch(unsigned int pos, unsigned int size);
45 
51  void Write(unsigned int pos, unsigned int size,const T* data);
52 
53  unsigned LogicalSize() const {return mLogicalSize;}
54 
55  unsigned int PhantomSize() const { return mBuffer.size() - mLogicalSize; }
56 
57  void Resize(unsigned int size,
58  unsigned int phantom,
59  unsigned int insert_pos);
60 
67  void FulfilsInvariant() const;
68 
69  private:
74  void UpdatePhantom(unsigned int pos, unsigned int size);
79  void UpdateBeginning(unsigned int pos, unsigned int size);
80 
81  unsigned int AllocatedSize() const
82  {
83  return mBuffer.size();
84  }
85 
86 
87  // attributes
88  std::vector<T> mBuffer;
89  unsigned mLogicalSize;
90  };
91 
92 
93  template<class T>
95  : mLogicalSize(0)
96  {}
97 
98 
99  template<class T>
100  void PhantomBuffer<T>::UpdatePhantom(unsigned int pos, unsigned int size)
101  {
102  CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(),
103  "PhantomBuffer::UpdatePhantom():"
104  "Requested region falls outside phantom zone");
105  unsigned int s,d;
106  for (s=pos, d=mLogicalSize+pos; s<pos+size; s++, d++)
107  mBuffer[d] = mBuffer[s];
108  }
109 
110  template<class T>
111  void PhantomBuffer<T>::UpdateBeginning(unsigned int pos, unsigned int size)
112  {
113  CLAM_DEBUG_ASSERT(pos+size <= PhantomSize(),
114  "PhantomBuffer::UpdateBeginning():"
115  "Requested region falls outside beginning zone");
116  unsigned int s,d;
117  for (d=pos, s=mLogicalSize+pos; d<size; d++, s++)
118  mBuffer[d] = mBuffer[s];
119  }
120 
121 
122  template<class T>
123  void PhantomBuffer<T>::Resize(unsigned int newLogicalSize, unsigned int newPhantomSize, unsigned int insertionPos)
124  {
125  CLAM_ASSERT(insertionPos <= LogicalSize(),
126  "PhantomBuffer::Resize(): "
127  "Insertion position can not be greater than previous size.");
128  CLAM_ASSERT(newPhantomSize <= newLogicalSize,
129  "PhantomBuffer::Resize(): Phantom Size can not be greater than size.");
130 
131  if ( newLogicalSize <= LogicalSize() )
132  return;
133 
134  CLAM_ASSERT(newPhantomSize >= PhantomSize(),
135  "PhantomBuffer::Resize(): PhantomSize can not be decreased.");
136 
137  unsigned int logicalElementsToInsert = newLogicalSize - LogicalSize();
138  unsigned int phantomElementsToInsert = newPhantomSize - PhantomSize();
139 
140  typename std::vector<T>::iterator it = mBuffer.begin();
141  it += insertionPos;
142  mBuffer.insert(it, logicalElementsToInsert, T());
143 
144  mBuffer.insert( mBuffer.end(), phantomElementsToInsert, T());
145  //TODO update phantom
146 
147  mLogicalSize = newLogicalSize;
148  }
149 
150 
151  template<class T>
152  T* PhantomBuffer<T>::Read(unsigned int pos, unsigned int size)
153  {
154  CLAM_DEBUG_ASSERT( (pos+size-1) <= ( AllocatedSize() ),
155  "PhantomBuffer::Read(): Position outside bounds");
156  return &mBuffer[pos];
157  }
158 
159 
160  template<class T>
161  void PhantomBuffer<T>::Touch(unsigned int pos, unsigned int size)
162  {
163  CLAM_DEBUG_ASSERT( (pos+size) <= ( AllocatedSize() ),
164  "PhantomBuffer::Write(): Position outside bounds");
165  unsigned int writen_area_end = pos+size;
166 
167  if (writen_area_end > mLogicalSize)
168  {
169  unsigned int update_start;
170  if (mLogicalSize > pos)
171  update_start = 0;
172  else
173  update_start = pos-mLogicalSize;
174  UpdateBeginning(update_start, writen_area_end - mLogicalSize - update_start);
175  }
176  else if ( pos < PhantomSize() )
177  {
178  int update_end;
179  if (PhantomSize() < writen_area_end )
180  update_end = PhantomSize();
181  else
182  update_end = writen_area_end;
183  UpdatePhantom(pos,update_end-pos);
184  }
185  }
186 
187 
188  template<class T>
189  void PhantomBuffer<T>::Write(unsigned int pos, unsigned int size,const T* data)
190  {
191  CLAM_DEBUG_ASSERT( (pos+size) <= ( AllocatedSize() ),
192  "PhantomBuffer::Write(): Position outside bounds");
193  unsigned int s,d;
194 
195  for (s=0, d=pos; s<size; s++, d++)
196  mBuffer[d] = data[s];
197  Touch(pos,size);
198  }
199 
200 
201  template<class T>
203  {
204  CLAM_ASSERT(mBuffer.size() == AllocatedSize(),
205  "PhantomBuffer<T>::FulfilsInvariant(): "
206  "internal vector size unconsistency");
207  CLAM_ASSERT(PhantomSize() <= mLogicalSize,
208  "PhantomBuffer<T>::FulfilsInvariant(): "
209  "Phantom size biger than logical size");
210  unsigned int i;
211  for (i=0; i<PhantomSize(); i++)
212  CLAM_ASSERT(mBuffer[i] == mBuffer[i+mLogicalSize],
213  "PhantomBuffer<T>::FulfilsInvariant(): "
214  "Phantom data is unconsistent!");
215 
216  }
217 
218 } // namespace CLAM
219 
220 #endif
221