850 lines
17 KiB
C
850 lines
17 KiB
C
/* $Id$ */
|
|
/* Copyright (c) 2012-2014 Pierre Pronchery <khorben@defora.org> */
|
|
/* This file is part of DeforaOS System libSystem */
|
|
/* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, version 3 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <arpa/inet.h>
|
|
#include "System/error.h"
|
|
#include "System/object.h"
|
|
#include "System/variable.h"
|
|
|
|
|
|
/* Variable */
|
|
/* private */
|
|
/* types */
|
|
struct _Variable
|
|
{
|
|
VariableType type;
|
|
|
|
union
|
|
{
|
|
int8_t int8;
|
|
uint8_t uint8;
|
|
int16_t int16;
|
|
uint16_t uint16;
|
|
int32_t int32;
|
|
uint32_t uint32;
|
|
int64_t int64;
|
|
uint64_t uint64;
|
|
float f;
|
|
double d;
|
|
Buffer * buffer;
|
|
String * string;
|
|
} u;
|
|
};
|
|
|
|
|
|
/* constants */
|
|
#define VT_LAST VT_STRING
|
|
#define VT_COUNT (VT_LAST + 1)
|
|
static const size_t _variable_sizes[VT_COUNT] = { 0, 1,
|
|
sizeof(int8_t), sizeof(uint8_t), sizeof(int16_t), sizeof(uint16_t),
|
|
sizeof(int32_t), sizeof(uint32_t), sizeof(int64_t), sizeof(uint64_t),
|
|
0, 0, sizeof(uint32_t), 0 };
|
|
|
|
|
|
/* prototypes */
|
|
static void _variable_destroy(Variable * variable);
|
|
|
|
|
|
/* public */
|
|
/* variable_new */
|
|
Variable * variable_new(VariableType type, void * value)
|
|
{
|
|
Variable * variable;
|
|
|
|
if((variable = object_new(sizeof(*variable))) == NULL)
|
|
return NULL;
|
|
if(variable_set_from(variable, type, value) != 0)
|
|
{
|
|
object_delete(variable);
|
|
return NULL;
|
|
}
|
|
return variable;
|
|
}
|
|
|
|
|
|
/* variable_new_array */
|
|
Variable * variable_new_array(VariableType type, size_t size, ...)
|
|
{
|
|
/* FIXME implement */
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* variable_new_arrayv */
|
|
Variable * variable_new_arrayv(VariableType type, size_t size, void ** values)
|
|
{
|
|
/* FIXME implement */
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* variable_new_compound */
|
|
Variable * variable_new_compound(String const * name, size_t members, ...)
|
|
{
|
|
/* FIXME implement */
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* variable_new_compoundv */
|
|
Variable * variable_new_compoundv(String const * name, size_t members,
|
|
VariableType * types, void ** values)
|
|
{
|
|
/* FIXME implement */
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* variable_new_copy */
|
|
Variable * variable_new_copy(Variable * variable)
|
|
{
|
|
switch(variable->type)
|
|
{
|
|
case VT_NULL:
|
|
case VT_BOOL:
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
case VT_INT16:
|
|
case VT_UINT16:
|
|
case VT_INT32:
|
|
case VT_UINT32:
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
case VT_FLOAT:
|
|
case VT_DOUBLE:
|
|
return variable_new(variable->type, &variable->u);
|
|
case VT_STRING:
|
|
return variable_new(variable->type, variable->u.string);
|
|
case VT_BUFFER:
|
|
return variable_new(variable->type, variable->u.buffer);
|
|
}
|
|
error_set_code(1, "%s", "Unable to copy this type of variable");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* variable_new_deserialize */
|
|
Variable * variable_new_deserialize(size_t * size, char const * data)
|
|
{
|
|
Variable * variable;
|
|
uint8_t u8;
|
|
size_t s;
|
|
|
|
/* check the arguments */
|
|
if(size == NULL || *size < sizeof(u8) || data == NULL)
|
|
{
|
|
error_set_code(-EINVAL, "%s", strerror(EINVAL));
|
|
return NULL;
|
|
}
|
|
/* obtain the type from the data */
|
|
u8 = data[0];
|
|
s = *size - sizeof(u8);
|
|
/* deserialize according to the type */
|
|
variable = variable_new_deserialize_type(u8, &s, &data[sizeof(u8)]);
|
|
*size = s + sizeof(u8);
|
|
return variable;
|
|
}
|
|
|
|
|
|
/* variable_new_deserialize_buffer */
|
|
Variable * variable_new_deserialize_buffer(size_t * size, Buffer const * buffer)
|
|
{
|
|
char const * data;
|
|
|
|
data = buffer_get_data(buffer);
|
|
return variable_new_deserialize(size, data);
|
|
}
|
|
|
|
|
|
/* variable_new_deserialize_type */
|
|
Variable * variable_new_deserialize_type(VariableType type, size_t * size,
|
|
char const * data)
|
|
{
|
|
Variable * v;
|
|
size_t s;
|
|
uint8_t u8;
|
|
int16_t i16;
|
|
int32_t i32;
|
|
uint32_t u32;
|
|
int64_t i64;
|
|
float f;
|
|
double d;
|
|
Buffer * b = NULL;
|
|
void * p = (char *)data;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u, %lu, %p)\n", __func__, type, *size,
|
|
(void *)data);
|
|
#endif
|
|
/* estimate the size required */
|
|
s = (type < sizeof(_variable_sizes) / sizeof(*_variable_sizes))
|
|
? _variable_sizes[type] : 0;
|
|
switch(type)
|
|
{
|
|
case VT_NULL:
|
|
break;
|
|
case VT_BOOL:
|
|
p = (char *)&u8;
|
|
break;
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
break;
|
|
case VT_INT16:
|
|
case VT_UINT16:
|
|
p = (char *)&i16;
|
|
break;
|
|
case VT_INT32:
|
|
case VT_UINT32:
|
|
p = (char *)&i32;
|
|
break;
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
p = (char *)&i64;
|
|
break;
|
|
case VT_BUFFER:
|
|
if(*size < s)
|
|
break;
|
|
memcpy(&u32, data, s);
|
|
u32 = ntohl(u32);
|
|
s += u32;
|
|
break;
|
|
case VT_FLOAT:
|
|
case VT_DOUBLE:
|
|
case VT_STRING:
|
|
for(s = 0; s < *size; s++)
|
|
if(data[s] != '\0')
|
|
continue;
|
|
else if((p = malloc(++s)) == NULL)
|
|
{
|
|
error_set_code(-errno, "%s",
|
|
strerror(errno));
|
|
return NULL;
|
|
}
|
|
else
|
|
break;
|
|
break;
|
|
default:
|
|
error_set_code(1, "Unable to deserialize type %u",
|
|
type);
|
|
return NULL;
|
|
}
|
|
if(*size < s)
|
|
{
|
|
*size = s;
|
|
error_set_code(1, "More data needed to deserialize type %u",
|
|
type);
|
|
return NULL;
|
|
}
|
|
*size = s;
|
|
if(p != data)
|
|
memcpy(p, data, s);
|
|
/* convert the data if necessary */
|
|
switch(type)
|
|
{
|
|
case VT_NULL:
|
|
break;
|
|
case VT_BOOL:
|
|
u8 = u8 ? 1 : 0;
|
|
break;
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
break;
|
|
case VT_INT16:
|
|
case VT_UINT16:
|
|
i16 = ntohs(i16);
|
|
break;
|
|
case VT_INT32:
|
|
case VT_UINT32:
|
|
i32 = ntohl(i32);
|
|
break;
|
|
case VT_FLOAT:
|
|
i32 = sscanf(p, "%e", &f);
|
|
free(p);
|
|
if(i32 != 1)
|
|
{
|
|
error_set_code(1, "Invalid float value", type);
|
|
return NULL;
|
|
}
|
|
p = &f;
|
|
break;
|
|
case VT_DOUBLE:
|
|
i32 = sscanf(p, "%le", &d);
|
|
free(p);
|
|
if(i32 != 1)
|
|
{
|
|
error_set_code(1, "Invalid double value", type);
|
|
return NULL;
|
|
}
|
|
p = &d;
|
|
break;
|
|
case VT_STRING:
|
|
break;
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
/* FIXME need to be converted */
|
|
break;
|
|
case VT_BUFFER:
|
|
if((b = buffer_new(s - sizeof(u32), &data[sizeof(u32)]))
|
|
== NULL)
|
|
return NULL;
|
|
p = b;
|
|
break;
|
|
default:
|
|
error_set_code(1, "Unable to deserialize type %u",
|
|
type);
|
|
return NULL;
|
|
}
|
|
v = variable_new(type, p);
|
|
if(b != NULL)
|
|
buffer_delete(b);
|
|
return v;
|
|
}
|
|
|
|
|
|
/* variable_delete */
|
|
void variable_delete(Variable * variable)
|
|
{
|
|
_variable_destroy(variable);
|
|
object_delete(variable);
|
|
}
|
|
|
|
|
|
/* variable_get_as */
|
|
int variable_get_as(Variable * variable, VariableType type, void * result)
|
|
{
|
|
size_t size = 0;
|
|
void * p = NULL;
|
|
int8_t i8;
|
|
uint8_t u8;
|
|
int16_t i16;
|
|
uint16_t u16;
|
|
int32_t i32;
|
|
uint32_t u32;
|
|
Buffer ** b;
|
|
String ** s;
|
|
|
|
switch(type)
|
|
{
|
|
case VT_NULL:
|
|
if(variable->type == VT_NULL)
|
|
return 0;
|
|
break;
|
|
case VT_INT8:
|
|
size = sizeof(i8);
|
|
if(variable->type == VT_INT8)
|
|
{
|
|
p = &variable->u.int8;
|
|
break;
|
|
}
|
|
if(variable->type == VT_UINT8
|
|
&& variable->u.uint8 < (1 << 7))
|
|
i8 = variable->u.uint8;
|
|
else if(variable->type == VT_INT16
|
|
&& variable->u.int16 >= -128
|
|
&& variable->u.int16 < (1 << 7))
|
|
i8 = variable->u.int16;
|
|
else if(variable->type == VT_UINT16
|
|
&& variable->u.uint16 < (1 << 7))
|
|
i8 = variable->u.uint16;
|
|
else if(variable->type == VT_INT32
|
|
&& variable->u.int32 >= -128
|
|
&& variable->u.int32 < (1 << 7))
|
|
i8 = variable->u.int32;
|
|
else if(variable->type == VT_UINT32
|
|
&& variable->u.uint32 < (1 << 7))
|
|
i8 = variable->u.uint32;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
p = &i8;
|
|
break;
|
|
case VT_BOOL:
|
|
case VT_UINT8:
|
|
size = sizeof(u8);
|
|
if(variable->type == VT_UINT8)
|
|
{
|
|
p = &variable->u.uint8;
|
|
break;
|
|
}
|
|
if(variable->type == VT_INT8
|
|
&& variable->u.int8 >= 0)
|
|
u8 = variable->u.int8;
|
|
else if(variable->type == VT_INT16
|
|
&& variable->u.int16 >= 0
|
|
&& variable->u.int16 < (1 << 8))
|
|
u8 = variable->u.int16;
|
|
else if(variable->type == VT_UINT16
|
|
&& variable->u.uint16 < (1 << 8))
|
|
u8 = variable->u.uint16;
|
|
else if(variable->type == VT_INT32
|
|
&& variable->u.int32 >= 0
|
|
&& variable->u.int32 < (1 << 8))
|
|
u8 = variable->u.int32;
|
|
else if(variable->type == VT_UINT32
|
|
&& variable->u.uint32
|
|
< (1 << 8))
|
|
u8 = variable->u.uint32;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
p = &u8;
|
|
break;
|
|
case VT_INT16:
|
|
size = sizeof(i16);
|
|
if(variable->type == VT_INT16)
|
|
{
|
|
p = &variable->u.int16;
|
|
break;
|
|
}
|
|
if(variable->type == VT_UINT16
|
|
&& variable->u.uint16 < (1 << 15))
|
|
i16 = variable->u.uint16;
|
|
else if(variable->type == VT_INT8)
|
|
i16 = variable->u.int8;
|
|
else if(variable->type == VT_UINT8)
|
|
i16 = variable->u.uint8;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
p = &i16;
|
|
break;
|
|
case VT_UINT16:
|
|
size = sizeof(u16);
|
|
if(variable->type == VT_UINT16)
|
|
{
|
|
p = &variable->u.uint16;
|
|
break;
|
|
}
|
|
if(variable->type == VT_INT16 && variable->u.int16 >= 0)
|
|
u16 = variable->u.int16;
|
|
else if(variable->type == VT_INT8
|
|
&& variable->u.int8 >= 0)
|
|
u16 = variable->u.int8;
|
|
else if(variable->type == VT_UINT8)
|
|
u16 = variable->u.uint8;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
p = &u16;
|
|
break;
|
|
case VT_INT32:
|
|
size = sizeof(i32);
|
|
if(variable->type == VT_INT32)
|
|
{
|
|
p = &variable->u.int32;
|
|
break;
|
|
}
|
|
if(variable->type == VT_UINT32
|
|
&& variable->u.uint32
|
|
< (uint32_t)1 << 31)
|
|
i32 = variable->u.uint32;
|
|
else if(variable->type == VT_INT8)
|
|
i32 = variable->u.int8;
|
|
else if(variable->type == VT_UINT8)
|
|
i32 = variable->u.uint8;
|
|
else if(variable->type == VT_INT16)
|
|
i32 = variable->u.int16;
|
|
else if(variable->type == VT_UINT16)
|
|
i32 = variable->u.uint16;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
p = &i32;
|
|
break;
|
|
case VT_UINT32:
|
|
size = sizeof(u32);
|
|
if(variable->type == VT_UINT32)
|
|
{
|
|
p = &variable->u.uint32;
|
|
break;
|
|
}
|
|
if(variable->type == VT_INT32
|
|
&& variable->u.int32 >= 0)
|
|
u32 = variable->u.int32;
|
|
else if(variable->type == VT_INT8
|
|
&& variable->u.int8 >= 0)
|
|
u32 = variable->u.int8;
|
|
else if(variable->type == VT_UINT8)
|
|
u32 = variable->u.uint8;
|
|
else if(variable->type == VT_INT16
|
|
&& variable->u.int16 >= 0)
|
|
u32 = variable->u.int16;
|
|
else if(variable->type == VT_UINT16)
|
|
u32 = variable->u.uint16;
|
|
else
|
|
/* FIXME implement more conversions */
|
|
break;
|
|
size = sizeof(u32);
|
|
p = &u32;
|
|
break;
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
/* FIXME consider signedness */
|
|
if(variable->type == VT_INT64
|
|
|| variable->type == VT_UINT64)
|
|
{
|
|
size = sizeof(variable->u.uint64);
|
|
p = &variable->u.uint64;
|
|
break;
|
|
}
|
|
break;
|
|
case VT_FLOAT:
|
|
if(variable->type == VT_FLOAT)
|
|
{
|
|
size = sizeof(variable->u.f);
|
|
p = &variable->u.f;
|
|
break;
|
|
}
|
|
break;
|
|
case VT_DOUBLE:
|
|
if(variable->type == VT_DOUBLE)
|
|
{
|
|
size = sizeof(variable->u.d);
|
|
p = &variable->u.d;
|
|
break;
|
|
}
|
|
break;
|
|
case VT_BUFFER:
|
|
if(variable->type == VT_BUFFER)
|
|
{
|
|
b = result;
|
|
*b = buffer_new_copy(variable->u.buffer);
|
|
return 0;
|
|
}
|
|
break;
|
|
case VT_STRING:
|
|
if(variable->type == VT_STRING)
|
|
{
|
|
s = result;
|
|
*s = string_new(variable->u.string);
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
if(size != 0 && p != NULL)
|
|
{
|
|
memcpy(result, p, size);
|
|
return 0;
|
|
}
|
|
return -error_set_code(1, "Unable to convert from type %u to %u",
|
|
variable->type, type);
|
|
}
|
|
|
|
|
|
/* variable_get_type */
|
|
VariableType variable_get_type(Variable * variable)
|
|
{
|
|
return variable->type;
|
|
}
|
|
|
|
|
|
/* variable_set */
|
|
int variable_set(Variable * variable, Variable * from)
|
|
{
|
|
Buffer * b;
|
|
String * s;
|
|
|
|
switch(from->type)
|
|
{
|
|
case VT_NULL:
|
|
case VT_BOOL:
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
case VT_INT16:
|
|
case VT_UINT16:
|
|
case VT_INT32:
|
|
case VT_UINT32:
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
case VT_FLOAT:
|
|
case VT_DOUBLE:
|
|
_variable_destroy(variable);
|
|
memcpy(&variable->u, &from->u, sizeof(from->u));
|
|
break;
|
|
case VT_BUFFER:
|
|
if((b = buffer_new_copy(from->u.buffer)) == NULL)
|
|
return -1;
|
|
_variable_destroy(variable);
|
|
variable->u.buffer = b;
|
|
break;
|
|
case VT_STRING:
|
|
if((s = string_new(from->u.string)) == NULL)
|
|
return -1;
|
|
_variable_destroy(variable);
|
|
variable->u.string = s;
|
|
break;
|
|
default:
|
|
/* FIXME implement */
|
|
return -error_set_code(-ENOSYS, "%s", strerror(ENOSYS));
|
|
}
|
|
variable->type = from->type;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* variable_set_from */
|
|
int variable_set_from(Variable * variable, VariableType type, void * value)
|
|
{
|
|
int8_t * i8;
|
|
uint8_t * u8;
|
|
int16_t * i16;
|
|
uint16_t * u16;
|
|
int32_t * i32;
|
|
uint32_t * u32;
|
|
int64_t * i64;
|
|
uint64_t * u64;
|
|
float * f;
|
|
double * d;
|
|
Buffer * b;
|
|
char const * s;
|
|
|
|
/* XXX keep the previous contents in case of error? */
|
|
_variable_destroy(variable);
|
|
memset(&variable->u, 0, sizeof(variable->u));
|
|
if(value == NULL)
|
|
type = VT_NULL;
|
|
switch((variable->type = type))
|
|
{
|
|
case VT_NULL:
|
|
break;
|
|
case VT_BOOL:
|
|
u8 = value;
|
|
variable->u.uint8 = (*u8 != 0) ? 1 : 0;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__,
|
|
variable->u.uint8);
|
|
#endif
|
|
break;
|
|
case VT_INT8:
|
|
i8 = value;
|
|
variable->u.int8 = *i8;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%d)\n", __func__,
|
|
variable->u.int8);
|
|
#endif
|
|
break;
|
|
case VT_UINT8:
|
|
u8 = value;
|
|
variable->u.uint8 = *u8;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__,
|
|
variable->u.uint8);
|
|
#endif
|
|
break;
|
|
case VT_INT16:
|
|
i16 = value;
|
|
variable->u.int16 = *i16;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, *i16);
|
|
#endif
|
|
break;
|
|
case VT_UINT16:
|
|
u16 = value;
|
|
variable->u.uint16 = *u16;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, *u16);
|
|
#endif
|
|
break;
|
|
case VT_INT32:
|
|
i32 = value;
|
|
variable->u.int32 = *i32;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, *i32);
|
|
#endif
|
|
break;
|
|
case VT_UINT32:
|
|
u32 = value;
|
|
variable->u.uint32 = *u32;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, *u32);
|
|
#endif
|
|
break;
|
|
case VT_INT64:
|
|
i64 = value;
|
|
variable->u.int64 = *i64;
|
|
break;
|
|
case VT_UINT64:
|
|
u64 = value;
|
|
variable->u.uint64 = *u64;
|
|
break;
|
|
case VT_FLOAT:
|
|
f = value;
|
|
variable->u.f = *f;
|
|
break;
|
|
case VT_DOUBLE:
|
|
d = value;
|
|
variable->u.d = *d;
|
|
break;
|
|
case VT_BUFFER:
|
|
if((b = buffer_new_copy(value)) == NULL)
|
|
return -1;
|
|
variable->u.buffer = b;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%p)\n", __func__, (void *)b);
|
|
#endif
|
|
break;
|
|
case VT_STRING:
|
|
s = value;
|
|
if((variable->u.string = string_new(s)) == NULL)
|
|
return -1;
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, s);
|
|
#endif
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* useful */
|
|
/* variable_serialize */
|
|
int variable_serialize(Variable * variable, Buffer * buffer, int type)
|
|
{
|
|
size_t size = 0;
|
|
size_t offset;
|
|
void * p;
|
|
uint8_t u8;
|
|
int16_t i16;
|
|
uint16_t u16;
|
|
int32_t i32;
|
|
uint32_t u32;
|
|
char buf[16];
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, variable->type);
|
|
#endif
|
|
switch(variable->type)
|
|
{
|
|
case VT_NULL:
|
|
p = NULL;
|
|
break;
|
|
case VT_BOOL:
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
size = sizeof(variable->u.int8);
|
|
p = &variable->u.int8;
|
|
break;
|
|
case VT_INT16:
|
|
size = sizeof(i16);
|
|
i16 = htons(variable->u.int16);
|
|
p = &i16;
|
|
break;
|
|
case VT_UINT16:
|
|
size = sizeof(u16);
|
|
u16 = htons(variable->u.uint16);
|
|
p = &u16;
|
|
break;
|
|
case VT_INT32:
|
|
size = sizeof(i32);
|
|
i32 = htonl(variable->u.int32);
|
|
p = &i32;
|
|
break;
|
|
case VT_UINT32:
|
|
size = sizeof(u32);
|
|
u32 = htonl(variable->u.uint32);
|
|
p = &u32;
|
|
break;
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
/* FIXME convert to network endian */
|
|
size = sizeof(variable->u.int64);
|
|
p = &variable->u.int64;
|
|
break;
|
|
case VT_FLOAT:
|
|
size = snprintf(buf, sizeof(buf), "%.e", variable->u.f);
|
|
p = buf;
|
|
break;
|
|
case VT_DOUBLE:
|
|
size = snprintf(buf, sizeof(buf), "%.e", variable->u.d);
|
|
p = buf;
|
|
break;
|
|
case VT_BUFFER:
|
|
size = buffer_get_size(variable->u.buffer);
|
|
u32 = buffer_get_size(variable->u.buffer);
|
|
u32 = htonl(u32);
|
|
p = buffer_get_data(variable->u.buffer);
|
|
break;
|
|
case VT_STRING:
|
|
size = string_get_length(variable->u.string) + 1;
|
|
p = variable->u.string;
|
|
break;
|
|
}
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "DEBUG: %s() %lu\n", __func__, size);
|
|
#endif
|
|
if(size == 0 && variable->type != VT_NULL)
|
|
return -error_set_code(1, "Unable to serialize type %u", type);
|
|
if(type)
|
|
{
|
|
/* prefix with the type */
|
|
u8 = variable->type;
|
|
if(buffer_set(buffer, sizeof(u8), (char *)&u8) != 0)
|
|
return -1;
|
|
offset = sizeof(u8);
|
|
if(variable->type == VT_BUFFER)
|
|
{
|
|
if(buffer_set_data(buffer, offset, (char *)&u32,
|
|
sizeof(u32)) != 0)
|
|
return -1;
|
|
offset += sizeof(u32);
|
|
}
|
|
return buffer_set_data(buffer, offset, p, size);
|
|
}
|
|
if(variable->type == VT_BUFFER)
|
|
{
|
|
if(buffer_set(buffer, sizeof(u32), (char *)&u32) != 0)
|
|
return -1;
|
|
return buffer_set_data(buffer, sizeof(u32), p, size);
|
|
}
|
|
return buffer_set(buffer, size, p);
|
|
}
|
|
|
|
|
|
/* private */
|
|
/* variable_destroy */
|
|
static void _variable_destroy(Variable * variable)
|
|
{
|
|
switch(variable->type)
|
|
{
|
|
case VT_NULL:
|
|
case VT_BOOL:
|
|
case VT_INT8:
|
|
case VT_UINT8:
|
|
case VT_INT16:
|
|
case VT_UINT16:
|
|
case VT_INT32:
|
|
case VT_UINT32:
|
|
case VT_INT64:
|
|
case VT_UINT64:
|
|
case VT_FLOAT:
|
|
case VT_DOUBLE:
|
|
break;
|
|
case VT_BUFFER:
|
|
buffer_delete(variable->u.buffer);
|
|
break;
|
|
case VT_STRING:
|
|
string_delete(variable->u.string);
|
|
break;
|
|
}
|
|
}
|