diff options
author | David Robillard <d@drobilla.net> | 2022-01-02 18:22:35 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-28 21:57:29 -0500 |
commit | c02d28085a1f81b542df62fe97a530bb6cbce86d (patch) | |
tree | e528bf4e337656c5a9d5391f4af4b1c080f9da67 /src | |
parent | 77eebec72c0507309ce89f8cdaceff4adfd147cf (diff) | |
download | serd-c02d28085a1f81b542df62fe97a530bb6cbce86d.tar.gz serd-c02d28085a1f81b542df62fe97a530bb6cbce86d.tar.bz2 serd-c02d28085a1f81b542df62fe97a530bb6cbce86d.zip |
Add support for xsd:hexBinary literals
Diffstat (limited to 'src')
-rw-r--r-- | src/node.c | 119 | ||||
-rw-r--r-- | src/nodes.c | 31 |
2 files changed, 121 insertions, 29 deletions
@@ -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) { diff --git a/src/nodes.c b/src/nodes.c index b989259d..84c6b696 100644 --- a/src/nodes.c +++ b/src/nodes.c @@ -442,9 +442,9 @@ serd_nodes_integer(SerdNodes* const nodes, const int64_t value) } const SerdNode* -serd_nodes_base64(SerdNodes* const nodes, - const void* const value, - const size_t value_size) +serd_nodes_hex(SerdNodes* const nodes, + const void* const value, + const size_t value_size) { assert(nodes); assert(value); @@ -459,6 +459,31 @@ serd_nodes_base64(SerdNodes* const nodes, like a Real Database(TM) would largely avoid this problem. */ // Determine how much space the node needs + SerdWriteResult r = serd_node_construct_hex(0, NULL, value_size, value); + + // Allocate a new entry to and construct the node into it + NodesEntry* const entry = new_entry(nodes->allocator, r.count); + if (entry) { + r = serd_node_construct_hex(r.count, &entry->node, value_size, value); + + assert(!r.status); + (void)r; + } + + return serd_nodes_manage_entry(nodes, entry); +} + +const SerdNode* +serd_nodes_base64(SerdNodes* const nodes, + const void* const value, + const size_t value_size) +{ + assert(nodes); + assert(value); + + // Same situation as for hex above + + // Determine how much space the node needs SerdWriteResult r = serd_node_construct_base64(0, NULL, value_size, value); // Allocate a new entry to and construct the node into it |