Add getter and setter to support nested message
authorAhmet Artu Yildirim <ahmet@artulab.com>
Sat, 24 Dec 2022 06:43:56 +0000 (22:43 -0800)
committerAhmet Artu Yildirim <ahmet@artulab.com>
Sat, 24 Dec 2022 07:39:47 +0000 (23:39 -0800)
src/check_progbuf.c
src/common.h
src/progbuf.c
src/progbuf.h

index 06d0fb2..8e0fd88 100644 (file)
@@ -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;
 }
index f56318e..60b7313 100644 (file)
@@ -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
index 8d2747b..8a14f52 100644 (file)
@@ -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)
 {
index 806631a..306807e 100644 (file)
@@ -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);