From 6408ee7d93ed041a053627e3506c444e215654d4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 1 Mar 2012 06:39:57 +0000 Subject: Implement Turtle reading (except for atom:Vector). git-svn-id: http://svn.drobilla.net/lad/trunk/sratom@4006 a436a847-0d15-0410-975c-d299462d15a1 --- sratom.pc.in | 10 +- sratom/sratom.h | 31 ++++- src/sratom.c | 348 ++++++++++++++++++++++++++++++++++++++++++++-------- tests/sratom_test.c | 136 ++++++-------------- wscript | 15 ++- 5 files changed, 378 insertions(+), 162 deletions(-) diff --git a/sratom.pc.in b/sratom.pc.in index 1e3af45..4daf9fa 100644 --- a/sratom.pc.in +++ b/sratom.pc.in @@ -3,9 +3,9 @@ exec_prefix=@EXEC_PREFIX@ libdir=@LIBDIR@ includedir=@INCLUDEDIR@ -Name: Seriatom -Version: @SERIATOM_VERSION@ +Name: Sratom +Version: @SRATOM_VERSION@ Description: LV2 Atom RDF serialisation library -Requires: serd-0 -Libs: -L${libdir} -l@LIB_SERIATOM@ -Cflags: -I${includedir}/seriatom-@SERIATOM_MAJOR_VERSION@ +Requires: serd-0 sord-0 +Libs: -L${libdir} -lsratom-@SRATOM_MAJOR_VERSION@ +Cflags: -I${includedir}/sratom-@SRATOM_MAJOR_VERSION@ diff --git a/sratom/sratom.h b/sratom/sratom.h index 68d1390..fdbad78 100644 --- a/sratom/sratom.h +++ b/sratom/sratom.h @@ -24,7 +24,9 @@ #include #include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "serd/serd.h" +#include "sord/sord.h" #ifdef SRATOM_SHARED # ifdef _WIN32 @@ -75,17 +77,31 @@ sratom_free(Sratom* sratom); /** Write an Atom to RDF. + The resulting serialised atom is written to @p writer. */ SRATOM_API void sratom_write(Sratom* sratom, + SerdWriter* writer, uint32_t flags, const SerdNode* subject, const SerdNode* predicate, - uint32_t type_urid, + uint32_t type, uint32_t size, const void* body); +/** + Read an Atom from RDF. + The resulting atom will be written to @p forge. +*/ +SRATOM_API +void +sratom_read(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node); + /** Serialise an Atom to a Turtle string. The returned string must be free()'d by the caller. @@ -95,10 +111,21 @@ char* sratom_to_turtle(Sratom* sratom, const SerdNode* subject, const SerdNode* predicate, - uint32_t type_urid, + uint32_t type, uint32_t size, const void* body); +/** + Read an Atom from a Turtle string. + The returned atom must be free()'d by the caller. +*/ +SRATOM_API +LV2_Atom* +sratom_from_turtle(Sratom* sratom, + const SerdNode* subject, + const SerdNode* predicate, + const char* str); + /** @} */ diff --git a/src/sratom.c b/src/sratom.c index f919f89..b38b304 100644 --- a/src/sratom.c +++ b/src/sratom.c @@ -23,34 +23,56 @@ #include "sratom/sratom.h" +#define NS_ATOM (const uint8_t*)"http://lv2plug.in/ns/ext/atom#" +#define NS_MIDI (const uint8_t*)"http://lv2plug.in/ns/ext/midi#" #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 NS_MIDI (const uint8_t*)"http://lv2plug.in/ns/ext/midi#" #define USTR(str) ((const uint8_t*)(str)) +typedef enum { + MODE_NORMAL, + MODE_SEQUENCE, +} ReadMode; + struct SratomImpl { - SerdWriter* writer; LV2_URID_Map* map; LV2_URID_Unmap* unmap; LV2_Atom_Forge forge; LV2_URID atom_Event; LV2_URID midi_MidiEvent; unsigned next_id; + struct { + SordNode* atom_frameTime; + SordNode* rdf_first; + SordNode* rdf_rest; + SordNode* rdf_type; + SordNode* rdf_value; + } nodes; }; +static void +sratom_read_internal(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode); + SRATOM_API Sratom* sratom_new(LV2_URID_Map* map, LV2_URID_Unmap* unmap) { Sratom* sratom = (Sratom*)malloc(sizeof(Sratom)); - sratom->writer = NULL; sratom->map = map; sratom->unmap = unmap; - sratom->atom_Event = map->map(map->handle, LV2_ATOM_URI "#Event"); - sratom->midi_MidiEvent = map->map(map->handle, (const char*)NS_MIDI "MidiEvent"); + sratom->atom_Event = map->map(map->handle, + (const char*)NS_ATOM "#Event"); + sratom->midi_MidiEvent = map->map(map->handle, + (const char*)NS_MIDI "MidiEvent"); sratom->next_id = 0; + memset(&sratom->nodes, 0, sizeof(sratom->nodes)); lv2_atom_forge_init(&sratom->forge, map); return sratom; } @@ -85,24 +107,24 @@ gensym(SerdNode* out, char c, unsigned num) } static void -list_append(Sratom* sratom, - unsigned* flags, - SerdNode* s, - SerdNode* p, - SerdNode* node, - uint32_t type, - uint32_t size, - void* body) +list_append(Sratom* sratom, + SerdWriter* writer, + unsigned* flags, + SerdNode* s, + SerdNode* p, + SerdNode* node, + uint32_t type, + uint32_t size, + void* body) { // Generate a list node gensym(node, 'l', sratom->next_id); - serd_writer_write_statement(sratom->writer, *flags, NULL, - s, p, node, NULL, NULL); + serd_writer_write_statement(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"); - sratom_write(sratom, SERD_LIST_CONT, node, p, type, size, body); + sratom_write(sratom, writer, SERD_LIST_CONT, node, p, type, size, body); // Set subject to node and predicate to rdf:rest for next time gensym(node, 'l', ++sratom->next_id); @@ -121,6 +143,7 @@ list_end(SerdWriter* writer, unsigned* flags, SerdNode* s, SerdNode* p) static void start_object(Sratom* sratom, + SerdWriter* writer, uint32_t flags, const SerdNode* subject, const SerdNode* predicate, @@ -128,13 +151,13 @@ start_object(Sratom* sratom, const char* type) { serd_writer_write_statement( - sratom->writer, flags|SERD_ANON_O_BEGIN, NULL, + 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( - sratom->writer, SERD_ANON_CONT, NULL, + writer, SERD_ANON_CONT, NULL, node, &p, &o, NULL, NULL); } } @@ -142,6 +165,7 @@ start_object(Sratom* sratom, SRATOM_API void sratom_write(Sratom* sratom, + SerdWriter* writer, uint32_t flags, const SerdNode* subject, const SerdNode* predicate, @@ -187,7 +211,7 @@ 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); + object = serd_node_from_string(SERD_LITERAL, str); datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path)); } else if (type_urid == sratom->forge.URI) { const uint8_t* str = USTR(body); @@ -216,45 +240,46 @@ sratom_write(Sratom* sratom, } else if (type_urid == sratom->midi_MidiEvent) { new_node = true; datatype = serd_node_from_string(SERD_URI, NS_MIDI "MidiEvent"); - uint8_t* str = calloc(size * 2, 1); + uint8_t* str = calloc(size * 2 + 1, 1); for (uint32_t i = 0; i < size; ++i) { - sprintf((char*)str + (2 * i), "%02X", - (unsigned)(uint8_t)*((uint8_t*)body + i)); + snprintf((char*)str + (2 * i), size * 2 + 1, "%02X", + (unsigned)(uint8_t)*((uint8_t*)body + i)); } object = serd_node_from_string(SERD_LITERAL, USTR(str)); } else if (type_urid == sratom->atom_Event) { const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body; gensym(&id, 'e', sratom->next_id++); - start_object(sratom, flags, subject, predicate, &id, NULL); + start_object(sratom, writer, flags, subject, predicate, &id, NULL); // TODO: beat time - SerdNode p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__frameTime)); SerdNode time = serd_node_new_integer(ev->time.frames); + SerdNode p = serd_node_from_string(SERD_URI, + USTR(LV2_ATOM__frameTime)); datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal"); - serd_writer_write_statement(sratom->writer, SERD_ANON_CONT, NULL, + serd_writer_write_statement(writer, SERD_ANON_CONT, NULL, &id, &p, &time, &datatype, &language); serd_node_free(&time); - + p = serd_node_from_string(SERD_URI, NS_RDF "value"); - sratom_write(sratom, SERD_ANON_CONT, &id, &p, + sratom_write(sratom, writer, SERD_ANON_CONT, &id, &p, ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body)); - serd_writer_end_anon(sratom->writer, &id); + serd_writer_end_anon(writer, &id); } else if (type_urid == sratom->forge.Tuple) { gensym(&id, 't', sratom->next_id++); - start_object(sratom, flags, subject, predicate, &id, type); + start_object(sratom, writer, flags, subject, predicate, &id, type); SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); flags |= SERD_LIST_O_BEGIN; LV2_TUPLE_BODY_FOREACH(body, size, i) { - list_append(sratom, &flags, &id, &p, &node, + list_append(sratom, writer, &flags, &id, &p, &node, i->type, i->size, LV2_ATOM_BODY(i)); } - list_end(sratom->writer, &flags, &id, &p); - serd_writer_end_anon(sratom->writer, &id); + list_end(writer, &flags, &id, &p); + serd_writer_end_anon(writer, &id); } else if (type_urid == sratom->forge.Vector) { const LV2_Atom_Vector_Body* vec = (const LV2_Atom_Vector_Body*)body; gensym(&id, 'v', sratom->next_id++); - start_object(sratom, flags, subject, predicate, &id, type); + start_object(sratom, writer, flags, subject, predicate, &id, type); SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); const uint32_t content_size = size - sizeof(LV2_Atom_Vector_Body); const uint32_t elem_size = content_size / vec->elem_count; @@ -262,46 +287,47 @@ sratom_write(Sratom* sratom, for (char* i = (char*)(vec + 1); i < (char*)vec + size; i += elem_size) { - list_append(sratom, &flags, &id, &p, &node, + list_append(sratom, writer, &flags, &id, &p, &node, vec->elem_type, elem_size, i); } - list_end(sratom->writer, &flags, &id, &p); - serd_writer_end_anon(sratom->writer, &id); + list_end(writer, &flags, &id, &p); + serd_writer_end_anon(writer, &id); } else if (type_urid == sratom->forge.Blank) { const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body; - const char* otype = unmap->unmap(unmap->handle, obj->otype); + const char* otype = unmap->unmap(unmap->handle, + obj->otype); gensym(&id, 'b', sratom->next_id++); - start_object(sratom, flags, subject, predicate, &id, otype); + start_object(sratom, writer, flags, subject, predicate, &id, otype); LV2_OBJECT_BODY_FOREACH(obj, size, 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)); - sratom_write(sratom, flags|SERD_ANON_CONT, &id, &pred, + sratom_write(sratom, writer, flags|SERD_ANON_CONT, &id, &pred, prop->value.type, prop->value.size, LV2_ATOM_BODY(&prop->value)); } - serd_writer_end_anon(sratom->writer, &id); + serd_writer_end_anon(writer, &id); } else if (type_urid == sratom->forge.Sequence) { - const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body; + const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body; gensym(&id, 'v', sratom->next_id++); - start_object(sratom, flags, subject, predicate, &id, type); + start_object(sratom, writer, flags, subject, predicate, &id, type); SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); flags |= SERD_LIST_O_BEGIN; LV2_SEQUENCE_BODY_FOREACH(seq, size, i) { LV2_Atom_Event* ev = lv2_sequence_iter_get(i); - list_append(sratom, &flags, &id, &p, &node, + list_append(sratom, writer, &flags, &id, &p, &node, sratom->atom_Event, sizeof(LV2_Atom_Event) + ev->body.size, ev); } - list_end(sratom->writer, &flags, &id, &p); - serd_writer_end_anon(sratom->writer, &id); + list_end(writer, &flags, &id, &p); + serd_writer_end_anon(writer, &id); } else { object = serd_node_from_string(SERD_LITERAL, USTR("(unknown)")); } if (object.buf) { - serd_writer_write_statement(sratom->writer, flags, NULL, + serd_writer_write_statement(writer, flags, NULL, subject, predicate, &object, &datatype, &language); } @@ -332,17 +358,237 @@ sratom_to_turtle(Sratom* sratom, serd_env_set_prefix_from_strings(env, USTR("eg"), USTR("http://example.org/")); - sratom->writer = serd_writer_new( + SerdWriter* writer = serd_writer_new( SERD_TURTLE, SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED, env, &base_uri, string_sink, &str); - sratom_write(sratom, SERD_EMPTY_S, subject, predicate, type, size, body); - serd_writer_finish(sratom->writer); + // Write @prefix directives + serd_env_foreach(env, + (SerdPrefixSink)serd_writer_set_prefix, + writer); + + sratom_write(sratom, writer, SERD_EMPTY_S, + subject, predicate, type, size, body); + serd_writer_finish(writer); string_sink("", 1, &str); - serd_writer_free(sratom->writer); + serd_writer_free(writer); serd_env_free(env); - free(str.buf); return str.buf; } + +static const SordNode* +get_object(SordModel* model, + const SordNode* subject, + const SordNode* predicate) +{ + const SordNode* object = NULL; + SordQuad q = { subject, predicate, 0, 0 }; + SordIter* i = sord_find(model, q); + if (!sord_iter_end(i)) { + SordQuad quad; + sord_iter_get(i, quad); + object = quad[SORD_OBJECT]; + } + sord_iter_free(i); + return object; +} + +static void +read_list_value(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode) +{ + const SordNode* first = get_object(model, node, sratom->nodes.rdf_first); + const SordNode* rest = get_object(model, node, sratom->nodes.rdf_rest); + if (first && rest) { + sratom_read_internal(sratom, forge, world, model, first, mode); + read_list_value(sratom, forge, world, model, rest, mode); + } +} + +static void +sratom_read_internal(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode) +{ + const char* str = (const char*)sord_node_get_string(node); + if (sord_node_get_type(node) == SORD_LITERAL) { + char* endptr; + SordNode* datatype = sord_node_get_datatype(node); + const char* language = sord_node_get_language(node); + if (datatype) { + const char* type_uri = (const char*)sord_node_get_string(datatype); + if (!strcmp(type_uri, (char*)NS_XSD "int")) { + lv2_atom_forge_int32(forge, strtol(str, &endptr, 10)); + } else if (!strcmp(type_uri, (char*)NS_XSD "long")) { + lv2_atom_forge_int64(forge, strtol(str, &endptr, 10)); + } else if (!strcmp(type_uri, (char*)NS_XSD "float")) { + lv2_atom_forge_float(forge, serd_strtod(str, &endptr)); + } else if (!strcmp(type_uri, (char*)NS_XSD "double")) { + lv2_atom_forge_float(forge, serd_strtod(str, &endptr)); + } else if (!strcmp(type_uri, (char*)NS_XSD "boolean")) { + lv2_atom_forge_bool(forge, !strcmp(str, "true")); + } else { + lv2_atom_forge_literal( + forge, (const uint8_t*)str, strlen(str), + sratom->map->map(sratom->map->handle, type_uri), + 0); + } + } else if (language) { + const char* prefix = "http://lexvo.org/id/iso639-3/"; + const size_t lang_len = strlen(prefix) + strlen(language); + char* lang_uri = calloc(lang_len + 1, 1); + snprintf(lang_uri, lang_len + 1, "%s%s", prefix, language); + lv2_atom_forge_literal( + forge, (const uint8_t*)str, strlen(str), 0, + sratom->map->map(sratom->map->handle, lang_uri)); + free(lang_uri); + } else { + lv2_atom_forge_string(forge, (const uint8_t*)str, strlen(str)); + } + } else if (sord_node_get_type(node) == SORD_URI) { + lv2_atom_forge_uri(forge, (const uint8_t*)str, strlen(str)); + } else { + LV2_URID_Map* map = sratom->map; + const SordNode* type = get_object(model, node, sratom->nodes.rdf_type); + + const uint8_t* type_uri = NULL; + uint32_t type_urid = 0; + if (type) { + type_uri = sord_node_get_string(type); + type_urid = map->map(map->handle, (const char*)type_uri); + } + + LV2_Atom_Forge_Frame frame = { 0, 0 }; + if (mode == MODE_SEQUENCE) { + const SordNode* frame_time = get_object( + model, node, sratom->nodes.atom_frameTime); + const SordNode* value = get_object( + model, node, sratom->nodes.rdf_value); + 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)); + sratom_read_internal(sratom, forge, world, model, value, MODE_NORMAL); + } else if (type_urid == sratom->forge.Tuple) { + lv2_atom_forge_tuple(forge, &frame); + const SordNode* value = get_object( + model, node, sratom->nodes.rdf_value); + read_list_value(sratom, forge, world, model, value, MODE_NORMAL); + } else if (type_urid == sratom->forge.Sequence) { + lv2_atom_forge_sequence_head(forge, &frame, 0); + const SordNode* value = get_object( + model, node, sratom->nodes.rdf_value); + read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE); + } else { + lv2_atom_forge_blank(forge, &frame, 1, type_urid); + + SordQuad q = { node, 0, 0, 0 }; + for (SordIter* i = sord_find(model, q); + !sord_iter_end(i); + sord_iter_next(i)) { + SordQuad quad; + sord_iter_get(i, quad); + const SordNode* key = quad[SORD_PREDICATE]; + lv2_atom_forge_property_head( + forge, + map->map(map->handle, (const char*)sord_node_get_string(key)), + 0); + sratom_read_internal(sratom, forge, world, model, quad[SORD_OBJECT], MODE_NORMAL); + } + } + if (frame.ref) { + lv2_atom_forge_pop(forge, &frame); + } + } +} + +SRATOM_API +void +sratom_read(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node) +{ + sratom->nodes.atom_frameTime = sord_new_uri(world, NS_ATOM "frameTime"); + sratom->nodes.rdf_first = sord_new_uri(world, NS_RDF "first"); + sratom->nodes.rdf_rest = sord_new_uri(world, NS_RDF "rest"); + sratom->nodes.rdf_type = sord_new_uri(world, NS_RDF "type"); + sratom->nodes.rdf_value = sord_new_uri(world, NS_RDF "value"); + + sratom_read_internal(sratom, forge, world, model, node, MODE_NORMAL); + + sord_node_free(world, sratom->nodes.rdf_value); + sord_node_free(world, sratom->nodes.rdf_type); + sord_node_free(world, sratom->nodes.rdf_rest); + sord_node_free(world, sratom->nodes.rdf_first); + sord_node_free(world, sratom->nodes.atom_frameTime); + memset(&sratom->nodes, 0, sizeof(sratom->nodes)); +} + +static LV2_Atom_Forge_Ref +forge_sink(LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size) +{ + String* string = (String*)handle; + const LV2_Atom_Forge_Ref ref = string->len; + string_sink(buf, size, string); + return ref; +} + +static void* +forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref) +{ + String* string = (String*)handle; + return string->buf + ref; +} + +SRATOM_API +LV2_Atom* +sratom_from_turtle(Sratom* sratom, + const SerdNode* subject, + const SerdNode* predicate, + const char* str) +{ + String 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); + + 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, forge_sink, forge_deref, &out); + sratom_read(sratom, &sratom->forge, world, model, result[SORD_OBJECT]); + } else { + fprintf(stderr, "Failed to find node\n"); + } + } else { + fprintf(stderr, "Failed to read Turtle\n"); + } + + serd_reader_free(reader); + serd_env_free(env); + sord_free(model); + sord_world_free(world); + + return (LV2_Atom*)out.buf; +} diff --git a/tests/sratom_test.c b/tests/sratom_test.c index 253d52c..973819e 100644 --- a/tests/sratom_test.c +++ b/tests/sratom_test.c @@ -27,8 +27,8 @@ #define USTR(s) ((const uint8_t*)(s)) -char** uris = NULL; -size_t n_uris = 0; +static char** uris = NULL; +static size_t n_uris = 0; char* copy_string(const char* str) @@ -57,7 +57,7 @@ const char* urid_unmap(LV2_URID_Unmap_Handle handle, LV2_URID urid) { - if (urid <= n_uris) { + if (urid > 0 && urid <= n_uris) { return uris[urid - 1]; } return NULL; @@ -106,109 +106,65 @@ main() lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf)); LV2_Atom_Forge_Frame obj_frame; - LV2_Atom* obj = (LV2_Atom*)lv2_atom_forge_blank( - &forge, &obj_frame, 1, eg_Object); + LV2_Atom* obj = (LV2_Atom*)lv2_atom_forge_deref( + &forge, lv2_atom_forge_blank(&forge, &obj_frame, 1, eg_Object)); // eg_one = (Int32)1 lv2_atom_forge_property_head(&forge, eg_one, 0); - LV2_Atom_Int32* one = lv2_atom_forge_int32(&forge, 1); - if (one->body != 1) { - return test_fail("%d != 1\n", one->body); - } + lv2_atom_forge_int32(&forge, 1); // eg_two = (Int64)2 lv2_atom_forge_property_head(&forge, eg_two, 0); - LV2_Atom_Int64* two = lv2_atom_forge_int64(&forge, 2); - if (two->body != 2) { - return test_fail("%ld != 2\n", two->body); - } + lv2_atom_forge_int64(&forge, 2); // eg_three = (Float)3.0 lv2_atom_forge_property_head(&forge, eg_three, 0); - LV2_Atom_Float* three = lv2_atom_forge_float(&forge, 3.0f); - if (three->body != 3) { - return test_fail("%f != 3\n", three->body); - } - + lv2_atom_forge_float(&forge, 3.0f); + // eg_four = (Double)4.0 lv2_atom_forge_property_head(&forge, eg_four, 0); - LV2_Atom_Double* four = lv2_atom_forge_double(&forge, 4.0); - if (four->body != 4) { - return test_fail("%ld != 4\n", four->body); - } + lv2_atom_forge_double(&forge, 4.0); // eg_true = (Bool)1 lv2_atom_forge_property_head(&forge, eg_true, 0); - LV2_Atom_Bool* t = lv2_atom_forge_bool(&forge, true); - if (t->body != 1) { - return test_fail("%ld != 1 (true)\n", t->body); - } + lv2_atom_forge_bool(&forge, true); // eg_false = (Bool)0 lv2_atom_forge_property_head(&forge, eg_false, 0); - LV2_Atom_Bool* f = lv2_atom_forge_bool(&forge, false); - if (f->body != 0) { - return test_fail("%ld != 0 (false)\n", f->body); - } + lv2_atom_forge_bool(&forge, false); // eg_path = (Path)"/foo/bar" const uint8_t* pstr = (const uint8_t*)"/foo/bar"; const size_t pstr_len = strlen((const char*)pstr); lv2_atom_forge_property_head(&forge, eg_path, 0); - LV2_Atom_String* path = lv2_atom_forge_uri(&forge, pstr, pstr_len); - uint8_t* pbody = (uint8_t*)LV2_ATOM_BODY(path); - if (strcmp((const char*)pbody, (const char*)pstr)) { - return test_fail("%s != \"%s\"\n", - (const char*)pbody, (const char*)pstr); - } + lv2_atom_forge_uri(&forge, pstr, pstr_len); // eg_uri = (URI)"http://example.org/value" const uint8_t* ustr = (const uint8_t*)"http://example.org/value"; const size_t ustr_len = strlen((const char*)ustr); lv2_atom_forge_property_head(&forge, eg_uri, 0); - LV2_Atom_String* uri = lv2_atom_forge_uri(&forge, ustr, ustr_len); - uint8_t* ubody = (uint8_t*)LV2_ATOM_BODY(uri); - if (strcmp((const char*)ubody, (const char*)ustr)) { - return test_fail("%s != \"%s\"\n", - (const char*)ubody, (const char*)ustr); - } + 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); - LV2_Atom_URID* urid = lv2_atom_forge_urid(&forge, eg_value); - if (urid->body != eg_value) { - return test_fail("%u != %u\n", urid->body, eg_value); - } + lv2_atom_forge_urid(&forge, eg_value); // eg_string = (String)"hello" lv2_atom_forge_property_head(&forge, eg_string, 0); - LV2_Atom_String* string = lv2_atom_forge_string( - &forge, (const uint8_t*)"hello", strlen("hello")); - uint8_t* sbody = (uint8_t*)LV2_ATOM_BODY(string); - if (strcmp((const char*)sbody, "hello")) { - return test_fail("%s != \"hello\"\n", (const char*)sbody); - } + lv2_atom_forge_string(&forge, (const uint8_t*)"hello", strlen("hello")); // eg_langlit = (Literal)"bonjour"@fr lv2_atom_forge_property_head(&forge, eg_langlit, 0); - LV2_Atom_Literal* langlit = lv2_atom_forge_literal( + lv2_atom_forge_literal( &forge, (const uint8_t*)"bonjour", strlen("bonjour"), 0, urid_map(NULL, "http://lexvo.org/id/iso639-3/fra")); - uint8_t* llbody = (uint8_t*)LV2_ATOM_CONTENTS(LV2_Atom_Literal, langlit); - if (strcmp((const char*)llbody, "bonjour")) { - return test_fail("%s != \"bonjour\"\n", (const char*)llbody); - } // eg_typelit = (Literal)"bonjour"@fr lv2_atom_forge_property_head(&forge, eg_typelit, 0); - LV2_Atom_Literal* typelit = lv2_atom_forge_literal( + lv2_atom_forge_literal( &forge, (const uint8_t*)"value", strlen("value"), urid_map(NULL, "http://example.org/Type"), 0); - uint8_t* tlbody = (uint8_t*)LV2_ATOM_CONTENTS(LV2_Atom_Literal, typelit); - if (strcmp((const char*)tlbody, "value")) { - return test_fail("%s != \"value\"\n", (const char*)tlbody); - } // eg_blank = [ a ] lv2_atom_forge_property_head(&forge, eg_blank, 0); @@ -219,68 +175,48 @@ main() // eg_tuple = "foo",true lv2_atom_forge_property_head(&forge, eg_tuple, 0); LV2_Atom_Forge_Frame tuple_frame; - LV2_Atom_Tuple* tuple = (LV2_Atom_Tuple*)lv2_atom_forge_tuple( - &forge, &tuple_frame); - LV2_Atom_String* tup0 = lv2_atom_forge_string( - &forge, (const uint8_t*)"foo", strlen("foo")); - LV2_Atom_Bool* tup1 = lv2_atom_forge_bool(&forge, true); + lv2_atom_forge_tuple(&forge, &tuple_frame); + lv2_atom_forge_string(&forge, (const uint8_t*)"foo", strlen("foo")); + lv2_atom_forge_bool(&forge, true); lv2_atom_forge_pop(&forge, &tuple_frame); - LV2_Atom_Tuple_Iter i = lv2_tuple_begin(tuple); - if (lv2_tuple_is_end(tuple, i)) { - return test_fail("Tuple iterator is empty\n"); - } - LV2_Atom* tup0i = (LV2_Atom*)lv2_tuple_iter_get(i); - if (!lv2_atom_equals((LV2_Atom*)tup0, tup0i)) { - return test_fail("Corrupt tuple element 0\n"); - } - i = lv2_tuple_iter_next(i); - if (lv2_tuple_is_end(tuple, i)) { - return test_fail("Premature end of tuple iterator\n"); - } - LV2_Atom* tup1i = lv2_tuple_iter_get(i); - if (!lv2_atom_equals((LV2_Atom*)tup1, tup1i)) { - return test_fail("Corrupt tuple element 1\n"); - } - i = lv2_tuple_iter_next(i); - if (!lv2_tuple_is_end(tuple, i)) { - return test_fail("Tuple iter is not at end\n"); - } // eg_vector = (Vector)1,2,3,4 lv2_atom_forge_property_head(&forge, eg_vector, 0); int32_t elems[] = { 1, 2, 3, 4 }; - LV2_Atom_Vector* vector = lv2_atom_forge_vector( - &forge, 4, forge.Int32, sizeof(int32_t), elems); - void* vec_body = LV2_ATOM_CONTENTS(LV2_Atom_Vector, vector); - if (memcmp(elems, vec_body, sizeof(elems))) { - return test_fail("Corrupt vector\n"); - } + lv2_atom_forge_vector(&forge, 4, forge.Int32, sizeof(int32_t), elems); // eg_seq = (Sequence)1, 2 LV2_URID midi_midiEvent = map.map(map.handle, NS_MIDI "MidiEvent"); lv2_atom_forge_property_head(&forge, eg_seq, 0); LV2_Atom_Forge_Frame seq_frame; lv2_atom_forge_sequence_head(&forge, &seq_frame, 0); - + const uint8_t ev1[3] = { 0x90, 0x1A, 0x1 }; lv2_atom_forge_frame_time(&forge, 1); - lv2_atom_forge_atom(&forge, midi_midiEvent, sizeof(ev1)); + lv2_atom_forge_atom(&forge, sizeof(ev1), midi_midiEvent); lv2_atom_forge_raw(&forge, ev1, sizeof(ev1)); lv2_atom_forge_pad(&forge, sizeof(ev1)); const uint8_t ev2[3] = { 0x90, 0x2B, 0x2 }; lv2_atom_forge_frame_time(&forge, 3); - lv2_atom_forge_atom(&forge, midi_midiEvent, sizeof(ev2)); + lv2_atom_forge_atom(&forge, sizeof(ev2), midi_midiEvent); lv2_atom_forge_raw(&forge, ev2, sizeof(ev2)); lv2_atom_forge_pad(&forge, sizeof(ev2)); lv2_atom_forge_pop(&forge, &seq_frame); lv2_atom_forge_pop(&forge, &obj_frame); - SerdNode s = serd_node_from_string(SERD_BLANK, USTR("obj")); - SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); - printf("%s", sratom_to_turtle(sratom, &s, &p, - obj->type, obj->size, LV2_ATOM_BODY(obj))); + 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, &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); + + char* instr = sratom_to_turtle( + sratom, &s, &p, parsed->type, parsed->size, LV2_ATOM_BODY(parsed)); + printf("# Turtle => Atom\n\n%s", instr); printf("All tests passed.\n"); sratom_free(sratom); diff --git a/wscript b/wscript index 6253af7..b8798f4 100644 --- a/wscript +++ b/wscript @@ -37,6 +37,7 @@ def options(opt): def configure(conf): conf.load('compiler_c') + conf.line_just = 41 autowaf.configure(conf) autowaf.display_header('Sratom Configuration') @@ -54,8 +55,14 @@ def configure(conf): define_name='HAVE_GCOV', mandatory=False) + autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-atom', + uselib_store='LV2_ATOM', mandatory=True) + autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-urid', + uselib_store='LV2_URID', mandatory=True) autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD', atleast_version='0.10.0', mandatory=True) + autowaf.check_pkg(conf, 'sord-0', uselib_store='SORD', + atleast_version='0.5.0', mandatory=True) autowaf.define(conf, 'SRATOM_VERSION', SRATOM_VERSION) conf.write_config_header('sratom_config.h', remove=False) @@ -72,7 +79,7 @@ def build(bld): # Pkgconfig file autowaf.build_pc(bld, 'SRATOM', SRATOM_VERSION, SRATOM_MAJOR_VERSION, - 'SERD', + ['SERD', 'SORD'], {'SRATOM_MAJOR_VERSION' : SRATOM_MAJOR_VERSION}) libflags = [ '-fvisibility=hidden' ] @@ -93,7 +100,7 @@ def build(bld): install_path = '${LIBDIR}', cflags = libflags + [ '-DSRATOM_SHARED', '-DSRATOM_INTERNAL' ]) - autowaf.use_lib(bld, obj, 'SERD') + autowaf.use_lib(bld, obj, 'SERD SORD') # Static library if bld.env['BUILD_STATIC']: @@ -107,7 +114,7 @@ def build(bld): vnum = SRATOM_LIB_VERSION, install_path = '${LIBDIR}', cflags = ['-DSRATOM_INTERNAL']) - autowaf.use_lib(bld, obj, 'SERD') + autowaf.use_lib(bld, obj, 'SERD SORD') if bld.env['BUILD_TESTS']: test_libs = libs @@ -125,7 +132,7 @@ def build(bld): target = 'sratom_profiled', install_path = '', cflags = test_cflags + ['-DSRATOM_INTERNAL']) - autowaf.use_lib(bld, obj, 'SERD') + autowaf.use_lib(bld, obj, 'SERD SORD') # Unit test program obj = bld(features = 'c cprogram', -- cgit v1.2.1