You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
441 lines
9.0 KiB
441 lines
9.0 KiB
/*
|
|
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 "config.h"
|
|
#include "marshal.h"
|
|
|
|
#include <glib.h>
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* The code in previous revisions was broken on little endian system, also see KDE bug #32463 */
|
|
/* The current code was not tested on big endian system, so it could be another issue and big */
|
|
/* endian systems would need the same code as the little endian ones */
|
|
#include <endian.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 );
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
buf[0] = val;
|
|
buf[1] = val >> 8;
|
|
buf[2] = val >> 16;
|
|
buf[3] = val >> 24;
|
|
#else
|
|
buf[3] = val;
|
|
buf[2] = val >> 8;
|
|
buf[1] = val >> 16;
|
|
buf[0] = val >> 24;
|
|
#endif
|
|
|
|
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;
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
*val = (data->cur[3] << 24) |
|
|
(data->cur[2] << 16) |
|
|
(data->cur[1] << 8) |
|
|
data->cur[0];
|
|
#else
|
|
*val = (data->cur[0] << 24) |
|
|
(data->cur[1] << 16) |
|
|
(data->cur[2] << 8) |
|
|
data->cur[3];
|
|
#endif
|
|
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; }
|