|
libose
the C library every o.se host is built on
|
contains functions that structure an OSC bundle for use with other parts of this library More...
Go to the source code of this file.
Macros | |
| #define | OSE_CONTEXT_ALIGNMENT 4 |
| Bytes passed to ose_newBundleFromCBytes will be aligned to a boundary that is a multiple of this number of bytes. | |
| #define | OSE_CONTEXT_CACHE_SIZE 64 |
| #define | OSE_CONTEXT_NUM_CACHE_ITEMS 3 |
| #define | OSE_CONTEXT_CACHE_TYPETAG_STRLEN 8 |
| #define | OSE_CONTEXT_BUNDLE_SIZE_OFFSET -4 |
| #define | OSE_CONTEXT_TOTAL_SIZE_OFFSET -8 |
| #define | OSE_CONTEXT_PARENT_BUNDLE_OFFSET_OFFSET -12 |
| #define | OSE_CONTEXT_STATUS_OFFSET -16 |
| #define | OSE_CONTEXT_MEMUSAGE_OFFSET -20 |
| #define | OSE_CONTEXT_CHANGED_OFFSET -24 |
| #define | OSE_CONTEXT_FLAGS_OFFSET -28 |
| #define | OSE_CONTEXT_CACHE_OFFSET -(36 + OSE_CONTEXT_CACHE_SIZE) |
| #define | OSE_CONTEXT_MESSAGE_TYPETAGS ",bbiiiiiibb" |
| The number of bytes between the beginning of a context message and the bundle (blob). | |
| #define | OSE_CONTEXT_MESSAGE_TYPETAGS_PLEN 12 |
| Padded length of the context message typetag string. | |
| #define | OSE_CONTEXT_BUNDLE_OFFSET |
| #define | OSE_CONTEXT_MESSAGE_OVERHEAD |
| The overhead in bytes of a context message. | |
| #define | OSE_CONTEXT_STATUS_MESSAGE_SIZE 16 |
| The size of the status message. | |
| #define | OSE_CONTEXT_TYPE_MESSAGE_SIZE 1024 |
| The size of the type message. | |
| #define | OSE_CONTEXT_MAX_OVERHEAD |
| Maximum overhead used by the system. | |
| #define | ose_copyElem(src, dest) |
| #define | ose_moveElem(src, dest) |
| #define | OSE_REGISTER_ADDRESS_LEN 3 |
| The length of a register's name, including the leading slash. | |
Functions | |
| void | ose_context_set_status (ose_bundle b, int32_t s) |
| int32_t | ose_context_get_status (ose_bundle b) |
| void | ose_context_set_changed (ose_bundle b) |
| The context's version: moved on by every change to its bundle's size, and never set back. | |
| uint32_t | ose_context_get_version (ose_bundle b) |
| void | ose_context_set_flags (ose_bundle b, int32_t flags) |
| Read and write the flags word of a context message. | |
| int32_t | ose_context_get_flags (ose_bundle b) |
| void | ose_context_cache_set (ose_bundle B, int32_t o, void *i) |
| void | ose_context_cache_setGetFirstOffsetForMatchFn (ose_bundle B, int32_t(*getFirstOffsetForMatch)(ose_bundle, const char *const, void **)) |
| void | ose_context_cache_setUserdata (ose_bundle B, void *userdata) |
| void * | ose_context_cache_getUserdata (ose_bundle B) |
| void | ose_context_cache_setTypeBundle (ose_bundle B, ose_bundle tx) |
| int32_t | ose_context_getFirstOffsetForMatch (ose_bundle B, const char *const address) |
| ose_bundle | ose_getTypeBundle (ose_bundle bundle) |
| int32_t | ose_get_memusage (ose_bundle b) |
| void | ose_reset_memusage (ose_bundle b) |
| int32_t | ose_readSize (ose_bundle bundle) |
| int32_t | ose_init (ose_bundle bundle, int32_t size, const char *const address) |
| Initializes a newly created bundle with a context message. | |
| int32_t | ose_pushContextMessage (ose_bundle bundle, int32_t size, const char *const address) |
| Pushes a new context message onto the current bundle. | |
| void | ose_dropContextMessage (ose_bundle bundle) |
| int32_t | ose_spaceAvailable (ose_bundle bundle) |
| Returns the number of unused bytes in the bundle. | |
| int32_t | ose_getContextMessageOffset (ose_bundle bundle, const char *const address) |
| Returns the offset of the context message for a given address. | |
| ose_bundle | ose_enterBundleAtOffset (ose_bundle bundle, int32_t offset) |
| Enter a new bundle context. | |
| ose_bundle | ose_enter (ose_bundle bundle, const char *const address) |
| Enter a new bundle context. | |
| ose_bundle | ose_exit (ose_bundle bundle) |
| Exit a bundle context and move one level up. | |
| int | ose_addToSize (ose_bundle bundle, int32_t amt) |
| Add an amount to the size of a bundle. This function takes care of adjusting the size of the blob of free space, and must be called to ensure that all sizes are updated properly, when using the context machinery in this file, as well as the stack operations in ose_stackops.h. | |
| int | ose_incSize (ose_bundle bundle, int32_t amt) |
| int | ose_decSize (ose_bundle bundle, int32_t amt) |
| void | ose_copyBundle (ose_bundle src, ose_bundle dest) |
| Copy the topmost bundle element to a destination at the same level. | |
| void | ose_appendBundle (ose_bundle src, ose_bundle dest) |
| Append the contents of the topmost element of src to dest. Equivalent to. | |
| void | ose_replaceBundle (ose_bundle src, ose_bundle dest) |
| Replace the contents of dest with those of the topmost element of src. Equivalent to. | |
| void | ose_copyElemAtOffset (int32_t srcoffset, ose_bundle src, ose_bundle dest) |
Append the element at srcoffset in src to dest. | |
| int32_t | ose_routeElemAtOffset (int32_t srcoffset, ose_bundle src, int32_t prefixlen, ose_bundle dest) |
| ose_bundle | ose_newBundleFromCBytes (int32_t nbytes, char *bytes) |
| Initialize a new bundle from an array of bytes. | |
| ose_bundle | ose_newBundleFromZeroedCBytes (int32_t nbytes, char *bytes) |
| The same, for bytes the caller knows are all zero – from calloc, say – which are not written over: pages not yet touched stay untouched until something is put in them. Bytes that are not all zero make a bundle that is not well formed. | |
| int32_t | ose_addressToRegister (ose_bundle osevm, const char *const address, ose_bundle *reg, const char **rest) |
| Split an address into a register and the rest of the address. | |
contains functions that structure an OSC bundle for use with other parts of this library
| #define OSE_CONTEXT_BUNDLE_OFFSET |
| #define OSE_CONTEXT_MAX_OVERHEAD |
Maximum overhead used by the system.
| #define OSE_CONTEXT_MESSAGE_OVERHEAD |
The overhead in bytes of a context message.
| #define OSE_CONTEXT_MESSAGE_TYPETAGS ",bbiiiiiibb" |
The number of bytes between the beginning of a context message and the bundle (blob).
The typetag string of a context message.
Was a bare literal inside ose_context.c with nothing to check it against. It is a constant so that a generated bundle can be validated structurally – see test/ose_test/tools/emit_vm_literal.c – rather than only by asking libose to read back what libose wrote.
b : cache b : unused i : flags (was the second unused blob) i : version (the changed word) i : memusage i : status i : offset of data section relative to start of bundle i : total number of bytes b : bundle (blob) b : free space (blob)
| #define ose_copyElem | ( | src, | |
| dest | |||
| ) |
| #define ose_moveElem | ( | src, | |
| dest | |||
| ) |
| #define OSE_REGISTER_ADDRESS_LEN 3 |
The length of a register's name, including the leading slash.
A register (context bundle) is named with exactly three characters: a slash and two more. /_s, /_e, /_x, /le, /db, /py.
| int32_t ose_addressToRegister | ( | ose_bundle | osevm, |
| const char *const | address, | ||
| ose_bundle * | reg, | ||
| const char ** | rest | ||
| ) |
Split an address into a register and the rest of the address.
This is how namespacing works in ose, and it is OSC's own mechanism rather than an invention: an address is a path, and the first segment selects where the rest is looked up.
/log/net/send -> register /log, address /net/send /_e/x -> register /_e, address /x /net/send -> no register named /net: not routed
A register's name is exactly OSE_REGISTER_ADDRESS_LEN characters, so the split needs no delimiter search, no allocation and no parsing – which is why it is fixed width, and why it is cheap enough to do on every lookup on a microcontroller.
| osevm | The bundle whose context messages are searched. |
| address | The address to split. Reading address[3] is safe for any address: OSC pads addresses to a multiple of four with at least one NUL, so a shorter address has readable padding there. |
| reg | Filled in with the register, if one was named. |
| rest | Filled in with the remainder of the address, if one was named. Points into address; nothing is copied. |
address begins with the name of an existing register, 0 otherwise. A prefix that names no register is not an error: the address is just an ordinary address, which is what makes the convention additive rather than a reserved syntax.Four call sites implemented this independently, with the 3 written out in each – osevm_lookupInEnv_impl(), osevm_assignStackToEnv(), and two more in layers above, across three repositories. They call this instead now. The convention was never the problem; four copies of it were.
| int ose_addToSize | ( | ose_bundle | bundle, |
| int32_t | amt | ||
| ) |
Add an amount to the size of a bundle. This function takes care of adjusting the size of the blob of free space, and must be called to ensure that all sizes are updated properly, when using the context machinery in this file, as well as the stack operations in ose_stackops.h.
| bundle | The bundle to change the size of. |
| amt | The amount to add to (or subtract from) the bundle. |
Check the result before writing where the space was supposed to be. These functions already compute whether the new size fits; the check is not an assert, so it runs in release builds too. A caller that ignores the answer and copies anyway writes past the end of the bundle's memory, and the whole cost of avoiding that is one comparison the callee has already made.
The return type is the only thing that changed; the parameters and behaviour are as they were, so a call site that does not care still compiles unchanged.
| void ose_appendBundle | ( | ose_bundle | src, |
| ose_bundle | dest | ||
| ) |
Append the contents of the topmost element of src to dest. Equivalent to.
| src | The source bundle. |
| dest | The destination bundle. |
| void ose_context_set_changed | ( | ose_bundle | b | ) |
The context's version: moved on by every change to its bundle's size, and never set back.
Something that depends on what a register holds keeps the version it saw and trusts what it knows while the version is the same. Nothing clears it, so any number of readers, on any number of threads, can each keep their own. It is the word that was the changed flag; a write that leaves the size exactly as it was does not move it, as it did not set the flag.
| void ose_context_set_flags | ( | ose_bundle | b, |
| int32_t | flags | ||
| ) |
Read and write the flags word of a context message.
Whatever a client put there, or 0 for a context message made before it had a use for one – which is every one of them, since ose_newContextMessage() zeroes it. See OSE_CONTEXT_FLAGS_OFFSET for why libose names no bits.
b must be a context bundle. Asked of anything else this reads four bytes in front of a bundle that has no header, which is why both assert. | void ose_copyBundle | ( | ose_bundle | src, |
| ose_bundle | dest | ||
| ) |
Copy the topmost bundle element to a destination at the same level.
| src | The source bundle. |
| dest | The destination bundle. |
Copy the topmost bundle element to a destination at the same level.
| src | The source bundle. |
| dest_addr | The destination address. |
Move the topmost bundle element to a destination at the same level.
| src | The source bundle. |
| dest | The destination bundle. |
Move the topmost bundle element to a destination at the same level.
| src | The source bundle. |
| dest_addr | The destination address. |
Move the topmost bundle element to a destination at the same level, replacing the first element with the same address if it is a message. If no message in the destination bundle exists with the same address, this function behaves like #ose_copyBundleElemToDestAddr.
| src | The source bundle. |
| dest | The destination bundle. |
Move the topmost bundle element to a destination at the same level, replacing the first element with the same address if it is a message. If no message in the destination bundle exists with the same address, this function behaves like #ose_copyBundleElemToDestAddr.
| src | The source bundle. |
| dest_addr | The destination address. |
Push a copy of src onto the top of dest.
| src | The source bundle. |
| dest | The destination bundle. |
| void ose_copyElemAtOffset | ( | int32_t | srcoffset, |
| ose_bundle | src, | ||
| ose_bundle | dest | ||
| ) |
Append the element at srcoffset in src to dest.
| srcoffset | the offset of the element's size word, as returned by ose_getLastBundleElemOffset – not the offset of its address. |
srcoffset must point to a valid element within src. dest must have room for it.dest to OSE_ERR_RANGE and copies nothing. Neither precondition used to be checked at all: the element's length was read from srcoffset without bounds testing and then handed straight to memcpy, and a dest with no room got the copy anyway, because ose_incSize declines silently rather than failing. | ose_bundle ose_enter | ( | ose_bundle | bundle, |
| const char *const | address | ||
| ) |
Enter a new bundle context.
| bundle | The current bundle. |
| address | The address of the context message containing the bundle to enter. |
address names no context bundle, with OSE_ERR_UNKNOWN_CONTEXT_BUNDLE set on bundle. Modules call this with addresses of their own, so the failure is reachable from outside libose; a null bundle faults at first use rather than letting a mistyped address be written to. | ose_bundle ose_enterBundleAtOffset | ( | ose_bundle | bundle, |
| int32_t | offset | ||
| ) |
Enter a new bundle context.
| bundle | The current bundle. |
| offset | The offsetof the context message containing the bundle to enter. |
| ose_bundle ose_exit | ( | ose_bundle | bundle | ) |
Exit a bundle context and move one level up.
| bundle | The current bundle. |
| int32_t ose_getContextMessageOffset | ( | ose_bundle | bundle, |
| const char *const | address | ||
| ) |
Returns the offset of the context message for a given address.
| bundle | The bundle to look for the context message in. |
| address | The address of the context message to look for. |
| int32_t ose_init | ( | ose_bundle | bundle, |
| int32_t | size, | ||
| const char *const | address | ||
| ) |
Initializes a newly created bundle with a context message.
| bundle | The bundle. |
| size | The number of bytes available for this context message |
| address | The address of this context message. |
| ose_bundle ose_newBundleFromCBytes | ( | int32_t | nbytes, |
| char * | bytes | ||
| ) |
Initialize a new bundle from an array of bytes.
| nbytes | The number of bytes in the array. |
| bytes | An array of bytes containing nbytes, preallocated. |
There is no need to dispose of the returned object in a special way. You may simply free the byte array when you are finished, in accordance with the way it was allocated.
| int32_t ose_pushContextMessage | ( | ose_bundle | bundle, |
| const int32_t | size, | ||
| const char *const | address | ||
| ) |
Pushes a new context message onto the current bundle.
| bundle | The bundle. |
| size | The number of bytes available for this context message |
| address | The address of this context message. |
Pushes a new context message onto the current bundle.
| address | The register's name. It must be exactly three characters: a slash and two more, as in /_x, /le, /db. This is not a style preference. An address of the form /xy/rest is routed to the register named /xy and looked up there as /rest – the leading three characters are a namespace selector with no delimiter to parse, which is why they are fixed width. osevm_lookup() and osevm_assignStackToEnv() implement that split here, and callers above this library implement it again; every one of them hardcodes 3. |
The name must also be free. A second claim on a live register is refused with OSE_ERR_REGISTER_EXISTS; see the comment on that guard for what accepting one used to do.
bundle is unchanged and errno is set.These were preconditions guarded only by ose_assert(), which ose.h compiles out unless OSE_CONF_DEBUG. That was survivable while every caller passed a string literal – and every caller in the tree does, except one. osevm_makeRegister() takes both arguments from the stack, and it is bound as /o/make/register, so (65536, "/audio") /o/make/register typed at the prompt reached here with a six-character name and segfaulted the CLI. (3, "/ab") hung instead. Both in release, from a line a user can type.
Same class as the 31 stackops conversions of 2026-08-09; this one is in ose_context.c and was missed.
| void ose_replaceBundle | ( | ose_bundle | src, |
| ose_bundle | dest | ||
| ) |
Replace the contents of dest with those of the topmost element of src. Equivalent to.
| int32_t ose_spaceAvailable | ( | ose_bundle | bundle | ) |
Returns the number of unused bytes in the bundle.
| bundle | The bundle. |