diff options
Diffstat (limited to 'src/write.c')
-rw-r--r-- | src/write.c | 96 |
1 files changed, 44 insertions, 52 deletions
diff --git a/src/write.c b/src/write.c index e4d524c6..ef10594b 100644 --- a/src/write.c +++ b/src/write.c @@ -16,6 +16,7 @@ */ #include <assert.h> +#include <stdio.h> #include <stdlib.h> #include "serd/serd.h" @@ -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_ 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_ } 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, 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, 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, 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 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; } |