aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/env.c28
-rw-r--r--src/node.c108
-rw-r--r--src/node.h13
3 files changed, 116 insertions, 33 deletions
diff --git a/src/env.c b/src/env.c
index 8d3c3ec4..3dc89ac3 100644
--- a/src/env.c
+++ b/src/env.c
@@ -298,12 +298,28 @@ expand_literal(const SerdEnv* env, const SerdNode* node)
{
assert(serd_node_type(node) == SERD_LITERAL);
- SerdNode* datatype = serd_env_expand(env, serd_node_datatype(node));
- if (datatype) {
- const char* str = serd_node_string(node);
- SerdNode* ret = serd_new_typed_literal(str, datatype);
- serd_node_free(datatype);
- return ret;
+ const SerdNode* const datatype = serd_node_datatype(node);
+ if (datatype && serd_node_type(datatype) == SERD_CURIE) {
+ SerdStringView prefix;
+ SerdStringView suffix;
+ if (!serd_env_expand_in_place(env, datatype, &prefix, &suffix)) {
+ return serd_new_typed_literal_expanded(serd_node_string(node),
+ serd_node_length(node),
+ serd_node_flags(node),
+ prefix,
+ suffix);
+ }
+ } else if (datatype && serd_node_type(datatype) == SERD_URI) {
+ SerdURI datatype_uri;
+ serd_uri_parse(serd_node_string(datatype), &datatype_uri);
+
+ SerdURI abs_datatype_uri;
+ serd_uri_resolve(&datatype_uri, &env->base_uri, &abs_datatype_uri);
+
+ return serd_new_typed_literal_uri(serd_node_string(node),
+ serd_node_length(node),
+ serd_node_flags(node),
+ abs_datatype_uri);
}
return NULL;
diff --git a/src/node.c b/src/node.c
index c1b817d2..8163f7ae 100644
--- a/src/node.c
+++ b/src/node.c
@@ -228,6 +228,70 @@ serd_new_plain_literal_i(const char* str,
return node;
}
+/// Internal implementation of serd_new_typed_literal from datatype URI parts
+SerdNode*
+serd_new_typed_literal_expanded(const char* str,
+ const size_t str_len,
+ const SerdNodeFlags flags,
+ const SerdStringView datatype_prefix,
+ const SerdStringView datatype_suffix)
+{
+ const size_t datatype_uri_len = datatype_prefix.len + datatype_suffix.len;
+ const size_t len = serd_node_pad_size(str_len);
+ const size_t total_len = len + sizeof(SerdNode) + datatype_uri_len;
+
+ SerdNode* node =
+ serd_node_malloc(total_len, flags | SERD_HAS_DATATYPE, SERD_LITERAL);
+
+ memcpy(serd_node_buffer(node), str, str_len);
+ node->n_bytes = str_len;
+
+ SerdNode* const datatype_node = node + 1 + (len / sizeof(SerdNode));
+ char* const datatype_buf = serd_node_buffer(datatype_node);
+
+ datatype_node->n_bytes = datatype_uri_len;
+ datatype_node->type = SERD_URI;
+ memcpy(datatype_buf, datatype_prefix.buf, datatype_prefix.len);
+ memcpy(datatype_buf + datatype_prefix.len,
+ datatype_suffix.buf,
+ datatype_suffix.len);
+
+ serd_node_check_padding(datatype_node);
+ serd_node_check_padding(node);
+ return node;
+}
+
+/// Internal implementation of serd_new_typed_literal from a parsed datatype URI
+SerdNode*
+serd_new_typed_literal_uri(const char* str,
+ const size_t str_len,
+ const SerdNodeFlags flags,
+ const SerdURI datatype_uri)
+{
+ const size_t datatype_uri_len = serd_uri_string_length(&datatype_uri);
+ const size_t len = serd_node_pad_size(str_len);
+ const size_t total_len = len + sizeof(SerdNode) + datatype_uri_len;
+
+ SerdNode* node =
+ serd_node_malloc(total_len, flags | SERD_HAS_DATATYPE, SERD_LITERAL);
+
+ memcpy(serd_node_buffer(node), str, str_len);
+ node->n_bytes = str_len;
+
+ SerdNode* const datatype_node = node + 1 + (len / sizeof(SerdNode));
+ char* ptr = serd_node_buffer(datatype_node);
+
+ const size_t actual_len = serd_uri_serialise(&datatype_uri, string_sink, &ptr);
+
+ serd_node_buffer(datatype_node)[actual_len] = '\0';
+ datatype_node->n_bytes = actual_len;
+ datatype_node->type = SERD_URI;
+
+ serd_node_check_padding(datatype_node);
+ serd_node_check_padding(node);
+ return node;
+}
+
/// Internal pre-measured implementation of serd_new_typed_literal
static SerdNode*
serd_new_typed_literal_i(const char* str,
@@ -240,23 +304,11 @@ serd_new_typed_literal_i(const char* str,
assert(datatype_uri);
assert(strcmp(datatype_uri, NS_RDF "langString"));
- flags |= SERD_HAS_DATATYPE;
-
- const size_t len = serd_node_pad_size(str_len);
- const size_t total_len = len + sizeof(SerdNode) + datatype_uri_len;
-
- SerdNode* node = serd_node_malloc(total_len, flags, SERD_LITERAL);
- memcpy(serd_node_buffer(node), str, str_len);
- node->n_bytes = str_len;
-
- SerdNode* datatype_node = node + 1 + (len / sizeof(SerdNode));
- datatype_node->n_bytes = datatype_uri_len;
- datatype_node->type = SERD_URI;
- memcpy(serd_node_buffer(datatype_node), datatype_uri, datatype_uri_len);
- serd_node_check_padding(datatype_node);
+ const SerdStringView datatype_prefix = {datatype_uri, datatype_uri_len};
+ const SerdStringView datatype_suffix = {"", 0};
- serd_node_check_padding(node);
- return node;
+ return serd_new_typed_literal_expanded(
+ str, str_len, flags, datatype_prefix, datatype_suffix);
}
SerdNode*
@@ -444,20 +496,22 @@ serd_node_resolve(const SerdNode* node, const SerdNode* base)
SerdNode*
serd_new_resolved_uri_i(const char* str, const SerdURI* base)
{
- SerdNode* result = NULL;
- if (!str || str[0] == '\0') {
+ if (serd_uri_string_has_scheme(str)) {
+ // Already absolute
+ return serd_new_uri(str);
+ } else if (!base || !base->scheme.len) {
+ // Base URI isn't given or is relative, can't resolve an absolute URI
+ return NULL;
+ } else if (!str || str[0] == '\0') {
// Empty URI => Base URI, or nothing if no base is given
- result = base ? serd_new_from_uri(base, NULL) : NULL;
- } else {
- SerdURI uri;
- serd_uri_parse(str, &uri);
- result = serd_new_from_uri(&uri, base);
+ return serd_new_from_uri(base, NULL);
}
- if (!serd_uri_string_has_scheme(serd_node_string(result))) {
- serd_node_free(result);
- return NULL;
- }
+ SerdURI uri;
+ serd_uri_parse(str, &uri);
+ SerdNode* const result = serd_new_from_uri(&uri, base);
+
+ assert(serd_uri_string_has_scheme(serd_node_string(result)));
return result;
}
diff --git a/src/node.h b/src/node.h
index d69d6421..7df2c54d 100644
--- a/src/node.h
+++ b/src/node.h
@@ -68,4 +68,17 @@ size_t serd_node_total_size(const SerdNode* node);
void serd_node_zero_pad(SerdNode* node);
SerdNode* serd_new_resolved_uri_i(const char* str, const SerdURI* base);
+SerdNode*
+serd_new_typed_literal_expanded(const char* str,
+ size_t str_len,
+ SerdNodeFlags flags,
+ SerdStringView datatype_prefix,
+ SerdStringView datatype_suffix);
+
+SerdNode*
+serd_new_typed_literal_uri(const char* str,
+ size_t str_len,
+ SerdNodeFlags flags,
+ SerdURI datatype_uri);
+
#endif // SERD_NODE_H