From 94e1af55b9fdc7d0b6e4444ab7edecb50f0f370c Mon Sep 17 00:00:00 2001 From: Ahmet Artu Yildirim Date: Sun, 18 Dec 2022 01:34:56 -0800 Subject: [PATCH] Add basic APIs including var_int32 getter and setters --- .gitignore | 9 +- build-debug.sh | 3 + build-release.sh | 3 + configure.ac | 1 + scripts/clean.sh | 2 +- scripts/format.sh | 2 +- src/Makefile.am | 9 +- src/check_progbuf.c | 372 ++++++++++++++++++++++++++++++++++++++++++++ src/common.h | 25 ++- src/progbuf.c | 299 +++++++++++++++++++++++++++++++++-- src/progbuf.h | 36 ++++- src/test_progbuf.c | 8 - 12 files changed, 740 insertions(+), 29 deletions(-) create mode 100755 build-debug.sh create mode 100755 build-release.sh create mode 100644 src/check_progbuf.c delete mode 100644 src/test_progbuf.c diff --git a/.gitignore b/.gitignore index 0da60c7..ad1001a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,8 +26,13 @@ src/.libs/ src/Makefile src/libprogbuf.la src/libprogbuf.lo -src/test_progbuf src/*.o +src/check_progbuf +src/check_progbuf.log +src/check_progbuf.trs +src/progbuf.lo +src/test-suite.log +test-driver stamp-h1 -.idea/ +.vscode/ build/ diff --git a/build-debug.sh b/build-debug.sh new file mode 100755 index 0000000..e70a968 --- /dev/null +++ b/build-debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./configure CPPFLAGS=-DDEBUG CFLAGS="-g -O0" && make diff --git a/build-release.sh b/build-release.sh new file mode 100755 index 0000000..5bb11df --- /dev/null +++ b/build-release.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./configure && make diff --git a/configure.ac b/configure.ac index c840754..a29fb11 100644 --- a/configure.ac +++ b/configure.ac @@ -3,6 +3,7 @@ AM_INIT_AUTOMAKE([-Wall -Werror gnu]) AC_PROG_CC AM_PROG_AR LT_INIT +PKG_CHECK_MODULES([CHECK], [check]) AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ diff --git a/scripts/clean.sh b/scripts/clean.sh index bdb3380..18ff4c4 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -1,3 +1,3 @@ #!/bin/sh -rm -rf aclocal.m4 config.sub configure depcomp m4 ar-lib compile config.guess config.h install-sh Makefile Makefile.in autom4te.cache config.h.in ltmain.sh missing libtool config.status config.log INSTALL stamp-h1 src/Makefile.in src/.libs src/.deps src/*.o src/Makefile src/libprogbuf.la src/progbuf.lo src/test_progbuf build config.h.in~ +rm -rf aclocal.m4 config.sub configure depcomp m4 ar-lib compile config.guess config.h install-sh test-driver Makefile Makefile.in autom4te.cache config.h.in ltmain.sh missing libtool config.status config.log INSTALL stamp-h1 src/Makefile.in src/.libs src/.deps src/*.o src/Makefile src/libprogbuf.la src/progbuf.lo src/check_progbuf build config.h.in~ diff --git a/scripts/format.sh b/scripts/format.sh index 718c9f5..ee3a1dd 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -1,4 +1,4 @@ #!/bin/sh -find src -iname *.h -o -iname *.c | xargs clang-format -style=GNU -i +find ./src -iname *.h -o -iname *.c | xargs clang-format -style=GNU -i diff --git a/src/Makefile.am b/src/Makefile.am index ad6cdfe..4d4941b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,6 +3,9 @@ libprogbuf_la_SOURCES = progbuf.c libprogbuf_la_LDFLAGS = -version-info 0:1:0 include_HEADERS = progbuf.h -bin_PROGRAMS = test_progbuf -test_progbuf_SOURCES = test_progbuf.c -test_progbuf_LDADD = libprogbuf.la +noinst_PROGRAMS = check_progbuf +TESTS = check_progbuf +check_progbuf_SOURCES = check_progbuf.c +check_progbuf_CFLAGS = $(CFLAGS) $(CHECK_CFLAGS) +check_progbuf_LDADD = libprogbuf.la $(LDFLAGS) $(CHECK_LIBS) +check_progbuf_LDFLAGS = -no-install diff --git a/src/check_progbuf.c b/src/check_progbuf.c new file mode 100644 index 0000000..756b3a4 --- /dev/null +++ b/src/check_progbuf.c @@ -0,0 +1,372 @@ +#include +#include + +#include "common.h" +#include "progbuf.h" + +START_TEST (test_progbuf_alloc_version) +{ + int ret; + long message_tag; + + ret = progbuf_get_message_tag (NULL, &message_tag); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + progbuf_h buf = progbuf_alloc (1); + + ck_assert (buf); + + ret = progbuf_get_message_tag (buf, NULL); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_tag (buf, &message_tag); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (message_tag == 1); + + size_t size; + ret = progbuf_get_message_buffer (buf, NULL, &size); + + ck_assert (ret == PROGBUF_SUCCESS); + + ck_assert (size == 1); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); +} +END_TEST + +void +parametric_test_progbuf_write_read_long (const long val, + const int expected_val_size) +{ + progbuf_h buf = progbuf_alloc (1); + + ck_assert (buf); + + long p_val = val; + + int ret = progbuf_set_long (buf, p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + + size_t size; + ret = progbuf_get_message_buffer (buf, NULL, &size); + + ck_assert (ret == PROGBUF_SUCCESS); + + ck_assert (size == 1 + 1 + expected_val_size); + + progbuf_it_h iter = progbuf_iter_alloc (buf); + + ck_assert (iter); + + ret = progbuf_get_long (iter, &p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (val == p_val); + + struct progbuf_it_s *iter_internal = iter; + + ck_assert (iter_internal->read_pos == 1 + 1 + expected_val_size); + + ret = progbuf_iter_free (iter); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); +} + +START_TEST (test_progbuf_write_read_positive_long) +{ + parametric_test_progbuf_write_read_long (0, 1); + parametric_test_progbuf_write_read_long (1, 1); + parametric_test_progbuf_write_read_long (0x3F, 1); + + parametric_test_progbuf_write_read_long (0x7F, 2); + parametric_test_progbuf_write_read_long (0x1FFF, 2); + + parametric_test_progbuf_write_read_long (0x3FFF, 3); + parametric_test_progbuf_write_read_long (0xFFFFF, 3); + + parametric_test_progbuf_write_read_long (0x1FFFFF, 4); + parametric_test_progbuf_write_read_long (0x7FFFFFF, 4); + + parametric_test_progbuf_write_read_long (0xFFFFFFF, 5); + parametric_test_progbuf_write_read_long (0x7FFFFFFF, 5); +} +END_TEST + +START_TEST (test_progbuf_write_read_negative_long) +{ + parametric_test_progbuf_write_read_long (-1, 1); + parametric_test_progbuf_write_read_long (-0x3F, 1); + + parametric_test_progbuf_write_read_long (-0x7F, 2); + parametric_test_progbuf_write_read_long (-0x1FFF, 2); + + parametric_test_progbuf_write_read_long (-0x3FFF, 3); + parametric_test_progbuf_write_read_long (-0xFFFFF, 3); + + parametric_test_progbuf_write_read_long (-0x1FFFFF, 4); + parametric_test_progbuf_write_read_long (-0x7FFFFFF, 4); + + parametric_test_progbuf_write_read_long (-0xFFFFFFF, 5); + parametric_test_progbuf_write_read_long (-0x7FFFFFFF, 5); +} +END_TEST + +START_TEST (test_progbuf_write_read_ulong) +{ + progbuf_h buf = progbuf_alloc (1); + + ck_assert (buf); + + unsigned long val = 0xFFFFFFFF; + unsigned long p_val = val; + + int ret = progbuf_set_ulong (buf, p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + + size_t size; + + ret = progbuf_get_message_buffer (NULL, NULL, NULL); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (NULL, NULL, &size); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (buf, NULL, NULL); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (buf, NULL, &size); + ck_assert (ret == PROGBUF_SUCCESS); + + ck_assert (size == 1 + 6); + + progbuf_it_h iter = progbuf_iter_alloc (buf); + + ck_assert (iter); + + ret = progbuf_get_ulong (iter, &p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (val == p_val); + + struct progbuf_it_s *iter_internal = iter; + + ck_assert (iter_internal->read_pos == 1 + 6); + + ret = progbuf_iter_free (iter); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); +} +END_TEST + +void +parametric_test_progbuf_write_read_longlong (const long long val, + const int expected_val_size) +{ + progbuf_h buf = progbuf_alloc (1); + + ck_assert (buf); + + long long p_val = val; + + int ret = progbuf_set_longlong (buf, p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + + size_t size; + ret = progbuf_get_message_buffer (buf, NULL, &size); + + ck_assert (ret == PROGBUF_SUCCESS); + + ck_assert (size == 1 + 1 + expected_val_size); + + progbuf_it_h iter = progbuf_iter_alloc (buf); + + ck_assert (iter); + + ret = progbuf_get_longlong (iter, &p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (val == p_val); + + struct progbuf_it_s *iter_internal = iter; + + ck_assert (iter_internal->read_pos == 1 + 1 + expected_val_size); + + ret = progbuf_iter_free (iter); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); +} + +START_TEST (test_progbuf_write_read_positive_longlong) +{ + parametric_test_progbuf_write_read_longlong (0, 1); + parametric_test_progbuf_write_read_longlong (1, 1); + parametric_test_progbuf_write_read_longlong (0x3F, 1); + + parametric_test_progbuf_write_read_longlong (0x7F, 2); + parametric_test_progbuf_write_read_longlong (0x1FFF, 2); + + parametric_test_progbuf_write_read_longlong (0x3FFF, 3); + parametric_test_progbuf_write_read_longlong (0xFFFFF, 3); + + parametric_test_progbuf_write_read_longlong (0x1FFFFF, 4); + parametric_test_progbuf_write_read_longlong (0x7FFFFFF, 4); + + parametric_test_progbuf_write_read_longlong (0xFFFFFFF, 5); + parametric_test_progbuf_write_read_longlong (0x3FFFFFFFF, 5); + + parametric_test_progbuf_write_read_longlong (0x7FFFFFFFF, 6); + parametric_test_progbuf_write_read_longlong (0x1FFFFFFFFFF, 6); + + parametric_test_progbuf_write_read_longlong (0x3FFFFFFFFFF, 7); + parametric_test_progbuf_write_read_longlong (0xFFFFFFFFFFFF, 7); + + parametric_test_progbuf_write_read_longlong (0x1FFFFFFFFFFFF, 8); + parametric_test_progbuf_write_read_longlong (0x7FFFFFFFFFFFFF, 8); + + parametric_test_progbuf_write_read_longlong (0xFFFFFFFFFFFFFF, 9); + parametric_test_progbuf_write_read_longlong (0x3FFFFFFFFFFFFFFF, 9); + + parametric_test_progbuf_write_read_longlong (0x7FFFFFFFFFFFFFFF, 10); +} +END_TEST + +START_TEST (test_progbuf_write_read_negative_longlong) +{ + parametric_test_progbuf_write_read_longlong (-1, 1); + parametric_test_progbuf_write_read_longlong (-0x3F, 1); + + parametric_test_progbuf_write_read_longlong (-0x7F, 2); + parametric_test_progbuf_write_read_longlong (-0x1FFF, 2); + + parametric_test_progbuf_write_read_longlong (-0x3FFF, 3); + parametric_test_progbuf_write_read_longlong (-0xFFFFF, 3); + + parametric_test_progbuf_write_read_longlong (-0x1FFFFF, 4); + parametric_test_progbuf_write_read_longlong (-0x7FFFFFF, 4); + + parametric_test_progbuf_write_read_longlong (-0xFFFFFFF, 5); + parametric_test_progbuf_write_read_longlong (-0x7FFFFFFF, 5); + + parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFF, 6); + parametric_test_progbuf_write_read_longlong (-0x1FFFFFFFFFF, 6); + + parametric_test_progbuf_write_read_longlong (-0x3FFFFFFFFFF, 7); + parametric_test_progbuf_write_read_longlong (-0xFFFFFFFFFFFF, 7); + + parametric_test_progbuf_write_read_longlong (-0x1FFFFFFFFFFFF, 8); + parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFFFFFFF, 8); + + parametric_test_progbuf_write_read_longlong (-0xFFFFFFFFFFFFFF, 9); + parametric_test_progbuf_write_read_longlong (-0x3FFFFFFFFFFFFFFF, 9); + + parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFFFFFFFFF, 10); +} +END_TEST + +START_TEST (test_progbuf_write_read_ulonglong) +{ + progbuf_h buf = progbuf_alloc (1); + + ck_assert (buf); + + unsigned long long val = 0xFFFFFFFFFFFFFFFF; + unsigned long long p_val = val; + + int ret = progbuf_set_ulonglong (buf, p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + + size_t size; + + ret = progbuf_get_message_buffer (NULL, NULL, NULL); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (NULL, NULL, &size); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (buf, NULL, NULL); + ck_assert (ret == PROGBUF_ERROR_NULL_PARAM); + + ret = progbuf_get_message_buffer (buf, NULL, &size); + ck_assert (ret == PROGBUF_SUCCESS); + + ck_assert (size == 1 + 1 + 10); + + progbuf_it_h iter = progbuf_iter_alloc (buf); + + ck_assert (iter); + + ret = progbuf_get_ulonglong (iter, &p_val); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (val == p_val); + + struct progbuf_it_s *iter_internal = iter; + + ck_assert (iter_internal->read_pos == 1 + 1 + 10); + + ret = progbuf_iter_free (iter); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); +} +END_TEST + +static Suite * +progbuf_suite (void) +{ + Suite *s; + TCase *tc_basic, *tc_long, *tc_longlong; + + s = suite_create ("progbuf test suite"); + + tc_basic = tcase_create ("basic"); + + tcase_add_test (tc_basic, test_progbuf_alloc_version); + + tc_long = tcase_create ("encode_long"); + + tcase_add_test (tc_long, test_progbuf_write_read_positive_long); + tcase_add_test (tc_long, test_progbuf_write_read_negative_long); + tcase_add_test (tc_long, test_progbuf_write_read_ulong); + + tc_longlong = tcase_create ("encode_longlong"); + + tcase_add_test (tc_longlong, test_progbuf_write_read_positive_longlong); + tcase_add_test (tc_longlong, test_progbuf_write_read_negative_longlong); + tcase_add_test (tc_longlong, test_progbuf_write_read_ulonglong); + + suite_add_tcase (s, tc_basic); + suite_add_tcase (s, tc_long); + suite_add_tcase (s, tc_longlong); + + return s; +} + +int +main () +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = progbuf_suite (); + sr = srunner_create (s); + + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/common.h b/src/common.h index 2a2e8ca..5d63f7e 100644 --- a/src/common.h +++ b/src/common.h @@ -1,12 +1,31 @@ #ifndef LIBPROGBUF_COMMON_H #define LIBPROGBUF_COMMON_H +#include + +#define ABS(N) ((N<0)?(-N):(N)) + +#define PROGBUF_INIT_BUFSIZ 128 + +#define PROGBUF_TYPE_VAR_INT 0x00 +#define PROGBUF_TYPE_FLOAT32 0x01 +#define PROGBUF_TYPE_FLOAT64 0x02 +#define PROGBUF_TYPE_BYTE 0x03 +#define PROGBUF_TYPE_ARRAY 0x04 + struct progbuf_s { - int message_tag; - int version; char *buffer; - int bufsiz; + long message_tag; + int header_size; + size_t capacity; + size_t size; +}; + +struct progbuf_it_s +{ + struct progbuf_s* buf; + size_t read_pos; }; #endif // LIBPROGBUF_COMMON_H diff --git a/src/progbuf.c b/src/progbuf.c index a300efe..47d450e 100644 --- a/src/progbuf.c +++ b/src/progbuf.c @@ -2,28 +2,309 @@ #include "common.h" #include +#include + +typedef unsigned int uint; +typedef unsigned long ulong; +typedef long long longlong; +typedef unsigned long long ulonglong; + +#define DETERMINE_VAR_SIZE(type) \ + static inline int determine_var_##type##_size (type value) \ + { \ + type mask; \ + memset (&mask, 0xFF, sizeof (mask)); \ + \ + mask <<= 6; \ + \ + if ((value & mask) == 0) \ + return 1; \ + \ + int s = 2; \ + while (1) \ + { \ + mask <<= 7; \ + \ + if ((value & mask) == 0) \ + return s; \ + \ + s++; \ + } \ + } + +#define READ_VAR_SIZE(type) \ + static inline int read_var_##type (progbuf_it_h iter, type *value, \ + int *negative) \ + { \ + type tmp = 0; \ + size_t prev_read_pos = iter->read_pos; \ + \ + int i = 0; \ + char byte; \ + const int bitsize = sizeof (type) * 8; \ + while (i < bitsize) \ + { \ + byte = iter->buf->buffer[iter->read_pos++]; \ + if (i == 0) \ + { \ + *negative = byte & 0x40; \ + tmp |= (type)(byte & 0x3F) << i; \ + i += 6; \ + } \ + else \ + { \ + tmp |= (type)(byte & 0x7F) << i; \ + i += 7; \ + } \ + \ + if ((byte & 0x80) == 0) \ + { \ + *value = tmp; \ + return 0; \ + } \ + } \ + \ + iter->read_pos = prev_read_pos; \ + return -1; \ + } + +#define WRITE_VAR_SIZE(type) \ + static inline void write_var_##type (progbuf_h buf, type value, int size, \ + int negative) \ + { \ + for (int i = 0; i < size - 1; ++i) \ + { \ + if (i == 0) \ + { \ + if (negative) \ + { \ + buf->buffer[buf->size] = (char)((value & 0x3F) | 0xC0); \ + } \ + else \ + { \ + buf->buffer[buf->size] = (char)((value & 0x3F) | 0x80); \ + } \ + value = (type)((type)value >> 6); \ + } \ + else \ + { \ + buf->buffer[buf->size + i] = (char)((value & 0x7F) | 0x80); \ + value = (type)((type)value >> 7); \ + } \ + } \ + \ + if (size == 1 && negative) \ + { \ + buf->buffer[buf->size] = (char)value | 0x40; \ + } \ + else \ + { \ + buf->buffer[buf->size + (size - 1)] = (char)value; \ + } \ + \ + buf->size += size; \ + } + +static inline int +check_buffer_and_expand (progbuf_h buf, int size) +{ + if (buf->size + size > buf->capacity) + { + char *newbuf = malloc (buf->capacity * 2); + if (!newbuf) + return PROGBUF_ERROR_MEM_ALLOC; + + memcpy (newbuf, buf->buffer, buf->capacity); + free (buf->buffer); + buf->buffer = newbuf; + buf->capacity *= 2; + } + return 0; +} + +DETERMINE_VAR_SIZE (uint) +READ_VAR_SIZE (uint) +WRITE_VAR_SIZE (uint) + +DETERMINE_VAR_SIZE (ulong) +READ_VAR_SIZE (ulong) +WRITE_VAR_SIZE (ulong) + +DETERMINE_VAR_SIZE (ulonglong) +READ_VAR_SIZE (ulonglong) +WRITE_VAR_SIZE (ulonglong) + +#define PROGBUF_SET(type, utype) \ + int progbuf_set_##type (progbuf_h buf, type value) \ + { \ + int val_size, ret; \ + \ + if (!buf) \ + return PROGBUF_ERROR_NULL_PARAM; \ + \ + val_size = determine_var_##utype##_size (ABS (value)); \ + ret = check_buffer_and_expand (buf, val_size + 1); \ + if (ret != 0) \ + return ret; \ + \ + buf->buffer[buf->size] = PROGBUF_TYPE_VAR_INT; \ + buf->size++; \ + \ + write_var_##utype (buf, ABS (value), val_size, value < 0); \ + \ + return PROGBUF_SUCCESS; \ + } + +#define PROGBUF_GET(type, utype) \ + int progbuf_get_##type (progbuf_it_h iter, type *value) \ + { \ + if (!iter || !value) \ + return PROGBUF_ERROR_NULL_PARAM; \ + \ + if (iter->read_pos >= iter->buf->size) \ + return PROGBUF_ERROR_END_OF_ITER; \ + \ + char val_type = iter->buf->buffer[iter->read_pos]; \ + \ + if ((val_type & PROGBUF_TYPE_VAR_INT) != PROGBUF_TYPE_VAR_INT) \ + return PROGBUF_ERROR_UNEXPECTED_TYPE; \ + \ + iter->read_pos++; \ + \ + utype u_value; \ + int negative; \ + if (read_var_##utype (iter, &u_value, &negative) != 0) \ + { \ + iter->read_pos--; \ + return PROGBUF_ERROR_READ; \ + } \ + \ + *value = (negative ? -u_value : u_value); \ + \ + return PROGBUF_SUCCESS; \ + } + +PROGBUF_SET (int, uint) +PROGBUF_GET (int, uint) + +PROGBUF_SET (uint, uint) +PROGBUF_GET (uint, uint) + +PROGBUF_SET (long, ulong) +PROGBUF_GET (long, ulong) + +PROGBUF_SET (ulong, ulong) +PROGBUF_GET (ulong, ulong) + +PROGBUF_SET (longlong, ulonglong) +PROGBUF_GET (longlong, ulonglong) + +PROGBUF_SET (ulonglong, ulonglong) +PROGBUF_GET (ulonglong, ulonglong) progbuf_h -progbuf_alloc (int message_tag, int version) +progbuf_alloc (long message_tag) { - struct progbuf_s *buf = calloc (1, sizeof (struct progbuf_s)); + struct progbuf_s *buf = malloc (sizeof (struct progbuf_s)); + + if (!buf) + return 0; + + buf->buffer = malloc (PROGBUF_INIT_BUFSIZ); + if (!buf->buffer) + { + free (buf); + return 0; + } + + buf->capacity = PROGBUF_INIT_BUFSIZ; + buf->size = 0; + buf->message_tag = message_tag; + + int tag_size = determine_var_ulong_size (ABS (message_tag)); + write_var_ulong (buf, ABS (message_tag), tag_size, message_tag < 0); + buf->header_size = tag_size; + return buf; } -void +progbuf_it_h +progbuf_iter_alloc (progbuf_h buf) +{ + if (!buf) + return 0; + + struct progbuf_it_s *iter = malloc (sizeof (struct progbuf_it_s)); + + if (!iter) + return 0; + + iter->buf = buf; + iter->read_pos = buf->header_size; + + return iter; +} + +int progbuf_free (progbuf_h buf) { - if (buf) + if (!buf) + return PROGBUF_ERROR_NULL_PARAM; + + free (buf->buffer); + free (buf); + + return PROGBUF_SUCCESS; +} + +int +progbuf_iter_free (progbuf_it_h iter) +{ + if (!iter) + return PROGBUF_ERROR_NULL_PARAM; + + free (iter); + + return PROGBUF_SUCCESS; +} + +int +progbuf_get_message_tag (progbuf_h buf, long *message_tag) +{ + if (!buf || !message_tag) + return PROGBUF_ERROR_NULL_PARAM; + + *message_tag = buf->message_tag; + + return PROGBUF_SUCCESS; +} + +int +progbuf_get_message_buffer (progbuf_h buf, char **buffer, size_t *size) +{ + if (!buf || (!buffer && !size)) + return PROGBUF_ERROR_NULL_PARAM; + + if (buffer) { - if (buf->buffer) - free (buf->buffer); + *buffer = buf->buffer; + } - free (buf); + if (size) + { + *size = buf->size; } + + return 0; } int -progbuf_set_int (progbuf_h buf, int value) +progbuf_iter_reset (progbuf_it_h iter) { - return -1; + if (!iter) + return PROGBUF_ERROR_NULL_PARAM; + + iter->read_pos = iter->buf->header_size; + + return PROGBUF_SUCCESS; } diff --git a/src/progbuf.h b/src/progbuf.h index da21548..8995862 100644 --- a/src/progbuf.h +++ b/src/progbuf.h @@ -1,10 +1,42 @@ #ifndef LIBPROGBUF_H #define LIBPROGBUF_H +#include + +#define PROGBUF_SUCCESS 0 +#define PROGBUF_ERROR_NULL_PARAM -1 +#define PROGBUF_ERROR_MEM_ALLOC -2 +#define PROGBUF_ERROR_END_OF_ITER -3 +#define PROGBUF_ERROR_UNEXPECTED_TYPE -4 +#define PROGBUF_ERROR_READ -5 +#define PROGBUF_ERROR_INCORRECT_SIGN -6 + typedef struct progbuf_s *progbuf_h; +typedef struct progbuf_it_s *progbuf_it_h; + +progbuf_h progbuf_alloc (long message_tag); + +int progbuf_get_message_tag (progbuf_h buf, long *message_tag); +int progbuf_get_message_buffer (progbuf_h buf, char **buffer, size_t *size); +int progbuf_free (progbuf_h buf); -progbuf_h progbuf_alloc (int message_tag, int version); -void progbuf_free (progbuf_h buf); int progbuf_set_int (progbuf_h buf, int value); +int progbuf_get_int (progbuf_it_h iter, int *value); +int progbuf_set_uint (progbuf_h buf, unsigned int value); +int progbuf_get_uint (progbuf_it_h iter, unsigned int *value); + +int progbuf_set_long (progbuf_h buf, long value); +int progbuf_get_long (progbuf_it_h iter, long *value); +int progbuf_set_ulong (progbuf_h buf, unsigned long value); +int progbuf_get_ulong (progbuf_it_h iter, unsigned long *value); + +int progbuf_set_longlong (progbuf_h buf, long long value); +int progbuf_get_longlong (progbuf_it_h iter, long long *value); +int progbuf_set_ulonglong (progbuf_h buf, unsigned long long value); +int progbuf_get_ulonglong (progbuf_it_h iter, unsigned long long *value); + +progbuf_it_h progbuf_iter_alloc (progbuf_h buf); +int progbuf_iter_free (progbuf_it_h iter); +int progbuf_iter_reset (progbuf_it_h iter); #endif diff --git a/src/test_progbuf.c b/src/test_progbuf.c deleted file mode 100644 index f6956fe..0000000 --- a/src/test_progbuf.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "progbuf.h" - -int -main () -{ - progbuf_h buf = progbuf_alloc (1, 1); - return 0; -} -- 2.20.1