AG_VARIABLE(3)

NAME
AG_Variable - agar object variables

SYNOPSIS

    #include <agar/core.h>

DESCRIPTION
Every Agar AG_Object(3) instance has an associated set of named variables, which are useful for storing primitive data as well as references to external, structured data. An Agar variable can store the following types of data:

•   Integers (e.g., int, Uint, Sint16)
•   Floating-point numbers (e.g., float, double, long double)
•   C strings (dynamically allocated)
•   Generic pointers

An AG_Variable can also reference the following types of data:

•   Integers (e.g., int *, Uint *, Sint16 *)
•   Floating-point numbers (e.g., float *, double *, long double *)
•   C strings (in fixed-size buffers)
•   Agar text elements (see AG_Text(3))
•   Generic pointers
•   Agar objects (pointer to AG_Object(3))
•   Named Agar object variables.

AG_Variable is used extensively throughout Agar and Agar-based libraries. In the Agar-GUI system, GUI widgets use Agar variables to reference external data (also known as "bindings"). For example, the "value" variable of an AG_Numerical(3) spinbutton may be tied to a fixed-size integer, a floating-point number, or any other type implemented by AG_Numerical.

It is also possible to allocate anonymous AG_Variable structures on the fly. For instance, the event system of AG_Object(3) uses a list of AG_Variable elements to describe the list of arguments passed to event handler routines.

INTERFACE
int AG_Defined(AG_Object *obj, const char *name)

AG_Variable * AG_GetVariable(AG_Object *obj, const char *name, void **data)

AG_Variable * AG_GetVariableLocked(AG_Object *obj, const char *name)

AG_Variable * AG_FetchVariable(AG_Object *obj, const char *name, enum ag_variable_type type)

AG_Variable * AG_FetchVariableOfType(AG_Object *obj, const char *name, enum ag_variable_type type)

void AG_LockVariable(AG_Variable *var)

void AG_UnlockVariable(AG_Variable *var)

AG_Variable * AG_GetVariableVFS(AG_Object *obj, const char *name)

int AG_EvalVariable(AG_Object *obj, AG_Variable *var)

void AG_PrintVariable(char *dst, size_t len, AG_Variable *var)

void AG_CopyVariable(AG_Variable *Vdst, const AG_Variable *Vsrc)

void AG_DerefVariable(AG_Variable *Vdst, const AG_Variable *Vsrc)

int AG_CompareVariables(const AG_Variable *a, const AG_Variable *b)

AG_Variable * AG_Set(AG_Object *obj, const char *name, const char *fmt, ...)

void AG_Unset(AG_Object *obj, const char *name)

void AG_VariableSubst(AG_Object *obj, const char *s, char *dst, size_t dst_len)

The AG_Defined() routine returns 1 if the specified variable name is defined under the object obj, otherwise it returns 0. The caller must lock obj before invoking AG_Defined().

The AG_GetVariable() routine searches for a named variable under object obj and returns a pointer to the corresponding AG_Variable structure if found. If no such variable exists, NULL is returned. If the variable is tied to a function, the function is evaluated first. If the data argument is not NULL, a pointer to the variable's primitive data is returned into it (not valid for strings).

AG_GetVariableLocked() looks up the named variable under obj and returns a pointer to the corresponding AG_Variable structure if found, otherwise NULL is returned. If the variable is tied to a function, the function is not evaluated internally. Before returning, AG_GetVariableLocked() acquires any locking devices associated with the variable. The caller is expected to invoke AG_UnlockVariable() when done accessing the data.

The AG_FetchVariable() routine looks up a variable by name, returning a pointer to the corresponding AG_Variable structure. If no such variable exists, a new one of the specified type is allocated.

The AG_FetchVariableOfType() variant works like AG_FetchVariable(), except that preexisting variables of a differing type are automatically destroyed and recreated to match the specified type.

AG_LockVariable() and AG_UnlockVariable() acquire and release any locking device associated with the specified variable.

AG_GetVariableVFS() searches an AG_Object(3) VFS for a variable from a string of the form ‘object:variable’.

The AG_EvalVariable() function evaluates the value of a variable tied to a function. The corresponding function is invoked and the value is returned into the data union. Note that internally, AG_GetVariable() calls AG_EvalVariable(), but AG_GetVariableLocked() does not.

AG_PrintVariable() returns a string representation of the value of variable var into a fixed-size buffer dst, of len bytes.

AG_CopyVariable() copies the contents of a variable from Vsrc to Vdst. Pointer references are preserved. For AG_VARIABLE_STRING variable types, internally-allocated strings are duplicated.

AG_DerefVariable() copies the contents of Vsrc to Vdst, converting pointer references to immediate values. For AG_VARIABLE_STRING variable types, strings are duplicated unconditionally.

The AG_CompareVariables() compares the value of two variables, returning zero if they are identical. If they differ, the difference between the two first differing bytes is returned. If AG_CompareVariables() encounters pointer types, they are not dereferenced (rather the value of the pointer itself is compared).

The AG_Set() sets an object-bound variable value using a format-string interface (see AG_PARSE_VARIABLE_ARGS()).

AG_Unset() deletes the named object-bound variable.

AG_VariableSubst() parses the string s for references of the form "$(foo)", and substitutes those references for the value of variable foo (under object obj). The substituted string is returned into fixed-size buffer dst, of size dst_size.

TYPE-SPECIFIC INTERFACES
The following functions are used to retrieve or set variables of specific types.

The AG_GetFoo() functions return the value of variable name (under object obj). If the variable is a pointer type, it is dereferenced. If it is tied to a function, the function is evaluated first.

The AG_InitFoo() functions initialize an AG_Variable structure var with the specified value val.

The AG_SetFoo() functions set the value of variable name to the specified value val. If the variable does not exist, it is created.

The AG_BindFoo() functions create or modify a typed pointer variable. The argument pVal is a pointer to the actual value.

The AG_BindFooMp() variant accepts an extra lock argument, which is a mutex device (i.e., an AG_Mutex or pthread_mutex_t) to be acquired whenever the data referenced by pVal will be accessed.

The AG_BindFooFn() variants create or modify a variable, tying the variable to a function fn, which will be evaluated whenever the variable is read. A list of optional AG_Event(3) style arguments follow the fn argument.

INTEGERS
Uint AG_GetUint(AG_Object *obj, const char *name)

void AG_InitUint(AG_Variable *var, Uint val)

AG_Variable * AG_SetUint(AG_Object *obj, const char *name, Uint val)

AG_Variable * AG_BindUint(AG_Object *obj, const char *name, Uint *pVal)

AG_Variable * AG_BindUintMp(AG_Object *obj, const char *name, Uint *pVal, AG_Mutex *lock)

AG_Variable * AG_BindUintFn(AG_Object *obj, const char *name, Uint (*fn)(AG_Event *), ...)

int AG_GetInt(AG_Object *obj, const char *name)

void AG_InitInt(AG_Variable *var, int val)

AG_Variable * AG_SetInt(AG_Object *obj, const char *name, int val)

AG_Variable * AG_BindInt(AG_Object *obj, const char *name, int *pVal)

AG_Variable * AG_BindIntMp(AG_Object *obj, const char *name, int *pVal, AG_Mutex *lock)

AG_Variable * AG_BindIntFn(AG_Object *obj, const char *name, int (*fn)(AG_Event *))

Uint8 AG_GetUint8(AG_Object *obj, const char *name)

void AG_InitUint8(AG_Variable *var, Uint8 val)

AG_Variable * AG_SetUint8(AG_Object *obj, const char *name, Uint8 val)

AG_Variable * AG_BindUint8(AG_Object *obj, const char *name, Uint8 *pVal)

AG_Variable * AG_BindUint8Mp(AG_Object *obj, const char *name, Uint8 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindUint8Fn(AG_Object *obj, const char *name, Uint8 (*fn)(AG_Event *))

Sint8 AG_GetSint8(AG_Object *obj, const char *name)

void AG_InitSint8(AG_Variable *var, Sint8 val)

AG_Variable * AG_SetSint8(AG_Object *obj, const char *name, Sint8 val)

AG_Variable * AG_BindSint8(AG_Object *obj, const char *name, Sint8 *pVal)

AG_Variable * AG_BindSint8Mp(AG_Object *obj, const char *name, Sint8 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindSint8Fn(AG_Object *obj, const char *name, Sint8 (*fn)(AG_Event *))

Uint16 AG_GetUint16(AG_Object *obj, const char *name)

void AG_InitUint16(AG_Variable *var, Uint16 val)

AG_Variable * AG_SetUint16(AG_Object *obj, const char *name, Uint16 val)

AG_Variable * AG_BindUint16(AG_Object *obj, const char *name, Uint16 *pVal)

AG_Variable * AG_BindUint16Mp(AG_Object *obj, const char *name, Uint16 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindUint16Fn(AG_Object *obj, const char *name, Uint16 (*fn)(AG_Event *))

Sint16 AG_GetSint16(AG_Object *obj, const char *name)

void AG_InitSint16(AG_Variable *var, Sint16 val)

AG_Variable * AG_SetSint16(AG_Object *obj, const char *name, Sint16 val)

AG_Variable * AG_BindSint16(AG_Object *obj, const char *name, Sint16 *pVal)

AG_Variable * AG_BindSint16Mp(AG_Object *obj, const char *name, Sint16 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindSint16Fn(AG_Object *obj, const char *name, Sint16 (*fn)(AG_Event *))

Uint32 AG_GetUint32(AG_Object *obj, const char *name)

void AG_InitUint32(AG_Variable *var, Uint32 val)

AG_Variable * AG_SetUint32(AG_Object *obj, const char *name, Uint32 val)

AG_Variable * AG_BindUint32(AG_Object *obj, const char *name, Uint32 *pVal)

AG_Variable * AG_BindUint32Mp(AG_Object *obj, const char *name, Uint32 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindUint32Fn(AG_Object *obj, const char *name, Uint32 (*fn)(AG_Event *))

Sint32 AG_GetSint32(AG_Object *obj, const char *name)

void AG_InitSint32(AG_Variable *var, Sint32 val)

AG_Variable * AG_SetSint32(AG_Object *obj, const char *name, Sint32 val)

AG_Variable * AG_BindSint32(AG_Object *obj, const char *name, Sint32 *pVal)

AG_Variable * AG_BindSint32Mp(AG_Object *obj, const char *name, Sint32 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindSint32Fn(AG_Object *obj, const char *name, Sint32 (*fn)(AG_Event *))

Uint64 AG_GetUint64(AG_Object *obj, const char *name)

void AG_InitUint64(AG_Variable *var, Uint64 val)

AG_Variable * AG_SetUint64(AG_Object *obj, const char *name, Uint64 val)

AG_Variable * AG_BindUint64(AG_Object *obj, const char *name, Uint64 *pVal)

AG_Variable * AG_BindUint64Mp(AG_Object *obj, const char *name, Uint64 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindUint64Fn(AG_Object *obj, const char *name, Uint64 (*fn)(AG_Event *))

Sint64 AG_GetSint64(AG_Object *obj, const char *name)

void AG_InitSint64(AG_Variable *var, Sint64 val)

AG_Variable * AG_SetSint64(AG_Object *obj, const char *name, Sint64 val)

AG_Variable * AG_BindSint64(AG_Object *obj, const char *name, Sint64 *pVal)

AG_Variable * AG_BindSint64Mp(AG_Object *obj, const char *name, Sint64 *pVal, AG_Mutex *lock)

AG_Variable * AG_BindSint64Fn(AG_Object *obj, const char *name, Sint64 (*fn)(AG_Event *))

These functions provide an interface to both natural and fixed-size integers. The Uint64 and Sint64 types are only available if AG_HAVE_64BIT is defined.

REAL NUMBERS
float AG_GetFloat(AG_Object *obj, const char *name)

void AG_InitFloat(AG_Variable *var, float val)

AG_Variable * AG_SetFloat(AG_Object *obj, const char *name, float val)

AG_Variable * AG_BindFloat(AG_Object *obj, const char *name, float *pVal)

AG_Variable * AG_BindFloatMp(AG_Object *obj, const char *name, float *pVal, AG_Mutex *lock)

AG_Variable * AG_BindFloatFn(AG_Object *obj, const char *name, float (*fn)(AG_Event *))

double AG_GetDouble(AG_Object *obj, const char *name)

void AG_InitDouble(AG_Variable *var, double val)

AG_Variable * AG_SetDouble(AG_Object *obj, const char *name, double val)

AG_Variable * AG_BindDouble(AG_Object *obj, const char *name, double *pVal)

AG_Variable * AG_BindDoubleMp(AG_Object *obj, const char *name, double *pVal, AG_Mutex *lock)

AG_Variable * AG_BindDoubleFn(AG_Object *obj, const char *name, double (*fn)(AG_Event *))

long double AG_GetLongDouble(AG_Object *obj, const char *name)

void AG_InitLongDouble(AG_Variable *var, long double val)

AG_Variable * AG_SetLongDouble(AG_Object *obj, const char *name, long double val)

AG_Variable * AG_BindLongDouble(AG_Object *obj, const char *name, long double *pVal)

AG_Variable * AG_BindLongDoubleMp(AG_Object *obj, const char *name, long double *pVal, AG_Mutex *lock)

AG_Variable * AG_BindLongDoubleFn(AG_Object *obj, const char *name, long double (*fn)(AG_Event *))

These functions provide an interface to floating-point numbers. The long double functions are only available if AG_HAVE_LONG_DOUBLE is defined.

C STRINGS
size_t AG_GetString(AG_Object *obj, const char *name, char *dst, size_t dst_size)

char * AG_GetStringDup(AG_Object *obj, const char *name)

char * AG_GetStringP(AG_Object *obj, const char *name)

void AG_InitString(AG_Variable *var, const char *s)

void AG_InitStringNODUP(AG_Variable *var, const char *s)

AG_Variable * AG_SetString(AG_Object *obj, const char *name, const char *s)

AG_Variable * AG_SetStringNODUP(AG_Object *obj, const char *name, const char *s)

AG_Variable * AG_PrtString(AG_Object *obj, const char *name, const char *fmt, ...)

AG_Variable * AG_BindString(AG_Object *obj, const char *name, char *s, size_t len)

AG_Variable * AG_BindStringMp(AG_Object *obj, const char *name, char *s, size_t len, AG_Mutex *lock)

AG_Variable * AG_BindStringFn(AG_Object *obj, const char *name, size_t (*fn)(AG_Event *, char *, size_t))

AG_Variable * AG_SetConstString(AG_Object *obj, const char *name, const char *s)

AG_Variable * AG_BindConstString(AG_Object *obj, const char *name, const char **s)

AG_Variable * AG_BindConstStringMp(AG_Object *obj, const char *name, const char **s, AG_Mutex *lock)

These functions provide an interface to C strings. A string variable can either contain a dynamically-allocated buffer, or reference an external, fixed-size buffer.

AG_GetString() returns the contents of a string variable. The string is safely copied to fixed-size buffer dst, of size dst_size. The return value is the number of bytes that would have been copied, were dst_size unlimited.

AG_GetStringDup() returns a newly-allocated copy of the string variable. If the string cannot be allocated, NULL is returned.

The AG_GetStringP() function returns a direct pointer to the buffer containing the string. If the given variable is function-defined (i.e., it was set by AG_BindStringFn()), the value generated by the last AG_EvalVariable() operation is returned. Note that AG_GetStringP() is not free-threaded, so calls to this function should be protected by AG_LockVariable() (as an exception, dynamically-allocated strings set by AG_SetString() are safe to access without locking, as long as the variable's parent object is locked).

AG_InitString() initializes a AG_Variable structure with the given string, which is copied from s. The AG_InitStringNODUP() variant sets the s pointer without copying the string.

The AG_SetString() function creates or modifies a string variable. The s argument is a C string which will be duplicated or copied. If the variable exists as a reference to a fixed-size buffer (i.e., it has been created by AG_BindString()), then the contents of s are copied to the buffer. If the buffer has insufficient space, the string is truncated. The s argument may be set to NULL (in which case further AG_GetString() calls will return NULL).

The AG_SetStringNODUP() variant accepts a pointer to a dynamically-allocated string buffer. This buffer will be freed automatically when the parent object is destroyed.

The AG_PrtString() variant sets a string variable from a format string argument.

AG_BindString() creates or modifies a variable referencing a fixed-size string buffer s, of size len. The AG_BindStringFn() variant ties the variable to a function fn.

TEXT OBJECTS
AG_Text * AG_GetText(AG_Object *obj, const char *name)

void AG_InitText(AG_Variable *var, AG_Text *txt)

AG_Variable * AG_SetText(AG_Object *obj, const char *name, AG_Text *txt)

AG_Variable * AG_BindText(AG_Object *obj, const char *name, AG_Text *txt)

AG_Variable * AG_BindTextMp(AG_Object *obj, const char *name, AG_Text *txt, AG_Mutex *lock)

AG_Variable * AG_BindTextFn(AG_Object *obj, const char *name, AG_Text *(*fn)(AG_Event *))

These functions provide an interface to Agar text objects (see AG_Text(3)).

GENERIC POINTERS
void * AG_GetPointer(AG_Object *obj, const char *name)

void AG_InitPointer(AG_Variable *var, void *val)

AG_Variable * AG_SetPointer(AG_Object *obj, const char *name, void *val)

AG_Variable * AG_BindPointer(AG_Object *obj, const char *name, void **pVal)

AG_Variable * AG_BindPointerMp(AG_Object *obj, const char *name, void **pVal, AG_Mutex *lock)

AG_Variable * AG_BindPointerFn(AG_Object *obj, const char *name, void *(*fn)(AG_Event *))

const void * AG_GetConstPointer(AG_Object *obj, const char *name)

void AG_InitConstPointer(AG_Variable *var, const void *val)

AG_Variable * AG_SetConstPointer(AG_Object *obj, const char *name, const void *val)

AG_Variable * AG_BindConstPointer(AG_Object *obj, const char *name, const void **pVal)

AG_Variable * AG_BindConstPointerMp(AG_Object *obj, const char *name, const void **pVal, AG_Mutex *lock)

AG_Variable * AG_BindConstPointerFn(AG_Object *obj, const char *name, const void *(*fn)(AG_Event *))

These functions provide an interface to generic pointer types.

BITS
AG_Variable * AG_BindFlag(AG_Object *obj, const char *name, Uint *pVal, Uint bitmask)

AG_Variable * AG_BindFlagMp(AG_Object *obj, const char *name, Uint *pVal, Uint bitmask, AG_Mutex *lock)

AG_Variable * AG_BindFlag8(AG_Object *obj, const char *name, Uint8 *pVal, Uint8 bitmask)

AG_Variable * AG_BindFlag8Mp(AG_Object *obj, const char *name, Uint8 *pVal, Uint8 bitmask, AG_Mutex *lock)

AG_Variable * AG_BindFlag16(AG_Object *obj, const char *name, Uint16 *pVal, Uint16 bitmask)

AG_Variable * AG_BindFlag16Mp(AG_Object *obj, const char *name, Uint16 *pVal, Uint16 bitmask, AG_Mutex *lock)

AG_Variable * AG_BindFlag32(AG_Object *obj, const char *name, Uint32 *pVal, Uint32 bitmask)

AG_Variable * AG_BindFlag32Mp(AG_Object *obj, const char *name, Uint32 *pVal, Uint32 bitmask, AG_Mutex *lock)

These functions provide an interface for binding to specific bits in integers. They follow the standard form, with an extra bitmask argument.

NAMED VARIABLE REFERENCES
AG_Variable * AG_BindVariable(AG_Object *obj, const char *name, AG_Object *varObj, const char *varKey)

The AG_BindVariable() function creates a reference to a variable named varKey, under the target object varObj. Whenever AG_GetVariable() or AG_GetVariableLocked() finds a reference variable, the target variable is looked up and returned.

STRUCTURE DATA
For the AG_Variable structure:

char *name
    Variable name string.
AG_VariableType type
    Variable type (see <core/variable.h>).
AG_Mutex *mutex
    Mutex protecting referenced data.
union ag_variable_data data
    Stored data (see <core/variable.h>).

SEE ALSO
AG_Intro(3), AG_List(3), AG_Object(3), AG_Tbl(3), AG_Tree(3)

HISTORY
The AG_Variable interface first appeared in Agar 1.3.4. It replaced the older AG_Prop(3) interface, and widget bindings which were previously stored in AG_Widget(3) itself.