Make GIB_Reply an actual function, store object handles as a string, add

the ObjectHash class.
This commit is contained in:
Brian Koropoff 2003-09-21 00:30:47 +00:00
parent 52417dceb3
commit ad61e0684c
3 changed files with 235 additions and 10 deletions

View file

@ -62,6 +62,7 @@ typedef struct gib_object_s {
unsigned long int handle, refs;
hashtab_t *signals;
llist_t *slots;
const char *handstr;
} gib_object_t;
typedef struct gib_message_s {
@ -93,6 +94,7 @@ typedef struct gib_class_s {
unsigned int depth;
struct gib_object_s *classobj;
struct gib_class_s *parent;
llist_t *children;
} gib_class_t;
typedef struct gib_methodtab_s {
@ -109,9 +111,6 @@ typedef struct gib_classdesc_s {
struct gib_methodtab_s *methods, *class_methods;
} gib_classdesc_t;
#define GIB_Reply(obj,mesg,argc,argv) if ((mesg).reply) { \
((mesg).reply(argc,argv,(mesg).replydata)); \
GIB_Object_Decref ((obj));}
#define GIB_ForwardToSuper(mesg,obj,method) ((method)->parent->func ((obj), \
(method)->parent, \
(obj)->data[(method)->parent->class->depth], \
@ -126,6 +125,8 @@ int GIB_Send (gib_object_t *obj, gib_object_t *sender, int argc, const char **ar
int GIB_SendToMethod (gib_object_t *obj, gib_method_t *method, gib_object_t
*sender, int argc, const char **argv, gib_reply_handler reply,
void *replydata);
void GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char
**argv);
gib_object_t *GIB_Object_Get (const char *id);
void GIB_Object_Signal_Slot_Pair (gib_object_t *sender, const char *signal,
gib_object_t *receiver, const char *slot);

View file

@ -64,13 +64,11 @@ static int
Object_Retain_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
const char *r;
baseobj_t *base = data;
base->ref++;
GIB_Object_Incref (obj);
r = va ("%lu", obj->handle);
GIB_Reply (obj, mesg, 1, &r);
GIB_Reply (obj, mesg, 1, &obj->handstr);
return 0;
}
@ -91,10 +89,7 @@ static int
Object_Init_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
const char *r;
r = va ("%lu", obj->handle);
GIB_Reply (obj, mesg, 1, &r);
GIB_Reply (obj, mesg, 1, &obj->handstr);
return 0;
}
@ -106,6 +101,37 @@ Object_Class_f (gib_object_t *obj, gib_method_t *method, void *data,
return 0;
}
static int
Object_SuperClass_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
if (obj->class->parent)
GIB_Reply (obj, mesg, 1, &obj->class->parent->name);
else
GIB_Reply (obj, mesg, 0, NULL);
return 0;
}
static int
Object_IsKindOf_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
gib_class_t *c;
static const char *one = "1";
static const char *zero = "0";
if (mesg.argc < 2)
return -1;
for (c = obj->class; c; c = c->parent)
if (!strcmp (mesg.argv[1], c->name)) {
GIB_Reply (obj, mesg, 1, &one);
return 0;
}
GIB_Reply (obj, mesg, 1, &zero);
return 0;
}
static int
Object_Dispose_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
@ -157,6 +183,31 @@ Object_Class_New_f (gib_object_t *obj, gib_method_t *method, void *data,
mesg.argv[0] = old;
return 0;
}
static int
Object_Class_Children_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
const char **reply;
unsigned int size;
unsigned int i = 0;
static qboolean
iterator (gib_class_t *class, void *unused)
{
reply[i++] = class->name;
return false;
}
size = llist_size (obj->class->children);
if (size) {
reply = malloc (sizeof (char *) * size);
llist_iterate (obj->class->children, LLIST_ICAST (iterator));
GIB_Reply (obj, mesg, size, reply);
} else
GIB_Reply (obj, mesg, 0, NULL);
return 0;
}
static void *
Object_Construct (gib_object_t *obj)
@ -180,6 +231,8 @@ gib_methodtab_t Object_methods[] = {
{"release", Object_Release_f, NULL},
{"init", Object_Init_f, NULL},
{"class", Object_Class_f, NULL},
{"superClass", Object_SuperClass_f, NULL},
{"isKindOf", Object_IsKindOf_f, NULL},
{"dispose", Object_Dispose_f, NULL},
{"signalConnect", Object_SignalConnect_f, NULL},
{"signalDisconnect", Object_SignalDisconnect_f, NULL},
@ -187,6 +240,8 @@ gib_methodtab_t Object_methods[] = {
};
gib_methodtab_t Object_class_methods[] = {
{"parent", Object_SuperClass_f, NULL},
{"children", Object_Class_Children_f, NULL},
{"new", Object_Class_New_f, NULL},
{"signalConnect", Object_SignalConnect_f, NULL},
{"signalDisconnect", Object_SignalDisconnect_f, NULL},
@ -296,6 +351,162 @@ gib_classdesc_t Thread_class = {
Thread_methods, Thread_class_methods
};
/*
Object hash class
Stores references to objects in a Hash
*/
typedef struct ObjRef_s {
const char *key;
gib_object_t *obj;
} ObjRef_t;
typedef struct ObjectHash_s {
hashtab_t *objects;
} ObjectHash_t;
static const char *
ObjRef_Get_Key (void *ele, void *ptr)
{
return ((ObjRef_t *) ele)->key;
}
static void
ObjRef_Free (void *ele, void *ptr)
{
ObjRef_t *ref = ele;
free ((void *)ref->key);
GIB_Object_Decref (ref->obj);
free (ref);
}
static void *
ObjectHash_Construct (gib_object_t *obj)
{
ObjectHash_t *data = malloc (sizeof (ObjectHash_t));
data->objects = Hash_NewTable (1024, ObjRef_Get_Key, ObjRef_Free,
NULL);
return data;
}
static void
ObjectHash_Destruct (void *data)
{
ObjectHash_t *objh = data;
Hash_DelTable (objh->objects);
free (objh);
}
static int
ObjectHash_Insert_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
ObjectHash_t *objh = data;
gib_object_t *ins;
ObjRef_t *new;
int i;
if (mesg.argc < 3)
return -1;
for (i = 2; i < mesg.argc; i++) {
if ((ins = GIB_Object_Get (mesg.argv[i]))) {
new = malloc (sizeof (ObjRef_t));
new->key = strdup (mesg.argv[1]);
new->obj = ins;
GIB_Object_Incref (ins);
Hash_Add (objh->objects, new);
} else
return -1;
}
GIB_Reply (obj, mesg, 0, NULL);
return 0;
}
static int
ObjectHash_Get_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
ObjectHash_t *objh = data;
ObjRef_t **refs, **r;
const char **reply;
int i, len;
if (mesg.argc < 2)
return -1;
if ((refs = (ObjRef_t **) Hash_FindList (objh->objects,
mesg.argv[1]))) {
for (r = refs, len = 0; *r; r++, len++);
reply = malloc (sizeof (char **) * len);
for (r = refs, i = 0; *r; r++, i++)
reply[i] = (*r)->obj->handstr;
GIB_Reply (obj, mesg, len, reply);
free (reply);
} else
GIB_Reply (obj, mesg, 0, NULL);
return 0;
}
static int
ObjectHash_Remove_f (gib_object_t *obj, gib_method_t *method, void *data,
gib_object_t *sender, gib_message_t mesg)
{
ObjectHash_t *objh = data;
ObjRef_t **refs, **r;
int i;
if (mesg.argc < 2)
return -1;
if ((refs = (ObjRef_t **) Hash_FindList (objh->objects,
mesg.argv[1]))) {
if (mesg.argc == 2)
for (r = refs; *r; r++) {
Hash_DelElement (objh->objects, *r);
Hash_Free (objh->objects, *r);
}
else
for (r = refs; *r; r++)
for (i = 2; i < mesg.argc; i++)
if (!strcmp (mesg.argv[i],
(*r)->obj->handstr))
{
Hash_DelElement
(objh->objects,
*r);
Hash_Free
(objh->objects,
*r);
}
}
GIB_Reply (obj, mesg, 0, NULL);
return 0;
}
gib_methodtab_t ObjectHash_methods[] = {
{"insert", ObjectHash_Insert_f, NULL},
{"get", ObjectHash_Get_f, NULL},
{"remove", ObjectHash_Remove_f, NULL},
{NULL, NULL, NULL}
};
gib_methodtab_t ObjectHash_class_methods[] = {
{NULL, NULL, NULL}
};
gib_classdesc_t ObjectHash_class = {
"ObjectHash", "Object",
ObjectHash_Construct, NULL,
ObjectHash_Destruct,
ObjectHash_methods, ObjectHash_class_methods
};
/*
Scripted object class factory
@ -472,4 +683,5 @@ GIB_Classes_Init (void)
{
GIB_Class_Create (&Object_class);
GIB_Class_Create (&Thread_class);
GIB_Class_Create (&ObjectHash_class);
}

View file

@ -161,6 +161,7 @@ GIB_Class_Create (gib_classdesc_t *desc)
if (desc->parentname && (parent = Hash_Find (gib_classes, desc->parentname))) {
class->parent = parent;
class->depth = parent->depth + 1;
llist_append (parent->children, class);
} else
class->depth = 0;
@ -173,6 +174,7 @@ GIB_Class_Create (gib_classdesc_t *desc)
parent->methods : NULL, desc->methods);
class->class_methods = GIB_Method_Build_Hash (class, parent ?
parent->class_methods : NULL, desc->class_methods);
class->children = llist_new (NULL, NULL, NULL);
Hash_Add (gib_classes, class);
@ -205,6 +207,7 @@ GIB_Object_Create (const char *classname, qboolean classobj)
obj->data = malloc (sizeof (void *) * (class->depth+1));
obj->methods = classobj ? class->class_methods : class->methods;
obj->handle = classobj ? 0 : GIB_Handle_New (obj);
obj->handstr = strdup (va ("%lu", obj->handle));
obj->refs = 1;
obj->signals = Hash_NewTable (128, GIB_Signal_Get_Key,
GIB_Signal_Free, NULL);
@ -235,6 +238,7 @@ GIB_Object_Finish_Destroy (int argc, const char **argv, void *data)
temp->destruct (obj->data[i]);
free (obj->data);
GIB_Handle_Free (obj->handle);
free ((void *) obj->handstr);
Hash_DelTable (obj->signals);
llist_delete (obj->slots);
free (obj);
@ -308,6 +312,14 @@ GIB_SendToMethod (gib_object_t *obj, gib_method_t *method, gib_object_t
sender, message);
}
void
GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char
**argv)
{
mesg.reply (argc, argv, mesg.replydata);
GIB_Object_Decref (obj);
}
gib_object_t *
GIB_Object_Get (const char *id)
{