From 7a171498eca31ddedb0de1f372c982eca00d3d50 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 12 May 2018 18:03:13 +0200 Subject: Set datatypes on integer, decimal, and base64 nodes --- src/node.c | 78 +++++++++++++++++++++++++++++++++++------------------- src/static_nodes.h | 38 ++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 src/static_nodes.h (limited to 'src') diff --git a/src/node.c b/src/node.c index fcec7336..8f981856 100644 --- a/src/node.c +++ b/src/node.c @@ -17,6 +17,7 @@ #include "node.h" #include "base64.h" +#include "static_nodes.h" #include "string_utils.h" #include "system.h" @@ -47,6 +48,7 @@ static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE); static SerdNode* serd_new_from_uri(SerdURIView uri, SerdURIView base); +SERD_PURE_FUNC static size_t serd_uri_string_length(const SerdURIView* const uri) { @@ -78,8 +80,16 @@ string_sink(const void* const buf, const size_t len, void* const stream) static size_t serd_node_pad_size(const size_t n_bytes) { - const size_t pad = sizeof(SerdNode) - (n_bytes + 2) % sizeof(SerdNode); - return n_bytes + 2 + pad; + const size_t pad = sizeof(SerdNode) - (n_bytes + 2) % sizeof(SerdNode); + const size_t size = n_bytes + 2 + pad; + assert(size % sizeof(SerdNode) == 0); + return size; +} + +static SerdNode* +serd_node_meta(SerdNode* const node) +{ + return node + 1 + (serd_node_pad_size(node->length) / sizeof(SerdNode)); } static const SerdNode* @@ -409,21 +419,28 @@ serd_digits(const double abs) } SerdNode* -serd_new_decimal(const double d, const unsigned frac_digits) +serd_new_decimal(const double d, + const unsigned frac_digits, + const SerdNode* const 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; @@ -461,19 +478,24 @@ serd_new_decimal(const double d, const unsigned frac_digits) } } + memcpy(serd_node_meta(node), type, type_len); return node; } SerdNode* -serd_new_integer(const int64_t i) +serd_new_integer(const int64_t i, const SerdNode* const 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; @@ -486,25 +508,35 @@ serd_new_integer(const 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* const buf, const size_t size, const bool wrap_lines) +serd_new_blob(const void* const buf, + const size_t size, + const bool wrap_lines, + const SerdNode* const 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->length = len; + memcpy(serd_node_meta(node), type, type_len); return node; } @@ -541,14 +573,6 @@ serd_node_uri_view(const SerdNode* const node) : SERD_URI_NULL; } -SERD_PURE_FUNC -static const SerdNode* -serd_node_meta_node(const SerdNode* node) -{ - const size_t len = serd_node_pad_size(node->length); - return node + 1 + (len / sizeof(SerdNode)); -} - const SerdNode* serd_node_datatype(const SerdNode* const node) { @@ -556,7 +580,7 @@ serd_node_datatype(const SerdNode* const 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; } @@ -568,7 +592,7 @@ serd_node_language(const SerdNode* const 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; } diff --git a/src/static_nodes.h b/src/static_nodes.h new file mode 100644 index 00000000..1b1fc062 --- /dev/null +++ b/src/static_nodes.h @@ -0,0 +1,38 @@ +/* + Copyright 2019-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef SERD_STATIC_NODES_H +#define SERD_STATIC_NODES_H + +#include "serd/serd.h" + +#include "node.h" +#include "serd_internal.h" + +typedef struct StaticNode { + SerdNode node; + char buf[sizeof(NS_XSD "base64Binary")]; +} StaticNode; + +#define DEFINE_XSD_NODE(name) \ + static const StaticNode serd_xsd_##name = { \ + {sizeof(NS_XSD #name) - 1, 0, SERD_URI}, NS_XSD #name}; + +DEFINE_XSD_NODE(base64Binary) +DEFINE_XSD_NODE(decimal) +DEFINE_XSD_NODE(integer) + +#endif // SERD_STATIC_NODES_H -- cgit v1.2.1