Browse Source

Make writer write to any sink passed in by the user.

git-svn-id: http://svn.drobilla.net/serd/trunk@20 490d8e77-9747-427b-9fa3-0b8f29cee8a0
zrythm_meson
David Robillard 12 years ago
parent
commit
235eef1849
  1. 7
      serd/serd.h
  2. 15
      src/serdi.c
  3. 2
      src/uri.c
  4. 96
      src/write.c

7
serd/serd.h

@ -119,7 +119,7 @@ bool @@ -119,7 +119,7 @@ bool
serd_uri_write(const SerdURI* uri, FILE* file);
/** Sink function for raw string output. */
typedef size_t (*SerdSink)(const uint8_t* buf, size_t len, void* stream);
typedef size_t (*SerdSink)(const void* buf, size_t len, void* stream);
/** Serialise @a uri with a series of calls to @a sink. */
SERD_API
@ -249,8 +249,9 @@ SERD_API @@ -249,8 +249,9 @@ SERD_API
SerdWriter
serd_writer_new(SerdSyntax syntax,
SerdNamespaces ns,
FILE* file,
const SerdURI* base_uri);
const SerdURI* base_uri,
SerdSink sink,
void* stream);
/** Free @a writer. */
SERD_API

15
src/serdi.c

@ -123,6 +123,13 @@ print_usage(const char* name, bool error) @@ -123,6 +123,13 @@ print_usage(const char* name, bool error)
return error ? 1 : 0;
}
static size_t
file_sink(const void* buf, size_t len, void* stream)
{
FILE* file = (FILE*)stream;
return fwrite(buf, 1, len, file);
}
int
main(int argc, char** argv)
{
@ -168,10 +175,10 @@ main(int argc, char** argv) @@ -168,10 +175,10 @@ main(int argc, char** argv)
}
SerdNamespaces ns = serd_namespaces_new();
State state = { serd_writer_new(SERD_NTRIPLES, ns, out_fd, &base_uri),
ns,
base_uri_str,
base_uri };
State state = {
serd_writer_new(SERD_NTRIPLES, ns, &base_uri, file_sink, out_fd),
ns, base_uri_str, base_uri
};
SerdReader reader = serd_reader_new(
SERD_TURTLE, &state, event_base, event_prefix, event_statement);

2
src/uri.c

@ -366,7 +366,7 @@ serd_uri_string_length(const SerdURI* uri) @@ -366,7 +366,7 @@ serd_uri_string_length(const SerdURI* uri)
}
static size_t
string_sink(const uint8_t* buf, size_t len, void* stream)
string_sink(const void* buf, size_t len, void* stream)
{
uint8_t** ptr = (uint8_t**)stream;
memcpy(*ptr, buf, len);

96
src/write.c

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "serd/serd.h"
@ -23,39 +24,29 @@ @@ -23,39 +24,29 @@
struct SerdWriterImpl {
SerdSyntax syntax;
SerdNamespaces ns;
FILE* fd;
SerdURI base_uri;
SerdSink sink;
void* stream;
};
static size_t
file_sink(const uint8_t* buf, size_t len, void* stream)
{
FILE* file = (FILE*)stream;
return fwrite(buf, 1, len, file);
}
static inline bool
serd_write_uri(FILE* file, const SerdURI* uri)
{
return serd_uri_serialise(uri, file_sink, file);
}
static bool
serd_write_ascii(const uint8_t* utf8, size_t n_bytes, FILE* out_fd, const uint8_t esc)
serd_write_ascii(SerdWriter writer, const uint8_t* utf8, size_t n_bytes, const uint8_t esc)
{
char escape[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (size_t i = 0; i < n_bytes;) {
uint8_t in = utf8[i++];
switch (in) {
case '\\': fwrite("\\\\", 1, 2, out_fd); continue;
case '\n': fwrite("\\n", 1, 2, out_fd); continue;
case '\r': fwrite("\\r", 1, 2, out_fd); continue;
case '\t': fwrite("\\t", 1, 2, out_fd); continue;
case '"': if (esc == '"') { fwrite("\\\"", 1, 2, out_fd); continue; }
case '\\': writer->sink("\\\\", 2, writer->stream); continue;
case '\n': writer->sink("\\n", 2, writer->stream); continue;
case '\r': writer->sink("\\r", 2, writer->stream); continue;
case '\t': writer->sink("\\t", 2, writer->stream); continue;
case '"': if (esc == '"') { writer->sink("\\\"", 2, writer->stream); continue; }
default: break;
}
if (in == esc) {
fprintf(out_fd, "\\u%04X", esc);
sprintf(escape, "\\u%04X", esc);
writer->sink(escape, 6, writer->stream);
continue;
}
@ -65,7 +56,7 @@ serd_write_ascii(const uint8_t* utf8, size_t n_bytes, FILE* out_fd, const uint8_ @@ -65,7 +56,7 @@ serd_write_ascii(const uint8_t* utf8, size_t n_bytes, FILE* out_fd, const uint8_
size = 1;
c = in & 0x7F;
if ((in >= 0x20) && (in <= 0x7E)) { // Printable ASCII
fwrite(&in, 1, 1, out_fd);
writer->sink(&in, 1, writer->stream);
continue;
}
} else if ((in & 0xE0) == 0xC0) { // Starts with `110'
@ -104,23 +95,23 @@ serd_write_ascii(const uint8_t* utf8, size_t n_bytes, FILE* out_fd, const uint8_ @@ -104,23 +95,23 @@ serd_write_ascii(const uint8_t* utf8, size_t n_bytes, FILE* out_fd, const uint8_
}
if (c < 0xFFFF) {
fprintf(out_fd, "\\u%04X", c);
sprintf(escape, "\\u%04X", c);
writer->sink(escape, 6, writer->stream);
} else {
fprintf(out_fd, "\\U%08X", c);
sprintf(escape, "\\U%08X", c);
writer->sink(escape, 10, writer->stream);
}
}
return true;
}
SERD_API
bool
static bool
serd_write_node(SerdWriter writer,
SerdNodeType type,
const SerdString* str,
const SerdString* datatype,
const SerdString* lang)
{
FILE* const fd = writer->fd;
const SerdURI* base_uri = &writer->base_uri;
SerdNamespaces ns = writer->ns;
@ -128,18 +119,18 @@ serd_write_node(SerdWriter writer, @@ -128,18 +119,18 @@ serd_write_node(SerdWriter writer,
SerdChunk uri_suffix;
switch (type) {
case BLANK:
fwrite("_:", 1, 2, fd);
fwrite(str->buf, 1, str->n_bytes - 1, fd);
writer->sink("_:", 2, writer->stream);
writer->sink(str->buf, str->n_bytes - 1, writer->stream);
break;
case QNAME:
if (!serd_namespaces_expand(ns, str, &uri_prefix, &uri_suffix)) {
fprintf(stderr, "error: undefined namespace prefix `%s'\n", str->buf);
return false;
}
fwrite("<", 1, 1, fd);
serd_write_ascii(uri_prefix.buf, uri_prefix.len, fd, '>');
serd_write_ascii(uri_suffix.buf, uri_suffix.len, fd, '>');
fwrite(">", 1, 1, fd);
writer->sink("<", 1, writer->stream);
serd_write_ascii(writer, uri_prefix.buf, uri_prefix.len, '>');
serd_write_ascii(writer, uri_suffix.buf, uri_suffix.len, '>');
writer->sink(">", 1, writer->stream);
break;
case URI:
if (!serd_uri_string_has_scheme(str->buf)) {
@ -147,28 +138,28 @@ serd_write_node(SerdWriter writer, @@ -147,28 +138,28 @@ serd_write_node(SerdWriter writer,
if (serd_uri_parse(str->buf, &uri)) {
SerdURI abs_uri;
if (serd_uri_resolve(&uri, base_uri, &abs_uri)) {
fwrite("<", 1, 1, fd);
serd_write_uri(fd, &abs_uri);
fwrite(">", 1, 1, fd);
writer->sink("<", 1, writer->stream);
serd_uri_serialise(&abs_uri, writer->sink, writer->stream);
writer->sink(">", 1, writer->stream);
return true;
}
}
} else {
fwrite("<", 1, 1, fd);
serd_write_ascii(str->buf, str->n_bytes - 1, fd, '>');
fwrite(">", 1, 1, fd);
writer->sink("<", 1, writer->stream);
serd_write_ascii(writer, str->buf, str->n_bytes - 1, '>');
writer->sink(">", 1, writer->stream);
return true;
}
return false;
case LITERAL:
fwrite("\"", 1, 1, fd);
serd_write_ascii(str->buf, str->n_bytes - 1, fd, '"');
fwrite("\"", 1, 1, fd);
writer->sink("\"", 1, writer->stream);
serd_write_ascii(writer, str->buf, str->n_bytes - 1, '"');
writer->sink("\"", 1, writer->stream);
if (lang) {
fwrite("@", 1, 1, fd);
fwrite(lang->buf, 1, lang->n_bytes - 1, fd);
writer->sink("@", 1, writer->stream);
writer->sink(lang->buf, lang->n_bytes - 1, writer->stream);
} else if (datatype) {
fwrite("^^", 1, 2, fd);
writer->sink("^^", 2, writer->stream);
serd_write_node(writer, URI, datatype, NULL, NULL);
}
break;
@ -189,13 +180,12 @@ serd_writer_write_statement(SerdWriter writer, @@ -189,13 +180,12 @@ serd_writer_write_statement(SerdWriter writer,
const SerdString* object_datatype,
const SerdString* object_lang)
{
FILE* const fd = writer->fd;
serd_write_node(writer, subject_type, subject, NULL, NULL);
fwrite(" ", 1, 1, fd);
writer->sink(" ", 1, writer->stream);
serd_write_node(writer, predicate_type, predicate, NULL, NULL);
fwrite(" ", 1, 1, fd);
writer->sink(" ", 1, writer->stream);
serd_write_node(writer, object_type, object, object_datatype, object_lang);
fwrite(" .\n", 1, 3, fd);
writer->sink(" .\n", 3, writer->stream);
return true;
}
@ -203,14 +193,16 @@ SERD_API @@ -203,14 +193,16 @@ SERD_API
SerdWriter
serd_writer_new(SerdSyntax syntax,
SerdNamespaces ns,
FILE* file,
const SerdURI* base_uri)
const SerdURI* base_uri,
SerdSink sink,
void* stream)
{
SerdWriter writer = malloc(sizeof(struct SerdWriterImpl));
writer->syntax = syntax;
writer->ns = ns;
writer->fd = file;
writer->base_uri = *base_uri;
writer->sink = sink;
writer->stream = stream;
return writer;
}

Loading…
Cancel
Save