diff --git a/sml/include/sml/sml_list.h b/sml/include/sml/sml_list.h index 923f5dd..7251f78 100644 --- a/sml/include/sml/sml_list.h +++ b/sml/include/sml/sml_list.h @@ -48,6 +48,7 @@ typedef struct sml_list_entry { sml_list *sml_list_init(); void sml_list_write(sml_list *list, sml_buffer *buf); +void sml_list_add(sml_list *list, sml_list *new_entry); sml_list *sml_list_parse(sml_buffer *buf); diff --git a/sml/src/sml_list.c b/sml/src/sml_list.c index 48d430a..772c5a0 100644 --- a/sml/src/sml_list.c +++ b/sml/src/sml_list.c @@ -25,6 +25,9 @@ #include #include +void sml_list_entry_free(sml_list *list) ; +sml_list *sml_list_entry_parse(sml_buffer *buf); +void sml_list_entry_write(sml_list *list, sml_buffer *buf); sml_list *sml_list_init(){ sml_list *s = (sml_list *)malloc(sizeof(sml_list)); @@ -33,75 +36,123 @@ sml_list *sml_list_init(){ return s; } +void sml_list_add(sml_list *list, sml_list *new_entry) { + list->next = new_entry; +} + +// This function doesn't free the allocated memory in error cases, +// this is done in sml_list_parse. +sml_list *sml_list_entry_parse(sml_buffer *buf) { + if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (sml_buf_get_next_length(buf) != 7) { + buf->error = 1; + goto error; + } + sml_list *l = sml_list_init(); + + l->obj_name = sml_octet_string_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->status = sml_status_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->val_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->unit = sml_u8_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->scaler = sml_i8_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->value = sml_value_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + l->value_signature = sml_octet_string_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + + return l; + + error: + printf("error\n"); + buf->error = 1; + return 0; +} + sml_list *sml_list_parse(sml_buffer *buf) { - int elems, i; + if (sml_buf_optional_is_skipped(buf)) { + return 0; + } + if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) { buf->error = 1; return 0; } - elems = sml_buf_get_next_length(buf); - sml_list *start = 0; - sml_list *cur = 0; - sml_list *tmp; + sml_list *first = 0; + sml_list *last = 0; + int elems; - for (i = 0; i < elems; i++) { - - if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) { - buf->error = 1; - goto error; - } - - if (sml_buf_get_next_length(buf) != 7) { - buf->error = 1; - goto error; - } - - tmp = (sml_list *) malloc(sizeof(sml_list)); - if (i == 0) { - start = tmp; - cur = tmp; - } - else { - cur->next = tmp; - cur = tmp; - } + elems = sml_buf_get_next_length(buf); - cur->obj_name = sml_octet_string_parse(buf); + if (elems > 0) { + first = sml_list_entry_parse(buf); if (sml_buf_has_errors(buf)) goto error; - - cur->status = SML_SKIP_OPTIONAL sml_status_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->val_time = SML_SKIP_OPTIONAL sml_time_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->unit = SML_SKIP_OPTIONAL sml_u8_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->scaler = SML_SKIP_OPTIONAL sml_i8_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->value = SML_SKIP_OPTIONAL sml_value_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->value_signature = sml_octet_string_parse(buf); - if (sml_buf_has_errors(buf)) goto error; - - cur->next = 0; + last = first; + elems--; } - return start; + + while(elems > 0) { + last->next = sml_list_entry_parse(buf); + if (sml_buf_has_errors(buf)) goto error; + last = last->next; + elems--; + } + + return first; error: buf->error = 1; - sml_list_free(start); + sml_list_free(first); return 0; } +void sml_list_entry_write(sml_list *list, sml_buffer *buf) { + sml_buf_set_type_and_length(buf, SML_TYPE_LIST, 7); + sml_octet_string_write(list->obj_name, buf); + sml_status_write(list->status, buf); + sml_time_write(list->val_time, buf); + sml_u8_write(list->unit, buf); + sml_i8_write(list->scaler, buf); + sml_value_write(list->value, buf); + sml_octet_string_write(list->value_signature, buf); +} + void sml_list_write(sml_list *list, sml_buffer *buf){ - sml_buf_set_type_and_length(buf, SML_TYPE_LIST, 1); - sml_buf_optional_write(buf); - // + if (list == 0) { + sml_buf_optional_write(buf); + return; + } + + sml_list *i = list; + int len = 0; + while(i) { + i = i->next; + len++; + } + + sml_buf_set_type_and_length(buf, SML_TYPE_LIST, len); + + i = list; + while(i) { + sml_list_entry_write(i, buf); + i = i->next; + } + } void sml_list_entry_free(sml_list *list) { diff --git a/test/src/sml_list_test.c b/test/src/sml_list_test.c index 7ff1879..d1408c2 100644 --- a/test/src/sml_list_test.c +++ b/test/src/sml_list_test.c @@ -33,10 +33,58 @@ TEST_TEAR_DOWN(sml_list) { } TEST(sml_list, init) { - sml_list *v = sml_list_init(); - TEST_ASSERT_NOT_NULL(v); + sml_list *l = sml_list_init(); + TEST_ASSERT_NOT_NULL(l); + TEST_ASSERT_NULL(l->next); +} + +TEST(sml_list, add) { + sml_list *l = sml_list_init(); + sml_list *n = sml_list_init(); + sml_list_add(l, n); + TEST_ASSERT_NOT_NULL(l); + TEST_ASSERT_NOT_NULL(l->next); + TEST_ASSERT_TRUE(n == l->next); +} + +TEST(sml_list, parse_two_entries) { + hex2binary("727702610101010142000177026101010101420001", sml_buf_get_current_buf(buf)); + sml_list *l = sml_list_parse(buf); + + TEST_ASSERT_FALSE(sml_buf_has_errors(buf)); + TEST_ASSERT_NOT_NULL(l); + TEST_ASSERT_NOT_NULL(l->next); + TEST_ASSERT_EQUAL(0, sml_octet_string_cmp_with_hex(l->obj_name, "61")); +} + +TEST(sml_list, parse_optional) { + hex2binary("01", sml_buf_get_current_buf(buf)); + sml_list *l = sml_list_parse(buf); + TEST_ASSERT_NULL(l); + TEST_ASSERT_FALSE(sml_buf_has_errors(buf)); +} + +TEST(sml_list, write_one_entry) { + sml_list *l = sml_list_init(); + l->obj_name = sml_octet_string_init((unsigned char *)"Hallo", 5); + l->value = sml_value_init(); + l->value->type = SML_TYPE_OCTET_STRING; + l->value->data.bytes = sml_octet_string_init((unsigned char *)"Hallo", 5); + + sml_list_write(l, buf); + expected_buf(buf, "71770648616C6C6F010101010648616C6C6F01", 19); +} + +TEST(sml_list, write_optional) { + sml_list_write(0, buf); + expected_buf(buf, "01", 1); } TEST_GROUP_RUNNER(sml_list) { RUN_TEST_CASE(sml_list, init); + RUN_TEST_CASE(sml_list, add); + RUN_TEST_CASE(sml_list, parse_two_entries); + RUN_TEST_CASE(sml_list, parse_optional); + RUN_TEST_CASE(sml_list, write_one_entry); + RUN_TEST_CASE(sml_list, write_optional); }