UXRscV2
UXRscV2 reads the UXNB chunk (v2, and from 0.7 v3) out of a .rsc file,
entirely in portable code. It reads the bytes in place; to load a form, use
UXRsc.
#use <UXKit> // or #import "UXRscV2.xc"Why v2 is parsed here and v1 is not
Section titled “Why v2 is parsed here and v1 is not”v1’s chunk is read by libGEM’s C rscload, whose surface
UXRscGem declares. That makes
v1 rsc loading GEM-only.
v2 is parsed here, from the raw bytes, with no host dependency. Variant selection, logical-id resolution and validation therefore run, and are gated, on every backend, wasm32 included.
A resource format read by one platform’s C library cannot be used by the other six backends, which is why v2 exists.
The two formats coexist cleanly
Section titled “The two formats coexist cleanly”The magics differ:
| magic | |
|---|---|
UXNB | v2 and v3 — invisible to the C v1 reader |
XGNB | v1 — this parser reports it as version 1 |
A v2 file cannot confuse the old reader. A v1 file handed to this parser is
presented per the spec’s compatibility rule: every tree its own single-variant
form of class any.
There is no migration step. Old resources keep working, new ones gain variants, and the same code path consumes both.
v3: scoped connections
Section titled “v3: scoped connections”From 0.7 the chunk can be version 3. Three things change:
- A connection carries a scope, the layout themes it binds in.
connScopereads it, and every v2 connection reads as 0, all themes. - A top-level object carries a label, the name the designer shows.
- The chunk can carry extension sections,
{tag, size, body}, which a reader skips by size when it does not know the tag.
The classic body is unchanged, so a v3 file is still a plain .rsc to a GEM
AES.
Variant selection walks a chain
Section titled “Variant selection walks a chain”i32 tree = rsc.selectTree(formId, klass, &chosenClass);A form can carry several variants (a phone layout, a tablet layout, a
desktop one). selectTree picks the best available for a requested class by
walking a fallback chain of up to four steps.
An rsc file that only ships a desktop variant still loads on a phone by falling
back. An rsc file that ships both gets the right one with no if in the
application.
chosenClass reports which variant was used. This matters when the
answer was a fallback rather than the exact match: it separates
“there is a phone layout” from “the desktop layout is in use on a
phone”.
A form with no usable variant returns -1 rather than guessing.
Orientation is a second axis
Section titled “Orientation is a second axis”A phone or tablet layout can also come in portrait and landscape trees. A rotation can re-nest a layout, not just stretch it, so each orientation gets a whole tree of its own, exactly as each form factor does.
i32 tree = rsc.selectTreeOriented(formId, gDriver.formFactorClass(), gDriver.orientation(), &cls, &orient);Within each class of the fallback chain the order is:
- a tree for the current orientation;
- a tree with no orientation, drawn to work both ways;
- the other orientation’s tree.
Only then does selection move on to the next class. A tablet held upright with only a landscape tablet layout therefore gets that layout, not the desktop’s.
The orientation rides in the top two bits of a variant’s class word (0
none, 1 portrait, 2 landscape). Files written before it existed have
0 there and read unchanged. selectTree masks those bits
off, so code that ignores orientation keeps working.
Logical ids, and why absent is legal
Section titled “Logical ids, and why absent is legal”i32 obj = rsc.objForLogical(tree, logicalId);// -1 means the variant genuinely does not have that controlA control is referred to by a logical id instead of its index in a tree, so the same code binds to it in every variant even though the layouts differ.
-1 is a normal answer, not an error:
The parser borrows the caller’s buffer
Section titled “The parser borrows the caller’s buffer”Borrowing keeps loading an rsc file cheap: a resource file with hundreds of names costs no allocations to parse.
All multi-byte fields are big-endian, matching the .rsc body. The
parser is byte-order-independent, and a resource built on one machine loads on
another.
Topics
Section titled “Topics”open · parse · version · formCount · formAt · formOffById · formName · selectTree · selectTreeOriented · chainAt / chain · classOf · orientOf · objForLogical · resolveView · connScope · connInScope · themeBit · topObjectLabel · extCount · extTag / extSize / extBody · str
static UXRscV2* open(u8* rsc, u32 rscLen)Finds the chunk in a resource file. The buffer is borrowed; see the caution.
bool parse(void)Reads the header and the section offsets. Returns false on a malformed chunk.
Check this before trusting anything else.
version
Section titled “version”i32 version(void)1 for a v1 file presented through the compatibility rule, otherwise the
chunk’s own version, 2 or 3.
formCount
Section titled “formCount”i32 formCount(void)formAt
Section titled “formAt”u32 formAt(i32 f)The byte offset of the i-th form record.
formOffById
Section titled “formOffById”u32 formOffById(i32 formId)By id rather than by index. 0 when absent.
formName
Section titled “formName”u8* formName(i32 formId)Borrowed, like every string here.
selectTree
Section titled “selectTree”i32 selectTree(i32 formId, i32 klass, i32* chosenClass)The best variant for a form-factor class, ignoring orientation. See above.
selectTreeOriented
Section titled “selectTreeOriented”i32 selectTreeOriented(i32 formId, i32 klass, i32 orient, i32* chosenClass, i32* chosenOrient)The best variant for a class held at an orientation (UX_ORIENT_*). See
Orientation is a second axis.
chosenOrient reports the orientation of the tree that won.
chainAt / chain
Section titled “chainAt / chain”i32 chainAt(i32 klass, i32 step)static i32 chain(i32 klass, i32 step)The form-factor class at step (0 to 3) of klass’s fallback chain.
classOf
Section titled “classOf”static i32 classOf(u32 word)The form-factor class in a variant’s class word: its low 14 bits.
orientOf
Section titled “orientOf”static i32 orientOf(u32 word)The orientation in a variant’s class word: its top two bits.
objForLogical
Section titled “objForLogical”i32 objForLogical(i32 tree, i32 logicalId)An object index within a tree, or -1.
resolveView
Section titled “resolveView”i32 resolveView(u32 refAt, i32 tree)Resolves a reference record to an object. References carry a space saying what they point at: a view by coordinate, a top-level object, the owner, or a view by logical id. This lets a connection survive a variant that moved things around.
connScope
Section titled “connScope”u32 connScope(i32 i)Connection i’s scope: bit class * 3 + orientation per theme, 0 for all.
connInScope
Section titled “connInScope”bool connInScope(i32 i, i32 klass, i32 orient)Whether connection i binds in a theme.
themeBit
Section titled “themeBit”static u32 themeBit(i32 klass, i32 orient)topObjectLabel
Section titled “topObjectLabel”u8* topObjectLabel(i32 i)The designer’s name for top-level object i; "" before v3.
extCount
Section titled “extCount”i32 extCount(void)extTag / extSize / extBody
Section titled “extTag / extSize / extBody”u32 extTag(i32 i)u32 extSize(i32 i)u32 extBody(i32 i)Extension section i: its tag, its size, and the offset of its body in the
buffer.
u8* str(u32 off)A string from the chunk’s table, borrowed.
See also
Section titled “See also”UXRsc: loading a form on every backendUXRscGem: v1, and the host surface that makes it GEM-onlyUXViewDriver:formFactorClass, which supplies the classselectTreeis asked forUXViewTree: what a loaded rsc becomes