diff --git a/protobuf.c b/protobuf.c index 5ad42ab..24a48a0 100644 --- a/protobuf.c +++ b/protobuf.c @@ -23,6 +23,7 @@ int protobuf_encode_string(int field_number, enum WireType field_type, const cha unsigned int field_no = field_number << 3; unsigned long long field = field_no | field_type; size_t bytes_processed; + *bytes_written = 0; // field type & number varint_encode(field, buffer, max_buffer_length, &bytes_processed); *bytes_written += bytes_processed; diff --git a/test/Makefile b/test/Makefile index 25b5a72..7a17da4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,7 +2,7 @@ CC = gcc CFLAGS = -O0 -g3 -Wall -I../ LFLAGS = DEPS = ../protobuf.h -OBJS = testit.o ../protobuf.o ../varint.o Test1_protobuf.o Test2_protobuf.o +OBJS = testit.o ../protobuf.o ../varint.o Test1_protobuf.o Test2_protobuf.o Test3_protobuf.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/test/Test3_protobuf.c b/test/Test3_protobuf.c new file mode 100644 index 0000000..3acfac4 --- /dev/null +++ b/test/Test3_protobuf.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include "protobuf.h" +#include "varint.h" +#include "Test3_protobuf.h" + +enum WireType Test3_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_VARINT, WIRETYPE_LENGTH_DELIMITED }; + +int Test3_new(struct Test3** test3) { + *test3 = (struct Test3*)malloc(sizeof(struct Test3)); + if (*test3 == NULL) + return 0; + (*test3)->a_string = NULL; + (*test3)->an_int = 0; + (*test3)->test2 = NULL; + return 1; +} + +int Test3_free(struct Test3* test3) { + if (test3->a_string != NULL) + free(test3->a_string); + if (test3->test2 != NULL) + Test2_free(test3->test2); + free(test3); + return 1; +} + +int Test3_protobuf_encode(struct Test3* incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) { + size_t bytes_used; + *bytes_written = 0; + protobuf_encode_string(1, Test3_message_fields[0], incoming->a_string, buffer, max_buffer_length, &bytes_used); + *bytes_written += bytes_used; + protobuf_encode_varint(2, Test3_message_fields[1], incoming->an_int, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); + *bytes_written += bytes_used; + return Test2_protobuf_encode(incoming->test2, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); +} + +int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test3** output) { + size_t pos = 0; + if (Test3_new(output) == 0) + return 0; + + while (pos < buffer_length) { // loop through buffer + size_t bytes_read = 0; + int field_no; + enum WireType field_type; + if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) { + Test3_free(*output); + return 0; + } + pos += bytes_read; + switch (field_no) { + case(1): + protobuf_decode_string(&buffer[pos], buffer_length - pos, &((*output)->a_string), &bytes_read); + pos += bytes_read; + break; + case (2): + (*output)->an_int = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); + pos += bytes_read; + break; + case(3): + Test2_protobuf_decode(&buffer[pos], buffer_length - pos, &((*output)->test2)); + pos += bytes_read; + break; + } + } + return 1; +} diff --git a/test/Test3_protobuf.h b/test/Test3_protobuf.h new file mode 100644 index 0000000..d859ddc --- /dev/null +++ b/test/Test3_protobuf.h @@ -0,0 +1,22 @@ +/* + * Test3_protobuf.h + */ + +#pragma once + +#include "protobuf.h" + +#include "Test2_protobuf.h" + +struct Test3 { + char* a_string; + int an_int; + struct Test2* test2; +}; + +int Test3_new(struct Test3** test1); +int Test3_free(struct Test3* test1); + +int Test3_protobuf_encode(struct Test3* incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written); +int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test3** output); + diff --git a/test/test_protobuf.h b/test/test_protobuf.h index 47bec42..599e58c 100644 --- a/test/test_protobuf.h +++ b/test/test_protobuf.h @@ -17,10 +17,65 @@ * int Test1_protobuf_encode(struct Test1* incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written); * int Test1_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test1** output); */ +#include +#include +#include "Test3_protobuf.h" #include "Test1_protobuf.h" #include "Test2_protobuf.h" +int test_complex_protobuf() { + int buffer_length = 255; + size_t bytes_used = 0; + unsigned char buffer[buffer_length]; + + // build the objects + struct Test2* test2; + Test2_new(&test2); + struct Test3* test3; + Test3_new(&test3); + test3->test2 = test2; + + // set values + test3->a_string = malloc(15); + strcpy(test3->a_string, "Hello, World!"); + test3->an_int = 29; + test3->test2->a = malloc(10); + strcpy(test3->test2->a, "Testing"); + + // encode + Test3_protobuf_encode(test3, buffer, buffer_length, &bytes_used); + + // decode + struct Test3* results; + Test3_protobuf_decode(buffer, bytes_used, &results); + + // view results + if (strcmp(results->a_string, test3->a_string) != 0) { + printf("String a does not match: %s vs %s\n", test3->a_string, results->a_string); + Test3_free(test3); + Test3_free(results); + return 0; + } + + if (results->an_int != test3->an_int) { + printf("Integers do not match: %d vs %d\n", test3->an_int, results->an_int); + Test3_free(test3); + Test3_free(results); + return 0; + } + + if (strcmp(results->test2->a, test3->test2->a) == 0) { + printf("String a does not match: %s vs %s\n", test3->test2->a, results->test2->a); + Test3_free(test3); + Test3_free(results); + return 0; + } + + return 1; + +} + int test_rightshift() { struct Test1 test1; test1.a = 0; diff --git a/test/testit.c b/test/testit.c index a510f65..3d8faf8 100644 --- a/test/testit.c +++ b/test/testit.c @@ -19,6 +19,7 @@ const char* names[] = { "test_write_negative", "test_write_string", "test_rightshift", + "test_complex_protobuf", "test_varint" }; @@ -27,6 +28,7 @@ int (*funcs[])(void) = { test_write_negative, test_write_string, test_rightshift, + test_complex_protobuf, test_varint };