diff options
-rw-r--r-- | src/sratom.c | 110 | ||||
-rw-r--r-- | tests/sratom_test.c | 52 |
2 files changed, 111 insertions, 51 deletions
diff --git a/src/sratom.c b/src/sratom.c index dd13b1b..8c17de9 100644 --- a/src/sratom.c +++ b/src/sratom.c @@ -32,7 +32,8 @@ #define USTR(str) ((const uint8_t*)(str)) typedef enum { - MODE_NORMAL, + MODE_SUBJECT, + MODE_BODY, MODE_SEQUENCE, } ReadMode; @@ -351,20 +352,28 @@ sratom_write(Sratom* sratom, if (sratom->end_anon) { sratom->end_anon(sratom->handle, &id); } - } else if (type_urid == sratom->forge.Blank) { + } else if (type_urid == sratom->forge.Blank || + type_urid == sratom->forge.Resource) { const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body; const char* otype = unmap->unmap(unmap->handle, obj->otype); - gensym(&id, 'b', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, otype); + if (type_urid == sratom->forge.Blank) { + gensym(&id, 'b', sratom->next_id++); + start_object(sratom, &flags, subject, predicate, &id, otype); + } else { + id = serd_node_from_string( + SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, obj->id)); + flags = 0; + start_object(sratom, &flags, NULL, NULL, &id, otype); + } LV2_ATOM_OBJECT_BODY_FOREACH(obj, size, prop) { const char* const key = unmap->unmap(unmap->handle, prop->key); SerdNode pred = serd_node_from_string(SERD_URI, USTR(key)); - sratom_write(sratom, unmap, flags|SERD_ANON_CONT, &id, &pred, + sratom_write(sratom, unmap, flags, &id, &pred, prop->value.type, prop->value.size, LV2_ATOM_BODY(&prop->value)); } - if (sratom->end_anon && subject && predicate) { + if (sratom->end_anon && (flags & SERD_ANON_CONT)) { sratom->end_anon(sratom->handle, &id); } } else if (type_urid == sratom->forge.Sequence) { @@ -491,6 +500,34 @@ read_list_value(Sratom* sratom, } } +static void +read_resource(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + LV2_URID otype) +{ + LV2_URID_Map* map = sratom->map; + SordQuad q = { node, NULL, NULL, NULL }; + SordIter* i = sord_find(model, q); + SordQuad match; + for (;!sord_iter_end(i); sord_iter_next(i)) { + sord_iter_get(i, match); + const SordNode* p = match[SORD_PREDICATE]; + const SordNode* o = match[SORD_OBJECT]; + const char* p_uri = (const char*)sord_node_get_string(p); + uint32_t p_urid = map->map(map->handle, p_uri); + if (!(sord_node_equals(p, sratom->nodes.rdf_type) && + sord_node_get_type(o) == SORD_URI && + map->map(map->handle, (const char*)sord_node_get_string(o)) == otype)) { + lv2_atom_forge_property_head(forge, p_urid, 0); + read_node(sratom, forge, world, model, o, MODE_BODY); + } + } + sord_iter_free(i); +} + static uint32_t atom_size(Sratom* sratom, uint32_t type_urid) { @@ -576,7 +613,7 @@ read_node(Sratom* sratom, } else { lv2_atom_forge_string(forge, str, len); } - } else if (sord_node_get_type(node) == SORD_URI) { + } else if (sord_node_get_type(node) == SORD_URI && mode == MODE_BODY) { if (!strcmp(str, (const char*)NS_RDF "nil")) { lv2_atom_forge_atom(forge, 0, 0); } else if (!strncmp(str, "file://", 7)) { @@ -598,17 +635,21 @@ read_node(Sratom* sratom, } LV2_Atom_Forge_Frame frame = { 0, 0 }; - if (mode == MODE_SEQUENCE) { + if (mode == MODE_SUBJECT && sord_node_get_type(node) == SORD_URI) { + lv2_atom_forge_resource( + forge, &frame, map->map(map->handle, str), type_urid); + read_resource(sratom, forge, world, model, node, type_urid); + } else if (mode == MODE_SEQUENCE) { const SordNode* frame_time = get_object( model, node, sratom->nodes.atom_frameTime); const char* frame_time_str = frame_time ? (const char*)sord_node_get_string(frame_time) : ""; lv2_atom_forge_frame_time(forge, serd_strtod(frame_time_str, NULL)); - read_node(sratom, forge, world, model, value, MODE_NORMAL); + read_node(sratom, forge, world, model, value, MODE_BODY); } else if (type_urid == sratom->forge.Tuple) { lv2_atom_forge_tuple(forge, &frame); - read_list_value(sratom, forge, world, model, value, MODE_NORMAL); + read_list_value(sratom, forge, world, model, value, MODE_BODY); } else if (type_urid == sratom->forge.Sequence) { lv2_atom_forge_sequence_head(forge, &frame, 0); read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE); @@ -620,7 +661,7 @@ read_node(Sratom* sratom, uint32_t child_size = atom_size(sratom, child_type); if (child_size > 0) { lv2_atom_forge_vector_head(forge, &frame, child_size, child_type); - read_list_value(sratom, forge, world, model, value, MODE_NORMAL); + read_list_value(sratom, forge, world, model, value, MODE_BODY); } } else if (value && sord_node_equals(sord_node_get_datatype(value), sratom->nodes.xsd_base64Binary)) { @@ -633,24 +674,7 @@ read_node(Sratom* sratom, free(body); } else { lv2_atom_forge_blank(forge, &frame, sratom->next_id++, type_urid); - SordQuad match; - - SordQuad q2 = { node, 0, 0, 0 }; - SordIter* i = sord_find(model, q2); - for (;!sord_iter_end(i); sord_iter_next(i)) { - sord_iter_get(i, match); - const SordNode* p = match[SORD_PREDICATE]; - const char* p_uri = (const char*)sord_node_get_string(p); - uint32_t p_urid = map->map(map->handle, p_uri); - if (!(sord_node_equals(p, sratom->nodes.rdf_type) - && sord_node_equals(match[SORD_OBJECT], type))) { - // TODO: This will lose multiple rdf:type properties - lv2_atom_forge_property_head(forge, p_urid, 0); - read_node(sratom, forge, world, model, - match[SORD_OBJECT], MODE_NORMAL); - } - } - sord_iter_free(i); + read_resource(sratom, forge, world, model, node, type_urid); } if (frame.ref) { lv2_atom_forge_pop(forge, &frame); @@ -675,7 +699,7 @@ sratom_read(Sratom* sratom, sratom->nodes.xsd_base64Binary = sord_new_uri(world, NS_XSD "base64Binary"); sratom->next_id = 1; - read_node(sratom, forge, world, model, node, MODE_NORMAL); + read_node(sratom, forge, world, model, node, MODE_SUBJECT); sord_node_free(world, sratom->nodes.xsd_base64Binary); sord_node_free(world, sratom->nodes.rdf_value); @@ -724,19 +748,23 @@ sratom_from_turtle(Sratom* sratom, if (!serd_reader_read_string(reader, (const uint8_t*)str)) { SordNode* s = sord_node_from_serd_node(world, env, subject, 0, 0); - SordNode* p = sord_node_from_serd_node(world, env, predicate, 0, 0); - SordQuad q = { s, p, 0, 0 }; - SordIter* i = sord_find(model, q); - if (!sord_iter_end(i)) { - SordQuad result; - sord_iter_get(i, result); - lv2_atom_forge_set_sink( - &sratom->forge, sratom_forge_sink, sratom_forge_deref, &out); - sratom_read(sratom, &sratom->forge, world, model, result[SORD_OBJECT]); + lv2_atom_forge_set_sink( + &sratom->forge, sratom_forge_sink, sratom_forge_deref, &out); + if (subject && predicate) { + SordNode* p = sord_node_from_serd_node(world, env, predicate, 0, 0); + SordQuad q = { s, p, 0, 0 }; + SordIter* i = sord_find(model, q); + if (!sord_iter_end(i)) { + SordQuad result; + sord_iter_get(i, result); + sratom_read(sratom, &sratom->forge, world, model, result[SORD_OBJECT]); + } else { + fprintf(stderr, "Failed to find node\n"); + } + sord_iter_free(i); } else { - fprintf(stderr, "Failed to find node\n"); + sratom_read(sratom, &sratom->forge, world, model, s); } - sord_iter_free(i); } else { fprintf(stderr, "Failed to read Turtle\n"); } diff --git a/tests/sratom_test.c b/tests/sratom_test.c index fe5d573..f9235bc 100644 --- a/tests/sratom_test.c +++ b/tests/sratom_test.c @@ -14,6 +14,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <ctype.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -75,7 +76,7 @@ test_fail(const char* fmt, ...) } int -main() +test(bool top_level) { LV2_URID_Map map = { NULL, urid_map }; LV2_URID_Unmap unmap = { NULL, urid_unmap }; @@ -107,9 +108,15 @@ main() uint8_t buf[1024]; lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf)); + const char* obj_uri = "http://example.org/obj"; + LV2_URID obj_id = urid_map(NULL, obj_uri); LV2_Atom_Forge_Frame obj_frame; - LV2_Atom* obj = (LV2_Atom*)lv2_atom_forge_deref( - &forge, lv2_atom_forge_blank(&forge, &obj_frame, 1, eg_Object)); + if (top_level) { + lv2_atom_forge_resource(&forge, &obj_frame, obj_id, eg_Object); + } else { + lv2_atom_forge_blank(&forge, &obj_frame, 1, eg_Object); + } + LV2_Atom* obj = lv2_atom_forge_deref(&forge, obj_frame.ref); // eg_one = (Int32)1 lv2_atom_forge_property_head(&forge, eg_one, 0); @@ -182,7 +189,7 @@ main() // eg_blank = [ a <http://example.org/Object> ] lv2_atom_forge_property_head(&forge, eg_blank, 0); LV2_Atom_Forge_Frame blank_frame; - lv2_atom_forge_blank(&forge, &blank_frame, 2, eg_Object); + lv2_atom_forge_blank(&forge, &blank_frame, top_level ? 1 : 2, eg_Object); lv2_atom_forge_pop(&forge, &blank_frame); // eg_tuple = "foo",true @@ -221,20 +228,31 @@ main() 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, base_uri, &s, &p, + 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")); + + SerdNode* subj = top_level ? NULL : &s; + SerdNode* pred = top_level ? NULL : &p; + + char* outstr = sratom_to_turtle( + sratom, &unmap, base_uri, subj, pred, obj->type, obj->size, LV2_ATOM_BODY(obj)); + printf("# Atom => Turtle\n\n%s", outstr); - LV2_Atom* parsed = sratom_from_turtle(sratom, base_uri, &s, &p, outstr); + LV2_Atom* parsed = NULL; + if (top_level) { + SerdNode s = serd_node_from_string(SERD_URI, (const uint8_t*)obj_uri); + parsed = sratom_from_turtle(sratom, base_uri, &s, NULL, outstr); + } else { + parsed = sratom_from_turtle(sratom, base_uri, subj, pred, outstr); + } if (!lv2_atom_equals(obj, parsed)) { return test_fail("Parsed atom does not match original\n"); } char* instr = sratom_to_turtle( - sratom, &unmap, base_uri, &s, &p, + sratom, &unmap, base_uri, subj, pred, parsed->type, parsed->size, LV2_ATOM_BODY(parsed)); printf("# Turtle => Atom\n\n%s", instr); @@ -251,7 +269,21 @@ main() for (uint32_t i = 0; i < n_uris; ++i) { free(uris[i]); } + free(uris); + uris = NULL; + n_uris = 0; return 0; } + +int +main() +{ + if (test(false)) { + return 1; + } else if (test(true)) { + return 1; + } + return 0; +} |