diff options
-rw-r--r-- | src/uri.c | 51 | ||||
-rw-r--r-- | src/writer.c | 9 |
2 files changed, 37 insertions, 23 deletions
@@ -269,27 +269,40 @@ serd_uri_serialise(const SerdURI* uri, SerdSink sink, void* stream) /* Merge paths, removing dot components. See http://tools.ietf.org/html/rfc3986#section-5.2.3 */ - const uint8_t* uri_first = uri->path.buf; - const uint8_t* uri_end = uri_first; + const uint8_t* begin = uri->path.buf; + const uint8_t* end = begin; size_t up = 1; - if (uri_first) { + if (begin) { // Count and skip leading dot components - uri_end = uri->path.buf + uri->path.len; - while (uri_first < uri_end) { - if (!memcmp((const char*)uri_first, "./", 2)) { - uri_first += 2; - } else if (!memcmp((const char*)uri_first, "../", 3)) { - ++up; - uri_first += 3; - } else if (!memcmp((const char*)uri_first, "..", 2)) { - ++up; - uri_first += 2; - } else if (!memcmp((const char*)uri_first, ".", 1)) { - ++uri_first; - } else if (!memcmp((const char*)uri_first, "//", 1)) { - ++uri_first; - } else { + end = uri->path.buf + uri->path.len; + for (bool done = false; !done && (begin < end);) { + switch (begin[0]) { + case '.': + switch (begin[1]) { + case '/': + begin += 2; // Chop leading "./" + break; + case '.': + ++up; + switch (begin[2]) { + case '/': + begin += 3; // Chop lading "../" + break; + default: + begin += 2; // Chop leading ".." + } + break; + default: + ++begin; // Chop leading "." + } break; + case '/': + if (begin[1] == '/') { + ++begin; // Replace leading "//" with "/" + break; + } // else fall through + default: + done = true; // Finished chopping dot components } } @@ -312,7 +325,7 @@ serd_uri_serialise(const SerdURI* uri, SerdSink sink, void* stream) } // Write URI suffix - WRITE(uri_first, uri_end - uri_first); + WRITE(begin, end - begin); } } } else { diff --git a/src/writer.c b/src/writer.c index eca334a8..85d20deb 100644 --- a/src/writer.c +++ b/src/writer.c @@ -64,9 +64,9 @@ write_text(SerdWriter writer, TextContext ctx, 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 '\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); @@ -86,7 +86,7 @@ write_text(SerdWriter writer, TextContext ctx, if ((in & 0x80) == 0) { // Starts with `0' size = 1; c = in & 0x7F; - if ((in >= 0x20) && (in <= 0x7E)) { // Printable ASCII + if (in_range((in >= 0x20) && (in <= 0x7E)) { // Printable ASCII writer->sink(&in, 1, writer->stream); continue; } @@ -112,6 +112,7 @@ write_text(SerdWriter writer, TextContext ctx, if (ctx == WRITE_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); i += size - 1; continue; |