libose
Loading...
Searching...
No Matches
Macros | Functions | Variables
ose_context.h File Reference

contains functions that structure an OSC bundle for use with other parts of this library More...

#include <inttypes.h>
#include "ose.h"
Include dependency graph for ose_context.h:
This graph shows which files directly or indirectly include this file:

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)
 
void ose_context_reset_changed (ose_bundle b)
 
int32_t ose_context_get_changed (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.
 
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.
 

Variables

uint32_t ose_context_generation
 Make a new context bundle (a register) inside bundle.
 

Detailed Description

contains functions that structure an OSC bundle for use with other parts of this library

Macro Definition Documentation

◆ OSE_CONTEXT_BUNDLE_OFFSET

#define OSE_CONTEXT_BUNDLE_OFFSET
Value:
(4 /* size */ \
+ 4 /* padded address len */ \
+ 12 /* padded typetag str */ \
+ 4 + OSE_CONTEXT_CACHE_SIZE /* blob - cache */ \
+ 4 /* blob - unused */ \
+ 4 /* int - flags */ \
+ 4 /* int - changed */ \
+ 4 /* int - memusage */ \
+ 4 /* int - status */ \
+ 4 /* int - offset to bundle */ \
+ 4 /* int - total size */ \
+ 4) /* blob size */

◆ OSE_CONTEXT_MAX_OVERHEAD

#define OSE_CONTEXT_MAX_OVERHEAD
Value:
+ OSE_BUNDLE_HEADER_LEN \
#define OSE_CONTEXT_TYPE_MESSAGE_SIZE
The size of the type message.
Definition ose_context.h:213
#define OSE_CONTEXT_ALIGNMENT
Bytes passed to ose_newBundleFromCBytes will be aligned to a boundary that is a multiple of this numb...
Definition ose_context.h:45
#define OSE_CONTEXT_STATUS_MESSAGE_SIZE
The size of the status message.
Definition ose_context.h:205
#define OSE_CONTEXT_MESSAGE_OVERHEAD
The overhead in bytes of a context message.
Definition ose_context.h:194

Maximum overhead used by the system.

◆ OSE_CONTEXT_MESSAGE_OVERHEAD

#define OSE_CONTEXT_MESSAGE_OVERHEAD
Value:
(OSE_CONTEXT_BUNDLE_OFFSET \
+ OSE_BUNDLE_HEADER_LEN /* bundle header */ \
+ 4) /* blob size */

The overhead in bytes of a context message.

◆ OSE_CONTEXT_MESSAGE_TYPETAGS

#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 : changed flag
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)

◆ ose_copyElem

#define ose_copyElem (   src,
  dest 
)
Value:
ose_copyElemAtOffset(ose_getLastBundleElemOffset(src), \
src, dest)
void ose_copyElemAtOffset(int32_t srcoffset, ose_bundle src, ose_bundle dest)
Append the element at srcoffset in src to dest.
Definition ose_context.c:901

◆ ose_moveElem

#define ose_moveElem (   src,
  dest 
)
Value:
{ \
int32_t o = ose_getLastBundleElemOffset(src); \
ose_copyElemAtOffset(o, src, dest); \
ose_dropAtOffset(src, o); \
}

◆ OSE_REGISTER_ADDRESS_LEN

#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.

See also
ose_addressToRegister for why it is fixed, and doc/REGISTERS.md for the convention as a whole.

Function Documentation

◆ ose_addressToRegister()

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.

Parameters
osevmThe bundle whose context messages are searched.
addressThe 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.
regFilled in with the register, if one was named.
restFilled in with the remainder of the address, if one was named. Points into address; nothing is copied.
Returns
1 if 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.

◆ ose_addToSize()

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.

Parameters
bundleThe bundle to change the size of.
amtThe amount to add to (or subtract from) the bundle.
Returns
Nonzero if the size was changed; 0 if the change was refused because there is not room for it, in which case errno is set to OSE_ERR_RANGE and the bundle is untouched.

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.

◆ ose_appendBundle()

void ose_appendBundle ( ose_bundle  src,
ose_bundle  dest 
)

Append the contents of the topmost element of src to dest. Equivalent to.

#ose_copyBundle(src, dest);
#ose_unpackDrop(dest);
#ose_drop(src);
Parameters
srcThe source bundle.
destThe destination bundle.

◆ ose_context_set_flags()

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.

Precondition
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.

◆ ose_copyBundle()

void ose_copyBundle ( ose_bundle  src,
ose_bundle  dest 
)

Copy the topmost bundle element to a destination at the same level.

Parameters
srcThe source bundle.
destThe destination bundle.

Copy the topmost bundle element to a destination at the same level.

Parameters
srcThe source bundle.
dest_addrThe destination address.

Move the topmost bundle element to a destination at the same level.

Parameters
srcThe source bundle.
destThe destination bundle.

Move the topmost bundle element to a destination at the same level.

Parameters
srcThe source bundle.
dest_addrThe 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.

Parameters
srcThe source bundle.
destThe 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.

Parameters
srcThe source bundle.
dest_addrThe destination address.

Push a copy of src onto the top of dest.

Parameters
srcThe source bundle.
destThe destination bundle.

◆ ose_copyElemAtOffset()

void ose_copyElemAtOffset ( int32_t  srcoffset,
ose_bundle  src,
ose_bundle  dest 
)

Append the element at srcoffset in src to dest.

Parameters
srcoffsetthe offset of the element's size word, as returned by ose_getLastBundleElemOffset – not the offset of its address.
Precondition
srcoffset must point to a valid element within src.
dest must have room for it.
Postcondition
On violation, sets errno on 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_enter()

ose_bundle ose_enter ( ose_bundle  bundle,
const char *const  address 
)

Enter a new bundle context.

Parameters
bundleThe current bundle.
addressThe address of the context message containing the bundle to enter.
Returns
The requested bundle, or a bundle whose pointer is null if 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_enterBundleAtOffset()

ose_bundle ose_enterBundleAtOffset ( ose_bundle  bundle,
int32_t  offset 
)

Enter a new bundle context.

Parameters
bundleThe current bundle.
offsetThe offsetof the context message containing the bundle to enter.
Returns
The requested bundle.

◆ ose_exit()

ose_bundle ose_exit ( ose_bundle  bundle)

Exit a bundle context and move one level up.

Parameters
bundleThe current bundle.
Returns
The bundle one level up.

◆ ose_getContextMessageOffset()

int32_t ose_getContextMessageOffset ( ose_bundle  bundle,
const char *const  address 
)

Returns the offset of the context message for a given address.

Parameters
bundleThe bundle to look for the context message in.
addressThe address of the context message to look for.
Returns
The offset if found, or -1 otherwise.

◆ ose_init()

int32_t ose_init ( ose_bundle  bundle,
int32_t  size,
const char *const  address 
)

Initializes a newly created bundle with a context message.

Parameters
bundleThe bundle.
sizeThe number of bytes available for this context message
addressThe address of this context message.
Returns
The size available for the bundle minus the ovehead of the message.

◆ ose_newBundleFromCBytes()

ose_bundle ose_newBundleFromCBytes ( int32_t  nbytes,
char *  bytes 
)

Initialize a new bundle from an array of bytes.

Parameters
nbytesThe number of bytes in the array.
bytesAn array of bytes containing nbytes, preallocated.
Returns
An initialized ose_bundle.

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.

◆ ose_pushContextMessage()

int32_t ose_pushContextMessage ( ose_bundle  bundle,
int32_t  size,
const char *const  address 
)

Pushes a new context message onto the current bundle.

Parameters
bundleThe bundle.
sizeThe number of bytes available for this context message
addressThe address of this context message.
Returns
The size available for the bundle minus the ovehead of the message.

◆ ose_replaceBundle()

void ose_replaceBundle ( ose_bundle  src,
ose_bundle  dest 
)

Replace the contents of dest with those of the topmost element of src. Equivalent to.

#ose_clear(dest);
#ose_append(src, dest);

◆ ose_spaceAvailable()

int32_t ose_spaceAvailable ( ose_bundle  bundle)

Returns the number of unused bytes in the bundle.

Parameters
bundleThe bundle.
Returns
The number of unused bytes in the bundle.

Variable Documentation

◆ ose_context_generation

uint32_t ose_context_generation
extern

Make a new context bundle (a register) inside bundle.

Parameters
addressThe 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.

Returns
the offset of the new context message, or -1 if it refused, in which case 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.