aboutsummaryrefslogtreecommitdiffstats
path: root/src/node.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-01-02 18:22:35 -0500
committerDavid Robillard <d@drobilla.net>2022-01-28 21:57:29 -0500
commitc02d28085a1f81b542df62fe97a530bb6cbce86d (patch)
treee528bf4e337656c5a9d5391f4af4b1c080f9da67 /src/node.c
parent77eebec72c0507309ce89f8cdaceff4adfd147cf (diff)
downloadserd-c02d28085a1f81b542df62fe97a530bb6cbce86d.tar.gz
serd-c02d28085a1f81b542df62fe97a530bb6cbce86d.tar.bz2
serd-c02d28085a1f81b542df62fe97a530bb6cbce86d.zip
Add support for xsd:hexBinary literals
Diffstat (limited to 'src/node.c')
-rw-r--r--src/node.c119
1 files changed, 93 insertions, 26 deletions
diff --git a/src/node.c b/src/node.c
index 7ccc039f..46552449 100644
--- a/src/node.c
+++ b/src/node.c
@@ -446,27 +446,26 @@ serd_node_construct_integer(const size_t buf_size,
SERD_STRING(NS_XSD "integer"));
}
-SerdWriteResult
-serd_node_construct_base64(const size_t buf_size,
- void* const buf,
- const size_t value_size,
- const void* const value)
+static SerdWriteResult
+serd_node_construct_binary(
+ const size_t buf_size,
+ void* const buf,
+ const size_t value_size,
+ const void* const value,
+ const SerdStringView datatype_uri,
+ ExessResult (*write_func)(size_t, const void*, size_t, char*))
{
- static const SerdStringView xsd_base64Binary =
- SERD_STRING(NS_XSD "base64Binary");
-
// Verify argument sanity
if (!value || !value_size) {
return result(SERD_BAD_ARG, 0);
}
- // Determine the type to use (default to xsd:base64Binary)
- const SerdStringView type = xsd_base64Binary;
- const size_t type_length = serd_node_pad_length(type.len);
- const size_t type_size = sizeof(SerdNode) + type_length;
+ // Find the size required for the datatype
+ const size_t type_length = serd_node_pad_length(datatype_uri.len);
+ const size_t type_size = sizeof(SerdNode) + type_length;
// Find the length of the encoded string (just an O(1) arithmetic expression)
- ExessResult r = exess_write_base64(value_size, value, 0, NULL);
+ ExessResult r = write_func(value_size, value, 0, NULL);
// Check that the provided buffer is large enough
const size_t padded_length = serd_node_pad_length(r.count);
@@ -480,8 +479,8 @@ serd_node_construct_base64(const size_t buf_size,
node->flags = SERD_HAS_DATATYPE;
node->type = SERD_LITERAL;
- // Write the encoded base64 into the node body
- r = exess_write_base64(
+ // Write the encoded string into the node body
+ r = write_func(
value_size, value, total_size - sizeof(SerdNode), serd_node_buffer(node));
MUST_SUCCEED(r.status);
@@ -489,14 +488,42 @@ serd_node_construct_base64(const size_t buf_size,
// Append datatype
SerdNode* meta_node = node + 1 + (padded_length / sizeof(SerdNode));
- meta_node->length = type.len;
+ meta_node->length = datatype_uri.len;
meta_node->flags = 0u;
meta_node->type = SERD_URI;
- memcpy(serd_node_buffer(meta_node), type.buf, type.len);
+ memcpy(serd_node_buffer(meta_node), datatype_uri.buf, datatype_uri.len);
return result(SERD_SUCCESS, total_size);
}
+SerdWriteResult
+serd_node_construct_hex(const size_t buf_size,
+ void* const buf,
+ const size_t value_size,
+ const void* const value)
+{
+ return serd_node_construct_binary(buf_size,
+ buf,
+ value_size,
+ value,
+ SERD_STRING(NS_XSD "hexBinary"),
+ exess_write_hex);
+}
+
+SerdWriteResult
+serd_node_construct_base64(const size_t buf_size,
+ void* const buf,
+ const size_t value_size,
+ const void* const value)
+{
+ return serd_node_construct_binary(buf_size,
+ buf,
+ value_size,
+ value,
+ SERD_STRING(NS_XSD "base64Binary"),
+ exess_write_base64);
+}
+
static size_t
string_sink(const void* const buf,
const size_t size,
@@ -650,21 +677,45 @@ serd_get_value_as(const SerdNode* const node,
}
size_t
-serd_get_base64_size(const SerdNode* const node)
+serd_get_blob_size(const SerdNode* const node)
{
- return exess_base64_decoded_size(serd_node_length(node));
+ const SerdNode* const datatype = serd_node_datatype(node);
+ if (!datatype) {
+ return 0u;
+ }
+
+ if (!strcmp(serd_node_string(datatype), NS_XSD "hexBinary")) {
+ return exess_hex_decoded_size(serd_node_length(node));
+ }
+
+ if (!strcmp(serd_node_string(datatype), NS_XSD "base64Binary")) {
+ return exess_base64_decoded_size(serd_node_length(node));
+ }
+
+ return 0u;
}
SerdWriteResult
-serd_get_base64(const SerdNode* const node,
- const size_t buf_size,
- void* const buf)
+serd_get_blob(const SerdNode* const node,
+ const size_t buf_size,
+ void* const buf)
{
- const size_t max_size = serd_get_base64_size(node);
- const ExessVariableResult r =
- exess_read_base64(buf_size, buf, serd_node_string(node));
+ const SerdNode* const datatype = serd_node_datatype(node);
+ if (!datatype) {
+ return result(SERD_BAD_ARG, 0u);
+ }
+
+ ExessVariableResult r = {EXESS_UNSUPPORTED, 0u, 0u};
- return r.status == EXESS_NO_SPACE ? result(SERD_OVERFLOW, max_size)
+ if (!strcmp(serd_node_string(datatype), NS_XSD "hexBinary")) {
+ r = exess_read_hex(buf_size, buf, serd_node_string(node));
+ } else if (!strcmp(serd_node_string(datatype), NS_XSD "base64Binary")) {
+ r = exess_read_base64(buf_size, buf, serd_node_string(node));
+ } else {
+ return result(SERD_BAD_ARG, 0u);
+ }
+
+ return r.status == EXESS_NO_SPACE ? result(SERD_OVERFLOW, r.write_count)
: r.status ? result(SERD_BAD_SYNTAX, 0u)
: result(SERD_SUCCESS, r.write_count);
}
@@ -906,6 +957,22 @@ serd_new_base64(SerdAllocator* const allocator, const void* buf, size_t size)
return node;
}
+SerdNode*
+serd_new_hex(SerdAllocator* const allocator, const void* buf, size_t size)
+{
+ SerdWriteResult r = serd_node_construct_hex(0, NULL, size, buf);
+ SerdNode* const node = serd_node_try_malloc(allocator, r);
+
+ if (node) {
+ r = serd_node_construct_hex(r.count, node, size, buf);
+ MUST_SUCCEED(r.status);
+ assert(serd_node_length(node) == strlen(serd_node_string(node)));
+ serd_node_check_padding(node);
+ }
+
+ return node;
+}
+
SerdNodeType
serd_node_type(const SerdNode* const node)
{