String Handling#
ovstage passes strings as ovx_string_t, a non-owning (ptr, length) view
that is not required to be null-terminated. The caller owns the pointed-to
bytes, length is a byte count (not a code-point count), and the text is
UTF-8. Many entry points — attribute names, filter attributes, prim paths —
accept the dual-mode ovx_string_or_token_t, which carries either a
pre-resolved path-dictionary token or a raw string.
ovx_string_t#
typedef struct ovx_string_t {
const char* ptr; // borrowed bytes, not necessarily null-terminated
size_t length; // byte count
} ovx_string_t;
Always use both fields together:
Print with
%.*s, passing(int)length, ptr— never assume a terminator:printf("%.*s\n", (int)name.length, name.ptr);
Compare by checking
lengthfirst, thenmemcmp/strncmpover exactlylengthbytes.In C++, wrap a borrowed view as
std::string_view{ s.ptr, s.length }; copy to astd::stringif it must outlive the source buffer:// ovx_string_t is a non-owning (ptr, length) view; wrap it in string_view // for zero-copy use. Copy it if it must outlive the dictionary. std::string_view name{ resolved.ptr, resolved.length }; std::printf("attribute token %llu = '%.*s'\n", (unsigned long long)attr, (int)name.size(), name.data());
A string view returned from the path dictionary is valid only for the dictionary’s lifetime — copy it to outlive the dictionary.
ovx_string_or_token_t: String or Token#
typedef struct ovx_string_or_token_t {
ovx_token_t token; // uint64; 0 == unresolved (use string)
ovx_string_t string; // resolved through the dictionary when token == 0
} ovx_string_or_token_t;
If token != 0 the token is used directly; if token == 0 the string is
resolved through the path dictionary at call time. Pre-resolving a token avoids
per-call hashing in hot loops:
// Attributes pass as ovx_string_or_token_t. We already hold an interned
// token, so set it (token != 0) and leave the string empty to skip a lookup.
ovx_string_or_token_t attrArg{ attr, {} };
In Python#
Python has no ovx_string_t. Methods accept a plain str (interned each
call) or a pre-interned int token (cheaper for repeated use):
# Intern a string -> a stable integer token, and resolve it back.
attr = paths.intern_token("temperature")
print("attribute token", attr, "=", paths.token_to_string(attr))
# Attribute arguments accept an interned token (int) or a plain str:
# a token skips the per-call dictionary lookup, a str is interned for
# you at call time.
stage.write_attribute(
query, "temperature", ordinal=2, tensors=np.array([4.0, 5.0, 6.0], np.float32),
is_array=False,
).wait()
stage.advance_write_floor(ordinal=2).wait()
Where to Go Next#
Path Dictionary — interning, token identity, and token lifetime.
Error Handling and Diagnostics — the
ovx_string_tvalues returned by the diagnostics accessors.