aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/serd/serd.h19
-rw-r--r--src/env.c5
-rw-r--r--src/node.c111
-rw-r--r--test/test_node.c62
-rw-r--r--test/test_reader_writer.c5
5 files changed, 131 insertions, 71 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h
index 41ee9993..16c600ef 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -557,14 +557,23 @@ serd_new_string(SerdStringView string);
/**
Create a new literal node from `str`.
- Either `datatype_uri` or `lang` can be given, but not both, unless
- `datatype_uri` is rdf:langString in which case it is ignored.
+ A plain literal has no datatype, but may have a language tag. The `lang`
+ may be NULL, in which case this is equivalent to `serd_new_string()`.
*/
SERD_API
SerdNode* SERD_ALLOCATED
-serd_new_literal(SerdStringView string,
- SerdStringView datatype_uri,
- SerdStringView lang);
+serd_new_plain_literal(SerdStringView str, SerdStringView lang);
+
+/**
+ Create a new typed literal node from `str`.
+
+ A typed literal has no language tag, but may have a datatype. The
+ `datatype` may be NULL, in which case this is equivalent to
+ `serd_new_string()`.
+*/
+SERD_API
+SerdNode* SERD_ALLOCATED
+serd_new_typed_literal(SerdStringView str, SerdStringView datatype_uri);
/// Create a new blank node
SERD_API
diff --git a/src/env.c b/src/env.c
index f0d0705c..944319d8 100644
--- a/src/env.c
+++ b/src/env.c
@@ -210,9 +210,8 @@ serd_env_expand_node(const SerdEnv* env, const SerdNode* node)
if (short_datatype) {
SerdNode* const datatype = serd_env_expand_node(env, short_datatype);
if (datatype) {
- SerdNode* ret = serd_new_literal(serd_node_string_view(node),
- serd_node_string_view(datatype),
- SERD_EMPTY_STRING());
+ SerdNode* ret = serd_new_typed_literal(serd_node_string_view(node),
+ serd_node_string_view(datatype));
serd_node_free(datatype);
return ret;
}
diff --git a/src/node.c b/src/node.c
index ed962150..007be2c0 100644
--- a/src/node.c
+++ b/src/node.c
@@ -183,58 +183,95 @@ serd_new_string(const SerdStringView str)
return node;
}
-SerdNode*
-serd_new_literal(const SerdStringView str,
- const SerdStringView datatype_uri,
- const SerdStringView lang)
+/// Internal pre-measured implementation of serd_new_plain_literal
+static SerdNode*
+serd_new_plain_literal_i(const SerdStringView str,
+ SerdNodeFlags flags,
+ const SerdStringView lang)
{
- if (!str.len || (lang.len && datatype_uri.len &&
- strcmp(datatype_uri.buf, NS_RDF "langString"))) {
- return NULL;
- }
+ assert(str.len);
+ assert(lang.len);
- SerdNodeFlags flags = 0;
- const size_t n_bytes = serd_substrlen(str.buf, str.len, &flags);
- const size_t len = serd_node_pad_size(n_bytes);
+ flags |= SERD_HAS_LANGUAGE;
- SerdNode* node = NULL;
- if (lang.len) {
- const size_t total_len = len + sizeof(SerdNode) + lang.len;
+ const size_t len = serd_node_pad_size(str.len);
+ const size_t total_len = len + sizeof(SerdNode) + lang.len;
- node = serd_node_malloc(total_len, flags | SERD_HAS_LANGUAGE, SERD_LITERAL);
- node->n_bytes = n_bytes;
- memcpy(serd_node_buffer(node), str.buf, n_bytes);
+ SerdNode* node = serd_node_malloc(total_len, flags, SERD_LITERAL);
+ memcpy(serd_node_buffer(node), str.buf, str.len);
+ node->n_bytes = str.len;
- SerdNode* lang_node = node + 1 + (len / serd_node_align);
- lang_node->type = SERD_LITERAL;
- lang_node->n_bytes = lang.len;
- memcpy(serd_node_buffer(lang_node), lang.buf, lang.len);
- serd_node_check_padding(lang_node);
+ SerdNode* lang_node = node + 1 + (len / serd_node_align);
+ lang_node->type = SERD_LITERAL;
+ lang_node->n_bytes = lang.len;
+ memcpy(serd_node_buffer(lang_node), lang.buf, lang.len);
+ serd_node_check_padding(lang_node);
- } else if (datatype_uri.len) {
- const size_t total_len = len + sizeof(SerdNode) + datatype_uri.len;
+ serd_node_check_padding(node);
+ return node;
+}
- node = serd_node_malloc(total_len, flags | SERD_HAS_DATATYPE, SERD_LITERAL);
- node->n_bytes = n_bytes;
- memcpy(serd_node_buffer(node), str.buf, n_bytes);
+/// Internal pre-measured implementation of serd_new_typed_literal
+static SerdNode*
+serd_new_typed_literal_i(const SerdStringView str,
+ SerdNodeFlags flags,
+ const SerdStringView datatype_uri)
+{
+ assert(str.len);
+ assert(datatype_uri.len);
+ assert(strcmp(datatype_uri.buf, NS_RDF "langString"));
- SerdNode* datatype_node = node + 1 + (len / serd_node_align);
- datatype_node->type = SERD_URI;
- datatype_node->n_bytes = datatype_uri.len;
- memcpy(serd_node_buffer(datatype_node), datatype_uri.buf, datatype_uri.len);
- serd_node_check_padding(datatype_node);
+ flags |= SERD_HAS_DATATYPE;
- } else {
- node = serd_node_malloc(n_bytes, flags, SERD_LITERAL);
- memcpy(serd_node_buffer(node), str.buf, n_bytes);
- node->n_bytes = n_bytes;
- }
+ 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.buf, str.len);
+ node->n_bytes = str.len;
+
+ SerdNode* datatype_node = node + 1 + (len / serd_node_align);
+ datatype_node->n_bytes = datatype_uri.len;
+ datatype_node->type = SERD_URI;
+ memcpy(serd_node_buffer(datatype_node), datatype_uri.buf, datatype_uri.len);
+ serd_node_check_padding(datatype_node);
serd_node_check_padding(node);
return node;
}
SerdNode*
+serd_new_plain_literal(const SerdStringView str, const SerdStringView lang)
+{
+ if (!lang.len) {
+ return serd_new_string(str);
+ }
+
+ SerdNodeFlags flags = 0;
+ serd_strlen(str.buf, &flags);
+
+ return serd_new_plain_literal_i(str, flags, lang);
+}
+
+SerdNode*
+serd_new_typed_literal(const SerdStringView str,
+ const SerdStringView datatype_uri)
+{
+ if (!datatype_uri.len) {
+ return serd_new_string(str);
+ }
+
+ if (!strcmp(datatype_uri.buf, NS_RDF "langString")) {
+ return NULL;
+ }
+
+ SerdNodeFlags flags = 0;
+ serd_strlen(str.buf, &flags);
+
+ return serd_new_typed_literal_i(str, flags, datatype_uri);
+}
+
+SerdNode*
serd_new_blank(const SerdStringView str)
{
return serd_new_simple_node(SERD_BLANK, str);
diff --git a/test/test_node.c b/test/test_node.c
index 93a408d6..8a93f215 100644
--- a/test/test_node.c
+++ b/test/test_node.c
@@ -174,10 +174,12 @@ test_node_equals(void)
{
static const uint8_t replacement_char_str[] = {0xEF, 0xBF, 0xBD, 0};
- SerdNode* const lhs =
- serd_new_string(SERD_STRING_VIEW((const char*)replacement_char_str, 3));
+ static const SerdStringView replacement_char = {
+ (const char*)replacement_char_str, 3};
+
+ SerdNode* lhs = serd_new_string(replacement_char);
+ SerdNode* rhs = serd_new_string(SERD_STATIC_STRING("123"));
- SerdNode* const rhs = serd_new_string(SERD_STATIC_STRING("123"));
assert(!serd_node_equals(lhs, rhs));
SerdNode* const qnode = serd_new_curie(SERD_STATIC_STRING("foo:bar"));
@@ -220,40 +222,54 @@ test_simple_node(void)
static void
test_literal(void)
{
- SerdNode* hello2 = serd_new_literal(
- SERD_STATIC_STRING("hello\""), SERD_EMPTY_STRING(), SERD_EMPTY_STRING());
+ SerdNode* hello2 = serd_new_string(SERD_STATIC_STRING("hello\""));
assert(serd_node_length(hello2) == 6 &&
serd_node_flags(hello2) == SERD_HAS_QUOTE &&
!strcmp(serd_node_string(hello2), "hello\""));
+
+ SerdNode* hello3 =
+ serd_new_plain_literal(SERD_STATIC_STRING("hello\""), SERD_EMPTY_STRING());
+
+ assert(serd_node_equals(hello2, hello3));
+
+ SerdNode* hello4 =
+ serd_new_typed_literal(SERD_STATIC_STRING("hello\""), SERD_EMPTY_STRING());
+
+ assert(serd_node_equals(hello4, hello2));
+
+ serd_node_free(hello4);
+ serd_node_free(hello3);
serd_node_free(hello2);
- SerdNode* hello_l = serd_new_literal(SERD_STATIC_STRING("hello_l\""),
- SERD_EMPTY_STRING(),
- SERD_STATIC_STRING("en"));
+ const char* lang_lit_str = "\"Hello\"@en";
+ SerdNode* sliced_lang_lit =
+ serd_new_plain_literal(SERD_STRING_VIEW(lang_lit_str + 1, 5),
+ SERD_STRING_VIEW(lang_lit_str + 8, 2));
- assert(serd_node_length(hello_l) == 8);
- assert(!strcmp(serd_node_string(hello_l), "hello_l\""));
- assert(serd_node_flags(hello_l) == (SERD_HAS_QUOTE | SERD_HAS_LANGUAGE));
+ assert(!strcmp(serd_node_string(sliced_lang_lit), "Hello"));
- const SerdNode* const lang = serd_node_language(hello_l);
+ const SerdNode* const lang = serd_node_language(sliced_lang_lit);
assert(lang);
assert(!strcmp(serd_node_string(lang), "en"));
- serd_node_free(hello_l);
+ serd_node_free(sliced_lang_lit);
- SerdNode* hello_dt =
- serd_new_literal(SERD_STATIC_STRING("hello_dt\""),
- SERD_STATIC_STRING("http://example.org/Thing"),
- SERD_EMPTY_STRING());
+ const char* type_lit_str = "\"Hallo\"^^<http://example.org/Greeting>";
+ SerdNode* sliced_type_lit =
+ serd_new_typed_literal(SERD_STRING_VIEW(type_lit_str + 1, 5),
+ SERD_STRING_VIEW(type_lit_str + 10, 27));
- assert(serd_node_length(hello_dt) == 9);
- assert(!strcmp(serd_node_string(hello_dt), "hello_dt\""));
- assert(serd_node_flags(hello_dt) == (SERD_HAS_QUOTE | SERD_HAS_DATATYPE));
+ assert(!strcmp(serd_node_string(sliced_type_lit), "Hallo"));
- const SerdNode* const datatype = serd_node_datatype(hello_dt);
+ const SerdNode* const datatype = serd_node_datatype(sliced_type_lit);
assert(datatype);
- assert(!strcmp(serd_node_string(datatype), "http://example.org/Thing"));
- serd_node_free(hello_dt);
+ assert(!strcmp(serd_node_string(datatype), "http://example.org/Greeting"));
+ serd_node_free(sliced_type_lit);
+
+ SerdNode* const plain_lit =
+ serd_new_plain_literal(SERD_STATIC_STRING("Plain"), SERD_EMPTY_STRING());
+ assert(!strcmp(serd_node_string(plain_lit), "Plain"));
+ serd_node_free(plain_lit);
}
static void
diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c
index b39ea761..cb3371b6 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -199,12 +199,11 @@ test_writer(const char* const path)
assert(serd_sink_write(iface, 0, junk[i][0], junk[i][1], junk[i][2], NULL));
}
- static const SerdStringView empty = SERD_EMPTY_STRING();
static const SerdStringView urn_Type = SERD_STATIC_STRING("urn:Type");
static const SerdStringView en = SERD_STATIC_STRING("en");
- SerdNode* const t = serd_new_literal(buf_view, urn_Type, empty);
- SerdNode* const l = serd_new_literal(buf_view, empty, en);
+ SerdNode* const t = serd_new_typed_literal(buf_view, urn_Type);
+ SerdNode* const l = serd_new_plain_literal(buf_view, en);
const SerdNode* good[][3] = {{s, p, o}, {s, p, t}, {s, p, l}};
for (size_t i = 0; i < sizeof(good) / (sizeof(SerdNode*) * 3); ++i) {