diff --git a/src/geonames.c b/src/geonames.c index 5f8d019c..bd0f23b0 100644 --- a/src/geonames.c +++ b/src/geonames.c @@ -1,4 +1,5 @@ #include "geonames.h" +#include "msgpack_utils.h" #define DEFAULT_BUFFER_SIZE 4096 @@ -93,70 +94,6 @@ void geoname_destroy(geoname_t *self) { free(self); } -static char_array *read_string(char_array *str, size_t len, buffer_t *buffer) { - char_array_clear(str); - char_array_cat_len(str, buffer->data->a + buffer->offset, len); - buffer->offset += len; - return str; -} - -static bool bytes_reader(cmp_ctx_t *ctx, void *data, size_t size) { - buffer_t *buffer = ctx->buf; - if (buffer->offset + size > char_array_len(buffer->data)) { - return false; - } - memcpy(data, buffer->data->a + buffer->offset, size); - buffer->offset += size; - return true; -} - -static size_t bytes_writer(cmp_ctx_t *ctx, const void *data, size_t count) { - buffer_t *buffer = (buffer_t *)ctx->buf; - char_array_cat_len(buffer->data, (char *)data, count); - buffer->offset += count; - return count; -} - -bool cmp_read_str_size_or_nil(cmp_ctx_t *ctx, char_array **str, uint32_t *size) { - cmp_object_t obj; - - if (!cmp_read_object(ctx, &obj)) { - return false; - } - - if (cmp_object_is_str(&obj)) { - *size = obj.as.str_size; - *str = read_string(*str, *size, ctx->buf); - } else if (cmp_object_is_nil(&obj)) { - *size = 0; - char_array_clear(*str); - } - - return true; -} - -bool cmp_write_str_or_nil(cmp_ctx_t *ctx, char_array *str) { - if (str != NULL && char_array_len(str) > 0) { - return cmp_write_str(ctx, str->a, char_array_len(str)); - } else { - return cmp_write_nil(ctx); - } -} - -bool cmp_write_uint_vector(cmp_ctx_t *ctx, uint32_array *array) { - size_t n = array->n; - if (!cmp_write_array(ctx, n)) { - return false; - } - - for (size_t i = 0; i < n; i++) { - if (!cmp_write_uint(ctx, array->a[i])) { - return false; - } - } - return true; -} - bool geoname_deserialize_ctx(geoname_t *self, cmp_ctx_t *ctx) { uint32_t len; @@ -262,8 +199,8 @@ bool geoname_deserialize_ctx(geoname_t *self, cmp_ctx_t *ctx) { bool geoname_deserialize(geoname_t *self, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); return geoname_deserialize_ctx(self, &ctx); } @@ -301,8 +238,8 @@ bool geoname_serialize_ctx(geoname_t *self, cmp_ctx_t *ctx) { bool geoname_serialize(geoname_t *self, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); return geoname_serialize_ctx(self, &ctx); } @@ -463,8 +400,8 @@ bool gn_postal_code_deserialize_ctx(gn_postal_code_t *self, cmp_ctx_t *ctx) { bool gn_postal_code_deserialize(gn_postal_code_t *self, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); return gn_postal_code_deserialize_ctx(self, &ctx); } @@ -490,8 +427,8 @@ static bool gn_postal_code_serialize_ctx(gn_postal_code_t *self, cmp_ctx_t *ctx) bool gn_postal_code_serialize(gn_postal_code_t *self, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); return gn_postal_code_serialize_ctx(self, &ctx); @@ -526,8 +463,8 @@ void gn_postal_code_print(gn_postal_code_t *self) { bool geonames_generic_serialize(geonames_generic_t *gn, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); if (!cmp_write_u8(&ctx, (uint8_t)gn->type)) { return false; @@ -544,8 +481,8 @@ bool geonames_generic_serialize(geonames_generic_t *gn, char_array *str) { bool geonames_generic_deserialize(gn_type *type, geoname_t *geoname, gn_postal_code_t *postal_code, char_array *str) { cmp_ctx_t ctx; - buffer_t buffer = (buffer_t){str, 0}; - cmp_init(&ctx, &buffer, bytes_reader, bytes_writer); + msgpack_buffer_t buffer = (msgpack_buffer_t){str, 0}; + cmp_init(&ctx, &buffer, msgpack_bytes_reader, msgpack_bytes_writer); uint8_t geonames_type; diff --git a/src/geonames.h b/src/geonames.h index c5e572e2..06a0ae3a 100644 --- a/src/geonames.h +++ b/src/geonames.h @@ -11,7 +11,6 @@ extern "C" { #include #include "collections.h" -#include "cmp/cmp.h" #include "features.h" #include "string_utils.h" @@ -27,11 +26,6 @@ typedef enum { NUM_BOUNDARY_TYPES } boundary_type_t; -typedef struct buffer { - char_array *data; - int offset; -} buffer_t; - typedef struct geoname { uint32_t geonames_id; char_array *name; diff --git a/src/msgpack_utils.c b/src/msgpack_utils.c new file mode 100644 index 00000000..ec75ee68 --- /dev/null +++ b/src/msgpack_utils.c @@ -0,0 +1,99 @@ +#include "msgpack_utils.h" + +static char_array *read_string(char_array *str, size_t len, msgpack_buffer_t *buffer) { + char_array_clear(str); + char_array_cat_len(str, buffer->data->a + buffer->offset, len); + buffer->offset += len; + return str; +} + +bool msgpack_bytes_reader(cmp_ctx_t *ctx, void *data, size_t size) { + msgpack_buffer_t *buffer = ctx->buf; + if (buffer->offset + size > char_array_len(buffer->data)) { + return false; + } + memcpy(data, buffer->data->a + buffer->offset, size); + buffer->offset += size; + return true; +} + +size_t msgpack_bytes_writer(cmp_ctx_t *ctx, const void *data, size_t count) { + msgpack_buffer_t *buffer = (msgpack_buffer_t *)ctx->buf; + char_array_cat_len(buffer->data, (char *)data, count); + buffer->offset += count; + return count; +} + +bool cmp_read_str_size_or_nil(cmp_ctx_t *ctx, char_array **str, uint32_t *size) { + cmp_object_t obj; + + if (!cmp_read_object(ctx, &obj)) { + return false; + } + + if (cmp_object_is_str(&obj)) { + *size = obj.as.str_size; + *str = read_string(*str, *size, ctx->buf); + } else if (cmp_object_is_nil(&obj)) { + *size = 0; + char_array_clear(*str); + } + + return true; +} + +bool cmp_write_str_or_nil(cmp_ctx_t *ctx, char_array *str) { + if (str != NULL && char_array_len(str) > 0) { + return cmp_write_str(ctx, str->a, char_array_len(str)); + } else { + return cmp_write_nil(ctx); + } +} + +bool cmp_write_uint_vector(cmp_ctx_t *ctx, uint32_array *array) { + size_t n = array->n; + if (!cmp_write_array(ctx, n)) { + return false; + } + + for (size_t i = 0; i < n; i++) { + if (!cmp_write_uint(ctx, array->a[i])) { + return false; + } + } + return true; +} + +bool cmp_read_uint_vector(cmp_ctx_t *ctx, uint32_array **array) { + cmp_object_t obj; + + if (!cmp_read_object(ctx, &obj)) { + return false; + } + + if (!cmp_object_is_array(&obj)) { + return false; + } + + uint32_t size = 0; + if (!cmp_read_array(ctx, &size)) { + return false; + } + + if (size == 0) { + *array = NULL; + return true; + } + + uint32_array *tmp = uint32_array_new_size((size_t)size); + uint32_t value; + for (int i = 0; i < size; i++) { + if (!cmp_read_uint(ctx, &value)) { + uint32_array_destroy(tmp); + return false; + } + uint32_array_push(tmp, value); + } + *array = tmp; + return true; +} \ No newline at end of file diff --git a/src/msgpack_utils.h b/src/msgpack_utils.h new file mode 100644 index 00000000..63ef7f3a --- /dev/null +++ b/src/msgpack_utils.h @@ -0,0 +1,25 @@ +#ifndef MSGPACK_UTILS_H +#define MSGPACK_UTILS_H + +#include +#include + +#include "cmp/cmp.h" +#include "collections.h" +#include "string_utils.h" + +typedef struct msgpack_buffer { + char_array *data; + int offset; +} msgpack_buffer_t; + +bool msgpack_bytes_reader(cmp_ctx_t *ctx, void *data, size_t size); +size_t msgpack_bytes_writer(cmp_ctx_t *ctx, const void *data, size_t count); + +bool cmp_read_str_size_or_nil(cmp_ctx_t *ctx, char_array **str, uint32_t *size); +bool cmp_write_str_or_nil(cmp_ctx_t *ctx, char_array *str); + +bool cmp_read_uint_vector(cmp_ctx_t *ctx, uint32_array **array); +bool cmp_write_uint_vector(cmp_ctx_t *ctx, uint32_array *array); + +#endif \ No newline at end of file diff --git a/src/string_utils.c b/src/string_utils.c index f17c3c03..1aee090d 100644 --- a/src/string_utils.c +++ b/src/string_utils.c @@ -628,6 +628,10 @@ inline uint32_t cstring_array_start_token(cstring_array *self) { return index; } +inline void cstring_array_terminate(cstring_array *self) { + char_array_terminate(self->str); +} + inline uint32_t cstring_array_add_string(cstring_array *self, char *str) { uint32_t index = cstring_array_start_token(self); char_array_append(self->str, str); diff --git a/src/string_utils.h b/src/string_utils.h index bfe1f600..55b07b4b 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -150,9 +150,9 @@ uint32_t cstring_array_start_token(cstring_array *self); uint32_t cstring_array_add_string(cstring_array *self, char *str); uint32_t cstring_array_add_string_len(cstring_array *self, char *str, size_t len); - void cstring_array_append_string(cstring_array *self, char *str); void cstring_array_append_string_len(cstring_array *self, char *str, size_t len); +void cstring_array_terminate(cstring_array *self); int32_t cstring_array_get_offset(cstring_array *self, uint32_t i); char *cstring_array_get_string(cstring_array *self, uint32_t i); int64_t cstring_array_token_length(cstring_array *self, uint32_t i);