randolf.ca
1.00
Randolf Richardson's C++ classes
|
Ring buffer implementation for 8-bit bytes that's threadsafe and resizeable, and the methods are designed to be efficient in various ways, including by supporting the transfer of multiple bytes in variable quantities. More...
#include <rring>
Public Member Functions | |
rring (const size_t buffer_size) | |
Instantiate an empty ring buffer (without automatic resizing-expansions). | |
rring (const size_t buffer_size, const uint xp_max, const uint xp_play=2, const uint xp_block_size=0) | |
Instantiate an empty ring buffer (with automatic resizing-expansion policies set so the internal buffer will be re-sized to adapt to unexpected allocation needs behind-the-scenes automatically). | |
~rring () noexcept | |
Free internal memory resources, after clearing buffer's memory (if the policy indicates that it needs to be cleared). | |
rring * | append (const char *data, int len=-1) |
Add any number of characters that fit within the unused portion of the internal ring buffer. | |
rring * | append (const char data) |
Add one character to the unused portion of the internal ring buffer. | |
rring * | append (const std::string data, int len=-1) |
Add any number of characters that fit within the unused portion of the internal ring buffer. | |
rring * | append (const std::vector< char > data, int len=-1) |
Add any number of characters that fit within the unused portion of the internal ring buffer. | |
rring * | append (const std::vector< unsigned char > data, int len=-1) |
Add any number of characters that fit within the unused portion of the internal ring buffer. | |
char | at (int index) |
Array-style access to the utilized portion of the ring buffer's contents, which yields the same result as that of the at() method. | |
char * | c_str (char *data=nullptr) noexcept |
Return the contents of the ring buffer as an ASCIIZ string. | |
randolf::rline * | copy_to_rline (int len=-1, randolf::rline *data=nullptr) |
Copy a line of text into a randolf::rline object. If an EoL sequence is not detected, the data will still fill the randolf::rline object. | |
char * | data (bool defragment_flag=true) noexcept |
Returns a pointer to the underlying ring buffer's array. If the "defragment" flag is cleared then the beginning of the array may not be the same as where the data actually begins (and ends) within the buffer (see the warning hereunder). | |
rring_bam * | data_bam (rring_bam *bam=nullptr) noexcept |
Returns the lengths and addresses of available memory. There may be only one block of memory, or two, depending on whether the available memory straddles the boundary of the ring buffer. | |
rring * | data_bam_adjust (size_t head, size_t tail=0) |
Arbitrarily change the head and tail positions in the ring buffer. This is intended for use in conjunction with appending data directly to the ring buffer after the data_bam method. | |
rring * | defragment (const bool full=true) |
Reorganizes the utilized memory in the ring buffer memory by moving the tail to the beginning. Defragmentation is completed in the most efficient manner, depending on what needs to be done. If data wraps around the buffer memory, then new memory will be allocated and data will be moved to it (old memory will also be cleared if the wipe policy is in effect). | |
size_t | discard (int len=-1) noexcept |
Discard data from the ring buffer. | |
bool | empty () noexcept |
Indicates whether the ring buffer is empty. | |
std::string | get_ascii_map (int len=65, const std::string u="|", const std::string a=".") noexcept |
Obtains a one-line ASCII art depiction of a map of the ring buffer's memory usage, wherein the utilized and available portions are represented by the | (pipe) and . (period) characters, respectively. These characters are configurable and may each contain more than one character, which is particularly useful for text-mode console output in a typical Linux shell in which ANSI or AVATAR codes may be used to present these characters or sequences in different colours, although there may be other uses for this too. | |
size_t | get_available () noexcept |
Calculate the number of available entries in the ring buffer. | |
size_t | get_base_size () noexcept |
Obtains the base size of the ring buffer, regardless of how much is utilized or available, and without any of the expansion policy limits. | |
size_t | get_head () noexcept |
Obtains the position of the head in the ring buffer. | |
size_t | get_max_size () noexcept |
Obtains the potential total size of the ring buffer, including both its utilized and available portions, including the maximum limit of what the expansion policies can extend the internal ring buffer's size to. | |
size_t | get_size () noexcept |
Obtains the total size of the current ring buffer, including both its utilized and available portions. | |
size_t | get_tail () noexcept |
Obtains the position of the tail in the ring buffer. | |
size_t | get_utilized () noexcept |
Calculate the number of utilized entries in the ring buffer. | |
bool | get_wipe_policy () noexcept |
Indicate whether internal buffer's memory will be cleared by the destructor before de-allocating it (default is true upon instantiation). | |
size_t | get_xp_block_size () noexcept |
Obtain block size in expansion policy. | |
size_t | get_xp_blocks_available () noexcept |
Obtain quantity of blocks available for use in buffer ring memory expansions. | |
size_t | get_xp_blocks_utilized () noexcept |
Obtain quantity of blocks utilized utilized for buffer ring memory expansion. | |
size_t | get_xp_max () noexcept |
Obtain maximum block quantity in expansion policy. | |
size_t | get_xp_play () noexcept |
Obtain minimum quantity of blocks available before automatic expansion block reduction policy. | |
operator char * () noexcept | |
Convert the entire contents of this ring buffer to an ASCIIZ string in the form of a char* array. | |
operator std::string () noexcept | |
Convert the entire contents of this ring buffer to an std::string object. | |
operator std::vector< char > () noexcept | |
Convert the entire contents of this ring buffer to an std::vector<char> object. | |
char | operator[] (int index) |
Array-style access to the utilized portion of the ring buffer's contents, which yields the same result as that of the at() method. | |
char | peek () |
Duplicate a single character from the utilized portion of the internal ring buffer, and return it as an char primitive. | |
char * | peek_to_array (size_t len, char *data=nullptr) |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return them as a char* array. | |
std::string | peek_to_string (int len=-1, std::string data=std::string()) |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string object. | |
std::vector< char > | peek_to_vector (int len=-1, std::vector< char > data=std::vector< char >()) |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string object. | |
char | remove () |
Remove one character from the utilized portion of the internal ring buffer, and return it . | |
char * | remove_to_array (size_t len, char *data=nullptr) |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return them as a char* array. | |
std::string | remove_to_string (int len=-1, std::string data=std::string()) |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string object. | |
std::vector< char > | remove_to_vector (int len=-1, std::vector< char > data=std::vector< char >()) |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string object. | |
rring * | reverse () |
Flip the order of all entries in the ring buffer. | |
rring * | set_head (int offset, bool type=true) |
Alter the position of the internal head position, without changing any of the the pre-existing data in the underlying ring buffer. | |
rring * | set_size (const size_t len) |
Configure the total size of the ring buffer. The new size cannot be smaller than the amount of data that's already present in the ring buffer (see the get_utilized method to find out how much data is present). | |
rring * | set_tail (int offset, bool type=true) |
Alter the position of the internal tail position, without changing any of the the pre-existing data in the underlying ring buffer. | |
rring * | set_wipe_policy (const bool policy_flag) noexcept |
Specify whether the internal buffer's memory will be cleared by the destructor before de-allocating it (default is true upon instantiation). | |
rring * | set_xp_block_size (const uint xp_block_size) |
Configure the automatic expansion policy's incremental block size. | |
rring * | set_xp_max (const uint xp_max) |
Configure the automatic expansion policy's maximum number of blocks. | |
rring * | set_xp_play (const uint xp_play) noexcept |
Configure the automatic expansion policy's quantity of available blocks that must be present before attempting a reduction of ring buffer memory. | |
Friends | |
std::ostream & | operator<< (std::ostream &o, rring &c) noexcept |
Support convenient streaming usage with std::cout, std::cerr, and friends. | |
Ring buffer implementation for 8-bit bytes that's threadsafe and resizeable, and the methods are designed to be efficient in various ways, including by supporting the transfer of multiple bytes in variable quantities.
Data is stored internally as a char*
array, but a few methods are provided to also support easy interoperability with std::vector
objects since there are many scenarios where this can be helpful (and from the perspective of optimization, this eliminates the cumbersome need to utilize conversions between std::string
and std::vector
objects since, internally, we use direct access to/from std::vector
objects where needed).
Expanding and reducing ring buffer memory automatically (which is disabled by default) is a feature that's particularly useful for server daemons that process small amounts of data most of the time. For example, an SMTP, IMAP4, POP3, MEOW, FTP, HTTP, FINGER, or WHOIS server that is rqeuired to minimize per-connection memory requirements can have a line buffer that begins with 80 characters, and be configured to increase to millions on-demand that will automatically shrink back down to the minimal 80 character buffer size, hence most of the time the buffer will only utilize 80 characters, with occasional longer lines that can be rejected efficiently or handled in some other way by the daemon without the complexity of memory management and, most importantly, without having to pre-allocate larger amounts of memory "just in case" a few connections start sending long lines (such as corrupt data, buffer overflow attempts that could be part of fuzzing tests or hacking efforts, etc.).
An ASCIIZ string is a C-string (char* array) that includes a terminating null (0) character at the end.
peek_
methods to peek_to_
and remove_
methods to remove_to
, so that the intention of these methods is more easily understoodlen
parameter to various constructor, assign, and append methods for greater flexibility
|
inline |
Instantiate an empty ring buffer (without automatic resizing-expansions).
std::bad_alloc | If malloc() fails to allocate memory |
buffer_size | Size of buffer |
|
inline |
Instantiate an empty ring buffer (with automatic resizing-expansion policies set so the internal buffer will be re-sized to adapt to unexpected allocation needs behind-the-scenes automatically).
std::bad_alloc | If malloc() fails to allocate memory |
buffer_size | Size of buffer |
xp_max | Maximum possible number of expansion blocks 0 = no expansions / effectively disabling expansion (default) |
xp_play | Minimum number of available blocks before a reduction can occur |
xp_block_size | Size of expansion blocks 0 = use buffer_size (default) |
|
inlinenoexcept |
Free internal memory resources, after clearing buffer's memory (if the policy indicates that it needs to be cleared).
|
inline |
|
inline |
Add any number of characters that fit within the unused portion of the internal ring buffer.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the available free space in the ring buffer |
data | Data to add |
len | Length of data (-1 = treat data as an ASCIIZ string) |
|
inline |
Add any number of characters that fit within the unused portion of the internal ring buffer.
std::invalid_argument | If data length is -2 or below |
std::length_error | If data length is too long |
std::overflow_error | If the amount of data exceeds the available free space in the ring buffer |
data | Data to add |
len | Length of data (-1 = rely on data.length()) |
|
inline |
Add any number of characters that fit within the unused portion of the internal ring buffer.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the available free space in the ring buffer |
data | Data to add |
len | Length of data (-1 = treat data as an ASCIIZ string) |
|
inline |
Add any number of characters that fit within the unused portion of the internal ring buffer.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the available free space in the ring buffer |
data | Data to add |
len | Length of data (-1 = treat data as an ASCIIZ string) |
|
inline |
Array-style access to the utilized portion of the ring buffer's contents, which yields the same result as that of the at() method.
The first element is at index 0.
std::out_of_range | if the index is out-of-range |
index | Index of character to access (0 = first element; negative index values are calculated in reverse, starting with -1 as the final position) |
|
inlinenoexcept |
Return the contents of the ring buffer as an ASCIIZ string.
free()
'd after it's no longer needed.std::bad_alloc | If malloc() fails to allocate memory |
data | Where to store the ASCIIZ string (including terminating zero, so it is imperative that utilized() + 1 bytes be pre-allocated)nullptr = allocate the needed memory using malloc() |
|
inline |
Copy a line of text into a randolf::rline object. If an EoL sequence is not detected, the data will still fill the randolf::rline object.
std::invalid_argument | If len is less than -1 |
len | Maximum quantity of data to duplicate -1 = all data |
data | Pointer to an already-instantiated randolf::rline object to use nullptr = instantiate a new randolf::rline object (this will need to be delete 'd when it's no longer needed) |
|
inlinenoexceptADVANCED |
Returns a pointer to the underlying ring buffer's array. If the "defragment" flag is cleared then the beginning of the array may not be the same as where the data actually begins (and ends) within the buffer (see the warning
hereunder).
std::bad_alloc | If malloc() fails to allocate memory (this can only occur when the "defragment" flag is set) |
defragment_flag | Whether to defragment the data firstTRUE = fuly defragment so that data begins at position 0 (default) FALSE = don't defragment the data (this is an advanced feature that will require knowing how to use the data_bam method, and also the data_bam method if adding or removing data) |
Returns the lengths and addresses of available memory. There may be only one block of memory, or two, depending on whether the available memory straddles the boundary of the ring buffer.
This is the nearest equivalent of the data() methods provided in classes such as std::string
and std::vector
, but with the nuance of supporting the underpinnings of this ring buffer wherein the utilized portions may be stored at both the end and beginning of the buffer memory.
head
will also need to be updated accordingly, for which the data_bam_adjust method is provided. std::bad_alloc | If malloc() fails to allocate memory |
bam | Pointer to rring_bam structure (that's already been allocated)nullptr (default) = allocate memory for this structure with malloc (which will need to be free 'd when it's no longer needed) |
|
inlineADVANCED |
Arbitrarily change the head and tail positions in the ring buffer. This is intended for use in conjunction with appending data directly to the ring buffer after the data_bam method.
std::overflow_error | If either adjustment would result in causing an overflow |
head | New internal head position |
tail | New internal tail position |
|
inline |
Reorganizes the utilized memory in the ring buffer memory by moving the tail to the beginning. Defragmentation is completed in the most efficient manner, depending on what needs to be done. If data wraps around the buffer memory, then new memory will be allocated and data will be moved to it (old memory will also be cleared if the wipe policy is in effect).
A full defragmentation always results in the tail changing to position 0.
std::length_error | If the new buffer_size is less than the total quantity of utilized entries (which would result in the truncation of data) |
std::bad_alloc | If malloc() fails to allocate memory |
full | Whether to defrag when the utilized block isn't straddling the internal memory buffer boundary TRUE = always fully defragment (default) FALSE = only defragment if utilized block straddles memory boundary (this favours reducing processor overhead if all that's wanted is to have one block of memory to contend with in the BAM, hence it's also what the set_size() method uses for better performance overall because resizing most likely occurs when the need for CPU cycles are more critical, so we're doing our part by reducing our CPU load) |
|
inlinenoexcept |
Discard data from the ring buffer.
std::invalid_argument | If len is less than -1 |
len | Number of bytes to discard -1 = all utilized data that remains will be discarded (default) |
|
inlinenoexcept |
Indicates whether the ring buffer is empty.
|
inlinenoexcept |
Obtains a one-line ASCII art depiction of a map of the ring buffer's memory usage, wherein the utilized and available portions are represented by the |
(pipe) and .
(period) characters, respectively. These characters are configurable and may each contain more than one character, which is particularly useful for text-mode console output in a typical Linux shell in which ANSI
or AVATAR
codes may be used to present these characters or sequences in different colours, although there may be other uses for this too.
std::invalid_argument | If length is -2 or below |
len | Desired size of ASCII map -1 = Use size of entire ring buffer |
u | Character(s) representing utilized entries |
a | Character(s) representing available entries |
|
inlinenoexcept |
Calculate the number of available entries in the ring buffer.
|
inlinenoexceptADVANCED |
Obtains the base size of the ring buffer, regardless of how much is utilized or available, and without any of the expansion policy limits.
|
inlinenoexceptADVANCED |
Obtains the position of the head in the ring buffer.
|
inlinenoexceptADVANCED |
Obtains the potential total size of the ring buffer, including both its utilized and available portions, including the maximum limit of what the expansion policies can extend the internal ring buffer's size to.
|
inlinenoexceptADVANCED |
Obtains the total size of the current ring buffer, including both its utilized and available portions.
|
inlinenoexceptADVANCED |
Obtains the position of the tail in the ring buffer.
|
inlinenoexcept |
Calculate the number of utilized entries in the ring buffer.
|
inlinenoexceptADVANCED |
Indicate whether internal buffer's memory will be cleared by the destructor before de-allocating it (default is true
upon instantiation).
malloc()
).
|
inlinenoexceptADVANCED |
Obtain block size in expansion policy.
|
inlinenoexceptADVANCED |
Obtain quantity of blocks available for use in buffer ring memory expansions.
|
inlinenoexceptADVANCED |
Obtain quantity of blocks utilized utilized for buffer ring memory expansion.
|
inlinenoexceptADVANCED |
Obtain maximum block quantity in expansion policy.
|
inlinenoexceptADVANCED |
Obtain minimum quantity of blocks available before automatic expansion block reduction policy.
|
inline |
Duplicate a single character from the utilized portion of the internal ring buffer, and return it as an char
primitive.
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
|
inline |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return them as a char*
array.
free()
'd after it's no longer needed. std::bad_alloc | If malloc() fails to allocate memory |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Amount of data to duplicate |
data | Where to store the datanullptr = allocate the needed memory using malloc() |
|
inline |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string
object.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Amount of data to duplicate -1 = all data |
data | The previously instantiated std::string object to use (the default is to instantiate a new instance of std::string). |
|
inline |
Duplicate the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string
object.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Amount of data to duplicate -1 = all data |
data | The previously instantiated std::string object to use (the default is to instantiate a new instance of std::string). |
|
inline |
Remove one character from the utilized portion of the internal ring buffer, and return it .
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
|
inline |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return them as a char*
array.
free()
'd after it's no longer needed. std::bad_alloc | If malloc() fails to allocate memory |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Maximum quantity of data to move |
data | Where to store the datanullptr = allocate the needed memory using malloc() |
|
inline |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string
object.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Amount of data to remove -1 = all data |
data | The previously instantiated std::string object to use (the default is to instantiate a new instance of std::string). |
|
inline |
Remove the specified number of characters from the utilized portion of the internal ring buffer, and return it as an std::string
object.
std::invalid_argument | If data length is -2 or below |
std::overflow_error | If the amount of data exceeds the amount of data in the ring buffer |
len | Amount of data to remove -1 = all data |
data | The previously instantiated std::string object to use (the default is to instantiate a new instance of std::string). |
|
inline |
Flip the order of all entries in the ring buffer.
|
inlineADVANCED |
Alter the position of the internal head position, without changing any of the the pre-existing data in the underlying ring buffer.
std::overflow_error | If the new position falls beyond the internal tail position (or, in other words, it exceeds the available free space in the ring buffer) |
offset | Position adjustment (may also be negative, but only for relative type ) |
type | Type of adjustment TRUE = absolute (default) FALSE = relative ( offset may also be negative) |
|
inline |
Configure the total size of the ring buffer. The new size cannot be smaller than the amount of data that's already present in the ring buffer (see the get_utilized method to find out how much data is present).
std::overflow_error | If the new size exceeds the amount of data that's already present in the ring buffer |
len | New size of ring buffer |
|
inlineADVANCED |
Alter the position of the internal tail position, without changing any of the the pre-existing data in the underlying ring buffer.
std::overflow_error | If the new position falls beyond the internal head position (or, in other words, it exceeds the available free space in the ring buffer) |
offset | Position adjustment (may also be negative, but only for relative type ) |
type | Type of adjustment TRUE = absolute (default) FALSE = relative ( offset may also be negative) |
|
inlinenoexceptADVANCED |
Specify whether the internal buffer's memory will be cleared by the destructor before de-allocating it (default is true
upon instantiation).
malloc()
). policy_flag | TRUE = clear buffer memory in destructor FALSE = don't clear buffer memory in destructor |
|
inlineADVANCED |
Configure the automatic expansion policy's incremental block size.
std::overflow_error | If the new setting, which reduces the maximum quantity of blocks, exceeds the available memory and would otherwise result in losing some of the utilized entries |
xp_block_size | Maximum possible number of expansion blocks 0 = disable expansion policy |
|
inlineADVANCED |
Configure the automatic expansion policy's maximum number of blocks.
std::overflow_error | If the new setting, which reduces the maximum quantity of blocks, exceeds the available memory and would otherwise result in losing some of the utilized entries |
xp_max | Maximum possible number of expansion blocks 0 = disable expansion policy |
|
inlinenoexceptADVANCED |
Configure the automatic expansion policy's quantity of available blocks that must be present before attempting a reduction of ring buffer memory.
xp_play | Number of available blocks must be present before attempting reduction |
|
inlinenoexcept |
Convert the entire contents of this ring buffer to an ASCIIZ string in the form of a char*
array.
free()
'd after it's no longer needed.std::bad_alloc | If malloc() fails to allocate memory |
char*
array.
|
inlinenoexcept |
Convert the entire contents of this ring buffer to an std::string
object.
|
inlinenoexcept |
Convert the entire contents of this ring buffer to an std::vector<char>
object.
|
inline |
Array-style access to the utilized portion of the ring buffer's contents, which yields the same result as that of the at() method.
The first element is at index 0.
std::out_of_range | if the index is out-of-range |
index | Index of character to access (0 = first element; negative index values are calculated in reverse, starting with -1 as the final position) |
|
friend |
Support convenient streaming usage with std::cout, std::cerr, and friends.
o | Output stream (provided automatically by std::cout and std::cerr) |
c | Object class (matched by compiler) |