/* -*-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 */ #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; }