From 11aa09abebe98b2db277a2d80698d8c3d63019df Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Thu, 14 Jan 2021 00:15:40 +1000 Subject: [PATCH] + f2b_buf_t --- src/buf.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ src/buf.h | 15 ++++++++++ t/CMakeLists.txt | 2 ++ t/t_buf.c | 48 +++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 src/buf.c create mode 100644 src/buf.h create mode 100644 t/t_buf.c diff --git a/src/buf.c b/src/buf.c new file mode 100644 index 0000000..ed08886 --- /dev/null +++ b/src/buf.c @@ -0,0 +1,74 @@ +#include "common.h" +#include "buf.h" + +bool +f2b_buf_alloc(f2b_buf_t *buf, size_t size) { + assert(buf != NULL); + assert(size > 0); + + memset(buf, 0x0, sizeof(f2b_buf_t)); + if ((buf->data = malloc(size)) == NULL) + return false; /* can't allocate memory */ + + buf->size = size; + return true; +} + +void +f2b_buf_free(f2b_buf_t *buf) { + assert(buf != NULL); + + free(buf->data); + memset(buf, 0x0, sizeof(f2b_buf_t)); +} + +bool +f2b_buf_append(f2b_buf_t *buf, const char *str, size_t len) { + + assert(buf != NULL); + assert(str != NULL); + + if (len == 0) + len = strlen(str); + if (buf->size < (buf->used + len)) + return false; /* not enough space */ + + memcpy(&buf->data[buf->used], str, len); + buf->used += len; + buf->data[buf->used] = '\0'; + return true; +} + +/** + * @brief Extracts line terminated by '\r', '\n' + * @return Pointer to extracted string on success or NULL otherwise + * @note Use only with 'read' buffer type + */ +char * +f2b_buf_extract(f2b_buf_t *buf, const char *end) { + char *s = NULL; + size_t len = 0; + + assert(buf != NULL); + assert(end != NULL); + + if (buf->data == NULL || buf->used == 0) + return NULL; /* no data */ + + if ((s = strstr(buf->data, end)) == NULL) + return NULL; /* not found */ + + /* copy the data before modifying buffer */ + len = s - buf->data; + if ((s = strndup(buf->data, len)) == NULL) + return NULL; /* malloc error */ + + /* shift data inside buffer */ + len += strlen(end); + assert(buf->used >= len); + buf->used -= len, + memmove(buf->data, &buf->data[len], buf->used); + buf->data[buf->used] = '\0'; + + return s; +} diff --git a/src/buf.h b/src/buf.h new file mode 100644 index 0000000..31d5472 --- /dev/null +++ b/src/buf.h @@ -0,0 +1,15 @@ +#ifndef F2B_BUF_H_ +#define F2B_BUF_H_ + +typedef struct f2b_buf_t { + size_t used; /**< bytes used in buffer */ + size_t size; /**< available size in data */ + char *data; /**< allocated buffer */ +} f2b_buf_t; + +bool f2b_buf_alloc(f2b_buf_t *buf, size_t max); +void f2b_buf_free(f2b_buf_t *buf); +bool f2b_buf_append(f2b_buf_t *buf, const char *str, size_t size); +char * f2b_buf_extract(f2b_buf_t *buf, const char *end); + +#endif /* F2B_BUF_H_ */ diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt index 7ec6c88..ad6c2a7 100644 --- a/t/CMakeLists.txt +++ b/t/CMakeLists.txt @@ -2,6 +2,7 @@ enable_testing() set(SRC_DIR "../src") +add_executable("t_buf" "t_buf.c" "${SRC_DIR}/strlcpy.c" "${SRC_DIR}/buf.c") add_executable("t_cmd" "t_cmd.c" "${SRC_DIR}/strlcpy.c" "${SRC_DIR}/commands.c") add_executable("t_cmsg" "t_cmsg.c" "${SRC_DIR}/strlcpy.c" "${SRC_DIR}/cmsg.c") add_executable("t_matches" "t_matches.c" "${SRC_DIR}/strlcpy.c" "${SRC_DIR}/matches.c") @@ -10,6 +11,7 @@ add_executable("t_statefile" "t_statefile.c" "${SRC_DIR}/strlcpy.c" "${SRC_D add_executable("t_config_param" "t_config_param.c" "${SRC_DIR}/strlcpy.c" "${SRC_DIR}/config.c" "${SRC_DIR}/log.c") add_executable("t_backend_usage" "t_backend_usage.c" "${SRC_DIR}/strlcpy.c") +add_test("tests/f2b_buf_*" "t_buf") add_test("tests/f2b_cmd_*" "t_cmd") add_test("tests/f2b_cmsg_*" "t_cmsg") add_test("tests/f2b_matches_*" "t_matches") diff --git a/t/t_buf.c b/t/t_buf.c new file mode 100644 index 0000000..129b487 --- /dev/null +++ b/t/t_buf.c @@ -0,0 +1,48 @@ +#include "../src/common.h" +#include "../src/buf.h" + +int main() { + f2b_buf_t buf; + char *line; + bool ret; + + memset(&buf, 0x0, sizeof(buf)); + + ret = f2b_buf_alloc(&buf, 512); + assert(ret = true); + assert(buf.used == 0); + assert(buf.size == 512); + + ret = f2b_buf_append(&buf, "test ", 0); + assert(ret == true); + assert(buf.used == 5); + + line = f2b_buf_extract(&buf, "\n"); + assert(line == NULL); + + ret = f2b_buf_append(&buf, "test2\n", 0); + assert(ret == true); + assert(buf.used == 11); + + ret = f2b_buf_append(&buf, "test3\n", 0); + assert(ret == true); + assert(buf.used == 17); + + line = f2b_buf_extract(&buf, "\n"); + assert(line != NULL); + assert(strcmp(line, "test test2") == 0); + assert(buf.used == 6); + free(line); + + line = f2b_buf_extract(&buf, "\n"); + assert(line != NULL); + assert(buf.used == 0); + free(line); + + f2b_buf_free(&buf); + assert(buf.used == 0); + assert(buf.size == 0); + assert(buf.data == NULL); + + return 0; +}