diff options
author | David Robillard <d@drobilla.net> | 2023-03-29 07:28:19 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 16:27:02 -0500 |
commit | fff826f406e0b9975fd8672041e50dd1a342339f (patch) | |
tree | 03a22b89b83a8b26fdf18dd8700e51833b488d81 /include | |
parent | 94d3433dcf0e77d2c867c9a2dd6928acfea4184c (diff) | |
download | serd-fff826f406e0b9975fd8672041e50dd1a342339f.tar.gz serd-fff826f406e0b9975fd8672041e50dd1a342339f.tar.bz2 serd-fff826f406e0b9975fd8672041e50dd1a342339f.zip |
Simplify URI API and implementation
Diffstat (limited to 'include')
-rw-r--r-- | include/serd/node.h | 43 | ||||
-rw-r--r-- | include/serd/uri.h | 125 |
2 files changed, 89 insertions, 79 deletions
diff --git a/include/serd/node.h b/include/serd/node.h index 1c64b6b9..b95891c9 100644 --- a/include/serd/node.h +++ b/include/serd/node.h @@ -112,20 +112,16 @@ serd_new_substring(SerdNodeType type, size_t len); /** - Create a new URI node from a node. + Create a new URI node from a parsed URI. */ SERD_API SerdNode* SERD_ALLOCATED -serd_new_uri_from_node(const SerdNode* SERD_NONNULL uri_node, - const SerdURIView* SERD_NULLABLE base, - SerdURIView* SERD_NULLABLE out); +serd_new_parsed_uri(SerdURIView uri); /** Create a new URI node from a string. */ SERD_API SerdNode* SERD_ALLOCATED -serd_new_uri_from_string(const char* SERD_NULLABLE str, - const SerdURIView* SERD_NULLABLE base, - SerdURIView* SERD_NULLABLE out); +serd_new_uri(const char* SERD_NONNULL str); /** Create a new file URI node from a file system path and optional hostname. @@ -142,39 +138,6 @@ serd_new_file_uri(const char* SERD_NONNULL path, SerdURIView* SERD_NULLABLE out); /** - Create a new node by serialising `uri` into a new string. - - @param uri The URI to serialise. - - @param base Base URI to resolve `uri` against (or NULL for no resolution). - - @param out Set to the parsing of the new URI (i.e. points only to - memory owned by the new returned node). -*/ -SERD_API SerdNode* SERD_ALLOCATED -serd_new_uri(const SerdURIView* SERD_NONNULL uri, - const SerdURIView* SERD_NULLABLE base, - SerdURIView* SERD_NULLABLE out); - -/** - Create a new node by serialising `uri` into a new relative URI. - - @param uri The URI to serialise. - - @param base Base URI to make `uri` relative to, if possible. - - @param root Root URI for resolution (see serd_uri_serialise_relative()). - - @param out Set to the parsing of the new URI (i.e. points only to - memory owned by the new returned node). -*/ -SERD_API SerdNode* SERD_ALLOCATED -serd_new_relative_uri(const SerdURIView* SERD_NONNULL uri, - const SerdURIView* SERD_NULLABLE base, - const SerdURIView* SERD_NULLABLE root, - SerdURIView* SERD_NULLABLE out); - -/** Create a new node by serialising `d` into an xsd:decimal string. The resulting node will always contain a '.', start with a digit, and end diff --git a/include/serd/uri.h b/include/serd/uri.h index 06cb97fb..7b5529dc 100644 --- a/include/serd/uri.h +++ b/include/serd/uri.h @@ -5,7 +5,6 @@ #define SERD_URI_H #include "serd/attributes.h" -#include "serd/status.h" #include "serd/stream.h" #include "serd/string_view.h" @@ -21,19 +20,30 @@ SERD_BEGIN_DECLS */ /** - A parsed URI. - - This struct directly refers to slices in other strings, it does not own any - memory itself. This allows some URI operations like resolution to be done - in-place without allocating memory. + A parsed view of a URI. + + This representation is designed for fast streaming. It makes it possible to + create relative URI references or resolve them into absolute URIs in-place + without any string allocation. + + Each component refers to slices in other strings, so a URI view must outlive + any strings it was parsed from. Note that the components are not + necessarily null-terminated. + + The scheme, authority, path, query, and fragment simply point to the string + value of those components, not including any delimiters. The path_prefix is + a special component for storing relative or resolved paths. If it points to + a string (usually a base URI the URI was resolved against), then this string + is prepended to the path. Otherwise, the length is interpreted as the + number of up-references ("../") that must be prepended to the path. */ typedef struct { - SerdStringView scheme; ///< Scheme - SerdStringView authority; ///< Authority - SerdStringView path_base; ///< Path prefix if relative - SerdStringView path; ///< Path suffix - SerdStringView query; ///< Query - SerdStringView fragment; ///< Fragment + SerdStringView scheme; ///< Scheme + SerdStringView authority; ///< Authority + SerdStringView path_prefix; ///< Path prefix for relative/resolved paths + SerdStringView path; ///< Path suffix + SerdStringView query; ///< Query + SerdStringView fragment; ///< Fragment } SerdURIView; static const SerdURIView SERD_URI_NULL = @@ -46,49 +56,86 @@ static const SerdURIView SERD_URI_NULL = @param uri A file URI. @param hostname If non-NULL, set to the hostname, if present. - @return The path component of the URI. + @return A newly-allocated filesystem path. */ -SERD_API char* SERD_NULLABLE -serd_file_uri_parse(const char* SERD_NONNULL uri, +SERD_API char* SERD_ALLOCATED +serd_parse_file_uri(const char* SERD_NONNULL uri, char* SERD_NONNULL* SERD_NULLABLE hostname); -/// Return true iff `utf8` starts with a valid URI scheme +/// Return true iff `string` starts with a valid URI scheme SERD_PURE_API bool -serd_uri_string_has_scheme(const char* SERD_NULLABLE utf8); +serd_uri_string_has_scheme(const char* SERD_NONNULL string); -/// Parse `utf8`, writing result to `out` -SERD_API SerdStatus -serd_uri_parse(const char* SERD_NONNULL utf8, SerdURIView* SERD_NONNULL out); +/// Parse `string` and return a URI view that points into it +SERD_PURE_API SerdURIView +serd_parse_uri(const char* SERD_NONNULL string); /** - Set target `t` to reference `r` resolved against `base`. + Return reference `r` resolved against `base`. + + This will make `r` an absolute URI if possible. @see [RFC3986 5.2.2](http://tools.ietf.org/html/rfc3986#section-5.2.2) + + @param r URI reference to make absolute, for example "child/path". + + @param base Base URI, for example "http://example.org/base/". + + @return An absolute URI, for example "http://example.org/base/child/path", + or `r` if it is not a URI reference that can be resolved against `base`. */ -SERD_API void -serd_uri_resolve(const SerdURIView* SERD_NONNULL r, - const SerdURIView* SERD_NONNULL base, - SerdURIView* SERD_NONNULL t); +SERD_PURE_API SerdURIView +serd_resolve_uri(SerdURIView r, SerdURIView base); -/// Serialise `uri` with a series of calls to `sink` -SERD_API size_t -serd_uri_serialise(const SerdURIView* SERD_NONNULL uri, - SerdSink SERD_NONNULL sink, - void* SERD_NONNULL stream); +/** + Return `r` as a reference relative to `base` if possible. + + @see [RFC3986 5.2.2](http://tools.ietf.org/html/rfc3986#section-5.2.2) + + @param r URI to make relative, for example + "http://example.org/base/child/path". + + @param base Base URI, for example "http://example.org/base". + + @return A relative URI reference, for example "child/path", `r` if it can + not be made relative to `base`, or a null URI if `r` could be made relative + to base, but the path prefix is already being used (most likely because `r` + was previously a relative URI reference that was resolved against some + base). +*/ +SERD_PURE_API SerdURIView +serd_relative_uri(SerdURIView r, SerdURIView base); + +/** + Return whether `r` can be written as a reference relative to `base`. + + For example, with `base` "http://example.org/base/", this returns true if + `r` is also "http://example.org/base/", or something like + "http://example.org/base/child" ("child") + "http://example.org/base/child/grandchild#fragment" + ("child/grandchild#fragment"), + "http://example.org/base/child/grandchild?query" ("child/grandchild?query"), + and so on. + + @return True if `r` and `base` are equal or if `r` is a child of `base`. +*/ +SERD_PURE_API bool +serd_uri_is_within(SerdURIView r, SerdURIView base); /** - Serialise `uri` relative to `base` with a series of calls to `sink` + Write `uri` as a string to `sink`. + + This will call `sink` several times to emit the URI. - The `uri` is written as a relative URI iff if it a child of `base` and - `root`. The optional `root` parameter must be a prefix of `base` and can be - used keep up-references ("../") within a certain namespace. + @param uri URI to write as a string. + @param sink Sink to write string output to. + @param stream Opaque user argument to pass to `sink`. + @return The number of bytes written. */ SERD_API size_t -serd_uri_serialise_relative(const SerdURIView* SERD_NONNULL uri, - const SerdURIView* SERD_NULLABLE base, - const SerdURIView* SERD_NULLABLE root, - SerdSink SERD_NONNULL sink, - void* SERD_NONNULL stream); +serd_write_uri(SerdURIView uri, + SerdSink SERD_NONNULL sink, + void* SERD_NONNULL stream); /** @} |