diff options
author | David Robillard <d@drobilla.net> | 2012-02-21 04:49:07 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2012-02-21 04:49:07 +0000 |
commit | 3ece29105d12819e602dbd0309f4ffda321a2ea3 (patch) | |
tree | 6655ebd358424e43387649318b8631ebc0b6d389 | |
parent | ee1e682e0a3787a4b293e55a09d2394bd1d47252 (diff) | |
download | sratom-3ece29105d12819e602dbd0309f4ffda321a2ea3.tar.gz sratom-3ece29105d12819e602dbd0309f4ffda321a2ea3.tar.bz2 sratom-3ece29105d12819e602dbd0309f4ffda321a2ea3.zip |
Tuple serialisation.
git-svn-id: http://svn.drobilla.net/lad/trunk/seriatom@3990 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | seriatom/seriatom.h | 24 | ||||
-rw-r--r-- | src/atom_to_rdf.c | 181 | ||||
-rw-r--r-- | tests/seriatom_test.c | 5 | ||||
-rw-r--r-- | wscript | 2 |
4 files changed, 169 insertions, 43 deletions
diff --git a/seriatom/seriatom.h b/seriatom/seriatom.h index 8381778..61bd46a 100644 --- a/seriatom/seriatom.h +++ b/seriatom/seriatom.h @@ -55,12 +55,30 @@ extern "C" { */ /** + Atom serialiser. +*/ +typedef struct SeriatomImpl Seriatom; + +/** + Create a new Atom serialiser. +*/ +SERIATOM_API +Seriatom* +seriatom_new(LV2_URID_Unmap* unmap); + +/** + Free an Atom serialisation. +*/ +SERIATOM_API +void +seriatom_free(Seriatom* seriatom); + +/** Serialise an Atom to a SerdWriter. */ SERIATOM_API void -atom_to_rdf(SerdWriter* writer, - LV2_URID_Unmap* unmap, +atom_to_rdf(Seriatom* seriatom, const SerdNode* subject, const SerdNode* predicate, const LV2_Atom* atom, @@ -72,7 +90,7 @@ atom_to_rdf(SerdWriter* writer, */ SERIATOM_API char* -atom_to_turtle(LV2_URID_Unmap* unmap, +atom_to_turtle(Seriatom* seriatom, const SerdNode* subject, const SerdNode* predicate, const LV2_Atom* atom); diff --git a/src/atom_to_rdf.c b/src/atom_to_rdf.c index f9e3895..11b2d38 100644 --- a/src/atom_to_rdf.c +++ b/src/atom_to_rdf.c @@ -14,17 +14,42 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <assert.h> #include <stdlib.h> #include <string.h> #include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "seriatom/seriatom.h" -#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define NS_XSD "http://www.w3.org/2001/XMLSchema#" +#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" +#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" #define USTR(str) ((const uint8_t*)(str)) +struct SeriatomImpl { + SerdWriter* writer; + LV2_URID_Unmap* unmap; + unsigned next_id; +}; + +SERIATOM_API +Seriatom* +seriatom_new(LV2_URID_Unmap* unmap) +{ + Seriatom* seriatom = (Seriatom*)malloc(sizeof(Seriatom)); + seriatom->writer = NULL; + seriatom->unmap = unmap; + seriatom->next_id = 0; + return seriatom; +} + +SERIATOM_API +void +seriatom_free(Seriatom* seriatom) +{ + free(seriatom); +} + typedef struct { char* buf; size_t len; @@ -40,20 +65,90 @@ string_sink(const void* buf, size_t len, void* stream) return len; } +static void +gensym(SerdNode* out, char c, unsigned num) +{ + out->n_bytes = out->n_chars = snprintf((char*)out->buf, 10, + "%c%u", c, num); +} + +static void +list_append(Seriatom* seriatom, + unsigned* flags, + SerdNode* s, + SerdNode* p, + SerdNode* node, + LV2_Atom* atom) +{ + // Generate a list node + gensym(node, 'l', seriatom->next_id); + serd_writer_write_statement(seriatom->writer, *flags, NULL, + s, p, node, NULL, NULL); + + // _:node rdf:first value + *flags = SERD_LIST_CONT; + *p = serd_node_from_string(SERD_URI, NS_RDF "first"); + atom_to_rdf(seriatom, node, p, atom, SERD_LIST_CONT); + + // Set subject to node and predicate to rdf:rest for next time + gensym(node, 'l', ++seriatom->next_id); + *s = *node; + *p = serd_node_from_string(SERD_URI, NS_RDF "rest"); +} + +static void +list_end(SerdWriter* writer, + LV2_URID_Unmap* unmap, + unsigned* flags, + SerdNode* s, + SerdNode* p) + +{ + // _:node rdf:rest rdf:nil + const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil"); + serd_writer_write_statement(writer, *flags, NULL, + s, p, &nil, NULL, NULL); +} + +static void +start_object(Seriatom* seriatom, + uint32_t flags, + const SerdNode* subject, + const SerdNode* predicate, + const SerdNode* node, + const char* type) +{ + serd_writer_write_statement( + seriatom->writer, flags|SERD_ANON_O_BEGIN, NULL, + subject, predicate, node, NULL, NULL); + if (type) { + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "type"); + SerdNode o = serd_node_from_string(SERD_URI, USTR(type)); + serd_writer_write_statement( + seriatom->writer, flags|SERD_ANON_CONT, NULL, + node, &p, &o, NULL, NULL); + } +} + SERIATOM_API void -atom_to_rdf(SerdWriter* writer, - LV2_URID_Unmap* unmap, +atom_to_rdf(Seriatom* seriatom, const SerdNode* subject, const SerdNode* predicate, const LV2_Atom* atom, uint32_t flags) { - const char* const type = unmap->unmap(unmap->handle, atom->type); - SerdNode object = SERD_NODE_NULL; - SerdNode datatype = SERD_NODE_NULL; - SerdNode language = SERD_NODE_NULL; - bool new_node = false; + LV2_URID_Unmap* unmap = seriatom->unmap; + SerdWriter* writer = seriatom->writer; + const char* const type = unmap->unmap(unmap->handle, atom->type); + uint8_t idbuf[12] = "b0000000000"; + SerdNode id = serd_node_from_string(SERD_BLANK, idbuf); + uint8_t nodebuf[12] = "b0000000000"; + SerdNode node = serd_node_from_string(SERD_BLANK, nodebuf); + SerdNode object = SERD_NODE_NULL; + SerdNode datatype = SERD_NODE_NULL; + SerdNode language = SERD_NODE_NULL; + bool new_node = false; if (atom->type == 0 && atom->size == 0) { object = serd_node_from_string(SERD_BLANK, USTR("null")); } else if (!strcmp(type, LV2_ATOM__String)) { @@ -91,52 +186,55 @@ atom_to_rdf(SerdWriter* writer, } else if (!strcmp(type, LV2_ATOM__Int32)) { new_node = true; object = serd_node_new_integer(*(int32_t*)LV2_ATOM_BODY(atom)); - datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "int")); + datatype = serd_node_from_string(SERD_URI, NS_XSD "int"); } else if (!strcmp(type, LV2_ATOM__Int64)) { new_node = true; object = serd_node_new_integer(*(int64_t*)LV2_ATOM_BODY(atom)); - datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "long")); + datatype = serd_node_from_string(SERD_URI, NS_XSD "long"); } else if (!strcmp(type, LV2_ATOM__Float)) { new_node = true; object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 8); - datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "float")); + datatype = serd_node_from_string(SERD_URI, NS_XSD "float"); } else if (!strcmp(type, LV2_ATOM__Double)) { new_node = true; object = serd_node_new_decimal(*(double*)LV2_ATOM_BODY(atom), 16); - datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "double")); + datatype = serd_node_from_string(SERD_URI, NS_XSD "double"); } else if (!strcmp(type, LV2_ATOM__Bool)) { const int32_t val = *(const int32_t*)LV2_ATOM_BODY(atom); - datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "boolean")); + datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean"); object = serd_node_from_string(SERD_LITERAL, USTR(val ? "true" : "false")); - } else if (!strcmp(type, LV2_ATOM__Blank)) { - const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom; - const char* otype = unmap->unmap(unmap->handle, obj->otype); - SerdNode idnum = serd_node_new_integer(obj->id); - SerdNode id = serd_node_from_string(SERD_BLANK, idnum.buf); - serd_writer_write_statement( - writer, flags|SERD_ANON_O_BEGIN, NULL, - subject, predicate, &id, NULL, NULL); - if (otype) { - SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "type")); - SerdNode o = serd_node_from_string(SERD_URI, USTR(otype)); - serd_writer_write_statement(writer, SERD_ANON_CONT, NULL, - &id, &p, &o, NULL, NULL); + } else if (!strcmp(type, LV2_ATOM__Tuple)) { + const LV2_Atom_Tuple* tup = (const LV2_Atom_Tuple*)atom; + gensym(&id, 't', seriatom->next_id++); + start_object(seriatom, flags, subject, predicate, &id, type); + SerdNode s = id; + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); + flags |= SERD_LIST_O_BEGIN; + LV2_TUPLE_FOREACH(tup, i) { + list_append(seriatom, &flags, &s, &p, &node, i); } + list_end(writer, unmap, &flags, &s, &p); + + serd_writer_end_anon(writer, &id); + } else if (!strcmp(type, LV2_ATOM__Blank)) { + const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom; + const char* otype = unmap->unmap(unmap->handle, obj->otype); + gensym(&id, 'b', seriatom->next_id++); + start_object(seriatom, flags, subject, predicate, &id, otype); LV2_OBJECT_FOREACH(obj, i) { const LV2_Atom_Property_Body* prop = lv2_object_iter_get(i); const char* const key = unmap->unmap(unmap->handle, prop->key); SerdNode pred = serd_node_from_string(SERD_URI, USTR(key)); - atom_to_rdf(writer, unmap, &id, &pred, &prop->value, SERD_ANON_CONT); + atom_to_rdf(seriatom, &id, &pred, &prop->value, flags|SERD_ANON_CONT); } - serd_writer_end_anon(writer, &id); - serd_node_free(&idnum); + serd_writer_end_anon(seriatom->writer, &id); } else { object = serd_node_from_string(SERD_LITERAL, USTR("(unknown)")); } if (object.buf) { - serd_writer_write_statement(writer, flags, NULL, + serd_writer_write_statement(seriatom->writer, flags, NULL, subject, predicate, &object, &datatype, &language); } @@ -148,7 +246,7 @@ atom_to_rdf(SerdWriter* writer, SERIATOM_API char* -atom_to_turtle(LV2_URID_Unmap* unmap, +atom_to_turtle(Seriatom* seriatom, const SerdNode* subject, const SerdNode* predicate, const LV2_Atom* atom) @@ -156,18 +254,25 @@ atom_to_turtle(LV2_URID_Unmap* unmap, SerdURI base_uri = SERD_URI_NULL; SerdEnv* env = serd_env_new(NULL); String str = { NULL, 0 }; - SerdWriter* writer = serd_writer_new( + + serd_env_set_prefix_from_strings(env, USTR("atom"), + USTR(LV2_ATOM_URI "#")); + serd_env_set_prefix_from_strings(env, USTR("rdf"), NS_RDF); + serd_env_set_prefix_from_strings(env, USTR("xsd"), NS_XSD); + + + seriatom->writer = serd_writer_new( SERD_TURTLE, SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED, + /* SERD_NTRIPLES, + 0,*/ env, &base_uri, string_sink, &str); - serd_env_set_prefix_from_strings(env, USTR("rdf"), USTR(NS_RDF)); - serd_env_set_prefix_from_strings(env, USTR("xsd"), USTR(NS_XSD)); - atom_to_rdf(writer, unmap, subject, predicate, atom, 0); - serd_writer_finish(writer); + atom_to_rdf(seriatom, subject, predicate, atom, 0); + serd_writer_finish(seriatom->writer); string_sink("", 1, &str); - serd_writer_free(writer); + serd_writer_free(seriatom->writer); serd_env_free(env); return str.buf; } diff --git a/tests/seriatom_test.c b/tests/seriatom_test.c index 799c498..67da65d 100644 --- a/tests/seriatom_test.c +++ b/tests/seriatom_test.c @@ -81,6 +81,8 @@ main() LV2_Atom_Forge forge; lv2_atom_forge_init(&forge, &map); + Seriatom* seriatom = seriatom_new(&unmap); + LV2_URID eg_Object = urid_map(NULL, "http://example.org/Object"); LV2_URID eg_one = urid_map(NULL, "http://example.org/one"); LV2_URID eg_two = urid_map(NULL, "http://example.org/two"); @@ -267,8 +269,9 @@ main() SerdNode s = serd_node_from_string(SERD_BLANK, USTR("obj")); SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); - printf("%s", atom_to_turtle(&unmap, &s, &p, obj)); + printf("%s", atom_to_turtle(seriatom, &s, &p, obj)); printf("All tests passed.\n"); + seriatom_free(seriatom); return 0; } @@ -55,7 +55,7 @@ def configure(conf): mandatory=False) autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD', - atleast_version='0.8.0', mandatory=True) + atleast_version='0.10.0', mandatory=True) autowaf.define(conf, 'SERIATOM_VERSION', SERIATOM_VERSION) conf.write_config_header('seriatom_config.h', remove=False) |