aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-05-12 18:03:13 +0200
committerDavid Robillard <d@drobilla.net>2023-12-02 16:27:02 -0500
commitcd89a74a2f7bf8c3efc3ecf1597cf39d6295db00 (patch)
tree3cc01ec3ac53ea4457d49691198b68581229b773 /src/node.c
parent5c02da92038072f28408854e862fc2d4edf765d4 (diff)
downloadserd-cd89a74a2f7bf8c3efc3ecf1597cf39d6295db00.tar.gz
serd-cd89a74a2f7bf8c3efc3ecf1597cf39d6295db00.tar.bz2
serd-cd89a74a2f7bf8c3efc3ecf1597cf39d6295db00.zip
Set datatypes on integer, decimal, and base64 nodes
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/src/node.c b/src/node.c
index 43a4b502..96a9bcaa 100644
--- a/src/node.c
+++ b/src/node.c
@@ -31,6 +31,21 @@
# endif
#endif
+#define NS_XSD "http://www.w3.org/2001/XMLSchema#"
+
+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)
+
static const size_t serd_node_align = 2 * sizeof(uint64_t);
static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE);
@@ -38,7 +53,7 @@ static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE);
static SerdNode*
serd_new_from_uri(SerdURIView uri, SerdURIView base);
-static size_t
+SERD_PURE_FUNC static size_t
serd_uri_string_length(const SerdURIView* const uri)
{
size_t len = uri->path_prefix.length;
@@ -66,20 +81,28 @@ string_sink(const void* const buf, const size_t len, void* const stream)
return len;
}
-static size_t
+SERD_PURE_FUNC 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;
+}
+
+SERD_PURE_FUNC static SerdNode*
+serd_node_meta(SerdNode* const node)
+{
+ return node + 1 + (serd_node_pad_size(node->length) / sizeof(SerdNode));
}
-static const SerdNode*
+SERD_PURE_FUNC static const SerdNode*
serd_node_meta_c(const SerdNode* const node)
{
return node + 1 + (serd_node_pad_size(node->length) / sizeof(SerdNode));
}
-static const SerdNode*
+SERD_PURE_FUNC static const SerdNode*
serd_node_maybe_get_meta_c(const SerdNode* const node)
{
return (node->flags & meta_mask) ? serd_node_meta_c(node) : NULL;
@@ -405,21 +428,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;
@@ -457,19 +487,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 = (uint64_t)((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;
@@ -482,25 +517,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* const node = serd_node_malloc(len + 1, 0, SERD_LITERAL);
- uint8_t* const 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;
}
@@ -537,13 +582,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)
{
@@ -551,7 +589,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;
}
@@ -563,7 +601,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;
}