From f6e4bb2bf9fb001d1c4b0a26eba45da8445dfa6e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 23 Feb 2012 02:41:59 +0000 Subject: Seriatom => Sratom. git-svn-id: http://svn.drobilla.net/lad/trunk/sratom@3994 a436a847-0d15-0410-975c-d299462d15a1 --- seriatom.pc.in | 11 -- seriatom/seriatom.h | 106 ------------------- sratom.pc.in | 11 ++ sratom/seriatom.h | 120 ++++++++++++++++++++++ src/atom_to_rdf.c | 192 +++++++++++++++++++++++++--------- tests/seriatom_test.c | 277 -------------------------------------------------- tests/sratom_test.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 551 insertions(+), 443 deletions(-) delete mode 100644 seriatom.pc.in delete mode 100644 seriatom/seriatom.h create mode 100644 sratom.pc.in create mode 100644 sratom/seriatom.h delete mode 100644 tests/seriatom_test.c create mode 100644 tests/sratom_test.c diff --git a/seriatom.pc.in b/seriatom.pc.in deleted file mode 100644 index 1e3af45..0000000 --- a/seriatom.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@PREFIX@ -exec_prefix=@EXEC_PREFIX@ -libdir=@LIBDIR@ -includedir=@INCLUDEDIR@ - -Name: Seriatom -Version: @SERIATOM_VERSION@ -Description: LV2 Atom RDF serialisation library -Requires: serd-0 -Libs: -L${libdir} -l@LIB_SERIATOM@ -Cflags: -I${includedir}/seriatom-@SERIATOM_MAJOR_VERSION@ diff --git a/seriatom/seriatom.h b/seriatom/seriatom.h deleted file mode 100644 index 61bd46a..0000000 --- a/seriatom/seriatom.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright 2012 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file seriatom.h API for Seriatom, an LV2 Atom RDF serialisation library. -*/ - -#ifndef SERIATOM_SERIATOM_H -#define SERIATOM_SERIATOM_H - -#include - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" -#include "serd/serd.h" - -#ifdef SERIATOM_SHARED -# ifdef _WIN32 -# define SERIATOM_LIB_IMPORT __declspec(dllimport) -# define SERIATOM_LIB_EXPORT __declspec(dllexport) -# else -# define SERIATOM_LIB_IMPORT __attribute__((visibility("default"))) -# define SERIATOM_LIB_EXPORT __attribute__((visibility("default"))) -# endif -# ifdef SERIATOM_INTERNAL -# define SERIATOM_API SERIATOM_LIB_EXPORT -# else -# define SERIATOM_API SERIATOM_LIB_IMPORT -# endif -#else -# define SERIATOM_API -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @defgroup seriatom Seriatom - An LV2 Atom RDF serialisation library. - @{ -*/ - -/** - 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(Seriatom* seriatom, - const SerdNode* subject, - const SerdNode* predicate, - const LV2_Atom* atom, - uint32_t flags); - -/** - Serialise an Atom to a Turtle string. - The returned string must be free()'d by the caller. -*/ -SERIATOM_API -char* -atom_to_turtle(Seriatom* seriatom, - const SerdNode* subject, - const SerdNode* predicate, - const LV2_Atom* atom); - -/** - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* SERIATOM_SERIATOM_H */ diff --git a/sratom.pc.in b/sratom.pc.in new file mode 100644 index 0000000..1e3af45 --- /dev/null +++ b/sratom.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: Seriatom +Version: @SERIATOM_VERSION@ +Description: LV2 Atom RDF serialisation library +Requires: serd-0 +Libs: -L${libdir} -l@LIB_SERIATOM@ +Cflags: -I${includedir}/seriatom-@SERIATOM_MAJOR_VERSION@ diff --git a/sratom/seriatom.h b/sratom/seriatom.h new file mode 100644 index 0000000..1fe2547 --- /dev/null +++ b/sratom/seriatom.h @@ -0,0 +1,120 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file seriatom.h API for Seriatom, an LV2 Atom RDF serialisation library. +*/ + +#ifndef SERIATOM_SERIATOM_H +#define SERIATOM_SERIATOM_H + +#include + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "serd/serd.h" + +#ifdef SERIATOM_SHARED +# ifdef _WIN32 +# define SERIATOM_LIB_IMPORT __declspec(dllimport) +# define SERIATOM_LIB_EXPORT __declspec(dllexport) +# else +# define SERIATOM_LIB_IMPORT __attribute__((visibility("default"))) +# define SERIATOM_LIB_EXPORT __attribute__((visibility("default"))) +# endif +# ifdef SERIATOM_INTERNAL +# define SERIATOM_API SERIATOM_LIB_EXPORT +# else +# define SERIATOM_API SERIATOM_LIB_IMPORT +# endif +#else +# define SERIATOM_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @defgroup seriatom Seriatom + An LV2 Atom RDF serialisation library. + @{ +*/ + +/** + Atom serialiser. +*/ +typedef struct SeriatomImpl Seriatom; + +/** + Create a new Atom serialiser. +*/ +SERIATOM_API +Seriatom* +seriatom_new(LV2_URID_Map* map, + 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(Seriatom* seriatom, + const SerdNode* subject, + const SerdNode* predicate, + const LV2_Atom* atom, + uint32_t flags); + +/** + Serialise an Atom body to a SerdWriter. +*/ +SERIATOM_API +void +atom_body_to_rdf(Seriatom* seriatom, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type_urid, + uint32_t size, + const void* body, + uint32_t flags); + +/** + Serialise an Atom to a Turtle string. + The returned string must be free()'d by the caller. +*/ +SERIATOM_API +char* +atom_to_turtle(Seriatom* seriatom, + const SerdNode* subject, + const SerdNode* predicate, + const LV2_Atom* atom); + +/** + @} +*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SERIATOM_SERIATOM_H */ diff --git a/src/atom_to_rdf.c b/src/atom_to_rdf.c index f5d9858..e280244 100644 --- a/src/atom_to_rdf.c +++ b/src/atom_to_rdf.c @@ -18,28 +18,40 @@ #include #include +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" #include "lv2/lv2plug.in/ns/ext/atom/util.h" + #include "seriatom/seriatom.h" -#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_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)) struct SeriatomImpl { 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; }; SERIATOM_API Seriatom* -seriatom_new(LV2_URID_Unmap* unmap) +seriatom_new(LV2_URID_Map* map, + LV2_URID_Unmap* unmap) { Seriatom* seriatom = (Seriatom*)malloc(sizeof(Seriatom)); - seriatom->writer = NULL; - seriatom->unmap = unmap; - seriatom->next_id = 0; + seriatom->writer = NULL; + seriatom->map = map; + seriatom->unmap = unmap; + seriatom->atom_Event = map->map(map->handle, LV2_ATOM_URI "#Event"); + seriatom->midi_MidiEvent = map->map(map->handle, (const char*)NS_MIDI "MidiEvent"); + seriatom->next_id = 0; + lv2_atom_forge_init(&seriatom->forge, map); return seriatom; } @@ -78,7 +90,9 @@ list_append(Seriatom* seriatom, SerdNode* s, SerdNode* p, SerdNode* node, - LV2_Atom* atom) + uint32_t type, + uint32_t size, + void* body) { // Generate a list node gensym(node, 'l', seriatom->next_id); @@ -88,7 +102,7 @@ list_append(Seriatom* seriatom, // _: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); + atom_body_to_rdf(seriatom, node, p, type, size, body, SERD_LIST_CONT); // Set subject to node and predicate to rdf:rest for next time gensym(node, 'l', ++seriatom->next_id); @@ -125,22 +139,23 @@ start_object(Seriatom* seriatom, 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, + seriatom->writer, SERD_ANON_CONT, NULL, node, &p, &o, NULL, NULL); } } SERIATOM_API void -atom_to_rdf(Seriatom* seriatom, - const SerdNode* subject, - const SerdNode* predicate, - const LV2_Atom* atom, - uint32_t flags) +atom_body_to_rdf(Seriatom* seriatom, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type_urid, + uint32_t size, + const void* body, + uint32_t flags) { LV2_URID_Unmap* unmap = seriatom->unmap; - SerdWriter* writer = seriatom->writer; - const char* const type = unmap->unmap(unmap->handle, atom->type); + const char* const type = unmap->unmap(unmap->handle, type_urid); uint8_t idbuf[12] = "b0000000000"; SerdNode id = serd_node_from_string(SERD_BLANK, idbuf); uint8_t nodebuf[12] = "b0000000000"; @@ -149,14 +164,13 @@ atom_to_rdf(Seriatom* seriatom, SerdNode datatype = SERD_NODE_NULL; SerdNode language = SERD_NODE_NULL; bool new_node = false; - if (atom->type == 0 && atom->size == 0) { + if (type_urid == 0 && size == 0) { object = serd_node_from_string(SERD_BLANK, USTR("null")); - } else if (!strcmp(type, LV2_ATOM__String)) { - const uint8_t* str = USTR(LV2_ATOM_BODY(atom)); - object = serd_node_from_string(SERD_LITERAL, str); - } else if (!strcmp(type, LV2_ATOM__Literal)) { - LV2_Atom_Literal* lit = (LV2_Atom_Literal*)atom; - const uint8_t* str = USTR(LV2_ATOM_CONTENTS(LV2_Atom_Literal, lit)); + } else if (type_urid == seriatom->forge.String) { + object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body); + } else if (type_urid == seriatom->forge.Literal) { + LV2_Atom_Literal_Body* lit = (LV2_Atom_Literal_Body*)body; + const uint8_t* str = USTR(lit + 1); object = serd_node_from_string(SERD_LITERAL, str); if (lit->datatype) { datatype = serd_node_from_string( @@ -172,59 +186,122 @@ atom_to_rdf(Seriatom* seriatom, fprintf(stderr, "Unknown language URI <%s>\n", lang); } } - } else if (!strcmp(type, LV2_ATOM__URID)) { - const uint32_t id = *(const uint32_t*)LV2_ATOM_BODY(atom); + } else if (type_urid == seriatom->forge.URID) { + const uint32_t id = *(const uint32_t*)body; const uint8_t* str = USTR(unmap->unmap(unmap->handle, id)); object = serd_node_from_string(SERD_URI, str); - } else if (!strcmp(type, LV2_ATOM__Path)) { - const uint8_t* str = USTR(LV2_ATOM_BODY(atom)); + } else if (type_urid == seriatom->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)); - } else if (!strcmp(type, LV2_ATOM__URI)) { - const uint8_t* str = USTR(LV2_ATOM_BODY(atom)); + } else if (type_urid == seriatom->forge.URI) { + const uint8_t* str = USTR(body); object = serd_node_from_string(SERD_URI, str); - } else if (!strcmp(type, LV2_ATOM__Int32)) { + } else if (type_urid == seriatom->forge.Int32) { new_node = true; - object = serd_node_new_integer(*(int32_t*)LV2_ATOM_BODY(atom)); + object = serd_node_new_integer(*(int32_t*)body); datatype = serd_node_from_string(SERD_URI, NS_XSD "int"); - } else if (!strcmp(type, LV2_ATOM__Int64)) { + } else if (type_urid == seriatom->forge.Int64) { new_node = true; - object = serd_node_new_integer(*(int64_t*)LV2_ATOM_BODY(atom)); + object = serd_node_new_integer(*(int64_t*)body); datatype = serd_node_from_string(SERD_URI, NS_XSD "long"); - } else if (!strcmp(type, LV2_ATOM__Float)) { + } else if (type_urid == seriatom->forge.Float) { new_node = true; - object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 8); + object = serd_node_new_decimal(*(float*)body, 8); datatype = serd_node_from_string(SERD_URI, NS_XSD "float"); - } else if (!strcmp(type, LV2_ATOM__Double)) { + } else if (type_urid == seriatom->forge.Double) { new_node = true; - object = serd_node_new_decimal(*(double*)LV2_ATOM_BODY(atom), 16); + object = serd_node_new_decimal(*(double*)body, 16); 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); + } else if (type_urid == seriatom->forge.Bool) { + const int32_t val = *(const int32_t*)body; 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__Tuple)) { + } else if (type_urid == seriatom->midi_MidiEvent) { + new_node = true; + datatype = serd_node_from_string(SERD_URI, NS_MIDI "MidiEvent"); + uint8_t* str = calloc(size * 2, 1); + for (uint32_t i = 0; i < size; ++i) { + sprintf((char*)str + (2 * i), "%02X", + (unsigned)(uint8_t)*((uint8_t*)body + i)); + } + object = serd_node_from_string(SERD_LITERAL, USTR(str)); + } else if (type_urid == seriatom->atom_Event) { + const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body; + gensym(&id, 'e', seriatom->next_id++); + start_object(seriatom, 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); + datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal"); + serd_writer_write_statement(seriatom->writer, SERD_ANON_CONT, NULL, + &id, &p, &time, + &datatype, &language); + serd_node_free(&time); + + p = serd_node_from_string(SERD_URI, NS_RDF "value"); + atom_body_to_rdf(seriatom, &id, &p, + ev->body.type, ev->body.size, + LV2_ATOM_BODY(&ev->body), + SERD_ANON_CONT); + serd_writer_end_anon(seriatom->writer, &id); + } else if (type_urid == seriatom->forge.Tuple) { gensym(&id, 't', seriatom->next_id++); start_object(seriatom, flags, subject, predicate, &id, type); SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); flags |= SERD_LIST_O_BEGIN; - LV2_TUPLE_FOREACH((LV2_Atom_Tuple*)atom, i) { - list_append(seriatom, &flags, &id, &p, &node, i); + LV2_TUPLE_BODY_FOREACH(body, size, i) { + list_append(seriatom, &flags, &id, &p, &node, + i->type, i->size, LV2_ATOM_BODY(i)); + } + list_end(seriatom->writer, unmap, &flags, &id, &p); + serd_writer_end_anon(seriatom->writer, &id); + } else if (type_urid == seriatom->forge.Vector) { + const LV2_Atom_Vector_Body* vec = (const LV2_Atom_Vector_Body*)body; + gensym(&id, 'v', seriatom->next_id++); + start_object(seriatom, 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; + flags |= SERD_LIST_O_BEGIN; + for (char* i = (char*)(vec + 1); + i < (char*)vec + size; + i += elem_size) { + list_append(seriatom, &flags, &id, &p, &node, + vec->elem_type, elem_size, i); } - list_end(writer, unmap, &flags, &id, &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); + list_end(seriatom->writer, unmap, &flags, &id, &p); + serd_writer_end_anon(seriatom->writer, &id); + } else if (type_urid == seriatom->forge.Blank) { + const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body; + 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) { + 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)); - atom_to_rdf(seriatom, &id, &pred, &prop->value, flags|SERD_ANON_CONT); + atom_body_to_rdf(seriatom, &id, &pred, + prop->value.type, prop->value.size, + LV2_ATOM_BODY(&prop->value), + flags|SERD_ANON_CONT); + } + serd_writer_end_anon(seriatom->writer, &id); + } else if (type_urid == seriatom->forge.Sequence) { + const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body; + gensym(&id, 'v', seriatom->next_id++); + start_object(seriatom, 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(seriatom, &flags, &id, &p, &node, + seriatom->atom_Event, + sizeof(LV2_Atom_Event) + ev->body.size, + ev); } + list_end(seriatom->writer, unmap, &flags, &id, &p); serd_writer_end_anon(seriatom->writer, &id); } else { object = serd_node_from_string(SERD_LITERAL, USTR("(unknown)")); @@ -241,6 +318,19 @@ atom_to_rdf(Seriatom* seriatom, } } +SERIATOM_API +void +atom_to_rdf(Seriatom* seriatom, + const SerdNode* subject, + const SerdNode* predicate, + const LV2_Atom* atom, + uint32_t flags) +{ + atom_body_to_rdf(seriatom, subject, predicate, + atom->type, atom->size, LV2_ATOM_BODY(atom), + flags); +} + SERIATOM_API char* atom_to_turtle(Seriatom* seriatom, @@ -252,10 +342,13 @@ atom_to_turtle(Seriatom* seriatom, SerdEnv* env = serd_env_new(NULL); String str = { NULL, 0 }; + serd_env_set_prefix_from_strings(env, USTR("midi"), NS_MIDI); 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); + serd_env_set_prefix_from_strings(env, USTR("eg"), + USTR("http://example.org/")); seriatom->writer = serd_writer_new( SERD_TURTLE, @@ -268,5 +361,6 @@ atom_to_turtle(Seriatom* seriatom, serd_writer_free(seriatom->writer); serd_env_free(env); + free(str.buf); return str.buf; } diff --git a/tests/seriatom_test.c b/tests/seriatom_test.c deleted file mode 100644 index 67da65d..0000000 --- a/tests/seriatom_test.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - Copyright 2012 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include -#include -#include - -#include "lv2/lv2plug.in/ns/ext/atom/forge.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 USTR(s) ((const uint8_t*)(s)) - -char** uris = NULL; -size_t n_uris = 0; - -char* -copy_string(const char* str) -{ - const size_t len = strlen(str); - char* dup = (char*)malloc(len + 1); - memcpy(dup, str, len + 1); - return dup; -} - -LV2_URID -urid_map(LV2_URID_Map_Handle handle, const char* uri) -{ - for (size_t i = 0; i < n_uris; ++i) { - if (!strcmp(uris[i], uri)) { - return i + 1; - } - } - - uris = (char**)realloc(uris, ++n_uris * sizeof(char*)); - uris[n_uris - 1] = copy_string(uri); - return n_uris; -} - -const char* -urid_unmap(LV2_URID_Unmap_Handle handle, - LV2_URID urid) -{ - if (urid <= n_uris) { - return uris[urid - 1]; - } - return NULL; -} - -int -test_fail(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - fprintf(stderr, "error: "); - vfprintf(stderr, fmt, args); - va_end(args); - return 1; -} - -int -main() -{ - LV2_URID_Map map = { NULL, urid_map }; - LV2_URID_Unmap unmap = { NULL, urid_unmap }; - 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"); - LV2_URID eg_three = urid_map(NULL, "http://example.org/three"); - LV2_URID eg_four = urid_map(NULL, "http://example.org/four"); - LV2_URID eg_true = urid_map(NULL, "http://example.org/true"); - LV2_URID eg_false = urid_map(NULL, "http://example.org/false"); - LV2_URID eg_path = urid_map(NULL, "http://example.org/path"); - LV2_URID eg_uri = urid_map(NULL, "http://example.org/uri"); - LV2_URID eg_urid = urid_map(NULL, "http://example.org/urid"); - LV2_URID eg_string = urid_map(NULL, "http://example.org/string"); - LV2_URID eg_langlit = urid_map(NULL, "http://example.org/langlit"); - LV2_URID eg_typelit = urid_map(NULL, "http://example.org/typelit"); - LV2_URID eg_blank = urid_map(NULL, "http://example.org/blank"); - LV2_URID eg_tuple = urid_map(NULL, "http://example.org/tuple"); - LV2_URID eg_vector = urid_map(NULL, "http://example.org/vector"); - LV2_URID eg_seq = urid_map(NULL, "http://example.org/seq"); - - uint8_t buf[1024]; - 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); - - // 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->value != 1) { - return test_fail("%d != 1\n", one->value); - } - - // 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->value != 2) { - return test_fail("%ld != 2\n", two->value); - } - - // 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->value != 3) { - return test_fail("%f != 3\n", three->value); - } - - // 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->value != 4) { - return test_fail("%ld != 4\n", four->value); - } - - // 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->value != 1) { - return test_fail("%ld != 1 (true)\n", t->value); - } - - // 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->value != 0) { - return test_fail("%ld != 0 (false)\n", f->value); - } - - // 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); - } - - // 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); - } - - // 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->id != eg_value) { - return test_fail("%u != %u\n", urid->id, 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); - } - - // eg_langlit = (Literal)"bonjour"@fr - lv2_atom_forge_property_head(&forge, eg_langlit, 0); - LV2_Atom_Literal* langlit = 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( - &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); - LV2_Atom_Forge_Frame blank_frame; - lv2_atom_forge_blank(&forge, &blank_frame, 2, eg_Object); - lv2_atom_forge_pop(&forge, &blank_frame); - - // 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_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"); - } - - // eg_seq = (Sequence)1, 2 - lv2_atom_forge_property_head(&forge, eg_seq, 0); - LV2_Atom_Forge_Frame seq_frame; - lv2_atom_forge_sequence_head(&forge, &seq_frame, 0); - lv2_atom_forge_audio_time(&forge, 0, 0); - lv2_atom_forge_int32(&forge, 1); - lv2_atom_forge_audio_time(&forge, 1, 0); - lv2_atom_forge_int32(&forge, 2); - 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", atom_to_turtle(seriatom, &s, &p, obj)); - - printf("All tests passed.\n"); - seriatom_free(seriatom); - return 0; -} diff --git a/tests/sratom_test.c b/tests/sratom_test.c new file mode 100644 index 0000000..67da65d --- /dev/null +++ b/tests/sratom_test.c @@ -0,0 +1,277 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/forge.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 USTR(s) ((const uint8_t*)(s)) + +char** uris = NULL; +size_t n_uris = 0; + +char* +copy_string(const char* str) +{ + const size_t len = strlen(str); + char* dup = (char*)malloc(len + 1); + memcpy(dup, str, len + 1); + return dup; +} + +LV2_URID +urid_map(LV2_URID_Map_Handle handle, const char* uri) +{ + for (size_t i = 0; i < n_uris; ++i) { + if (!strcmp(uris[i], uri)) { + return i + 1; + } + } + + uris = (char**)realloc(uris, ++n_uris * sizeof(char*)); + uris[n_uris - 1] = copy_string(uri); + return n_uris; +} + +const char* +urid_unmap(LV2_URID_Unmap_Handle handle, + LV2_URID urid) +{ + if (urid <= n_uris) { + return uris[urid - 1]; + } + return NULL; +} + +int +test_fail(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, args); + va_end(args); + return 1; +} + +int +main() +{ + LV2_URID_Map map = { NULL, urid_map }; + LV2_URID_Unmap unmap = { NULL, urid_unmap }; + 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"); + LV2_URID eg_three = urid_map(NULL, "http://example.org/three"); + LV2_URID eg_four = urid_map(NULL, "http://example.org/four"); + LV2_URID eg_true = urid_map(NULL, "http://example.org/true"); + LV2_URID eg_false = urid_map(NULL, "http://example.org/false"); + LV2_URID eg_path = urid_map(NULL, "http://example.org/path"); + LV2_URID eg_uri = urid_map(NULL, "http://example.org/uri"); + LV2_URID eg_urid = urid_map(NULL, "http://example.org/urid"); + LV2_URID eg_string = urid_map(NULL, "http://example.org/string"); + LV2_URID eg_langlit = urid_map(NULL, "http://example.org/langlit"); + LV2_URID eg_typelit = urid_map(NULL, "http://example.org/typelit"); + LV2_URID eg_blank = urid_map(NULL, "http://example.org/blank"); + LV2_URID eg_tuple = urid_map(NULL, "http://example.org/tuple"); + LV2_URID eg_vector = urid_map(NULL, "http://example.org/vector"); + LV2_URID eg_seq = urid_map(NULL, "http://example.org/seq"); + + uint8_t buf[1024]; + 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); + + // 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->value != 1) { + return test_fail("%d != 1\n", one->value); + } + + // 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->value != 2) { + return test_fail("%ld != 2\n", two->value); + } + + // 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->value != 3) { + return test_fail("%f != 3\n", three->value); + } + + // 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->value != 4) { + return test_fail("%ld != 4\n", four->value); + } + + // 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->value != 1) { + return test_fail("%ld != 1 (true)\n", t->value); + } + + // 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->value != 0) { + return test_fail("%ld != 0 (false)\n", f->value); + } + + // 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); + } + + // 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); + } + + // 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->id != eg_value) { + return test_fail("%u != %u\n", urid->id, 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); + } + + // eg_langlit = (Literal)"bonjour"@fr + lv2_atom_forge_property_head(&forge, eg_langlit, 0); + LV2_Atom_Literal* langlit = 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( + &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); + LV2_Atom_Forge_Frame blank_frame; + lv2_atom_forge_blank(&forge, &blank_frame, 2, eg_Object); + lv2_atom_forge_pop(&forge, &blank_frame); + + // 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_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"); + } + + // eg_seq = (Sequence)1, 2 + lv2_atom_forge_property_head(&forge, eg_seq, 0); + LV2_Atom_Forge_Frame seq_frame; + lv2_atom_forge_sequence_head(&forge, &seq_frame, 0); + lv2_atom_forge_audio_time(&forge, 0, 0); + lv2_atom_forge_int32(&forge, 1); + lv2_atom_forge_audio_time(&forge, 1, 0); + lv2_atom_forge_int32(&forge, 2); + 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", atom_to_turtle(seriatom, &s, &p, obj)); + + printf("All tests passed.\n"); + seriatom_free(seriatom); + return 0; +} -- cgit v1.2.1