sbuf_init
, sbuf_free
,
sbuf_clear
, sbuf_zero
,
sbuf_add
, sbuf_add2
,
sbuf_trim,
sbuf_detach
,
sbuf_extend
, sbuf_sprintf
,
sbuf_vsprintf,
sbuf_fetch
,
sbuf_fgets
—
smart buffers manipulation functions
#include <strfunc.h>
Create, and destroy the buffer
sbuf *
sbuf_init
(void);
void
sbuf_free
(sbuf
*sb);
Clean and truncate the buffer
int
sbuf_clear
(sbuf
*sb);
Just clean the buffer
int
sbuf_zero
(sbuf
*sb);
Add values to the end of the buffer
ssize_t
sbuf_add
(sbuf
*sb, conat char
*string);
ssize_t
sbuf_add2
(sbuf
*sb, const void
*data, size_t
nbytes);
Trim buffer from left or right side
ssize_t
sbuf_trim
(sbuf
*sb, int
_from_left, size_t
nbytes);
Detach the buffer contents
char *
sbuf_detach
(sbuf
*sb, size_t
*optLength, size_t
*optSize);
Extend the buffer
ssize_t
sbuf_extend
(sbuf
*, size_t
upto);
Add the formatted string
ssize_t
sbuf_sprintf
(sbuf
*, const char *fmt,
...);
ssize_t
sbuf_vsprintf
(sbuf
*, const char *fmt,
va_list ap);
Get a first len characters or token
char *
sbuf_fetch
(sbuf
*, size_t optLen,
char *optDelimiter,
size_t *optRetLen,
int flags);
Get a line from the stream
char *
sbuf_fgets
(sbuf
*, FILE
*stream);
These routines give the user a method of manipulating smart buffers. Smart
buffers are used to omit headache of checking the buffer boundaries every time
you're trying to add something.
Buffers may be used to handle any types of data. Internally, the
buffer always contain the terminating NULL and thus significiantly
simplifies the string handling.
Here is the sbuf structure (public):
typedef struct {
char *buf; /* The buffer data */
size_t len; /* Offset to end of real data (' ') */
size_t size; /* Allocated memory */
size_t off; /* Offset to start of real data */
} sbuf;
The following macros are available for your convenience
#define sbuf2ptr(sb) ((sb)->buf + (sb)->off)
#define sbuf_len(sb) ((sb)->len - (sb)->off) /* Meaningful length */
To create a buffer, you must invoke
sbuf_init
() first. After all the necessary
operations, the sbuf * structure must be disposed with
sbuf_free
().
After the buffer is created, you might want to add a data to the
buffer. It can be done using
sbuf_add
(sbuf *sb,
const char *string) and
sbuf_add2
(sbuf *sb,
const void *data, size_t nbytes)
functions. The second function does not rely on ASCIIZ idea and places the
nbytes of the data into the smart
buffer. Both functions automatically extend buffer to fit all the characters
provided. In case of error, the functions will return -1 and the buffer will
be left intact. Upon success, sbuf_add
() returns
with the number of written bytes and sbuf_add2
()
returns with the adjusted len
field of the passed
sbuf *
structure. Otherwise a -1 is returned by both
functions.
sbuf_trim
() trims given number of
characters off the buffer from the left or right side, returning a number of
bytes actually trimmed (which may be less than requested in case the actual
buffer length is smaller). This is a zero-cost operation, as it just shifts
pointers.
sbuf_detach
() used to detach the buffer
from the smart buffer descriptor, and return a pointer to that detached
memory. If the optional optLength or
optSize are given, sbuf_detach
()
will fill them with the actual values of the buffer length (number of
meaningful bytes) and buffer size (allocated memory) appropriately. Upon
detach, the smart buffer descriptor will be re-initialized to contain new,
empty buffer. After detaching, the buffer descriptor
(sbuf) will be reinitialized (read "empty").
To pre-extend the buffer up to the specified size, use
sbuf_extend
(). This function will also clear the
buffer from the current position (sb->len) to the end
of the allocated memory.
sbuf_sprintf
() and
sbuf_vsprintf
() functions used to add the formatted
string to the end of the buffer. These functions returns the number of bytes
actually writen. Buffer will be automatically extended to fit the string. In
case of error, -1 will be returned and buffer will be left intact. See the
manual pages on
sprintf(3)
and
vsprintf(3)
to learn more.
sbuf_fetch
() used to fetch the substring
or token from the start of the buffer. If optLen argument
is zero optDdelimiter must contain the set of delimiting
characters, overwise ignored. The flags argument controls
the behavior of splitting routinge most like in
splitf(3)
function, with exception that the buffer can't be split by regular
expression. optRetLen will contain the length of returned
string.
sbuf_fgets
() is analogous to plain
fgets(3),
but has the significant feature. It adds the whole line from the given
stream to the buffer and returns the pointer. The buffer is reallocated to
suffice the memory requirements by this line.
All functions returning ssize_t may fail with -1 and the
set errno to the appropriate value.
All functions returning pointer values (sbuf
*, char *) may fail with NULL and the set errno
to the appropriate value.
By default, functions may not fail with ENOMEM unless the library
memory control behavior was changed, see
sf_mem(3).
Here is an example of creating and filling the smart buffer.
void main() {
sbuf *sb; /* Declare a buffer pointer */
sb=sbuf_init(); /* Create and initialize buffer */
/* Add some data */
sbuf_add(sb, "one\n");
sbuf_add2(sb, "two\n", sizeof("two\n") - 1);
/* This will print:
* "one\ntwo\n"
*/
printf("%s", sb->buf);
/* Add the formatted string */
sbuf_sprintf(sb, "one: %d\n", 1);
/* This will print:
* "one\ntwo\none: 1\n"
*/
printf("%s", sb->buf);
/* Destroy the buffer */
sbuf_free(sb);
};
Here is an example of reading the stream line-by-line.
void readfile(FILE *stream) {
sbuf *sb;
char *p;
sb = sbuf_init();
while((p = sbuf_fgets(sb, stream) != NULL) {
printf("Read line: %s", p);
/* Rewind buffer */
sbuf_zero(sb);
};
sbuf_free(sb);
};
Lev Walkin <vlm@lionet.info>