AG_Variable
— agar
object variables
In the Agar object system, each
AG_Object(3)
instance has a set of typed variables. Variables can be named (referenced by
a string key) or anonymous (referenced by an
AG_Variable pointer). Discrete types include:
- Integers (e.g., int, Uint,
long, Sint16,
Uint64).
- Real numbers (e.g., float,
double, long double).
- C strings (unbounded; auto-allocated).
- Generic pointers.
- Functions.
Typed references (or "pointer variables") are also
supported. Optionally, pointer variables can be configured to acquire an
AG_Mutex(3)
locking device prior to accessing the data. Base reference types
include:
- Integers (e.g., int *, Uint *,
long *, Sint16 *,
Uint64 *).
- Real numbers (e.g., float *, double
*, long double *).
- Bits in a fixed-size word (per given bitmask).
- Bounded C strings (in fixed-size buffer).
- Agar objects (pointer to
AG_Object(3)).
- Proxy for another
AG_Variable
in an external
AG_Object(3).
int
AG_Defined
(AG_Object
*obj, const char
*name);
AG_Variable *
AG_GetVariable
(AG_Object
*obj, const char
*name, void
**data);
AG_Variable *
AG_AccessVariable
(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_Size
AG_PrintVariable
(char
*dst, AG_Size 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);
void
AG_Unset
(AG_Object
*obj, const char
*name);
void
AG_VariableSubst
(AG_Object
*obj, const char
*s, char *dst,
AG_Size dst_len);
AG_Defined
()
returns 1 if the variable name is defined under the
object obj, otherwise it returns 0. The object
obj must be locked.
AG_GetVariable
()
searches for a variable name under
obj and returns a pointer to the corresponding
AG_Variable in a locked condition. The caller must use
AG_UnlockVariable
() when finished accessing the
variable data. A pointer to the data itself is also returned in the
data argument. If the variable is undefined, a fatal
exception is raised.
The
AG_AccessVariable
()
function searches for a variable by name and returns
the matching AG_Variable in a locked condition. The
caller must use AG_UnlockVariable
() when done
accessing the data. Both AG_GetVariable
() and
AG_AccessVariable
() return NULL if the named
variable is undefined.
The
AG_FetchVariable
()
function searches for a variable by name and
type. If found, return the corresponding
AG_Variable. If the variable is undefined then a new
one of the specified type is automatically created and
returned. Raises an exception if insufficient memory is available.
The
AG_FetchVariableOfType
()
variant works like AG_FetchVariable
(), except that
if the variable exists and is of a different type, then it is mutated into
type and returned.
Note: Unlike
AG_GetVariable
()
and AG_AccessVariable
(),
AG_FetchVariable
() and
AG_FetchVariableOfType
() do not return the
AG_Variable locked.
AG_LockVariable
()
and AG_UnlockVariable
() acquire and release any
locking device associated with the specified variable.
AG_PrintVariable
()
generates a string from the value of variable var. The
string is written to the fixed-size buffer dst (of
size len). AG_PrintVariable
()
returns the length of the string it tried to create.
AG_CopyVariable
()
copies the contents of a variable from Vsrc to
Vdst. Pointer references are preserved. Discrete
strings are duplicated.
AG_DerefVariable
()
copies the contents of Vsrc to
Vdst, converting pointer references to immediate
values. Discrete strings are duplicated, and pointers to strings are turned
into discrete strings.
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).
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.
The following functions get and set variables of specific
types.
AG_Get<Type>
()
returns the value of variable name under object
obj with implicit dereferencing. If the variable is a
pointer type then the value referenced by it is returned.
The
AG_Init<Type>
()
functions initialize an AG_Variable structure
var with the specified value
val.
The
AG_Set<Type>
()
functions set the value of variable name to the
specified value val. Implicit dereferencing is done.
If the variable does not exist, it is created.
The
AG_Bind<Type>
()
functions create or modify a typed pointer variable. The argument
pVal is a pointer to the actual value.
The
AG_Bind<Type>Mp
()
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.
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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.
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);
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);
These functions provide an interface to floating-point
numbers.
AG_Size
AG_GetString
(AG_Object
*obj, const char
*name, char *dst,
AG_Size 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);
AG_Variable *
AG_SetString
(AG_Object
*obj, const char
*name, const char
*s);
AG_Variable *
AG_SetStringF
(AG_Object
*obj, const char
*name, const char
*fmt, ...);
AG_Variable *
AG_SetStringNODUP
(AG_Object
*obj, const char
*name, const char
*s);
AG_Variable *
AG_BindString
(AG_Object
*obj, const char
*name, char *s,
AG_Size len);
AG_Variable *
AG_BindStringMp
(AG_Object
*obj, const char
*name, char *s,
AG_Size len,
AG_Mutex *lock);
These functions provide an interface to C strings. A string
variable may contain an unbounded (auto-allocated) string or it may
reference a bounded string (i.e., a string contained in a fixed-size
buffer).
AG_GetString
()
copies the contents of a string variable to a fixed-size buffer
dst of size dst_size and returns
the number of bytes that would have been copied were
dst_size unlimited.
AG_GetStringDup
()
returns a newly-allocated copy of the contents of a string variable. If the
copy cannot be allocated, NULL is returned. The returned string should be
freed with
AG_Free(3)
after use.
The potentially-unsafe
AG_GetStringP
()
returns a direct pointer to the buffer containing the string. It is not
free-threaded (so the object must be locked, and calls protected by
AG_LockVariable
()). Auto-allocated strings set by
AG_SetString
() may be accessed safely without
locking as long as the parent object is locked.
AG_InitString
()
initializes a AG_Variable structure with the given
string, which is copied from s.
AG_SetString
()
sets the value of a string variable (possibly creating a new variable). The
s argument is a C string which will be either
duplicated or copied. If the given variable exists and is a reference to a
fixed-size buffer (i.e., it was generated by a
AG_BindString
() call), then the contents of
s are copied to the the referenced buffer. If the
buffer is too small to fit the string, the string is safely truncated. The
s argument may be set to NULL (in which case further
AG_GetString
() calls will also return NULL). The
AG_SetStringF
() variant accepts a
printf(3)
style format string argument.
The potentially-unsafe
AG_SetStringNODUP
()
variant accepts a pointer to a dynamically-allocated string buffer which
will be free'd whenever the parent object is destroyed.
AG_BindString
()
creates or modifies a variable referencing a fixed-size string buffer
s, of size len.
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);
These functions provide an interface to generic pointer types.
AG_Variable *
AG_SetFn
(AG_Object
*obj, const char
*name, AG_EventFn
fn, const char
*fmt, ...);
AG_SetFn
()
sets the value of a function pointer variable to the specified function
fn and optional function arguments
fmt. The object must be locked. See
AG_Event(3)
for more information on the argument format.
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.
AG_Variable *
AG_BindObject
(AG_Object
*obj, const char
*name, AG_Object
*varObj);
AG_Variable *
AG_BindVariable
(AG_Object
*obj, const char
*name, AG_Object
*varObj, const char
*varKey);
The
AG_BindObject
()
function creates an Object->Object reference and hard dependency to an
external object varObj and return a
P_OBJECT
type Variable on success. A hard dependency
implies that if both obj and
varObj share the same VFS then Agar will not allow
varObj to be released from memory (or detached from
the VFS) for as long as the reference exists.
The
AG_BindVariable
()
function creates an Object->Variable reference to the variable called
varKey under an external object
varObj, returning a P_VARIABLE
type Variable on success. Whenever this Variable is accessed, the external
object will be locked and a copy of its variable
varKey will be returned implicitely. Note: Circular
references must be avoided.
AG_BindVariable
()
creates an anonymous Object->Object reference to
varObj (which is also removed by
AG_Unset
() or
AG_ObjectFreeVariables(3)
when no more Object->Variable references make use of the object).
AG_BindObject
()
and AG_BindVariable
() may fail and return NULL.
For the AG_Variable structure:
- char name[AG_VARIABLE_NAME_MAX]
- Variable name (or "" = anonymous).
- 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>).
The following code tests if "delete-me" is defined and
if so, deletes it:
AG_Object *obj;
if (AG_Defined(obj, "delete-me"))
AG_Unset(obj, "delete-me");
The following code atomically increments a variable
"value", which may be either an int or a
float:
void
IncrementValue(AG_Object *obj)
{
AG_Variable *V;
void *pValue;
V = AG_AccessVariable(obj, "value", &pValue);
switch (AG_VARIABLE_TYPE(V)) {
case AG_VARIABLE_INT:
(*(int *)pValue)++;
break;
case AG_VARIABLE_FLOAT:
(*(float *)pValue) += 1.0f;
break;
}
AG_UnlockVariable(obj);
}
The following code prints a string representation of a variable
"value" to a fixed-size buffer buf:
char buf[32];
AG_Object *obj;
AG_Variable *V;
if ((V = AG_AccessVariable(obj, "value")) == NULL) {
AG_FatalError(NULL);
}
AG_PrintVariable(buf, sizeof(buf), V);
AG_UnlockVariable(V);
AG_Verbose("value = %s\n", buf);
The following code atomically duplicates the contents of variable
"copy-me" from one object objSrc to another
object objDst:
AG_Object *objSrc, *objDst;
AG_Variable *Vsrc, *Vdst;
Vsrc = AG_AccessVariable(objSrc, "copy-me");
Vdst = AG_AccessVariable(objDst, "copy-me");
if (Vsrc == NULL || Vdst == NULL)
AG_FatalError(NULL);
AG_CopyVariable(Vdst, Vsrc);
if (AG_CompareVariables(Vsrc, Vdst) == 0)
AG_Verbose("Copy successful\n");
AG_UnlockVariable(Vdst);
AG_UnlockVariable(Vsrc);
The following code uses object variable substitution to generate
the string "Hello world!" into a fixed-size buffer:
char buf[32];
AG_Object *obj;
AG_SetString(obj, "the-string", "world");
AG_VariableSubst(obj, "Hello $(the-string)!",
buf, sizeof(buf));
AG_Verbose("%s\n", buf);
AG_Variable
is used to represent
AG_Object(3)
instance variables and arguments passed to
AG_Event(3)
callback routines.
In Agar-GUI, widgets use AG_Variable
to
reference data in memory (also known as "bindings"). Refer to the
"BINDINGS" section of each widget's manual page for details.
In Agar-GUI, the "value" of an
AG_Numerical(3)
spinbutton can be tied to an int, a
float a mutex-protected Uint32,
etc.
The AG_Variable
interface first appeared
in Agar 1.3.4. It replaced the older "AG_Prop" interface and
AG_Widget(3)
specific bindings. In Agar 1.6.0, Object->Object references appeared and
AG_GetVariableLocked
() was renamed
AG_AccessVariable
(). Functions appeared in Agar
1.7.0.