cleanup, docs
This commit is contained in:
parent
ea08d5f28b
commit
b8b56cf3dd
16
site/doc/examples/sample_unit.uce
Normal file
16
site/doc/examples/sample_unit.uce
Normal 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);
|
||||
}
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -20,4 +20,4 @@ Returns a version of the input string where special HTML characters are replaced
|
||||
- `"` becomes `"`
|
||||
|
||||
:example
|
||||
print("html_escape example\n");
|
||||
print(html_escape("<b>Tom & Jerry</b>"), "\n");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
@ -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");
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user