#ifndef BUFFER_H
#define BUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
// standard C includes
#include <stdint.h>
#include <stddef.h>
// resizeable buffer structure type definition
typedef struct buffer_s
{
uint8_t *bytes; // buffer data, mallocated
size_t size; // buffer size in bytes (i.e byte length of data)
} buffer_t;
// function prototypes
#define Buffer_Initialize(buffer) (memset ((buffer), 0, sizeof (buffer_t)), 1)
#define Buffer_InitWithSize(buffer,size) (Buffer_Initialize ((buffer)), Buffer_Append ((buffer), NULL, (size)))
#define Buffer_InitWithCString(buffer,data_string) (Buffer_Initialize ((buffer)), Buffer_Append ((buffer), (data_string), strlen ((data_string))))
#define Buffer_InitWithFormattedCString(buffer,fmt_string,...) (Buffer_Initialize ((buffer)), Buffer_AppendFormattedCString ((buffer), (fmt_string), __VA_ARGS__))
#define Buffer_InitWithByteArray(buffer,data_array) (Buffer_Initialize ((buffer)), Buffer_Append ((buffer), (data_array), sizeof ((data_array)) - 1)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_InitWithData(buffer,data,data_size) (Buffer_Initialize ((buffer)), Buffer_Append ((buffer), (data), (data_size)))
#define Buffer_InitWithBuffer(buffer,data_buffer) (Buffer_Initialize ((buffer)), Buffer_Append ((buffer), (data_buffer)->bytes, (data_buffer)->size))
void Buffer_Forget (buffer_t *buffer);
int Buffer_Reset (buffer_t *buffer);
#define Buffer_ResetWithData(buffer,data,data_size) (Buffer_Reset ((buffer)), Buffer_Append ((buffer), (data), (data_size)))
#define Buffer_ResetWithCString(buffer,data_string) (Buffer_Reset ((buffer)), Buffer_Append ((buffer), (data_string), strlen ((data_string))))
#define Buffer_ResetWithFormattedCString(buffer,fmt_string,...) (Buffer_Reset ((buffer)), Buffer_AppendFormattedCString ((buffer), (fmt_string), __VA_ARGS__))
#define Buffer_ResetWithByteArray(buffer,data_array) (Buffer_Reset ((buffer)), Buffer_Append ((buffer), (data_array), sizeof ((data_array)) - 1)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ResetWithBuffer(buffer,data_buffer) (Buffer_Reset ((buffer)), Buffer_Append ((buffer), (data_buffer)->bytes, (data_buffer)->size))
int Buffer_Append (buffer_t *buffer, const void *data, const size_t data_size);
#define Buffer_AppendCString(buffer,data_string) Buffer_Append ((buffer), (data_string), strlen ((data_string)))
#define Buffer_AppendByteArray(buffer,data_array) Buffer_Append ((buffer), (data_array), sizeof ((data_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_AppendBuffer(buffer,data_buffer) Buffer_Append ((buffer), (data_buffer)->bytes, (data_buffer)->size)
int Buffer_AppendFormattedCString (buffer_t *buffer, const char *fmt_string, ...);
int Buffer_Prepend (buffer_t *buffer, const void *data, const size_t data_size);
#define Buffer_PrependCString(buffer,data_string) Buffer_Prepend ((buffer), (data_string), strlen ((data_string)))
#define Buffer_PrependByteArray(buffer,data_array) Buffer_Prepend ((buffer), (data_array), sizeof ((data_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_PrependBuffer(buffer,data_buffer) Buffer_Prepend ((buffer), (data_buffer)->bytes, (data_buffer)->size)
int Buffer_PrependFormattedCString (buffer_t *buffer, const char *fmt_string, ...);
int Buffer_InsertAt (buffer_t *buffer, const size_t insert_index, const void *data, const size_t data_size);
static inline int Buffer_InsertInt8At (buffer_t *buffer, const size_t insert_index, const uint8_t int8_data) { return (Buffer_InsertAt (buffer, insert_index, (const uint8_t *) &int8_data, 1)); }
static inline int Buffer_InsertInt16At (buffer_t *buffer, const size_t insert_index, const uint16_t int16_data) { return (Buffer_InsertAt (buffer, insert_index, (const uint8_t *) &int16_data, 2)); }
static inline int Buffer_InsertInt32At (buffer_t *buffer, const size_t insert_index, const uint32_t int32_data) { return (Buffer_InsertAt (buffer, insert_index, (const uint8_t *) &int32_data, 4)); }
static inline int Buffer_InsertInt64At (buffer_t *buffer, const size_t insert_index, const uint64_t int64_data) { return (Buffer_InsertAt (buffer, insert_index, (const uint8_t *) &int64_data, 8)); }
#define Buffer_InsertCStringAt(buffer,insert_index,data_string) Buffer_InsertAt ((buffer), (insert_index), (data_string), strlen ((data_string)))
#define Buffer_InsertByteArrayAt(buffer,insert_index,data_array) Buffer_InsertAt ((buffer), (insert_index), (data_array), sizeof ((data_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_InsertBufferAt(buffer,insert_index,data_buffer) Buffer_InsertAt ((buffer), (insert_index), (data_buffer)->bytes, (data_buffer)->size)
int Buffer_WriteAt (buffer_t *buffer, const size_t write_index, const void *data, const size_t data_size);
static inline int Buffer_WriteInt8At (buffer_t *buffer, const size_t write_index, const uint8_t int8_data) { return (Buffer_WriteAt (buffer, write_index, (const uint8_t *) &int8_data, 1)); }
static inline int Buffer_WriteInt16At (buffer_t *buffer, const size_t write_index, const uint16_t int16_data) { return (Buffer_WriteAt (buffer, write_index, (const uint8_t *) &int16_data, 2)); }
static inline int Buffer_WriteInt32At (buffer_t *buffer, const size_t write_index, const uint32_t int32_data) { return (Buffer_WriteAt (buffer, write_index, (const uint8_t *) &int32_data, 4)); }
static inline int Buffer_WriteInt64At (buffer_t *buffer, const size_t write_index, const uint64_t int64_data) { return (Buffer_WriteAt (buffer, write_index, (const uint8_t *) &int64_data, 8)); }
#define Buffer_WriteCStringAt(buffer,write_index,data_string) Buffer_WriteAt ((buffer), (write_index), (data_string), strlen ((data_string)))
#define Buffer_WriteByteArrayAt(buffer,write_index,data_array) Buffer_WriteAt ((buffer), (write_index), (data_array), sizeof ((data_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_WriteBufferAt(buffer,write_index,data_buffer) Buffer_WriteAt ((buffer), (write_index), (data_buffer)->bytes, (data_buffer)->size)
#define Buffer_PadWithZeroesTo(buffer,offset) Buffer_WriteAt ((buffer), (offset), NULL, 0)
int Buffer_SubsetFromTo (buffer_t *buffer, const size_t from_index, const size_t to_index);
#define Buffer_SubsetWithLength(buffer,from_index,length) Buffer_SubsetFromTo ((buffer), (from_index), ((length) > 0 ? (from_index) : (buffer)->size) + (length)) // length > 0 => character index; length == 0 => end of string; length < 0 => end of string minus length
#define Buffer_Subset(buffer,from_index) Buffer_SubsetFromTo ((buffer), (from_index), (buffer)->size - (from_index))
int Buffer_ReadFromFile (buffer_t *buffer, const char *file_pathname);
int Buffer_WriteToFile (buffer_t *buffer, const char *file_pathname);
//#define Buffer_Find(buffer,needle,needle_length) Buffer_FindFirst (buffer, needle, needle_length) // FIXME: DEPRECATED, REMOVE
//#define Buffer_FindCString(buffer,needle_string) Buffer_FindFirst ((buffer), (needle_string), strlen (needle_string)) // FIXME: DEPRECATED, REMOVE
//#define Buffer_FindByteArray(buffer,needle_array) Buffer_FindFirst ((buffer), (needle_array), sizeof (needle_array) - 1) // FIXME: DEPRECATED, REMOVE
//#define Buffer_FindBuffer(buffer,needle_buffer) Buffer_FindFirst ((buffer), (needle_buffer)->bytes, (needle_buffer)->size) // FIXME: DEPRECATED, REMOVE
uint8_t *Buffer_FindFirst (const buffer_t *buffer, const void *needle, const size_t needle_length);
uint8_t *Buffer_FindFirstCI (const buffer_t *buffer, const char *needle);
#define Buffer_FindFirstCString(buffer,needle_string) Buffer_FindFirst ((buffer), (needle_string), strlen ((needle_string)))
#define Buffer_FindFirstByteArray(buffer,needle_array) Buffer_FindFirst ((buffer), (needle_array), sizeof ((needle_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_FindFirstBuffer(buffer,needle_buffer) Buffer_FindFirst ((buffer), (needle_buffer)->bytes, (needle_buffer)->size)
uint8_t *Buffer_FindLast (const buffer_t *buffer, const void *needle, const size_t needle_length);
uint8_t *Buffer_FindLastCI (const buffer_t *buffer, const char *needle);
#define Buffer_FindLastCString(buffer,needle_string) Buffer_FindLast ((buffer), (needle_string), strlen ((needle_string)))
#define Buffer_FindLastByteArray(buffer,needle_array) Buffer_FindLast ((buffer), (needle_array), sizeof ((needle_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_FindLastBuffer(buffer,needle_buffer) Buffer_FindLast ((buffer), (needle_buffer)->bytes, (needle_buffer)->size)
size_t Buffer_Replace (buffer_t *buffer, const void *needle, const size_t needle_length, const void *replacement, const size_t replacement_length, const int howmany_with_zero_for_all_and_minus_for_backwards);
#define Buffer_ReplaceCStringWithCString(buffer,needle_string,replacement_string,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_string), strlen ((needle_string)), (replacement_string), strlen ((replacement_string)), (howmany_with_zero_for_all_and_minus_for_backwards))
#define Buffer_ReplaceCStringWithByteArray(buffer,needle_string,replacement_array,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_string), strlen ((needle_string)), (replacement_array), sizeof ((replacement_array)) - 1, (howmany_with_zero_for_all_and_minus_for_backwards)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ReplaceCStringWithBuffer(buffer,needle_string,replacement_buffer,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_string), strlen ((needle_string)), (replacement_buffer)->bytes, (replacement_buffer)->size, (howmany_with_zero_for_all_and_minus_for_backwards))
#define Buffer_ReplaceByteArrayWithCString(buffer,needle_array,replacement_string,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_array), sizeof ((needle_array)) - 1, (replacement_string), strlen ((replacement_string)), (howmany_with_zero_for_all_and_minus_for_backwards)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ReplaceByteArrayWithByteArray(buffer,needle_array,replacement_array,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_array), sizeof ((needle_array)) - 1, (replacement_array), sizeof ((replacement_array)) - 1, (howmany_with_zero_for_all_and_minus_for_backwards)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ReplaceByteArrayWithBuffer(buffer,needle_array,replacement_buffer,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_array), sizeof ((needle_array)) - 1, (replacement_buffer)->bytes, (replacement_buffer)->size, (howmany_with_zero_for_all_and_minus_for_backwards)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ReplaceBufferWithCString(buffer,needle_buffer,replacement_string,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_buffer)->bytes, ((needle_buffer))->size, (replacement_string), strlen ((replacement_string)), (howmany_with_zero_for_all_and_minus_for_backwards))
#define Buffer_ReplaceBufferWithByteArray(buffer,needle_buffer,replacement_array,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_buffer)->bytes, ((needle_buffer))->size, (replacement_array), sizeof ((replacement_array)) - 1, (howmany_with_zero_for_all_and_minus_for_backwards)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_ReplaceBufferWithBuffer(buffer,needle_buffer,replacement_buffer,howmany_with_zero_for_all_and_minus_for_backwards) Buffer_Replace ((buffer), (needle_buffer)->bytes, ((needle_buffer))->size, (replacement_buffer)->bytes, (replacement_buffer)->size, (howmany_with_zero_for_all_and_minus_for_backwards))
int Buffer_Compare (buffer_t *buffer, const void *data, const size_t data_size);
#define Buffer_CompareWithCString(buffer,comparable_string) Buffer_Compare ((buffer), (comparable_string), strlen ((comparable_string)))
#define Buffer_CompareWithByteArray(buffer,comparable_array) Buffer_Compare ((buffer), (comparable_array), sizeof ((comparable_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_CompareWithBuffer(buffer,comparable_buffer) Buffer_Compare ((buffer), (comparable_buffer)->bytes, (comparable_buffer)->size)
#define Buffer_BeginsWith(buffer,data,data_size) (((buffer)->size >= (data_size)) && (memcmp ((buffer)->bytes, (data), (data_size)) == 0))
#define Buffer_BeginsWithCString(buffer,data_string) (((buffer)->size >= strlen ((data_string))) && (memcmp ((buffer)->bytes, (data_string), strlen ((data_string))) == 0))
#define Buffer_BeginsWithByteArray(buffer,data_array) (((buffer)->size >= sizeof ((data_array)) - 1) && (memcmp ((buffer)->bytes, (data_array), sizeof ((data_array)) - 1) == 0)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_EndsWith(buffer,data,data_size) (((buffer)->size >= (data_size)) && (memcmp (&(buffer)->bytes[(buffer)->size - (data_size)], (data), (data_size)) == 0))
#define Buffer_EndsWithCString(buffer,data_string) (((buffer)->size >= strlen ((data_string))) && (memcmp (&(buffer)->bytes[(buffer)->size - strlen ((data_string))], (data_string), strlen ((data_string))) == 0))
#define Buffer_EndsWithByteArray(buffer,data_array) (((buffer)->size >= sizeof ((data_array)) - 1) && (memcmp (&(buffer)->bytes[(buffer)->size - (sizeof ((data_array)) - 1)], (data_array), sizeof ((data_array)) - 1) == 0)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
size_t Buffer_OffsetOf (buffer_t *buffer, const void *something);
int Buffer_TrimLeftUntil (buffer_t *buffer, const uint8_t *trimmable_bytes, const size_t trimmable_count, const int howmany);
#define Buffer_TrimLeft(buffer,trimmable_data,trimmable_size) Buffer_TrimLeftUntil (buffer, trimmable_data, trimmable_size, 0)
#define Buffer_TrimLeftCString(buffer,trimmable_string) Buffer_TrimLeft ((buffer), (trimmable_string), strlen ((trimmable_string)))
#define Buffer_TrimLeftCString(buffer,trimmable_string) Buffer_TrimLeft ((buffer), (trimmable_string), strlen ((trimmable_string)))
#define Buffer_TrimLeftByteArray(buffer,trimmable_array) Buffer_TrimLeft ((buffer), (trimmable_array), sizeof ((trimmable_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
int Buffer_TrimRightUntil (buffer_t *buffer, const uint8_t *trimmable_bytes, const size_t trimmable_count, const int howmany);
#define Buffer_TrimRight(buffer,trimmable_data,trimmable_size) Buffer_TrimRightUntil ((buffer), (trimmable_data), (trimmable_size), 0)
#define Buffer_TrimRightCString(buffer,trimmable_string) Buffer_TrimRight ((buffer), (trimmable_string), strlen ((trimmable_string)))
#define Buffer_TrimRightByteArray(buffer,trimmable_array) Buffer_TrimRight ((buffer), (trimmable_array), sizeof ((trimmable_array)) - 1) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
#define Buffer_Trim(buffer,trimmable_bytes,trimmable_count) (Buffer_TrimRight ((buffer), (trimmable_bytes), (trimmable_count)) & Buffer_TrimLeft ((buffer), (trimmable_bytes), (trimmable_count)))
#define Buffer_TrimCString(buffer,trimmable_string) (Buffer_TrimRight ((buffer), (trimmable_string), strlen ((trimmable_string))) & Buffer_TrimLeft ((buffer), (trimmable_string), strlen ((trimmable_string))))
#define Buffer_TrimByteArray(buffer,trimmable_array) (Buffer_TrimRight ((buffer), (trimmable_array), sizeof ((trimmable_array)) - 1) & Buffer_TrimLeft ((buffer), (trimmable_array), sizeof ((trimmable_array)) - 1)) // WARNING: DO NOT USE WITH TERNARY OPERATORS!
int Buffer_GetNthParts (buffer_t *buffer, const size_t wanted_part_index, const int howmany, const void *separator, const size_t separator_len, const int should_parse_as_text, buffer_t *preinitialized_outbuf);
#define Buffer_GetNthLine(buffer,line_index,preinitialized_outbuf) Buffer_GetNthParts ((buffer), (line_index), 1, "\n", 1, 1, (preinitialized_outbuf))
#ifdef __cplusplus
}
#endif
#endif // BUFFER_H