summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-03-01 06:39:57 +0000
committerDavid Robillard <d@drobilla.net>2012-03-01 06:39:57 +0000
commit6408ee7d93ed041a053627e3506c444e215654d4 (patch)
treeda8888efd3d243018e9d56e09a60ef0aecfb5c01
parent6e4c4ee8a1fccebedf48b750151a258a559fc50b (diff)
downloadsratom-6408ee7d93ed041a053627e3506c444e215654d4.tar.gz
sratom-6408ee7d93ed041a053627e3506c444e215654d4.tar.bz2
sratom-6408ee7d93ed041a053627e3506c444e215654d4.zip
Implement Turtle reading (except for atom:Vector).
git-svn-id: http://svn.drobilla.net/lad/trunk/sratom@4006 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--sratom.pc.in10
-rw-r--r--sratom/sratom.h31
-rw-r--r--src/sratom.c348
-rw-r--r--tests/sratom_test.c136
-rw-r--r--wscript15
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 <stdint.h>
#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,18 +77,32 @@ 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,11 +111,22 @@ 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 <http://example.org/Object> ]
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<Int32>)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',