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...
T | 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...
T | 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

  T | Type to use for the array.

## Constructor & Destructor Documentation

## ◆ CircularBuffer() [1/4]

RJCP.Datastructures.CircularBuffer< T >.CircularBuffer | ( | int | capacity | ) |

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

Parameters

  capacity | Size of array to allocate.

## ◆ CircularBuffer() [2/4]

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

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

  array | Array (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

  array | Array (zero indexed) to allocate.
  count | Length 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

  array | Array (zero indexed) to allocate.
  offset | Offset of first byte in the array.
  count | Length 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

  array | Array 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

  array | Array to copy from.
  offset | Offset to copy data from.
  count | Length 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

  buffer | Buffer 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

  buffer | Buffer to append.
  count | Number 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

  buffer | Buffer to append.
  count | Number of bytes to append.
  offset | Offset 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 | ( | T | element | ) |

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

Parameters

  element | The 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

  length | Amount 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

  array | The 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

  array | The array to copy the data to.
  offset | Offset into the array to copy to.
  count | Amount 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

  offset | Offset.

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

  array | The 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

  array | The array to copy the data to.
  offset | Offset into the array to copy to.
  count | Amount 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()

T RJCP.Datastructures.CircularBuffer< T >.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

  length | The 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()

void RJCP.Datastructures.CircularBuffer< T >.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

  length | The 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

  index | Index 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

T [] RJCP.Datastructures.CircularBuffer< T >.Array
| get

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

int RJCP.Datastructures.CircularBuffer< T >.End
| get

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

int RJCP.Datastructures.CircularBuffer< T >.Free
| get

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

int RJCP.Datastructures.CircularBuffer< T >.Length
| get

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

int RJCP.Datastructures.CircularBuffer< T >.Start
| get

Get start index into array where data begins.

## ◆ this[int index]

T RJCP.Datastructures.CircularBuffer< T >.this[int index]
| get set

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

Parameters

  index | Index 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:

- C:/PROJECTS/C#/BSL430.NET/src/BSL430.NET/Library/serialportstream/2.1.4/src/Datastructures/CircularBuffer.cs