/* -*-Mode: C;-*- * $Id: default.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* Default Sink methods */ static gboolean sink_type_default (SerialSink* sink, SerialType type, guint32 len, gboolean set_allocation) { if (! sink->next_uint32 (sink, type)) return FALSE; /* Note: set_allocation is deprecated in 1.1.4 */ if (set_allocation && !sink->next_uint32 (sink, len)) return FALSE; return TRUE; } static gboolean sink_next_uint16 (SerialSink* sink, guint16 num) { num = g_htons (num); return sink->sink_write (sink, (guint8*) &num, sizeof (num)); } static gboolean sink_next_uint32 (SerialSink* sink, guint32 num) { num = g_htonl (num); return sink->sink_write (sink, (guint8*) &num, sizeof (num)); } static gboolean sink_next_uint (SerialSink* sink, guint32 num) { /* This is mostly because I dislike endian, and less to save space * on small ints. However, the uint32 and uint16 functions are used * when the number is expected to be large, in which case this * format can expand the number. */ guint8 sink_buf[16]; /* this is enough room for a 12-byte int */ guint sink_count = 0; do { guint left = num & 0x7f; guint outnum; num >>= 7; outnum = left | (num ? 0x80 : 0); sink_buf[sink_count++] = outnum; } while (num); return sink->sink_write (sink, sink_buf, sink_count); } static gboolean sink_next_uint8 (SerialSink* sink, guint8 val) { return sink->sink_write (sink, &val, 1); } static gboolean sink_next_bool (SerialSink* sink, gboolean val) { guint8 sink_buf[1]; sink_buf[0] = val; return sink->sink_write (sink, sink_buf, 1); } static gboolean sink_next_string (SerialSink* sink, const char *ptr) { return sink->next_bytes (sink, ptr, strlen (ptr)); } static gboolean sink_next_bytes (SerialSink* sink, const guint8 *ptr, guint32 len) { return sink->next_uint (sink, len) && sink->sink_write (sink, ptr, len); } static gboolean sink_next_bytes_known (SerialSink* sink, const guint8 *ptr, guint32 len) { return sink->sink_write (sink, ptr, len); } void serializeio_sink_init (SerialSink* it, gboolean (* sink_type) (SerialSink* sink, SerialType type, guint32 mem_size, gboolean set_allocation), gboolean (* sink_close) (SerialSink* sink), gboolean (* sink_write) (SerialSink* sink, const guint8 *ptr, guint32 len), void (* sink_free) (SerialSink* sink), gboolean (* sink_quantum) (SerialSink* sink)) { it->next_bytes_known = sink_next_bytes_known; it->next_bytes = sink_next_bytes; it->next_uint = sink_next_uint; it->next_uint32 = sink_next_uint32; it->next_uint16 = sink_next_uint16; it->next_uint8 = sink_next_uint8; it->next_bool = sink_next_bool; it->next_string = sink_next_string; if (sink_type) it->sink_type = sink_type; else it->sink_type = sink_type_default; it->sink_close = sink_close; it->sink_write = sink_write; it->sink_free = sink_free; it->sink_quantum = sink_quantum; } /* Default Source methods */ static SerialType source_type_default (SerialSource* source, gboolean set_allocation) { guint32 x; if (! source->next_uint32 (source, & x)) return ST_Error; if (set_allocation) { /* Note: set_allocation is deprecated in 1.1.4 */ guint32 bogus; if (! source->next_uint32 (source, &bogus)) return ST_Error; } return x; } static gboolean source_next_uint32 (SerialSource* source, guint32 *ptr) { guint32 x; if (! source->source_read (source, (guint8*) &x, sizeof (x))) return FALSE; (*ptr) = g_ntohl (x); return TRUE; } static gboolean source_next_uint16 (SerialSource* source, guint16 *ptr) { guint16 x; if (! source->source_read (source, (guint8*) &x, sizeof (x))) return FALSE; (*ptr) = g_ntohs (x); return TRUE; } static gboolean source_next_uint (SerialSource* source, guint32 *ptr) { /* This is mostly because I dislike endian, and less to save space * on small ints */ guint8 c; guint8 arr[16]; gint i = 0; gint donebit = 1; gint bits; while (source->next_uint8 (source, &c)) { donebit = c & 0x80; bits = c & 0x7f; arr[i++] = bits; if (!donebit) break; } if (donebit) return FALSE; *ptr = 0; for (i -= 1; i >= 0; i -= 1) { *ptr <<= 7; *ptr |= arr[i]; } return TRUE; } static gboolean source_next_uint8 (SerialSource* source, guint8 *ptr) { return source->source_read (source, ptr, 1); } static gboolean source_next_bool (SerialSource* source, gboolean *ptr) { guint8 sink_buf[1]; if (! source->source_read (source, sink_buf, 1)) return FALSE; if (sink_buf[0]) *ptr = TRUE; else *ptr = FALSE; return TRUE; } static gboolean source_next_string (SerialSource* source, const char **ptr) { guint32 len; guint8* buf; if (! source->next_uint (source, &len)) return FALSE; if (! (buf = serializeio_source_alloc (source, len+1))) return FALSE; buf[len] = 0; (*ptr) = buf; return source->source_read (source, buf, len); } static gboolean source_next_bytes (SerialSource* source, const guint8 **ptr, guint32 *len_ptr) { guint32 len; guint8* buf; if (! source->next_uint (source, &len)) return FALSE; if (! (buf = serializeio_source_alloc (source, len))) return FALSE; (*len_ptr) = len; (*ptr) = buf; return source->source_read (source, buf, len); } static gboolean source_next_bytes_known (SerialSource* source, guint8 *ptr, guint32 len) { return source->source_read (source, ptr, len); } void* serializeio_source_alloc (SerialSource* source, guint32 len) { AllocList *al; void* ret; if (source->salloc_func) { ret = source->salloc_func (source, len); al = source->salloc_func (source, sizeof(AllocList)); } else { ret = g_malloc0 (len); al = g_malloc0 (sizeof(AllocList)); } al->ptr = ret; al->next = source->alloc_list; source->alloc_list = al; return ret; } void serializeio_source_init (SerialSource* it, SerialType (* source_type) (SerialSource* source, gboolean set_allocation), gboolean (* source_close) (SerialSource* source), gboolean (* source_read) (SerialSource* source, guint8 *ptr, guint32 len), void (* source_free) (SerialSource* source), void* (* salloc_func) (SerialSource* source, guint32 len), void (* sfree_func) (SerialSource* source, void* ptr)) { it->alloc_list = NULL; it->next_bytes_known = source_next_bytes_known; it->next_bytes = source_next_bytes; it->next_uint = source_next_uint; it->next_uint32 = source_next_uint32; it->next_uint16 = source_next_uint16; it->next_uint8 = source_next_uint8; it->next_bool = source_next_bool; it->next_string = source_next_string; if (source_type != NULL) it->source_type = source_type; else it->source_type = source_type_default; it->source_close = source_close; it->source_read = source_read; it->source_free = source_free; it->salloc_func = salloc_func; it->sfree_func = sfree_func; }