143 lines
4.5 KiB
Plaintext
143 lines
4.5 KiB
Plaintext
:title
|
|
DValue
|
|
|
|
:sig
|
|
DValue
|
|
|
|
:see
|
|
>types
|
|
get_by_path
|
|
json_decode
|
|
|
|
:content
|
|
`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
|
|
|
|
`DValue` can hold:
|
|
|
|
- `String`
|
|
- `f64`
|
|
- `bool`
|
|
- pointer values
|
|
- nested child `DValue` values in a map-shaped container
|
|
|
|
Map-shaped `DValue` values can also represent list-like data when their keys are numeric strings in sequence.
|
|
|
|
## Where It Appears
|
|
|
|
You will encounter `DValue` throughout the runtime, especially in:
|
|
|
|
- `context.cfg`
|
|
- `context.props`
|
|
- `context.connection`
|
|
- `json_decode()` results
|
|
- `unit_call()` return values
|
|
- `unit_info()`
|
|
|
|
## Reading Values
|
|
|
|
- `["key"]` accesses or creates a child node.
|
|
- `.has("key")` checks whether a child exists without creating it.
|
|
- `.key("key")` returns a child pointer when it already exists.
|
|
- `.get_or_create("key")` returns a child pointer and creates it when missing.
|
|
- `.get_by_path("a/b/c")` traverses nested children without creating missing keys.
|
|
- `.to_string(default)` reads scalar content as text.
|
|
- `.to_s64(default)`, `.to_u64(default)`, and `.to_f64(default)` perform best-effort numeric conversion.
|
|
- `.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 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");
|
|
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 `DValue` nodes, so typed numeric conversion is the normal way to consume those values.
|
|
|
|
References are dereferenced automatically in most normal reads.
|
|
|
|
## Conversion Rules
|
|
|
|
- Scalar-looking strings are trimmed before numeric and boolean parsing.
|
|
- `.to_bool()` understands common textual forms such as `true`, `false`, `yes`, `no`, `1`, and `0`.
|
|
- `bool` values convert numerically to `1` and `0`.
|
|
- Pointer values convert numerically when read as numbers.
|
|
- Single-value maps can act as scalar wrappers for numeric and boolean conversion.
|
|
- Missing values and invalid numeric input fall back to the accessor's `default_value` argument (`0`, `""`, or `false` when not given).
|
|
- `.to_stringmap()` converts map children key-by-key using each child's `to_string()`.
|
|
|
|
## Writing Values
|
|
|
|
Common mutating helpers include:
|
|
|
|
- `.set(String)`
|
|
- `.set(f64)`
|
|
- `.set_bool(bool)`
|
|
- `.set(StringMap)`
|
|
- `.set_array()`
|
|
- `.push(...)`
|
|
- `.pop()`
|
|
- `.remove(key)`
|
|
- `.clear()`
|
|
|
|
Use `.set_array()` when you want list-style behavior with `push()` and `pop()`.
|
|
|
|
## Inspection Helpers
|
|
|
|
Useful inspection helpers include:
|
|
|
|
- `.has(key)`
|
|
- `.key(key)`
|
|
- `.get_or_create(key)`
|
|
- `.get_type_name()`
|
|
- `.is_array()`
|
|
- `.is_list()`
|
|
- `.to_json()`
|
|
|
|
## each()
|
|
|
|
`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 `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
|
|
|
|
For non-map values, `each()` still invokes the callback once:
|
|
|
|
- `t` is the current value
|
|
- `key` is an empty string
|
|
|
|
```cpp
|
|
context.connection["items"].each([&](const DValue& item, String key) {
|
|
print(key, ": ", item.to_string(), "\n");
|
|
});
|
|
```
|
|
|
|
## Examples
|
|
|
|
```cpp
|
|
String theme = context.cfg.get_by_path("theme/key").to_string();
|
|
|
|
u64 compiled_mtime = unit_info("test/hello.uce")["compiled_mtime"].to_u64();
|
|
|
|
bool dark_mode = context.props["dark_mode"].to_bool();
|
|
|
|
if(DValue* user = payload.key("user")) {
|
|
print(user->to_json());
|
|
}
|
|
|
|
payload.get_or_create("headers")->get_or_create("Content-Type")->set("text/plain");
|
|
|
|
StringMap headers = payload["headers"].to_stringmap();
|
|
```
|
|
|
|
## Related Concepts
|
|
|
|
- PHP: nested associative arrays, `stdClass`, decoded JSON trees, and helper accessors for deep array paths
|
|
- JavaScript / Node.js: plain objects, arrays, `Map`, and JSON-shaped data passed between handlers
|