diff options
author | David Robillard <d@drobilla.net> | 2018-05-12 18:03:13 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-07 15:32:24 -0500 |
commit | d4ae57afbd7da668dbf89f7b7e66e2f064437a98 (patch) | |
tree | ed521f64a0e844ce9fbd0cd7794739a6f292d766 /src/node.c | |
parent | 471ef4960aba6b5e1c9445229cddc0b3eb9ca148 (diff) | |
download | serd-d4ae57afbd7da668dbf89f7b7e66e2f064437a98.tar.gz serd-d4ae57afbd7da668dbf89f7b7e66e2f064437a98.tar.bz2 serd-d4ae57afbd7da668dbf89f7b7e66e2f064437a98.zip |
Set datatypes on integer, decimal, and base64 nodes
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 82 |
1 files changed, 54 insertions, 28 deletions
@@ -18,6 +18,7 @@ #include "base64.h" #include "serd_internal.h" +#include "static_nodes.h" #include "string_utils.h" #include "serd/serd.h" @@ -48,8 +49,22 @@ serd_new_from_uri(const SerdURIView uri, const SerdURIView base); static size_t serd_node_pad_size(const size_t n_bytes) { - const size_t pad = serd_node_align - (n_bytes + 2) % serd_node_align; - return n_bytes + 2 + pad; + const size_t pad = serd_node_align - (n_bytes + 2) % serd_node_align; + const size_t size = n_bytes + 2 + pad; + assert(size % serd_node_align == 0); + return size; +} + +static const SerdNode* +serd_node_meta_c(const SerdNode* node) +{ + return node + 1 + (serd_node_pad_size(node->n_bytes) / serd_node_align); +} + +static SerdNode* +serd_node_meta(SerdNode* node) +{ + return node + 1 + (serd_node_pad_size(node->n_bytes) / serd_node_align); } static const SerdNode* @@ -383,21 +398,26 @@ serd_digits(double abs) } SerdNode* -serd_new_decimal(double d, unsigned frac_digits) +serd_new_decimal(double d, unsigned frac_digits, const SerdNode* datatype) { if (isnan(d) || isinf(d)) { return NULL; } + const SerdNode* type = datatype ? datatype : &serd_xsd_decimal.node; const double abs_d = fabs(d); const unsigned int_digits = serd_digits(abs_d); const size_t len = int_digits + frac_digits + 3; - SerdNode* const node = serd_node_malloc(len, 0, SERD_LITERAL); - char* const buf = serd_node_buffer(node); - const double int_part = floor(abs_d); + const size_t type_len = serd_node_total_size(type); + const size_t total_len = len + type_len; + + SerdNode* const node = + serd_node_malloc(total_len, SERD_HAS_DATATYPE, SERD_LITERAL); // Point s to decimal point location - char* s = buf + int_digits; + char* const buf = serd_node_buffer(node); + const double int_part = floor(abs_d); + char* s = buf + int_digits; if (d < 0.0) { *buf = '-'; ++s; @@ -435,19 +455,24 @@ serd_new_decimal(double d, unsigned frac_digits) } } + memcpy(serd_node_meta(node), type, type_len); return node; } SerdNode* -serd_new_integer(int64_t i) +serd_new_integer(int64_t i, const SerdNode* datatype) { - uint64_t abs_i = (i < 0) ? -i : i; - const unsigned digits = serd_digits((double)abs_i); - SerdNode* node = serd_node_malloc(digits + 2, 0, SERD_LITERAL); - char* buf = serd_node_buffer(node); + const SerdNode* type = datatype ? datatype : &serd_xsd_integer.node; + uint64_t abs_i = (uint64_t)((i < 0) ? -i : i); + const unsigned digits = serd_digits((double)abs_i); + const size_t type_len = serd_node_total_size(type); + const size_t total_len = digits + 2 + type_len; + + SerdNode* node = serd_node_malloc(total_len, SERD_HAS_DATATYPE, SERD_LITERAL); // Point s to the end - char* s = buf + digits - 1; + char* buf = serd_node_buffer(node); + char* s = buf + digits - 1; if (i < 0) { *buf = '-'; ++s; @@ -460,25 +485,35 @@ serd_new_integer(int64_t i) *s-- = (char)('0' + (abs_i % 10)); } while ((abs_i /= 10) > 0); + memcpy(serd_node_meta(node), type, type_len); return node; } SerdNode* -serd_new_blob(const void* buf, size_t size, bool wrap_lines) +serd_new_blob(const void* buf, + size_t size, + bool wrap_lines, + const SerdNode* datatype) { if (!buf || !size) { return NULL; } - const size_t len = serd_base64_get_length(size, wrap_lines); - SerdNode* node = serd_node_malloc(len + 1, 0, SERD_LITERAL); - uint8_t* str = (uint8_t*)serd_node_buffer(node); + const SerdNode* type = datatype ? datatype : &serd_xsd_base64Binary.node; + const size_t len = serd_base64_get_length(size, wrap_lines); + const size_t type_len = serd_node_total_size(type); + const size_t total_len = len + 1 + type_len; + SerdNode* const node = + serd_node_malloc(total_len, SERD_HAS_DATATYPE, SERD_LITERAL); + + uint8_t* str = (uint8_t*)serd_node_buffer(node); if (serd_base64_encode(str, buf, size, wrap_lines)) { node->flags |= SERD_HAS_NEWLINE; } node->n_bytes = len; + memcpy(serd_node_meta(node), type, type_len); return node; } @@ -521,15 +556,6 @@ serd_node_uri_view(const SerdNode* SERD_NONNULL node) : SERD_URI_NULL; } -static const SerdNode* -serd_node_meta_node(const SerdNode* node) -{ - const size_t len = serd_node_pad_size(node->n_bytes); - assert((intptr_t)node % serd_node_align == 0); - assert(len % serd_node_align == 0); - return node + 1 + (len / serd_node_align); -} - const SerdNode* serd_node_datatype(const SerdNode* node) { @@ -537,7 +563,7 @@ serd_node_datatype(const SerdNode* node) return NULL; } - const SerdNode* const datatype = serd_node_meta_node(node); + const SerdNode* const datatype = serd_node_meta_c(node); assert(datatype->type == SERD_URI || datatype->type == SERD_CURIE); return datatype; } @@ -549,7 +575,7 @@ serd_node_language(const SerdNode* node) return NULL; } - const SerdNode* const lang = serd_node_meta_node(node); + const SerdNode* const lang = serd_node_meta_c(node); assert(lang->type == SERD_LITERAL); return lang; } |