|
BSL430.NET
1.2.1
|
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... | |
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.
| T | Type to use for the array. |
| RJCP.Datastructures.CircularBuffer< T >.CircularBuffer | ( | int | capacity | ) |
Allocate an Array of type T[] of particular capacity.
| capacity | Size of array to allocate. |
| 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).
| array | Array (zero indexed) to allocate. |
| 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.
| array | Array (zero indexed) to allocate. |
| count | Length of data in array, beginning from offset 0. |
| 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).
| 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. |
| int RJCP.Datastructures.CircularBuffer< T >.Append | ( | T [] | array | ) |
Copy data from array to the end of this circular buffer and update the length.
| array | Array to copy from. |
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.
| 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.
| array | Array to copy from. |
| offset | Offset to copy data from. |
| count | Length of data to copy. |
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.
| int RJCP.Datastructures.CircularBuffer< T >.Append | ( | CircularBuffer< T > | buffer | ) |
Copy data from the circular buffer to the end of this circular buffer.
| buffer | Buffer to append. |
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.
| int RJCP.Datastructures.CircularBuffer< T >.Append | ( | CircularBuffer< T > | buffer, |
| int | count | ||
| ) |
Copy data from the circular buffer to the end of this circular buffer.
| buffer | Buffer to append. |
| count | Number of bytes to append. |
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.
| 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.
| buffer | Buffer to append. |
| count | Number of bytes to append. |
| offset | Offset into the buffer to start appending. |
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.
| int RJCP.Datastructures.CircularBuffer< T >.Append | ( | T | element | ) |
Append a single element to the end of the Circular Buffer.
| element | The element to add at the end of the buffer. |
| 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.
| length | Amount of data to consume. |
| int RJCP.Datastructures.CircularBuffer< T >.CopyTo | ( | T [] | array | ) |
Copy data from the circular buffer to the array.
| array | The array to copy the data to. |
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.
| int RJCP.Datastructures.CircularBuffer< T >.CopyTo | ( | T [] | array, |
| int | offset, | ||
| int | count | ||
| ) |
Copy data from the circular buffer to the array.
| array | The array to copy the data to. |
| offset | Offset into the array to copy to. |
| count | Amount of data to copy to. |
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.
| 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); }
| offset | Offset. |
| 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.
| array | The array to copy the data to. |
| 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.
| array | The array to copy the data to. |
| offset | Offset into the array to copy to. |
| count | Amount of data to copy to. |
This method is very similar to the CopyTo(T[], int, int) method, but it will also consume the data that was copied also.
| T RJCP.Datastructures.CircularBuffer< T >.Pop | ( | ) |
Retrieve a single element from the Circular buffer and consume it.
| void RJCP.Datastructures.CircularBuffer< T >.Produce | ( | int | length | ) |
Produce bytes (allocating space at the end) updating pointers in the circular buffer.
| 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. |
| void RJCP.Datastructures.CircularBuffer< T >.Reset | ( | ) |
Reset the pointers in the circular buffer, effectively noting the circular buffer as empty.
| void RJCP.Datastructures.CircularBuffer< T >.Revert | ( | int | length | ) |
Revert elements produced to the end of the circular buffer.
| 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.
| int RJCP.Datastructures.CircularBuffer< T >.ToArrayIndex | ( | int | index | ) |
Convert an index from the start of the data to read to an array index.
| index | Index in circular buffer, where an index of 0 is equivalent to the Start property. |
|
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.
|
get |
|
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.
|
get |
|
get |
|
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).
|
get |
Get start index into array where data begins.
|
getset |
Access an element in the array using the Start as index 0.
| index | Index into the array referenced from Start. |
|
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}.
If the property WriteLength is not zero, then there is space in the buffer to read data.
1.8.15