Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
AG_OBJECT(3)		    Library Functions Manual		  AG_OBJECT(3)

NAME
       AG_Object -- agar object	system

SYNOPSIS
       #include	<agar/core.h>

DESCRIPTION
       The  Agar  object system	provides object-oriented programming capabili-
       ties (inheritance and virtual functions)	as well	as serialization, man-
       aged timers, abstracted data types and a	virtual	filesystem (VFS).

       Agar objects are	organized in a tree structure, which we	 refer	to  as
       the  VFS.   Any	AG_Object  can become the root of a VFS.  A VFS	can be
       made persistent to the degree required by the  application.   Agar  ob-
       jects  can  be  serialized  to a	machine-independent binary format with
       AG_DataSource(3).

OBJECT INTERFACE
       AG_Object  *  AG_ObjectNew(AG_Object   *parent,	 const	 char	*name,
       AG_ObjectClass *classInfo)

       void AG_ObjectInit(AG_Object *obj, AG_ObjectClass *classInfo)

       void AG_ObjectAttach(AG_Object *newParent, AG_Object *child)

       void AG_ObjectDetach(AG_Object *child)

       void AG_ObjectMoveToHead(AG_Object *obj)

       void AG_ObjectMoveToTail(AG_Object *obj)

       void AG_ObjectMoveUp(AG_Object *obj)

       void AG_ObjectMoveDown(AG_Object	*obj)

       void AG_ObjectDelete(AG_Object *obj)

       AG_Object * AG_ObjectRoot(AG_Object *obj)

       AG_Object * AG_ObjectParent(AG_Object *obj)

       AG_Object * AG_ObjectFind(AG_Object *vfsRoot, const char	*format, ...)

       AG_Object * AG_ObjectFindS(AG_Object *vfsRoot, const char *name)

       AG_Object * AG_ObjectFindParent(AG_Object *obj, const char *name, const
       char *type)

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

       char * AG_ObjectGetName(AG_Object *obj)

       int AG_ObjectCopyName(AG_Object *obj, char *buf,	AG_Size	bufSize)

       void AG_ObjectSetName(AG_Object *obj, const char	*fmt, ...)

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

       void  AG_ObjectGenName(AG_Object	 *obj, AG_ObjectClass *classInfo, char
       *name, AG_Size nameSize)

       void  AG_ObjectGenNamePfx(AG_Object  *obj,  const  char	*prefix,  char
       *name, AG_Size nameSize)

       AGOBJECT_FOREACH_CHILD(AG_Object	*child,	AG_Object *parent, TYPE	type)

       The  AG_ObjectNew() function allocates and initializes a	new object in-
       stance of the class described by	classInfo.  The	object is attached  to
       parent  (unless	parent is NULL).  If insufficient memory is available,
       or parent and name are both specified and a child object	of  the	 given
       name already exists then	AG_ObjectNew() fails and return	NULL.

       AG_ObjectInit()	initializes an already-allocated instance of the class
       described by classInfo.	It invokes the init() method over  each	 class
       in the inheritance hierarchy.

       The name	argument to AG_ObjectNew() and AG_ObjectInit() may be NULL, in
       which case a unique name	(e.g., "object0") will be generated.  name may
       not exceed AG_OBJECT_NAME_MAX characters	and must not contain `/'.  The
       classInfo  argument  must point to an initialized AG_ObjectClass	struc-
       ture (see "OBJECT CLASSES").

       AG_ObjectAttach() attaches an object child to another object newParent,
       raising an `attached' event.  It's a no-op if newParent is NULL.

       AG_ObjectDetach() removes an object child from  its  parent  (if	 any),
       cancelling scheduled AG_Timer(3)	expirations before raising `detached'.

       AG_ObjectMoveUp(),   AG_ObjectMoveDown(),   AG_ObjectMoveToHead()   and
       AG_ObjectMoveToTail() move the object in	the parent  object's  list  of
       child  objects.	 This is useful	when the ordering of objects is	impor-
       tant.

       AG_ObjectDelete()     calls     AG_ObjectDetach()      followed	    by
       AG_ObjectDestroy().

       AG_ObjectRoot()	returns	 a  pointer  to	 the root of the VFS which the
       given object is attached	to.  AG_ObjectParent()	returns	 the  object's
       parent.

       The  AG_ObjectFind()  function  returns the object corresponding	to the
       specified path name.  If	there is no such object	it returns NULL.

       AG_ObjectFindParent() returns the first ancestor	of the object matching
       either the name of the object (if name is non-NULL) or the class	of the
       object (if type is non-NULL).

       AG_ObjectFindChild() searches the child objects directly	under obj  for
       an  object called name.	It returns a pointer to	the object if found or
       NULL.

       AG_ObjectGetName() returns an autoallocated string containing the  full
       pathname	 of  an	object (relative to the	root of	its VFS).  If insuffi-
       cient memory is available to construct the path,	it fails  and  returns
       NULL.

       AG_ObjectCopyName()  copies the object's	full pathname (relative	to its
       VFS root) to a fixed-size buffer	buf of size bufSize in bytes.	Compo-
       nents  of  the path are separated by the	path separator AG_PATHSEP ("/"
       or "\").	 The returned pathname is guaranteed to	begin and to end  with
       the  path separator.  AG_ObjectCopyName() returns 0 on success or -1 if
       buf is too small	to contain the complete	path.

       AG_ObjectSetName() updates the name of the given	object.	 If the	object
       is attached to a	VFS then the VFS must be locked.

       AG_ObjectGenName() generates a unique name for a	child object  of  obj.
       The  class  name	(converted to lowercase) is used as prefix followed by
       an integer (starting from 0 and counting	up).  The generated string  is
       copied  to  the	fixed-size buffer name of size nameSize	in bytes.  The
       AG_ObjectGenNamePfx() variant generates a name using the	specified pre-
       fix instead of the class	name.

       The AGOBJECT_FOREACH_CHILD() macro iterates child over every child  ob-
       ject  of	 parent.  The child pointer is cast to type.  In Debug builds,
       an object validity and class-membership test is performed.

OBJECT CLASSES
       void AG_RegisterClass(AG_ObjectClass *classInfo)

       void AG_UnregisterClass(AG_ObjectClass *classInfo)

       AG_ObjectClass  *   AG_CreateClass(const	  char	 *classSpec,   AG_Size
       objectSize, AG_Size classSize, Uint major, Uint minor)

       AG_ObjectInitFn AG_ClassSetInit(AG_ObjectClass *cl, AG_ObjectInitFn fn)

       AG_ObjectResetFn	 AG_ClassSetReset(AG_ObjectClass *cl, AG_ObjectResetFn
       fn)

       AG_ObjectDestroyFn	 AG_ClassSetDestroy(AG_ObjectClass	  *cl,
       AG_ObjectDestroyFn fn)

       AG_ObjectLoadFn AG_ClassSetLoad(AG_ObjectClass *cl, AG_ObjectLoadFn fn)

       AG_ObjectSaveFn AG_ClassSetSave(AG_ObjectClass *cl, AG_ObjectSaveFn fn)

       AG_ObjectEditFn AG_ClassSetEdit(AG_ObjectClass *cl, AG_ObjectEditFn fn)

       void AG_DestroyClass(AG_ObjectClass *cl)

       void  AG_RegisterNamespace(const	 char *name, const char	*prefix, const
       char *url)

       void AG_UnregisterNamespace(const char *name)

       AG_ObjectClass *	AG_LookupClass(const char *classSpec)

       AG_ObjectClass *	AG_LoadClass(const char	*classSpec)

       void AG_RegisterModuleDirectory(const char *path)

       void AG_UnregisterModuleDirectory(const char *path)

       int AG_OfClass(AG_Object	*obj, const char *pattern)

       char * AG_ObjectGetClassName(const AG_Object *obj, int full)

       AG_ObjectClass *	AG_ObjectSuperclass(const AG_Object *obj)

       int AG_ObjectGetInheritHier(AG_Object *obj, AG_ObjectClass **pHier, int
       *nHier)

       AGOBJECT_FOREACH_CLASS(AG_Object	*child,	AG_Object *parent, TYPE	 type,
       const char *pattern)

       The   AG_RegisterClass()	  function   registers	a  new	object	class.
       classInfo should	be an initialized AG_ObjectClass structure:

       typedef struct ag_object_class {
	       char hier[AG_OBJECT_HIER_MAX];  /* Full inheritance hierarchy */
	       AG_Size size;		       /* Size of instance structure */
	       AG_Version ver;		       /* Version numbers */
	       void (*init)(void *obj);
	       void (*reset)(void *obj);
	       void (*destroy)(void *obj);
	       int  (*load)(void *obj, AG_DataSource *ds, const	AG_Version *ver);
	       int  (*save)(void *obj, AG_DataSource *ds);
	       void *(*edit)(void *obj);
       } AG_ObjectClass;

       New methods (and	other class-specific data) can be added	by overloading
       AG_ObjectClass.	For example, AG_WidgetClass adds GUI-specific methods:

       typedef struct ag_widget_class {
	       struct ag_object_class _inherit;

	       void (*draw)(void *);
	       void (*size_request)(void *, AG_SizeReq *);
	       /* ... */
       } AG_WidgetClass;

       The first field hier describes the  full	 inheritance  hierarchy.   The
       string	"Agar(Widget:Button)"  (or  "AG_Widget:AG_Button")  says  that
       AG_Button is a direct subclass of AG_Widget.

       If a class requires dynamically loadable	modules	(see  AG_DSO(3)),  the
       list  of	 modules  can be indicated in the hier string by appending "@"
       and a comma-separated list of library names.  For example:

	     "AG_Widget:MY_Widget@myLib,myOtherLib"

       The size	member specifies the size in  bytes  of	 the  object  instance
       structure.    ver   is	an   optional  datafile	 version  number  (see
       AG_Version(3)).

       The init() method initializes a new object instance.   It's  called  by
       AG_ObjectInit() (and AG_ObjectNew() after a successful allocation).

       The  reset()  method  is	 an  optional cleanup routine.	It's called by
       AG_ObjectLoad()	before	load()	and   by   AG_ObjectDestroy()	before
       destroy().

       The destroy() method frees all resources	allocated by the object.

       The  load()  method  reads the serialized state of object obj from data
       source ds.  save() saves	the state of obj to data  source  ds.	load()
       and  save()  must  both	return	0  on  success	or -1 on failure.  See
       AG_DataSource(3)	and the	"SERIALIZATION"	section.

       edit() is an application-specific method.  In a typical Agar GUI	appli-
       cation edit() may generate and return an	AG_Window(3) or	an AG_Box(3).

       AG_UnregisterClass() removes the	specified object class.

       AG_CreateClass()	provides an alternative	interface to the passing of  a
       statically-initialized  AG_ObjectClass structure	to AG_RegisterClass().
       AG_CreateClass()	allocates and initializes an AG_ObjectClass  structure
       (or   derivative	  thereof).    AG_ClassSetInit(),  AG_ClassSetReset(),
       AG_ClassSetDestroy(),	AG_ClassSetLoad(),    AG_ClassSetSave()	   and
       AG_ClassSetEdit()  set  the  function pointer for the respective	method
       (returning the previous one).

       AG_DestroyClass()   unregisters	  and	 frees	  an	auto-allocated
       AG_ObjectClass (or derivative thereof).

       AG_RegisterNamespace()  registers  a  new  namespace with the specified
       name, prefix and	informational URL.  For	example,  Agar	registers  its
       own using:

	     AG_RegisterNamespace("Agar", "AG_", "https://libagar.org/");

       Once the	namespace is registered, it is possible	to specify inheritance
       hierarchies using the partitioned namespace format:

	     Agar(Widget:Button):MyLib(MyButton)

       which is	equivalent to the conventional format:

	     AG_Widget:AG_Button:MY_Button

       AG_UnregisterNamespace()	deletes	the specified namespace.

       The AG_LookupClass() function searches for the AG_ObjectClass structure
       corresponding to	the given class	The classSpec string can be in conven-
       tional  or  partitioned	namespace format (see AG_RegisterNamespace()).
       If the search is	unsuccessful, it returns NULL.

       AG_LoadClass() ensures that the class specified by the classSpec	string
       is registered, possibly loading dynamic libraries if  needed.   If  the
       class  description  string includes libraries (e.g., "@lib1,lib2") then
       the registered modules directories  (see	 AG_RegisterModuleDirectory())
       will be scanned and the needed modules loaded automatically.

       Library names in	class description strings should be bare, without pre-
       fix  or	suffix (the actual filename on disk being platform-dependent).
       Valid libraries are loaded via AG_DSO(3).  The first library  must  de-
       fine  a	`myFooClass'  symbol  (where  `myFoo' is the name of the class
       transformed  from  `MY_Foo'),  which  should  be	 a  pointer   to   the
       AG_ObjectClass describing the object class.

       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.

       The AG_RegisterModuleDirectory()	function adds the specified  directory
       to  the module search path.  AG_UnregisterModuleDirectory() removes the
       specified directory from	the search path.

       The AG_OfClass()	function tests whether obj is an instance of the class
       described by pattern and	returns	1 if the object	belongs	to that	class.
       pattern is a class description string which may include "*"  wildcards.
       For  example, "AG_Widget:AG_Button:*" would match the "AG_Button" class
       or any subclass thereof.	 The pattern "AG_Widget:AG_Button" would match
       only the	"AG_Button" class but not its subclasses.  Fast	paths are pro-
       vided for patterns such as "Super:Sub:*"	and "Super:Sub",  but  general
       patterns	such as	"Super:*:Sub:*"	are also supported.

       AG_ObjectGetClassName() returns a newly-allocated string	containing the
       name  of	the class of an	object obj.  If	full is	1, return the complete
       inheritance hierarchy (e.g., "AG_Widget:AG_Button").  Otherwise,	return
       only the	subclass (e.g.,	"AG_Button").

       AG_ObjectSuperclass() returns a pointer to the class description	struc-
       ture of the superclass of obj.  If obj  is  an  instance	 of  the  base
       AG_Object class then the	base class (i.e., agObjectClass	returned).

       The  AG_ObjectGetInheritHier()  function	returns	into pHier an array of
       AG_ObjectClass pointers describing the inheritance hierarchy of an  ob-
       ject.   The  size of the	array is returned into nHier.  If the returned
       item count is > 0, the returned array should be freed when no longer in
       use.  AG_ObjectGetInheritHier() returns 0 on success or -1 if there  is
       insufficient memory.

       The  AGOBJECT_FOREACH_CLASS() macro iterates child over every child ob-
       ject of parent which is an instance of the class	specified in  pattern.
       The  pattern  argument  is a class description string (that may include
       "*").  The child	variable is cast to type with type checking  in	 Debug
       builds (and no checking in Release builds).

SERIALIZATION
       int AG_ObjectLoad(AG_Object *obj)

       int AG_ObjectLoadFromFile(AG_Object *obj, const char *file)

       int AG_ObjectLoadFromDB(AG_Object *obj, AG_Db *db, const	AG_Dbt *key)

       int AG_ObjectLoadData(AG_Object *obj)

       int AG_ObjectLoadDataFromFile(AG_Object *obj, const char	*file)

       int AG_ObjectLoadGeneric(AG_Object *obj)

       int AG_ObjectLoadGenericFromFile(AG_Object *obj,	const char *file)

       int AG_ObjectSave(AG_Object *obj)

       int AG_ObjectSaveAll(AG_Object *obj)

       int AG_ObjectSaveToFile(AG_Object *obj, const char *path)

       int AG_ObjectSaveToDB(AG_Object *obj, AG_Db *db,	const AG_Dbt *key)

       int AG_ObjectSerialize(AG_Object	*obj, AG_DataSource *ds)

       int AG_ObjectUnserialize(AG_Object *obj,	AG_DataSource *ds)

       int AG_ObjectReadHeader(AG_DataSource *ds, AG_ObjectHeader *header)

       These  functions	 implement serialization, or archiving of the state of
       an AG_Object to a flat, machine-independent binary format.

       The AG_ObjectLoad*() family of functions	load the state of an Agar  ob-
       ject  from  some	binary data source.  The generic AG_Object part	of the
       object is loaded	first, followed	by any class-specific serialized  data
       (which  is read by invoking the load() function over every class	in the
       inheritance hierarchy).

       The  AG_ObjectLoad(),  AG_ObjectLoadGeneric()  and  AG_ObjectLoadData()
       functions  look	for  an	archive	file in	the default search path	(using
       the AG_CONFIG_PATH_DATA of AG_Config(3)).

       The   AG_ObjectLoadFromFile(),	 AG_ObjectLoadGenericFromFile()	   and
       AG_ObjectLoadDataFromFile()  variants  attempt to load the object state
       from a specific file.  The AG_ObjectLoadFromDB()	variant	loads the  ob-
       ject state from the given AG_Db(3) database entry.

       The  AG_ObjectSave*()  family of	functions serialize and	save the state
       of the given object.  The generic AG_Object  state  is  written	first,
       followed	 by the	object's serialized data (which	is written by invoking
       the save() function of every class in the inheritance hierarchy).

       AG_ObjectSave() creates an archive of the object	in the	default	 loca-
       tion (the AG_CONFIG_PATH_DATA of	AG_Config(3)).	The AG_ObjectSaveAll()
       variant	saves  the  object's  children	as  well as the	object itself.
       AG_ObjectSaveToFile()  archives	the  object  to	 the  specified	 file.
       AG_ObjectSaveToDB() archives the	object to the given AG_Db(3) entry.

       The AG_ObjectSerialize()	function writes	an archive of the given	object
       to  the specified AG_DataSource(3), and AG_ObjectUnserialize() reads an
       archive of the given object.

       The AG_ObjectReadHeader() routine attempts to read the header of	a  se-
       rialized	 Agar  object from a AG_DataSource(3) and returns 0 on success
       or -1 if	no valid header	could be read.	On success, header information
       is returned into	the header structure:

       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 string	*/
	       Uint32 dataOffs;			   /* Dataset offset */
	       AG_Version ver;			   /* AG_Object	version	*/
	       Uint flags;			   /* Object flags */
       } AG_ObjectHeader;

FINALIZATION
       void AG_ObjectDestroy(AG_Object *obj)

       void AG_ObjectReset(AG_Object *obj)

       void AG_ObjectFreeEvents(AG_Object *obj)

       void AG_ObjectFreeVariables(AG_Object *obj)

       void AG_ObjectFreeChildren(AG_Object *obj)

       void AG_ObjectFreeChildrenOfType(AG_Object *obj,	const char *pattern)

       void  AG_ObjectFreeChildrenOfTypeLockless(AG_Object  *obj,  const  char
       *pattern)

       AG_ObjectReset()	restores the state of an object	to some	initial	state.
       It  invokes the object's	reset(), which is expected to bring the	object
       to a consistent state prior to deserialization (before load()).

       AG_ObjectDestroy() frees	all resources allocated	by an object.  It  in-
       vokes  the reset() and destroy()	methods	over each class	in the inheri-
       tance  hierarchy.   AG_ObjectDestroy()  also  cancels   any   scheduled
       AG_Timer(3)	  expiration.	      AG_ObjectDestroy()       implies
       AG_ObjectFreeEvents(),		AG_ObjectFreeVariables()	   and
       AG_ObjectFreeChildren().	     Unless	AG_OBJECT_STATIC    is	  set,
       AG_ObjectDestroy() also implies free(3).

       AG_ObjectFreeEvents() clears all	configured event handlers  (also  can-
       celling any scheduled timer expirations).

       AG_ObjectFreeVariables()	clears the AG_Variable(3) table	of the object.

       The   AG_ObjectFreeChildren()  routine  invokes	AG_ObjectDetach()  and
       AG_ObjectDestroy() over every child object under	parent.

       AG_ObjectFreeChildrenOfType()	 invokes     AG_ObjectDetach()	   and
       AG_ObjectDestroy()  on  every child object under	parent which is	an in-
       stance of the class described  by  pattern  (see	 AG_OfClass(3)).   The
       AG_ObjectFreeChildrenOfTypeLockless() variant assumes obj is locked.

THREADS
       void AG_ObjectLock(AG_Object *obj)

       void AG_ObjectUnlock(AG_Object *obj)

       void AG_LockVFS(AG_Object *obj)

       void AG_UnlockVFS(AG_Object *obj)

       void AG_ObjectDetachLockless(AG_Object *child)

       void AG_ObjectFreeChildrenLockless(AG_Object *obj)

       AG_ObjectLock()	and  AG_ObjectUnlock()	acquire	or release the locking
       device associated with the given	object.	 This is  a  mutex  protecting
       all  read/write members of the AG_Object	structure, except parent, root
       and the list of child objects cobjs which are all  considered  part  of
       the virtual filesystem and are instead protected	by AG_LockVFS().

       The  AG_ObjectLock() mutex can be used as a general-purpose locking de-
       vice which is guaranteed	to be held during  processing  of  all	events
       posted to the object as well as during object method such as load() and
       save().

       AG_LockVFS()  and AG_UnlockVFS()	acquire	or release the lock which pro-
       tects the layout	of the entire VFS which	obj is a part of.

       Agar is compiled	without	 threads  support  ("--disable-threads")  then
       AG_ObjectLock(),	AG_ObjectUnlock(), AG_LockVFS()	and AG_UnlockVFS() are
       no-ops.

       The  AG_ObjectDetachLockless()  call  is	a variant of AG_ObjectDetach()
       which assumes that parent and child are locked.

       The   AG_ObjectFreeChildrenLockless()   call   is    a	 variant    of
       AG_ObjectFreeChildren() which assumes that parent and child are locked.

FLAGS
       The following public AG_Object flags are	defined:

       AG_OBJECT_INDESTRUCTIBLE	  Application-specific advisory	flag.

       AG_OBJECT_STATIC		  Object is statically allocated (or allocated
				  via  a facility other	than malloc(3)).  Dis-
				  able use of free(3) by AG_ObjectDestroy().

       AG_OBJECT_READONLY	  Application-specific advisory	flag.

       AG_OBJECT_DEBUG		  Application-specific debugging flag.

       AG_OBJECT_NAME_ONATTACH	  Automatically	generate a unique name for the
				  object as soon as AG_ObjectAttach() occurs.

EVENTS
       The AG_Object mechanism generates the following events:

       attached(AG_Object *parent)
	   The object has been attached	to a new parent.

       detached(AG_Object *parent)
	   The object has been detached	from its parent.

       renamed(void)
	   The object's	name has changed.

       object-post-load(const char *path)
	   Invoked by AG_ObjectLoadData(), on  success.	  If  the  object  was
	   loaded from file, path is the pathname of the file.

       bound(AG_Variable *V)
	   A  new variable binding has been created, or	the value of an	exist-
	   ing binding has been	updated; see AG_Variable(3) for	details.

STRUCTURE DATA
       For the AG_ObjectClass structure	(see "OBJECT CLASSES" section):

       char *hier	 Full inheritance hierarchy.
       AG_Size size	 Size of instance structure (in	bytes).
       AG_Version ver	 Versioning information	(see AG_Version(3)).
       void (*init)	 Initialization	routine.
       void (*reset)	 Cleanup routine (for AG_ObjectReset()).
       void (*destroy)	 Final cleanup routine.
       int (*load)	 Deserialization routine.
       int (*save)	 Serialization routine.
       void *(*edit)	 Application-specific entry point.

       The following read-only members are initialized internally:

       char *name		   The name for	this class only.
       char *libs		   Comma-separated list	of DSO modules.
       AG_ObjectClass *super	   Pointer to the superclass.
       TAILQ(AG_ObjectClass) sub   Direct subclasses of	this class.

       For the AG_Object structure:

       char name[AG_OBJECT_NAME_MAX]   Unique (in parent) identifier for  this
				       object instance.	 May not contain `/'.

       AG_ObjectClass *cls	       A  pointer  to  the  AG_ObjectClass for
				       this  object's	class	(see   "OBJECT
				       CLASSES").

       Uint flags		       Option  flags  for this object instance
				       (see "FLAGS" section).

       TAILQ(AG_Event) events	       Table of	registered event handlers (set
				       by AG_SetEvent(3))  and	virtual	 func-
				       tions (set by AG_Set<Type>Fn()).

       TAILQ(AG_Timer) timers	       Active timers (see AG_Timer(3)).

       TAILQ(AG_Variable) vars	       Named variables (see AG_Variable(3)).

       TAILQ(AG_Object)	children       Child objects.

EXAMPLES
       The  following code initializes a stack-allocated object, prints	a mes-
       sage on the debug console and finally destroys the object:

	     AG_Object myObject;

	     AG_ObjectInit(&obj, "myObject", &agObjectClass);
	     Debug(&obj, "Hello, world!\n");
	     AG_ObjectDestroy(&obj);

       The following code creates a VFS	representing a document, searches  for
       an element by name and finally destroys the VFS:

	     AG_Object *doc, *head, *title, *body, *p;
	     AG_Object *result;

	     doc   = AG_ObjectNew(NULL,	"doc",	 &agObjectClass);
	     head  = AG_ObjectNew(doc,	"head",	 &agObjectClass);
	     title = AG_ObjectNew(head,	"title", &agObjectClass);
	     body  = AG_ObjectNew(doc,	"body",	 &agObjectClass);
	     p	   = AG_ObjectNew(body,	"p",	 &agObjectClass);

	     result = AG_ObjectFindS(doc, "/doc/head/title");
	     if	(result	!= NULL) {
		     AG_Verbose("Title = %s\n",	result->name);
	     }
	     AG_ObjectDestroy(doc);

       The following code transforms an	object's name to upper-case:

	     void
	     ObjectNameToUpper(AG_Object *obj)
	     {
		     char name[AG_OBJECT_NAME_MAX], *c;

		     if	(AG_ObjectCopyName(obj,	name,
			 sizeof(name)) == -1) {
			     return;
		     }
		     for (c = name; *c != '\0';	c++) {
			     *c	= toupper(*c);
		     }
		     AG_ObjectSetNameS(obj, name);
	     }

       The following code attaches an object to	a parent, detaches it and then
       reattaches it to	a different parent:

	     AG_Object parent1,	parent2, child;

	     AG_ObjectInit(&parent1, NULL, &agObjectClass);
	     AG_ObjectInit(&parent2, NULL, &agObjectClass);
	     AG_ObjectInit(&child, NULL, &agObjectClass);

	     AG_ObjectAttach(&parent1, &child);
	     AG_ObjectDetach(&child);
	     AG_ObjectAttach(&parent2, &child);

       The  following  code  uses AGOBJECT_FOREACH_CLASS to iterate child over
       every child object of the parent	object which is	an  instance  of  "My-
       Class":

	     struct my_class *chld;

	     AGOBJECT_FOREACH_CLASS(chld, parent, my_class, "MyClass") {
		     printf("Child %s is an instance of	MyClass.\n",
			 AGOBJECT(chld)->name);
	     }

       The following code performs a class-membership test with	a pattern:

	     AG_Button *btn = AG_ButtonNew(NULL, 0, NULL);

	     if	(AG_OfClass(btn, "AG_Widget:AG_Button")) {
		     /*
		      *	btn is an instance of AG_Button,
		      *	and NOT	a subclass thereof.
		      */
	     }
	     if	(AG_OfClass(btn, "AG_Widget:AG_Button:*")) {
		     /*
		      *	btn is an instance of AG_Button,
		      *	OR a subclass thereof.
		      */
	     }

       The  following  code  performs the same class-membership	test using the
       numerical class identifier (as opposed to an AG_OfClass() pattern):

	     AG_Button *btn = AG_ButtonNew(NULL, 0, NULL);

	     if	(OBJECT(btn)->cid == AGC_BUTTON) {
		     /*
		      *	btn is an instance of AG_Button,
		      *	and NOT	a subclass thereof.
		      */
	     }
	     if	(AG_BUTTON_ISA(btn)) {
		     /*
		      *	btn is an instance of AG_Button
		      *	OR a subclass thereof.
		      */
	     }

       The following code registers a new class	"MyClass" and instantiates it:

	     AG_ObjectClass myClass = {
		     "MY_Class",
		     sizeof(AG_Object),
		     { 1,0, 1234, 0xE03A },
		     NULL,    /* init */
		     NULL,    /* reset */
		     NULL,    /* destroy */
		     NULL,    /* load */
		     NULL,    /* save */
		     NULL     /* edit */
	     };

	     AG_Object *obj;

	     AG_RegisterClass(&myClass);

	     obj = AG_ObjectNew(NULL, NULL, &myClass);
	     Debug(obj,	"Hello,	world!\n");

	     AG_ObjectDestroy(obj);

       The following code implements a new class  "MY_Dummy"  which  overloads
       AG_Object  with	new  structure members.	 It also handles serialization
       and provides a public interface in C.  The public header	file follows:

	     /*
	      *	Public header file for MY_Dummy	(my_dummy.h).
	      */
	     typedef struct my_dummy {
		     struct ag_object _inherit;	/* AG_Object ->
						   MY_Dummy */
		     Uint flags;
	     #define MY_DUMMY_OPT1 0x01	 /* Some option	*/
	     #define MY_DUMMY_OPT2 0x02	 /* Another option */
		     int x,y;		 /* Some integers */
		     void *myData;	 /* Allocated data */
	     } MY_Dummy;

	     extern AG_ObjectClass myDummyClass;
	     MY_Dummy *_Nullable MY_DummyNew(int, int, Uint);

       The implementation follows:

	     /*
	      *	Implementation of MY_Dummy (my_dummy.c).
	      */
	     #define MYDATASIZE	1024

	     MY_Dummy *
	     MY_DummyNew(int x,	int y, Uint flags)
	     {
		     MY_Dummy *d;

		     d = AG_TryMalloc(sizeof(MY_Dummy));
		     if	(d == NULL) {
			     return (NULL);
		     }
		     AG_ObjectInit(d, &mdDummyClass);
		     d->x = x;
		     d->y = y;
		     d->flags =	flags;
		     return (d);
	     }

	     static void
	     Init(void *_Nonnull obj)
	     {
		     MY_Dummy *d = obj;

		     d->flags =	0;
		     d->x = 0;
		     d->y = 0;
		     d->myData = Malloc(MYDATASIZE);
		     memset(d->myData, 0, MYDATASIZE);
	     }

	     static void
	     Destroy(void *_Nonnull obj)
	     {
		     MY_Dummy *d = obj;

		     free(d->myData);
	     }

	     static int
	     Load(void *_Nonnull obj, AG_DataSource *_Nonnull ds,
		 const AG_Version *_Nonnull ver)
	     {
		     MY_Dummy *d = obj;

		     d->flags =	AG_ReadUint8(ds);
		     d->x = (int)AG_ReadUint16(ds);
		     d->y = (int)AG_ReadUint16(ds);
		     return AG_Read(ds,	d->myData, MYDATASIZE);
	     }

	     static int
	     Save(void *_Nonnull obj, AG_DataSource *_Nonnull ds)
	     {
		     MY_Dummy *d = obj;

		     AG_WriteUint8(ds, (Uint8)(d->flags));
		     AG_WriteUint16(ds,	(Uint16)d->x);
		     AG_WriteUint16(ds,	(Uint16)d->y);
		     return AG_Write(ds, d->myData, MYDATASIZE);
	     }

	     AG_ObjectClass myDummyClass = {
		     "MY_Dummy",
		     sizeof(MY_Dummy),
		     { 1,0, 0,0	},
		     Init,
		     NULL,	/* reset */
		     Destroy,
		     Load,
		     Save,
		     NULL	/* edit	*/
	     };

       The following code maps the "MY_" prefix	to a new namespace "MyPackage"
       and uses	it in the class	description string  classSpec  passed  to  the
       AG_LookupClass()	function:

	     AG_ObjectClass *C;

	     AG_RegisterNamespace("MyPackage", "MY_",
		 "https://example.com/");

	     AG_RegisterClass(&myImageViewerClass);

	     C = AG_LookupClass("Agar(Widget):"
				"MyPackage(ImageViewer)");
	     if	(C != NULL) {
		     AG_Verbose("Found class %s\n", C->name);
		     AG_Verbose("Structure size	= %d\n", C->size);
	     }

       The following code prints the inheritance hierarchy of an object:

	     void
	     PrintInheritHier(AG_Object	*obj)
	     {
		     AG_ObjectClass *hier;
		     int nHier,	i;

		     if	(AG_ObjectGetInheritHier(obj,
			 &hier,	&nHier)	!= 0) {
			     AG_FatalError(NULL);
		     }
		     AG_Verbose("AG_Object");
		     for (i = 0; i < nHier; i++) {
			     AG_Verbose(" -> %s",
				 hier[i]->name);
		     }
		     AG_Verbose("\n");
		     AG_Free(hier);
	     }

       The  following  code loads an object from a file, increments a variable
       counter and writes back the object to the file:

	     AG_Object obj;
	     int counter;

	     AG_ObjectInit(&obj, NULL, &agObjectClass);
	     AG_SetInt(&obj, "counter",	0);

	     if	(AG_ObjectLoadFromFile(&obj,
		 "test.obj") ==	-1)
		     AG_FatalError(NULL);

	     counter = AG_GetInt(&obj, "counter");
	     AG_Debug(&obj, "Counter: %d -> %d\n",
		 counter, counter+1);
	     AG_SetInt(&obj, "counter",	counter+1);

	     AG_ObjectSaveToFile(obj, "test.obj");

       The Agar	GUI represents user interfaces using a	tree  of  AG_Widget(3)
       objects	attached  to a parent AG_Window(3) which is itself attached to
       some parent AG_Driver(3).

       The SG(3) scene-graph structure of Agar-SG is a VFS of  SG_Node(3)  ob-
       jects.  Non-visible nodes can be	paged out to storage, saving memory.

       Edacious	 (https://edacious.hypertriton.com/) represents	circuits, com-
       ponents and simulation data using an in-memory VFS.  Circuits are saved
       to a flat binary	file which embeds the circuit's	serialized  data  with
       that  of	 its sub-components (which may include third-party components,
       in which	case AG_Object will autoload any required DSOs).

SEE ALSO
       AG_Event(3), AG_Intro(3), AG_Timer(3), AG_Variable(3)

HISTORY
       The AG_Object interface appeared	in Agar	 1.0.	AG_ObjectFreeDataset()
       was   renamed   AG_ObjectReset()	  in   Agar   1.6.0.	The  functions
       AG_CreateClass(),	AG_ClassSetInit(),	   AG_ClassSetReset(),
       AG_ClassSetDestroy(),	   AG_ClassSetLoad(),	    AG_ClassSetSave(),
       AG_ClassSetEdit(), AG_DestroyClass()  and  AG_ObjectGetClassName()  ap-
       peared in Agar 1.6.0.

Agar 1.7		       December	21, 2022		  AG_OBJECT(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=AG_Object&sektion=3&manpath=FreeBSD+Ports+14.3.quarterly>

home | help