From e32efc5d212de4b2d16c962eed57670262e92eef Mon Sep 17 00:00:00 2001 From: Ahmet Artu Yildirim Date: Fri, 23 Dec 2022 22:43:56 -0800 Subject: [PATCH] Add getter and setter to support nested message --- src/check_progbuf.c | 114 +++++++++++++++++++++++++++++++++++++++++++- src/common.h | 1 + src/progbuf.c | 93 ++++++++++++++++++++++++++++++++++++ src/progbuf.h | 3 ++ 4 files changed, 210 insertions(+), 1 deletion(-) diff --git a/src/check_progbuf.c b/src/check_progbuf.c index 06d0fb2..8e0fd88 100644 --- a/src/check_progbuf.c +++ b/src/check_progbuf.c @@ -833,11 +833,119 @@ START_TEST (test_progbuf_write_read_multiple_arrays) } END_TEST +START_TEST (test_progbuf_write_read_message) +{ + int ret; + + progbuf_h buf = progbuf_alloc (7); + ck_assert (buf); + + ret = progbuf_set_float (buf, FLT_MAX); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_set_float (buf, FLT_MIN); + ck_assert (ret == PROGBUF_SUCCESS); + + progbuf_h container_buf = progbuf_alloc (11); + ck_assert (container_buf); + + ret = progbuf_set_int (container_buf, 17); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_set_message (container_buf, buf); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (buf); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_set_int (container_buf, 21); + ck_assert (ret == PROGBUF_SUCCESS); + + size_t size; + ret = progbuf_buffer_size (container_buf, &size); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (size == 18); + + progbuf_it_h iter = progbuf_iter_alloc (container_buf); + ck_assert (iter); + + long message_tag; + ret = progbuf_message_tag (container_buf, &message_tag); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (message_tag == 11); + + int i_value; + ret = progbuf_get_int (iter, &i_value); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (i_value == 17); + + progbuf_h nested_buf; + ret = progbuf_get_message (iter, &nested_buf); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_get_int (iter, &i_value); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (i_value == 21); + + ret = progbuf_iter_free (iter); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_buffer_size (nested_buf, &size); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (size == 11); + + ret = progbuf_message_tag (nested_buf, &message_tag); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (message_tag == 7); + + /* let's extend the nested message now*/ + ret = progbuf_set_int (nested_buf, 23); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_buffer_size (nested_buf, &size); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (size == 13); + + progbuf_it_h iter_nested = progbuf_iter_alloc (nested_buf); + ck_assert (iter_nested); + + float float_value; + ret = progbuf_get_float (iter_nested, &float_value); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (float_value == FLT_MAX); + + ret = progbuf_get_float (iter_nested, &float_value); + + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (float_value == FLT_MIN); + + ret = progbuf_get_float (iter_nested, &float_value); + ck_assert (ret == PROGBUF_ERROR_UNEXPECTED_TYPE); + + ret = progbuf_get_int (iter_nested, &i_value); + ck_assert (ret == PROGBUF_SUCCESS); + ck_assert (i_value == 23); + + struct progbuf_it_s *iter_internal = iter_nested; + ck_assert (iter_internal->read_pos == 13); + + ret = progbuf_iter_free (iter_nested); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (nested_buf); + ck_assert (ret == PROGBUF_SUCCESS); + + ret = progbuf_free (container_buf); + ck_assert (ret == PROGBUF_SUCCESS); +} + static Suite * progbuf_suite (void) { Suite *s; - TCase *tc_basic, *tc_long, *tc_longlong, *tc_load, *tc_float, *tc_array; + TCase *tc_basic, *tc_long, *tc_longlong, *tc_load, *tc_float, *tc_array, + *tc_message; s = suite_create ("progbuf test suite"); @@ -869,12 +977,16 @@ progbuf_suite (void) tcase_add_test (tc_array, test_progbuf_write_read_raw_data); tcase_add_test (tc_array, test_progbuf_write_read_multiple_arrays); + tc_message = tcase_create ("encode_message"); + tcase_add_test (tc_message, test_progbuf_write_read_message); + suite_add_tcase (s, tc_basic); suite_add_tcase (s, tc_long); suite_add_tcase (s, tc_longlong); suite_add_tcase (s, tc_load); suite_add_tcase (s, tc_float); suite_add_tcase (s, tc_array); + suite_add_tcase (s, tc_message); return s; } diff --git a/src/common.h b/src/common.h index f56318e..60b7313 100644 --- a/src/common.h +++ b/src/common.h @@ -12,6 +12,7 @@ #define PROGBUF_TYPE_DOUBLE 0x03 #define PROGBUF_TYPE_CHAR 0x04 #define PROGBUF_TYPE_RAW 0x05 +#define PROGBUF_TYPE_MESSAGE 0x06 #define PROGBUF_TYPE_ARRAY 0x10 #define PROGBUF_TYPE_VAR_INT_ARRAY 0x11 #define PROGBUF_TYPE_VAR_FLOAT_ARRAY 0x12 diff --git a/src/progbuf.c b/src/progbuf.c index 8d2747b..8a14f52 100644 --- a/src/progbuf.c +++ b/src/progbuf.c @@ -699,6 +699,99 @@ progbuf_get_raw_data (progbuf_it_h iter, void **ptr, size_t *len) return PROGBUF_SUCCESS; } +int +progbuf_set_message (progbuf_h buf, const progbuf_h message) +{ + int val_size, ret; + + if (!buf || !message) + return PROGBUF_ERROR_NULL_PARAM; + + if (!buf->buffer || !message->buffer) + return PROGBUF_ERROR_NOT_OWNING; + + val_size = determine_var_size_t_size (message->size); + ret = check_buffer_and_expand (buf, 1 + val_size + message->size); + if (ret != 0) + return ret; + + buf->buffer[buf->size] = PROGBUF_TYPE_MESSAGE; + buf->size++; + + write_var_size_t (buf, message->size, val_size, 0); + memcpy (buf->buffer + buf->size, message->buffer, message->size); + buf->size += message->size; + + return PROGBUF_SUCCESS; +} + +int +progbuf_get_message (progbuf_it_h iter, progbuf_h *message) +{ + if (!iter || !message) + return PROGBUF_ERROR_NULL_PARAM; + + if (!iter->buf->buffer) + return PROGBUF_ERROR_NOT_OWNING; + + 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_MESSAGE) != PROGBUF_TYPE_MESSAGE) + return PROGBUF_ERROR_UNEXPECTED_TYPE; + + iter->read_pos++; + + size_t size; + size_t prev_read_pos = iter->read_pos; + int negative; + if (read_var_size_t (iter, &size, &negative) != 0) + { + iter->read_pos--; + return PROGBUF_ERROR_READ; + } + + void *buffer = malloc (size); + + if (!buffer) + { + iter->read_pos -= (1 + iter->read_pos - prev_read_pos); + return PROGBUF_ERROR_MEM_ALLOC; + } + + memcpy (buffer, iter->buf->buffer + iter->read_pos, size); + iter->read_pos += size; + + ulong message_tag; + + struct progbuf_s *buf = malloc (sizeof (struct progbuf_s)); + buf->buffer = buffer; + + struct progbuf_it_s tag_iter; + tag_iter.buf = buf; + tag_iter.read_pos = 0; + + if (read_var_ulong (&tag_iter, &message_tag, &negative) != 0) + { + iter->read_pos -= (1 + size + iter->read_pos - prev_read_pos); + free (buffer); + free (buf); + return PROGBUF_ERROR_READ; + } + + buf->message_tag = (negative ? -message_tag : message_tag); + buf->header_size = determine_var_ulong_size (ABS (buf->message_tag)); + + buf->size = size; + buf->capacity = size; + + *message = buf; + + return PROGBUF_SUCCESS; +} + int progbuf_set_string (progbuf_h buf, const char *str) { diff --git a/src/progbuf.h b/src/progbuf.h index 806631a..306807e 100644 --- a/src/progbuf.h +++ b/src/progbuf.h @@ -54,6 +54,9 @@ int progbuf_get_string (progbuf_it_h iter, char **str); int progbuf_set_raw_data (progbuf_h buf, const void *ptr, size_t len); int progbuf_get_raw_data (progbuf_it_h iter, void **ptr, size_t *len); +int progbuf_set_message (progbuf_h buf, const progbuf_h message); +int progbuf_get_message (progbuf_it_h iter, progbuf_h *message); + int progbuf_set_int_array (progbuf_h buf, const int *arr, size_t len); int progbuf_get_int_array (progbuf_it_h iter, int **arr, size_t *len); int progbuf_set_uint_array (progbuf_h buf, const unsigned int *arr, size_t len); -- 2.20.1