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