Last active
June 15, 2020 12:00
-
-
Save igormorgado/8c492021ae6b15c5979015ea0afb9bf3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <glib.h> | |
#include <glib/gi18n.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
typedef int32_t i32; | |
// A sample object data | |
struct data | |
{ | |
int val; | |
float real; | |
char txt[256]; | |
}; | |
// Object header | |
struct object { | |
char id[38]; | |
char name[256]; | |
size_t refcount; | |
struct data data; | |
}; | |
struct object * object_init(); | |
char * object_get_id (struct object *object); | |
char * object_get_name (struct object *object); | |
void object_print (struct object *object); | |
void _object_print_hash (gpointer key, gpointer value, gpointer user_data); | |
void object_unref (struct object *object); // Remove a refcount and free it if 0 | |
void object_free (struct object *object); // Remove if refcount == 0; | |
void object_destroy (struct object *object); // Destroy object ignore refcount | |
gboolean object_equal (gconstpointer obja, gconstpointer objb); | |
guint object_hash (gconstpointer obj); | |
struct manager { | |
size_t nobjects; | |
GHashTable * objects; | |
}; | |
struct manager * manager_init(); | |
bool manager_destroy (struct manager *manager, bool cleanup); | |
char * manager_new_object (struct manager *manager); | |
bool manager_add_object (struct manager *manager, struct object *object); | |
bool manager_del_object (struct manager *manager, const char *id); | |
bool manager_del_object_by_name (struct manager *manager, const char *name); | |
void _manager_object_unref (gpointer key, gpointer value, gpointer data); | |
i32 manager_print (struct manager *manager); | |
struct object * manager_get_object_by_name(char *name); | |
struct object * manager_get_object_by_id(char *id); | |
char * manager_get_object_id_by_name(char *name); | |
char * manager_get_object_name_by_id(char *id); | |
int main(int argc, char *argv[]) { | |
struct manager * mgr = manager_init(); | |
char *oid = manager_new_object(mgr); | |
manager_new_object(mgr); | |
manager_new_object(mgr); | |
manager_print(mgr); | |
g_print("Objects in manager %zu\n", mgr->nobjects); | |
g_print("Deleting %s\n", oid); | |
manager_del_object(mgr, oid); | |
g_print("Objects in manager %zu\n", mgr->nobjects); | |
manager_destroy(mgr, true); | |
return EXIT_SUCCESS; | |
} | |
/* | |
* | |
* OBJECT FUNCTIONS | |
* | |
*/ | |
struct object * | |
object_init() | |
{ | |
struct object *self = malloc(sizeof *self); | |
char *id = g_uuid_string_random(); | |
g_strlcpy(self->id, id, 38); | |
free(id); | |
g_strlcpy(self->name, "PLACEHOLDER", 256); | |
self->refcount = 0; | |
self->data.val = 42; | |
self->data.real = 3.1415f; | |
g_strlcpy(self->data.txt, "DATA PLACEHOLDER", 256); | |
return self; | |
} | |
void | |
object_destroy (struct object *self) | |
{ | |
// Debug, use object_print instead... | |
// g_print("Destroy object id: %s - name: %s - count: %zu\n", | |
// ((struct object*)self)->id, | |
// ((struct object*)self)->name, | |
// ((struct object*)self)->refcount); | |
free(self); | |
} | |
void | |
object_free (struct object *self) | |
{ | |
if(self && self->refcount < 1) | |
{ | |
// Debug, use object_print instead... | |
// g_print("Free object id: %s - name: %s - count: %zu\n", | |
// ((struct object*)self)->id, | |
// ((struct object*)self)->name, | |
// ((struct object*)self)->refcount); | |
object_destroy(self); | |
} | |
} | |
void | |
object_unref (struct object *self) | |
{ | |
if(self) | |
{ | |
self->refcount -= 1; | |
object_free(self); | |
} | |
} | |
void | |
_object_print_hash(gpointer key, gpointer value, gpointer user_data) | |
{ | |
object_print ((struct object *)value); | |
} | |
void | |
object_print (struct object *self) | |
{ | |
g_print("(%s)[%s]: %d, %f, %s\n", | |
self->id, | |
self->name, | |
self->data.val, | |
self->data.real, | |
self->data.txt); | |
} | |
struct manager * | |
manager_init() | |
{ | |
struct manager * self = malloc(sizeof *self); | |
self->nobjects = 0; | |
self->objects = g_hash_table_new(object_hash, object_equal); | |
return self; | |
} | |
void | |
_manager_object_unref(gpointer key, gpointer value, gpointer data) | |
{ | |
// DEBUG, use object_print instead... | |
g_print("Unref object id: %s - name: %s - count: %zu\n", | |
((struct object*)value)->id, | |
((struct object*)value)->name, | |
((struct object*)value)->refcount); | |
((struct manager *)data)->nobjects -= 1; | |
object_unref((struct object*)value); | |
} | |
bool | |
manager_del_object(struct manager *self, const char *id) | |
{ | |
bool retval = false; | |
// TODO: NEED TO USE g_hash_table_full | |
struct object * obj = g_hash_table_lookup(self->objects, id); | |
retval = g_hash_table_remove (self->objects, id); | |
// TODO: NEED TO USE g_hash_table_full | |
object_unref(obj); | |
if (retval == true) | |
{ | |
self->nobjects -= 1; | |
} | |
return retval; | |
} | |
bool | |
manager_destroy(struct manager *self, bool clean) { | |
if(self) | |
{ | |
if(self->objects) | |
{ | |
if(clean) | |
{ | |
g_hash_table_foreach(self->objects, _manager_object_unref, self); | |
} | |
g_hash_table_destroy(self->objects); | |
} | |
free(self); | |
return true; | |
} | |
return false; | |
} | |
bool | |
manager_add_object(struct manager *self, struct object *object) { | |
bool retval = false; | |
retval = g_hash_table_insert(self->objects, object->id, object); | |
if(retval == true) | |
{ | |
object->refcount += 1; | |
} | |
return retval; | |
} | |
char * | |
manager_new_object(struct manager *self) | |
{ | |
bool retval = false; | |
struct object *obj = object_init(); | |
if (obj) { | |
retval = manager_add_object(self, obj); | |
} | |
if(retval == true) { | |
self->nobjects +=1; | |
return obj->id; | |
} else { | |
return NULL; | |
} | |
} | |
i32 | |
manager_print(struct manager *self) | |
{ | |
g_hash_table_foreach(self->objects, _object_print_hash, NULL); | |
return g_hash_table_size(self->objects); | |
} | |
gboolean | |
object_equal(gconstpointer obja, gconstpointer objb) { | |
return g_str_equal (((struct object *)obja)->id, ((struct object *)objb)->id); | |
} | |
guint | |
object_hash(gconstpointer obj) { | |
return g_str_hash (((struct object *)obj)->id); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment