summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sratom/sratom.h5
-rw-r--r--src/sratom.c65
-rw-r--r--tests/sratom_test.c41
3 files changed, 72 insertions, 39 deletions
diff --git a/sratom/sratom.h b/sratom/sratom.h
index 6398135..b1ef071 100644
--- a/sratom/sratom.h
+++ b/sratom/sratom.h
@@ -77,9 +77,10 @@ sratom_free(Sratom* sratom);
/**
Write an Atom to RDF.
The resulting serialised atom is written to @p writer.
+ @return 0 on success, or a non-zero error code otherwise.
*/
SRATOM_API
-void
+int
sratom_write(Sratom* sratom,
LV2_URID_Unmap* unmap,
SerdWriter* writer,
@@ -110,6 +111,7 @@ SRATOM_API
char*
sratom_to_turtle(Sratom* sratom,
LV2_URID_Unmap* unmap,
+ const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type,
@@ -123,6 +125,7 @@ sratom_to_turtle(Sratom* sratom,
SRATOM_API
LV2_Atom*
sratom_from_turtle(Sratom* sratom,
+ const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
const char* str);
diff --git a/src/sratom.c b/src/sratom.c
index c70eee8..1e74067 100644
--- a/src/sratom.c
+++ b/src/sratom.c
@@ -15,6 +15,7 @@
*/
#include <assert.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -146,8 +147,16 @@ start_object(Sratom* sratom,
}
}
+static bool
+path_is_absolute(const char* path)
+{
+ return (path[0] == '/'
+ || (isalpha(path[0]) && path[1] == ':'
+ && (path[2] == '/' || path[2] == '\\')));
+}
+
SRATOM_API
-void
+int
sratom_write(Sratom* sratom,
LV2_URID_Unmap* unmap,
SerdWriter* writer,
@@ -195,8 +204,25 @@ sratom_write(Sratom* sratom,
object = serd_node_from_string(SERD_URI, str);
} else if (type_urid == sratom->forge.Path) {
const uint8_t* str = USTR(body);
- object = serd_node_from_string(SERD_LITERAL, str);
- datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path));
+ if (path_is_absolute((const char*)str)) {
+ new_node = true;
+ object = serd_node_new_file_uri(str, NULL, NULL);
+ } else {
+ SerdEnv* env = serd_writer_get_env(writer);
+ SerdURI base_uri = SERD_URI_NULL;
+ const SerdNode* base = serd_env_get_base_uri(env, &base_uri);
+ if (strncmp((const char*)base->buf, "file://", 7)) {
+ fprintf(stderr, "warning: Relative path but base is not a file URI.\n");
+ fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n");
+ object = serd_node_from_string(SERD_LITERAL, str);
+ datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path));
+ } else {
+ new_node = true;
+ SerdNode rel = serd_node_new_file_uri(str, NULL, NULL);
+ object = serd_node_new_uri_from_node(&rel, &base_uri, NULL);
+ serd_node_free(&rel);
+ }
+ }
} else if (type_urid == sratom->forge.URI) {
const uint8_t* str = USTR(body);
object = serd_node_from_string(SERD_URI, str);
@@ -331,21 +357,25 @@ sratom_write(Sratom* sratom,
if (new_node) {
serd_node_free(&object);
}
+
+ return 0;
}
SRATOM_API
char*
sratom_to_turtle(Sratom* sratom,
LV2_URID_Unmap* unmap,
+ const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type,
uint32_t size,
const void* body)
{
- SerdURI base_uri = SERD_URI_NULL;
- SerdEnv* env = serd_env_new(NULL);
- SerdChunk str = { NULL, 0 };
+ SerdURI buri = SERD_URI_NULL;
+ SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, &buri);
+ SerdEnv* env = serd_env_new(&base);
+ SerdChunk str = { NULL, 0 };
serd_env_set_prefix_from_strings(env, USTR("midi"), NS_MIDI);
serd_env_set_prefix_from_strings(env, USTR("atom"),
@@ -358,7 +388,7 @@ sratom_to_turtle(Sratom* sratom,
SerdWriter* writer = serd_writer_new(
SERD_TURTLE,
SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED,
- env, &base_uri, serd_chunk_sink, &str);
+ env, &buri, serd_chunk_sink, &str);
// Write @prefix directives
serd_env_foreach(env,
@@ -487,10 +517,12 @@ read_node(Sratom* sratom,
} else if (sord_node_get_type(node) == SORD_URI) {
if (!strcmp(str, (const char*)NS_RDF "nil")) {
lv2_atom_forge_atom(forge, 0, 0);
- } else if (serd_uri_string_has_scheme((const uint8_t*)str)) {
- lv2_atom_forge_urid(forge, map->map(map->handle, str));
+ } else if (!strncmp(str, "file://", 7)) {
+ uint8_t* path = serd_file_uri_parse((const uint8_t*)str, NULL);
+ lv2_atom_forge_path(forge, path, strlen((const char*)path));
+ free(path);
} else {
- lv2_atom_forge_uri(forge, (const uint8_t*)str, len);
+ lv2_atom_forge_urid(forge, map->map(map->handle, str));
}
} else {
const SordNode* type = get_object(model, node, sratom->nodes.rdf_type);
@@ -615,16 +647,17 @@ sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref)
SRATOM_API
LV2_Atom*
sratom_from_turtle(Sratom* sratom,
+ const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
const char* str)
{
- SerdChunk out = { NULL, 0 };
- SerdNode base_uri_node = SERD_NODE_NULL;
- SordWorld* world = sord_world_new();
- SordModel* model = sord_new(world, SORD_SPO, false);
- SerdEnv* env = serd_env_new(&base_uri_node);
- SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
+ SerdChunk out = { NULL, 0 };
+ SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, NULL);
+ SordWorld* world = sord_world_new();
+ SordModel* model = sord_new(world, SORD_SPO, false);
+ SerdEnv* env = serd_env_new(&base);
+ SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
if (!serd_reader_read_string(reader, (const uint8_t*)str)) {
SordNode* s = sord_node_from_serd_node(world, env, subject, 0, 0);
diff --git a/tests/sratom_test.c b/tests/sratom_test.c
index 4789ce2..c3eb70b 100644
--- a/tests/sratom_test.c
+++ b/tests/sratom_test.c
@@ -92,17 +92,16 @@ main()
LV2_URID eg_true = urid_map(NULL, "http://example.org/e-true");
LV2_URID eg_false = urid_map(NULL, "http://example.org/f-false");
LV2_URID eg_path = urid_map(NULL, "http://example.org/g-path");
- LV2_URID eg_uri = urid_map(NULL, "http://example.org/h-uri");
- LV2_URID eg_urid = urid_map(NULL, "http://example.org/i-urid");
- LV2_URID eg_string = urid_map(NULL, "http://example.org/j-string");
- LV2_URID eg_langlit = urid_map(NULL, "http://example.org/k-langlit");
- LV2_URID eg_typelit = urid_map(NULL, "http://example.org/l-typelit");
- LV2_URID eg_null = urid_map(NULL, "http://example.org/m-null");
- LV2_URID eg_blob = urid_map(NULL, "http://example.org/o-blob");
- LV2_URID eg_blank = urid_map(NULL, "http://example.org/p-blank");
- LV2_URID eg_tuple = urid_map(NULL, "http://example.org/q-tuple");
- LV2_URID eg_vector = urid_map(NULL, "http://example.org/r-vector");
- LV2_URID eg_seq = urid_map(NULL, "http://example.org/s-seq");
+ LV2_URID eg_urid = urid_map(NULL, "http://example.org/h-urid");
+ LV2_URID eg_string = urid_map(NULL, "http://example.org/i-string");
+ LV2_URID eg_langlit = urid_map(NULL, "http://example.org/j-langlit");
+ LV2_URID eg_typelit = urid_map(NULL, "http://example.org/k-typelit");
+ LV2_URID eg_null = urid_map(NULL, "http://example.org/l-null");
+ LV2_URID eg_blob = urid_map(NULL, "http://example.org/m-blob");
+ LV2_URID eg_blank = urid_map(NULL, "http://example.org/n-blank");
+ LV2_URID eg_tuple = urid_map(NULL, "http://example.org/o-tuple");
+ LV2_URID eg_vector = urid_map(NULL, "http://example.org/p-vector");
+ LV2_URID eg_seq = urid_map(NULL, "http://example.org/q-seq");
uint8_t buf[1024];
lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
@@ -135,18 +134,12 @@ main()
lv2_atom_forge_property_head(&forge, eg_false, 0);
lv2_atom_forge_bool(&forge, false);
- // eg_path = (Path)"/foo/bar"
- const uint8_t* pstr = (const uint8_t*)"/foo/bar";
+ // eg_path = (Path)"/absolute/path"
+ const uint8_t* pstr = (const uint8_t*)"/absolute/path";
const size_t pstr_len = strlen((const char*)pstr);
lv2_atom_forge_property_head(&forge, eg_path, 0);
lv2_atom_forge_path(&forge, pstr, pstr_len);
- // eg_uri = (URI)"a/relative/uri"
- const uint8_t* ustr = (const uint8_t*)"a/relative/uri";
- const size_t ustr_len = strlen((const char*)ustr);
- lv2_atom_forge_property_head(&forge, eg_uri, 0);
- lv2_atom_forge_uri(&forge, ustr, ustr_len);
-
// eg_urid = (URID)"http://example.org/value"
LV2_URID eg_value = urid_map(NULL, "http://example.org/value");
lv2_atom_forge_property_head(&forge, eg_urid, 0);
@@ -219,19 +212,23 @@ main()
lv2_atom_forge_pop(&forge, &seq_frame);
lv2_atom_forge_pop(&forge, &obj_frame);
+ const char* base_uri = "file:///tmp/base/";
+
SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/obj"));
SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value"));
char* outstr = sratom_to_turtle(
- sratom, &unmap, &s, &p, obj->type, obj->size, LV2_ATOM_BODY(obj));
+ sratom, &unmap, base_uri, &s, &p,
+ obj->type, obj->size, LV2_ATOM_BODY(obj));
printf("# Atom => Turtle\n\n%s", outstr);
- LV2_Atom* parsed = sratom_from_turtle(sratom, &s, &p, outstr);
+ LV2_Atom* parsed = sratom_from_turtle(sratom, base_uri, &s, &p, outstr);
if (!lv2_atom_equals(obj, parsed)) {
return test_fail("Parsed atom does not match original\n");
}
char* instr = sratom_to_turtle(
- sratom, &unmap, &s, &p, parsed->type, parsed->size, LV2_ATOM_BODY(parsed));
+ sratom, &unmap, base_uri, &s, &p,
+ parsed->type, parsed->size, LV2_ATOM_BODY(parsed));
printf("# Turtle => Atom\n\n%s", instr);
if (strcmp(outstr, instr)) {