summaryrefslogtreecommitdiff
path: root/xdelta1/libedsio/edsio.c
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta1/libedsio/edsio.c')
-rw-r--r--xdelta1/libedsio/edsio.c1610
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
31static GHashTable* all_event_defs = NULL;
32
33static GPtrArray* all_event_watchers = NULL;
34
35typedef struct _ErrorDeliveryWatcher ErrorDeliveryWatcher;
36typedef struct _DelayedEvent DelayedEvent;
37
38struct _ErrorDeliveryWatcher {
39 ErrorDeliveryFunc deliver;
40};
41
42struct _DelayedEvent {
43 GenericEvent ev;
44 GenericEventDef *def;
45 const char *msg;
46};
47
48void
49eventdelivery_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
71void
72eventdelivery_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
84GenericEventDef*
85eventdelivery_event_lookup (gint code)
86{
87 return g_hash_table_lookup (all_event_defs, & code);
88}
89
90void
91eventdelivery_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
240const char*
241eventdelivery_int_to_string (int x)
242{
243 return g_strdup_printf ("%d", x);
244}
245
246const char*
247eventdelivery_string_to_string (const char* x)
248{
249 return g_strdup (x);
250}
251
252const char*
253eventdelivery_source_to_string (SerialSource* x)
254{
255 return g_strdup ("@@@SerialSource");
256}
257
258const char*
259eventdelivery_sink_to_string (SerialSink* x)
260{
261 return g_strdup ("@@@SerialSink");
262}
263
264const char*
265eventdelivery_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
275gboolean
276edsio_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
323gchar*
324edsio_time_to_iso8601 (SerialGenericTime *tp)
325{
326 return edsio_time_t_to_iso8601 (tp->seconds);
327}
328
329gchar*
330edsio_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(&lt, 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
356static gboolean
357strtosl_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
375gboolean
376strtosi_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
400gboolean
401strtoss_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
425gboolean
426strtoui_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
459gboolean
460strtous_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
493gint
494edsio_md5_equal (gconstpointer v,
495 gconstpointer v2)
496{
497 return memcmp (v, v2, 16) == 0;
498}
499
500guint
501edsio_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
513void
514serializeio_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
531void
532edsio_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
540static gboolean
541from_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
568gboolean
569edsio_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
606const 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
619typedef struct _EdsioHostType EdsioHostType;
620typedef struct _EdsioPropertyType EdsioPropertyType;
621
622struct _EdsioPropertyType {
623 const char *type_name;
624 PropFreeFunc freer;
625 PropGSFunc getter;
626 PropGSFunc setter;
627 PropSerialize serialize;
628 PropUnserialize unserialize;
629};
630
631struct _EdsioHostType {
632 const char *host_name;
633 PropertyTableFunc ptable;
634 PersistSourceFunc source;
635 PersistSinkFunc sink;
636 PersistIssetFunc isset;
637 PersistUnsetFunc unset;
638};
639
640struct _EdsioProperty {
641 guint32 prop_code;
642 const char *prop_name;
643 guint32 prop_flags;
644 EdsioPropertyType *type;
645 EdsioHostType *host;
646};
647
648union _EdsioPropertyEntry {
649 guint32 as_uint32;
650 SerialEdsioBytes as_bytes;
651 gpointer as_vptr;
652 const char* as_string;
653};
654
655struct _EdsioGenericProperty
656{
657 guint32 code;
658};
659
660static GHashTable* all_property_types = NULL;
661static GHashTable* all_host_types = NULL;
662static GHashTable* all_properties = NULL;
663static GHashTable* all_property_codes = NULL;
664static guint32 property_code_sequence = 0;
665
666void
667edsio_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
698void
699edsio_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
732gboolean
733edsio_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
792static EdsioProperty*
793edsio_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
827EdsioPropertyEntry*
828edsio_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
872gboolean
873edsio_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
917gboolean
918edsio_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
958gboolean
959edsio_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
1001static gboolean
1002edsio_false ()
1003{
1004 return FALSE;
1005}
1006
1007PropGSFunc
1008edsio_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
1016PropGSFunc
1017edsio_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 */
1030gboolean
1031edsio_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
1043gboolean
1044edsio_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
1053void
1054edsio_property_uint_free (gpointer obj)
1055{
1056 g_free (obj);
1057}
1058
1059gboolean
1060unserialize_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
1079gboolean
1080serialize_uint_obj (SerialSink *sink, guint32* x)
1081{
1082 return serialize_edsiouint (sink, *x);
1083}
1084
1085/* String
1086 */
1087
1088void
1089edsio_property_string_free (gpointer obj)
1090{
1091 g_free (obj);
1092}
1093
1094gboolean
1095edsio_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
1103gboolean
1104edsio_property_string_setter (gpointer obj, EdsioProperty* prop, const char* set)
1105{
1106 return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set);
1107}
1108
1109gboolean
1110unserialize_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
1124gboolean
1125serialize_string_obj (SerialSink *sink, const char* x)
1126{
1127 return serialize_edsiostring (sink, x);
1128}
1129
1130/* Bytes
1131 */
1132
1133gboolean
1134unserialize_bytes (SerialSource *source, SerialEdsioBytes** x)
1135{
1136 return unserialize_edsiobytes (source, x);
1137}
1138
1139gboolean
1140serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x)
1141{
1142 return serialize_edsiobytes_obj (sink, x);
1143}
1144
1145gboolean
1146edsio_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
1159gboolean
1160edsio_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
1170void
1171edsio_property_bytes_free (gpointer obj)
1172{
1173 g_free (obj);
1174}
1175
1176/* Vptr
1177 */
1178
1179gboolean
1180edsio_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
1188gboolean
1189edsio_property_vptr_setter (gpointer obj, EdsioProperty* prop, void* set)
1190{
1191 return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set);
1192}
1193
1194void
1195edsio_property_vptr_free (gpointer obj)
1196{
1197 /* nothing */
1198}
1199
1200/* Testing
1201 */
1202
1203#ifdef DEBUG_LIBEDSIO
1204
1205GHashTable**
1206edsio_proptest_property_table (PropTest *pt)
1207{
1208 return & pt->_edsio_property_table;
1209}
1210
1211SerialSource*
1212edsio_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
1231static void
1232pt_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
1249SerialSink*
1250edsio_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
1257gboolean
1258edsio_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
1266gboolean
1267edsio_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
1291SerialSink*
1292serializeio_gzip_sink (SerialSink* sink)
1293{
1294 /* @@@ not implemented */
1295 return sink;
1296}
1297
1298SerialSource*
1299serializeio_gzip_source (SerialSource* source)
1300{
1301 /* @@@ not implemented */
1302 return source;
1303}
1304
1305/* Checksum sink
1306 */
1307typedef struct _ChecksumSink ChecksumSink;
1308
1309static gboolean checksum_sink_close (SerialSink* sink);
1310static gboolean checksum_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
1311static void checksum_sink_free (SerialSink* sink);
1312static gboolean checksum_sink_quantum (SerialSink* sink);
1313
1314struct _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
1326SerialSink*
1327serializeio_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
1346gboolean
1347checksum_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
1359gboolean
1360checksum_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
1379void
1380checksum_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
1389gboolean
1390checksum_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
1403typedef struct _ChecksumSource ChecksumSource;
1404
1405struct _ChecksumSource {
1406 SerialSource source;
1407
1408 SerialSource *in;
1409
1410 EdsioMD5Ctx ctx;
1411};
1412
1413static gboolean checksum_source_close (SerialSource* source);
1414static gboolean checksum_source_read (SerialSource* source, guint8 *ptr, guint32 len);
1415static void checksum_source_free (SerialSource* source);
1416
1417SerialSource*
1418serializeio_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
1438gboolean
1439checksum_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
1462gboolean
1463checksum_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
1475void
1476checksum_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
1488GQueue *
1489g_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
1500void
1501g_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
1512guint
1513g_queue_get_size (GQueue *q)
1514{
1515 return (q == NULL) ? 0 : q->list_size;
1516}
1517
1518
1519void
1520g_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
1534void
1535g_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
1551gpointer
1552g_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
1582gpointer
1583g_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}