1 /* -*-Mode: C;-*-
2 * $Id: generic.c 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10 #include "edsio.h"
11
12 /* Type-based selectors for unknown types
13 */
14
15 typedef struct {
16 const char* name;
17 gboolean (*unserialize_func) ();
18 gboolean (*serialize_func) ();
19 guint (*count_func) ();
20 void (*print_func) ();
21 guint32 val;
22 } SerEntry;
23
24 static GArray *ser_array;
25 static gboolean ser_array_sorted;
26
27 void
serializeio_initialize_type(const char * name,guint32 val,gboolean (* unserialize_func)(),gboolean (* serialize_func)(),guint (* count_func)(),void (* print_func)())28 serializeio_initialize_type (const char* name,
29 guint32 val,
30 gboolean (*unserialize_func) (),
31 gboolean (*serialize_func) (),
32 guint (*count_func) (),
33 void (*print_func) ())
34 {
35 SerEntry it;
36
37 it.name = name;
38 it.val = val;
39 it.unserialize_func = unserialize_func;
40 it.serialize_func = serialize_func;
41 it.count_func = count_func;
42 it.print_func = print_func;
43
44 if (ser_array == NULL)
45 ser_array = g_array_new (FALSE, TRUE, sizeof (SerEntry));
46
47 g_array_append_val (ser_array, it);
48
49 ser_array_sorted = FALSE;
50 }
51
52 static int
ser_entry_compare(const void * va,const void * vb)53 ser_entry_compare (const void* va, const void* vb)
54 {
55 SerEntry* a = (SerEntry*) va;
56 SerEntry* b = (SerEntry*) vb;
57
58 return a->val - b->val;
59 }
60
61 static SerEntry*
serializeio_find_entry(SerialType type)62 serializeio_find_entry (SerialType type)
63 {
64 if (! edsio_library_check (type & EDSIO_LIBRARY_OFFSET_MASK))
65 return NULL;
66
67 if (ser_array)
68 {
69 gint high_index = ser_array->len;
70 gint low_index = 0;
71 gint index;
72 gint this_val;
73
74 if (! ser_array_sorted)
75 {
76 ser_array_sorted = TRUE;
77 qsort (ser_array->data, ser_array->len, sizeof (SerEntry), ser_entry_compare);
78 }
79
80 again:
81
82 index = (low_index + high_index) / 2;
83
84 this_val = g_array_index (ser_array, SerEntry, index).val;
85
86 if (this_val < type)
87 {
88 low_index = index + 1;
89 goto again;
90 }
91 else if (this_val > type)
92 {
93 high_index = index - 1;
94 goto again;
95 }
96 else
97 {
98 return & g_array_index (ser_array, SerEntry, index);
99 }
100 }
101
102 edsio_generate_intint_event (EC_EdsioUnregisteredType,
103 type & EDSIO_LIBRARY_OFFSET_MASK,
104 type >> EDSIO_LIBRARY_OFFSET_BITS);
105 return NULL;
106 }
107
108 gboolean
serializeio_unserialize_generic_internal(SerialSource * source,SerialType * object_type,void ** object,gboolean set_allocation)109 serializeio_unserialize_generic_internal (SerialSource *source,
110 SerialType *object_type,
111 void **object,
112 gboolean set_allocation)
113 {
114 SerialType type = (* source->source_type) (source, set_allocation);
115 SerEntry* ent;
116 gboolean res = FALSE;
117
118 if (type < 0)
119 return FALSE;
120
121 ent = serializeio_find_entry (type);
122
123 (*object_type) = type;
124
125 if (ent)
126 {
127 res = ent->unserialize_func (source, object);
128 }
129
130 return res;
131 }
132
133 gboolean
serializeio_unserialize_generic(SerialSource * source,SerialType * object_type,void ** object)134 serializeio_unserialize_generic (SerialSource *source,
135 SerialType *object_type,
136 void **object)
137 {
138 return serializeio_unserialize_generic_internal (source, object_type, object, TRUE);
139 }
140
141 gboolean
serializeio_serialize_generic(SerialSink * sink,SerialType object_type,void * object)142 serializeio_serialize_generic (SerialSink *sink,
143 SerialType object_type,
144 void *object)
145 {
146 return serializeio_serialize_generic_internal (sink, object_type, object, TRUE);
147 }
148
149 gboolean
serializeio_serialize_generic_internal(SerialSink * sink,SerialType object_type,void * object,gboolean set_allocation)150 serializeio_serialize_generic_internal (SerialSink *sink,
151 SerialType object_type,
152 void *object,
153 gboolean set_allocation)
154 {
155 SerEntry* ent;
156 gboolean res = FALSE;
157
158 if (! (* sink->sink_type) (sink, object_type, set_allocation ? serializeio_generic_count (object_type, object) : 0, set_allocation))
159 return FALSE;
160
161 ent = serializeio_find_entry (object_type);
162
163 if (ent)
164 res = ent->serialize_func (sink, object);
165
166 return res;
167 }
168
169 const char*
serializeio_generic_type_to_string(SerialType type)170 serializeio_generic_type_to_string (SerialType type)
171 {
172 SerEntry* ent;
173 const char* res = "*Unknown*";
174
175 ent = serializeio_find_entry (type);
176
177 if (ent)
178 res = ent->name;
179
180 return res;
181 }
182
183 guint
serializeio_generic_count(SerialType object_type,void * object)184 serializeio_generic_count (SerialType object_type,
185 void *object)
186 {
187 SerEntry* ent;
188 gboolean res = FALSE;
189
190 ent = serializeio_find_entry (object_type);
191
192 if (ent)
193 res = ent->count_func (object);
194
195 return res;
196 }
197
198 void
serializeio_generic_print(SerialType type,void * object,guint indent_spaces)199 serializeio_generic_print (SerialType type, void* object, guint indent_spaces)
200 {
201 SerEntry* ent;
202
203 ent = serializeio_find_entry (type);
204
205 if (ent)
206 ent->print_func (object, indent_spaces);
207 else
208 {
209 int i = 0;
210
211 for (; i < indent_spaces; i += 1)
212 g_print (" ");
213
214 g_print ("*Type Not Registered*\n");
215 }
216 }
217
218 gboolean
serializeio_unserialize_generic_acceptable(SerialSource * source,guint32 accept,SerialType * object_type,void ** object)219 serializeio_unserialize_generic_acceptable (SerialSource *source,
220 guint32 accept,
221 SerialType *object_type,
222 void **object)
223 {
224 gboolean s;
225
226 s = serializeio_unserialize_generic (source, object_type, object);
227
228 if (s)
229 {
230 if (accept != -1)
231 {
232 if ((*object_type & EDSIO_LIBRARY_OFFSET_MASK) != (accept & EDSIO_LIBRARY_OFFSET_MASK))
233 {
234 edsio_generate_intint_event (EC_EdsioUnexpectedLibraryType,
235 accept & EDSIO_LIBRARY_OFFSET_MASK,
236 *object_type & EDSIO_LIBRARY_OFFSET_MASK);
237
238 return FALSE;
239 }
240
241 if (! ((*object_type & ~EDSIO_LIBRARY_OFFSET_MASK) |
242 (accept & ~EDSIO_LIBRARY_OFFSET_MASK)))
243 {
244 edsio_generate_void_event (EC_EdsioUnexpectedType);
245
246 return FALSE;
247 }
248 }
249 }
250
251 return s;
252 }
253