aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-01-23 20:18:20 +0000
committerDavid Robillard <d@drobilla.net>2011-01-23 20:18:20 +0000
commit0993d312cb18131de8aa5a73eda65305f8f7899b (patch)
treeb3f15437587d5e4414318bda832a3f37b81c33f4
parent2c45a0e0d3e89946726c76f0e68b12048fb48785 (diff)
downloadserd-0993d312cb18131de8aa5a73eda65305f8f7899b.tar.gz
serd-0993d312cb18131de8aa5a73eda65305f8f7899b.tar.bz2
serd-0993d312cb18131de8aa5a73eda65305f8f7899b.zip
Faster serd_uri_serialise.
git-svn-id: http://svn.drobilla.net/serd/trunk@50 490d8e77-9747-427b-9fa3-0b8f29cee8a0
-rw-r--r--src/uri.c51
-rw-r--r--src/writer.c9
2 files changed, 37 insertions, 23 deletions
diff --git a/src/uri.c b/src/uri.c
index 5b2e4423..6fb6d42e 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -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;