Fixed protobuf bugs and added 3rd example of a complex object
This commit is contained in:
parent
a443c699cf
commit
9983fbbb83
5 changed files with 34 additions and 6 deletions
|
@ -48,6 +48,7 @@ int protobuf_encode_string(int field_number, enum WireType field_type, const cha
|
||||||
*/
|
*/
|
||||||
int protobuf_encode_varint(int field_number, enum WireType field_type, unsigned long long incoming, unsigned char* buffer,
|
int protobuf_encode_varint(int field_number, enum WireType field_type, unsigned long long incoming, unsigned char* buffer,
|
||||||
size_t max_buffer_length, size_t* bytes_written) {
|
size_t max_buffer_length, size_t* bytes_written) {
|
||||||
|
*bytes_written = 0;
|
||||||
// push the field number and wire type together
|
// push the field number and wire type together
|
||||||
unsigned int field_no = field_number << 3;
|
unsigned int field_no = field_number << 3;
|
||||||
unsigned long long field = field_no | field_type;
|
unsigned long long field = field_no | field_type;
|
||||||
|
@ -72,17 +73,20 @@ int protobuf_encode_varint(int field_number, enum WireType field_type, unsigned
|
||||||
*/
|
*/
|
||||||
int protobuf_decode_string(const unsigned char* buffer, size_t buffer_length, char** results, size_t* bytes_read) {
|
int protobuf_decode_string(const unsigned char* buffer, size_t buffer_length, char** results, size_t* bytes_read) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
*bytes_read = 0;
|
||||||
// grab the field size
|
// grab the field size
|
||||||
int length = varint_decode(&buffer[pos], buffer_length - pos, bytes_read);
|
int length = varint_decode(&buffer[pos], buffer_length - pos, bytes_read);
|
||||||
pos += *bytes_read;
|
pos += *bytes_read;
|
||||||
|
|
||||||
// allocate memory
|
// allocate memory
|
||||||
*results = malloc(sizeof(char) * length);
|
*results = malloc(sizeof(char) * length + 1);
|
||||||
if ((*results) == NULL)
|
if ((*results) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// copy the string
|
// copy the string
|
||||||
memcpy((*results), &buffer[pos], length);
|
memcpy((*results), &buffer[pos], length);
|
||||||
|
// don't forget the null
|
||||||
|
(*results)[length] = 0;
|
||||||
pos += length;
|
pos += length;
|
||||||
*bytes_read = pos;
|
*bytes_read = pos;
|
||||||
|
|
||||||
|
@ -98,9 +102,10 @@ int protobuf_decode_string(const unsigned char* buffer, size_t buffer_length, ch
|
||||||
* @param bytes_read the number of bytes read from the buffer
|
* @param bytes_read the number of bytes read from the buffer
|
||||||
*/
|
*/
|
||||||
int protobuf_decode_field_and_type(const unsigned char* buffer, int buffer_length, int *field_no, enum WireType *field_type, size_t* bytes_read) {
|
int protobuf_decode_field_and_type(const unsigned char* buffer, int buffer_length, int *field_no, enum WireType *field_type, size_t* bytes_read) {
|
||||||
|
*bytes_read = 0;
|
||||||
unsigned long long field = varint_decode(buffer, buffer_length, bytes_read);
|
unsigned long long field = varint_decode(buffer, buffer_length, bytes_read);
|
||||||
*field_no = field >> 3;
|
*field_no = field >> 3;
|
||||||
*field_type = field | *field_no;
|
*field_type = field & *field_no;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ int Test1_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Te
|
||||||
Test1_free(*output);
|
Test1_free(*output);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
pos += bytes_read;
|
||||||
switch (field_no) {
|
switch (field_no) {
|
||||||
case (1):
|
case (1):
|
||||||
(*output)->a = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
|
(*output)->a = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
|
||||||
|
|
|
@ -33,7 +33,16 @@ int Test3_protobuf_encode(struct Test3* incoming, unsigned char* buffer, size_t
|
||||||
*bytes_written += 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);
|
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;
|
*bytes_written += bytes_used;
|
||||||
return Test2_protobuf_encode(incoming->test2, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
|
// write Test2 to safe area
|
||||||
|
int pos = *bytes_written + 11;
|
||||||
|
size_t test2_size = 0;
|
||||||
|
int retVal = Test2_protobuf_encode(incoming->test2, &buffer[pos], max_buffer_length - pos, &test2_size);
|
||||||
|
protobuf_encode_varint(3, Test3_message_fields[2], test2_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
|
||||||
|
*bytes_written += bytes_used;
|
||||||
|
// now move the encoded Test2 to the correct area
|
||||||
|
memcpy(&buffer[*bytes_written], &buffer[pos], test2_size);
|
||||||
|
*bytes_written += test2_size;
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test3** output) {
|
int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Test3** output) {
|
||||||
|
@ -59,10 +68,13 @@ int Test3_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Te
|
||||||
(*output)->an_int = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
|
(*output)->an_int = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
break;
|
break;
|
||||||
case(3):
|
case(3): {
|
||||||
Test2_protobuf_decode(&buffer[pos], buffer_length - pos, &((*output)->test2));
|
size_t test2_size = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
Test2_protobuf_decode(&buffer[pos], buffer_length - pos, &((*output)->test2));
|
||||||
|
pos += test2_size;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -65,7 +65,7 @@ int test_complex_protobuf() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(results->test2->a, test3->test2->a) == 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);
|
printf("String a does not match: %s vs %s\n", test3->test2->a, results->test2->a);
|
||||||
Test3_free(test3);
|
Test3_free(test3);
|
||||||
Test3_free(results);
|
Test3_free(results);
|
||||||
|
@ -145,6 +145,15 @@ int test_write_simple() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Test1* results;
|
||||||
|
retVal = Test1_protobuf_decode(buffer, bytes_written, &results);
|
||||||
|
|
||||||
|
if (results->a != test1.a) {
|
||||||
|
printf("Incorrect results after decode");
|
||||||
|
Test1_free(results);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
varint.c
1
varint.c
|
@ -61,6 +61,7 @@ unsigned char* varint_encode(const unsigned long long n, unsigned char* buf, int
|
||||||
*/
|
*/
|
||||||
unsigned long long varint_decode(const unsigned char* buf, int len, size_t* bytes) {
|
unsigned long long varint_decode(const unsigned char* buf, int len, size_t* bytes) {
|
||||||
unsigned long long result = 0;
|
unsigned long long result = 0;
|
||||||
|
if (bytes != NULL) *bytes = 0;
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
const unsigned char* ptr = buf;
|
const unsigned char* ptr = buf;
|
||||||
unsigned long long ll;
|
unsigned long long ll;
|
||||||
|
|
Loading…
Reference in a new issue