OpO Client APIs v1.0.0
Types functions
Introduction

OpO is a fast triple store that is ideally suited for storing JSON documents. It has an HTTP API as well as more direct API. The OpO Client is a C client that provides access to that API.

The OpO Client provides basic connect, query, and close functions. The queries are TQL JSON. They can be constructed with the OjC library or more efficiently with the opoBuilder. All queries are made asynchronously but can be made synchronous with a simple wrapper function that makes use of the opo_client_process() function.

While query responses are asynchronous, processing of the responses is controlled by the caller with the opo_client_process() function. In the unit test a simple thread is created that continually processes responses but the call can be made one at a time for more control over response handling.

Install

For the initial release, build (type make) then copy libopoc and the headers in the include directory to a convenient place that will be picked up by the build. You could even leave the project in place and link directly to the repo.

Guides

An insert is shown below. The unit tests are the best source of usage otherwise.

#define OPO_MSG_MAX_DEPTH 512 #include #include #include static void add_cb(opoRef ref, opoVal response, void *ctx) { opoVal top = opo_msg_val(response); opoVal rval = struct _opoErr err = OPO_ERR_INIT; if (OPO_ERR_OK != opo_val_int(&err, opo_val_get(opo_msg_val(response), "code"))) { printf("error response\n"); } else { printf("got it!\n"); } } static void create_record(opoClient client) { int cnt; uint8_t query[1024]; struct _opoErr err = OPO_ERR_INIT; struct _opoBuilder builder; opo_builder_init(&err, &builder, query, sizeof(query)); opo_builder_push_object(&err, &builder, NULL, -1); opo_builder_push_object(&err, &builder, "insert", -1); opo_builder_push_string(&err, &builder, "Test", -1, "kind", -1); opo_builder_push_int(&err, &builder, i, "num", -1); opo_builder_push_string(&err, &builder, "something", -1, "str", -1); opo_builder_finish(&builder); opo_client_query(&err, client, query, add_cb, &ref); if (1 != opo_client_process(client, 1, 1.0)) { printf("query failed\n"); } }
opoBuilder
#define OPO_MSG_MAX_DEPTH 512 typedef struct _opoBuilder { uint8_t *head; uint8_t *end; uint8_t *cur; bool own; bool *top; bool stack[OPO_MSG_MAX_DEPTH]; } *opoBuilder;

The builder is used to build a binary message that is an opoVal. It is meant to be fast and achieves that by making the message construction a single pass or linear build. The structure members are public but only the .head should be accessed and then only for reading.

The normal use of the builder is to initialize the builder and then make multiple calls to push values into the message. Finally calling the opo_builder_finish() function to properly complete the message.

headthe current start or head of the messages being built
endthe current allocatd end of the message buffer
curthe current message end
owna flag indicating the builder owns the message buffer
topa pointer to the current top of the stack where the latest object or array is
stackstack used to keep track of objets and array while building
opo_builder_cleanup()
void opo_builder_cleanup(opoBuilder builder)

Cleans up any memory allocated by the builder. The builder itself is not freed.

builderbuilder to cleanup
opo_builder_finish()
opoErrCode opo_builder_finish(opoBuilder builder)

Completes the message being built. It also pops any open array and objects if they have not already been closed.

builderbuilder to complete and finish the message it is building.
Returns:the error code.
opo_builder_init()
opoErrCode opo_builder_init(opoErr err, opoBuilder builder, uint8_t *buf, size_t size)

Initialize a struct_opoBuilder with the buffer specified. If the buf argument is NULL the a buffer is allocated with the size specified or with a minimum size. If the buf argument is not NULL then that buffer is unless the message grows too large and a new buffer is allocated. This is indicated by the .own member of the builder. There should be no need to check as long as the opo_builder_take() function is used.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to initialize
bufbuffer to use initialy
sizethe size of the initial buffer or the initial size to allocate if the buf is NULL
Returns:the error status code.
opo_builder_length()
size_t opo_builder_length(opoBuilder builder)

Returns the current message length.

builderbuilder to get the message length from.
Returns:the current message length
opo_builder_pop()
opoErrCode opo_builder_pop(opoErr err, opoBuilder builder)

Closes an object or array. This is similar to typing a '}' character in JSON. An error will occur if there is no object or array open.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to pop a level.
Returns:the error status code.
opo_builder_push_array()
opoErrCode opo_builder_push_array(opoErr err, opoBuilder builder, const char *key, int klen)

Start an array. If pushing to an array the key should be NULL. If pushing to an object the key must point to the string to be used as the key.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_bool()
opoErrCode opo_builder_push_bool(opoErr err, opoBuilder builder, bool value, const char *key, int klen)

Push the value onto the message.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuevalue to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_double()
opoErrCode opo_builder_push_double(opoErr err, opoBuilder builder, double value, const char *key, int klen)

Push the value onto the message.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuevalue to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_int()
opoErrCode opo_builder_push_int(opoErr err, opoBuilder builder, int64_t value, const char *key, int klen)

Push the value onto the message.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuevalue to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_null()
opoErrCode opo_builder_push_null(opoErr err, opoBuilder builder, const char *key, int klen)

Push a null onto the message.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_object()
opoErrCode opo_builder_push_object(opoErr err, opoBuilder builder, const char *key, int klen)

Start a new object and push onto the message.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_string()
opoErrCode opo_builder_push_string(opoErr err, opoBuilder builder, const char *value, int len, const char *key, int klen)

Push the value string onto the message. The len is either the length of the string or zero or less indicating the length should be calculated by calling strlen() on the value string.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuestring to push
lenlength of the value string to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_time()
opoErrCode opo_builder_push_time(opoErr err, opoBuilder builder, int64_t value, const char *key, int klen)

Push the value onto the message. The time value should be the number of nanoseconds from epoch or Unix time to the nanosecond.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuevalue to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_uuid()
opoErrCode opo_builder_push_uuid(opoErr err, opoBuilder builder, uint64_t hi, uint64_t lo, const char *key, int klen)

Push the value onto the message. The UUID is composed of a high and low value unsigned 64 bit integers.

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
hithe high 64 bit integer part of the value to push
lothe low 64 bit integer part of the value to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_push_uuid_string()
opoErrCode opo_builder_push_uuid_string(opoErr err, opoBuilder builder, const char *value, const char *key, int klen)

Push the value onto the message. The UUID should be a 36 character string following the standard UUID format,

The klen can be the actual length of the key or if the key is terminated with a '\0' character the klen can be zero or below and the strlen() function will be called to calculate the length.

errpointer to an initialized opoErr struct that will be set if an error occurs.
builderbuilder to push the value to.
valuethe value to push
keykey string
klenlength of the key string
Returns:the error status code.
opo_builder_take()
opoMsg opo_builder_take(opoBuilder builder)

Returns the current message. Releasing ownership to the caller which take responsibility of freeing the message when no longer needed. Note that if a buffer was provided that may be returned so either check the ownerwhip of the buffer before taking or compare to the original before calling free. The message will be 'finished' before being given on this call.

builderbuilder to take the message from.
Returns:a completed message.
opoClient
typedef struct _opoClient *opoClient;

The client is the connection handle for making requests to the OpO database server. A client is creaed by connecting to the server. After that queiries can be made until the client conneciton is closed.

opoClientOptions
typedef struct _opoClientOptions { double timeout; int pending_max; opoStatusCallback status_callback; } *opoClientOptions;

Options for a client connection.

timeouttimeout in seconds for all queries
pending_maxmaximum pending queries
status_callbackcallback for status change
opoQueryCallback
typedef void (*opoQueryCallback)(opoRef ref, opoVal response, void *ctx)

Responses to asynchronous queries are delivered by calling the callback function specified when the query is made.

refreference to the query
responseresponse to the query
ctxcontext given when the query was made
opoStatusCallback
typedef void (*opoStatusCallback)(opoClient client, bool connected, opoErrCode code, const char *msg)

Called on status changes such as connect, closed, or errors.

clientclient to get status from
connectedwhether the client is connected or not
codeerror code if there was an error
msgerror message or information about the status
opoRef
typedef uint64_t opoRef

When an asynchronous query is made a reference to the query is returned. That reference included in the server response so that the query can be matched to the response.

opo_client_close()
void opo_client_close(opoClient client)

Closes the connection to the server. Outstanding queries are completed with error responses.

clientclient to close
opo_client_connect()
opoClient opo_client_connect(opoErr err, const char *host, int port, opoClientOptions options)

Connects to the server and creates a client that is returned to be used for queries. On error the err is set and NULL is returned.

errpointer to an initialized opoErr struct that will be set if an error occurs.
hostserver host name or address
portport the server is listening on
optionsoptions or NULL for the defaults
Returns:a new client or NULL on error.
opo_client_pending_count()
int opo_client_pending_count(opoClient client)

Returns the current number of pending queries. Note this can change rapidly as responses arrive.

clientclient to get the count from
Returns:the number of queries waiting from responses
opo_client_process()
int opo_client_process(opoClient client, int max, double wait)

Processes up the the specified max number of responses. If no response is ready to be processed in the before the wait time is exceeded the call returns. The wait is started after the last handled response. This call is thread safe to allow multiple servicing threads.

clientclient to process responses
maxmaximum number of responses to process before returning
waitidle time in seconds before returning
Returns:the number of responses processed
opo_client_query()
opoRef opo_client_query(opoErr err, opoClient client, opoVal query, opoQueryCallback cb, void *ctx)

Sends a query to the server and returns once the query has been sent. The provided callback is called with the response. The response callback is called when the opo_client_process() is called.

Queries callbacks always occur in the order they were sent from a single client. Different client callbacks may be called in different order than the order they were called in.

errpointer to an initialized opoErr struct that will be set if an error occurs.
clientclient to send the query
queryTQL query
cbcallback function to call with a response
ctxcontext that will be included in the callback
Returns:a reference to the query
opo_client_ready_count()
int opo_client_ready_count(opoClient client)

Returns the current number of responses ready for processing. Note this can change rapidly as responses arrive.

clientclient to get the count from
Returns:the number of responses ready to be processed
opoErr
typedef struct _opoErr { int code; char msg[256]; } *opoErr;

The struct used to report errors or status after a function returns. The struct must be initialized before use as most calls that take an err argument will return immediately if an error has already occurred.

codeerror code
msgerror message
OPO_ERR_INIT
#define OPO_ERR_INIT { 0, { 0 } }

A static initializer for an opoErr.

opoErrCode
typedef enum { OPO_ERR_OK = 0, OPO_ERR_MEMORY = ENOMEM, OPO_ERR_DENIED = EACCES, OPO_ERR_IMPL = ENOSYS, OPO_ERR_PARSE = ELAST + 1, OPO_ERR_READ, OPO_ERR_WRITE, OPO_ERR_OVERFLOW, OPO_ERR_ARG, OPO_ERR_NOT_FOUND, OPO_ERR_THREAD, OPO_ERR_NETWORK, OPO_ERR_LOCK, OPO_ERR_FREE, OPO_ERR_IN_USE, OPO_ERR_TOO_MANY, OPO_ERR_TYPE, OPO_ERR_LAST } opoErrCode;

The error codes for the opoErr struct. Not that errors in errno.h can also occur.

opo_err_clear()
void opo_err_clear(opoErr err)

Re-initializes an opoErr struct. The code is set to zero and the messages is cleared.

errstruct to re-initialize
opo_err_no()
opoErrCode opo_err_no(opoErr err, const char *fmt, ...)

Sets the err->code to the errno value and uses printf rules to fill in the msg element, limiting the size to the size of the msg size.

errstruct to modify
fmtprintf format argument
...additional printf arguments
Returns:the error code set
opo_err_set()
opoErrCode opo_err_set(opoErr err, opoErrCode code, const char *fmt, ...)

Sets the err->code to provided code and uses printf rules to fill in the msg element, limiting the size to the size of the msg size.

errstruct to modify
codeerror code
fmtprintf format argument
...additional printf arguments
Returns:the error code set
opo_err_str()
const char* opo_err_str(opoErrCode code)

Returns the string associated with an error code.

Returns:descriptive string for the code.
opoMsg
typedef const uint8_t *opoMsg;

An opoMsg a series of bytes that is the encoded form of a JSON like tree structure. It consists of 8 bytes at the start for a 64 bit unsigned integer that is the message identifier followed by an opoVal.

opo_msg_bsize()
size_t opo_msg_bsize(opoMsg msg)

Returns the byte size of the message.

msgopoMsg to the size of
Returns:the bytes size.
opo_msg_id()
uint64_t opo_msg_id(opoMsg msg)

Gets the ID of the opoMsg.

msgopoMsg to get ID from
Returns:the ID.
opo_msg_set_id()
void opo_msg_set_id(uint8_t *msg, uint64_t id)

Sets the ID of the message.

msgopoMsg as a byte array to the ID on
idID to set on the message
opo_msg_val()
opoVal opo_msg_val(opoMsg msg)

Returns the opoVal of the opoMsg.

msgopoMsg to get the value from
Returns:the value.
opoVal
typedef const uint8_t *opoVal;

An opoVal a series of bytes that is the encoded form of a JSON like tree structure. It adds support for time as a 64 bit integer as nanoseconds from epoch as well as UUIDs. It also allows multiple occurances of a key which somewhat ambiquous in the JSON definition.

The fact that a opoVal is a series of bytes is not important if the APIs are used. Where it does become important is when sending, writing, or reading a opoVal. Since it is a contiguous memory block it can be treated as such when readin and writing.

opoValCallbacks
typedef struct _opoValCallbacks { bool (*begin_object)(opoErr err, void *ctx); bool (*end_object)(opoErr err, void *ctx); bool (*key)(opoErr err, const char *key, int len, void *ctx); bool (*begin_array)(opoErr err, void *ctx); bool (*end_array)(opoErr err, void *ctx); bool (*null)(opoErr err, void *ctx); bool (*boolean)(opoErr err, bool b, void *ctx); bool (*fixnum)(opoErr err, int64_t num, void *ctx); bool (*decimal)(opoErr err, double num, void *ctx); bool (*string)(opoErr err, const char *str, int len, void *ctx); bool (*uuid)(opoErr err , uint64_t hi, uint64_t lo, void *ctx); bool (*uuid_str)(opoErr err, const char *str, void *ctx); bool (*time)(opoErr err, int64_t t, void *ctx); bool (*time_str)(opoErr err, const char *str, void *ctx); } *opoValCallbacks;

When iterating over an opoVal the opoValCallback is used to provide the callback functions to the iterator. Each callback function returns a boolean indicating whether iteration should continue or not. A return of true indicates iteration should continue. If the function is not set then it is not called. In the case of the UUID and time functions, if the native, integer version are not set then the string version is called if set. Only one will be called.

begin_objectcalled when an object is startedn
end_objectcalled when an object ends
keycalled when an object key is encountered
begin_arraycalled when an array starts
end_arraycalled when an array ends
nullcalled on null
booleancalled on a boolean
fixnumcalled on an integer
decimalcalled on a decimal
stringcalled on a string
uuidcalled on a UUID
uuid_strcalled if the uuid element is NULL
timecalled on time
time_strcalled if the time element is NULL/td>
opoValType
typedef enum { OPO_VAL_NONE = (uint8_t)0, OPO_VAL_NULL = (uint8_t)'n', OPO_VAL_BOOL = (uint8_t)'b', OPO_VAL_INT = (uint8_t)'i', OPO_VAL_STR = (uint8_t)'s', OPO_VAL_DEC = (uint8_t)'d', OPO_VAL_UUID = (uint8_t)'u', OPO_VAL_TIME = (uint8_t)'t', OPO_VAL_OBJ = (uint8_t)'o', OPO_VAL_ARRAY = (uint8_t)'a', } opoValType;

Like JSON each opoVal has a type. These types are defines by the opoValType enum. Each type has a different means of defining the length of the value.

OPO_VAL_NONEno type, usually an error or unset
OPO_VAL_NULLa JSON null
OPO_VAL_BOOLa boolean, true or false
OPO_VAL_INTan 64 bit integer
OPO_VAL_STRa \0 teminated string
OPO_VAL_DECA decimal, float, or double
OPO_VAL_UUIDa UUID represented as two 64 bit unsigned integers
OPO_VAL_TIMEtime as nanoseconds from epoch
OPO_VAL_OBJa JSON object, map, or hash
OPO_VAL_ARRAYan array
opo_val_bool()
bool opo_val_bool(opoErr err, opoVal val)

Gets a boolean from a opoVal if it is a boolean type. If not the err is set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
Returns:the value.
opo_val_bsize()
size_t opo_val_bsize(opoVal val)

Returns the size in bytes of a completed opoVal.

valopoVal to get the byte size of
Returns:the value size.
opo_val_double()
double opo_val_double(opoErr err, opoVal val)

Gets a double from a opoVal if it is a decimal type. If not the err is set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
Returns:the value.
opo_val_get()
opoVal opo_val_get(opoVal val, const char *path)

Gets a member from an object or array opoVal. The function will walk the path until either there is no match or the end of the path is reached. A path member that can be an index can be used for array elements.

valopoVal to get the value from
Returns:the opoVal at the end of the path or NULL.
opo_val_int()
int64_t opo_val_int(opoErr err, opoVal val)

Gets an integer from a opoVal if it is an integer type. If not the err is set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
Returns:the value.
opo_val_iterate()
opoErrCode opo_val_iterate(opoErr err, opoVal val, opoValCallbacks callbacks, void *ctx)

Iterates over a opoVal tree following each branch and calling the appropriate function in the callbacks struct. The return value is the last non OPO_ERR_OK value from the callbacks or OPO_ERR_OK if no error was set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to iterate over
ctxcontext to pass to the callbacks
Returns:the value of err->code.
opo_val_key()
const char* opo_val_key(opoErr err, opoVal key, int *lenp)

Returns the value of a key as a string if the key argument is a key in an object. If the lenp pointer is not NULL then the length of the key string is set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
lenppointer to an integer what will be set to the length
Returns:the key string.
opo_val_member_count()
int opo_val_member_count(opoErr err, opoVal val)

Counts the number of direct children of the value specified.

errErrors are reported using this argument. It must not be NULL.
valthe value to count the members of. If not an array or object then the count will be zero.
Returns:The number of direct members of the val argument.
opo_val_members()
opoVal opo_val_members(opoErr err, opoVal val)

Returns the first child member of a opoVal that is either an object or array. Since all the children are a block of bytes a for look can be used where the terminating condition is exceeding the bsize of the val and calling opo_val_next() for each subsequent member.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the members of
Returns:the first member.
opo_val_next()
opoVal opo_val_next(opoVal val)

Return the next opoVal following the specified val.

valopoVal to get following value from
Returns:the follwoing or next opoVal.
opo_val_size()
size_t opo_val_size(opoVal val)

Returns the size of the value contained in the opoVal. For example, a string value would return the length of the string. An array value would return the number of members in the array.

valopoVal to get the size of
Returns:size of the value.
opo_val_string()
const char* opo_val_string(opoErr err, opoVal val, int *lenp)

Gets a string from a opoVal if it is a string type. If not the err is set. If the lenp pointer is not NULL then the length of the string is set.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
lenppointer to an integer what will be set to the length
Returns:the value.
opo_val_time()
int64_t opo_val_time(opoErr err, opoVal val)

Gets a time value from a opoVal if it is a time type. If not the err is set. The time is in nanoseconds from epoch.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
Returns:the value.
opo_val_type()
opoValType opo_val_type(opoVal val)

Returns the val type.

valopoVal to get the type of
Returns:the type.
opo_val_uuid()
void opo_val_uuid(opoErr err, opoVal val, uint64_t *hip, uint64_t *lop)

Gets a UUID value from a opoVal if it is a UUID type. If not the err is set. A UUID can be thought of as a 128 bit number or as a high and low 64 bit pair. This function allows the extraction of those high and low unsigned integers from the val.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
hippointer to the slot for the high half
loppointer to the slot for the low half
opo_val_uuid_str()
void opo_val_uuid_str(opoErr err, opoVal val, char *str)

Gets a UUID value from a opoVal if it is a UUID type. If not the err is set. The str argument must be at least 37 character long to allow the UUID to be copied to the buffer along with a terminator character.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valopoVal to get the value from
strbuffer to write the UUID to
opo_msg_to_ojc()
ojcVal opo_msg_to_ojc(opoErr err, const opoVal msg)

Encodes an opoVal to an OjC value.

errpointer to an initialized opoErr struct that will be set if an error occurs.
msgopoValmessage to convert to an OjC value
Returns:the converted message.
opo_ojc_msg_size()
size_t opo_ojc_msg_size(ojcVal val)

Calculates the size of a buffer needed to encode an OjC value into a opoVal.

valojcVal value to calculate the needed size from
Returns:the size needed.
opo_ojc_fill_msg()
opoVal opo_ojc_fill_msg(ojcVal val, uint8_t *buf)

Encode an OjC value to a opoVal that is the buf argument. The buffer must be large enough to hold the encoded value.

valvalue to encode
bufbuffer to fill with the encoded value
opo_ojc_to_msg()
opoVal opo_ojc_to_msg(opoErr err, ojcVal val)

Encode an OjC value to a opoVal. The caller is responsible for freeing the returned value.

errpointer to an initialized opoErr struct that will be set if an error occurs.
valvalue to encode
Returns:an allocated The opoVal.