.\" Copyright (c) 2001-2007 Hypertriton, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistribution of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd March 17, 2002
.Dt AG_OBJECT 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.0
.Sh NAME
.Nm AG_Object
.Nd agar object system
.Sh SYNOPSIS
.Bd -literal
#include
.Ed
.Sh DESCRIPTION
The Agar object system provides object-oriented programming functionality
(e.g., inheritance, virtual functions, etc.) to applications written in
different languages (currently C, C++, Objective C, Perl and Ada).
.Sh EXAMPLE APPLICATIONS
The Agar-GUI library is intended to work under as many platforms, from as
many programming languages as possible so its base components are implemented
in ANSI C, but Agar-GUI still makes extensive use of inheritance, virtual
functions, virtual filesystems, etc.
Most widget classes in Agar-GUI are derived from other widget classes.
The task of implementing custom Agar widgets in C or other languages, as part
of a third-party library or application, would be tedious and redundant without the
.Nm
interface.
.Sh INITIALIZATION AND VFS FUNCTIONS
.nr nS 1
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectNew "AG_Object *parent" "const char *name" "AG_ObjectClass *classInfo"
.Pp
.Ft "void"
.Fn AG_ObjectInit "AG_Object *obj" "AG_ObjectClass *classInfo"
.Pp
.Ft "void"
.Fn AG_ObjectInitStatic "AG_Object *obj" "AG_ObjectClass *classInfo"
.Pp
.Ft "void"
.Fn AG_ObjectAttach "AG_Object *new_parent" "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectAttachToNamed "AG_Object *vfsRoot" "const char *path" "AG_Object *child"
.Pp
.Ft "void"
.Fn AG_ObjectDetach "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectDelete "AG_Object *obj"
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectRoot "AG_Object *obj"
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectParent "AG_Object *obj"
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectFind "AG_Object *vfsRoot" "const char *name"
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectFindF "AG_Object *vfsRoot" "const char *fmt" "..."
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectFindParent "AG_Object *obj" "const char *name" "const char *type"
.Pp
.Ft "AG_Object *"
.Fn AG_ObjectFindChild "AG_Object *obj" "const char *name"
.Pp
.Ft "int"
.Fn AG_ObjectCopyName "AG_Object *obj" "char *pathbuf" "size_t pathbuf_len"
.Pp
.Ft "void"
.Fn AG_ObjectLock "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectUnlock "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_LockVFS "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_UnlockVFS "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectSetName "AG_Object *obj" "const char *fmt" "..."
.Pp
.Ft "void"
.Fn AG_ObjectGenName "AG_Object *obj" "AG_ObjectClass *classInfo" "char *name" "size_t len"
.Pp
.Ft "void"
.Fn AG_ObjectGenNamePfx "AG_Object *obj" "const char *prefix" "char *name" "size_t len"
.Pp
.Ft "void"
.Fn AG_ObjectSetDebugFn "AG_Object *obj" "void (*fn)(void *obj, void *userPtr, void *msg)" "void *userPtr"
.Pp
.Fn AGOBJECT_FOREACH_CHILD "AG_Object *child" "AG_Object *parent" "TYPE type"
.Pp
.nr nS 0
The
.Fn AG_ObjectNew
function allocates and initializes a new object instance of the given class.
The object is attached to
.Fa parent ,
unless the argument is NULL.
If
.Fa name
is NULL, a unique name of the form
.Dq #
is automatically generated.
If both
.Fa parent
and
.Fa name
are specified and the parent object already has a child of the given name,
.Fn AG_ObjectNew
fails and returns NULL.
.Pp
The
.Fn AG_ObjectInit
function initializes an object of the specified class.
This involves invoking the
.Fn init
operation associated with every class in the inheritance hierarchy.
.Fa name
specifies a name for the object instance (maximum
.Dv AG_OBJECT_NAME_MAX
bytes and must not contain
.Sq /
characters).
.Fa classInfo
should point to an initialized
.Ft AG_ObjectClass
structure (see
.Dq CLASSES
section).
The
.Fa flags
argument specifies a default set of flags (see
.Dq FLAGS
section).
.Pp
The
.Fn AG_ObjectInitStatic
function is a variant of
.Fn AG_ObjectInit
which marks the new object as statically-allocated.
(see description of the
.Dv AG_OBJECT_STATIC
flag).
.Pp
Objects are organized in a tree structure.
.Fn AG_ObjectAttach
attaches an object to a new parent and
.Fn AG_ObjectDetach
detaches an object from its current parent.
These operations raise
.Sq attached
and
.Sq detached
events.
Prior to detaching the object,
.Fn AG_ObjectDetach
cancels scheduled
.Xr AG_Timeout 3
events where the
.Dv AG_CANCEL_ONDETACH
flag is set.
If
.Fa parent
is NULL,
.Fn AG_ObjectAttach
is a no-op.
.Pp
The
.fn AG_ObjectDelete
routine invokes
.Fn AG_ObjectDetach
if the object is attached to a parent, followed by
.Fn AG_ObjectDestroy .
.Pp
.Fn AG_ObjectAttachToNamed
is a variant of
.Fn AG_ObjectAttach
which looks up the parent inside the specified VFS using the pathname
.Fa path .
.Pp
.Fn AG_ObjectRoot
returns a pointer to the root of the VFS which the given object is attached to.
.Fn AG_ObjectParent
returns the immediate parent of the given object.
.Pp
The
.Fn AG_ObjectFind
and
.Fn AG_ObjectFindF
functions perform a pathname lookup on the specified VFS and return the object
if found, NULL otherwise.
.Pp
.Fn AG_ObjectFindParent
searches all parent objects of the given object for one matching the specified
.Fa name ,
or the standard class specification in
.Fa type .
Either argument can be NULL.
.Pp
.Fn AG_ObjectFindChild
performs a name lookup on the immediate children of the specified object and
return the matching object if found, otherwise NULL.
.Pp
The
.Fn AG_ObjectCopyName
function copies the absolute pathname of an object instance to a fixed-size
buffer, returning 0 on success and -1 on failure.
Under multithreading, the returned pathnames can be considered valid only
as long as the VFS of the object remains locked.
.Pp
The
.Fn AG_ObjectLock
and
.Fn AG_ObjectUnlock
functions acquire or release the mutex associated with the given object.
This mutex protects all read/write members of the
.Nm
structure, except
.Fa parent ,
.Fa root
and the list of child objects
.Fa cobjs
which are all considered part of the virtual filesystem and are instead
protected by
.Fn AG_LockVFS .
In most cases, it is best to use the
.Fn AG_ObjectLock
mutex as a general-purpose locking device for subclasses of
.Nm ,
because it is guaranteed to be held during processing of events posted to the
object, or object operations such as
.Fn load
and
.Fn save .
.Pp
The
.Fn AG_LockVFS
and
.Fn AG_UnlockVFS
functions acquire or release the lock protecting the layout of the entire
virtual system which the given object is part of.
.Pp
Note that all lock/unlock functions are turned to no-ops if Agar is compiled
without threads support.
.Pp
.Fn AG_ObjectSetName
changes the name of the given object.
If the object is attached to a VFS, it is assumed to be locked.
.Pp
.Fn AG_ObjectGenName
generates an object name string unique to the specified parent object
.Fa obj .
The class name is used as prefix, followed by a number.
The name is written to the fixed-size buffer
.Fa name
of the given size
.Fa len .
In a multithreaded context, the name is only guaranteed to remain unique as
long as the parent object's VFS is locked.
Similarly,
.Fn AG_ObjectGenNamePfx
generates a name using the specified prefix instead of the class name.
.Pp
.Fn AG_ObjectSetDebugFn
specifies a function to process debug messages (as issued by
.Xr AG_Debug 3 )
for the object.
This function is a no-op unless Agar was compiled with --enable-debug.
.Pp
The
.Fn AGOBJECT_FOREACH_CHILD
macro iterates
.Fa child
over every child object of
.Fa parent .
The
.Fa child
pointer is cast to the given structure
.Fa type ,
without type checking.
Example:
.Bd -literal
struct my_class *chld;
AGOBJECT_FOREACH_CHILD(chld, parent, my_class) {
printf("Child object: %s\\n", AGOBJECT(chld)->name);
}
.Ed
.Sh CLASSES
.nr nS 1
.Ft "void"
.Fn AG_RegisterClass "AG_ObjectClass *classInfo"
.Pp
.Ft "void"
.Fn AG_UnregisterClass "AG_ObjectClass *classInfo"
.Pp
.Ft "void"
.Fn AG_RegisterNamespace "const char *name" "const char *prefix" "const char *url"
.Pp
.Ft "void"
.Fn AG_UnregisterNamespace "const char *name"
.Pp
.Ft "AG_ObjectClass *"
.Fn AG_LookupClass "const char *classSpec"
.Pp
.Ft "AG_ObjectClass *"
.Fn AG_LoadClass "const char *classSpec"
.Pp
.Ft "void"
.Fn AG_RegisterModuleDirectory "const char *path"
.Pp
.Ft "void"
.Fn AG_UnregisterModuleDirectory "const char *path"
.Pp
.Ft "int"
.Fn AG_OfClass "AG_Object *obj" "const char *pattern"
.Pp
.Ft "AG_ObjectClass *"
.Fn AG_ObjectSuperclass "AG_Object *obj"
.Pp
.Fn AGOBJECT_FOREACH_CLASS "AG_Object *child" "AG_Object *parent" "TYPE type" "const char *pattern"
.Pp
.nr nS 0
The
.Fn AG_RegisterClass
function registers a new object class.
The
.Fa classInfo
argument should point to an initialized
.Ft AG_ObjectClass
structure, which is defined as:
.Bd -literal
typedef struct ag_object_class {
const char *name; /* Class name */
size_t size; /* Size of structure */
AG_Version ver; /* Version numbers */
void (*init)(void *obj);
void (*reinit)(void *obj);
void (*destroy)(void *obj);
int (*load)(void *obj, AG_DataSource *buf, const AG_Version *ver);
int (*save)(void *obj, AG_DataSource *buf);
void *(*edit)(void *obj);
} AG_ObjectClass;
.Ed
.Pp
The structure pointed by
.Fa classInfo
is used directly, it is not duplicated.
.Pp
Note that it is customary to overload
.Ft AG_ObjectClass .
For example,
.Ft AG_WidgetClass
in Agar-GUI (see
.Xr AG_Widget 3 )
augments
.Ft AG_ObjectClass
with widget-specific operations such as
.Fn draw
and
.Fn sizeRequest .
.Pp
The
.Va name
string specifies the full inheritance hierarchy and name of this class.
Subclasses are separated by colons, as in
.Dq AG_Superclass:AG_Subclass ,
or alternatively,
.Dq Namespace(Superclass:Subclass)
or
.Dq Namespace(Superclass:Subclass)@modules .
If the optional
.Sq @modules
string exists, it specifies a comma-separated list of dynamically-linked
library (modules) accessible from
.Xr AG_DSO 3 .
It is implied that
.Ft AG_Object
is the "root class", so there is no need to specify it in the string.
.Pp
.Va size
specifies the size in bytes of the object instance structure.
.Va ver
is the datafile version number (see
.Xr AG_Version 3 ) .
.Pp
The
.Fn init
operation initializes an
.Nm
instance.
.Fn reinit
releases any element of the dataset that has been dynamically allocated.
It is invoked by the object system prior to
.Fn load
or
.Fn destroy .
.Pp
The
.Fn destroy
operation is invoked from
.Fn AG_ObjectDestroy
to release any resources which are not handled by
.Fn reinit .
Note that
.Fn destroy
must not free the
.Nm
structure itself.
.Pp
The
.Fn load
and
.Fn save
operations are responsible for archiving the dataset (see the
.Dq ARCHIVING
section for more information).
.Pp
When defined, the
.Fn edit
operation generates user interface elements allowing the user to edit
the object's dataset.
It is a generic operation, not dependent on any particular GUI library.
If using the Agar-GUI for example,
.Fn edit
is expected to create a
.Xr AG_Window 3
or a container widget such as
.Xr AG_Box 3 .
.Pp
Note that whenever the
.Fn init ,
.Fn reinit ,
.Fn load ,
.Fn save
and
.Fn destroy
operations are used, they are invoked for every class in the inheritance
hierarchy of the given object.
.Pp
.Fn AG_UnregisterClass
removes the specified object class.
.Pp
.Fn AG_RegisterNamespace
registers a new namespace with the specified name, prefix and informational
URL.
For example, Agar registers its own namespace using:
.Bd -literal
AG_RegisterNamespace("Agar", "AG_", "http://libagar.org/");
.Ed
.Pp
Once the namespace is registered, it is possible to specify inheritance
hierarchies using the
.Em namespace
format:
.Bd -literal
Agar(Widget:Button):MyLib(MyButton)
.Ed
.Pp
or the equivalent
.Em expanded
format:
.Bd -literal
AG_Widget:AG_Button:MY_Button
.Ed
.Pp
The
.Fn AG_UnregisterNamespace
function removes all information about the specified namespace.
.Pp
The
.Fn AG_LookupClass
function looks up the
.Ft AG_ObjectClass
structure describing the specified class (in namespace or expanded format).
If there is no currently registered class matching the specification,
.Fn AG_LookupClass
returns NULL.
.Pp
.Fn AG_LoadClass
looks for a terminating
.Sq @mylib
string in the given class specification (in namespace or expanded format),
and scans the registered module directories (see
.Fn AG_RegisterModuleDirectory )
for a
.Pa mylib
dynamic library (the actual filename used is platform-dependent).
If the library is found, it is loaded into the current process's address
space using the
.Xr AG_DSO 3
interface.
.Pp
.Fn AG_UnloadClass
unregisters the specified class and also decrements the reference count of
any dynamically-located module associated with it.
If this reference count reaches zero, the module is removed from the current
process's address space.
.Pp
The
.Fn AG_RegisterModuleDirectory
function adds the specified directory to the module search path.
.Fn AG_UnregisterModuleDirectory
removes the specified directory from the search path.
.Pp
The
.Fn AG_OfClass
function returns 1 if the object is an instance of the class specified in
the
.Fa pattern ,
string.
The pattern may contain wildcards such as
.Dq MyClass:*
or
.Dq MyClass:*:MySubclass:* .
.Pp
The
.Fn AG_ObjectSuperclass
function returns a pointer to the
.Fa AG_ObjectClass
structure describing the superclass of the given object (or if the object is
an instance of the base class, the base class is returned).
.Pp
The
.Fn AGOBJECT_FOREACH_CLASS
macro iterates
.Fa child
over every child object of
.Fa parent
which is an instance of the class specified by
.Fa pattern .
.Fa child
is cast to the given structure
.Fa type .
Example:
.Bd -literal
struct my_class *chld;
AGOBJECT_FOREACH_CLASS(chld, parent, my_class, "MyClass") {
printf("Object %s is an instance of MyClass\\n",
AGOBJECT(chld)->name);
}
.Ed
.Sh DEPENDENCIES
.nr nS 1
.Ft "int"
.Fn AG_ObjectInUse "AG_Object *obj"
.Pp
.Ft "AG_ObjectDep *"
.Fn AG_ObjectAddDep "AG_Object *obj" "AG_Object *depobj" "int persistent"
.Pp
.Ft "void"
.Fn AG_ObjectDelDep "AG_Object *obj" "AG_Object *depobj"
.Pp
.Ft "Uint32"
.Fn AG_ObjectEncodeName "AG_Object *obj" "AG_Object *depobj"
.Pp
.Ft "int"
.Fn AG_ObjectFindDep "AG_Object *obj" "Uint32 ind" "AG_Object **objp"
.Pp
.nr nS 0
.Fn AG_ObjectInUse
returns 1 if the given object is being referenced by another object instance
or 0 if it isn't.
.Pp
.Fn AG_ObjectAddDep
either creates a new dependency upon
.Fa depobj
or increments the reference count if one exists.
If the
.Fa persistent
flag is set, the reference is preserved in object archives.
.Fn AG_ObjectDelDep
decrements the reference count upon
.Fa depobj
and removes the dependency if the count reaches zero (unless the object has the
.Dv AG_OBJECT_PRESERVE_DEPS
flag set).
.Pp
.Fn AG_ObjectEncodeName
returns a 32-bit integer identifier for the dependency, suitable for writing
into data files.
It may return the special values 0 (NULL reference) and 1 (self-reference),
the meaning of which is object-specific.
.Pp
.Fn AG_ObjectFindDep
tries to resolve the given 32-bit dependency identifier, return 0 on success
and -1 on failure.
.Sh RELEASING RESOURCES
.nr nS 1
.Ft "void"
.Fn AG_ObjectDestroy "AG_Object *obj"
.Pp
.Ft void
.Fn AG_ObjectFreeDataset "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectFreeEvents "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectFreeVariables "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectFreeDeps "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectFreeDummyDeps "AG_Object *obj"
.Pp
.Ft "void"
.Fn AG_ObjectFreeChildren "AG_Object *obj"
.Pp
.nr nS 0
The
.Fn AG_ObjectFreeDataset
function frees any dynamically allocated resources by invoking the
.Fn reinit
of every class in the inheritance hierachy.
The function also clears the
.Dv AG_OBJECT_RESIDENT
flag.
Contrary to the
.Fn destroy
operation,
.Fn reinit
must leave the data structures in a consistent state (e.g., for a subsequent
.Fn load
operation).
.Pp
The
.Fn AG_ObjectDestroy
function frees all resources reserved by the given object (and any of its
children that is not being referenced).
.Fn AG_ObjectDestroy
invokes the
.Fn reinit
and
.Fn destroy
operations of every class in the inheritance hierarchy.
Note that
.Fn AG_ObjectDestroy
also cancels any
.Xr AG_Timeout 3
event scheduled for future execution.
Unless the
.Dv AG_OBJECT_STATIC
flag is set,
.Fn AG_ObjectDestroy
invokes
.Xr free 3
on the structure.
.Pp
Internally,
.Fn AG_ObjectDestroy
invokes
.Fn AG_ObjectFreeEvents ,
.Fn AG_ObjectFreeVariables ,
.Fn AG_ObjectFreeDeps
and
.Fn AG_ObjectFreeChildren ,
but these functions may be called directly in order to destroy and reinitialize
the event handler list, the
.Xr AG_Variable 3
table and destroy the child objects,
respectively.
.Pp
In addition to reinitializing the event handler table,
.Fn AG_ObjectFreeEvents
also cancels scheduled events.
.Pp
.Fn AG_ObjectFreeChildren
releases all resources allocated by child objects, under the specified parent
object.
The function assumes that none of the child objects are currently in use.
.Pp
.Fn AG_ObjectFreeDummyDeps
removes entries in the dependency table where the reference count is zero
(which occur in objects that have the
.Dv AG_OBJECT_PRESERVE_DEPS
flag set).
.Pp
.Sh ARCHIVING
.nr nS 1
.Ft "int"
.Fn AG_ObjectLoad "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectLoadFromFile "AG_Object *obj" "const char *file"
.Pp
.Ft "int"
.Fn AG_ObjectLoadData "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectLoadDataFromFile "AG_Object *obj" "const char *file"
.Pp
.Ft "int"
.Fn AG_ObjectLoadGeneric "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectLoadGenericFromFile "AG_Object *obj" "const char *file"
.Pp
.Ft "int"
.Fn AG_ObjectSave "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectSaveAll "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectSaveToFile "AG_Object *obj" "const char *path"
.Pp
.Ft "int"
.Fn AG_ObjectSerialize "AG_Object *obj" "AG_DataSource *ds"
.Pp
.Ft "int"
.Fn AG_ObjectUnserialize "AG_Object *obj" "AG_DataSource *ds"
.Pp
.Ft "int"
.Fn AG_ObjectReadHeader "AG_Object *obj" "AG_ObjectHeader *header"
.Pp
.Ft "int"
.Fn AG_ObjectPageIn "AG_Object *obj"
.Pp
.Ft "int"
.Fn AG_ObjectPageOut "AG_Object *obj"
.Pp
.nr nS 0
These functions implement archiving (or "serialization") of generic object
information and arbitrary datasets to an efficient, machine-independent
representation.
.Pp
The
.Fn AG_ObjectLoad
function (and its variants) are used to load the generic part or the dataset
of either a single object or an object hierarchy, from archived data.
.Fn AG_ObjectLoad
invokes the
.Fn load
operation of every class in the inheritance hierarchy of the object.
.Pp
.Fn AG_ObjectLoad ,
.Fn AG_ObjectLoadGeneric
and
.Fn AG_ObjectLoadData
look for the archive file in the default search path (using the
.Sq load-path
setting of
.Xr AG_Config 3 ) .
.Pp
.Fn AG_ObjectLoadFromFile ,
.Fn AG_ObjectLoadGenericFromFile
and
.Fn AG_ObjectLoadDataFromFile
will load the data from a specific file.
.Pp
Note that when loading object hierarchies, objects will need to be allocated
and initialized from scratch.
This functionality requires that all classes be registered with
.Fn AG_RegisterClass .
.Pp
The
.Fn AG_ObjectSave
function creates an archive of the given object in the default location
(i.e., the
.Sq save-path
setting of
.Xr AG_Config 3 ) .
.Fn AG_ObjectSave
invokes the
.Fn load
operation of every class in the inheritance hierarchy of the object.
The
.Fn AG_ObjectSaveAll
variant also saves the entire tree of child objects.
.Pp
.Fn AG_ObjectSaveToFile
archives the given object to the specified file.
.Pp
.Fn AG_ObjectSerialize
writes an archive of the given object to the specified
.Xr AG_DataSource 3 ,
and
.Fn AG_ObjectUnserialize
reads an archive of the given object.
Note that the
.Dv AG_OBJECT_CHLD_AUTOSAVE
feature will not work with these functions.
.Pp
The
.Fn AG_ObjectReadHeader
routine decodes a standard Agar object archive header.
On success, it returns 0 and writes the information to the
.Fa header
structure:
.Bd -literal
typedef struct ag_object_header {
char hier[AG_OBJECT_HIER_MAX]; /* Inheritance hierarchy */
char libs[AG_OBJECT_LIBS_MAX]; /* Library list */
char classSpec[AG_OBJECT_HIER_MAX]; /* Full class specification */
Uint32 dataOffs; /* Dataset offset */
AG_Version ver; /* AG_Object version */
Uint flags; /* Object flags */
} AG_ObjectHeader;
.Ed
.Pp
The
.Fn AG_ObjectPageIn
function loads an object's dataset into memory, assuming it is a persistent
object and its dataset can be found on storage.
On success, the
.Dv AG_OBJECT_RESIDENT
flag is set.
.Fn AG_ObjectPageOut
checks whether an object is referenced by another object and if that is
not the case, the dataset is archived to storage and freed from memory.
Both functions return 0 on success or -1 if an error occured.
.Sh FLAGS
The following public
.Nm
flags are defined:
.Bl -tag -width "AG_OBJECT_NON_PERSISTENT "
.It AG_OBJECT_FLOATING_VARS
Remove all entries of the
.Xr AG_Variable 3
table in
.Fn AG_ObjectLoad .
By default, the existing table is preserved and entries are created or
replaced by items found in the archive.
.It AG_OBJECT_NON_PERSISTENT
Disables archiving of the object and its children.
If set,
.Fn AG_ObjectSave
becomes a no-op and
.Fn AG_ObjectLoad
calls will fail.
.It AG_OBJECT_INDESTRUCTIBLE
Advisory and application-specific.
.It AG_OBJECT_RESIDENT
Read-only flag set by the object system to indicate that the object's dataset
is currently resident in memory.
This flag is set by
.Fn AG_ObjectNew ,
.Fn AG_ObjectLoadData
and
.Fn AG_ObjectPageIn
and is cleared by
.Fn AG_ObjectFreeDataset
and
.Fn AG_ObjectPageOut .
.It AG_OBJECT_PRESERVE_DEPS
Disable automatic removal of object dependencies when reference counts
reach 0.
.It AG_OBJECT_STATIC
Indicates that this object is either statically-allocated (or allocated
through another facility than
.Xr malloc 3 ) .
The
.Fn AG_ObjectDestroy
operation will not call
.Xr free 3
on the structure.
.It AG_OBJECT_READONLY
Advisory and application-specific.
.It AG_OBJECT_REOPEN_ONLOAD
If the object has a
.Sq edit
operation, arrange for all graphical interface elements (as returned by
.Sq edit )
to be automatically destroyed and recreated after any
.Fn AG_ObjectLoad
call.
This flag is useful for complex objects where the graphical interface
references elements of the dataset.
.It AG_OBJECT_REMAIN_DATA
Prevent the object's dataset from being automatically freed (with
.Fn AG_ObjectFreeDataset )
as a result of an
.Fn AG_ObjectPageOut
call, when the reference count reaches zero.
.It AG_OBJECT_DEBUG
Enable per-object debugging; application-specific.
.It AG_OBJECT_NAME_ONATTACH
Request that
.Fn AG_ObjectAttach
calls automatically generates a name for the child object being attached.
The name will be unique in the parent.
.It AG_OBJECT_CHLD_AUTOSAVE
Arrange for child objects to be automatically saved along with the object
when
.Fn AG_ObjectSave*
is invoked.
.El
.Sh EVENTS
The
.Nm
mechanism generates the following events:
.Pp
.Bl -tag -width 2n
.It Fn attached "void"
The object has been attached to another.
This event originates from the parent object.
The linkage lock is held during the execution of the event handler.
.It Fn detached "void"
The object has been detached from its parent.
The linkage lock is held during the execution of the event handler.
This event originates from the parent.
.It Fn child-attached "void"
Same as
.Fn attached ,
except that the event is sent from the child to the parent.
.It Fn child-detached "void"
Same as
.Fn detached ,
except that the event is sent from the child to the parent.
.It Fn moved "AG_Object *new_parent"
The object has been moved from its current parent to
.Fa new_parent .
The linkage lock is held during the execution of the event handler.
This event originates from the previous parent.
.It Fn renamed "void"
The object's name has changed.
.It Fn object-post-load-data "const char *path"
Invoked by
.Fn AG_ObjectLoadData ,
on success.
If the object was loaded from file,
.Fa path
is the pathname of the file.
.It Fn bound "AG_Variable *V"
A new variable binding has been created, or the value of an existing binding
has been updated; see
.Xr AG_Variable 3
for details.
.El
.Sh EXAMPLES
See
.Pa demos/objsystem
in the Agar source distribution.
.Sh SEE ALSO
.Xr AG_Intro 3 ,
.Xr AG_Event 3 ,
.Xr AG_Variable 3 ,
.Xr AG_Timeout 3
.Sh HISTORY
The
.Nm
interface appeared in Agar 1.0