refactor: rename DTree to DValue

This commit is contained in:
udo
2026-06-12 11:05:52 +00:00
parent 941f5aea08
commit 7066da3cde
157 changed files with 1203 additions and 1074 deletions
+8 -8
View File
@@ -2,14 +2,14 @@ Types
0_Request
array_merge
0_DTree
dtree_filter
dtree_group_by
dtree_keys
dtree_map
dtree_omit
dtree_pick
dtree_values
0_DValue
dv_filter
dv_group_by
dv_keys
dv_map
dv_omit
dv_pick
dv_values
each
get_by_path
has
@@ -1,8 +1,8 @@
:title
DTree
DValue
:sig
DTree
DValue
:see
>types
@@ -10,23 +10,23 @@ get_by_path
json_decode
:content
`DTree` is UCE's general-purpose structured value type. It is the runtime's default container for nested data such as configuration trees, call payloads, decoded JSON, connection state, and metadata returned by runtime helpers.
`DValue` is UCE's general-purpose structured value type. It is the runtime's default container for nested data such as configuration trees, call payloads, decoded JSON, connection state, and metadata returned by runtime helpers.
## Value Kinds
`DTree` can hold:
`DValue` can hold:
- `String`
- `f64`
- `bool`
- pointer values
- nested child `DTree` values in a map-shaped container
- nested child `DValue` values in a map-shaped container
Map-shaped `DTree` values can also represent list-like data when their keys are numeric strings in sequence.
Map-shaped `DValue` values can also represent list-like data when their keys are numeric strings in sequence.
## Where It Appears
You will encounter `DTree` throughout the runtime, especially in:
You will encounter `DValue` throughout the runtime, especially in:
- `context.cfg`
- `context.props`
@@ -47,7 +47,7 @@ You will encounter `DTree` throughout the runtime, especially in:
- `.to_bool(default)` performs best-effort boolean conversion.
- `.to_stringmap()` converts a map-shaped tree into `StringMap`.
All read accessors are `const` and never modify the tree; they work directly on `const DTree&` values such as `each()` callback parameters. Every `to_*` conversion takes an optional default that is returned when the value is missing or cannot be converted — see the individual pages (`to_string`, `to_s64`, `to_u64`, `to_f64`, `to_bool`) for the exact rules:
All read accessors are `const` and never modify the tree; they work directly on `const DValue&` values such as `each()` callback parameters. Every `to_*` conversion takes an optional default that is returned when the value is missing or cannot be converted — see the individual pages (`to_string`, `to_s64`, `to_u64`, `to_f64`, `to_bool`) for the exact rules:
```cpp
String title = context.props["title"].to_string("Untitled");
@@ -56,7 +56,7 @@ s64 page_size = context.cfg.get_by_path("app/page_size").to_s64(25);
`operator[]` creates missing entries, just like `std::map`. `.has()` and `.key()` are the non-mutating lookup helpers, and `.get_by_path()` is the non-creating traversal helper.
`json_decode()` currently stores JSON numbers as string-valued `DTree` nodes, so typed numeric conversion is the normal way to consume those values.
`json_decode()` currently stores JSON numbers as string-valued `DValue` nodes, so typed numeric conversion is the normal way to consume those values.
References are dereferenced automatically in most normal reads.
@@ -100,9 +100,9 @@ Useful inspection helpers include:
## each()
`each(std::function<void (const DTree& t, String key)> f)` iterates over the current tree value (see the `each` page for details).
`each(std::function<void (const DValue& t, String key)> f)` iterates over the current tree value (see the `each` page for details).
For map-shaped `DTree` values, the callback runs once per child entry and receives:
For map-shaped `DValue` values, the callback runs once per child entry and receives:
- `t` as the child value, by const reference (no copy)
- `key` as the child key
@@ -113,7 +113,7 @@ For non-map values, `each()` still invokes the callback once:
- `key` is an empty string
```cpp
context.connection["items"].each([&](const DTree& item, String key) {
context.connection["items"].each([&](const DValue& item, String key) {
print(key, ": ", item.to_string(), "\n");
});
```
@@ -127,7 +127,7 @@ u64 compiled_mtime = unit_info("test/hello.uce")["compiled_mtime"].to_u64();
bool dark_mode = context.props["dark_mode"].to_bool();
if(DTree* user = payload.key("user")) {
if(DValue* user = payload.key("user")) {
print(user->to_json());
}
+9 -9
View File
@@ -24,7 +24,7 @@ ws_message
ws_connection_id
ws_connections
ws_send
0_DTree
0_DValue
StringMap
UploadedFile
@@ -120,7 +120,7 @@ Raw request body. For WebSocket handlers, this is the current message payload.
Use this for JSON APIs:
```cpp
DTree body = json_decode(context.in);
DValue body = json_decode(context.in);
```
### `context.uploaded_files`
@@ -165,7 +165,7 @@ Related helpers:
### `context.call`
Type: `DTree`
Type: `DValue`
General request-local scratch/configuration tree. It is shared by the page, components, and unit calls participating in the current request. Use it for app-level request state, fragments, router results, page type, page title, and other values that need to be read by later components.
@@ -181,7 +181,7 @@ Prefer clear top-level names when state is app-wide (`route`, `fragments`) and n
### `context.cfg`
Type: `DTree`
Type: `DValue`
Request-local structured configuration. The runtime does not fill this with application config by default; application code may assign it during boot/setup:
@@ -199,19 +199,19 @@ String site_name = context.cfg.get_by_path("site/name").to_string();
### `context.props`
Type: `DTree`
Type: `DValue`
Invocation-local props for `component()`, `component_render()`, and macro-style `unit_call()` entrypoints. During a component call, the runtime temporarily replaces `context.props` with the props passed to that component and restores the previous value after the call returns.
```cpp
DTree props;
DValue props;
props["title"] = "Dashboard";
print(component("components/card", props, context));
```
### `context.connection`
Type: `DTree`
Type: `DValue`
WebSocket connection-local state. Mutations persist across `WS(Request& context)` calls for the same socket.
@@ -394,7 +394,7 @@ RENDER(Request& context)
RENDER(Request& context)
{
context.header["Content-Type"] = "application/json";
DTree response;
DValue response;
response["ok"].set_bool(true);
print(json_encode(response));
}
@@ -413,7 +413,7 @@ RENDER(Request& context)
### Component props
```cpp
DTree props;
DValue props;
props["title"] = "Welcome";
print(component("components/card", props, context));
```
+2 -2
View File
@@ -46,12 +46,12 @@ Inside the handler, the usual `Request& context` fields are available:
CLI responses default to `text/plain; charset=utf-8`, but the handler may set headers and status explicitly.
Use `cli_input(context)` to merge query parameters, form parameters, and JSON POST fields into one `DTree`.
Use `cli_input(context)` to merge query parameters, form parameters, and JSON POST fields into one `DValue`.
```cpp
CLI(Request& context)
{
DTree input = cli_input(context);
DValue input = cli_input(context);
String action = first(input["action"].to_string(), "ping");
if(action == "ping")
{
+1 -1
View File
@@ -20,7 +20,7 @@ UCE reassembles fragmented messages before calling `WS(Request& context)`. Text
## Connection State
`context.connection` is a broker-owned `DTree` for the current socket. It starts empty for a new client and persists across later `WS(Request& context)` calls on that same connection.
`context.connection` is a broker-owned `DValue` for the current socket. It starts empty for a new client and persists across later `WS(Request& context)` calls on that same connection.
## Message Data
+3 -3
View File
@@ -1,6 +1,6 @@
:sig
StringMap array_merge(StringMap a, StringMap b)
DTree array_merge(DTree a, DTree b)
DValue array_merge(DValue a, DValue b)
:params
a : left-hand source map or tree
@@ -9,7 +9,7 @@ return value : merged result
:see
>types
0_DTree
0_DValue
StringMap
json_decode
@@ -18,7 +18,7 @@ Merges two maps or trees using PHP-like merge behavior.
For `StringMap`, keys from `b` overwrite keys from `a`.
For `DTree`, string keys from `b` overwrite keys from `a`. Numeric keys are appended and reindexed when either side behaves like a list.
For `DValue`, string keys from `b` overwrite keys from `a`. Numeric keys are appended and reindexed when either side behaves like a list.
This helper is the closest UCE equivalent to PHP `array_merge()` for common request, config, and JSON-shaped data.
+1 -1
View File
@@ -21,4 +21,4 @@ CLI(Request& context)
}
```
For commands that need multiple values or typed reads, prefer calling `cli_input(context)` once and reading the returned `DTree` directly.
For commands that need multiple values or typed reads, prefer calling `cli_input(context)` once and reading the returned `DValue` directly.
+4 -4
View File
@@ -2,17 +2,17 @@
cli_input
:sig
DTree cli_input(Request& context)
DValue cli_input(Request& context)
:see
>1_CLI
>json_decode
>DTree
>DValue
:content
Returns a structured parameter tree for a `CLI(Request& context)` invocation.
`cli_input()` merges simple command inputs into one `DTree`:
`cli_input()` merges simple command inputs into one `DValue`:
1. query parameters from `context.get`
2. form parameters from `context.post`
@@ -25,7 +25,7 @@ If the JSON body is a scalar or array instead of an object, the decoded value is
```cpp
CLI(Request& context)
{
DTree input = cli_input(context);
DValue input = cli_input(context);
String action = first(input["action"].to_string(), "help");
if(action == "echo")
+3 -3
View File
@@ -12,7 +12,7 @@ unit_render
3_C++ Preprocessor
map
filter
dtree_filter
dv_filter
:content
UCE is server-first C++ with a small template preprocessor. It does not try to be React, but several concepts map cleanly.
@@ -47,8 +47,8 @@ The function library includes small collection helpers for common route/menu/car
```cpp
auto visible = filter(routes, [](String route) { return(route != "admin"); });
auto labels = map(visible, [](String route) { return(to_upper(route)); });
DTree app_items = dtree_filter(menu, [](DTree item, String key) { return(item["section"].to_string() == "app"); });
DTree by_section = dtree_group_by(menu, [](DTree item, String key) { return(item["section"].to_string()); });
DValue app_items = dv_filter(menu, [](DValue item, String key) { return(item["section"].to_string() == "app"); });
DValue by_section = dv_group_by(menu, [](DValue item, String key) { return(item["section"].to_string()); });
```
Use these when the transformation communicates intent. Prefer explicit loops when side effects or multi-step validation are the main concern.
+4 -4
View File
@@ -1,5 +1,5 @@
:sig
String component(String name, [DTree props], [Request& context])
String component(String name, [DValue props], [Request& context])
:see
>ob
@@ -37,7 +37,7 @@ When a component unit defines `ONCE(Request& context)`, the runtime calls that h
Default component handler:
```cpp
DTree props;
DValue props;
props["title"] = "Status";
<><?: component("workspace/panel", props, context) ?></>
@@ -46,7 +46,7 @@ props["title"] = "Status";
Named component handler:
```cpp
DTree props;
DValue props;
props["title"] = "System";
props["body"] = "Healthy";
@@ -76,7 +76,7 @@ COMPONENT:BODY(Request& context)
Preparing props in C++ before rendering:
```cpp
DTree props;
DValue props;
props["items"][0] = "alpha";
props["items"][1] = "beta";
props["items"][2] = "gamma";
+2 -2
View File
@@ -1,5 +1,5 @@
:sig
void component_render(String name, [DTree props], [Request& context])
void component_render(String name, [DValue props], [Request& context])
:see
>ob
@@ -24,7 +24,7 @@ Use `component_render()` when you want to write component output directly from C
## Example
```cpp
DTree props;
DValue props;
props["body"] = "Hello";
component_render("components/card:BODY", props, context);
@@ -1,12 +1,12 @@
:title
dtree_filter
dv_filter
:sig
DTree dtree_filter(DTree tree, function<bool (DTree, String)> f)
DValue dv_filter(DValue tree, function<bool (DValue, String)> f)
:see
StringList
0_DTree
0_DValue
filter
:content
@@ -15,7 +15,7 @@ Keeps children for which f returns true. List-like input stays list-like.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree visible = dtree_filter(items, [](DTree item, String key) { return(item["hidden"].to_bool() == false); });
DValue visible = dv_filter(items, [](DValue item, String key) { return(item["hidden"].to_bool() == false); });
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,12 +1,12 @@
:title
dtree_group_by
dv_group_by
:sig
DTree dtree_group_by(DTree tree, function<String (DTree, String)> f)
DValue dv_group_by(DValue tree, function<String (DValue, String)> f)
:see
StringList
0_DTree
0_DValue
filter
:content
@@ -15,7 +15,7 @@ Groups children into list-like buckets by the string returned from f.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree by_section = dtree_group_by(menu, [](DTree item, String key) { return(item["section"].to_string()); });
DValue by_section = dv_group_by(menu, [](DValue item, String key) { return(item["section"].to_string()); });
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,21 +1,21 @@
:title
dtree_pick
dv_keys
:sig
DTree dtree_pick(DTree tree, StringList keys)
StringList dv_keys(DValue tree)
:see
StringList
0_DTree
0_DValue
filter
:content
Copies only selected keys from a DTree map.
Returns map keys from a DValue. Scalar values produce an empty list.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree public_user = dtree_pick(user, {"name", "avatar"});
StringList keys = dv_keys(context.cfg["menu"]);
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,12 +1,12 @@
:title
dtree_map
dv_map
:sig
DTree dtree_map(DTree tree, function<DTree (DTree, String)> f)
DValue dv_map(DValue tree, function<DValue (DValue, String)> f)
:see
StringList
0_DTree
0_DValue
filter
:content
@@ -15,7 +15,7 @@ Transforms each child. List-like input stays list-like; map input keeps keys.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree titles = dtree_map(items, [](DTree item, String key) { DTree out; out = item["title"].to_string(); return(out); });
DValue titles = dv_map(items, [](DValue item, String key) { DValue out; out = item["title"].to_string(); return(out); });
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,21 +1,21 @@
:title
dtree_omit
dv_omit
:sig
DTree dtree_omit(DTree tree, StringList keys)
DValue dv_omit(DValue tree, StringList keys)
:see
StringList
0_DTree
0_DValue
filter
:content
Copies a DTree map except for selected keys.
Copies a DValue map except for selected keys.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree safe_user = dtree_omit(user, {"password_hash"});
DValue safe_user = dv_omit(user, {"password_hash"});
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,21 +1,21 @@
:title
dtree_keys
dv_pick
:sig
StringList dtree_keys(DTree tree)
DValue dv_pick(DValue tree, StringList keys)
:see
StringList
0_DTree
0_DValue
filter
:content
Returns map keys from a DTree. Scalar values produce an empty list.
Copies only selected keys from a DValue map.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
StringList keys = dtree_keys(context.cfg["menu"]);
DValue public_user = dv_pick(user, {"name", "avatar"});
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
@@ -1,21 +1,21 @@
:title
dtree_values
dv_values
:sig
DTree dtree_values(DTree tree)
DValue dv_values(DValue tree)
:see
StringList
0_DTree
0_DValue
filter
:content
Returns child values as a list-like DTree.
Returns child values as a list-like DValue.
These helpers are intentionally small data-shaping conveniences for render code, routers, and configuration trees. They are useful when porting habits from React/Next/Remix code where lists of routes, navigation items, cards, or records are transformed close to the rendering boundary.
```cpp
DTree menu_items = dtree_values(context.cfg["menu"]);
DValue menu_items = dv_values(context.cfg["menu"]);
```
Prefer these helpers over open-coded loops when the transformation itself is the important part of the code. Use an explicit loop when mutation, error handling, or side effects are the main concern.
+9 -9
View File
@@ -1,5 +1,5 @@
:sig
void DTree::each(function<void (const DTree& item, String key)> f) const
void DValue::each(function<void (const DValue& item, String key)> f) const
:params
f : callback invoked per child with the child node and its key
@@ -7,26 +7,26 @@ return value : none
:see
>types
0_DTree
dtree_map
dtree_filter
dtree_keys
0_DValue
dv_map
dv_filter
dv_keys
is_list
:content
Iterates a `DTree`. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Iterates a `DValue`. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
For map-shaped nodes the callback runs once per child, in key order, receiving the child and its key. For scalar nodes it runs exactly once with the node itself and an empty key.
The callback receives the child as `const DTree&` — no copy is made, and all read accessors (`to_string()`, `to_s64()`, `get_by_path()`, ...) work on it directly:
The callback receives the child as `const DValue&` — no copy is made, and all read accessors (`to_string()`, `to_s64()`, `get_by_path()`, ...) work on it directly:
```cpp
rows.each([&](const DTree& row, String key) {
rows.each([&](const DValue& row, String key) {
out("<li>", html_escape(row.get_by_path("title").to_string("Untitled")), "</li>");
});
```
Declaring the callback parameter as plain `DTree` also works but deep-copies every child; prefer `const DTree&`. To transform or filter into a new tree, use `dtree_map()` / `dtree_filter()` instead of mutating inside the callback.
Declaring the callback parameter as plain `DValue` also works but deep-copies every child; prefer `const DValue&`. To transform or filter into a new tree, use `dv_map()` / `dv_filter()` instead of mutating inside the callback.
List-shaped trees (see `is_list`) iterate in numeric index order, matching `json_encode()` and the other serializers. Keyed maps iterate in string key order.
+1 -1
View File
@@ -14,7 +14,7 @@ page_runtime_error : UCE page rendered (status 500) after a recovered fault or u
:see
>runtime
0_Request
0_DTree
0_DValue
set_status
:content
+5 -5
View File
@@ -1,13 +1,13 @@
:sig
DTree DTree::get_by_path(String path, String delim = "/") const
DValue DValue::get_by_path(String path, String delim = "/") const
:params
path : slash-delimited path to traverse
delim : optional path separator
return value : the resolved child node, or an empty `DTree` when the path cannot be followed
return value : the resolved child node, or an empty `DValue` when the path cannot be followed
:see
0_DTree
0_DValue
0_Request
>types
json_decode
@@ -15,9 +15,9 @@ has
to_string
:content
Traverses a nested `DTree` without creating missing keys. This is a read accessor: it is `const` and never modifies the tree, unlike `operator[]`, which creates missing entries.
Traverses a nested `DValue` without creating missing keys. This is a read accessor: it is `const` and never modifies the tree, unlike `operator[]`, which creates missing entries.
Empty path segments are ignored, so leading and trailing `/` characters are harmless. If any intermediate node is not a map or a segment is missing, `get_by_path()` returns an empty `DTree`.
Empty path segments are ignored, so leading and trailing `/` characters are harmless. If any intermediate node is not a map or a segment is missing, `get_by_path()` returns an empty `DValue`.
A missing path therefore reads like an empty value — combine it with the `to_*` default arguments to express a fallback in one call:
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
bool DTree::has(String s) const
bool DValue::has(String s) const
:params
s : child key to test
@@ -7,13 +7,13 @@ return value : true when the node is map-shaped and contains the key
:see
>types
0_DTree
0_DValue
get_by_path
each
is_array
:content
Tests whether a map-shaped `DTree` contains a child key, without creating it. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Tests whether a map-shaped `DValue` contains a child key, without creating it. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Returns `false` for scalar nodes and for missing keys.
+5 -5
View File
@@ -1,26 +1,26 @@
:sig
bool DTree::is_array() const
bool DValue::is_array() const
:params
return value : true when the node is map-shaped
:see
>types
0_DTree
0_DValue
is_list
has
each
:content
Tests whether a `DTree` node is map-shaped, i.e. holds nested child values rather than a scalar. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Tests whether a `DValue` node is map-shaped, i.e. holds nested child values rather than a scalar. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
`is_array()` is true for both list-like and keyed containers; use `is_list()` to distinguish the two:
```cpp
DTree rows = sqlite_query(db, "select * from notes");
DValue rows = sqlite_query(db, "select * from notes");
if(rows.is_array())
{
rows.each([&](const DTree& row, String key) {
rows.each([&](const DValue& row, String key) {
// ...
});
}
+6 -6
View File
@@ -1,24 +1,24 @@
:sig
bool DTree::is_list() const
bool DValue::is_list() const
:params
return value : true when the node is a sequential, numerically indexed container
:see
>types
0_DTree
0_DValue
is_array
push
each
dtree_values
dv_values
:content
Tests whether a map-shaped `DTree` represents a list: its keys are the numeric strings `"0"`, `"1"`, `"2"`, ... in unbroken sequence. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Tests whether a map-shaped `DValue` represents a list: its keys are the numeric strings `"0"`, `"1"`, `"2"`, ... in unbroken sequence. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Containers built with `push()` are lists. An empty container counts as a list when it was created with `set_array()` or `push()`; a keyed map (or a map with gaps in its numeric keys) is `is_array()` but not `is_list()`.
```cpp
DTree items;
DValue items;
items.push(first_item);
items.push(second_item);
// items.is_list() == true
@@ -27,7 +27,7 @@ items["custom"] = "x";
// items.is_list() == false, items.is_array() == true
```
`dtree_map()` and `dtree_filter()` use this distinction to decide whether results re-index from zero or keep their original keys.
`dv_map()` and `dv_filter()` use this distinction to decide whether results re-index from zero or keep their original keys.
## Related Concepts
+9 -9
View File
@@ -1,21 +1,21 @@
:sig
DTree json_decode(String s)
DValue json_decode(String s)
:params
s : string containing JSON data
return value : a DTree object containing the deserialized JSON data
return value : a DValue object containing the deserialized JSON data
:see
0_DTree
0_DValue
json_encode
to_bool
to_f64
to_u64
:content
Deserializes `s` into a `DTree` structure.
Deserializes `s` into a `DValue` structure.
The returned structure is usually consumed through `DTree` accessors such as:
The returned structure is usually consumed through `DValue` accessors such as:
- `tree["key"].to_string()`
- `tree["count"].to_u64()`
@@ -23,10 +23,10 @@ The returned structure is usually consumed through `DTree` accessors such as:
Current runtime behavior:
- JSON objects and arrays become map-shaped `DTree` values.
- JSON booleans become native `bool` `DTree` values.
- JSON strings become native `String` `DTree` values.
- JSON numbers currently deserialize as string-valued `DTree` nodes, so typed conversions such as `to_f64()` and `to_u64()` are the normal way to read numeric content.
- JSON objects and arrays become map-shaped `DValue` values.
- JSON booleans become native `bool` `DValue` values.
- JSON strings become native `String` `DValue` values.
- 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.
Related:
+5 -5
View File
@@ -1,25 +1,25 @@
:sig
String json_encode(String s)
String json_encode(DTree t)
String json_encode(DValue t)
:params
s : string to encode as a JSON string literal
t : DTree object to be serialized
t : DValue object to be serialized
return value : string containing the JSON result
:see
>types
json_decode
0_DTree
0_DValue
String
html_escape
:content
Serializes either a `String` or a `DTree` into JSON notation.
Serializes either a `String` or a `DValue` into JSON notation.
When passed a `String`, `json_encode()` returns a quoted and escaped JSON string literal.
When passed a `DTree`, scalar values are serialized directly and nested map values are emitted as JSON objects.
When passed a `DValue`, scalar values are serialized directly and nested map values are emitted as JSON objects.
Related:
+1 -1
View File
@@ -6,7 +6,7 @@ bool list_every(StringList items, function<bool (String)> f)
:see
StringList
0_DTree
0_DValue
filter
:content
+1 -1
View File
@@ -6,7 +6,7 @@ String list_find(StringList items, function<bool (String)> f, String fallback =
:see
StringList
0_DTree
0_DValue
filter
:content
+1 -1
View File
@@ -6,7 +6,7 @@ bool list_some(StringList items, function<bool (String)> f)
:see
StringList
0_DTree
0_DValue
filter
:content
+1 -1
View File
@@ -6,7 +6,7 @@ StringList list_sort(StringList items)
:see
StringList
0_DTree
0_DValue
filter
:content
+1 -1
View File
@@ -6,7 +6,7 @@ StringList list_unique(StringList items)
:see
StringList
0_DTree
0_DValue
filter
:content
+1 -1
View File
@@ -14,7 +14,7 @@ return value : a new list containing the transformed values
>string
filter
StringList
0_DTree
0_DValue
:content
Returns a new list by calling `f` for each item in `items`.
+7 -7
View File
@@ -1,21 +1,21 @@
:sig
DTree markdown_to_ast(String src)
DTree markdown_to_ast(String src, DTree options)
DValue markdown_to_ast(String src)
DValue markdown_to_ast(String src, DValue options)
:params
src : markdown source text
options : optional markdown options tree
return value : a `DTree` document AST
return value : a `DValue` document AST
:see
markdown_to_html
component
component_render
json_encode
0_DTree
0_DValue
:content
Parses Markdown source into a structured `DTree` document tree.
Parses Markdown source into a structured `DValue` document tree.
The parser targets a practical GitHub-flavored subset by default:
@@ -67,8 +67,8 @@ Common inline nodes:
Example:
```uce
DTree options = json_decode("{\"components\":{\":::warning\":\"components/markdown/warning\"}}");
DTree ast = markdown_to_ast(file_get_contents("README.md"), options);
DValue options = json_decode("{\"components\":{\":::warning\":\"components/markdown/warning\"}}");
DValue ast = markdown_to_ast(file_get_contents("README.md"), options);
print(json_encode(ast));
```
+2 -2
View File
@@ -1,6 +1,6 @@
:sig
String markdown_to_html(String src)
String markdown_to_html(String src, DTree options)
String markdown_to_html(String src, DValue options)
:params
src : markdown source text
@@ -26,7 +26,7 @@ By default the function aims at a practical GitHub-flavored Markdown target, inc
Example:
```uce
DTree options;
DValue options;
options["components"][":::warning"] = "components/markdown/warning";
options["components"]["node.code_block"] = "components/markdown/code_block";
String html = markdown_to_html(file_get_contents("guide.md"), options);
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
DTree mysql_query(MySQL* m, String q, StringMap params)
DValue mysql_query(MySQL* m, String q, StringMap params)
:params
m : pointer to an active MySQL connection struct
@@ -18,13 +18,13 @@ Executes a MySQL query and returns the resulting data, if any.
```cpp
StringMap params;
params["email"] = "ada@example.test";
DTree rows = mysql_query(m,
DValue rows = mysql_query(m,
"select id, email from users where email = :email",
params
);
```
The result is returned as a `DTree`, which makes it easy to iterate through rows and read fields with the usual `DTree` accessors.
The result is returned as a `DValue`, which makes it easy to iterate through rows and read fields with the usual `DValue` accessors.
Related:
+5 -5
View File
@@ -1,12 +1,12 @@
:sig
DTree regex_search(String pattern, String subject)
DTree regex_search(String pattern, String subject, String flags)
DValue regex_search(String pattern, String subject)
DValue regex_search(String pattern, String subject, String flags)
:params
pattern : PCRE2 regular expression pattern
subject : string to search
flags : optional regex flags
return value : a DTree describing the first match
return value : a DValue describing the first match
:see
>regex
@@ -14,7 +14,7 @@ regex_match
regex_search_all
regex_replace
regex_split
0_DTree
0_DValue
:content
Searches `subject` for the first occurrence of `pattern` and returns structured match data.
@@ -22,7 +22,7 @@ Searches `subject` for the first occurrence of `pattern` and returns structured
Example:
```uce
DTree match = regex_search(
DValue match = regex_search(
"(?<user>[A-Za-z0-9._%+-]+)@(?<host>[A-Za-z0-9.-]+)",
"Contact ops@example.test"
);
+6 -6
View File
@@ -1,12 +1,12 @@
:sig
DTree regex_search_all(String pattern, String subject)
DTree regex_search_all(String pattern, String subject, String flags)
DValue regex_search_all(String pattern, String subject)
DValue regex_search_all(String pattern, String subject, String flags)
:params
pattern : PCRE2 regular expression pattern
subject : string to search
flags : optional regex flags
return value : a DTree containing all non-overlapping matches
return value : a DValue containing all non-overlapping matches
:see
>regex
@@ -14,7 +14,7 @@ regex_match
regex_search
regex_replace
regex_split
0_DTree
0_DValue
:content
Finds every non-overlapping match of `pattern` in `subject`.
@@ -22,9 +22,9 @@ Finds every non-overlapping match of `pattern` in `subject`.
Example:
```uce
DTree tags = regex_search_all("#(?<tag>[A-Za-z0-9_]+)", "Ship #uce and #docs");
DValue tags = regex_search_all("#(?<tag>[A-Za-z0-9_]+)", "Ship #uce and #docs");
tags["matches"].each([](DTree match, String key) {
tags["matches"].each([](DValue match, String key) {
print(match["named"]["tag"].to_string(), "\n");
});
```
+2 -2
View File
@@ -2,7 +2,7 @@
request_query_route
:sig
DTree request_query_route(Request& context, String default_path = "index")
DValue request_query_route(Request& context, String default_path = "index")
:see
request_query_path
@@ -21,7 +21,7 @@ Fields:
- `valid`: boolean; true when `l_path` is safe
```cpp
DTree route = request_query_route(context);
DValue route = request_query_route(context);
if(route["valid"].to_bool())
print("route=", route["l_path"].to_string());
```
+7 -7
View File
@@ -1,12 +1,12 @@
:sig
DTree sqlite_query(SQLite* db, String q)
DTree sqlite_query(SQLite* db, String q, StringMap params)
DValue sqlite_query(SQLite* db, String q)
DValue sqlite_query(SQLite* db, String q, StringMap params)
:params
db : pointer to an active SQLite connection
q : SQL statement
params : optional named parameter map
return value : list of result rows as a DTree
return value : list of result rows as a DValue
:see
>sqlite
@@ -14,10 +14,10 @@ sqlite_connect
sqlite_error
sqlite_insert_id
sqlite_affected_rows
0_DTree
0_DValue
:content
Executes one SQLite statement and returns result rows as a `DTree` array. Multi-statement SQL strings are rejected so migrations cannot silently run only their first statement.
Executes one SQLite statement and returns result rows as a `DValue` array. Multi-statement SQL strings are rejected so migrations cannot silently run only their first statement.
Use named parameters with `:name` placeholders only. Positional `?` placeholders and SQLite's other named marker forms (`@name`, `$name`) are rejected so UCE SQLite queries use the same placeholder style as the MySQL helper. UCE binds parameters with SQLite prepared statements; it does not substitute values into the SQL string.
@@ -26,12 +26,12 @@ SQLite* db = sqlite_connect("/tmp/app.sqlite");
StringMap params;
params["email"] = "ada@example.test";
DTree rows = sqlite_query(db,
DValue rows = sqlite_query(db,
"select id, email from users where email = :email",
params
);
```
Result rows are objects keyed by column name. SQLite integer, float, text, blob, and null values are converted to DTree values. Blob values are returned as byte strings.
Result rows are objects keyed by column name. SQLite integer, float, text, blob, and null values are converted to DValue values. Blob values are returned as byte strings.
For statements that do not return rows, inspect `sqlite_affected_rows()` or `sqlite_insert_id()` after the call.
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
bool DTree::to_bool(bool default_value = false) const
bool DValue::to_bool(bool default_value = false) const
:params
default_value : returned when the value is missing or empty
@@ -7,14 +7,14 @@ return value : the value as a boolean, or `default_value`
:see
>types
0_DTree
0_DValue
json_decode
to_f64
to_u64
to_string
:content
Reads a `DTree` value as a boolean. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Reads a `DValue` value as a boolean. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
String values such as `true`, `yes`, `on`, and `1` read as true. Values such as `false`, `no`, `off`, `0`, and `null` read as false. Numeric values read as true when non-zero.
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
f64 DTree::to_f64(f64 default_value = 0) const
f64 DValue::to_f64(f64 default_value = 0) const
:params
default_value : returned when the value is missing or cannot be parsed as a number
@@ -7,7 +7,7 @@ return value : the value as a floating-point number, or `default_value`
:see
>types
0_DTree
0_DValue
json_decode
float_val
to_bool
@@ -15,7 +15,7 @@ to_s64
to_u64
:content
Reads a `DTree` value as a floating-point number. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Reads a `DValue` value as a floating-point number. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
String values are trimmed and parsed permissively: numeric forms and the boolean words understood by `to_bool()` both convert. Boolean values become `1.0` or `0.0`.
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
String DTree::to_json(char quote_char = '"') const
String DValue::to_json(char quote_char = '"') const
:params
quote_char : quote character used around string output
@@ -7,13 +7,13 @@ return value : the scalar as a single JSON token
:see
>types
0_DTree
0_DValue
json_encode
json_decode
to_string
:content
Renders a single scalar `DTree` value as a JSON token. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Renders a single scalar `DValue` value as a JSON token. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Strings are escaped and quoted, numbers render as numeric literals, and booleans render as `true` / `false`.
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
s64 DTree::to_s64(s64 default_value = 0) const
s64 DValue::to_s64(s64 default_value = 0) const
:params
default_value : returned when the value is missing or cannot be parsed as a number
@@ -7,14 +7,14 @@ return value : the value as a signed 64-bit integer, or `default_value`
:see
>types
0_DTree
0_DValue
to_u64
to_f64
to_bool
to_string
:content
Reads a `DTree` value as a signed integer. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Reads a `DValue` value as a signed integer. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
String values are trimmed and parsed permissively: plain integers, floating-point forms (truncated toward zero), and the boolean words understood by `to_bool()` (`yes` reads as `1`) all convert. Results outside the `s64` range clamp to the range boundaries. Boolean values become `1` or `0`.
+3 -3
View File
@@ -1,5 +1,5 @@
:sig
String DTree::to_string(String default_value = "") const
String DValue::to_string(String default_value = "") const
:params
default_value : returned when the node holds no usable text
@@ -7,7 +7,7 @@ return value : the scalar content as text, or `default_value`
:see
>types
0_DTree
0_DValue
to_s64
to_f64
to_bool
@@ -15,7 +15,7 @@ to_json
get_by_path
:content
Reads a `DTree` value as text. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Reads a `DValue` value as text. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
`default_value` is returned when the value is missing or not text-convertible:
+6 -6
View File
@@ -1,19 +1,19 @@
:sig
StringMap DTree::to_stringmap() const
StringMap DValue::to_stringmap() const
:params
return value : a flat `StringMap` projection of the node
:see
>types
0_DTree
0_DValue
StringMap
to_string
dtree_keys
dtree_values
dv_keys
dv_values
:content
Converts a `DTree` into a flat `StringMap`. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Converts a `DValue` into a flat `StringMap`. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
- Map-shaped nodes produce one entry per child, with each child read via `to_string()`. Nested maps flatten to empty strings — this is a one-level projection, not a serializer.
- A non-empty scalar produces a single `"value"` entry holding the scalar.
@@ -25,7 +25,7 @@ Use this when handing request- or config-shaped data to APIs that take `StringMa
```cpp
StringMap params = context.props["filters"].to_stringmap();
DTree rows = sqlite_query(db, "select * from notes where author = :author", params);
DValue rows = sqlite_query(db, "select * from notes where author = :author", params);
```
For a faithful representation of nested data, use `json_encode()` instead.
+4 -4
View File
@@ -1,5 +1,5 @@
:sig
u64 DTree::to_u64(u64 default_value = 0) const
u64 DValue::to_u64(u64 default_value = 0) const
:params
default_value : returned when the value is missing or cannot be parsed as a number
@@ -7,7 +7,7 @@ return value : the value as an unsigned 64-bit integer, or `default_value`
:see
>types
0_DTree
0_DValue
json_decode
int_val
to_bool
@@ -15,7 +15,7 @@ to_s64
to_f64
:content
Reads a `DTree` value as an unsigned integer. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
Reads a `DValue` value as an unsigned integer. This is a read accessor: it is `const`, never creates or modifies nodes, and dereferences internal references automatically.
String values are trimmed and parsed permissively, like `to_s64()`. Boolean values become `1` or `0`. Negative values clamp to `0`, and results above the `u64` range clamp to the maximum.
@@ -34,7 +34,7 @@ u64 limit = context.get["limit"].to_u64(50);
u64 owner_id = row.get_by_path("owner/id").to_u64();
```
Use this for counts, identifiers, limits, timestamps, and other non-negative numeric values stored inside a `DTree`.
Use this for counts, identifiers, limits, timestamps, and other non-negative numeric values stored inside a `DValue`.
## Related Concepts
+7 -7
View File
@@ -1,11 +1,11 @@
:sig
DTree* unit_call(String file_name, String function_name, DTree* call_param = null)
DValue* unit_call(String file_name, String function_name, DValue* call_param = null)
:params
file_name : UCE file to load and execute
function_name : name of the function to invoke
call_param : optional, call parameter
return value : DTree* returned from function
return value : DValue* returned from function
:see
>ob
@@ -20,7 +20,7 @@ Calls an exported function inside another UCE file.
Use `unit_call()` when you need structured data exchange between units rather than rendered HTML output.
The callee must expose an `EXPORT` function whose name matches `function_name`. Arguments are passed through `call_param`, and the return value is a `DTree*` owned by the callee.
The callee must expose an `EXPORT` function whose name matches `function_name`. Arguments are passed through `call_param`, and the return value is a `DValue*` owned by the callee.
`unit_call()` also understands the request-bound UCE entrypoint names:
@@ -31,7 +31,7 @@ The callee must expose an `EXPORT` function whose name matches `function_name`.
- `ONCE`
- `INIT`
When `function_name` matches one of those macro-style entrypoints, `unit_call()` does not look for a plain `EXPORT DTree* ...` function. Instead, it translates the name to the generated C++ symbol, uses the current `Request` context, and passes `call_param` into `context.props`, matching the normal component invocation model.
When `function_name` matches one of those macro-style entrypoints, `unit_call()` does not look for a plain `EXPORT DValue* ...` function. Instead, it translates the name to the generated C++ symbol, uses the current `Request` context, and passes `call_param` into `context.props`, matching the normal component invocation model.
For `RENDER...` and `COMPONENT...`, the unit's `ONCE(Request& context)` hook is still honored automatically before the selected handler runs.
@@ -39,7 +39,7 @@ Example:
```cpp
// export a function
EXPORT DTree* test_func(DTree* call_param)
EXPORT DValue* test_func(DValue* call_param)
{
print("HELLO FROM TEST FUNCTION");
return(0);
@@ -52,7 +52,7 @@ unit_call("call_file_funcs.uce", "test_func");
Calling a named component handler through `unit_call()`:
```cpp
DTree props;
DValue props;
props["title"] = "Diagnostics";
props["body"] = "Ready";
@@ -62,7 +62,7 @@ unit_call("components/card.uce", "COMPONENT:BODY", &props);
Calling a page render handler through `unit_call()`:
```cpp
DTree props;
DValue props;
props["section"] = "summary";
unit_call("reports/summary.uce", "RENDER", &props);
+1 -1
View File
@@ -1,5 +1,5 @@
:sig
DTree unit_info(String path = "")
DValue unit_info(String path = "")
:params
path : optional UCE unit path. If empty, uses the current executing unit.
+2 -2
View File
@@ -1,7 +1,7 @@
:sig
String var_dump(StringMap t, String prefix = "", String postfix = "\n")
String var_dump(StringList t, String prefix = "", String postfix = "\n")
String var_dump(DTree t, String prefix = "", String postfix = "\n")
String var_dump(DValue t, String prefix = "", String postfix = "\n")
:params
t : object to be dumped into a string
@@ -9,7 +9,7 @@ return value : string containing a human-friendly representation of 't'
:see
>types
0_DTree
0_DValue
StringMap
json_encode
print
+6 -6
View File
@@ -1,19 +1,19 @@
:sig
DTree xml_decode(String s)
DValue xml_decode(String s)
:params
s : XML source string
return value : element-shaped DTree
return value : element-shaped DValue
:see
>markup
xml_encode
json_decode
0_DTree
0_DValue
String
:content
Parses a simple XML document into a structured `DTree`.
Parses a simple XML document into a structured `DValue`.
`xml_decode()` is intentionally small. It does not validate schemas, DTDs, namespaces, or document types. It parses the first root element and returns the same structural element shape accepted by `xml_encode()`.
@@ -31,7 +31,7 @@ node["children"] = list of child element nodes
Example:
```uce
DTree book = xml_decode("<book id=\"b1\"><title>UCE &amp; XML</title></book>");
DValue book = xml_decode("<book id=\"b1\"><title>UCE &amp; XML</title></book>");
book["name"].to_string(); // book
book["attrs"]["id"].to_string(); // b1
@@ -42,7 +42,7 @@ book["children"]["0"]["text"].to_string(); // UCE & XML
CDATA and numeric entities are folded into text:
```uce
DTree note = xml_decode("<note><![CDATA[5 < 6]]><symbol>&#x41;&#66;</symbol></note>");
DValue note = xml_decode("<note><![CDATA[5 < 6]]><symbol>&#x41;&#66;</symbol></note>");
note["text"].to_string(); // 5 < 6
note["children"]["0"]["text"].to_string(); // AB
+8 -8
View File
@@ -1,6 +1,6 @@
:sig
String xml_encode(DTree t)
String xml_encode(DTree t, String root_name)
String xml_encode(DValue t)
String xml_encode(DValue t, String root_name)
:params
t : tree to serialize as XML
@@ -11,11 +11,11 @@ return value : XML string
>markup
xml_decode
json_encode
0_DTree
0_DValue
html_escape
:content
Serializes a `DTree` into a simple XML string.
Serializes a `DValue` into a simple XML string.
`xml_encode()` does not validate against a schema, DTD, or namespace rules. It is a structural converter for application data, similar in spirit to `json_encode()`.
@@ -33,11 +33,11 @@ node["children"] = list of child element nodes
Example:
```uce
DTree book;
DValue book;
book["name"] = "book";
book["attrs"]["id"] = "b1";
DTree title;
DValue title;
title["name"] = "title";
title["text"] = "UCE & XML";
book["children"].push(title);
@@ -54,7 +54,7 @@ The result is:
For simple map/list/scalar trees, `xml_encode()` creates ordinary child elements:
```uce
DTree payload;
DValue payload;
payload["title"] = "Hello";
payload["count"] = "3";
@@ -73,4 +73,4 @@ Notes:
- Text and attribute values are escaped.
- List values use repeated `<item>` children.
- Empty elements serialize as self-closing tags.
- Map child order follows `DTree` map iteration order.
- Map child order follows `DValue` map iteration order.
+5 -5
View File
@@ -1,19 +1,19 @@
:sig
DTree yaml_decode(String s)
DValue yaml_decode(String s)
:params
s : YAML source string
return value : decoded DTree
return value : decoded DValue
:see
>markup
yaml_encode
json_decode
xml_decode
0_DTree
0_DValue
:content
Parses a practical YAML subset into a `DTree`.
Parses a practical YAML subset into a `DValue`.
`yaml_decode()` is designed for concise UCE config files. It intentionally avoids full YAML schema behavior and does not support anchors, aliases, tags, directives, or complex inline collection syntax.
@@ -30,7 +30,7 @@ String source = "app:\n"
" - site\n"
" - cache\n";
DTree cfg = yaml_decode(source);
DValue cfg = yaml_decode(source);
cfg["app"]["name"].to_string(); // UCE Starter
cfg["app"]["debug"].to_bool(); // true
+7 -7
View File
@@ -1,5 +1,5 @@
:sig
String yaml_encode(DTree t)
String yaml_encode(DValue t)
:params
t : tree to serialize as YAML
@@ -10,10 +10,10 @@ return value : YAML string
yaml_decode
json_encode
xml_encode
0_DTree
0_DValue
:content
Serializes a `DTree` into a compact YAML string for configuration files.
Serializes a `DValue` into a compact YAML string for configuration files.
`yaml_encode()` focuses on the ordinary data shapes UCE apps use for config: nested maps, lists, strings, booleans, and numeric `f64` values. It does not emit YAML tags, anchors, aliases, or custom schema features.
@@ -22,12 +22,12 @@ Try the live example in the [YAML demo](../demo/yaml.uce).
Example:
```uce
DTree cfg;
DValue cfg;
cfg["app"]["name"] = "UCE Starter";
cfg["app"]["debug"].set_bool(true);
cfg["app"]["port"] = (f64)8080;
DTree path;
DValue path;
path = "site";
cfg["app"]["paths"].push(path);
path = "cache";
@@ -50,8 +50,8 @@ app:
Notes:
- Map keys are emitted in `DTree` map iteration order.
- Map keys are emitted in `DValue` map iteration order.
- Strings are left plain when safe and quoted when needed.
- Multiline strings are emitted as literal block scalars with `|`.
- Empty strings are emitted as `""` so they are not confused with YAML null.
- Decoded numeric-looking config values are strings unless the original `DTree` value was explicitly numeric.
- Decoded numeric-looking config values are strings unless the original `DValue` value was explicitly numeric.
+4 -4
View File
@@ -1,5 +1,5 @@
:sig
bool zip_create(String zip_file_name, DTree entries)
bool zip_create(String zip_file_name, DValue entries)
:params
zip_file_name : path to the archive to create
@@ -11,7 +11,7 @@ return value : `true` when the archive is written
zip_list
zip_read
zip_extract
DTree
DValue
:content
Creates a ZIP archive at `zip_file_name`.
@@ -19,7 +19,7 @@ Creates a ZIP archive at `zip_file_name`.
`entries` can be a simple map where each key is the archive member name and each value is the file content:
```uce
DTree entries;
DValue entries;
entries["hello.txt"] = "Hello ZIP";
entries["nested/readme.txt"] = "Nested file";
zip_create("/tmp/example.zip", entries);
@@ -28,7 +28,7 @@ zip_create("/tmp/example.zip", entries);
For list-shaped input or when the map key should not be the member name, each child can provide explicit fields:
```uce
DTree item;
DValue item;
item["name"] = "data/value.txt";
item["content"] = "42";
entries["ignored-key"] = item;
+4 -4
View File
@@ -1,16 +1,16 @@
:sig
DTree zip_list(String zip_file_name)
DValue zip_list(String zip_file_name)
:params
zip_file_name : path to the ZIP archive to inspect
return value : DTree containing archive metadata and an `entries` array
return value : DValue containing archive metadata and an `entries` array
:see
>sys
zip_create
zip_read
zip_extract
DTree
DValue
:content
Reads the central directory from `zip_file_name` and returns structured metadata.
@@ -33,6 +33,6 @@ Each entry contains:
Example:
```uce
DTree info = zip_list("/tmp/example.zip");
DValue info = zip_list("/tmp/example.zip");
print(json_encode(info));
```