cleanup, docs

This commit is contained in:
root 2026-06-16 23:02:45 +00:00
parent ea08d5f28b
commit b8b56cf3dd
160 changed files with 1076 additions and 511 deletions

View File

@ -0,0 +1,16 @@
// Small target unit used by the unit_*/component documentation examples.
RENDER(Request& context)
{
print("hello from the sample unit");
}
COMPONENT(Request& context)
{
print("hello from the sample component");
}
EXPORT DValue* doc_greet(DValue* call_param)
{
print("doc_greet() was called");
return(0);
}

View File

@ -22,4 +22,7 @@ Assignment overloads forward to the matching `set(...)` overloads. They are the
:example
print("DValue::assign example\n");
DValue row;
row["name"] = "Ada";
row["role"] = "engineer";
print(row["name"].to_string(), " / ", row["role"].to_string(), "\n");

View File

@ -13,4 +13,7 @@ Clears the value into an empty map-shaped value and resets its array index. Unli
:example
print("DValue::clear example\n");
DValue u;
u["a"] = "1"; u["b"] = "2";
u.clear();
print("after clear, has a: ", u.has("a") ? "yes" : "no", "\n");

View File

@ -14,4 +14,8 @@ Returns the value after following internal reference links. Most public accessor
:example
print("DValue::deref example\n");
DValue target;
target.set("value");
DValue ref;
ref.set_reference(&target);
print("through ref: ", ref.deref().to_string(), "\n");

View File

@ -15,4 +15,6 @@ Ensures the value is map-shaped and returns the named child. If the key does not
:example
print("DValue::get_or_create example\n");
DValue config;
config.get_or_create("host")->set("localhost");
print(config.has("host") ? config["host"].to_string() : "missing", "\n");

View File

@ -12,4 +12,6 @@ Returns a human-readable name for the dereferenced value's type tag.
:example
print("DValue::get_type_name example\n");
DValue s; s.set("text");
DValue m; m["k"] = "v";
print(s.get_type_name(), " / ", m.get_type_name(), "\n");

View File

@ -15,6 +15,6 @@ return value : true when the dereferenced value is map-shaped and contains the k
Checks for a child key without creating it. Returns false for scalars and missing keys.
:example
DValue user;
user["name"] = "Ada";
print(user.has("name") ? "yes\n" : "no\n");
DValue u;
u["name"] = "Ada";
print(u.has("name") ? "has name" : "no name", " / ", u.has("age") ? "has age" : "no age", "\n");

View File

@ -14,4 +14,7 @@ Reports whether the current node's direct type tag is the internal reference tag
:example
print("DValue::is_reference example\n");
DValue target; target.set("x");
DValue ref; ref.set_reference(&target);
DValue plain; plain.set("y");
print(ref.is_reference() ? "ref" : "plain", " / ", plain.is_reference() ? "ref" : "plain", "\n");

View File

@ -16,4 +16,8 @@ Looks up one child without creating it. The non-const overload forwards through
:example
print("DValue::key example\n");
DValue user;
user["email"] = "ada@example.test";
const DValue* found = user.key("email");
const DValue* missing = user.key("phone");
print(found ? found->to_string() : "none", " / ", missing ? "present" : "absent", "\n");

View File

@ -19,4 +19,6 @@ Returns a mutable reference to a child, creating the child when it does not alre
:example
print("DValue::operator_index example\n");
DValue m;
m["a"]["b"] = "nested";
print(m["a"]["b"].to_string(), "\n");

View File

@ -13,4 +13,9 @@ Ensures the value is map-shaped, removes the last entry according to `std::map`
:example
print("DValue::pop example\n");
DValue list;
list.set_array();
DValue a; a.set("first"); list.push(a);
DValue b; b.set("last"); list.push(b);
DValue popped = list.pop();
print("popped ", popped.to_string(), ", remaining ", list.keys().size(), "\n");

View File

@ -15,4 +15,8 @@ Appends a child under the next numeric key. Empty values become list-shaped. Exi
:example
print("DValue::push example\n");
DValue list;
list.set_array();
DValue a; a.set("x"); list.push(a);
DValue b; b.set("y"); list.push(b);
print("count: ", list.keys().size(), "\n");

View File

@ -15,4 +15,8 @@ If this node is an internal reference, follows reference links up to the runtime
:example
print("DValue::reference_target example\n");
DValue target;
target.set("data");
DValue ref;
ref.set_reference(&target);
print(ref.reference_target() == &target ? "points to target" : "elsewhere", "\n");

View File

@ -15,4 +15,7 @@ Ensures the value is map-shaped and erases the named child. Removing the last ch
:example
print("DValue::remove example\n");
DValue u;
u["a"] = "1"; u["b"] = "2";
u.remove("a");
print("has a: ", u.has("a") ? "yes" : "no", ", has b: ", u.has("b") ? "yes" : "no", "\n");

View File

@ -22,4 +22,6 @@ Assigns a new value, forwarding through references when possible. String, pointe
:example
print("DValue::set example\n");
DValue v;
v.set("hello");
print(v.to_string(), "\n");

View File

@ -14,4 +14,8 @@ Clears the value and makes it an empty list-shaped map. Subsequent `push()` call
:example
print("DValue::set_array example\n");
DValue list;
list.set_array();
DValue item; item.set("first");
list.push(item);
print("is_list=", list.is_list() ? "yes" : "no", " count=", list.keys().size(), "\n");

View File

@ -14,4 +14,6 @@ Stores a boolean value, forwarding through references when possible.
:example
print("DValue::set_bool example\n");
DValue flag;
flag.set_bool(true);
print(flag.to_bool() ? "true" : "false", "\n");

View File

@ -14,4 +14,8 @@ Stores an internal reference to another `DValue`. Most unit code should not need
:example
print("DValue::set_reference example\n");
DValue target;
target.set("original");
DValue ref;
ref.set_reference(&target);
print(ref.deref().to_string(), "\n");

View File

@ -17,4 +17,7 @@ Prefer the typed setters (`set`, `set_bool`, `set_array`) in normal unit code.
:example
print("DValue::set_type example\n");
DValue v;
v.set_array();
DValue item; item.set("x"); v.push(item);
print("type after set_array: ", v.get_type_name(), "\n");

View File

@ -14,4 +14,7 @@ Starts a new output buffer for the request and makes it the active `context.ob`.
:example
print("Request::ob_start example\n");
context.ob_start();
print("fragment");
String captured = ob_get_close();
print("captured: ", captured, "\n");

View File

@ -55,6 +55,3 @@ listed, so a deployment cannot be bricked by an over-broad blocklist:
- Pure-compute library functions that are NOT hostcalls (string ops, `DValue`
methods, hashing helpers like `gen_noise`, etc.) are not OS capabilities and
cannot be blocked this way — only `uce_host_*` membrane calls are gateable.
:example
print("Blocked functions documents a UCE concept.\n");

View File

@ -119,4 +119,8 @@ The page template can then render `context.call["fragments"]["head"]` inside `<h
- If a `#load` include looks wrong, check the current file's directory, the configured `BIN_DIRECTORY`, and whether the loaded page already produced its own generated `.cpp`.
:example
print("C++ Preprocessor documents a UCE concept.\n");
// The preprocessor lets you mix C++ logic with output. Code generates markup:
StringList items = split("apples,pears,plums", ",");
String html = "";
items.each([&](String item) { html += "<li>" + item + "</li>"; });
print(html, "\n");

View File

@ -64,4 +64,5 @@ When a unit fails to compile, UCE reports the source path, generated C++ path, c
- Component children/slot syntax is not part of UCE yet; use explicit props and component calls for now.
:example
print("Coming from React documents a UCE concept.\n");
// Components are UCE's reusable, props-driven building blocks (like React components).
print(component("examples/sample_unit"), "\n");

View File

@ -2,17 +2,15 @@
String ascii_safe_name(String raw)
:params
raw : input string to normalize
return value : ASCII-safe identifier made from letters, digits, and underscores
raw : arbitrary input string
return value : an ASCII-only sanitized name
:content
Like `safe_name()`, but also restricts the result to ASCII, transliterating or dropping non-ASCII characters. Use it when the consumer (a legacy filesystem, header, or protocol) requires plain ASCII.
:example
print(ascii_safe_name("Cafe Munchen 2024"), "\n");
:see
>string
:content
Builds a conservative identifier by keeping ASCII letters, digits, and underscores and dropping other characters.
This is useful when turning user- or config-provided names into handler suffixes, DOM-safe variable stems, or CSS and JS hook names.
:example
print(ascii_safe_name("Hello, UCE!"), "\n");
safe_name

View File

@ -20,4 +20,5 @@ Example:
:example
print("backtrace_capture example\n");
String trace = backtrace_capture();
print(trace == "" ? "(empty in the wasm sandbox; populated by the native crash handler)" : trace, "\n");

View File

@ -18,4 +18,4 @@ Formats a captured native backtrace frame array.
Most page code should use `backtrace_capture()` instead. Use this helper when you already have raw frame pointers from lower-level diagnostic code.
:example
print("backtrace_get_frames example\n");
print(backtrace_get_frames(0, 0) == "" ? "(no frames available in the wasm sandbox)" : "frames captured", "\n");

View File

@ -1,24 +1,16 @@
:sig
String base64_decode(String raw, bool& ok)
String base64_decode(String raw)
:params
raw : Base64 encoded string
ok : set to `true` when decoding succeeds; set to `false` for invalid input
return value : decoded binary-safe string, or an empty string when decoding fails
:see
>string
base64_encode
raw : Base64-encoded text
return value : the decoded bytes (empty on invalid input)
:content
Decodes a Base64 string.
Pass a `bool` variable for `ok` so callers can distinguish invalid input from a valid empty decoded value.
Example:
Decodes Base64 text back to bytes. Pairs with `base64_encode()` for round-tripping binary data through text channels.
:example
bool ok = false;
print(base64_decode("aGVsbG8=", ok), " ", ok ? "ok" : "bad", "\n");
print(base64_decode("aGVsbG8="), "\n");
:see
>uri
base64_encode

View File

@ -2,21 +2,16 @@
String base64_encode(String raw)
:params
raw : binary-safe source string
return value : Base64 encoded string
:see
>string
base64_decode
raw : binary-safe source bytes
return value : the Base64-encoded text
:content
Encodes a string with Base64.
UCE strings can contain binary data, so `raw` may include NUL bytes and non-text bytes.
Example:
Encodes bytes as Base64 text. UCE strings are binary-safe, so `raw` may contain NUL and other non-text bytes — handy for embedding `random_bytes()` or a `sha256()` digest in headers, cookies, or JSON.
:example
print(base64_encode("hello"), "\n");
:see
>uri
base64_decode
random_bytes

View File

@ -2,14 +2,16 @@
String basename(String fn)
:params
fn : raw filename
return value : the file's name
fn : a path
return value : the final path component
:content
Returns the last component of a path — the file or directory name without its leading directories.
:example
print(basename("/var/www/site/index.uce"), "\n");
:see
>sys
:content
Isolates the file name component from a path or file name.
:example
print("basename example\n");
dirname
path_join

View File

@ -15,4 +15,5 @@ If the key is missing, or the resolved value is empty, `default_value` is return
For commands that need multiple values or typed reads, prefer calling `cli_input(context)` once and reading the returned `DValue` directly.
:example
print("cli_arg example\n");
String name = cli_arg(context, "name", "world");
print("hello ", name, "\n");

View File

@ -25,4 +25,5 @@ Convenience script usage:
:example
print("cli_input example\n");
DValue input = cli_input(context);
print("parsed ", input.keys().size(), " CLI arguments\n");

View File

@ -58,4 +58,4 @@ Because `<?= ... ?>` escapes HTML, use `<?: ... ?>` when inserting the returned
- `component()` then calls either `COMPONENT(Request& context)` or the selected `COMPONENT:NAME(Request& context)` handler.
:example
print("component example\n");
print(component("examples/sample_unit"), "\n");

View File

@ -18,4 +18,4 @@ If `name` contains a colon, only the file portion is used for existence checks.
This is useful when a page wants to render an optional component if it is present without hard-failing when it is missing.
:example
print("component_exists example\n");
print(component_exists("examples/sample_unit") ? "exists" : "not found", " / ", component_exists("no_such_component") ? "exists" : "not found", "\n");

View File

@ -25,4 +25,5 @@ Use `component_render()` when you want to write component output directly from C
:example
print("component_render example\n");
component_render("examples/sample_unit");
print("\n");

View File

@ -18,4 +18,4 @@ If `name` contains a colon, only the file portion is used for resolution.
This is primarily a debugging helper so you can see which concrete file a shorthand component name maps to.
:example
print("component_resolve example\n");
print("resolved path: ", component_resolve("examples/sample_unit"), "\n");

View File

@ -1,10 +1,20 @@
# crypto_equal
:sig
bool crypto_equal(String a, String b)
:params
a : first value
b : second value
return value : true if the byte strings are equal
Constant-time byte comparison for secrets such as MACs and tokens.
:content
Compares two byte strings in constant time, so the comparison takes the same time whether they differ in the first byte or the last. Always use it to check secrets such as HMACs, tokens, and password hashes — `==` can leak how much of a secret matched via timing.
:example
print(crypto_equal("abc", "abc") ? "same\n" : "different\n");
String expected = hmac_sha256_hex("key", "payload");
print(crypto_equal(expected, hmac_sha256_hex("key", "payload")) ? "valid" : "invalid", " / ");
print(crypto_equal(expected, "tampered") ? "valid" : "invalid", "\n");
:see
>noise
>sys
hmac_sha256_hex
sha256_hex

View File

@ -11,4 +11,4 @@ return value : the current working directory
Returns the current working directory.
:example
print("cwd_get example\n");
print(cwd_get() != "" ? "have a working directory" : "none", "\n");

View File

@ -11,4 +11,7 @@ path : the new working directory
Sets the host worker process current directory. In wasm this is a hostcall, so restore the previous directory when using it inside request code.
:example
print("cwd_set example\n");
String old = cwd_get();
cwd_set("/tmp");
print("cwd is now ", cwd_get(), "\n");
cwd_set(old);

View File

@ -1,9 +1,26 @@
:sig
DValue dir_list(String path)
Returns a list of `{ name, type, size, mtime }` entries for a policy-gated directory. Names are sorted and exclude `.`/`..`.
:params
path : directory to list
return value : a list of entry maps, each with name, type, size, mtime
:content
Lists a directory's entries as a `DValue` list. Each entry is a map with `name`, `type` ("file", "dir", "symlink", or "other"), `size`, and `mtime`. Iterate with `.each()` and read fields with `item.key("name")->to_string()`.
:example
mkdir("/tmp/doc-dirlist");
file_put_contents("/tmp/doc-dirlist/note.txt", "hi");
DValue entries = dir_list("/tmp/doc-dirlist");
String found = "no";
entries.each([&](const DValue& item, String key) {
if(item.key("name") && item.key("name")->to_string() == "note.txt")
found = "yes";
});
print("note.txt listed: ", found, "\n");
:see
>sys
:example
print("dir_list example\n");
file_stat
mkdir
ls

View File

@ -1,9 +1,21 @@
dir_remove
:sig
bool dir_remove(String path, bool recursive = false)
Structural filesystem operation across the wasm host membrane. All path arguments are policy-gated through the same guest file/write roots as other file APIs and return false on denial or OS error.
:params
path : directory to remove
recursive : when true, remove the directory and everything inside it
return value : true on success
:content
Removes a directory. By default it must be empty; pass `recursive = true` to delete the directory and all of its contents.
:example
mkdir("/tmp/doc-rmdir");
file_put_contents("/tmp/doc-rmdir/child.txt", "x");
dir_remove("/tmp/doc-rmdir", true);
print(file_stat("/tmp/doc-rmdir")["exists"].to_bool() ? "still there" : "removed", "\n");
:see
>sys
:example
print("dir_remove example\n");
mkdir
file_unlink

View File

@ -2,14 +2,16 @@
String dirname(String fn)
:params
fn : raw filename
return value : the directory's name
fn : a path
return value : the directory portion of the path
:content
Returns everything in a path except the final component — i.e. the containing directory.
:example
print(dirname("/var/www/site/index.uce"), "\n");
:see
>sys
:content
Isolates the directory component from a path or file name.
:example
print("dirname example\n");
basename
path_join

View File

@ -51,6 +51,3 @@ While an error page renders, error-page handling is disabled: a compiling, broke
## Ready-made examples
`site/errors/compiling.uce`, `site/errors/compiler-error.uce`, and `site/errors/runtime-error.uce` in this repository are working examples — point the config keys at them or copy them into your site.
:example
print("error_pages example\n");

View File

@ -2,15 +2,17 @@
String expand_path(String path, String relative_to_path = "")
:params
path : a relative path
relative_to_path : optional, expand relative to this path (if not given, the current path is used)
return value : expanded version of the 'path'
path : path to expand
relative_to_path : base directory a relative `path` is resolved against
return value : the expanded path
:content
Expands a path: a relative `path` is resolved against `relative_to_path` (or the current unit's directory when that is empty), producing a normalized path you can hand to the file APIs.
:example
print(expand_path("sub/page.uce", "/var/www/site"), "\n");
:see
>sys
:content
Converts a relative path name into an absolute path, using the current working directory as a base when `relative_to_path` is not provided.
:example
print("expand_path example\n");
path_join
path_real

View File

@ -2,16 +2,19 @@
void file_append(String file_name, ...val)
:params
file_name : file name of file that should be written to
...val : one or more values that should be written into the file
file_name : file to append to, created if missing
...val : one or more values appended in order
return value : none
:content
Appends one or more values to a file, creating it if needed. Each call takes an exclusive lock for the append, so concurrent appends are serialized and readers wait for them; you never manage locks yourself.
:example
file_unlink("/tmp/doc-append.txt");
file_append("/tmp/doc-append.txt", "a", "b", "c");
print(file_get_contents("/tmp/doc-append.txt"), "\n");
:see
>sys
:content
Opens or creates a file and appends data to it.
The append transparently takes an exclusive file lock for the duration of the append operation. Concurrent writers are serialized, and `file_get_contents()` waits for in-progress writes to finish; callers do not manage locks manually.
:example
print("file_append example\n");
file_put_contents
file_get_contents

View File

@ -1,9 +1,19 @@
file_chmod
:sig
bool file_chmod(String path, u32 mode)
Filesystem nicety added to the wasm host membrane. Path arguments are policy-gated; operations return an empty value or false on denial/error. file_fsync() takes an open file handle and flushes it with fsync().
:params
path : file or directory to change
mode : permission bits, e.g. 0644 or 0600 (octal)
return value : true on success
:content
Sets a path's permission bits, like the shell `chmod`. Pass the mode as an octal literal such as `0600`.
:example
file_put_contents("/tmp/doc-chmod.txt", "secret");
print(file_chmod("/tmp/doc-chmod.txt", 0600) ? "mode set" : "failed", "\n");
:see
>sys
:example
print("file_chmod example\n");
file_stat
file_put_contents

View File

@ -1,11 +1,20 @@
file_close
:sig
void file_close(u64 h)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle returned by file_open()
See also: file_get_contents, file_put_contents, file_append.
:content
Closes a file handle and releases the lock that `file_open()` took. Always close handles you open: locks are scoped to the handle's lifetime, so a leaked handle holds its lock until the worker recycles.
:example
u64 h = file_open("/tmp/doc-close.txt", "w");
file_write(h, "done");
file_close(h);
print(file_exists("/tmp/doc-close.txt") ? "written and closed" : "missing", "\n");
:see
>sys
:example
print("file_close example\n");
file_open
file_write
file_read

View File

@ -1,9 +1,20 @@
file_copy
:sig
bool file_copy(String from, String to)
Structural filesystem operation across the wasm host membrane. All path arguments are policy-gated through the same guest file/write roots as other file APIs and return false on denial or OS error.
:params
from : source path
to : destination path (overwritten if it exists)
return value : true on success
:content
Copies a file's contents to a new path, overwriting the destination if present.
:example
file_put_contents("/tmp/doc-copy-src.txt", "payload");
file_copy("/tmp/doc-copy-src.txt", "/tmp/doc-copy-dst.txt");
print(file_get_contents("/tmp/doc-copy-dst.txt"), "\n");
:see
>sys
:example
print("file_copy example\n");
file_rename
file_put_contents

View File

@ -2,14 +2,18 @@
bool file_exists(String path)
:params
path : the path name to be checked
return value : true if the file exists
path : path to check, resolved against the unit's directory
return value : true if a regular file exists at `path`
:content
Reports whether a regular file exists. Use it to guard reads or to confirm a write or delete took effect. It is file-oriented and returns false for directories — use `file_stat()` and check `is_dir` to test for a directory.
:example
file_put_contents("/tmp/doc-exists.txt", "x");
print(file_exists("/tmp/doc-exists.txt") ? "exists" : "missing", " / ");
print(file_exists("/tmp/doc-not-here-xyz.txt") ? "exists" : "missing", "\n");
:see
>sys
:content
Checks whether the file or path specified by `path` exists.
:example
print("file_exists example\n");
file_stat
file_unlink

View File

@ -1,9 +1,20 @@
file_fsync
:sig
bool file_fsync(u64 h)
Filesystem nicety added to the wasm host membrane. Path arguments are policy-gated; operations return an empty value or false on denial/error. file_fsync() takes an open file handle and flushes it with fsync().
:params
h : handle from file_open() opened for writing
return value : true if the flush succeeded
:content
Flushes a handle's buffered writes to disk, so the data survives a crash or power loss. Call it before `file_close()` when durability matters (e.g. after writing a checkpoint).
:example
u64 h = file_open("/tmp/doc-fsync.txt", "w");
file_write(h, "durable");
print(file_fsync(h) ? "flushed to disk" : "fsync failed", "\n");
file_close(h);
:see
>sys
:example
print("file_fsync example\n");
file_write
file_close

View File

@ -2,18 +2,18 @@
String file_get_contents(String file_name)
:params
file_name : file name of file that should be read
return value : String containing the file's contents
file_name : file to read, resolved against the unit's directory
return value : the file's contents, or "" if it cannot be read
:content
Reads an entire file and returns it as a `String`. The read takes a shared lock for its duration, so it waits for any in-progress `file_put_contents()` / `file_append()` write to finish; you never manage locks yourself. For large files or random access, use `file_open()` + `file_read()`.
:example
file_put_contents("/tmp/doc-get.txt", "hello");
print(file_get_contents("/tmp/doc-get.txt"), "\n");
:see
>sys
:content
Reads the file identified by `file_name` and returns it as a `String`.
The read transparently takes a shared file lock for the duration of the call. If another worker is writing the same file with `file_put_contents()` or `file_append()`, this read waits for that exclusive write lock to finish, so callers do not manage locks manually.
If the file cannot be read, this function returns an empty string.
:example
print("file_get_contents example\n");
file_put_contents
file_append
file_open

View File

@ -1,16 +1,18 @@
:sig
time_t file_mtime(String file_name)
u64 file_mtime(String file_name)
:params
file_name : name of the file
return value : Unix time stamp of the file's last modification
file_name : path to inspect, resolved against the unit's directory
return value : last-modified time as a Unix timestamp, or 0 if missing
:content
Returns a file's last-modified time as a Unix timestamp. Compare two files' mtimes for cache-freshness checks, or test for `> 0` to confirm a file exists with a real timestamp.
:example
file_put_contents("/tmp/doc-mtime.txt", "x");
print(file_mtime("/tmp/doc-mtime.txt") > 0 ? "has a modification time" : "missing", "\n");
:see
>sys
>time
:content
Retrieves the last modification date of `file_name` as a Unix timestamp.
:example
print("file_mtime example\n");
file_stat
time

View File

@ -1,11 +1,23 @@
file_open
:sig
u64 file_open(String path, String mode)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
path : file to open, resolved against the unit's directory
mode : "r" read, "w" truncate+write, "a" append, "r+" read+write
return value : opaque handle; 0 means open failed (bad path, policy denial, or lock timeout)
See also: file_get_contents, file_put_contents, file_append.
:content
Opens a file for streaming, handle-based I/O and returns an opaque handle for `file_read()`, `file_write()`, `file_seek()`, and `file_close()`. Locks are automatic and scoped to the handle: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and `file_close()` releases it. Lock waits are bounded by `UCE_FILE_LOCK_TIMEOUT_MS` (default 2000ms), so a contended open returns 0 instead of blocking forever. For whole-file access prefer `file_get_contents()` / `file_put_contents()`.
:example
u64 h = file_open("/tmp/doc-open.txt", "w");
file_write(h, "streamed");
file_close(h);
print(file_get_contents("/tmp/doc-open.txt"), "\n");
:see
>sys
:example
print("file_open example\n");
file_read
file_write
file_close
file_get_contents

View File

@ -1,11 +1,25 @@
file_pread
:sig
String file_pread(u64 h, u64 offset, u64 len)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open() opened for reading
offset : absolute byte offset to read from
len : maximum number of bytes to read
return value : up to `len` bytes read at `offset`
See also: file_get_contents, file_put_contents, file_append.
:content
Reads `len` bytes from an absolute `offset` without moving the handle's current offset. Useful for random access reads that interleave with sequential ones.
:example
u64 w = file_open("/tmp/doc-pread.txt", "w");
file_write(w, "hello world");
file_close(w);
u64 r = file_open("/tmp/doc-pread.txt", "r");
print(file_pread(r, 6, 5), "\n");
file_close(r);
:see
>sys
:example
print("file_pread example\n");
file_read
file_pwrite
file_open

View File

@ -2,17 +2,20 @@
bool file_put_contents(String file_name, String content)
:params
file_name : file name of file that should be written
content : content that should be written
return value : true if write was successful
file_name : file to write, resolved against the unit's directory
content : bytes to write (replaces any existing content)
return value : true on success
:content
Writes `content` to a file, replacing whatever was there. The write takes an exclusive lock for the truncate-and-write, so concurrent writers are serialized and readers wait for it; you never manage locks yourself.
:example
file_put_contents("/tmp/doc-put.txt", "first");
file_put_contents("/tmp/doc-put.txt", "second");
print(file_get_contents("/tmp/doc-put.txt"), "\n");
:see
>sys
:content
Writes `content` into the file identified by `file_name`, overwriting any pre-existing content.
The write transparently takes an exclusive file lock for the duration of the truncate-and-write operation. Concurrent writers are serialized, and `file_get_contents()` waits for in-progress writes to finish; callers do not manage locks manually.
:example
print("file_put_contents example\n");
file_get_contents
file_append
file_open

View File

@ -1,11 +1,26 @@
file_pwrite
:sig
u64 file_pwrite(u64 h, u64 offset, String data)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open() opened for writing
offset : absolute byte offset to write at
data : bytes to write
return value : number of bytes written
See also: file_get_contents, file_put_contents, file_append.
:content
Writes `data` at an absolute `offset` without moving the handle's current offset. The handle must be opened with a writable mode (`"r+"` for in-place edits).
:example
u64 h = file_open("/tmp/doc-pwrite.txt", "w");
file_write(h, "hello world");
file_close(h);
u64 e = file_open("/tmp/doc-pwrite.txt", "r+");
file_pwrite(e, 6, "earth");
file_close(e);
print(file_get_contents("/tmp/doc-pwrite.txt"), "\n");
:see
>sys
:example
print("file_pwrite example\n");
file_write
file_pread
file_open

View File

@ -1,11 +1,25 @@
file_read
:sig
String file_read(u64 h, u64 len)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open() opened for reading
len : maximum number of bytes to read
return value : up to `len` bytes from the current offset (shorter at end of file)
See also: file_get_contents, file_put_contents, file_append.
:content
Reads up to `len` bytes starting at the handle's current offset and advances the offset. Returns fewer bytes (or `""`) at end of file. Use `file_seek()` to move the offset, or `file_pread()` to read at an absolute offset without moving it.
:example
u64 w = file_open("/tmp/doc-read.txt", "w");
file_write(w, "hello world");
file_close(w);
u64 r = file_open("/tmp/doc-read.txt", "r");
print(file_read(r, 5), "\n");
file_close(r);
:see
>sys
:example
print("file_read example\n");
file_open
file_pread
file_seek
file_close

View File

@ -1,9 +1,20 @@
file_rename
:sig
bool file_rename(String from, String to)
Structural filesystem operation across the wasm host membrane. All path arguments are policy-gated through the same guest file/write roots as other file APIs and return false on denial or OS error.
:params
from : source path
to : destination path
return value : true on success
:content
Renames or moves a file. After a successful rename the source path no longer exists. Use it for atomic publish patterns: write a temp file, then rename it into place.
:example
file_put_contents("/tmp/doc-rename-a.txt", "moved");
file_rename("/tmp/doc-rename-a.txt", "/tmp/doc-rename-b.txt");
print(file_get_contents("/tmp/doc-rename-b.txt"), " / source ", file_exists("/tmp/doc-rename-a.txt") ? "exists" : "gone", "\n");
:see
>sys
:example
print("file_rename example\n");
file_copy
file_temp

View File

@ -1,11 +1,26 @@
file_seek
:sig
s64 file_seek(u64 h, s64 offset, s64 whence)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open()
offset : byte offset relative to whence
whence : 0 from start, 1 from current, 2 from end
return value : the new absolute offset, or -1 on error
See also: file_get_contents, file_put_contents, file_append.
:content
Moves a handle's read/write offset for random access. Combine with `file_read()` / `file_write()` to jump around a file; `file_tell()` reports the current offset.
:example
u64 w = file_open("/tmp/doc-seek.txt", "w");
file_write(w, "hello world");
file_close(w);
u64 r = file_open("/tmp/doc-seek.txt", "r");
file_seek(r, 6, 0);
print(file_read(r, 5), "\n");
file_close(r);
:see
>sys
:example
print("file_seek example\n");
file_tell
file_read
file_open

View File

@ -1,9 +1,20 @@
:sig
DValue file_stat(String path)
Returns `{ exists, size, mtime, ctime, mode, is_dir, is_file, is_symlink }` for a policy-gated path. Missing or denied paths return `exists=false`.
:params
path : path to inspect, resolved against the unit's directory
return value : a map with exists, is_file, is_dir, is_symlink, size, mode, mtime, ctime
:content
Returns metadata about a path as a `DValue` map. Read fields with the usual accessors, e.g. `st["size"].to_u64()` and `st["is_file"].to_bool()`. When the path does not exist, `exists` is false.
:example
file_put_contents("/tmp/doc-stat.txt", "12345");
DValue st = file_stat("/tmp/doc-stat.txt");
print("size=", st["size"].to_u64(), " is_file=", st["is_file"].to_bool() ? "yes" : "no", "\n");
:see
>sys
:example
print("file_stat example\n");
dir_list
file_exists
file_mtime

View File

@ -1,9 +1,21 @@
file_symlink
:sig
bool file_symlink(String target, String linkpath)
Filesystem nicety added to the wasm host membrane. Path arguments are policy-gated; operations return an empty value or false on denial/error. file_fsync() takes an open file handle and flushes it with fsync().
:params
target : path the symlink should point at
linkpath : symlink to create
return value : true on success
:content
Creates a symbolic link at `linkpath` pointing to `target`. Reading through the link reads the target; use `path_real()` to resolve a link to its canonical destination.
:example
file_put_contents("/tmp/doc-symlink-target.txt", "data");
file_unlink("/tmp/doc-symlink-link.txt");
file_symlink("/tmp/doc-symlink-target.txt", "/tmp/doc-symlink-link.txt");
print(file_get_contents("/tmp/doc-symlink-link.txt"), "\n");
:see
>sys
:example
print("file_symlink example\n");
path_real
file_stat

View File

@ -1,11 +1,20 @@
file_tell
:sig
s64 file_tell(u64 h)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open()
return value : the current absolute byte offset
See also: file_get_contents, file_put_contents, file_append.
:content
Returns a handle's current read/write offset, as moved by `file_read()`, `file_write()`, and `file_seek()`.
:example
u64 h = file_open("/tmp/doc-tell.txt", "w");
file_write(h, "hello");
print("offset is ", file_tell(h), "\n");
file_close(h);
:see
>sys
:example
print("file_tell example\n");
file_seek
file_open

View File

@ -1,9 +1,20 @@
file_temp
:sig
String file_temp(String prefix)
Filesystem nicety added to the wasm host membrane. Path arguments are policy-gated; operations return an empty value or false on denial/error. file_fsync() takes an open file handle and flushes it with fsync().
:params
prefix : path prefix for the temp file; a unique suffix is appended
return value : the path of the newly created temp file, or "" on failure
:content
Creates a new, uniquely named empty file using `prefix` as the leading path and returns its full path. Use it for scratch files and the write-then-rename publish pattern.
:example
String path = file_temp("/tmp/doc-temp-");
file_put_contents(path, "scratch");
print(str_starts_with(path, "/tmp/doc-temp-") ? "created a temp file" : path, "\n");
file_unlink(path);
:see
>sys
:example
print("file_temp example\n");
file_rename
file_put_contents

View File

@ -1,9 +1,20 @@
file_truncate
:sig
bool file_truncate(String path, u64 size)
Structural filesystem operation across the wasm host membrane. All path arguments are policy-gated through the same guest file/write roots as other file APIs and return false on denial or OS error.
:params
path : file to resize
size : new length in bytes
return value : true on success
:content
Truncates (or extends) a file to exactly `size` bytes. Shrinking discards trailing bytes; growing pads with zero bytes.
:example
file_put_contents("/tmp/doc-truncate.txt", "hello world");
file_truncate("/tmp/doc-truncate.txt", 5);
print(file_get_contents("/tmp/doc-truncate.txt"), "\n");
:see
>sys
:example
print("file_truncate example\n");
file_put_contents
file_stat

View File

@ -2,13 +2,18 @@
void file_unlink(String file_name)
:params
file_name : name of the file
file_name : file to delete, resolved against the unit's directory
return value : none
:content
Deletes a file. Deleting a path that does not exist is a no-op, so it is safe to call before recreating a file.
:example
file_put_contents("/tmp/doc-unlink.txt", "x");
file_unlink("/tmp/doc-unlink.txt");
print(file_exists("/tmp/doc-unlink.txt") ? "exists" : "gone", "\n");
:see
>sys
:content
Deletes the file identified by `file_name`.
:example
print("file_unlink example\n");
file_exists
dir_remove

View File

@ -1,11 +1,23 @@
file_write
:sig
u64 file_write(u64 h, String data)
Streaming/handle-based file I/O across the wasm host membrane. Handles are opaque u64 values returned by file_open(); 0 means open failed (including path policy denial or bounded lock timeout). Locks are automatic and lifetime-scoped: read opens take a shared lock, write/append/read-write opens take an exclusive lock, and file_close() releases it. Lock wait is bounded by UCE_FILE_LOCK_TIMEOUT_MS (default 2000ms).
:params
h : handle from file_open() opened for writing
data : bytes to write at the current offset
return value : number of bytes written
See also: file_get_contents, file_put_contents, file_append.
:content
Writes `data` at the handle's current offset and advances the offset. The handle must come from `file_open()` with a writable mode (`"w"`, `"a"`, or `"r+"`). Binary-safe: `data` may contain NUL and other non-text bytes.
:example
u64 h = file_open("/tmp/doc-write.txt", "w");
u64 n = file_write(h, "hello world");
file_close(h);
print(n, " bytes -> ", file_get_contents("/tmp/doc-write.txt"), "\n");
:see
>sys
:example
print("file_write example\n");
file_open
file_pwrite
file_read
file_close

View File

@ -16,4 +16,4 @@ Extracts a floating point number from a `String`.
If no usable number can be identified, the result is `0`.
:example
print("float_val example\n");
print(float_val("3.14") + 1.0, "\n");

View File

@ -20,4 +20,6 @@ The result is binary data. Store it in a file, send it with an appropriate conte
UCE writes a standard gzip wrapper around a deflate stream, including CRC32 and uncompressed-size footer fields.
:example
print("gz_compress example\n");
String original = "hello hello hello hello hello";
String packed = gz_compress(original);
print(original.length(), " bytes -> ", packed.length(), " bytes; restores to: ", gz_uncompress(packed), "\n");

View File

@ -18,4 +18,5 @@ Uncompresses a gzip-format byte string and returns the original content.
`gz_uncompress()` validates the gzip header, CRC32 footer, and uncompressed-size footer. It throws a runtime error when the input is not a supported gzip stream or fails validation.
:example
print("gz_uncompress example\n");
String packed = gz_compress("round trip data");
print(gz_uncompress(packed), "\n");

View File

@ -1,10 +1,19 @@
# hmac_sha256
:sig
String hmac_sha256(String key, String data)
:params
key : secret key
data : message to authenticate
return value : the raw 32-byte HMAC-SHA256
Returns the raw 32-byte HMAC-SHA-256 digest for `data` keyed by `key`.
:content
Computes an HMAC-SHA256 and returns it as raw bytes. Prefer `hmac_sha256_hex()` for printable signatures; use the raw form for binary protocols.
:example
print(hmac_sha256("key", "data").length(), "\n");
print(hmac_sha256("key", "message").length(), " raw bytes, hex = ", hmac_sha256_hex("key", "message"), "\n");
:see
>noise
>sys
hmac_sha256_hex
sha256
crypto_equal

View File

@ -1,10 +1,19 @@
# hmac_sha256_hex
:sig
String hmac_sha256_hex(String key, String data)
:params
key : secret key
data : message to authenticate
return value : the HMAC-SHA256 as a 64-character lowercase hex string
Returns the lowercase hexadecimal HMAC-SHA-256 digest.
:content
Computes an HMAC-SHA256 message authentication code and returns it as hex. Use it to sign tokens, cookies, and webhook payloads, then verify with `crypto_equal()` to avoid timing leaks.
:example
print(hmac_sha256_hex("key", "data"), "\n");
print(hmac_sha256_hex("key", "The quick brown fox jumps over the lazy dog"), "\n");
:see
>noise
>sys
hmac_sha256
sha256_hex
crypto_equal

View File

@ -20,4 +20,4 @@ Returns a version of the input string where special HTML characters are replaced
- `"` becomes `&quot;`
:example
print("html_escape example\n");
print(html_escape("<b>Tom & Jerry</b>"), "\n");

View File

@ -12,4 +12,7 @@ Returns `{ status, headers, body, error }`. `headers` is a name/value map. A mis
>socket
:example
print("http_request is resource-bound; configure the service or connection, then call it in request code.\n");
DValue req; req["method"] = "GET"; req["url"] = "http://127.0.0.1/doc/index.uce";
req["headers"]["Host"] = "uce.openfu.com"; req["timeout_ms"] = (f64)2000;
DValue resp = http_request(req);
print("HTTP ", resp["status"].to_u64(), ", ", resp["body"].to_string().length(), " bytes returned\n");

View File

@ -10,4 +10,8 @@ Starts the same bounded curl-backed request as `http_request()` in the file-back
>socket
:example
print("http_request_async is resource-bound; configure the service or connection, then call it in request code.\n");
DValue req; req["method"] = "GET"; req["url"] = "http://127.0.0.1/doc/index.uce";
req["headers"]["Host"] = "uce.openfu.com"; req["timeout_ms"] = (f64)2000;
u64 job = http_request_async(req);
DValue done = job_await(job, 3000);
print("async HTTP ", done["result"]["status"].to_u64(), "\n");

View File

@ -17,4 +17,4 @@ Extracts an integer value from `s`.
The `base` argument controls which number system is used while parsing. If no usable number can be identified, the function returns `0`.
:example
print("int_val example\n");
print(int_val("42"), " / ", int_val("ff", 16), "\n");

View File

@ -7,4 +7,7 @@ Waits up to `timeout_ms` for a job to finish, then returns status/result data. T
>sys
:example
print("job_await example\n");
DValue spec; spec["cmd"] = "printf hello-from-job"; spec["timeout_ms"] = (f64)1000;
u64 job = shell_spawn(spec);
DValue waited = job_await(job, 3000);
print("done=", waited["done"].to_bool() ? "true" : "false", " stdout=", waited["result"]["stdout"].to_string(), "\n");

View File

@ -7,4 +7,6 @@ Attempts to terminate the background job process group and marks the registry en
>sys
:example
print("job_cancel example\n");
DValue spec; spec["cmd"] = "sleep 5"; spec["timeout_ms"] = (f64)10000;
u64 job = shell_spawn(spec);
print(job_cancel(job) ? "job cancelled" : "could not cancel", "\n");

View File

@ -7,4 +7,7 @@ Checks a job result with a small bounded wait. The returned value includes the c
>sys
:example
print("job_result example\n");
DValue spec; spec["cmd"] = "printf result-data"; spec["timeout_ms"] = (f64)1000;
u64 job = shell_spawn(spec);
job_await(job, 3000);
print(job_result(job)["result"]["stdout"].to_string(), "\n");

View File

@ -7,4 +7,7 @@ Returns the file-backed async job state, e.g. `{ state, done, kind, pid, job_id
>sys
:example
print("job_status example\n");
DValue spec; spec["cmd"] = "printf x"; spec["timeout_ms"] = (f64)1000;
u64 job = shell_spawn(spec);
job_await(job, 3000);
print("state: ", job_status(job)["state"].to_string(), "\n");

View File

@ -29,4 +29,5 @@ Current runtime behavior:
- JSON numbers currently deserialize as string-valued `DValue` nodes, so typed conversions such as `to_f64()` and `to_u64()` are the normal way to read numeric content.
:example
print("json_decode example\n");
DValue data = json_decode("{\"name\": \"Ada\", \"tags\": [\"x\", \"y\"]}");
print(data["name"].to_string(), " has ", data["tags"].keys().size(), " tags\n");

View File

@ -1,15 +0,0 @@
:sig
Use filter(StringList items, function<bool (String)> f)
:see
filter
0_StringList
:content
`list_filter()` was removed because `StringList` is `std::vector<String>` and the generic `filter()` helper covers the same behavior without a second implementation to maintain.
Use:
:example
print("list_filter example\n");

View File

@ -1,16 +0,0 @@
:sig
Use map(StringList items, function<String (String)> f)
:see
map
filter
0_StringList
:content
`list_map()` was removed because `StringList` is `std::vector<String>` and the generic `map()` helper covers the same behavior without a second implementation to maintain.
Use:
:example
print("list_map example\n");

View File

@ -14,4 +14,7 @@ Use `#load` when you want the current file to pull in declarations or reusable c
:example
print("load example\n");
// #load "file.uce" includes another unit at COMPILE time (a preprocessor directive,
// used at file top level). At RUNTIME, unit_render()/unit_call() invoke another unit:
unit_render("examples/sample_unit.uce");
print("\n");

View File

@ -2,16 +2,20 @@
StringList ls(String path)
:params
path : a filesystem path
return value : list of directory entries
path : directory to list
return value : a StringList of entry names
:content
Returns the names of the entries in a directory as a `StringList`. For names only this is simpler than `dir_list()`, which returns full metadata per entry.
:example
mkdir("/tmp/doc-ls");
file_put_contents("/tmp/doc-ls/one.txt", "1");
file_put_contents("/tmp/doc-ls/two.txt", "2");
print(join(ls("/tmp/doc-ls").sort(), ","), "\n");
dir_remove("/tmp/doc-ls", true);
:see
>sys
:content
Returns a list of files and subdirectories within `path`.
This is a simple directory listing helper for filesystem-oriented tasks.
:example
print("ls example\n");
dir_list
0_StringList

View File

@ -15,4 +15,6 @@ Executes a raw command on an open Memcache connection and returns the server res
This is the low-level escape hatch for Memcache operations that are not covered by the dedicated helpers.
:example
print("memcache_command is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
if(conn != 0) print(memcache_command(conn, "stats") != "" ? "stats command returned data" : "no data", "\n");
else print("(requires a reachable memcached server)\n");

View File

@ -1,5 +1,5 @@
:sig
u64 memcache_connect(String host = "127.0.0.1", short port = 11211)
u64 memcache_connect(String host = "127.0.0.1", u16 port = 11211)
:params
host : optional host name of the memcache server, defaults to local address 127.0.0.1
@ -15,4 +15,5 @@ Connects to a Memcache server instance.
If the connection fails, the function returns `-1`.
:example
print("memcache_connect is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
print(conn != 0 ? "connected to memcached" : "no memcached server reachable", "\n");

View File

@ -15,4 +15,11 @@ Deletes the entry identified by `key`.
The return value is `true` when the operation succeeds.
:example
print("memcache_delete is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
if(conn != 0)
{
memcache_set(conn, "doc_del_key", "v");
memcache_delete(conn, "doc_del_key");
print(memcache_get(conn, "doc_del_key", "gone"), "\n");
}
else print("(requires a reachable memcached server)\n");

View File

@ -13,4 +13,4 @@ return value : memcache-safe key string
Normalizes whitespace in a memcache key to underscores before it is placed into a text protocol command.
:example
print("memcache_escape_key is resource-bound; configure the service or connection, then call it in request code.\n");
print(memcache_escape_key("a key with spaces"), "\n");

View File

@ -13,4 +13,7 @@ return value : escaped keys
Applies `memcache_escape_key()` to each key in a list.
:example
print("memcache_escape_keys is resource-bound; configure the service or connection, then call it in request code.\n");
StringList keys;
keys.push_back("a b");
keys.push_back("c\td");
print(join(memcache_escape_keys(keys), ", "), "\n");

View File

@ -16,4 +16,6 @@ Retrieves a value from an existing Memcache connection.
If the key is missing, `default_value` is returned instead.
:example
print("memcache_get is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
if(conn != 0) { memcache_set(conn, "doc_get_key", "stored value"); print(memcache_get(conn, "doc_get_key"), "\n"); }
else print("(requires a reachable memcached server)\n");

View File

@ -15,4 +15,13 @@ Retrieves multiple entries in one call.
The result is returned as a `StringMap` keyed by the requested Memcache keys.
:example
print("memcache_get_multiple is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
if(conn != 0)
{
memcache_set(conn, "doc_k1", "v1");
memcache_set(conn, "doc_k2", "v2");
StringList keys; keys.push_back("doc_k1"); keys.push_back("doc_k2");
StringMap vals = memcache_get_multiple(conn, keys);
print(vals["doc_k1"], " / ", vals["doc_k2"], "\n");
}
else print("(requires a reachable memcached server)\n");

View File

@ -17,4 +17,6 @@ Stores `value` under `key` on the Memcache server.
`expires_in` controls the expiration timeout and defaults to one hour.
:example
print("memcache_set is resource-bound; configure the service or connection, then call it in request code.\n");
u64 conn = memcache_connect();
if(conn != 0) print(memcache_set(conn, "doc_set_key", "value") ? "stored" : "store failed", "\n");
else print("(requires a reachable memcached server)\n");

View File

@ -2,16 +2,19 @@
bool mkdir(String path)
:params
path : the path name to be created
return value : returns true if the directory was successfully created
path : directory to create
return value : true on success
:content
Creates a single directory and returns whether it succeeded. The parent directory must already exist, so build nested paths one level at a time.
:example
dir_remove("/tmp/doc-mkdir-demo", true);
mkdir("/tmp/doc-mkdir-demo");
print(file_stat("/tmp/doc-mkdir-demo")["is_dir"].to_bool() ? "created" : "not created", "\n");
dir_remove("/tmp/doc-mkdir-demo", true);
:see
>sys
:content
Creates the directory named by `path`.
The function returns `true` when the directory was created successfully.
:example
print("mkdir example\n");
dir_remove
dir_list

View File

@ -16,4 +16,6 @@ Establishes a connection to a MySQL server and returns a pointer to the connecti
This connection handle is then used with helpers such as `mysql_query()`, `mysql_error()`, and `mysql_disconnect()`.
:example
print("mysql_connect is resource-bound; configure the service or connection, then call it in request code.\n");
MySQL* db = mysql_connect();
print(db != 0 ? "connected to MySQL" : "no MySQL server reachable with these credentials", "\n");
if(db != 0) mysql_disconnect(db);

View File

@ -13,4 +13,6 @@ Closes an existing connection to a MySQL server.
Call this when you are done using a `MySQL*` connection handle.
:example
print("mysql_disconnect is resource-bound; configure the service or connection, then call it in request code.\n");
MySQL* db = mysql_connect();
if(db != 0) { mysql_disconnect(db); print("connection closed\n"); }
else print("(requires a reachable MySQL server)\n");

View File

@ -14,4 +14,11 @@ Returns the last error message associated with the given MySQL connection.
If there is no current error, the result is an empty string.
:example
print("mysql_error is resource-bound; configure the service or connection, then call it in request code.\n");
MySQL* db = mysql_connect();
if(db != 0)
{
mysql_query(db, "select * from no_such_table_xyz");
print(mysql_error(db) != "" ? "error reported" : "no error", "\n");
mysql_disconnect(db);
}
else print("(requires a reachable MySQL server)\n");

View File

@ -15,4 +15,4 @@ Escapes a string so it can be used safely as a value inside an SQL expression.
If `quote_char` is provided, the escaped result is wrapped with that quote character. Pass `NULL` when you only want escaping without wrapping.
:example
print("mysql_escape is resource-bound; configure the service or connection, then call it in request code.\n");
print(mysql_escape("O'Brien; DROP TABLE users", '\''), "\n");

View File

@ -14,4 +14,11 @@ Returns the last automatically assigned row ID used by the current MySQL connect
This is typically used after an `INSERT` into a table with an `AUTO_INCREMENT` primary key.
:example
print("mysql_insert_id is resource-bound; configure the service or connection, then call it in request code.\n");
MySQL* db = mysql_connect();
if(db != 0)
{
DValue row = mysql_query(db, "select last_insert_id() as id");
print("mysql_insert_id() returns the last AUTO_INCREMENT id for this connection (currently ", mysql_insert_id(db), ")\n");
mysql_disconnect(db);
}
else print("(requires a reachable MySQL server)\n");

View File

@ -27,4 +27,13 @@ DValue rows = mysql_query(m,
The result is returned as a `DValue`, which makes it easy to iterate through rows and read fields with the usual `DValue` accessors.
:example
print("mysql_query is resource-bound; configure the service or connection, then call it in request code.\n");
MySQL* db = mysql_connect();
if(db != 0)
{
DValue rows = mysql_query(db, "select 'ada@example.test' as email, 1 + 1 as total");
String email = "none"; String total = "?";
rows.each([&](DValue r, String key) { email = r["email"].to_string(); total = r["total"].to_string(); });
print(email, " / total=", total, "\n");
mysql_disconnect(db);
}
else print("(requires a reachable MySQL server)\n");

View File

@ -2,15 +2,18 @@
void ob_close()
:params
(none)
return value : none
:content
Discards the current output buffer and its contents, switching back to the previous buffer on the stack. Use it when you captured output only to throw it away (e.g. rendering for a side effect).
:example
ob_start();
print("this output is discarded");
ob_close();
print("the buffered text never reached the response\n");
:see
>ob
:content
Discards the current output buffer.
If more output buffers remain on the stack, UCE switches to the next one.
:example
print("ob_close example\n");
ob_get_close
ob_start

View File

@ -2,15 +2,19 @@
String ob_get()
:params
return value : content of the current output buffer
return value : the current buffer's contents
:content
Returns the current output buffer's contents WITHOUT discarding the buffer, so more output can still be appended. Use `ob_get_close()` when you also want to pop the buffer.
:example
ob_start();
print("partial");
String snapshot = ob_get();
ob_close();
print("snapshot was: ", snapshot, "\n");
:see
>ob
:content
Returns the contents of the current output buffer.
Unlike `ob_get_close()`, this does not discard the buffer.
:example
print("ob_get example\n");
ob_get_close
ob_start

Some files were not shown because too many files have changed in this diff Show More