diff options
Diffstat (limited to 'xdelta1/libedsio/edsio.c')
-rw-r--r-- | xdelta1/libedsio/edsio.c | 1610 |
1 files changed, 0 insertions, 1610 deletions
diff --git a/xdelta1/libedsio/edsio.c b/xdelta1/libedsio/edsio.c deleted file mode 100644 index 4d110f6..0000000 --- a/xdelta1/libedsio/edsio.c +++ /dev/null | |||
@@ -1,1610 +0,0 @@ | |||
1 | /* -*-Mode: C;-*- | ||
2 | * $Id: edsio.c 1.1 Sun, 28 Jan 2007 10:02:26 -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 | #include <stdio.h> | ||
12 | |||
13 | #if TIME_WITH_SYS_TIME | ||
14 | # include <sys/time.h> | ||
15 | # include <time.h> | ||
16 | #else | ||
17 | # if HAVE_SYS_TIME_H | ||
18 | # include <sys/time.h> | ||
19 | # else | ||
20 | # include <time.h> | ||
21 | # endif | ||
22 | #endif | ||
23 | |||
24 | #include "maketime.h" | ||
25 | |||
26 | /*#define DEBUG_PROPS*/ | ||
27 | |||
28 | /* Event delivery | ||
29 | */ | ||
30 | |||
31 | static GHashTable* all_event_defs = NULL; | ||
32 | |||
33 | static GPtrArray* all_event_watchers = NULL; | ||
34 | |||
35 | typedef struct _ErrorDeliveryWatcher ErrorDeliveryWatcher; | ||
36 | typedef struct _DelayedEvent DelayedEvent; | ||
37 | |||
38 | struct _ErrorDeliveryWatcher { | ||
39 | ErrorDeliveryFunc deliver; | ||
40 | }; | ||
41 | |||
42 | struct _DelayedEvent { | ||
43 | GenericEvent ev; | ||
44 | GenericEventDef *def; | ||
45 | const char *msg; | ||
46 | }; | ||
47 | |||
48 | void | ||
49 | eventdelivery_initialize_event_def (gint code, | ||
50 | gint level, | ||
51 | gint flags, | ||
52 | const char* name, | ||
53 | const char* oneline, | ||
54 | const char * (* field_to_string) (GenericEvent* ev, gint field)) | ||
55 | { | ||
56 | GenericEventDef* def = g_new0 (GenericEventDef, 1); | ||
57 | |||
58 | if (! all_event_defs) | ||
59 | all_event_defs = g_hash_table_new (g_int_hash, g_int_equal); | ||
60 | |||
61 | def->code = code; | ||
62 | def->level = level; | ||
63 | def->flags = flags; | ||
64 | def->name = name; | ||
65 | def->oneline = oneline; | ||
66 | def->field_to_string = field_to_string; | ||
67 | |||
68 | g_hash_table_insert (all_event_defs, & def->code, def); | ||
69 | } | ||
70 | |||
71 | void | ||
72 | eventdelivery_event_watch_all (ErrorDeliveryFunc func) | ||
73 | { | ||
74 | ErrorDeliveryWatcher* w = g_new0 (ErrorDeliveryWatcher, 1); | ||
75 | |||
76 | w->deliver = func; | ||
77 | |||
78 | if (! all_event_watchers) | ||
79 | all_event_watchers = g_ptr_array_new (); | ||
80 | |||
81 | g_ptr_array_add (all_event_watchers, w); | ||
82 | } | ||
83 | |||
84 | GenericEventDef* | ||
85 | eventdelivery_event_lookup (gint code) | ||
86 | { | ||
87 | return g_hash_table_lookup (all_event_defs, & code); | ||
88 | } | ||
89 | |||
90 | void | ||
91 | eventdelivery_event_deliver (GenericEvent* e) | ||
92 | { | ||
93 | static gint in_call = FALSE; | ||
94 | static GQueue* queued = NULL; | ||
95 | static GPtrArray* free_strings = NULL; | ||
96 | |||
97 | if (! queued) | ||
98 | { | ||
99 | queued = g_queue_new (); | ||
100 | free_strings = g_ptr_array_new (); | ||
101 | } | ||
102 | |||
103 | in_call += 1; | ||
104 | |||
105 | g_assert (e); | ||
106 | |||
107 | edsio_edsio_init (); | ||
108 | |||
109 | if (all_event_defs) | ||
110 | { | ||
111 | GenericEventDef* def = g_hash_table_lookup (all_event_defs, & e->code); | ||
112 | |||
113 | if (def) | ||
114 | { | ||
115 | GString* out; | ||
116 | const char* oneline = def->oneline; | ||
117 | char c; | ||
118 | |||
119 | out = g_string_new (NULL); | ||
120 | |||
121 | while ((c = *oneline++)) | ||
122 | { | ||
123 | switch (c) | ||
124 | { | ||
125 | case '$': | ||
126 | { | ||
127 | const char* field; | ||
128 | char *end; | ||
129 | int f; | ||
130 | |||
131 | if ((*oneline++) != '{') | ||
132 | goto badevent; | ||
133 | |||
134 | f = strtol (oneline, &end, 10); | ||
135 | |||
136 | if (f < 0 || !end || end[0] != '}') | ||
137 | goto badevent; | ||
138 | |||
139 | oneline = end+1; | ||
140 | |||
141 | g_assert (def->field_to_string); | ||
142 | |||
143 | field = def->field_to_string (e, f); | ||
144 | |||
145 | if (field) | ||
146 | { | ||
147 | g_string_append (out, field); | ||
148 | |||
149 | g_free ((void*) field); | ||
150 | } | ||
151 | else | ||
152 | goto badevent; | ||
153 | } | ||
154 | break; | ||
155 | default: | ||
156 | g_string_append_c (out, c); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | if (! all_event_watchers) | ||
161 | { | ||
162 | fprintf (stderr, "%s:%d: %s\n", e->srcfile, e->srcline, out->str); | ||
163 | |||
164 | g_string_free (out, TRUE); | ||
165 | } | ||
166 | else if (in_call == 1) | ||
167 | { | ||
168 | gint i; | ||
169 | |||
170 | for (i = 0; i < all_event_watchers->len; i += 1) | ||
171 | { | ||
172 | ErrorDeliveryWatcher* w = all_event_watchers->pdata[i]; | ||
173 | |||
174 | if (! w->deliver (e, def, out->str)) | ||
175 | { | ||
176 | g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str); | ||
177 | in_call = 0; | ||
178 | return; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | while (g_queue_get_size (queued) > 0) | ||
183 | { | ||
184 | DelayedEvent* de = g_queue_pop (queued); | ||
185 | |||
186 | for (i = 0; i < all_event_watchers->len; i += 1) | ||
187 | { | ||
188 | ErrorDeliveryWatcher* w = all_event_watchers->pdata[i]; | ||
189 | |||
190 | if (! w->deliver (& de->ev, de->def, de->msg)) | ||
191 | { | ||
192 | g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str); | ||
193 | in_call = 0; | ||
194 | return; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | for (i = 0; i < free_strings->len; i += 1) | ||
200 | g_string_free (free_strings->pdata[i], TRUE); | ||
201 | |||
202 | g_ptr_array_set_size (free_strings, 0); | ||
203 | |||
204 | g_string_free (out, TRUE); | ||
205 | } | ||
206 | else | ||
207 | { | ||
208 | DelayedEvent* de = g_new (DelayedEvent, 1); | ||
209 | |||
210 | de->ev = *e; | ||
211 | de->def = def; | ||
212 | de->msg = out->str; | ||
213 | |||
214 | g_queue_push (queued, de); | ||
215 | |||
216 | g_ptr_array_add (free_strings, out); | ||
217 | } | ||
218 | |||
219 | in_call -= 1; | ||
220 | |||
221 | return; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | g_warning ("%s:%d: Unrecognized event delivered (code=%d)\n", e->srcfile, e->srcline, e->code); | ||
226 | |||
227 | in_call -= 1; | ||
228 | |||
229 | return; | ||
230 | |||
231 | badevent: | ||
232 | |||
233 | g_warning ("%s:%d: An malformed error could not print here (code=%d)\n", e->srcfile, e->srcline, e->code); | ||
234 | |||
235 | in_call -= 1; | ||
236 | |||
237 | return; | ||
238 | } | ||
239 | |||
240 | const char* | ||
241 | eventdelivery_int_to_string (int x) | ||
242 | { | ||
243 | return g_strdup_printf ("%d", x); | ||
244 | } | ||
245 | |||
246 | const char* | ||
247 | eventdelivery_string_to_string (const char* x) | ||
248 | { | ||
249 | return g_strdup (x); | ||
250 | } | ||
251 | |||
252 | const char* | ||
253 | eventdelivery_source_to_string (SerialSource* x) | ||
254 | { | ||
255 | return g_strdup ("@@@SerialSource"); | ||
256 | } | ||
257 | |||
258 | const char* | ||
259 | eventdelivery_sink_to_string (SerialSink* x) | ||
260 | { | ||
261 | return g_strdup ("@@@SerialSink"); | ||
262 | } | ||
263 | |||
264 | const char* | ||
265 | eventdelivery_handle_to_string (FileHandle* x) | ||
266 | { | ||
267 | g_return_val_if_fail (x, g_strdup ("*error*")); | ||
268 | |||
269 | return x->table->table_handle_name (x); | ||
270 | } | ||
271 | |||
272 | /* Misc crap. | ||
273 | */ | ||
274 | |||
275 | gboolean | ||
276 | edsio_time_of_day (SerialGenericTime* setme) | ||
277 | { | ||
278 | #if HAVE_GETTIMEOFDAY | ||
279 | |||
280 | struct timeval tv; | ||
281 | |||
282 | if (gettimeofday (& tv, NULL)) | ||
283 | { | ||
284 | edsio_generate_errno_event (EC_EdsioGetTimeOfDayFailure); | ||
285 | goto bail; | ||
286 | } | ||
287 | |||
288 | if (setme) | ||
289 | { | ||
290 | setme->nanos = tv.tv_usec * 1000; | ||
291 | setme->seconds = tv.tv_sec; | ||
292 | } | ||
293 | |||
294 | #else | ||
295 | |||
296 | struct timeval tv; | ||
297 | time_t t = time (NULL); | ||
298 | |||
299 | if (t < 0) | ||
300 | { | ||
301 | edsio_generate_errno_event (EC_EdsioTimeFailure); | ||
302 | goto bail; | ||
303 | } | ||
304 | |||
305 | if (setme) | ||
306 | { | ||
307 | setme->nanos = 0; | ||
308 | setme->seconds = tv.tv_sec; | ||
309 | } | ||
310 | |||
311 | #endif | ||
312 | |||
313 | return TRUE; | ||
314 | |||
315 | bail: | ||
316 | |||
317 | setme->nanos = 0; | ||
318 | setme->seconds = 10; | ||
319 | |||
320 | return FALSE; | ||
321 | } | ||
322 | |||
323 | gchar* | ||
324 | edsio_time_to_iso8601 (SerialGenericTime *tp) | ||
325 | { | ||
326 | return edsio_time_t_to_iso8601 (tp->seconds); | ||
327 | } | ||
328 | |||
329 | gchar* | ||
330 | edsio_time_t_to_iso8601 (GTime t0) | ||
331 | { | ||
332 | static char timebuf[64]; | ||
333 | time_t t = t0; | ||
334 | |||
335 | struct tm lt = *localtime(&t); | ||
336 | int utc_offset = difftm(<, gmtime(&t)); | ||
337 | char sign = utc_offset < 0 ? '-' : '+'; | ||
338 | int minutes = abs (utc_offset) / 60; | ||
339 | int hours = minutes / 60; | ||
340 | |||
341 | sprintf(timebuf, | ||
342 | "%d-%02d-%02d %02d:%02d:%02d%c%02d%02d", | ||
343 | lt.tm_year + 1900, | ||
344 | lt.tm_mon + 1, | ||
345 | lt.tm_mday, | ||
346 | lt.tm_hour, | ||
347 | lt.tm_min, | ||
348 | lt.tm_sec, | ||
349 | sign, | ||
350 | hours, | ||
351 | minutes % 60); | ||
352 | |||
353 | return timebuf; | ||
354 | } | ||
355 | |||
356 | static gboolean | ||
357 | strtosl_checked (const char* str, long* l, const char* errmsg) | ||
358 | { | ||
359 | char* end; | ||
360 | |||
361 | (*l) = strtol (str, &end, 10); | ||
362 | |||
363 | if (!end || end[0]) | ||
364 | { | ||
365 | if (errmsg) | ||
366 | edsio_generate_stringstring_event (EC_EdsioInvalidIntegerString, errmsg, str); | ||
367 | |||
368 | (*l) = 0; | ||
369 | return FALSE; | ||
370 | } | ||
371 | |||
372 | return TRUE; | ||
373 | } | ||
374 | |||
375 | gboolean | ||
376 | strtosi_checked (const char* str, gint32* i, const char* errmsg) | ||
377 | { | ||
378 | long l; | ||
379 | |||
380 | if (! strtosl_checked (str, &l, errmsg)) | ||
381 | { | ||
382 | (*i) = 0; | ||
383 | return FALSE; | ||
384 | } | ||
385 | |||
386 | if (l > G_MAXINT || l < G_MININT) | ||
387 | { | ||
388 | if (errmsg) | ||
389 | edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); | ||
390 | |||
391 | (*i) = 0; | ||
392 | return FALSE; | ||
393 | } | ||
394 | |||
395 | (*i) = l; | ||
396 | |||
397 | return TRUE; | ||
398 | } | ||
399 | |||
400 | gboolean | ||
401 | strtoss_checked (const char* str, gint16* i, const char* errmsg) | ||
402 | { | ||
403 | long l; | ||
404 | |||
405 | if (! strtosl_checked (str, &l, errmsg)) | ||
406 | { | ||
407 | (*i) = 0; | ||
408 | return FALSE; | ||
409 | } | ||
410 | |||
411 | if (l > G_MAXSHORT || l < G_MINSHORT) | ||
412 | { | ||
413 | if (errmsg) | ||
414 | edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); | ||
415 | |||
416 | (*i) = 0; | ||
417 | return FALSE; | ||
418 | } | ||
419 | |||
420 | (*i) = l; | ||
421 | |||
422 | return TRUE; | ||
423 | } | ||
424 | |||
425 | gboolean | ||
426 | strtoui_checked (const char* str, guint32* i, const char* errmsg) | ||
427 | { | ||
428 | long l; | ||
429 | |||
430 | if (! strtosl_checked (str, &l, errmsg)) | ||
431 | { | ||
432 | (*i) = 0; | ||
433 | return FALSE; | ||
434 | } | ||
435 | |||
436 | if (l < 0) | ||
437 | { | ||
438 | if (errmsg) | ||
439 | edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str); | ||
440 | |||
441 | (*i) = 0; | ||
442 | return FALSE; | ||
443 | } | ||
444 | |||
445 | (*i) = l; | ||
446 | |||
447 | if (l != (*i)) | ||
448 | { | ||
449 | if (errmsg) | ||
450 | edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); | ||
451 | |||
452 | (*i) = 0; | ||
453 | return FALSE; | ||
454 | } | ||
455 | |||
456 | return TRUE; | ||
457 | } | ||
458 | |||
459 | gboolean | ||
460 | strtous_checked (const char* str, guint16* i, const char* errmsg) | ||
461 | { | ||
462 | long l; | ||
463 | |||
464 | if (! strtosl_checked (str, &l, errmsg)) | ||
465 | { | ||
466 | (*i) = 0; | ||
467 | return FALSE; | ||
468 | } | ||
469 | |||
470 | if (l < 0) | ||
471 | { | ||
472 | if (errmsg) | ||
473 | edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str); | ||
474 | |||
475 | (*i) = 0; | ||
476 | return FALSE; | ||
477 | } | ||
478 | |||
479 | (*i) = l; | ||
480 | |||
481 | if (l != (*i)) | ||
482 | { | ||
483 | if (errmsg) | ||
484 | edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); | ||
485 | |||
486 | (*i) = 0; | ||
487 | return FALSE; | ||
488 | } | ||
489 | |||
490 | return TRUE; | ||
491 | } | ||
492 | |||
493 | gint | ||
494 | edsio_md5_equal (gconstpointer v, | ||
495 | gconstpointer v2) | ||
496 | { | ||
497 | return memcmp (v, v2, 16) == 0; | ||
498 | } | ||
499 | |||
500 | guint | ||
501 | edsio_md5_hash (gconstpointer v) | ||
502 | { | ||
503 | guint8* md5 = (guint8*) v; | ||
504 | guint x = 0; | ||
505 | gint i, j; | ||
506 | |||
507 | for (i = 0, j = 0; i < 16; i += 1, j += 1, j %= sizeof (guint32)) | ||
508 | x ^= md5[i] << (8*j); | ||
509 | |||
510 | return x; | ||
511 | } | ||
512 | |||
513 | void | ||
514 | serializeio_print_bytes (const guint8* bytes, guint len0) | ||
515 | { | ||
516 | char buf[100]; | ||
517 | int i; | ||
518 | guint len; | ||
519 | |||
520 | len = MIN (len0, 32); | ||
521 | |||
522 | for (i = 0; i < len; i += 1) | ||
523 | sprintf (buf + 2*i, "%02x", bytes[i]); | ||
524 | |||
525 | if (len0 > len) | ||
526 | strcat (buf, "..."); | ||
527 | |||
528 | g_print ("%s\n", buf); | ||
529 | } | ||
530 | |||
531 | void | ||
532 | edsio_md5_to_string (const guint8* md5, char buf[33]) | ||
533 | { | ||
534 | gint i; | ||
535 | |||
536 | for (i = 0; i < 16; i += 1) | ||
537 | sprintf (buf + 2*i, "%02x", md5[i]); | ||
538 | } | ||
539 | |||
540 | static gboolean | ||
541 | from_hex (char c, int* x, const char* ctx) | ||
542 | { | ||
543 | char buf[2]; | ||
544 | |||
545 | if (c >= '0' && c <= '9') | ||
546 | { | ||
547 | (*x) = c - '0'; | ||
548 | return TRUE; | ||
549 | } | ||
550 | else if (c >= 'A' && c <= 'F') | ||
551 | { | ||
552 | (*x) = c - 'A' + 10; | ||
553 | return TRUE; | ||
554 | } | ||
555 | else if (c >= 'a' && c <= 'f') | ||
556 | { | ||
557 | (*x) = c - 'a' + 10; | ||
558 | return TRUE; | ||
559 | } | ||
560 | |||
561 | buf[0] = c; | ||
562 | buf[1] = 0; | ||
563 | |||
564 | edsio_generate_stringstring_event (EC_EdsioInvalidHexDigit, buf, ctx); | ||
565 | return FALSE; | ||
566 | } | ||
567 | |||
568 | gboolean | ||
569 | edsio_md5_from_string (guint8* md5, const char buf[33]) | ||
570 | { | ||
571 | gint i; | ||
572 | gint l = strlen (buf); | ||
573 | |||
574 | if (l < 32) | ||
575 | { | ||
576 | edsio_generate_string_event (EC_EdsioMD5StringShort, buf); | ||
577 | return FALSE; | ||
578 | } | ||
579 | else if (l > 32) | ||
580 | { | ||
581 | edsio_generate_string_event (EC_EdsioMD5StringLong, buf); | ||
582 | return FALSE; | ||
583 | } | ||
584 | |||
585 | for (i = 0; i < 16; i += 1) | ||
586 | { | ||
587 | char c1 = buf[(2*i)]; | ||
588 | char c2 = buf[(2*i)+1]; | ||
589 | int x1, x2; | ||
590 | |||
591 | if (! from_hex (c1, &x1, buf)) | ||
592 | return FALSE; | ||
593 | |||
594 | if (! from_hex (c2, &x2, buf)) | ||
595 | return FALSE; | ||
596 | |||
597 | md5[i] = (x1 << 4) | x2; | ||
598 | } | ||
599 | |||
600 | return TRUE; | ||
601 | } | ||
602 | |||
603 | /* Strings | ||
604 | */ | ||
605 | |||
606 | const char* edsio_intern_string (const char* str) | ||
607 | { | ||
608 | static GStringChunk* chunk = NULL; | ||
609 | |||
610 | if (! chunk) | ||
611 | chunk = g_string_chunk_new (256); | ||
612 | |||
613 | return g_string_chunk_insert_const (chunk, str); | ||
614 | } | ||
615 | |||
616 | /* Properties | ||
617 | */ | ||
618 | |||
619 | typedef struct _EdsioHostType EdsioHostType; | ||
620 | typedef struct _EdsioPropertyType EdsioPropertyType; | ||
621 | |||
622 | struct _EdsioPropertyType { | ||
623 | const char *type_name; | ||
624 | PropFreeFunc freer; | ||
625 | PropGSFunc getter; | ||
626 | PropGSFunc setter; | ||
627 | PropSerialize serialize; | ||
628 | PropUnserialize unserialize; | ||
629 | }; | ||
630 | |||
631 | struct _EdsioHostType { | ||
632 | const char *host_name; | ||
633 | PropertyTableFunc ptable; | ||
634 | PersistSourceFunc source; | ||
635 | PersistSinkFunc sink; | ||
636 | PersistIssetFunc isset; | ||
637 | PersistUnsetFunc unset; | ||
638 | }; | ||
639 | |||
640 | struct _EdsioProperty { | ||
641 | guint32 prop_code; | ||
642 | const char *prop_name; | ||
643 | guint32 prop_flags; | ||
644 | EdsioPropertyType *type; | ||
645 | EdsioHostType *host; | ||
646 | }; | ||
647 | |||
648 | union _EdsioPropertyEntry { | ||
649 | guint32 as_uint32; | ||
650 | SerialEdsioBytes as_bytes; | ||
651 | gpointer as_vptr; | ||
652 | const char* as_string; | ||
653 | }; | ||
654 | |||
655 | struct _EdsioGenericProperty | ||
656 | { | ||
657 | guint32 code; | ||
658 | }; | ||
659 | |||
660 | static GHashTable* all_property_types = NULL; | ||
661 | static GHashTable* all_host_types = NULL; | ||
662 | static GHashTable* all_properties = NULL; | ||
663 | static GHashTable* all_property_codes = NULL; | ||
664 | static guint32 property_code_sequence = 0; | ||
665 | |||
666 | void | ||
667 | edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser) | ||
668 | { | ||
669 | EdsioPropertyType* type; | ||
670 | |||
671 | t = edsio_intern_string (t); | ||
672 | |||
673 | if (! all_property_types) | ||
674 | all_property_types = g_hash_table_new (g_direct_hash, g_direct_equal); | ||
675 | |||
676 | if ((type = g_hash_table_lookup (all_property_types, t)) != NULL) | ||
677 | { | ||
678 | if (getter != type->getter || | ||
679 | setter != type->setter || | ||
680 | ser != type->serialize || | ||
681 | unser != type->unserialize) | ||
682 | edsio_generate_string_event (EC_EdsioDuplicatePropertyTypeRegistered, t); | ||
683 | return; | ||
684 | } | ||
685 | |||
686 | type = g_new0 (EdsioPropertyType, 1); | ||
687 | |||
688 | type->type_name = t; | ||
689 | type->freer = freer; | ||
690 | type->getter = getter; | ||
691 | type->setter = setter; | ||
692 | type->serialize = ser; | ||
693 | type->unserialize = unser; | ||
694 | |||
695 | g_hash_table_insert (all_property_types, (gpointer) t, type); | ||
696 | } | ||
697 | |||
698 | void | ||
699 | edsio_initialize_host_type (const char* ph, | ||
700 | PropertyTableFunc ptable, | ||
701 | PersistSourceFunc source, | ||
702 | PersistSinkFunc sink, | ||
703 | PersistIssetFunc isset, | ||
704 | PersistUnsetFunc unset) | ||
705 | { | ||
706 | EdsioHostType* host; | ||
707 | |||
708 | ph = edsio_intern_string (ph); | ||
709 | |||
710 | if (! all_host_types) | ||
711 | all_host_types = g_hash_table_new (g_direct_hash, g_direct_equal); | ||
712 | |||
713 | if (g_hash_table_lookup (all_host_types, ph)) | ||
714 | { | ||
715 | edsio_generate_string_event (EC_EdsioDuplicateHostTypeRegistered, ph); | ||
716 | return; | ||
717 | } | ||
718 | |||
719 | host = g_new0 (EdsioHostType, 1); | ||
720 | |||
721 | host->host_name = ph; | ||
722 | host->ptable = ptable; | ||
723 | host->source = source; | ||
724 | host->sink = sink; | ||
725 | host->isset = isset; | ||
726 | host->unset = unset; | ||
727 | |||
728 | g_hash_table_insert (all_host_types, (gpointer) ph, host); | ||
729 | |||
730 | } | ||
731 | |||
732 | gboolean | ||
733 | edsio_new_property (const char* name, const char* ph, const char* t, guint32 flags, EdsioGenericProperty *ret_prop) | ||
734 | { | ||
735 | EdsioProperty* prop; | ||
736 | EdsioPropertyType* type; | ||
737 | EdsioHostType* host; | ||
738 | |||
739 | name = edsio_intern_string (name); | ||
740 | ph = edsio_intern_string (ph); | ||
741 | t = edsio_intern_string (t); | ||
742 | |||
743 | g_assert (all_property_types); | ||
744 | |||
745 | if (! all_properties) | ||
746 | { | ||
747 | all_properties = g_hash_table_new (g_direct_hash, g_direct_equal); | ||
748 | all_property_codes = g_hash_table_new (g_int_hash, g_int_equal); | ||
749 | } | ||
750 | |||
751 | if ((prop = g_hash_table_lookup (all_properties, name)) != NULL) | ||
752 | { | ||
753 | edsio_generate_string_event (EC_EdsioDuplicatePropertyNameRegistered, name); | ||
754 | ret_prop->code = prop->prop_code; | ||
755 | return TRUE; | ||
756 | } | ||
757 | |||
758 | if ((type = g_hash_table_lookup (all_property_types, t)) == NULL) | ||
759 | { | ||
760 | edsio_generate_string_event (EC_EdsioNoSuchPropertyType, t); | ||
761 | return FALSE; | ||
762 | } | ||
763 | |||
764 | if ((host = g_hash_table_lookup (all_host_types, ph)) == NULL) | ||
765 | { | ||
766 | edsio_generate_string_event (EC_EdsioNoSuchHostType, ph); | ||
767 | return FALSE; | ||
768 | } | ||
769 | |||
770 | if (flags & PF_Persistent && ! host->isset) | ||
771 | { | ||
772 | edsio_generate_stringstring_event (EC_EdsioPersistenceUnavailable, name, ph); | ||
773 | return FALSE; | ||
774 | } | ||
775 | |||
776 | prop = g_new0 (EdsioProperty, 1); | ||
777 | |||
778 | prop->prop_code = ++property_code_sequence; | ||
779 | prop->prop_name = name; | ||
780 | prop->prop_flags = flags; | ||
781 | prop->type = type; | ||
782 | prop->host = host; | ||
783 | |||
784 | g_hash_table_insert (all_properties, (gpointer) name, prop); | ||
785 | g_hash_table_insert (all_property_codes, & prop->prop_code, prop); | ||
786 | |||
787 | ret_prop->code = prop->prop_code; | ||
788 | |||
789 | return TRUE; | ||
790 | } | ||
791 | |||
792 | static EdsioProperty* | ||
793 | edsio_property_find (const char* ph, const char* t, guint32 code) | ||
794 | { | ||
795 | EdsioProperty* prop; | ||
796 | |||
797 | ph = edsio_intern_string (ph); | ||
798 | t = edsio_intern_string (t); | ||
799 | |||
800 | if (code <= 0 || code > property_code_sequence) | ||
801 | { | ||
802 | edsio_generate_int_event (EC_EdsioNoSuchProperty, code); | ||
803 | return NULL; | ||
804 | } | ||
805 | |||
806 | if (! (prop = g_hash_table_lookup (all_property_codes, & code))) | ||
807 | { | ||
808 | edsio_generate_int_event (EC_EdsioNoSuchProperty, code); | ||
809 | return NULL; | ||
810 | } | ||
811 | |||
812 | if (prop->host->host_name != ph) | ||
813 | { | ||
814 | edsio_generate_stringstringstring_event (EC_EdsioWrongHostType, prop->prop_name, ph, prop->host->host_name); | ||
815 | return NULL; | ||
816 | } | ||
817 | |||
818 | if (prop->type->type_name != t) | ||
819 | { | ||
820 | edsio_generate_stringstringstring_event (EC_EdsioWrongDataType, prop->prop_name, t, prop->type->type_name); | ||
821 | return NULL; | ||
822 | } | ||
823 | |||
824 | return prop; | ||
825 | } | ||
826 | |||
827 | EdsioPropertyEntry* | ||
828 | edsio_property_get (gpointer obj, EdsioProperty* prop) | ||
829 | { | ||
830 | EdsioPropertyEntry* ent; | ||
831 | GHashTable* table = * prop->host->ptable (obj); | ||
832 | gboolean persist = prop->prop_flags & PF_Persistent; | ||
833 | |||
834 | #ifdef DEBUG_PROPS | ||
835 | g_print ("get %p.%s\n", obj, prop->prop_name); | ||
836 | #endif | ||
837 | |||
838 | if (table && (ent = g_hash_table_lookup (table, & prop->prop_code)) != NULL) | ||
839 | return ent; | ||
840 | |||
841 | if (persist) | ||
842 | { | ||
843 | SerialSource* src; | ||
844 | |||
845 | if (! (src = prop->host->source (obj, prop->prop_name))) | ||
846 | return NULL; | ||
847 | |||
848 | g_assert (prop->type->unserialize); | ||
849 | |||
850 | if (! prop->type->unserialize (src, & ent)) | ||
851 | return NULL; | ||
852 | |||
853 | g_assert (ent); | ||
854 | |||
855 | if (! src->source_close (src)) | ||
856 | return NULL; | ||
857 | |||
858 | src->source_free (src); | ||
859 | |||
860 | if (! table) | ||
861 | table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal); | ||
862 | |||
863 | g_hash_table_insert (table, & prop->prop_code, ent); | ||
864 | |||
865 | return ent; | ||
866 | } | ||
867 | |||
868 | edsio_generate_string_event (EC_EdsioPropertyNotSet, prop->prop_name); | ||
869 | return NULL; | ||
870 | } | ||
871 | |||
872 | gboolean | ||
873 | edsio_property_set (gpointer obj, EdsioProperty* prop, EdsioPropertyEntry* set) | ||
874 | { | ||
875 | EdsioPropertyEntry* ent; | ||
876 | gboolean persist = prop->prop_flags & PF_Persistent; | ||
877 | GHashTable* table = * prop->host->ptable (obj); | ||
878 | |||
879 | #ifdef DEBUG_PROPS | ||
880 | g_print ("set %p.%s\n", obj, prop->prop_name); | ||
881 | #endif | ||
882 | |||
883 | if (! table) | ||
884 | table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal); | ||
885 | |||
886 | ent = g_hash_table_lookup (table, & prop->prop_code); | ||
887 | |||
888 | if (ent) | ||
889 | { | ||
890 | g_hash_table_remove (table, & prop->prop_code); | ||
891 | prop->type->freer (ent); | ||
892 | } | ||
893 | |||
894 | g_hash_table_insert (table, & prop->prop_code, set); | ||
895 | |||
896 | if (persist) | ||
897 | { | ||
898 | SerialSink* sink; | ||
899 | |||
900 | if (! (sink = prop->host->sink (obj, prop->prop_name))) | ||
901 | return FALSE; | ||
902 | |||
903 | g_assert (prop->type->serialize); | ||
904 | |||
905 | if (! prop->type->serialize (sink, set)) | ||
906 | return FALSE; | ||
907 | |||
908 | if (! sink->sink_close (sink)) | ||
909 | return FALSE; | ||
910 | |||
911 | sink->sink_free (sink); | ||
912 | } | ||
913 | |||
914 | return TRUE; | ||
915 | } | ||
916 | |||
917 | gboolean | ||
918 | edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj) | ||
919 | { | ||
920 | EdsioProperty* prop; | ||
921 | GHashTable* table; | ||
922 | gboolean persist; | ||
923 | gboolean result = FALSE; | ||
924 | |||
925 | if (! (prop = edsio_property_find (ph, t, code))) | ||
926 | goto done; | ||
927 | |||
928 | persist = prop->prop_flags & PF_Persistent; | ||
929 | |||
930 | table = * prop->host->ptable (obj); | ||
931 | |||
932 | if (persist) | ||
933 | { | ||
934 | PersistIssetFunc issetfunc = prop->host->isset; | ||
935 | if (issetfunc(obj, prop->prop_name)) | ||
936 | { | ||
937 | if (! edsio_property_get (obj, prop)) | ||
938 | goto done; | ||
939 | |||
940 | table = * prop->host->ptable (obj); | ||
941 | } | ||
942 | } | ||
943 | |||
944 | if (! table) | ||
945 | goto done; | ||
946 | |||
947 | result = (g_hash_table_lookup (table, & code) != NULL); | ||
948 | |||
949 | done: | ||
950 | |||
951 | #ifdef DEBUG_PROPS | ||
952 | g_print ("isset %p.%s = %s\n", obj, prop->prop_name, result ? "true" : "false"); | ||
953 | #endif | ||
954 | |||
955 | return result; | ||
956 | } | ||
957 | |||
958 | gboolean | ||
959 | edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj) | ||
960 | { | ||
961 | EdsioProperty* prop; | ||
962 | gboolean persist; | ||
963 | GHashTable* table; | ||
964 | |||
965 | if (! (prop = edsio_property_find (ph, t, code))) | ||
966 | return FALSE; | ||
967 | |||
968 | #ifdef DEBUG_PROPS | ||
969 | g_print ("unset %p.%s\n", obj, prop->prop_name); | ||
970 | #endif | ||
971 | |||
972 | persist = prop->prop_flags & PF_Persistent; | ||
973 | table = * prop->host->ptable (obj); | ||
974 | |||
975 | if (table) | ||
976 | { | ||
977 | EdsioPropertyEntry* ent; | ||
978 | |||
979 | ent = g_hash_table_lookup (table, & code); | ||
980 | |||
981 | g_hash_table_remove (table, & code); | ||
982 | |||
983 | if (g_hash_table_size (table) == 0) | ||
984 | { | ||
985 | g_hash_table_destroy (table); | ||
986 | table = (* prop->host->ptable (obj)) = NULL; | ||
987 | } | ||
988 | |||
989 | /*g_free (ent);*/ | ||
990 | } | ||
991 | |||
992 | if (persist) | ||
993 | { | ||
994 | if (! prop->host->unset (obj, prop->prop_name)) | ||
995 | return FALSE; | ||
996 | } | ||
997 | |||
998 | return TRUE; | ||
999 | } | ||
1000 | |||
1001 | static gboolean | ||
1002 | edsio_false () | ||
1003 | { | ||
1004 | return FALSE; | ||
1005 | } | ||
1006 | |||
1007 | PropGSFunc | ||
1008 | edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** ep) | ||
1009 | { | ||
1010 | if (! ((*ep) = edsio_property_find (ph, t, code))) | ||
1011 | return & edsio_false; | ||
1012 | |||
1013 | return (* ep)->type->getter; | ||
1014 | } | ||
1015 | |||
1016 | PropGSFunc | ||
1017 | edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** ep) | ||
1018 | { | ||
1019 | if (! ((* ep) = edsio_property_find (ph, t, code))) | ||
1020 | return & edsio_false; | ||
1021 | |||
1022 | return (* ep)->type->setter; | ||
1023 | } | ||
1024 | |||
1025 | /* Primitive type serializers | ||
1026 | */ | ||
1027 | |||
1028 | /* integer | ||
1029 | */ | ||
1030 | gboolean | ||
1031 | edsio_property_uint_getter (gpointer obj, EdsioProperty* prop, guint32* get) | ||
1032 | { | ||
1033 | EdsioPropertyEntry *ent; | ||
1034 | |||
1035 | if (! (ent = edsio_property_get (obj, prop))) | ||
1036 | return FALSE; | ||
1037 | |||
1038 | (*get) = ent->as_uint32; | ||
1039 | |||
1040 | return TRUE; | ||
1041 | } | ||
1042 | |||
1043 | gboolean | ||
1044 | edsio_property_uint_setter (gpointer obj, EdsioProperty* prop, guint32 set) | ||
1045 | { | ||
1046 | EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1); | ||
1047 | |||
1048 | ent->as_uint32 = set; | ||
1049 | |||
1050 | return edsio_property_set (obj, prop, ent); | ||
1051 | } | ||
1052 | |||
1053 | void | ||
1054 | edsio_property_uint_free (gpointer obj) | ||
1055 | { | ||
1056 | g_free (obj); | ||
1057 | } | ||
1058 | |||
1059 | gboolean | ||
1060 | unserialize_uint (SerialSource *source, guint32** x) | ||
1061 | { | ||
1062 | SerialEdsioUint *s; | ||
1063 | guint32 *n; | ||
1064 | |||
1065 | if (! unserialize_edsiouint (source, & s)) | ||
1066 | return FALSE; | ||
1067 | |||
1068 | n = g_new (guint32, 1); | ||
1069 | |||
1070 | (* x) = n; | ||
1071 | |||
1072 | (* n) = s->val; | ||
1073 | |||
1074 | g_free (s); | ||
1075 | |||
1076 | return TRUE; | ||
1077 | } | ||
1078 | |||
1079 | gboolean | ||
1080 | serialize_uint_obj (SerialSink *sink, guint32* x) | ||
1081 | { | ||
1082 | return serialize_edsiouint (sink, *x); | ||
1083 | } | ||
1084 | |||
1085 | /* String | ||
1086 | */ | ||
1087 | |||
1088 | void | ||
1089 | edsio_property_string_free (gpointer obj) | ||
1090 | { | ||
1091 | g_free (obj); | ||
1092 | } | ||
1093 | |||
1094 | gboolean | ||
1095 | edsio_property_string_getter (gpointer obj, EdsioProperty* prop, const char** get) | ||
1096 | { | ||
1097 | if (! ((*get) = (const char*) edsio_property_get (obj, prop))) | ||
1098 | return FALSE; | ||
1099 | |||
1100 | return TRUE; | ||
1101 | } | ||
1102 | |||
1103 | gboolean | ||
1104 | edsio_property_string_setter (gpointer obj, EdsioProperty* prop, const char* set) | ||
1105 | { | ||
1106 | return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); | ||
1107 | } | ||
1108 | |||
1109 | gboolean | ||
1110 | unserialize_string (SerialSource *source, const char** x) | ||
1111 | { | ||
1112 | SerialEdsioString *s; | ||
1113 | |||
1114 | if (! unserialize_edsiostring (source, & s)) | ||
1115 | return FALSE; | ||
1116 | |||
1117 | (*x) = g_strdup (s->val); | ||
1118 | |||
1119 | g_free (s); | ||
1120 | |||
1121 | return TRUE; | ||
1122 | } | ||
1123 | |||
1124 | gboolean | ||
1125 | serialize_string_obj (SerialSink *sink, const char* x) | ||
1126 | { | ||
1127 | return serialize_edsiostring (sink, x); | ||
1128 | } | ||
1129 | |||
1130 | /* Bytes | ||
1131 | */ | ||
1132 | |||
1133 | gboolean | ||
1134 | unserialize_bytes (SerialSource *source, SerialEdsioBytes** x) | ||
1135 | { | ||
1136 | return unserialize_edsiobytes (source, x); | ||
1137 | } | ||
1138 | |||
1139 | gboolean | ||
1140 | serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x) | ||
1141 | { | ||
1142 | return serialize_edsiobytes_obj (sink, x); | ||
1143 | } | ||
1144 | |||
1145 | gboolean | ||
1146 | edsio_property_bytes_getter (gpointer obj, EdsioProperty* prop, guint8** get, guint32* get_len) | ||
1147 | { | ||
1148 | EdsioPropertyEntry *ent; | ||
1149 | |||
1150 | if (! (ent = edsio_property_get (obj, prop))) | ||
1151 | return FALSE; | ||
1152 | |||
1153 | (* get) = (gpointer) ent->as_bytes.val; | ||
1154 | (* get_len) = ent->as_bytes.val_len; | ||
1155 | |||
1156 | return TRUE; | ||
1157 | } | ||
1158 | |||
1159 | gboolean | ||
1160 | edsio_property_bytes_setter (gpointer obj, EdsioProperty* prop, guint8* set, guint32 set_len) | ||
1161 | { | ||
1162 | EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1); | ||
1163 | |||
1164 | ent->as_bytes.val = set; | ||
1165 | ent->as_bytes.val_len = set_len; | ||
1166 | |||
1167 | return edsio_property_set (obj, prop, ent); | ||
1168 | } | ||
1169 | |||
1170 | void | ||
1171 | edsio_property_bytes_free (gpointer obj) | ||
1172 | { | ||
1173 | g_free (obj); | ||
1174 | } | ||
1175 | |||
1176 | /* Vptr | ||
1177 | */ | ||
1178 | |||
1179 | gboolean | ||
1180 | edsio_property_vptr_getter (gpointer obj, EdsioProperty* prop, void** get) | ||
1181 | { | ||
1182 | if (! ((*get) = edsio_property_get (obj, prop))) | ||
1183 | return FALSE; | ||
1184 | |||
1185 | return TRUE; | ||
1186 | } | ||
1187 | |||
1188 | gboolean | ||
1189 | edsio_property_vptr_setter (gpointer obj, EdsioProperty* prop, void* set) | ||
1190 | { | ||
1191 | return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); | ||
1192 | } | ||
1193 | |||
1194 | void | ||
1195 | edsio_property_vptr_free (gpointer obj) | ||
1196 | { | ||
1197 | /* nothing */ | ||
1198 | } | ||
1199 | |||
1200 | /* Testing | ||
1201 | */ | ||
1202 | |||
1203 | #ifdef DEBUG_LIBEDSIO | ||
1204 | |||
1205 | GHashTable** | ||
1206 | edsio_proptest_property_table (PropTest *pt) | ||
1207 | { | ||
1208 | return & pt->_edsio_property_table; | ||
1209 | } | ||
1210 | |||
1211 | SerialSource* | ||
1212 | edsio_persist_proptest_source (PropTest *pt, const char* prop_name) | ||
1213 | { | ||
1214 | GByteArray* array; | ||
1215 | |||
1216 | if (! pt->ptable) | ||
1217 | { | ||
1218 | g_warning ("can't get persist property, no table\n"); | ||
1219 | return NULL; | ||
1220 | } | ||
1221 | |||
1222 | if (! (array = g_hash_table_lookup (pt->ptable, prop_name))) | ||
1223 | { | ||
1224 | g_warning ("can't lookup persist property\n"); | ||
1225 | return NULL; | ||
1226 | } | ||
1227 | |||
1228 | return edsio_simple_source (array->data, array->len, SBF_None); | ||
1229 | } | ||
1230 | |||
1231 | static void | ||
1232 | pt_success (gpointer data, GByteArray* result) | ||
1233 | { | ||
1234 | PropTest* pt = data; | ||
1235 | |||
1236 | GByteArray* old; | ||
1237 | |||
1238 | if (! pt->ptable) | ||
1239 | pt->ptable = g_hash_table_new (g_str_hash, g_str_equal); | ||
1240 | |||
1241 | old = g_hash_table_lookup (pt->ptable, (gpointer) pt->kludge); | ||
1242 | |||
1243 | if (old) | ||
1244 | g_byte_array_free (old, TRUE); | ||
1245 | |||
1246 | g_hash_table_insert (pt->ptable, (gpointer) pt->kludge, result); | ||
1247 | } | ||
1248 | |||
1249 | SerialSink* | ||
1250 | edsio_persist_proptest_sink (PropTest *pt, const char* prop_name) | ||
1251 | { | ||
1252 | pt->kludge = prop_name; | ||
1253 | |||
1254 | return edsio_simple_sink (pt, SBF_None, FALSE, pt_success, NULL); | ||
1255 | } | ||
1256 | |||
1257 | gboolean | ||
1258 | edsio_persist_proptest_isset (PropTest *pt, const char* prop_name) | ||
1259 | { | ||
1260 | if (! pt->ptable) | ||
1261 | return FALSE; | ||
1262 | |||
1263 | return g_hash_table_lookup (pt->ptable, prop_name) != NULL; | ||
1264 | } | ||
1265 | |||
1266 | gboolean | ||
1267 | edsio_persist_proptest_unset (PropTest *pt, const char* prop_name) | ||
1268 | { | ||
1269 | GByteArray* old; | ||
1270 | |||
1271 | if (! pt->ptable) | ||
1272 | return FALSE; | ||
1273 | |||
1274 | old = g_hash_table_lookup (pt->ptable, prop_name); | ||
1275 | |||
1276 | if (old) | ||
1277 | { | ||
1278 | g_byte_array_free (old, TRUE); | ||
1279 | g_hash_table_remove (pt->ptable, prop_name); | ||
1280 | return TRUE; | ||
1281 | } | ||
1282 | |||
1283 | return FALSE; | ||
1284 | } | ||
1285 | |||
1286 | #endif | ||
1287 | |||
1288 | /* Misc source/sink stuff | ||
1289 | */ | ||
1290 | |||
1291 | SerialSink* | ||
1292 | serializeio_gzip_sink (SerialSink* sink) | ||
1293 | { | ||
1294 | /* @@@ not implemented */ | ||
1295 | return sink; | ||
1296 | } | ||
1297 | |||
1298 | SerialSource* | ||
1299 | serializeio_gzip_source (SerialSource* source) | ||
1300 | { | ||
1301 | /* @@@ not implemented */ | ||
1302 | return source; | ||
1303 | } | ||
1304 | |||
1305 | /* Checksum sink | ||
1306 | */ | ||
1307 | typedef struct _ChecksumSink ChecksumSink; | ||
1308 | |||
1309 | static gboolean checksum_sink_close (SerialSink* sink); | ||
1310 | static gboolean checksum_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); | ||
1311 | static void checksum_sink_free (SerialSink* sink); | ||
1312 | static gboolean checksum_sink_quantum (SerialSink* sink); | ||
1313 | |||
1314 | struct _ChecksumSink | ||
1315 | { | ||
1316 | SerialSink sink; | ||
1317 | |||
1318 | SerialSink* out; | ||
1319 | |||
1320 | EdsioMD5Ctx ctx; | ||
1321 | guint8 md5[16]; | ||
1322 | gboolean md5_done; | ||
1323 | gboolean md5_written; | ||
1324 | }; | ||
1325 | |||
1326 | SerialSink* | ||
1327 | serializeio_checksum_sink (SerialSink* out) | ||
1328 | { | ||
1329 | ChecksumSink* it = g_new0 (ChecksumSink, 1); | ||
1330 | SerialSink* sink = (SerialSink*) it; | ||
1331 | |||
1332 | serializeio_sink_init (sink, | ||
1333 | NULL, | ||
1334 | checksum_sink_close, | ||
1335 | checksum_sink_write, | ||
1336 | checksum_sink_free, | ||
1337 | checksum_sink_quantum); | ||
1338 | |||
1339 | it->out = out; | ||
1340 | |||
1341 | edsio_md5_init (& it->ctx); | ||
1342 | |||
1343 | return sink; | ||
1344 | } | ||
1345 | |||
1346 | gboolean | ||
1347 | checksum_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len) | ||
1348 | { | ||
1349 | ChecksumSink* sink = (ChecksumSink*) fsink; | ||
1350 | |||
1351 | if (! sink->out->sink_write (sink->out, ptr, len)) | ||
1352 | return FALSE; | ||
1353 | |||
1354 | edsio_md5_update (& sink->ctx, ptr, len); | ||
1355 | |||
1356 | return TRUE; | ||
1357 | } | ||
1358 | |||
1359 | gboolean | ||
1360 | checksum_sink_close (SerialSink* fsink) | ||
1361 | { | ||
1362 | ChecksumSink* sink = (ChecksumSink*) fsink; | ||
1363 | |||
1364 | if (! sink->md5_done) | ||
1365 | { | ||
1366 | edsio_md5_final (sink->md5, & sink->ctx); | ||
1367 | sink->md5_done = TRUE; | ||
1368 | } | ||
1369 | |||
1370 | if (! sink->out->sink_write (sink->out, sink->md5, 16)) | ||
1371 | return FALSE; | ||
1372 | |||
1373 | if (! sink->out->sink_close (sink->out)) | ||
1374 | return FALSE; | ||
1375 | |||
1376 | return TRUE; | ||
1377 | } | ||
1378 | |||
1379 | void | ||
1380 | checksum_sink_free (SerialSink* fsink) | ||
1381 | { | ||
1382 | ChecksumSink* sink = (ChecksumSink*) fsink; | ||
1383 | |||
1384 | sink->out->sink_free (sink->out); | ||
1385 | |||
1386 | g_free (sink); | ||
1387 | } | ||
1388 | |||
1389 | gboolean | ||
1390 | checksum_sink_quantum (SerialSink* fsink) | ||
1391 | { | ||
1392 | ChecksumSink* sink = (ChecksumSink*) fsink; | ||
1393 | |||
1394 | if (sink->out->sink_quantum) | ||
1395 | return sink->out->sink_quantum (sink->out); | ||
1396 | |||
1397 | return TRUE; | ||
1398 | } | ||
1399 | |||
1400 | /* Checksum source | ||
1401 | */ | ||
1402 | |||
1403 | typedef struct _ChecksumSource ChecksumSource; | ||
1404 | |||
1405 | struct _ChecksumSource { | ||
1406 | SerialSource source; | ||
1407 | |||
1408 | SerialSource *in; | ||
1409 | |||
1410 | EdsioMD5Ctx ctx; | ||
1411 | }; | ||
1412 | |||
1413 | static gboolean checksum_source_close (SerialSource* source); | ||
1414 | static gboolean checksum_source_read (SerialSource* source, guint8 *ptr, guint32 len); | ||
1415 | static void checksum_source_free (SerialSource* source); | ||
1416 | |||
1417 | SerialSource* | ||
1418 | serializeio_checksum_source (SerialSource* in0) | ||
1419 | { | ||
1420 | ChecksumSource* it = g_new0 (ChecksumSource, 1); | ||
1421 | SerialSource* source = (SerialSource*) it; | ||
1422 | |||
1423 | serializeio_source_init (source, | ||
1424 | NULL, | ||
1425 | checksum_source_close, | ||
1426 | checksum_source_read, | ||
1427 | checksum_source_free, | ||
1428 | NULL, | ||
1429 | NULL); | ||
1430 | |||
1431 | it->in = in0; | ||
1432 | |||
1433 | edsio_md5_init (& it->ctx); | ||
1434 | |||
1435 | return source; | ||
1436 | } | ||
1437 | |||
1438 | gboolean | ||
1439 | checksum_source_close (SerialSource* fsource) | ||
1440 | { | ||
1441 | ChecksumSource* source = (ChecksumSource*) fsource; | ||
1442 | guint8 buf1[16]; | ||
1443 | guint8 buf2[16]; | ||
1444 | |||
1445 | if (! source->in->source_read (source->in, buf1, 16)) | ||
1446 | return FALSE; | ||
1447 | |||
1448 | edsio_md5_final (buf2, & source->ctx); | ||
1449 | |||
1450 | if (memcmp (buf1, buf2, 16) != 0) | ||
1451 | { | ||
1452 | edsio_generate_void_event (EC_EdsioInvalidStreamChecksum); | ||
1453 | return FALSE; | ||
1454 | } | ||
1455 | |||
1456 | if (! source->in->source_close (source->in)) | ||
1457 | return FALSE; | ||
1458 | |||
1459 | return TRUE; | ||
1460 | } | ||
1461 | |||
1462 | gboolean | ||
1463 | checksum_source_read (SerialSource* fsource, guint8 *ptr, guint32 len) | ||
1464 | { | ||
1465 | ChecksumSource* source = (ChecksumSource*) fsource; | ||
1466 | |||
1467 | if (! source->in->source_read (source->in, ptr, len)) | ||
1468 | return FALSE; | ||
1469 | |||
1470 | edsio_md5_update (& source->ctx, ptr, len); | ||
1471 | |||
1472 | return TRUE; | ||
1473 | } | ||
1474 | |||
1475 | void | ||
1476 | checksum_source_free (SerialSource* fsource) | ||
1477 | { | ||
1478 | ChecksumSource* source = (ChecksumSource*) fsource; | ||
1479 | |||
1480 | source->in->source_free (source->in); | ||
1481 | |||
1482 | g_free (source); | ||
1483 | } | ||
1484 | |||
1485 | /* Missing glib stuff | ||
1486 | */ | ||
1487 | |||
1488 | GQueue * | ||
1489 | g_queue_new (void) | ||
1490 | { | ||
1491 | GQueue *q = g_new (GQueue, 1); | ||
1492 | |||
1493 | q->list = q->list_end = NULL; | ||
1494 | q->list_size = 0; | ||
1495 | |||
1496 | return q; | ||
1497 | } | ||
1498 | |||
1499 | |||
1500 | void | ||
1501 | g_queue_free (GQueue *q) | ||
1502 | { | ||
1503 | if (q) | ||
1504 | { | ||
1505 | if (q->list) | ||
1506 | g_list_free (q->list); | ||
1507 | g_free (q); | ||
1508 | } | ||
1509 | } | ||
1510 | |||
1511 | |||
1512 | guint | ||
1513 | g_queue_get_size (GQueue *q) | ||
1514 | { | ||
1515 | return (q == NULL) ? 0 : q->list_size; | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | void | ||
1520 | g_queue_push_front (GQueue *q, gpointer data) | ||
1521 | { | ||
1522 | if (q) | ||
1523 | { | ||
1524 | q->list = g_list_prepend (q->list, data); | ||
1525 | |||
1526 | if (q->list_end == NULL) | ||
1527 | q->list_end = q->list; | ||
1528 | |||
1529 | q->list_size++; | ||
1530 | } | ||
1531 | } | ||
1532 | |||
1533 | |||
1534 | void | ||
1535 | g_queue_push_back (GQueue *q, gpointer data) | ||
1536 | { | ||
1537 | if (q) | ||
1538 | { | ||
1539 | q->list_end = g_list_append (q->list_end, data); | ||
1540 | |||
1541 | if (! q->list) | ||
1542 | q->list = q->list_end; | ||
1543 | else | ||
1544 | q->list_end = q->list_end->next; | ||
1545 | |||
1546 | q->list_size++; | ||
1547 | } | ||
1548 | } | ||
1549 | |||
1550 | |||
1551 | gpointer | ||
1552 | g_queue_pop_front (GQueue *q) | ||
1553 | { | ||
1554 | gpointer data = NULL; | ||
1555 | |||
1556 | if ((q) && (q->list)) | ||
1557 | { | ||
1558 | GList *node; | ||
1559 | |||
1560 | node = q->list; | ||
1561 | data = node->data; | ||
1562 | |||
1563 | if (! node->next) | ||
1564 | { | ||
1565 | q->list = q->list_end = NULL; | ||
1566 | q->list_size = 0; | ||
1567 | } | ||
1568 | else | ||
1569 | { | ||
1570 | q->list = node->next; | ||
1571 | q->list->prev = NULL; | ||
1572 | q->list_size--; | ||
1573 | } | ||
1574 | |||
1575 | g_list_free_1 (node); | ||
1576 | } | ||
1577 | |||
1578 | return data; | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | gpointer | ||
1583 | g_queue_pop_back (GQueue *q) | ||
1584 | { | ||
1585 | gpointer data = NULL; | ||
1586 | |||
1587 | if ((q) && (q->list)) | ||
1588 | { | ||
1589 | GList *node; | ||
1590 | |||
1591 | node = q->list_end; | ||
1592 | data = node->data; | ||
1593 | |||
1594 | if (! node->prev) | ||
1595 | { | ||
1596 | q->list = q->list_end = NULL; | ||
1597 | q->list_size = 0; | ||
1598 | } | ||
1599 | else | ||
1600 | { | ||
1601 | q->list_end = node->prev; | ||
1602 | q->list_end->next = NULL; | ||
1603 | q->list_size--; | ||
1604 | } | ||
1605 | |||
1606 | g_list_free_1 (node); | ||
1607 | } | ||
1608 | |||
1609 | return data; | ||
1610 | } | ||