aboutsummaryrefslogtreecommitdiffstats
path: root/src/writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/writer.c')
-rw-r--r--src/writer.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/src/writer.c b/src/writer.c
index 4e4ee2eb..a9cdf6ac 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -31,7 +31,7 @@ typedef struct {
} WriteContext;
static const WriteContext WRITE_CONTEXT_NULL = {
- { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}
+ { 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}
};
struct SerdWriterImpl {
@@ -47,9 +47,9 @@ struct SerdWriterImpl {
};
typedef enum {
- WRITE_NORMAL,
WRITE_URI,
- WRITE_STRING
+ WRITE_STRING,
+ WRITE_LONG_STRING
} TextContext;
static inline WriteContext*
@@ -67,23 +67,29 @@ write_text(SerdWriter* writer, TextContext ctx,
char escape[11] = { 0, 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 '\\': 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 (terminator == '"') {
- writer->sink("\\\"", 2, writer->stream);
- continue;
- } // else fall-through
- default: break;
- }
+ if (ctx == WRITE_LONG_STRING) {
+ if (in == '\\') {
+ writer->sink("\\\\", 2, writer->stream); continue;
+ }
+ } else {
+ switch (in) {
+ 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 (terminator == '"') {
+ writer->sink("\\\"", 2, writer->stream);
+ continue;
+ } // else fall-through
+ default: break;
+ }
- if (in == terminator) {
- snprintf(escape, 7, "\\u%04X", terminator);
- writer->sink(escape, 6, writer->stream);
- continue;
+ if (in == terminator) {
+ snprintf(escape, 7, "\\u%04X", terminator);
+ writer->sink(escape, 6, writer->stream);
+ continue;
+ }
}
uint32_t c = 0;
@@ -109,7 +115,8 @@ write_text(SerdWriter* writer, TextContext ctx,
return false;
}
- if (ctx == WRITE_STRING && !(writer->style & SERD_STYLE_ASCII)) {
+ if ((ctx == WRITE_STRING || ctx == WRITE_LONG_STRING)
+ && !(writer->style & SERD_STYLE_ASCII)) {
// Write UTF-8 character directly to UTF-8 output
// TODO: Scan to next escape and write entire range at once
writer->sink(utf8 + i - 1, size, writer->stream);
@@ -228,9 +235,17 @@ write_node(SerdWriter* writer,
break;
}
}
- writer->sink("\"", 1, writer->stream);
- write_text(writer, WRITE_STRING, node->buf, node->n_bytes - 1, '"');
- writer->sink("\"", 1, writer->stream);
+ if (writer->syntax != SERD_NTRIPLES
+ && ((node->flags & SERD_HAS_NEWLINE)
+ || (node->flags & SERD_HAS_QUOTE))) {
+ writer->sink("\"\"\"", 3, writer->stream);
+ write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes - 1, '\0');
+ writer->sink("\"\"\"", 3, writer->stream);
+ } else {
+ writer->sink("\"", 1, writer->stream);
+ write_text(writer, WRITE_STRING, node->buf, node->n_bytes - 1, '"');
+ writer->sink("\"", 1, writer->stream);
+ }
if (lang && lang->buf) {
writer->sink("@", 1, writer->stream);
writer->sink(lang->buf, lang->n_bytes - 1, writer->stream);