diff options
Diffstat (limited to 'dcopc/marshal.c')
-rw-r--r-- | dcopc/marshal.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/dcopc/marshal.c b/dcopc/marshal.c new file mode 100644 index 00000000..e0de9296 --- /dev/null +++ b/dcopc/marshal.c @@ -0,0 +1,420 @@ +/* +Copyright (c) 2000 Simon Hausmann <hausmann@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "marshal.h" + +#include <glib.h> + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +dcop_data *dcop_data_new() +{ + dcop_data *res = g_new( dcop_data, 1 ); + + res->ptr = 0; + res->size = 0; + res->cur = 0; + res->ref = 0; + + return res; +} + +void dcop_data_destroy( dcop_data *data ) +{ + g_assert( data->ref == 0 ); + + g_free( data->ptr ); + + g_free( data ); +} + +dcop_data *dcop_data_copy( dcop_data *data ) +{ + dcop_data *res = dcop_data_new(); + res->ptr = (char *)g_malloc( data->size ); + res->size = data->size; + dcop_data_reset( res ); + memcpy( res->ptr, data->ptr, data->size ); + return res; +} + +static gboolean dcop_data_check_size( dcop_data *data, unsigned int size ) +{ + if ( data->size - ( data->cur - data->ptr ) < size ) + return FALSE; + return TRUE; +} + +gboolean dcop_marshal_raw( dcop_data *data, const void *ptr, unsigned int size ) +{ + unsigned int relptr = data->cur - data->ptr; + + data->ptr = (char *)g_realloc( data->ptr, data->size + size ); + + if ( data->ptr == 0 ) + return FALSE; + + data->cur = data->ptr + relptr; + + memcpy( data->cur, ptr, size ); + + data->cur += size; + data->size += size; + + return TRUE; +} + +gboolean dcop_marshal_uint32( dcop_data *data, unsigned int val ) +{ + unsigned char buf[4]; + + g_assert( sizeof( unsigned int ) == 4 ); + + buf[0] = val; + buf[1] = val >> 8; + buf[2] = val >> 16; + buf[3] = val >> 24; + + return dcop_marshal_raw( data, buf, 4 ); +} + +gboolean dcop_demarshal_uint32( dcop_data *data, unsigned int *val ) +{ + g_assert( sizeof( unsigned int ) == 4 ); + + if ( !dcop_data_check_size( data, 4 ) ) + return FALSE; + + *val = (data->cur[3] << 24) | + (data->cur[2] << 16) | + (data->cur[1] << 8) | + data->cur[0]; + data->cur += 4; + + return TRUE; +} + +gboolean dcop_marshal_string( dcop_data *data, const gchar *str ) +{ + size_t l = 0; + + if ( str ) + l = strlen( str ) + 1; + + if( !dcop_marshal_uint32( data, l ) ) + return FALSE; + + if ( str ) + return dcop_marshal_raw( data, str, l ); + else + return TRUE; +} + +gboolean dcop_demarshal_string( dcop_data *data, gchar **str ) +{ + unsigned int l = 0; + gchar *res = 0; + + g_assert( str ); + + if ( !dcop_demarshal_uint32( data, &l ) ) + return FALSE; + + if ( !dcop_data_check_size( data, l ) ) + return FALSE; + + res = (char *)g_malloc( l ); + memcpy( res, data->cur, l ); + data->cur += l; + + *str = res; + + return TRUE; +} + + +gboolean dcop_marshal_string16( dcop_data *data, const gchar *str ) +{ + size_t l = 0; + size_t c = 0; + char *tmp = 0; + const char *src = str; + char *dst = 0; + + if ( str ) + l = strlen( str ) * 2; + else + { + /* null marker*/ + guint32 s = 0xffffffff; + return dcop_marshal_uint32( data, s ); + } + + if( !dcop_marshal_uint32( data, l ) ) + return FALSE; + + if ( str ) + { + dst = tmp = (char *)g_malloc( l ); + c = strlen( str ); + + while ( c-- ) + { + *dst++ = 0; + *dst++ = *src++; + } + + dcop_marshal_raw( data, tmp, l ); + + g_free( tmp ); + } + return TRUE; +} + +gboolean dcop_demarshal_string16( dcop_data *data, gchar **str ) +{ + unsigned int l = 0; + unsigned int size = 0; + char *res = 0; + char *p = 0; + + assert( str ); + + if ( !dcop_demarshal_uint32( data, &l ) ) + return FALSE; + + /* null marker*/ + if ( l == 0xffffffff ) + { + *str = 0; + return TRUE; + } + + if ( !dcop_data_check_size( data, l ) ) + return FALSE; + + size = ( l / 2 ); + + p = res = (char *)g_malloc( size + 1 ); + + while( size-- ) + { + data->cur++; + *p++ = *data->cur++; + } + + *p = '\0'; + + *str = res; + + return TRUE; +} + +gboolean dcop_marshal_bytearray( dcop_data *data, const gchar *str, size_t size ) +{ + if( !dcop_marshal_uint32( data, size ) ) + return FALSE; + + if ( str ) + return dcop_marshal_raw( data, str, size ); + else + return TRUE; +} + +gboolean dcop_demarshal_bytearray( dcop_data *data, gchar **str, size_t *size ) +{ + unsigned int l = 0; + gchar *res = 0; + + g_assert( str ); + + if ( !dcop_demarshal_uint32( data, &l ) ) + return FALSE; + + if ( !dcop_data_check_size( data, l ) ) + return FALSE; + + res = (char *)g_malloc( l ); + memcpy( res, data->cur, l ); + data->cur += l; + + *str = res; + *size = l; + + return TRUE; +} + + + +gboolean dcop_marshal_data( dcop_data *data, dcop_data *other ) +{ + if ( !dcop_marshal_uint32( data, other->size ) ) + return FALSE; + + return dcop_marshal_raw( data, other->ptr, other->size ); +} + +gboolean dcop_demarshal_data( dcop_data *data, dcop_data **other ) +{ + dcop_data *res = dcop_data_new(); + char *tmp = 0; + unsigned int l = 0; + + if ( !dcop_demarshal_uint32( data, &l ) ) + return FALSE; + + if ( !dcop_data_check_size( data, l ) ) + return FALSE; + + tmp = (char *)malloc( l ); + + memcpy( tmp, data->cur, l ); + data->cur += l; + + dcop_data_assign( res, tmp, l ); + dcop_data_ref( res ); + + *other = res; + return True; +} + +gboolean dcop_marshal_stringlist( dcop_data *data, GList *list ) +{ + GList *it = g_list_first( list ); + + if ( !dcop_marshal_uint32( data, g_list_length( list ) ) ) + return FALSE; + + while ( it ) + { + if ( !dcop_marshal_string( data, (gchar *)it->data ) ) + return FALSE; + it = g_list_next( it ); + } + return TRUE; +} + +gboolean dcop_demarshal_stringlist( dcop_data *data, GList**list ) +{ + unsigned int count = 0; + GList *res = 0; + unsigned int i = 0; + gchar *str = 0; + + *list = 0; + + if ( !dcop_demarshal_uint32( data, &count ) ) + return FALSE; + + for ( i = 0; i < count; ++i ) + { + if ( !dcop_demarshal_string( data, &str ) ) + { + dcop_list_free( res ); + return FALSE; + } + res = g_list_append( res, str ); + } + *list = res; + return TRUE; +} + +gboolean dcop_marshal_stringlist16( dcop_data *data, GList *list ) +{ + GList *it = g_list_first( list ); + + if ( !dcop_marshal_uint32( data, g_list_length( list ) ) ) + return False; + + while ( it ) + { + if ( !dcop_marshal_string16( data, (gchar *)it->data ) ) + return FALSE; + it = g_list_next( it ); + } + return TRUE; +} + +gboolean dcop_demarshal_stringlist16( dcop_data *data, GList **list ) +{ + unsigned int count = 0; + GList *res = 0; + unsigned int i = 0; + char *str = 0; + + *list = 0; + + if ( !dcop_demarshal_uint32( data, &count ) ) + return FALSE; + + for ( i = 0; i < count; ++i ) + { + if ( !dcop_demarshal_string16( data, &str ) ) + { + dcop_list_free( res ); + return FALSE; + } + res = g_list_append( res, str ); + } + *list = res; + return TRUE; +} + +void dcop_data_assign( dcop_data *data, char *d, unsigned int size ) +{ + data->ptr = data->cur = d; + data->size = size; +} + +gboolean dcop_marshal_boolean( dcop_data *data, gboolean val ) +{ + guint8 i = (guint8)val; + return dcop_marshal_uint8( data, i ); +} + +gboolean dcop_demarshal_boolean( dcop_data *data, gboolean *val ) +{ + guint8 i; + if ( !dcop_demarshal_uint8( data, &i ) ) + return FALSE; + *val = (gboolean)i; + return TRUE; +} + +gboolean dcop_marshal_uint8( dcop_data *data, guint8 val ) +{ + return dcop_marshal_raw( data, &val, 1 ); +} + +gboolean dcop_demarshal_uint8( dcop_data *data, guint8 *val ) +{ + if ( !dcop_data_check_size( data, 1 ) ) + return FALSE; + + *val = *data->cur++; + return TRUE; +} + +dcop_data *dcop_data_ref( dcop_data *data ) { data->ref++; return data; } +void dcop_data_deref( dcop_data *data ) { if ( !--data->ref ) dcop_data_destroy( data ); } +void dcop_data_reset( dcop_data *data ) { data->cur = data->ptr; } |