diff options
author | Olivier Gayot <duskcoder@gmail.com> | 2013-12-21 23:09:09 +0100 |
---|---|---|
committer | Olivier Gayot <duskcoder@gmail.com> | 2014-01-18 13:43:52 +0100 |
commit | 3522c68dcd38e3eef393771d65aff6de2f815da3 (patch) | |
tree | abe4ba88238482dbfb6fdebcded3f5c3626d1c7d | |
parent | 9f25faad5fe732e498942818dc45de78ce7f3766 (diff) |
rb: add ascii support
in order to be able to deal with strings (i.e null terminated), we
provide a new set of functions
rb_puts
rb_printf / rb_vprintf
rb_gets / rb_gets2
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | rb_str.h | 54 | ||||
-rw-r--r-- | src/rb_str.c | 120 |
3 files changed, 175 insertions, 1 deletions
@@ -3,7 +3,7 @@ CFLAGS += -W -Wall -std=c99 -Wextra CFLAGS += -I./ CFLAGS += -D _GNU_SOURCE NAME = librb.a -SRC = src/rb.c +SRC = src/rb.c src/rb_str.c AR = ar rc diff --git a/rb_str.h b/rb_str.h new file mode 100644 index 0000000..f48d685 --- /dev/null +++ b/rb_str.h @@ -0,0 +1,54 @@ +#ifndef RB_STR_H +#define RB_STR_H + +#include <string.h> +#include <stdarg.h> + +#include "rb.h" + +/* + * locate in the ring buffer pointed to by rb the first string ending by the + * string pointed to by string and return it. the string returned is + * allocated using malloc and should be freed by the developer. + * if no such delimiter can be found, NULL is returned and the ring buffer + * is left unmodified. Otherwise, the string is removed from it. + * nb: the delimiter is discarded in the returned string + * + * common use case: + * request = rb_gets(rb, "\r\n") + */ +char *rb_gets(t_rb *rb, const char *delim); + +/* + * same as the above function but takes a null terminated array of delimiters + * the function will return the shortest string matching the criteria. + * if two or more delimiters are found at the same place in the ring buffer, + * the longest will be discarded + * + * common use case: + * request = rb_gets(rb, (const char *[]){"\n", "\r", "\r\n"}) + * which will return a request disregarding whether netcat or telnet is used + */ +char *rb_gets2(t_rb *rb, const char *const *delim); + +/* + * this functions writes str to the ring buffer pointed by rb. If the ring + * buffer is not large enough to contain all the data, the beginning will be + * overriden. However, a buffer overflow is not susceptible to happen. + */ +static inline t_rb *rb_puts(t_rb *rb, const char *str) +{ + return rb_put(rb, str, strlen(str)); +} + +t_rb *rb_vprintf(t_rb *rb, const char *fmt, va_list list); + +/* + * function which behaves like sprintf but which writes into a ring buffer + * if the ring buffer is not large enough to contain all the data, + * the beginning will be overriden. However, a buffer overflow will not occur + */ + __attribute__((format(printf, 2, 3))) +t_rb *rb_printf(t_rb *rb, const char *fmt, ...); + +#endif /* RB_STR_H */ diff --git a/src/rb_str.c b/src/rb_str.c new file mode 100644 index 0000000..b80628f --- /dev/null +++ b/src/rb_str.c @@ -0,0 +1,120 @@ +#include <malloc.h> + +#include "rb_str.h" + +typedef uint8_t byte; + +static char *__rb_gets2(t_rb *rb, const char *const *delim, + const byte *data, size_t size) +{ + char *ret = NULL; + char *b_ptr = NULL; + char *ptr; + size_t b_len; /* length of the current best delimiter */ + size_t len; + + for (; *delim != NULL; ++delim) { + len = strlen(*delim); + ptr = memmem(data, size, *delim, len); + + if (ptr == NULL) + continue; + + if ((b_ptr == NULL) || (ptr < b_ptr) + || ((ptr == b_ptr) && len > b_len)) + { + b_ptr = ptr; + b_len = len; + } + } + + if (b_ptr != NULL) { + ret = strndup((const char *)data, (size_t)b_ptr - (size_t)data); + + /* TODO replace with an appropriate function */ + rb_get(rb, NULL, (size_t)b_ptr - (size_t)data + b_len); + } + + return ret; +} + +char *rb_gets2(t_rb *rb, const char *const *delim) +{ + size_t size; + char *ret; + byte *data; + + data = malloc((rb->size_filled) * sizeof(byte)); + + if (data == NULL) { + return NULL; + } + + size = rb_peek(rb, data, rb->size_filled); + + ret = __rb_gets2(rb, delim, data, size); + + free(data); + + return ret; +} + +char *rb_gets(t_rb *rb, const char *delimit) +{ + char *data = malloc((rb->size_filled) * sizeof(char)); + + if (data == NULL) { + return NULL; + } + + size_t size = rb_peek(rb, data, rb->size_filled); + void *ptr = memmem(data, size, delimit, strlen(delimit)); + char *ret = NULL; + + if (ptr != NULL) { + ret = strndup(data, (size_t)ptr - (size_t)data); + /* + * TODO replace by a function which only removes data from the + * ring buffer + */ + rb_get(rb, data, (size_t)ptr - (size_t)data + strlen(delimit)); + } + + free(data); + + return ret; +} + +t_rb *rb_vprintf(t_rb *rb, const char *fmt, va_list ap) +{ + char *buffer; + + if (vasprintf(&buffer, fmt, ap) < 0) { + /* + * TODO the manual says that the content of buffer is undefined, + * we should reconsider the use of vasprintf() + */ + + return rb; + } + + rb_puts(rb, buffer); + + free(buffer); + + return rb; +} + + __attribute__((format(printf, 2, 3))) +t_rb *rb_printf(t_rb *rb, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + rb_vprintf(rb, fmt, ap); + + va_end(ap); + + return rb; +} |