bser.c (358 lines of code) (raw):

#define _POSIX_C_SOURCE 200809L #include <string.h> #include <stdarg.h> #include <assert.h> #include "bser.h" #include "bser_private.h" int bser_is_integer(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_INT64; } int bser_is_real(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_REAL; } int bser_is_true(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_TRUE; } int bser_is_false(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_FALSE; } int bser_is_boolean(bser_t* bser) { return bser_is_true(bser) || bser_is_false(bser); } int bser_is_null(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_NULL; } int bser_is_string(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_STRING; } int bser_is_array(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_ARRAY; } int bser_is_object(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_OBJECT; } int bser_is_error(bser_t* bser) { bser_parse_if_necessary(bser); return bser->type == BSER_TAG_ERROR; } int64_t bser_integer_value(bser_t* bser) { bser_parse_if_necessary(bser); assert(bser_is_integer(bser)); return bser->value.integer; } double bser_real_value(bser_t* bser) { bser_parse_if_necessary(bser); assert(bser_is_real(bser)); return bser->value.real; } const char* bser_string_value(bser_t* bser, size_t* length_ret) { bser_parse_if_necessary(bser); assert(bser_is_string(bser)); *length_ret = bser->value.string.length; return bser->value.string.chars; } size_t bser_array_size(bser_t* bser) { bser_parse_if_necessary(bser); assert(bser_is_array(bser)); return bser->value.array.length; } size_t bser_object_size(bser_t* bser) { bser_parse_if_necessary(bser); assert(bser_is_object(bser)); return bser->value.object.length; } const char* bser_error_message(bser_t* bser) { assert(bser_is_error(bser)); return bser->value.error_message; } bser_t* bser_new_integer(int64_t value, bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_INT64; fill->value.integer = value; return fill; } bser_t* bser_new_real(double value, bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_REAL; fill->value.real = value; return fill; } bser_t* bser_new_true(bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_TRUE; return fill; } bser_t* bser_new_false(bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_FALSE; return fill; } bser_t* bser_new_null(bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_NULL; return fill; } bser_t* bser_new_string(const char* chars, size_t len, bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_STRING; fill->value.string.chars = chars; fill->value.string.length = len; return fill; } bser_t* bser_new_array(bser_t* elems, size_t len, bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_ARRAY; fill->value.array.elements = elems; fill->value.array.length = len; return fill; } bser_t* bser_new_object(bser_key_value_pair_t* fields, size_t length, bser_t* fill) { if (fill == NULL) { fill = bser_alloc(); } fill->type = BSER_TAG_OBJECT; fill->value.object.fields = fields; fill->value.object.length = length; return fill; } static void bser_free_array_contents(bser_t* bser) { assert(bser_is_array(bser)); for (int i = 0; i < bser->value.array.length; ++i) { bser_free_contents(&bser->value.array.elements[i]); } free(bser->value.array.elements); } static void bser_free_object_contents(bser_t* bser) { assert(bser_is_object(bser)); for (int i = 0; i < bser->value.object.length; ++i) { bser_free_contents(&bser->value.object.fields[i].value); } free(bser->value.object.fields); } void bser_free_contents(bser_t* bser) { if (bser_is_array(bser)) { bser_free_array_contents(bser); } else if (bser_is_object(bser)) { bser_free_object_contents(bser); } bser->type = BSER_TAG_ERROR; bser->value.error_message = "<deallocated>"; } void bser_free(bser_t* bser) { bser_free_contents(bser); free(bser); } int bser_string_strcmp(const char* match, bser_t* bser) { int cmp; assert(bser_is_string(bser)); bser_parse_if_necessary(bser); size_t match_len = strlen(match); size_t bser_len = bser->value.string.length; const char* bser_value = bser->value.string.chars; if (match_len > bser_len) { cmp = memcmp(match, bser_value, bser_len); cmp = cmp == 0 ? (unsigned char)match[bser_len] : cmp; } else if (bser_len > match_len) { cmp = memcmp(match, bser_value, match_len); cmp = cmp == 0 ? (unsigned char)bser_value[match_len] : cmp; } else { cmp = memcmp(match, bser_value, match_len); } return cmp; } bser_t* bser_object_get(bser_t* bser, const char* key) { assert(bser_is_object(bser)); for (int i = 0; i < bser->value.object.length; ++i) { bser_key_value_pair_t* pair = bser_object_pair_at(bser, i); bser_parse_if_necessary(&pair->key); assert(bser_is_string(&pair->key)); bser_parse_if_necessary(&pair->value); if (!bser_string_strcmp(key, &pair->key)) { if (bser_is_no_field(&pair->value)) { return NULL; } else { return &pair->value; } } } return NULL; } bser_t* bser_array_get(bser_t* bser, size_t index) { bser_parse_if_necessary(bser); assert(bser_is_array(bser)); assert(index < bser->value.array.length); bser_t* element = &bser->value.array.elements[index]; /* Can't return an unparsed element unless all elements prior * have been parsed. */ bser_parse_array_elements_to(bser, index); return element; } bser_t* bser_object_key_at(bser_t* bser, size_t index) { bser_parse_if_necessary(bser); assert(bser_is_object(bser)); bser_key_value_pair_t* field = bser_object_pair_at(bser, index); if (bser_is_unparsed(&field->key)) { bser_parse_object_fields_to(bser, index); } return &field->key; } bser_t* bser_object_value_at(bser_t* bser, size_t index) { bser_parse_if_necessary(bser); assert(bser_is_object(bser)); bser_key_value_pair_t* field = bser_object_pair_at(bser, index); if (bser_is_unparsed(&field->value)) { bser_parse_object_fields_to(bser, index); bser_parse_if_necessary(&field->key); } if (bser_is_no_field(&field->value)) { return NULL; } else { return &field->value; } } static void fill_in_error(const char* msg, json_error_t* err) { memset(err, 0, sizeof(*err)); strncpy(err->text, msg, JSON_ERROR_TEXT_LENGTH - 1); } json_t* bser2json(bser_t* bser, json_error_t* err) { if (bser_is_integer(bser)) { json_int_t v = bser_integer_value(bser); return json_integer(v); } else if (bser_is_real(bser)) { double v = bser_real_value(bser); return json_real(v); } else if (bser_is_true(bser)) { return json_true(); } else if (bser_is_false(bser)) { return json_false(); } else if (bser_is_null(bser)) { return json_null(); } else if (bser_is_string(bser)) { size_t length; const char* str = bser_string_value(bser, &length); char* dup = strndup(str, length); json_t* string = json_string(dup); free(dup); return string; } else if (bser_is_array(bser)) { size_t length = bser_array_size(bser); json_t* array = json_array(); for (int i = 0; i < length; ++i) { json_t* elem = bser2json(bser_array_get(bser, i), err); if (elem == NULL) { return NULL; } json_array_append_new(array, elem); } return array; } else if (bser_is_object(bser)) { size_t length = bser_object_size(bser); json_t* object = json_object(); for (int i = 0; i < length; ++i) { size_t key_length; bser_t* key = bser_object_key_at(bser, i); assert(bser_is_string(key)); bser_t* value = bser_object_value_at(bser, i); if (!bser_is_no_field(value)) { const char* key_chars = bser_string_value(key, &key_length); assert(key_chars != NULL && *key_chars != '\0'); char* key_dup = strndup(key_chars, key_length); json_t* field_value = bser2json(value, err); if (field_value == NULL) { return NULL; } json_object_set_new(object, key_dup, field_value); free(key_dup); } } return object; } else if (bser_is_error(bser)) { fill_in_error(bser_error_message(bser), err); return NULL; } else { fill_in_error("Unknown bser node type", err); return NULL; } }