This file is indexed.

/usr/include/CLAM/CircularBuffer.hxx is in libclam-dev 1.4.0-6.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
/*
 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
 *                         UNIVERSITAT POMPEU FABRA
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef	_CircularBuffer_
#define _CircularBuffer_

#include "Array.hxx"
#include "DataTypes.hxx"
#include "Err.hxx"

namespace CLAM
{


	/**
	 * Generic container-like circular buffer class.
	 * It can be pre-allocated to a certain capacity and 
	 * resized at any time (not while doing concurrent 
	 * reading/writing). This circular buffer is not thread-safe.
	 * You can either read/write single elements at a time or 
	 * read/write in blocks. The size of these blocks is specified 
	 * the read size and write size respectively.
	 * The circular buffer must be initialized (by calling Init()) 
	 * prior to being used. An initial read offset can be specified 
	 * which indicates the index at which the buffer starts reading 
	 * after it's been initialized (default: 0).
	 */
	template <class T> class CircularBuffer
	{
	protected: 
		Array<T> mBuffer;
		TSize mLogicalSize;
		TSize mReadSize;
		TSize mWriteSize;
		TSize mWriteIndex; // XXX: might want these mutable and read-like methods declared const
		TSize mReadIndex; // XXX: might want these mutable and read-like methods declared const
		TSize mInitialReadOffset;
		TSize mInitialWriteOffset;
	
	public:
	 
		/**
		 * Default constructor.
		 * Read and write indices will be initialized to 0. Read and write 
		 * sizes will be initialized to 1. Initial read and write offsets will 
		 * be initialized to 0. The buffer size will be 0.
		 */
		CircularBuffer() : mBuffer()
		{
			mWriteIndex = 0;				
			mReadIndex = 0;
			mReadSize = mWriteSize = 1;
			mInitialReadOffset = 0;
			mInitialWriteOffset = 0;
			SetBufferSize(0);
			mLogicalSize = 0;
		}
		
		/**
		 * Constructor which initializes the buffer to a certain capacity.
		 * This capacity (or buffer size) can be arbitrary (not power-of-two, 
		 * etc), but must be greater than 0.
		 */
		CircularBuffer(TSize bufferSize) : mBuffer(bufferSize)
		{
			CLAM_ASSERT(bufferSize > 0, "CircularBuffer:CircularBuffer: BufferSize has to be larger than zero");
			SetBufferSize(bufferSize);
			mWriteIndex = 0;				
			mReadIndex = 0;
			mReadSize = mWriteSize = 1;
			mInitialReadOffset = 0;
			mInitialWriteOffset = 0;
			mLogicalSize = 0;
		}

		// Methods for setting up the buffer: -------------------------------------------

		/**
		 * Returns the circular buffer's buffer size.
		 */
		TSize GetBufferSize() const
		{
			return mBuffer.Size()-GetReadSize();
		}

		/**
		 * Resizes the buffer to a new capacity (or buffer size). 
		 * This capacity (or buffer size) can be arbitrary (not power-of-two, 
		 * etc). If size is set to 0 or less the buffer will be deallocated.
		 */
		void SetBufferSize(TSize size)
		{
			mBuffer.Resize(size+GetReadSize());
			mBuffer.SetSize(size+GetReadSize());
			InitPointers();
		}

		/**
		 * Returns the index of the element that the buffer 
		 * is about to write (ie. on the next write-like call).
		 */
		TSize GetWriteIndex() const
		{
			return mWriteIndex;
		}

		/**
		 * Returns the index of the element that the buffer 
		 * is about to read (ie. on the next read-like call).
		 */
		TSize GetReadIndex() const
		{
			return mReadIndex;
		}

		/**
		 * Returns the initial read offset. That is, the 
		 * index at which the buffer starts reading after it 
		 * has been initialized.
		 */
		TSize GetInitialReadOffset() const
		{
			return mInitialReadOffset;
		}

		/**
		 * Sets the initial read offset. That is, the
		 * index at which the buffer starts reading after it 
		 * has been initialized. Init() or InitPointers() should be 
		 * called after this method.
		 */
		void SetInitialReadOffset(TSize size)
		{
			CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
				"CircularBuffer:SetInitialReadOffset: InitialReadOffset has to be larger than zero");
			mInitialReadOffset = size;
		}

		/**
		 * Returns the initial write offset. That is, the 
		 * index at which the buffer starts writeing after it 
		 * has been initialized.
		 */
		TSize GetInitialWriteOffset() const
		{
			return mInitialWriteOffset;
		}

		/**
		 * Sets the initial write offset. That is, the
		 * index at which the buffer starts writeing after it 
		 * has been initialized. Init() or InitPointers() should be 
		 * called after this method.
		 */
		void SetInitialWriteOffset(TSize size)
		{
			CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
				"CircularBuffer:SetInitialWriteOffset: InitialWriteOffset has to be larger than zero");
			mInitialWriteOffset = size;
		}

		// Methods for data acces: ------------------------------------------------------
	
		/**
		 * Initializes the buffer by setting all elements to 0 and 
		 * making sure read/write indices are set correctly (taking 
		 * into account initial read/write offsets).
		 */
		void Init()
		{
			SetBufferToZero();
			InitPointers();
		}

		/**
		 * Sets all elements in circular buffer to zero.
		 */
		void SetBufferToZero()
		{
			T *pBuffer;
			pBuffer = mBuffer.GetPtr();
			memset(pBuffer, 0, GetBufferSize()*sizeof(T));
		}

		/**
		 * Initializes read/write indices (taking into account 
		 * initial read/write offsets).
		 */
		void InitPointers()
		{
			if(mInitialReadOffset < 0)
				mReadIndex = GetBufferSize() + mInitialReadOffset;
			else
				mReadIndex = mInitialReadOffset;
			if(mInitialWriteOffset < 0)
				mWriteIndex = GetBufferSize() + mInitialWriteOffset;
			else
				mWriteIndex = mInitialWriteOffset;
			mLogicalSize=0;
		}

		// Methods for reading and writing: ---------------------------------------------

		/**
		 * Reads a single element at the current read index 
		 * into element.
		 */
		void Read(T& element)
		{
			element = mBuffer[mReadIndex];
			IncreaseReadIndex();
		}

		
		void NonCopyRead(Array<T>& buffer)
		{
			TSize limit;
			if((limit=mReadIndex+mReadSize)>GetBufferSize())
			{
				//will have to use phantom zone	
				memcpy(mBuffer.GetPtr()+GetBufferSize(),mBuffer.GetPtr(),mReadSize*sizeof(T));
			}
			buffer.SetPtr(mBuffer.GetPtr()+mReadIndex,mReadSize);
			IncreaseReadIndex(mReadSize);


		}
		
		/**
		 * Reads read size number of elements starting at the 
		 * current read index into buffer. If the read size + 
		 * read index is out of bounds (ie. past the end of the buffer) 
		 * the reading will 'wrap-around'.
		 */
		void Read(T* buffer)
		{
			TSize limit;
			if((limit=mReadIndex+mReadSize)>GetBufferSize())
			{
				TSize secondHalf=limit%GetBufferSize();
				TSize firstHalf=mReadSize-secondHalf;
				memcpy(buffer,mBuffer.GetPtr()+mReadIndex,firstHalf*sizeof(T));
				memcpy(buffer+firstHalf,mBuffer.GetPtr(),secondHalf*sizeof(T));
			}
			else
			{
				memcpy(buffer,mBuffer.GetPtr()+mReadIndex,mReadSize*sizeof(T));
			}
			
			IncreaseReadIndex(mReadSize);
		}

		/**
		 * Reads read size number of elements starting at the 
		 * current read index into the array at the specified offset 
		 * (default: offset = 0). The destination array must be large 
		 * enough to hold read size number of elements at the specified 
		 * offset. If reading is out of bounds it will wrap-around.
		 * Note: define CLAM_HIGH_OPTIMIZATIONS for this function to be 
		 * efficient.
		 */
		void Read(Array<T>& in, TSize offset = 0) // XXX: maybe call in, out instead?
		{
			CLAM_ASSERT(GetReadSize() <= in.Size()+offset, "Error, input buffer is not large enough"); // XXX: maybe call the input buffer the output buffer?

#ifdef CLAM_HIGH_OPTIMIZATIONS
			Read(in.GetPtr()+offset);
#else
			for(int i=0;i<mReadSize;i++)
				Read(in[i+offset]);
#endif
		}

		/**
		 * Writes a single element at the current write index.
		 */
		void Write(const T& element)
		{
			mBuffer[mWriteIndex] = element;
			IncreaseWriteIndex();
		}

		/**
		 * Writes write size number of elements starting at the 
		 * current write index from buffer. If it must write out 
		 * of bounds, it will 'wrap-around'.
		 */
		void Write(const T* buffer)
		{
			TSize limit;
			if((limit=mWriteIndex+mWriteSize)>GetBufferSize())
			{
				TSize secondHalf=limit%GetBufferSize();
				TSize firstHalf=mWriteSize-secondHalf;
				memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,firstHalf*sizeof(T));
				memcpy(mBuffer.GetPtr(),buffer+firstHalf,secondHalf*sizeof(T));
			}
			else
			{
				memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,mWriteSize*sizeof(T));
			}
			
			IncreaseWriteIndex(mWriteSize);
		}

		/**
		 * Writes write size number of elements starting at the current 
		 * write index from the array starting at the specified offset 
		 * (default: offset = 0). The input array must have atleast write 
		 * size number of elements from the specified offset onwards.
		 * Note: define CLAM_HIGH_OPTIMIZATIONS for this method to be efficient.
		 */
		void Write(const Array<T>& in, TSize offset = 0) 
		{
			CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
#ifdef CLAM_HIGH_OPTIMIZATIONS
			Write(in.GetPtr()+offset);
#else
			for(int i=0;i<mWriteSize;i++)
				Write(in[i+offset]);
#endif
		}

		/**
		 * Does an additive write of a single element at the 
		 * current write index. It 'mixes' the old element's content 
		 * with the new one.
		 */
		void Add(const T& elem)
		{
			mBuffer[mWriteIndex] += elem;
			IncreaseWriteIndex();
		}

		/**
		 * Does an additive write of write size number of elements 
		 * at the current write index onwards from the specified 
		 * input array starting at the specified offset (default: 
		 * offset = 0) onwards.
		 * Note: not very efficient.
		 */
		void Add(const Array<T>& in, TSize offset = 0)
		{
			CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
			for(int i=0;i<mWriteSize;i++)
				Add(in[i+offset]);
			// XXX: might also want a CLAM_HIGH_OPTIMIZATIONS version of this method...
		}

		/**
		 * Increases the read index by the specified number of 
		 * elements (default: step = 1).
		 */
		void IncreaseReadIndex(TSize step = 1)
		{
			mReadIndex += step;
			mReadIndex=mReadIndex%GetBufferSize();
			mLogicalSize-=step;
			CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
		}

		/**
		 * Increases the write index by the specified number of 
		 * elements (default: step = 1).
		 */
		void IncreaseWriteIndex(TSize step = 1)
		{
			// XXX: might want to assert that step > 0
			mWriteIndex += step;
			mWriteIndex =mWriteIndex%GetBufferSize();
			mLogicalSize+=step;
			CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
		}

		/**
		 * Decreases the read index by the specified number of 
		 * elements (default: step = 1).
		 */
		void DecreaseReadIndex(TSize step = 1)
		{
			// XXX: might want to assert that step > 0
			mReadIndex -= step;
			mReadIndex =mReadIndex%GetBufferSize();
			if(mReadIndex<0) mReadIndex=GetBufferSize()+mReadIndex;
			mLogicalSize+=step;
			CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
		}

		/**
		 * Decreases the write index by the specified number of 
		 * elements (default: step = 1).
		 */
		void DecreaseWriteIndex(TSize step = 1)
		{
			// XXX: might want to assert that step > 0
			mWriteIndex -= step;
			mWriteIndex =mWriteIndex%GetBufferSize();
			if(mWriteIndex<0) mWriteIndex =GetBufferSize()+mWriteIndex ;
			mLogicalSize-=step;
			CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
		}

		/**
		 * Returns a pointer (well, reference) to the element 
		 * at the specified index. If the specified index is 
		 * out of bounds it will 'wrap-around'.
		 */
		T& GetPtrToElement(int absPos)
		{
			int index = absPos%GetBufferSize(); // XXX: unnecessary copy.
			
			return mBuffer[index];
		}
		
		// Getters and setters: ---------------------------------------------------------

		/**
		 * Returns the current read size. The read size 
		 * determines how many elements will read at once 
		 * when doing 'chunk' reads.
		 */
		TSize GetReadSize() const
		{
			return mReadSize;
		}

		/**
		 * Returns the current write size. The write size 
		 * determines how many elements will be written at once 
		 * when doing 'chunk' writes.
		 */
		TSize GetWriteSize() const
		{
			return mWriteSize;
		}

		/**
		 * Sets the read size. This read size must be greater than or 
		 * equal to 0 and less than or equal to the buffer size.
		 */
		void SetReadSize(TSize size)
		{
			CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetReadSize: ReadSize has to be larger than zero");
			TSize previousBufferSize=GetBufferSize();
			mReadSize = size;
			SetBufferSize(previousBufferSize);
		}

		/**
		 * Sets the write size. This write size must be greater than or 
		 * equal to 0 and less than or equal to the buffer size.
		 */
		void SetWriteSize(TSize size)
		{
			CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetWriteSize: WriteSize has to be larger than zero");
			mWriteSize = size;
		}
	};



}; //end of namespace

#endif //_CircularBuffer_