diff options
author | David Robillard <d@drobilla.net> | 2012-03-08 15:57:20 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2012-03-08 15:57:20 +0000 |
commit | f4365012b555699b916dbeec4d81425bf663579c (patch) | |
tree | 27807b4430269cdb279d32e9f734f119b8bb7191 /src/node.c | |
parent | 7b022006c47586dc00ed8bca85fcb0bdf5f9465d (diff) | |
download | serd-f4365012b555699b916dbeec4d81425bf663579c.tar.gz serd-f4365012b555699b916dbeec4d81425bf663579c.tar.bz2 serd-f4365012b555699b916dbeec4d81425bf663579c.zip |
Add serd_writer_get_env().
Add serd_node_new_uri_from_path() and serd_file_uri_parse() and implement
proper URI to/from path hex escaping, etc.
Add serd_uri_serialise_relative() for making URIs relative to a base where
possible (by chopping a common prefix and adding dot segments).
Make URIs serialised by the writer properly escape characters.
git-svn-id: http://svn.drobilla.net/serd/trunk@330 490d8e77-9747-427b-9fa3-0b8f29cee8a0
Diffstat (limited to 'src/node.c')
-rw-r--r-- | src/node.c | 62 |
1 files changed, 62 insertions, 0 deletions
@@ -112,6 +112,68 @@ serd_node_new_uri_from_string(const uint8_t* str, return serd_node_new_uri(&uri, base, out); // Resolve/Serialise } +static inline bool +is_uri_path_char(const uint8_t c) +{ + if (is_alpha(c) || is_digit(c)) { + return true; + } + switch (c) { + case '-': case '.': case '_': case '~': // unreserved + case ':': case '@': // pchar + case '/': // separator + // sub-delims + case '!': case '$': case '&': case '\'': case '(': case ')': + case '*': case '+': case ',': case ';': case '=': + return true; + default: + return false; + } +} + +SERD_API +SerdNode +serd_node_new_uri_from_path(const uint8_t* path, + const uint8_t* hostname, + SerdURI* out) +{ + const size_t path_len = strlen((const char*)path); + const size_t hostname_len = hostname ? strlen((const char*)hostname) : 0; + const bool evil = is_windows_path(path); + size_t uri_len = 0; + uint8_t* uri = NULL; + + if (path[0] == '/' || is_windows_path(path)) { + uri_len = strlen("file://") + hostname_len + evil; + uri = (uint8_t*)malloc(uri_len + 1); + snprintf((char*)uri, uri_len + 1, "file://%s%s", + hostname ? (const char*)hostname : "", + evil ? "/" : ""); + } + + SerdChunk chunk = { uri, uri_len }; + for (size_t i = 0; i < path_len; ++i) { + if (evil && path[i] == '\\') { + serd_chunk_sink("/", 1, &chunk); + } else if (path[i] == '%') { + serd_chunk_sink("%%", 2, &chunk); + } else if (is_uri_path_char(path[i])) { + serd_chunk_sink(path + i, 1, &chunk); + } else { + char escape[4] = { '%', 0, 0, 0 }; + snprintf(escape + 1, sizeof(escape) - 1, "%X", path[i]); + serd_chunk_sink(escape, 3, &chunk); + } + } + serd_chunk_sink_finish(&chunk); + + if (out) { + serd_uri_parse(chunk.buf, out); + } + + return serd_node_from_string(SERD_URI, chunk.buf); +} + SERD_API SerdNode serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out) |