mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-18 20:30:58 +01:00
started documenting the api.
This commit is contained in:
@@ -19,18 +19,6 @@
|
||||
You can contact me by mail: <tom AT vondein DOT org>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Flexible buffer management, idea from openssh/buffer.c.
|
||||
This allows us to dissect buffers into parts at will
|
||||
whithout the hassle of boundary checking in each and every
|
||||
line. Therefore it is more secure, since this system wraps
|
||||
all this stuff from us, so in case we're attemt to overflow
|
||||
a buffer or the like, the buffer functions will catch this,
|
||||
warn us and die.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HAVE_PCP_BUFFER_H
|
||||
#define HAVE_PCP_BUFFER_H
|
||||
|
||||
@@ -40,116 +28,551 @@
|
||||
#include "util.h"
|
||||
#include "defines.h"
|
||||
|
||||
/**
|
||||
* \defgroup Buffer Buffer, a flexible buffer management class.
|
||||
* @{
|
||||
|
||||
Flexible buffer management, idea from openssh/buffer.c.
|
||||
|
||||
This class allows us to dissect buffers into parts at will
|
||||
whithout the hassle of boundary checking in each and every
|
||||
line. Therefore it is more secure, since this system wraps
|
||||
all this stuff from us, so in case we're attemt to overflow
|
||||
a buffer or the like, the buffer functions will catch this,
|
||||
warn us and die.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** \struct _pcp_buffer
|
||||
A flexible buffer object wich automatically resizes, if neccessary.
|
||||
*/
|
||||
struct _pcp_buffer {
|
||||
char *name; /* just for convenience in error messages and the
|
||||
like, so we know which buffer cause trouble */
|
||||
uint8_t allocated;
|
||||
size_t blocksize;
|
||||
size_t size;
|
||||
size_t offset; /* read position */
|
||||
size_t end; /* write position, data end */
|
||||
uint8_t isstring; /* treat as char array */
|
||||
void *buf;
|
||||
char *name; /**< just for convenience in error messages and the like, so we know which buffer cause trouble */
|
||||
uint8_t allocated; /**< marks the buffer as allocated */
|
||||
size_t blocksize; /**< the blocksize to use when resizing, also used for initial malloc() */
|
||||
size_t size; /**< stores the current allocated size of the object */
|
||||
size_t offset; /**< current read position */
|
||||
size_t end; /**< current write position, data end. maybe less than size. */
|
||||
uint8_t isstring; /**< treat as char array/string */
|
||||
void *buf; /**< the actual storage buffer */
|
||||
};
|
||||
|
||||
/** The name used everywhere */
|
||||
typedef struct _pcp_buffer Buffer;
|
||||
|
||||
/* create a new buffer, initially alloc'd to blocksize and zero-filled */
|
||||
/** Create a new buffer.
|
||||
|
||||
Create a new buffer, initially alloc'd to blocksize and zero-filled.
|
||||
|
||||
\param[in] blocksize Initial blocksize. The smaller the more often
|
||||
the buffer will be resized. Choose with care.
|
||||
|
||||
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
|
||||
|
||||
\return Returns a new Buffer object.
|
||||
*/
|
||||
Buffer *buffer_new(size_t blocksize, char *name);
|
||||
|
||||
/* same, but enable isstring */
|
||||
/** Create a new buffer.
|
||||
|
||||
Create a new buffer, initially alloc'd to a blocksize of 32 bytes and zero-filled.
|
||||
The buffer will be a string buffer. See buffer_get_str().
|
||||
|
||||
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
|
||||
|
||||
\return Returns a new Buffer object.
|
||||
*/
|
||||
Buffer *buffer_new_str(char *name);
|
||||
|
||||
/* initialize buffer vars */
|
||||
void buffer_init(Buffer *b, size_t blocksize, char *name);
|
||||
|
||||
/* zero the buffer and free it, if allocated */
|
||||
/** Clears and frees the Buffer.
|
||||
|
||||
This clears the buffer by filling it with zeroes and frees any
|
||||
allocated memory, including the Buffer object itself. Use this
|
||||
function instead of directly calling free(Buffer).
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
*/
|
||||
void buffer_free(Buffer *b);
|
||||
|
||||
/* zero the buffer, reset counters, always called from buffer_free() */
|
||||
/** Clears the Buffer.
|
||||
|
||||
This clears the buffer by filling it with zeroes and resetting
|
||||
all counters. Memory will not be free'd. Called from buffer_free()
|
||||
before free'ing memory.
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
*/
|
||||
void buffer_clear(Buffer *b);
|
||||
|
||||
/* put read offset to start */
|
||||
/** Put read offset back to start.
|
||||
|
||||
This function sets the read offset counter back to 0 (start
|
||||
of the buffer).
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
*/
|
||||
void buffer_rewind(Buffer *b);
|
||||
|
||||
/* add data to the buffer, memorize end position */
|
||||
/** Add data to the buffer.
|
||||
|
||||
Adds data of the size len to the buffer and resizes the
|
||||
buffer, if neccessary. The write position ('end' field)
|
||||
will be updated accordingly.
|
||||
|
||||
Data will be copied, you can free() the given pointer after copying..
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
|
||||
\param[out] data Arbitrary data to add to the Buffer.
|
||||
|
||||
\param[in] len The size of the data to add in Bytes.
|
||||
*/
|
||||
void buffer_add(Buffer *b, const void *data, size_t len);
|
||||
|
||||
/* the same but use another buffer as source */
|
||||
/** Add data to the buffer.
|
||||
|
||||
Adds data from the given Buffer src to the buffer and resizes the
|
||||
buffer, if neccessary. The write position ('end' field)
|
||||
will be updated accordingly.
|
||||
|
||||
Data will be copied, you can buffer_free() the given src Buffer after the copying.
|
||||
|
||||
\param[out] dst The destination Buffer object to copy data into.
|
||||
|
||||
\param[in] src The source Buffer object to copy data from.
|
||||
*/
|
||||
void buffer_add_buf(Buffer *dst, Buffer *src);
|
||||
|
||||
/* add a string, support printf style */
|
||||
/** Add a formated string to the buffer.
|
||||
|
||||
Use printf() like syntax to add a formatted string
|
||||
to the buffer. Refer to the documentation of printf() for
|
||||
details.
|
||||
|
||||
Data will be copied, you can free() the given format string and params after copying.
|
||||
|
||||
Example:
|
||||
@code
|
||||
Buffer *x = buffer_new_str("test");
|
||||
buffer_add_str(x, "There are %d elements left in %s\n", 4, "list");
|
||||
@endcode
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
|
||||
\param[in] fmt The printf() compatible format description.
|
||||
|
||||
\param[in] ... A variable number of arguments for the format string.
|
||||
*/
|
||||
void buffer_add_str(Buffer *b, const char * fmt, ...);
|
||||
|
||||
/* add some binary data to the buffer, but as hex string */
|
||||
/** Add data as hex string to the buffer.
|
||||
|
||||
Adds data of the size len to the buffer and resizes the
|
||||
buffer, if neccessary. The write position ('end' field)
|
||||
will be updated accordingly. Each byte will be put in its
|
||||
HEX form into the buffer (%02x).
|
||||
|
||||
Data will be copied, you can free() the given pointer after copying..
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
|
||||
\param[in] data Arbitrary data to add as hex into the Buffer.
|
||||
|
||||
\param[in] len The size of the data to add in Bytes.
|
||||
*/
|
||||
void buffer_add_hex(Buffer *b, void *data, size_t len);
|
||||
|
||||
/* resize the buffer if necessary */
|
||||
/* resize the buffer if necessary, used internally only */
|
||||
void buffer_resize(Buffer *b, size_t len);
|
||||
|
||||
/* return true if there are no more bytes to read */
|
||||
/** Tell if there are no more bytes to read.
|
||||
|
||||
This functions tells if the EOF of the buffer is reached
|
||||
during read operations (no more data to read left).
|
||||
|
||||
\param[in] b The Buffer object.
|
||||
|
||||
\return Returns 1 of EOF has been reached or 0 if there are more data left to read.
|
||||
*/
|
||||
int buffer_done(Buffer *b);
|
||||
|
||||
/* get some chunk of data from the buffer, starting from offset til len */
|
||||
/** Read some chunk of data from the Buffer.
|
||||
|
||||
Read some chunk of data from the Buffer, starting from current read
|
||||
offset til len.
|
||||
|
||||
Example: suppose you've got a buffer with the following content:
|
||||
|
||||
@code
|
||||
AAAABBBBCCCC
|
||||
@endcode
|
||||
|
||||
Then the following code would:
|
||||
|
||||
@code
|
||||
unsigned char g[4];
|
||||
buffer_get_chunk(b, g, 4); // => g now contains 'AAAA'
|
||||
buffer_get_chunk(b, g, 4); // => g now contains 'BBBB'
|
||||
buffer_get_chunk(b, g, 4); // => g now contains 'CCCC'
|
||||
@endcode
|
||||
|
||||
In order to catch buffer overflow, check the return value, which will
|
||||
be 0 in case of errors. See also: fatals_ifany(), buffer_done() and buffer_left().
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\param[out] buf The destination pointer where the data will be copied to. This pointer
|
||||
must be allocated by the caller properly and it must have at least a size of len.
|
||||
|
||||
\param[in] len The number of bytes to read from the Buffer.
|
||||
|
||||
*/
|
||||
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len);
|
||||
|
||||
/* return the whole buffer contents */
|
||||
/** Read the whole Buffer content.
|
||||
|
||||
This function returns the whole buffer contents as a pointer
|
||||
to the internal data member (Buffer->buf). The returned pointer
|
||||
is allocated and filled with data up to buffer_size(Buffer),
|
||||
however, the allocated memory might be more than size, in fact
|
||||
it will be a multitude of Buffer-blocksize.
|
||||
|
||||
Don't free() the pointer directly, use buffer_free() always.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return Pointer to the buffer data storage.
|
||||
*/
|
||||
unsigned char *buffer_get(Buffer *b);
|
||||
|
||||
/* access the buffer content as string (char *) the returned pointer
|
||||
points to b->buf and should not be free'd directly*/
|
||||
/** Read the whole Buffer content as string.
|
||||
|
||||
Access the Buffer content as string (char *).
|
||||
|
||||
The returned pointer
|
||||
is allocated and filled with data up to buffer_size(Buffer),
|
||||
however, the allocated memory might be more than size, in fact
|
||||
it will be a multitude of Buffer-blocksize.
|
||||
|
||||
The byte after buffer_size(Buffer) will be a \0.
|
||||
|
||||
Don't free() the pointer directly, use buffer_free() always.
|
||||
|
||||
Sample usage:
|
||||
|
||||
@code
|
||||
[..]
|
||||
fprintf(stdout, "Our buffer content: %s\n", buffer_get_str(b));
|
||||
@endcode
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return Pointer to the buffer data storage.
|
||||
*/
|
||||
char *buffer_get_str(Buffer *b);
|
||||
|
||||
/* fetch whatever is left in the buffer */
|
||||
/** Read the remaining data after current read offset.
|
||||
|
||||
Fetch whatever is left in the buffer. This works like
|
||||
buffer_get() but instead doesn't return everything,
|
||||
but only the part of the buffer, which follows after
|
||||
the current read offset.
|
||||
|
||||
The returned pointer will be allocated by buffer_get_remainder()
|
||||
with a size of buffer_left(). It's up to the caller to free()
|
||||
the returned pointer later on.
|
||||
|
||||
Example: suppose you've got a buffer with the following content:
|
||||
|
||||
@code
|
||||
AAAABBBBCCCC
|
||||
@endcode
|
||||
|
||||
Then:
|
||||
|
||||
@code
|
||||
[..]
|
||||
unsigned char g[4];
|
||||
unsigned char *r = NULL;
|
||||
buffer_get_chunk(b, g, 4); // => g now contains 'AAAA'
|
||||
size_t rs = buffer_left(b); // => rs = 8
|
||||
r = buffer_get_remainder(b); // => r now contains 'BBBBCCCC' and has a size of 8
|
||||
memset(r, 0, rs); // zerofill r
|
||||
free(r); // done with it
|
||||
@endcode
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return Pointer to the remaining chunk of data (copy).
|
||||
*/
|
||||
unsigned char *buffer_get_remainder(Buffer *b);
|
||||
|
||||
/* same as buffer_get() but fetch some data chunk from somewhere
|
||||
in the middle of the buffer */
|
||||
/** Read some data inside the Buffer.
|
||||
|
||||
Same as buffer_get() but fetch some data chunk from somewhere
|
||||
in the middle of the buffer.
|
||||
|
||||
The returned pointer has to be allocated by the caller to
|
||||
at least a size of len bytes.
|
||||
|
||||
The read offset will be left untouched by this function.
|
||||
|
||||
Example: suppose you've got a buffer with the following content:
|
||||
|
||||
@code
|
||||
AAAABBBBCCCC
|
||||
@endcode
|
||||
|
||||
Then:
|
||||
@code
|
||||
[..]
|
||||
unsigned char g[4];
|
||||
buffer_extract(b, g, 4, 4); // => g now contains 'BBBB'
|
||||
@endcode
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\param[out] buf The buffer to copy data to.
|
||||
|
||||
\param[in] offset Where to start copying.
|
||||
|
||||
\param[in] len How mush data to copy.
|
||||
|
||||
\return Returns the size of bytes read. Returns 0 in case of
|
||||
an overflow, which can be catched with fatals_ifany().
|
||||
|
||||
*/
|
||||
size_t buffer_extract(Buffer *b, void *buf, size_t offset, size_t len);
|
||||
|
||||
/* dump the buffer contents to stderr */
|
||||
/** Dump the Buffer contents to stderr in hex form.
|
||||
|
||||
\param[in] b The Buffer object to dump.
|
||||
*/
|
||||
void buffer_dump(const Buffer *b);
|
||||
|
||||
/* print buffer counters to stderr */
|
||||
/** Print Buffer counters to stderr.
|
||||
|
||||
\param[in] b The Buffer object to print infos about.
|
||||
*/
|
||||
void buffer_info(const Buffer *b);
|
||||
|
||||
/* tell how much data there is in the buffer */
|
||||
/** Tell how much data there is in the buffer available.
|
||||
|
||||
This function returns the number of bytes stored in the
|
||||
buffer so far. Please note, that the actual allocation might
|
||||
be bigger, because we always allocate memory blockwise.
|
||||
|
||||
\param[in] b The Buffer object to get the size from.
|
||||
|
||||
\return The number of bytes stored in the Buffer.
|
||||
*/
|
||||
size_t buffer_size(const Buffer *b);
|
||||
|
||||
/* tell how much data is left to read */
|
||||
/** Tell how much data is left to read in the Buffer.
|
||||
|
||||
Use this function to check if it's ok to read more
|
||||
bytes from to buffer to avoid buffer overflows.
|
||||
|
||||
Example: suppose you've got a buffer with the following content:
|
||||
|
||||
@code
|
||||
AAAABBBBCCCC
|
||||
@endcode
|
||||
|
||||
Then:
|
||||
@code
|
||||
[..]
|
||||
unsigned char g[4];
|
||||
unsigned char x[16];
|
||||
buffer_get_chunk(b, g, 4); // => g now contains 'BBBB'
|
||||
if(buffer_left(b) >= 16) // => will return 8 and therefore fail
|
||||
buffer_get_chunk(b, x, 16);
|
||||
else
|
||||
printf("not enough data"); // => will be printed
|
||||
@endcode
|
||||
|
||||
\param[in] b The Buffer object to get the size from.
|
||||
|
||||
\return The number of bytes left to read from the Buffer.
|
||||
|
||||
*/
|
||||
size_t buffer_left(const Buffer *b);
|
||||
|
||||
/* same as get_chunk, but return numbers directly */
|
||||
/** Read 1 byte (8 bit) number from a Buffer.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint8_t.
|
||||
*/
|
||||
uint8_t buffer_get8(Buffer *b);
|
||||
|
||||
/** Read 2 bytes (16 bit) number from a Buffer.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint16_t.
|
||||
*/
|
||||
uint16_t buffer_get16(Buffer *b);
|
||||
|
||||
/** Read 4 byte (32 bit) number from a Buffer.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint32_t.
|
||||
*/
|
||||
uint32_t buffer_get32(Buffer *b);
|
||||
|
||||
/** Read 8 byte (64 bit) from a Buffer.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint64_t.
|
||||
*/
|
||||
uint64_t buffer_get64(Buffer *b);
|
||||
|
||||
/* same, but convert to native endian before return */
|
||||
/** Read 2 bytes (16 bit) number from a Buffer, converted to host endian.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint16_t.
|
||||
*/
|
||||
uint16_t buffer_get16na(Buffer *b);
|
||||
|
||||
/** Read 4 byte (32 bit) number from a Buffer, converted to host endian.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint32_t.
|
||||
*/
|
||||
uint32_t buffer_get32na(Buffer *b);
|
||||
|
||||
/** Read 8 byte (64 bit) from a Buffer, converted to host endian.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint64_t.
|
||||
*/
|
||||
uint64_t buffer_get64na(Buffer *b);
|
||||
|
||||
/* access the last byte(s) as numbers directly, save typing,
|
||||
in contrast to buffer_get() it doesn't increment offset */
|
||||
/** Read the last 1 byte (8 bit) number from a Buffer.
|
||||
|
||||
Doesn't increment offset.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint8_t.
|
||||
*/
|
||||
uint8_t buffer_last8(Buffer *b);
|
||||
|
||||
/** Read the last 2 byte (16 bit) number from a Buffer.
|
||||
|
||||
Doesn't increment offset.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint16_t.
|
||||
*/
|
||||
uint16_t buffer_last16(Buffer *b);
|
||||
|
||||
/** Read the last 4 byte (32 bit) number from a Buffer.
|
||||
|
||||
Doesn't increment offset.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint32_t.
|
||||
*/
|
||||
uint32_t buffer_last32(Buffer *b);
|
||||
|
||||
/** Read the last 8 byte (64 bit) number from a Buffer.
|
||||
|
||||
Doesn't increment offset.
|
||||
|
||||
\param[in] b The Buffer object to read from.
|
||||
|
||||
\return a uint64_t.
|
||||
*/
|
||||
uint64_t buffer_last64(Buffer *b);
|
||||
|
||||
/* read from a file directly into a buffer object */
|
||||
/** Read data from a file directly into a Buffer.
|
||||
|
||||
This function reads in len bytes from the FILE stream
|
||||
'in' into the Buffer. The file must already be opened
|
||||
by the caller.
|
||||
|
||||
\param[in,out] b The Buffer object to read from.
|
||||
|
||||
\param[in] in The FILE stream to read from.
|
||||
|
||||
\param[in] len The number of bytes to read.
|
||||
|
||||
\return Returns the number of bytes read or 0 in case of an error or EOF.
|
||||
Use feof() and ferror() to check this afterwards, call fatals_ifany()
|
||||
in case of errors.
|
||||
*/
|
||||
size_t buffer_fd_read(Buffer *b, FILE *in, size_t len);
|
||||
|
||||
/* write numbers as binary into the buffer */
|
||||
/** Write a 1 byte (8 bit) number in binary form into the buffer.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint8_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add8(Buffer *b, uint8_t v);
|
||||
|
||||
/** Write a 2 byte (16 bit) number in binary form into the buffer.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint16_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add16(Buffer *b, uint16_t v);
|
||||
|
||||
/** Write a 4 byte (32 bit) number in binary form into the buffer.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint32_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add32(Buffer *b, uint32_t v);
|
||||
|
||||
/** Write a 8 byte (64 bit) number in binary form into the buffer.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint64_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add64(Buffer *b, uint64_t v);
|
||||
|
||||
/* the same, but convert to big-endian before doing so */
|
||||
/** Write a 2 byte (16 bit) number in binary form into the buffer, converted to big endian.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint16_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add16be(Buffer *b, uint16_t v);
|
||||
|
||||
/** Write a 4 byte (32 bit) number in binary form into the buffer, converted to big endian.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint32_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add32be(Buffer *b, uint32_t v);
|
||||
|
||||
/** Write a 8 byte (64 bit) number in binary form into the buffer, converted to big endian.
|
||||
|
||||
\param[out] b The Buffer object to write to.
|
||||
|
||||
\param[in] v The uint64_t to write to the buffer.
|
||||
*/
|
||||
void buffer_add64be(Buffer *b, uint64_t v);
|
||||
|
||||
|
||||
#endif // HAVE_PCP_BUFFER_H
|
||||
|
||||
/**@}*/
|
||||
|
||||
Reference in New Issue
Block a user