diff --git a/protobuf.c b/protobuf.c index efc9525..9fc2f23 100644 --- a/protobuf.c +++ b/protobuf.c @@ -7,6 +7,47 @@ #include "varint.h" #include "protobuf.h" +int protobuf_encode_length_delimited(int field_number, enum WireType field_type, const char* incoming, size_t incoming_length, + unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) +{ + // push the field number and wire type together + 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; + // field size + varint_encode(incoming_length, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_processed); + *bytes_written += bytes_processed; + // field value + memcpy(&buffer[*bytes_written], incoming, incoming_length); + *bytes_written += incoming_length; + return 1; +} + +int protobuf_decode_length_delimited(const unsigned char* buffer, size_t buffer_length, char** results, size_t *results_length, size_t* bytes_read) { + size_t pos = 0; + *bytes_read = 0; + // grab the field size + *results_length = varint_decode(&buffer[pos], buffer_length - pos, bytes_read); + pos += *bytes_read; + + // allocate memory + *results = malloc(sizeof(char) * (*results_length)); + if ((*results) == NULL) + return 0; + + // copy the bytes + memcpy((*results), &buffer[pos], (*results_length)); + pos += (*results_length); + *bytes_read = pos; + + return 1; +} + + /*** * encode a string into the buffer * @param field_number the field number @@ -19,21 +60,7 @@ */ int protobuf_encode_string(int field_number, enum WireType field_type, const char* incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) { - // push the field number and wire type together - 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; - // field size - varint_encode(strlen(incoming), &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_processed); - *bytes_written += bytes_processed; - // field value - memcpy(&buffer[*bytes_written], incoming, strlen(incoming)); - *bytes_written += strlen(incoming); - return 1; + return protobuf_encode_length_delimited(field_number, field_type, incoming, strlen(incoming), buffer, max_buffer_length, bytes_written); } /*** diff --git a/protobuf.h b/protobuf.h index dee77e5..0aa1d73 100644 --- a/protobuf.h +++ b/protobuf.h @@ -20,6 +20,22 @@ enum WireType { WIRETYPE_32BIT }; +/*** + * Encode a length delimited field into the buffer + * @param field_number the field number + * @param wire_type the wire type + * @param incoming the values + * @param incoming_length the lenght of incoming + * @param buffer the pointer to where to place the encoded value + * @param max_buffer_length the buffer length remaining + * @param bytes_written the number of bytes written + * @returns true(1) on success + */ +int protobuf_encode_length_delimited(int field_number, enum WireType wire_type, const char* incoming, size_t incoming_length, + unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written); + +int protobuf_decode_length_delimited(const unsigned char* buffer, size_t buffer_length, char** results, size_t *results_length, size_t* bytes_read); + /*** * encode a string into the buffer * @param field_number the field number