BSL430.NET  1.2.1
Public Member Functions | Properties | List of all members
RJCP.Datastructures.CircularBuffer< T > Class Template Reference

A simple datastructure to manage an array as a circular buffer. More...

Public Member Functions

 CircularBuffer (int capacity)
 Allocate an Array of type T[] of particular capacity. More...
 
 CircularBuffer (T[] array)
 Circular buffer based on an already allocated array. More...
 
 CircularBuffer (T[] array, int count)
 Circular buffer based on an already allocated array. More...
 
 CircularBuffer (T[] array, int offset, int count)
 Circular buffer based on an already allocated array. More...
 
int ToArrayIndex (int index)
 Convert an index from the start of the data to read to an array index. More...
 
int GetReadBlock (int offset)
 Given an offset, calculate the length of data that can be read until the end of the block. More...
 
void Consume (int length)
 Consume array elements (freeing space from the beginning) updating pointers in the circular buffer. More...
 
void Produce (int length)
 Produce bytes (allocating space at the end) updating pointers in the circular buffer. More...
 
void Revert (int length)
 Revert elements produced to the end of the circular buffer. More...
 
void Reset ()
 Reset the pointers in the circular buffer, effectively noting the circular buffer as empty. More...
 
int Append (T[] array)
 Copy data from array to the end of this circular buffer and update the length. More...
 
int Append (T[] array, int offset, int count)
 Copy data from array to the end of this circular buffer and update the length. More...
 
int Append (CircularBuffer< T > buffer)
 Copy data from the circular buffer to the end of this circular buffer. More...
 
int Append (CircularBuffer< T > buffer, int count)
 Copy data from the circular buffer to the end of this circular buffer. More...
 
int Append (CircularBuffer< T > buffer, int offset, int count)
 Copy data from the circular buffer to the end of this circular buffer. More...
 
int Append (T element)
 Append a single element to the end of the Circular Buffer. More...
 
Pop ()
 Retrieve a single element from the Circular buffer and consume it. More...
 
int MoveTo (T[] array)
 Copy data from the circular buffer to the array and then consume the data from the circular buffer. More...
 
int MoveTo (T[] array, int offset, int count)
 Copy data from the circular buffer to the array and then consume the data from the circular buffer. More...
 
int CopyTo (T[] array)
 Copy data from the circular buffer to the array. More...
 
int CopyTo (T[] array, int offset, int count)
 Copy data from the circular buffer to the array. More...
 

Properties

int Start [get]
 Get start index into array where data begins. More...
 
int End [get]
 Get end index into array where data ends. More...
 
int Length [get]
 Get total length of data in array. More...
 
int Free [get]
 Get total free data in array. More...
 
int Capacity [get]
 Get the total capacity of the array. More...
 
int WriteLength [get]
 Get length of continuous available space from the current position to the end of the array or until the buffer is full. More...
 
int ReadLength [get]
 Get the length of the continuous amount of data that can be read in a single copy operation from the start of the buffer data. More...
 
T [] Array [get]
 Get the reference to the array that's allocated. More...
 
this[int index] [get, set]
 Access an element in the array using the Start as index 0. More...
 

Detailed Description

A simple datastructure to manage an array as a circular buffer.

This class provides simple methods for abstracting a circular buffer. A circular buffer allows for faster access of data by avoiding potential copy operations for data that is at the beginning.

Stream data structures can benefit from this data structure by allocating a single block on the heap of an arbitrary size. If the stream is long-lived the benefits are larger. In the .NET framework (4.0 and earlier), all allocations of data structures that are 80kb and larger are automatically allocated on the heap. The heap is not garbage collected like smaller objects. Instead, new elements are added to the heap in an incremental fashion. It is theoretically possible to exhaust all memory in an application by allocating and deallocating regularly on a heap if such a new heap element requires space and there is not a single block large enough. By using the CircularBuffer<T> with the type T as byte, you can preallocate a buffer for a stream of any reasonable size (as a simple example 5MB). That block is allocated once and remains for the lifetime of the stream. No time will be allocated for compacting or garbage collection.

Template Parameters
TType to use for the array.

Constructor & Destructor Documentation

◆ CircularBuffer() [1/4]

Allocate an Array of type T[] of particular capacity.

Parameters
capacitySize of array to allocate.

◆ CircularBuffer() [2/4]

Circular buffer based on an already allocated array.

The array is used as the storage for the circular buffer. No copy of the array is made. The initial index in the circular buffer is index 0 in the array. The array is assumed to be completely used (i.e. it is initialised with zero bytes Free).

Parameters
arrayArray (zero indexed) to allocate.

◆ CircularBuffer() [3/4]

RJCP.Datastructures.CircularBuffer< T >.CircularBuffer ( T []  array,
int  count 
)

Circular buffer based on an already allocated array.

The array is used as the storage for the circular buffer. No copy of the array is made, only a reference. The initial index in the array is 0. The value count sets the initial length of the array. So an initial count of zero would imply an empty circular buffer.

Parameters
arrayArray (zero indexed) to allocate.
countLength of data in array, beginning from offset 0.

◆ CircularBuffer() [4/4]

RJCP.Datastructures.CircularBuffer< T >.CircularBuffer ( T []  array,
int  offset,
int  count 
)

Circular buffer based on an already allocated array.

The array is used as the storage for the circular buffer. No copy of the array is made, only a reference. The offset is defined to be the first entry in the circular buffer. This may be any value from zero to the last index (Array.Length - 1). The value count is the amount of data in the array, and it may cause wrapping (so that by setting offset near the end, a value of count may be set so that data can be considered at the end and beginning of the array given).

Parameters
arrayArray (zero indexed) to allocate.
offsetOffset of first byte in the array.
countLength of data in array, wrapping to the start of the array.

Member Function Documentation

◆ Append() [1/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( T []  array)

Copy data from array to the end of this circular buffer and update the length.

Parameters
arrayArray to copy from.
Returns
Number of bytes copied.

Data is copied to the end of the Circular Buffer. The amount of data that could be copied is dependent on the amount of free space. The result is the number of elements from the buffer array that is copied into the Circular Buffer. Pointers in the circular buffer are updated appropriately.

◆ Append() [2/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( T []  array,
int  offset,
int  count 
)

Copy data from array to the end of this circular buffer and update the length.

Parameters
arrayArray to copy from.
offsetOffset to copy data from.
countLength of data to copy.
Returns
Number of bytes copied.

Data is copied to the end of the Circular Buffer. The amount of data that could be copied is dependent on the amount of free space. The result is the number of elements from the buffer array that is copied into the Circular Buffer. Pointers in the circular buffer are updated appropriately.

◆ Append() [3/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( CircularBuffer< T >  buffer)

Copy data from the circular buffer to the end of this circular buffer.

Parameters
bufferBuffer to append.
Returns
Amount of data appended.

Data is copied to the end of the Circular Buffer. The amount of data that could be copied is dependent on the amount of free space. The result is the number of elements from the buffer array that is copied into the Circular Buffer. Pointers in the circular buffer are updated appropriately.

◆ Append() [4/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( CircularBuffer< T >  buffer,
int  count 
)

Copy data from the circular buffer to the end of this circular buffer.

Parameters
bufferBuffer to append.
countNumber of bytes to append.
Returns
Amount of data appended.

Data is copied to the end of the Circular Buffer. The amount of data that could be copied is dependent on the amount of free space. The result is the number of elements from the buffer array that is copied into the Circular Buffer. Pointers in the circular buffer are updated appropriately.

◆ Append() [5/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( CircularBuffer< T >  buffer,
int  offset,
int  count 
)

Copy data from the circular buffer to the end of this circular buffer.

Parameters
bufferBuffer to append.
countNumber of bytes to append.
offsetOffset into the buffer to start appending.
Returns
Amount of data appended.

Data is copied to the end of the Circular Buffer. The amount of data that could be copied is dependent on the amount of free space. The result is the number of elements from the buffer array that is copied into the Circular Buffer. Pointers in the circular buffer are updated appropriately.

◆ Append() [6/6]

int RJCP.Datastructures.CircularBuffer< T >.Append ( element)

Append a single element to the end of the Circular Buffer.

Parameters
elementThe element to add at the end of the buffer.
Returns
Amount of data appended. 1 if successful, 0 if no space available.

◆ Consume()

void RJCP.Datastructures.CircularBuffer< T >.Consume ( int  length)

Consume array elements (freeing space from the beginning) updating pointers in the circular buffer.

This method advances the internal pointers for Start based on the length that should be consumed. The pointer End does not change. It is important that this method does not Reset() the buffer in case that all data is consumed. A common scenario with Streams is to write into the buffer using asynchronous I/O. If a Reset() occurs during an asynchronous I/O ReadFile(), the End pointer is also changed, so that when a Produce() occurs on completion of the ReadFile() operation, the pointers are updated, but not using the pointers before the Reset(). No crash would occur (so long as the underlying array is pinned), but data corruption would occur if this method were not used in this particular scenario.

Parameters
lengthAmount of data to consume.

◆ CopyTo() [1/2]

int RJCP.Datastructures.CircularBuffer< T >.CopyTo ( T []  array)

Copy data from the circular buffer to the array.

Parameters
arrayThe array to copy the data to.
Returns
The number of bytes that were copied.

Data is copied from the first element in the array, up to the length of the array. The data from the Circular Buffer is not consumed. You must do this yourself. Else use the MoveTo() method.

◆ CopyTo() [2/2]

int RJCP.Datastructures.CircularBuffer< T >.CopyTo ( T []  array,
int  offset,
int  count 
)

Copy data from the circular buffer to the array.

Parameters
arrayThe array to copy the data to.
offsetOffset into the array to copy to.
countAmount of data to copy to.
Returns
The number of bytes that were copied.

Data is copied from the circular buffer into the array specified, at the offset given. The data from the Circular Buffer is not consumed. You must do this yourself. Else use the MoveTo() method.

◆ GetReadBlock()

int RJCP.Datastructures.CircularBuffer< T >.GetReadBlock ( int  offset)

Given an offset, calculate the length of data that can be read until the end of the block.

Similar to the property ReadLength, this function takes an argument offset which is used to determine the length of data that can be read from that offset, until either the end of the block, or the end of the buffer.

This function is useful if you want to read a block of data, not starting from the offset 0 (and you don't want to consume the data before hand to reach an offset of zero).

The example below, will calculate a checksum from the third byte in the block for the length of data. If the block to read from offset 3 can be done in one operation, it will do so. Else it must be done in two operations, first from offset 3 to the end, then from offset 0 for the remaining data.

UInt16 crc; if (buffer.GetReadBlock(3) >= length - 3) { crc = crc16.Compute(buffer.Array, buffer.ToArrayIndex(3), length - 3); } else { crc = crc16.Compute(buffer.Array, buffer.ToArrayIndex(3), buffer.ReadLength - 3); crc = crc16.Compute(crc, buffer.Array, 0, length - buffer.ReadLength); }

Parameters
offsetOffset.
Returns
Length.

◆ MoveTo() [1/2]

int RJCP.Datastructures.CircularBuffer< T >.MoveTo ( T []  array)

Copy data from the circular buffer to the array and then consume the data from the circular buffer.

Data is copied to the first element in the array, up to the length of the array.

Parameters
arrayThe array to copy the data to.
Returns
The number of bytes that were moved.

◆ MoveTo() [2/2]

int RJCP.Datastructures.CircularBuffer< T >.MoveTo ( T []  array,
int  offset,
int  count 
)

Copy data from the circular buffer to the array and then consume the data from the circular buffer.

Parameters
arrayThe array to copy the data to.
offsetOffset into the array to copy to.
countAmount of data to copy to.
Returns
The number of bytes that were moved.

This method is very similar to the CopyTo(T[], int, int) method, but it will also consume the data that was copied also.

◆ Pop()

Retrieve a single element from the Circular buffer and consume it.

Returns
The value at index 0.

◆ Produce()

void RJCP.Datastructures.CircularBuffer< T >.Produce ( int  length)

Produce bytes (allocating space at the end) updating pointers in the circular buffer.

Parameters
lengthThe number of bytes to indicate that have been added from the index End to the end of the array and possibly again from the start of the array if overlapped.

◆ Reset()

Reset the pointers in the circular buffer, effectively noting the circular buffer as empty.

◆ Revert()

void RJCP.Datastructures.CircularBuffer< T >.Revert ( int  length)

Revert elements produced to the end of the circular buffer.

Parameters
lengthThe number of bytes to remove from the end of the array, moving the End property to the left, leaving the Start property untouched.

This method can be used to remove data that has been added to the end of the circular buffer. When using this data structure for streams, you would not use this property to ensure consistency of your stream (the Read operation would consume from your circular buffer and Write would produce data to your circular buffer.

◆ ToArrayIndex()

int RJCP.Datastructures.CircularBuffer< T >.ToArrayIndex ( int  index)

Convert an index from the start of the data to read to an array index.

Parameters
indexIndex in circular buffer, where an index of 0 is equivalent to the Start property.
Returns
Index in array that can be used in array based operations.

Property Documentation

◆ Array

Get the reference to the array that's allocated.

This property allows you to access the content of the data in the circular buffer in an efficient manner. You can then use this property along with Start, ReadLength, End and WriteLength for knowing where in the buffer to read and write.

◆ Capacity

int RJCP.Datastructures.CircularBuffer< T >.Capacity
get

Get the total capacity of the array.

Get the total number of elements allocated for the underlying array of the circular buffer. The following rule applies: Length + Free = Capacity.

◆ End

Get end index into array where data ends.

This property is useful to know from what element in the underlying array that data can be written to.

◆ Free

Get total free data in array.

Returns the total amount of free elements in the circular buffer. The following rule applies: Length + Free = Capacity.

◆ Length

Get total length of data in array.

Returns the amount of allocated data in the circular buffer. The following rule applies: Length + Free = Capacity.

◆ ReadLength

int RJCP.Datastructures.CircularBuffer< T >.ReadLength
get

Get the length of the continuous amount of data that can be read in a single copy operation from the start of the buffer data.

This function is useful if you need to pass the array to another function that will use the contents of the array. You would pass Start as the offset for reading data and ReadLength as the count. Then based on the amount of data operated on, you would free space with Consume(ReadLength).

◆ Start

Get start index into array where data begins.

◆ this[int index]

T RJCP.Datastructures.CircularBuffer< T >.this[int index]
getset

Access an element in the array using the Start as index 0.

Parameters
indexIndex into the array referenced from Start.
Returns
Contents of the array.

◆ WriteLength

int RJCP.Datastructures.CircularBuffer< T >.WriteLength
get

Get length of continuous available space from the current position to the end of the array or until the buffer is full.

This function is useful if you need to pass the array to another function that will then fill the contents of the buffer. You would pass End as the offset for where writing the data should start, and WriteLength as the length of buffer space available until the end of the array buffer. After the read operation that writes in to your buffer, the array is completely full, or until the end of the array.

Such a property is necessary in case that the free space wraps around the buffer. Where below X is your stream you wish to read from, b is the circular buffer instantiated as the type CircularBuffer{T}.

c = X.Read(b.Array, b.End, b.WriteLength);
b.Produce(c);

If the property WriteLength is not zero, then there is space in the buffer to read data.


The documentation for this class was generated from the following file: