aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/serd/buffer.h1
-rw-r--r--include/serd/caret.h1
-rw-r--r--include/serd/error.h1
-rw-r--r--include/serd/memory.h1
-rw-r--r--include/serd/node.h2
-rw-r--r--include/serd/sink.h1
-rw-r--r--include/serd/statement.h1
-rw-r--r--include/serd/string_view.h1
-rw-r--r--include/serd/uri.h27
-rw-r--r--include/serd/world.h1
-rw-r--r--include/serd/writer.h1
-rw-r--r--src/node.c85
-rw-r--r--src/uri.c86
13 files changed, 116 insertions, 93 deletions
diff --git a/include/serd/buffer.h b/include/serd/buffer.h
index cf2170c3..d4fd63fb 100644
--- a/include/serd/buffer.h
+++ b/include/serd/buffer.h
@@ -5,7 +5,6 @@
#define SERD_BUFFER_H
#include "serd/attributes.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
#include <stddef.h>
diff --git a/include/serd/caret.h b/include/serd/caret.h
index f8983899..429a6fcd 100644
--- a/include/serd/caret.h
+++ b/include/serd/caret.h
@@ -6,7 +6,6 @@
#include "serd/attributes.h"
#include "serd/node.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
#include <stdbool.h>
diff --git a/include/serd/error.h b/include/serd/error.h
index 16b28e83..79b22a29 100644
--- a/include/serd/error.h
+++ b/include/serd/error.h
@@ -7,6 +7,7 @@
#include "serd/attributes.h"
#include "serd/caret.h"
#include "serd/status.h"
+#include "zix/attributes.h"
#include <stdarg.h>
diff --git a/include/serd/memory.h b/include/serd/memory.h
index 0e50c4e3..050b7597 100644
--- a/include/serd/memory.h
+++ b/include/serd/memory.h
@@ -5,6 +5,7 @@
#define SERD_MEMORY_H
#include "serd/attributes.h"
+#include "zix/attributes.h"
SERD_BEGIN_DECLS
diff --git a/include/serd/node.h b/include/serd/node.h
index 98fb3d1a..f745af6d 100644
--- a/include/serd/node.h
+++ b/include/serd/node.h
@@ -8,9 +8,7 @@
#include "serd/string_view.h"
#include "serd/uri.h"
#include "serd/write_result.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
-#include "zix/string_view.h"
#include <stdbool.h>
#include <stddef.h>
diff --git a/include/serd/sink.h b/include/serd/sink.h
index 58932435..291e8d3f 100644
--- a/include/serd/sink.h
+++ b/include/serd/sink.h
@@ -9,7 +9,6 @@
#include "serd/node.h"
#include "serd/statement.h"
#include "serd/status.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
SERD_BEGIN_DECLS
diff --git a/include/serd/statement.h b/include/serd/statement.h
index 2e8eddc2..9d987922 100644
--- a/include/serd/statement.h
+++ b/include/serd/statement.h
@@ -7,7 +7,6 @@
#include "serd/attributes.h"
#include "serd/caret.h"
#include "serd/node.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
#include <stdbool.h>
diff --git a/include/serd/string_view.h b/include/serd/string_view.h
index 07b6dd69..6b8e078c 100644
--- a/include/serd/string_view.h
+++ b/include/serd/string_view.h
@@ -5,6 +5,7 @@
#define SERD_STRING_VIEW_H
#include "serd/attributes.h"
+#include "zix/attributes.h"
#include <stddef.h>
#include <string.h>
diff --git a/include/serd/uri.h b/include/serd/uri.h
index bee9fe78..7a63f183 100644
--- a/include/serd/uri.h
+++ b/include/serd/uri.h
@@ -7,9 +7,7 @@
#include "serd/attributes.h"
#include "serd/stream.h"
#include "serd/string_view.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
-#include "zix/string_view.h"
#include <stdbool.h>
#include <stddef.h>
@@ -145,7 +143,8 @@ serd_uri_string_length(SerdURIView uri);
@param sink Sink to write string output to.
@param stream Opaque user argument to pass to `sink`.
- @return The number of bytes written, which is less than
+ @return The length of the written URI string (not including a null
+ terminator, which is not written), which may be less than
`serd_uri_string_length(uri)` on error.
*/
SERD_API size_t
@@ -154,6 +153,28 @@ serd_write_uri(SerdURIView uri,
void* ZIX_NONNULL stream);
/**
+ Write a file URI to `sink` from a path and optional hostname.
+
+ Backslashes in Windows paths will be converted, and other characters will be
+ percent encoded as necessary.
+
+ If `path` is relative, `hostname` is ignored.
+
+ @param path File system path.
+ @param hostname Optional hostname.
+ @param sink Sink to write string output to.
+ @param stream Opaque user argument to pass to `sink`.
+
+ @return The length of the written URI string (not including a null
+ terminator, which is not written)
+*/
+SERD_API size_t
+serd_write_file_uri(SerdStringView path,
+ SerdStringView hostname,
+ SerdWriteFunc ZIX_NONNULL sink,
+ void* ZIX_NONNULL stream);
+
+/**
@}
*/
diff --git a/include/serd/world.h b/include/serd/world.h
index 86e43bb1..0017b6eb 100644
--- a/include/serd/world.h
+++ b/include/serd/world.h
@@ -8,7 +8,6 @@
#include "serd/error.h"
#include "serd/node.h"
#include "serd/status.h"
-#include "zix/allocator.h"
#include "zix/attributes.h"
#include <stddef.h>
diff --git a/include/serd/writer.h b/include/serd/writer.h
index 60220570..fabdcd61 100644
--- a/include/serd/writer.h
+++ b/include/serd/writer.h
@@ -13,7 +13,6 @@
#include "serd/syntax.h"
#include "serd/world.h"
#include "zix/attributes.h"
-#include "zix/string_view.h"
#include <stdint.h>
diff --git a/src/node.c b/src/node.c
index cc29d7a1..79fcc38e 100644
--- a/src/node.c
+++ b/src/node.c
@@ -21,7 +21,6 @@
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -528,91 +527,13 @@ serd_new_resolved_uri(const SerdStringView string, const SerdURIView base)
return result;
}
-static bool
-is_uri_path_char(const char c)
-{
- if (is_alpha(c) || is_digit(c)) {
- return true;
- }
-
- switch (c) {
- // unreserved:
- case '-':
- case '.':
- case '_':
- case '~':
- case ':':
-
- case '@': // pchar
- case '/': // separator
-
- // sub-delimiters:
- case '!':
- case '$':
- case '&':
- case '\'':
- case '(':
- case ')':
- case '*':
- case '+':
- case ',':
- case ';':
- case '=':
- return true;
- default:
- return false;
- }
-}
-
-static bool
-is_dir_sep(const char c)
-{
-#ifdef _WIN32
- return c == '\\' || c == '/';
-#else
- return c == '/';
-#endif
-}
-
SerdNode*
serd_new_file_uri(const SerdStringView path, const SerdStringView hostname)
{
- const bool is_windows = is_windows_path(path.data);
- size_t uri_len = 0;
- char* uri = NULL;
-
- if (is_dir_sep(path.data[0]) || is_windows) {
- uri_len = strlen("file://") + hostname.length + is_windows;
- uri = (char*)calloc(uri_len + 1, 1);
-
- memcpy(uri, "file://", 7);
+ SerdBuffer buffer = {NULL, 0U};
- if (hostname.length) {
- memcpy(uri + 7, hostname.data, hostname.length + 1);
- }
-
- if (is_windows) {
- uri[7 + hostname.length] = '/';
- }
- }
-
- SerdBuffer buffer = {uri, uri_len};
- for (size_t i = 0; i < path.length; ++i) {
- if (path.data[i] == '%') {
- serd_buffer_sink("%%", 1, 2, &buffer);
- } else if (is_uri_path_char(path.data[i])) {
- serd_buffer_sink(path.data + i, 1, 1, &buffer);
-#ifdef _WIN32
- } else if (path.data[i] == '\\') {
- serd_buffer_sink("/", 1, 1, &buffer);
-#endif
- } else {
- char escape_str[10] = {'%', 0, 0, 0, 0, 0, 0, 0, 0, 0};
- snprintf(
- escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path.data[i]);
- serd_buffer_sink(escape_str, 1, 3, &buffer);
- }
- }
+ serd_write_file_uri(path, hostname, serd_buffer_sink, &buffer);
+ serd_buffer_sink_finish(&buffer);
const size_t length = buffer.len;
const char* const string = serd_buffer_sink_finish(&buffer);
diff --git a/src/uri.c b/src/uri.c
index bc9d9fad..e8bc9e05 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -492,3 +492,89 @@ serd_write_uri(const SerdURIView uri,
}
return len;
}
+
+static bool
+is_uri_path_char(const char c)
+{
+ if (is_alpha(c) || is_digit(c)) {
+ return true;
+ }
+
+ switch (c) {
+ // unreserved:
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case ':':
+
+ case '@': // pchar
+ case '/': // separator
+
+ // sub-delimiters:
+ case '!':
+ case '$':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+is_dir_sep(const char c)
+{
+#ifdef _WIN32
+ return c == '\\' || c == '/';
+#else
+ return c == '/';
+#endif
+}
+
+size_t
+serd_write_file_uri(const SerdStringView path,
+ const SerdStringView hostname,
+ const SerdWriteFunc sink,
+ void* const stream)
+{
+ const bool is_windows = is_windows_path(path.data);
+ size_t len = 0U;
+
+ if (is_dir_sep(path.data[0]) || is_windows) {
+ len += sink("file://", 1, strlen("file://"), stream);
+ if (hostname.length) {
+ len += sink(hostname.data, 1, hostname.length, stream);
+ }
+
+ if (is_windows) {
+ len += sink("/", 1, 1, stream);
+ }
+ }
+
+ for (size_t i = 0; i < path.length; ++i) {
+ if (path.data[i] == '%') {
+ len += sink("%%", 1, 2, stream);
+ } else if (is_uri_path_char(path.data[i])) {
+ len += sink(path.data + i, 1, 1, stream);
+#ifdef _WIN32
+ } else if (path.data[i] == '\\') {
+ len += sink("/", 1, 1, stream);
+#endif
+ } else {
+ char escape_str[10] = {'%', 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ snprintf(
+ escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path.data[i]);
+ len += sink(escape_str, 1, 3, stream);
+ }
+ }
+
+ return len;
+}