diff options
Diffstat (limited to 'libedsio/generic.c')
-rwxr-xr-x | libedsio/generic.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/libedsio/generic.c b/libedsio/generic.c new file mode 100755 index 0000000..d63dfb0 --- /dev/null +++ b/libedsio/generic.c @@ -0,0 +1,252 @@ +/* -*-Mode: C;-*- + * $Id: generic.c 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ + * + * Copyright (C) 1998, 1999, Josh MacDonald. + * All Rights Reserved. + * + * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU> + */ + +#include "edsio.h" + +/* Type-based selectors for unknown types + */ + +typedef struct { + const char* name; + gboolean (*unserialize_func) (); + gboolean (*serialize_func) (); + guint (*count_func) (); + void (*print_func) (); + guint32 val; +} SerEntry; + +static GArray *ser_array; +static gboolean ser_array_sorted; + +void +serializeio_initialize_type (const char* name, + guint32 val, + gboolean (*unserialize_func) (), + gboolean (*serialize_func) (), + guint (*count_func) (), + void (*print_func) ()) +{ + SerEntry it; + + it.name = name; + it.val = val; + it.unserialize_func = unserialize_func; + it.serialize_func = serialize_func; + it.count_func = count_func; + it.print_func = print_func; + + if (ser_array == NULL) + ser_array = g_array_new (FALSE, TRUE, sizeof (SerEntry)); + + g_array_append_val (ser_array, it); + + ser_array_sorted = FALSE; +} + +static int +ser_entry_compare (const void* va, const void* vb) +{ + SerEntry* a = (SerEntry*) va; + SerEntry* b = (SerEntry*) vb; + + return a->val - b->val; +} + +static SerEntry* +serializeio_find_entry (SerialType type) +{ + if (! edsio_library_check (type & EDSIO_LIBRARY_OFFSET_MASK)) + return NULL; + + if (ser_array) + { + gint high_index = ser_array->len; + gint low_index = 0; + gint index; + gint this_val; + + if (! ser_array_sorted) + { + ser_array_sorted = TRUE; + qsort (ser_array->data, ser_array->len, sizeof (SerEntry), ser_entry_compare); + } + + again: + + index = (low_index + high_index) / 2; + + this_val = g_array_index (ser_array, SerEntry, index).val; + + if (this_val < type) + { + low_index = index + 1; + goto again; + } + else if (this_val > type) + { + high_index = index - 1; + goto again; + } + else + { + return & g_array_index (ser_array, SerEntry, index); + } + } + + edsio_generate_intint_event (EC_EdsioUnregisteredType, + type & EDSIO_LIBRARY_OFFSET_MASK, + type >> EDSIO_LIBRARY_OFFSET_BITS); + return NULL; +} + +gboolean +serializeio_unserialize_generic_internal (SerialSource *source, + SerialType *object_type, + void **object, + gboolean set_allocation) +{ + SerialType type = (* source->source_type) (source, set_allocation); + SerEntry* ent; + gboolean res = FALSE; + + if (type < 0) + return FALSE; + + ent = serializeio_find_entry (type); + + (*object_type) = type; + + if (ent) + { + res = ent->unserialize_func (source, object); + } + + return res; +} + +gboolean +serializeio_unserialize_generic (SerialSource *source, + SerialType *object_type, + void **object) +{ + return serializeio_unserialize_generic_internal (source, object_type, object, TRUE); +} + +gboolean +serializeio_serialize_generic (SerialSink *sink, + SerialType object_type, + void *object) +{ + return serializeio_serialize_generic_internal (sink, object_type, object, TRUE); +} + +gboolean +serializeio_serialize_generic_internal (SerialSink *sink, + SerialType object_type, + void *object, + gboolean set_allocation) +{ + SerEntry* ent; + gboolean res = FALSE; + + if (! (* sink->sink_type) (sink, object_type, set_allocation ? serializeio_generic_count (object_type, object) : 0, set_allocation)) + return FALSE; + + ent = serializeio_find_entry (object_type); + + if (ent) + res = ent->serialize_func (sink, object); + + return res; +} + +const char* +serializeio_generic_type_to_string (SerialType type) +{ + SerEntry* ent; + const char* res = "*Unknown*"; + + ent = serializeio_find_entry (type); + + if (ent) + res = ent->name; + + return res; +} + +guint +serializeio_generic_count (SerialType object_type, + void *object) +{ + SerEntry* ent; + gboolean res = FALSE; + + ent = serializeio_find_entry (object_type); + + if (ent) + res = ent->count_func (object); + + return res; +} + +void +serializeio_generic_print (SerialType type, void* object, guint indent_spaces) +{ + SerEntry* ent; + + ent = serializeio_find_entry (type); + + if (ent) + ent->print_func (object, indent_spaces); + else + { + int i = 0; + + for (; i < indent_spaces; i += 1) + g_print (" "); + + g_print ("*Type Not Registered*\n"); + } +} + +gboolean +serializeio_unserialize_generic_acceptable (SerialSource *source, + guint32 accept, + SerialType *object_type, + void **object) +{ + gboolean s; + + s = serializeio_unserialize_generic (source, object_type, object); + + if (s) + { + if (accept != -1) + { + if ((*object_type & EDSIO_LIBRARY_OFFSET_MASK) != (accept & EDSIO_LIBRARY_OFFSET_MASK)) + { + edsio_generate_intint_event (EC_EdsioUnexpectedLibraryType, + accept & EDSIO_LIBRARY_OFFSET_MASK, + *object_type & EDSIO_LIBRARY_OFFSET_MASK); + + return FALSE; + } + + if (! ((*object_type & ~EDSIO_LIBRARY_OFFSET_MASK) | + (accept & ~EDSIO_LIBRARY_OFFSET_MASK))) + { + edsio_generate_void_event (EC_EdsioUnexpectedType); + + return FALSE; + } + } + } + + return s; +} |