UXURL
UXURL parses scheme://host:port/path?query#fragment into six fields and
builds it back again. It has the shape of NSURL/NSURLComponents.
It works on strings only: nothing here resolves, connects or looks anything up.
It is the model half of networking (a connection would take one of these),
and it also backs public.file-url pasteboard payloads and the file panel.
#use <UXKit> // or #import "UXURL.xc"Overview
Section titled “Overview”UXURL* u = UXURL.parse((u8*)"https://example.org:8443/docs/uxkit?tab=api#paths");
u.scheme; // "https"u.host; // "example.org"u.port; // 8443u.path; // "/docs/uxkit"u.query; // "tab=api" — no leading '?'u.fragment; // "paths" — no leading '#'u.lastPathComponent(); // "uxkit"u.toString(); // the whole thing againThe delimiters are not stored: query is "tab=api", not "?tab=api".
toString restores them when the part is non-empty, so a URL with
no fragment has no trailing #.
Every field has an empty default, never null
Section titled “Every field has an empty default, never null”scheme = ""; host = ""; path = ""; query = ""; fragment = ""; port = -1;A parsed URL is always safe to print and compare, whatever the input. There is
no “is this part present” call because there is no null to guard against. An
absent part is empty; test with slen(...) > 0 when you need to.
port is the exception, because 0 is a valid number:
”://” is what makes a scheme
Section titled “”://” is what makes a scheme”The parser looks for the literal ://. Without it there is no scheme and no
host, and the whole string is the path:
UXURL* bare = UXURL.parse((u8*)"notes/today.md");bare.scheme; // ""bare.host; // ""bare.path; // "notes/today.md"A bare filename or relative path therefore survives parse unchanged and is not
misread as a host. The cost of this rule is that mailto:user@example.org has a
scheme by RFC but not by this parser, and comes out as a path. Schemes without
an authority are not handled.
file: URLs are the bridge to UXPath
Section titled “file: URLs are the bridge to UXPath”UXURL* f = UXURL.fileURL((u8*)"/usr/local/share/fonts/system.fnt");f.toString(); // "file:///usr/local/share/fonts/system.fnt"f.isFileURL(); // trueUXPath* p = UXPath.parse(f.path);The three slashes are file://, an empty host, and a path that starts with /.
This is the correct form, and the rebuild produces it without a special case.
A dropped file arrives this way. The pasteboard carries public.file-url; you
parse it, take .path, and continue with
UXPath.
Fields
Section titled “Fields”scheme
Section titled “scheme”u8* scheme // "" when the string had no "://"u8* host // "" for file: URLs and for scheme-less stringsi32 port // -1 = unspecifiedu8* pathEverything after the authority, up to ? or #. Keeps its leading /.
u8* query // no leading '?'Held whole and not split into pairs. The structure of a query string is up to the application.
fragment
Section titled “fragment”u8* fragment // no leading '#'Topics
Section titled “Topics”parse · fileURL · isFileURL · lastPathComponent · toString
static UXURL* parse(u8* s)Splits a string into the six fields. Copies the bytes, so the input can be freed. Never fails: a string that is not a URL becomes a URL that is all path.
fileURL
Section titled “fileURL”static UXURL* fileURL(u8* path)A file: URL for a local path.
isFileURL
Section titled “isFileURL”bool isFileURL(void)Whether the scheme is file, compared by content.
lastPathComponent
Section titled “lastPathComponent”u8* lastPathComponent(void)The filename: everything after the last / in path. "" for a URL
whose path ends in a separator.
toString
Section titled “toString”u8* toString(void)Rebuilds the string, restoring ://, :port, ? and # for the parts that
are present. parse → toString round-trips.
Example
Section titled “Example”url scheme=https host=example.org port=8443 path=/docs/uxkit query=tab=api fragment=paths last=uxkit rebuilt=https://example.org:8443/docs/uxkit?tab=api#pathsno port: port=-1 rebuilt=http://example.com/index.htmlbare: scheme='' host='' path=notes/today.mdfile url: file:///usr/local/share/fonts/system.fnt isFile=1 name=system.fntback to path: '/usr/local/share/fonts/system.fnt' count=5 abs=1The program is website/site/examples/uxkit/paths.xc. The doc-examples gate
compiles it, and the block above is its output.
Conforms to
Section titled “Conforms to”- A plain class (not an
Objectsubclass)
See also
Section titled “See also”UXPath: the same job for filesystem pathsUXPasteboard: wherepublic.file-urlpayloads arriveUXFilePanel: choosing a file