diff options
-rw-r--r-- | sratom/sratom.h | 5 | ||||
-rw-r--r-- | src/sratom.c | 65 | ||||
-rw-r--r-- | tests/sratom_test.c | 41 |
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)) { |