O2 2.0
A communication protocol for interactive music and media applications.
|
Functions | |
int | o2_extract_start (o2_msg_data_ptr msg) |
initialize internal state to parse, extract, and coerce message arguments. More... | |
O2arg_ptr | o2_get_next (O2type type_code) |
get the next message parameter More... | |
These functions can retrieve message arguments one-at-a-time. There are some hidden state variables to keep track of the state of unpacking, so these functions are not reentrant. Arguments are returned using a pointer to a union type: #O2arg_ptr.
int o2_extract_start | ( | o2_msg_data_ptr | msg | ) |
initialize internal state to parse, extract, and coerce message arguments.
To get arguments from a message, call o2_extract_start, then for each parameter, call o2_get_next.
get ready to extract args with o2_get_next returns length of type string (not including ',') in message
get the next message parameter
This function is called repeatedly to obtain parameters in order from the message passed to o2_extract_start.
If the message parameter type matches the type_code
, a pointer to the parameter is returned. If the types do not match, but coercion is possible, the parameter is coerced, copied to a new location, and a pointer is returned. Otherwise, NULL is returned.
The type of any non-NULL return value always matches the type specified by the parameter type_code
. To determine the original type of the parameter as specified by the message, use the types
string which is passed to message handlers. (Or course, this assumes that message type strings are correct. Badly formed messages are detected when the type string and data imply that the message is longer than the actual length, but otherwise there is no way to detect errors in type strings.)
The result points into the message or to a statically allocated buffer if type coercion is required. This storage is valid until the next call to o2_extract_start
. If the value is a pointer (string, symbol, midi data, blob), then the value was not copied and remains in place within the message, so there should never be the need to immediately copy the data pointed to. However, since the storage for the value is the message, and the message will be freed when the handler returns, pointers to strings, symbols, midi data, and blobs must not be used after the handler returns.
Note: call o2_method_new with type_spec = "id", h = my_handler, coerce = false, parse = false. In this case, since there is no type coercion, type_spec must match the message exactly, so o2_get_next should always return a non-null O2arg_ptr. However, this code can fail if a badly formed message is sent because there is no test for the NULL value that will be returned by o2_get_next.
Note: call o2_method_new with type_spec = NULL, h = my_handler, coerce = false, parse = false. In this case, even though coerce is false, there is no type_spec, so the handler will be called without type checking. We could check the actual message types (given by types), but here, we will coerce into our desired types (int32 and double) if possible. Since type coercion can fail (e.g. string will not be converted to number, not even "123"), we need to check the return value from o2_get_next, where NULL indicates incompatible types.
type_code | the desired parameter type |
get the next argument from the message. If the to_type does not match the actual type in the message, convert if possible; otherwise, return NULL for the O2arg_ptr. Note that if coerce_flag was false, the type checking will have compared types for an exact match, so if we make it this far and we are constructing argv, then no type coercion will take place (and the tests for type matching are all redundant because they will all fail). If client code is calling this, then there is no way to turn off type coercion except that you can compare your desired to_type to the character in the actual type string and if there is no match, do not call o2_get_next().