blob: 90b04d58fc8e5751206337e51928ee5aa5c8c3e3 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2004-2006 Intel Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corp. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* @author Eugene Yarmosh
* @author Vadim Revyakin
*/
#ifdef HAVE_CONFIG_H
#include <wsman_config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#if defined (__SVR4) && defined (__sun)
#include <strings.h>
#endif
#include <u/libu.h>
#include <math.h>
#include "wsman-xml-api.h"
#include "wsman-soap.h"
#include "wsman-xml.h"
#include "wsman-dispatcher.h"
#include "wsman-xml-serializer.h"
#include "wsman-xml-serialize.h"
#include "wsman-soap-envelope.h"
struct __WsSerializerMemEntry {
char buf[0];
};
typedef struct __WsSerializerMemEntry WsSerializerMemEntry;
struct __WsSerializerContext
{
pthread_mutex_t lock;
list_t *WsSerializerAllocList;
};
WsSerializerContextH ws_serializer_init()
{
WsSerializerContextH serializercntx = NULL;
serializercntx = u_malloc(sizeof(struct __WsSerializerContext));
if(serializercntx == NULL) return NULL;
serializercntx->WsSerializerAllocList = list_create(LISTCOUNT_T_MAX);
if(serializercntx->WsSerializerAllocList == NULL) {
u_free(serializercntx);
return NULL;
}
u_init_lock(serializercntx);
return serializercntx;
}
int ws_serializer_cleanup(WsSerializerContextH serctx)
{
if(serctx && serctx->WsSerializerAllocList) {
ws_serializer_free_all(serctx);
u_destroy_lock(serctx);
list_destroy(serctx->WsSerializerAllocList);
u_free(serctx);
}
return 0;
}
void *xml_serializer_alloc(XmlSerializationData * data, int size,
int zeroInit)
{
void *ptr = ws_serializer_alloc(data->serctx, size);
TRACE_ENTER;
if (ptr && zeroInit)
memset(ptr, 0, size);
TRACE_EXIT;
return ptr;
}
int xml_serializer_free(XmlSerializationData * data, void *buf)
{
return ws_serializer_free(data->serctx, buf);
}
WsXmlNodeH
xml_serializer_add_child(XmlSerializationData * data, char *value)
{
const char *name = data->elementInfo->name;
const char *ns = data->elementInfo->ns;
WsXmlNodeH node;
TRACE_ENTER;
debug("name = %s; value(%p) = %s", name ? name : "NULL", value, value ? value : "NULL");
node = ws_xml_add_child(data->xmlNode, ns, name, value);
TRACE_EXIT;
return node;
}
WsXmlNodeH xml_serializer_get_child(XmlSerializationData * data)
{
WsXmlNodeH node;
const char *name = data->elementInfo->name;
const char *ns = data->elementInfo->ns;
TRACE_ENTER;
debug("name = %s:%s in %s [%d]", ns, name,
ws_xml_get_node_local_name(data->xmlNode), data->index);
node = ws_xml_get_child(data->xmlNode, data->index, ns, name);
#if 0
if (g_NameNameAliaseTable) {
int index = 0;
while (node == NULL &&
g_NameNameAliaseTable[index].name != NULL) {
if (!strcmp(g_NameNameAliaseTable[index].name, name))
node = ws_xml_get_child(data->xmlNode,
data->index, ns,
g_NameNameAliaseTable
[index].aliase);
index++;
}
}
#endif
debug("returned %p; %s",
node, node ? ws_xml_get_node_local_name(node) : "");
TRACE_EXIT;
return node;
}
static int get_struct_align(void)
{
typedef struct {
XML_TYPE_UINT8 a;
struct {
char x;
void *y;
} b;
} dummy;
return (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
static int
handle_attrs(struct __XmlSerializationData *data,
WsXmlNodeH node, size_t sz)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_NODE_ATTR *b;
} dummy;
int ret = 0;
char *savedBufPtr = DATA_BUF(data);
size_t al;
size_t pad;
int i;
XML_NODE_ATTR **attrsp;
XML_NODE_ATTR *attr;
WsXmlAttrH xmlattr;
char *src, *dstPtr;
int dstSize;
TRACE_ENTER;
debug("node name = %s", ws_xml_get_node_local_name(node));
if (!XML_IS_ATTRS(data->elementInfo)) {
debug("No attrs");
goto DONE;
}
DATA_BUF(data) = DATA_BUF(data) + sz;
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
debug("initial DATABUF = %p", DATA_BUF(data));
DATA_BUF(data) = DATA_BUF(data) + pad;
debug("alligned databuf = %p; pad = 0x%x", DATA_BUF(data), pad);
if (data->mode == XML_SMODE_FREE_MEM) {
// XXXXX free memory
goto DONE;
}
if (data->mode == XML_SMODE_SERIALIZE) {
XML_NODE_ATTR *attrs =
*((XML_NODE_ATTR **) DATA_BUF(data));
debug("attrs = %p", attrs);
while (attrs) {
debug("add attr. %s:%s = %s",
attrs->ns, attrs->name, attrs->value);
if (ws_xml_add_node_attr(node,
attrs->ns, attrs->name,
attrs->value) == NULL) {
error("could not add attr. %s:%s = %s",
attrs->ns, attrs->name,
attrs->value);
ret = 1;
goto DONE;
}
attrs = attrs->next;
}
goto DONE;
}
// XML_SMODE_DESERIALIZE
attrsp = (XML_NODE_ATTR **) DATA_BUF(data);
*attrsp = NULL;
for (i = 0; i < ws_xml_get_node_attr_count(node); i++) {
attr =
xml_serializer_alloc(data, sizeof(XML_NODE_ATTR), 1);
if (attr == NULL) {
error("no memory");
ret = 1;
goto DONE;
}
xmlattr = ws_xml_get_node_attr(node, i);
if (xmlattr == NULL) {
error("could not get attr %d", i);
ret = 1;
goto DONE;
}
src = ws_xml_get_attr_ns(xmlattr);
if (!(src == NULL || *src == 0)) {
dstSize = 1 + (int )strlen(src);
dstPtr =
(char *) xml_serializer_alloc(data, dstSize,
1);
if (dstPtr == NULL) {
error("no memory");
ret = 1;
goto DONE;
}
strncpy(dstPtr, src, dstSize);
attr->ns = dstPtr;
}
src = ws_xml_get_attr_name(xmlattr);
if (!(src == NULL || *src == 0)) {
dstSize = 1 + (int )strlen(src);
dstPtr =
(char *) xml_serializer_alloc(data, dstSize,
1);
if (dstPtr == NULL) {
error("no memory");
ret = 1;
goto DONE;
}
strncpy(dstPtr, src, dstSize);
attr->name = dstPtr;
}
src = ws_xml_get_attr_value(xmlattr);
if (!(src == NULL || *src == 0)) {
dstSize = 1 + (int )strlen(src);
dstPtr =
(char *) xml_serializer_alloc(data, dstSize,
1);
if (dstPtr == NULL) {
error("no memory");
ret = 1;
goto DONE;
}
strncpy(dstPtr, src, dstSize);
attr->value = dstPtr;
}
attr->next = *attrsp;
*attrsp = attr;
}
DONE:
DATA_BUF(data) = savedBufPtr;
TRACE_EXIT;
return ret;
}
static int do_serialize_int(XmlSerializationData * data, int valSize)
{
WsXmlNodeH child = NULL;
XML_TYPE_INT64 tmp;
int retVal = DATA_ALL_SIZE(data);
char *end;
char *str;
TRACE_ENTER;
debug("handle %d INT%d %s;", DATA_COUNT(data),
8 * valSize, data->elementInfo->name);
if (DATA_BUF(data) + retVal > data->stopper) {
error("size of %d structures %s exceeds stopper (%p > %p)",
DATA_COUNT(data), DATA_ELNAME(data),
DATA_BUF(data) + retVal, data->stopper);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) {
DATA_BUF(data) = DATA_BUF(data) + retVal;
goto DONE;
}
if ((data->mode != XML_SMODE_DESERIALIZE &&
data->mode != XML_SMODE_SERIALIZE)) {
error("invalid mode %d", data->mode);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
for (data->index = 0; data->index < DATA_COUNT(data);
data->index++) {
debug("%s[%d] = %p", data->elementInfo->name, data->index,
data->elementBuf);
if (data->mode == XML_SMODE_SERIALIZE) {
debug("value size: %d", valSize);
if (valSize == 1)
tmp =
*((XML_TYPE_INT8 *) data->elementBuf);
else if (valSize == 2)
tmp = *((XML_TYPE_INT16 *) data->
elementBuf);
else if (valSize == 4)
tmp = *((XML_TYPE_INT32 *) data->
elementBuf);
else if (valSize == 8)
tmp = *((XML_TYPE_INT64 *) data->
elementBuf);
else {
error("unsupported uint size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (((child = xml_serializer_add_child(data,
NULL)) == NULL)
|| (ws_xml_set_node_long(child, tmp)) != 0) {
debug("could not add child %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
}
if (data->mode == XML_SMODE_DESERIALIZE) {
if ((child = xml_serializer_get_child(data)) == NULL) {
error ("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if ((str = ws_xml_get_node_text(child)) == NULL) {
error("No text of node %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(str[0]))
str++;
errno = 0;
if (str[0] == 0) {
if (ws_xml_find_attr_bool(child,
XML_NS_SCHEMA_INSTANCE,
XML_SCHEMA_NIL)) {
goto ATTR;
}
error("absent value = %s", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
tmp = strtoll(str, &end, 10);
if (errno) {
error("strtoul(%s) failed; errno = %d",
str, errno);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(end[0]))
end++;
if (*end != 0) {
error("wrong token = %s.", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if (valSize == 1) {
if (tmp > 127 || tmp < -128) {
error("not int8 = %ld", tmp);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
*((XML_TYPE_INT8 *) data->elementBuf) =
(XML_TYPE_INT8) tmp;
} else if (valSize == 2) {
if (tmp > 32767 || tmp < -32768) {
error("not int16 = %ld", tmp);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
*((XML_TYPE_INT16 *) data->elementBuf) =
(XML_TYPE_INT16) tmp;
} else if (valSize == 4) {
*((XML_TYPE_INT32 *) data->elementBuf) =
(XML_TYPE_INT32) tmp;
} else if (valSize == 8) {
*((XML_TYPE_INT64 *) data->elementBuf) =
(XML_TYPE_INT64) tmp;
} else {
error("unsupported int size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
}
ATTR:
handle_attrs(data, child, valSize);
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
}
if ((data->mode == XML_SMODE_DESERIALIZE) &&
xml_serializer_get_child(data)) {
error("too many (%d > %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
DONE:
TRACE_EXIT;
return retVal;
}
static int do_serialize_uint(XmlSerializationData * data, int valSize)
{
WsXmlNodeH child = NULL;
XML_TYPE_UINT64 tmp;
int retVal = DATA_ALL_SIZE(data);
char *end;
char *str;
TRACE_ENTER;
debug("handle %d UINT%d %s;", DATA_COUNT(data),
8 * valSize, data->elementInfo->name);
if (DATA_BUF(data) + retVal > data->stopper) {
error("size of %d structures %s exceeds stopper (%p > %p)",
DATA_COUNT(data), DATA_ELNAME(data),
DATA_BUF(data) + retVal, data->stopper);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) {
DATA_BUF(data) = DATA_BUF(data) + retVal;
goto DONE;
}
if ((data->mode != XML_SMODE_DESERIALIZE &&
data->mode != XML_SMODE_SERIALIZE)) {
error("invalid mode %d", data->mode);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
for (data->index = 0; data->index < DATA_COUNT(data);
data->index++) {
debug("%s[%d] = %p", data->elementInfo->name, data->index,
data->elementBuf);
if (data->mode == XML_SMODE_SERIALIZE) {
debug("value size: %d", valSize);
if (valSize == 1)
tmp =
*((XML_TYPE_UINT8 *) data->elementBuf);
else if (valSize == 2)
tmp = *((XML_TYPE_UINT16 *) data->
elementBuf);
else if (valSize == 4)
tmp = *((XML_TYPE_UINT32 *) data->
elementBuf);
else if (valSize == 8)
tmp = *((XML_TYPE_UINT64 *) data->
elementBuf);
else {
error("unsupported uint size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (((child = xml_serializer_add_child(data,
NULL)) == NULL)
|| (ws_xml_set_node_ulong(child, tmp)) != 0) {
debug("could not add child %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
}
if (data->mode == XML_SMODE_DESERIALIZE) {
if ((child = xml_serializer_get_child(data)) == NULL) {
error ("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if ((str = ws_xml_get_node_text(child)) == NULL) {
error("No text of node %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(str[0]))
str++;
errno = 0;
if (str[0] == '-' || str[0] == 0) {
if (ws_xml_find_attr_bool(child,
XML_NS_SCHEMA_INSTANCE,
XML_SCHEMA_NIL)) {
goto ATTR;
}
error("absent value = %s", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
tmp = strtoull(str, &end, 10);
if (errno) {
error("strtoul(%s) failed; errno = %d",
str, errno);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(end[0]))
end++;
if (*end != 0) {
error("wrong token = %s.", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if (valSize == 1) {
if (tmp > 255) {
error("not uint8 = %ld", tmp);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
*((XML_TYPE_UINT8 *) data->elementBuf) =
(XML_TYPE_UINT8) tmp;
} else if (valSize == 2) {
if (tmp > 65535) {
error("not uint16 = %ld", tmp);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
*((XML_TYPE_UINT16 *) data->elementBuf) =
(XML_TYPE_UINT16) tmp;
} else if (valSize == 4) {
*((XML_TYPE_UINT32 *) data->elementBuf) =
(XML_TYPE_UINT32) tmp;
} else if (valSize == 8) {
*((XML_TYPE_UINT64 *) data->elementBuf) =
(XML_TYPE_UINT64) tmp;
} else {
error("unsupported uint size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
}
ATTR:
handle_attrs(data, child, valSize);
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
}
if ((data->mode == XML_SMODE_DESERIALIZE) &&
xml_serializer_get_child(data)) {
error("too many (%d > %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
DONE:
TRACE_EXIT;
return retVal;
}
int do_serialize_uint8(XmlSerializationData * data)
{
if (XML_IS_ATTRS(data->elementInfo)) {
size_t al = get_struct_align();
size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
}
return do_serialize_uint(data, sizeof(XML_TYPE_UINT8));
}
int do_serialize_uint16(XmlSerializationData * data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT16 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT16));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_uint32(XmlSerializationData * data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT32 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT32));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_uint64(XmlSerializationData * data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT64 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT64));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_int8(struct __XmlSerializationData* data)
{
if (XML_IS_ATTRS(data->elementInfo)) {
size_t al = get_struct_align();
size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
}
return do_serialize_int(data, sizeof(XML_TYPE_INT8));
}
int do_serialize_int16(struct __XmlSerializationData* data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT16 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_int(data, sizeof(XML_TYPE_INT16));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_int32(struct __XmlSerializationData* data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT32 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_int(data, sizeof(XML_TYPE_INT32));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_int64(struct __XmlSerializationData* data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_UINT64 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_int(data, sizeof(XML_TYPE_INT64));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
static int do_serialize_real(XmlSerializationData * data, int valSize)
{
WsXmlNodeH child = NULL;
XML_TYPE_REAL64 tmp;
int retVal = DATA_ALL_SIZE(data);
char *end;
char *str;
TRACE_ENTER;
debug("handle %d REAL%d %s;", DATA_COUNT(data),
8 * valSize, data->elementInfo->name);
if (DATA_BUF(data) + retVal > data->stopper) {
error("size of %d structures %s exceeds stopper (%p > %p)",
DATA_COUNT(data), DATA_ELNAME(data),
DATA_BUF(data) + retVal, data->stopper);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) {
DATA_BUF(data) = DATA_BUF(data) + retVal;
goto DONE;
}
if ((data->mode != XML_SMODE_DESERIALIZE &&
data->mode != XML_SMODE_SERIALIZE)) {
error("invalid mode %d", data->mode);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
for (data->index = 0; data->index < DATA_COUNT(data);
data->index++) {
debug("%s[%d] = %p", data->elementInfo->name, data->index,
data->elementBuf);
if (data->mode == XML_SMODE_SERIALIZE) {
debug("value size: %d", valSize);
if (valSize == 4)
tmp = *((XML_TYPE_REAL32 *) data->
elementBuf);
else if (valSize == 8)
tmp = *((XML_TYPE_REAL64 *) data->
elementBuf);
else {
error("unsupported real size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (((child = xml_serializer_add_child(data,
NULL)) == NULL)
|| (ws_xml_set_node_real(child, tmp)) != 0) {
debug("could not add child %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
}
if (data->mode == XML_SMODE_DESERIALIZE) {
if ((child = xml_serializer_get_child(data)) == NULL) {
error ("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if ((str = ws_xml_get_node_text(child)) == NULL) {
error("No text of node %s[%d]",
DATA_ELNAME(data), data->index);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(str[0]))
str++;
errno = 0;
if (str[0] == 0) {
if (ws_xml_find_attr_bool(child,
XML_NS_SCHEMA_INSTANCE,
XML_SCHEMA_NIL)) {
goto ATTR;
}
error("absent value = %s", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
tmp = strtod(str, &end);
if (errno) {
error("strtod(%s) failed; errno = %d",
str, errno);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
while (isspace(end[0]))
end++;
if (*end != 0) {
error("wrong token = %s.", str);
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if (valSize == 4) {
*((XML_TYPE_REAL32 *) data->elementBuf) =
(XML_TYPE_REAL32) tmp;
} else if (valSize == 8) {
*((XML_TYPE_REAL64 *) data->elementBuf) =
(XML_TYPE_REAL64) tmp;
} else {
error("unsupported REAL size + %d",
8 * valSize);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
}
ATTR:
handle_attrs(data, child, valSize);
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
}
if ((data->mode == XML_SMODE_DESERIALIZE) &&
xml_serializer_get_child(data)) {
error("too many (%d > %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
DONE:
TRACE_EXIT;
return retVal;
}
int do_serialize_real32(struct __XmlSerializationData* data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_REAL32 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_real(data, sizeof(XML_TYPE_REAL32));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_real64(struct __XmlSerializationData* data)
{
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_REAL64 b;
} dummy;
size_t al;
size_t pad;
int retVal;
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
retVal = do_serialize_real(data, sizeof(XML_TYPE_REAL64));
if (retVal >= 0) {
retVal += pad;
}
return retVal;
}
int do_serialize_string(XmlSerializationData * data)
{
WsXmlNodeH child = NULL;
int retVal = DATA_ALL_SIZE(data);
size_t al;
size_t pad;
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_STR b;
} dummy;
TRACE_ENTER;
debug("handle %d strings %s = %p", DATA_COUNT(data),
data->elementInfo->name, data->elementBuf);
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
retVal += pad;
if (DATA_BUF(data) + retVal > data->stopper) {
error("stopper: %p > %p",
DATA_BUF(data) + retVal, data->stopper);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data)) {
data->elementBuf = DATA_BUF(data) + retVal;
goto DONE;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
debug("adjusted elementBuf = %p", data->elementBuf);
for (data->index = 0; data->index < DATA_COUNT(data);
data->index++) {
if (data->mode == XML_SMODE_FREE_MEM) {
xml_serializer_free(data, *(XML_TYPE_STR *) DATA_BUF(data));
*(XML_TYPE_STR *) DATA_BUF(data) = NULL;
} else if (data->mode == XML_SMODE_SERIALIZE) {
char *valPtr = *((char **) DATA_BUF(data));
child = xml_serializer_add_child(data, valPtr);
if (child == NULL) {
error("xml_serializer_add_child failed.");
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
if (ws_xml_get_node_text(child) == NULL) {
ws_xml_add_node_attr(child,
XML_NS_SCHEMA_INSTANCE,
XML_SCHEMA_NIL,
"true");
}
} else if (data->mode == XML_SMODE_DESERIALIZE) {
char *src;
if ((child =
xml_serializer_get_child(data)) == NULL) {
error
("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
src = ws_xml_get_node_text(child);
if (src != NULL && *src != 0) {
char *dstPtr;
int dstSize = 1 + strlen(src);
dstPtr =
(char *) xml_serializer_alloc(data,
dstSize,
1);
if (dstPtr == NULL) {
error("no memory");
retVal =
WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
strncpy(dstPtr, src, dstSize);
*((XML_TYPE_PTR *) DATA_BUF(data)) =
dstPtr;
}
} else {
error("invalid mode");
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
handle_attrs(data, child, sizeof(XML_TYPE_STR));
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
}
if ((data->mode == XML_SMODE_DESERIALIZE) &&
xml_serializer_get_child(data)) {
error("too many (%d > %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
DONE:
TRACE_EXIT;
return retVal;
}
int do_serialize_bool(XmlSerializationData * data)
{
int retVal = DATA_ALL_SIZE(data);
typedef struct {
XML_TYPE_UINT8 a;
XML_TYPE_BOOL b;
} dummy;
size_t al;
size_t pad;
WsXmlNodeH child = NULL;
TRACE_ENTER;
debug("handle %d booleans %s; ptr = %p", DATA_COUNT(data),
DATA_ELNAME(data), DATA_BUF(data));
if (XML_IS_ATTRS(data->elementInfo)) {
al = get_struct_align();
} else {
al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
}
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
retVal += pad;
if (DATA_BUF(data) + retVal > data->stopper) {
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) {
data->elementBuf = DATA_BUF(data) + retVal;
goto DONE;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
debug("adjusted elementBuf = %p", data->elementBuf);
for (data->index = 0; data->index < DATA_COUNT(data);
data->index++) {
debug("%s[%d] = %p", DATA_ELNAME(data), data->index,
DATA_BUF(data));
if (data->mode == XML_SMODE_SERIALIZE) {
XML_TYPE_BOOL tmp;
tmp = *((XML_TYPE_BOOL *) DATA_BUF(data));
if ((child = xml_serializer_add_child(data,
(tmp == 0) ? "false" : "true")) == NULL) {
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
} else if (data->mode == XML_SMODE_DESERIALIZE) {
XML_TYPE_PTR dataPtr =
(XML_TYPE_PTR) DATA_BUF(data);
XML_TYPE_BOOL tmp = -1;
char *src;
if ((child =
xml_serializer_get_child(data)) == NULL) {
error("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
src = ws_xml_get_node_text(child);
if (src == NULL || *src == 0) {
tmp = 1;
} else {
if (isdigit(*src)) {
tmp = atoi(src);
} else {
if (strcmp(src, "yes") == 0 ||
strcmp(src, "true") == 0) {
tmp = 1;
} else if (strcmp(src, "no") == 0 ||
strcmp(src, "false") == 0) {
tmp = 0;
}
}
}
if (tmp == 0 || tmp == 1) {
*((XML_TYPE_BOOL *) dataPtr) = tmp;
} else {
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
} else {
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
handle_attrs(data, child, sizeof(XML_TYPE_BOOL));
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
}
if ((data->mode == XML_SMODE_DESERIALIZE) &&
xml_serializer_get_child(data)) {
error("too many (%d > %d) instances of element %s",
data->index, DATA_COUNT(data), DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
DONE:
TRACE_EXIT;
return retVal;
}
static XmlSerialiseDynamicSizeData *make_dyn_size_data(XmlSerializationData
* data,
int * retValp)
{
XmlSerialiseDynamicSizeData *dyn =
(XmlSerialiseDynamicSizeData *) data->elementBuf;
int savedIndex = data->index;
int size;
TRACE_ENTER;
data->index = 0;
while (xml_serializer_get_child(data) != NULL) {
data->index++;
}
dyn->count = data->index;
data->index = savedIndex;
if (dyn->count < DATA_MIN_COUNT(data)) {
error("not enough (%d < %d) elements %s", dyn->count,
DATA_MIN_COUNT(data), DATA_ELNAME(data));
*retValp = WS_ERR_XML_PARSING;
dyn = NULL;
goto DONE;
}
if ((DATA_MAX_COUNT(data) > 0)
&& dyn->count > DATA_MAX_COUNT(data)) {
error("too many (%d > %d) elements %s", dyn->count,
DATA_MAX_COUNT(data), DATA_ELNAME(data));
*retValp = WS_ERR_XML_PARSING;
dyn = NULL;
goto DONE;
}
debug("count = %d of %d sizes", dyn->count, DATA_SIZE(data));
if (dyn->count == 0) {
goto DONE;
}
size = DATA_SIZE(data) * dyn->count;
dyn->data = xml_serializer_alloc(data, size, 1);
if (dyn->data == NULL) {
error("no memory");
*retValp = WS_ERR_INSUFFICIENT_RESOURCES;
dyn = NULL;
}
DONE:
TRACE_EXIT;
return dyn;
}
int do_serialize_dyn_size_array(XmlSerializationData * data)
{
typedef struct {
char a;
XmlSerialiseDynamicSizeData b;
} dummy;
size_t al = (char *) &(((dummy *) NULL)->b) - (char *) NULL;
size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
int retVal;
char *savedBufPtr;
XmlSerializerInfo *savedElementInfo;
XmlSerialiseDynamicSizeData *dyn = NULL;
int tmp;
XmlSerializerInfo myinfo;
int savedIndex;
char *savedStopper;
TRACE_ENTER;
debug("Dyn size array %s; ptr = %p", data->elementInfo->name,
data->elementBuf);
if (pad)
pad = al - pad;
retVal = DATA_SIZE(data) + pad;
if (DATA_BUF(data) + retVal > data->stopper) {
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data)) {
DATA_BUF(data) = DATA_BUF(data) + retVal;
goto DONE;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
debug("adjusted elementBuf = %p", data->elementBuf);
savedBufPtr = DATA_BUF(data);
savedElementInfo = data->elementInfo;
if (data->mode != XML_SMODE_SERIALIZE &&
data->mode != XML_SMODE_DESERIALIZE &&
data->mode != XML_SMODE_FREE_MEM) {
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (data->mode == XML_SMODE_DESERIALIZE) {
if ((dyn = make_dyn_size_data(data, &retVal)) == NULL) {
goto DONE;
}
} else {
dyn = (XmlSerialiseDynamicSizeData *) data->elementBuf;
if (data->mode == XML_SMODE_SERIALIZE) {
if (dyn->count < DATA_MIN_COUNT(data)) {
error("not enough (%d < %d) elements %s",
dyn->count, DATA_MIN_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
if ((DATA_MAX_COUNT(data) > 0)
&& dyn->count > DATA_MAX_COUNT(data)) {
error("too many (%d > %d) elements %s",
dyn->count, DATA_MAX_COUNT(data),
DATA_ELNAME(data));
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
}
}
if (dyn->count == 0) {
// no dynamic data. nothing to do
goto DONE;
}
savedIndex = data->index;
savedStopper = data->stopper;
memcpy(&myinfo, savedElementInfo->extData,
sizeof(XmlSerializerInfo));
myinfo.count = dyn->count;
myinfo.name = data->elementInfo->name;
myinfo.ns = data->elementInfo->ns;
data->stopper = (char *) dyn->data + DATA_SIZE(data) * dyn->count;
data->elementInfo = &myinfo;
DATA_BUF(data) = dyn->data;
data->index = 0;
debug("dyn = %p, dyn->data = %p + 0x%x",
dyn, dyn->data, DATA_SIZE(data) * dyn->count);
tmp = data->elementInfo->proc(data);
data->index = savedIndex;
DATA_BUF(data) = savedBufPtr;
data->elementInfo = savedElementInfo;
data->stopper = savedStopper;
if (tmp < 0 && data->mode != XML_SMODE_FREE_MEM) {
retVal = tmp;
goto DONE;
}
if ((data->mode == XML_SMODE_FREE_MEM) && dyn->data) {
xml_serializer_free(data, dyn->data);
goto DONE;
}
DONE:
DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data);
TRACE_EXIT;
return retVal;
}
int do_serialize_struct(XmlSerializationData * data)
{
int retVal = 0;
int i;
int elementCount = 0;
XmlSerializerInfo *elements =
(XmlSerializerInfo *) data->elementInfo->extData;
WsXmlNodeH savedXmlNode = data->xmlNode;
XmlSerializerInfo *savedElement = data->elementInfo;
int savedMode = data->mode;
int savedIndex = data->index;
void *savedStopper = data->stopper;
size_t al = get_struct_align();
size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
size_t count;
size_t struct_size;
int savedLocalIndex;
char *savedLocalElementBuf;
WsXmlNodeH child;
TRACE_ENTER;
debug("handle %d structure \"%s\" ptr = %p", DATA_COUNT(data),
data->elementInfo->name ? data->elementInfo->name : "NULL",
data->elementBuf);
if (data->mode != XML_SMODE_SERIALIZE &&
data->mode != XML_SMODE_DESERIALIZE &&
data->mode != XML_SMODE_FREE_MEM) {
retVal = WS_ERR_INVALID_PARAMETER;
debug("Incorrect data->mode = %d", data->mode);
goto DONE;
}
al = get_struct_align();
pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al);
if (pad) {
pad = al - pad;
}
retVal = pad + XML_IS_HEAD(savedElement) ?
DATA_SIZE(data) : DATA_ALL_SIZE(data);
if ((char *) DATA_BUF(data) + retVal > data->stopper) {
error("size of %d structures \"%s\" exceeds stopper (%p > %p)",
DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL",
(char *) DATA_BUF(data) + retVal, data->stopper);
retVal = WS_ERR_INVALID_PARAMETER;
goto DONE;
}
if (DATA_MUST_BE_SKIPPED(data)) {
debug(" %d elements %s skipped", DATA_COUNT(data),
DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL");
DATA_BUF(data) = DATA_BUF(data) + retVal;
goto DONE;
}
DATA_BUF(data) = DATA_BUF(data) + pad;
debug("adjusted ptr= %p", data->elementBuf);
while (elements[elementCount].proc != NULL) {
elementCount++;
}
count = DATA_COUNT(data);
struct_size = DATA_SIZE(data);
if (XML_IS_HEAD(savedElement)) {
count = data->index + 1;
} else {
data->index = 0;
}
for (; data->index < count; data->index++) {
int tmp;
child = NULL;
savedLocalIndex = data->index;
savedLocalElementBuf = DATA_BUF(data);
data->stopper = savedLocalElementBuf + DATA_SIZE(data);
debug("%s[%d] = %p", DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL",
data->index,
DATA_BUF(data));
if (data->mode == XML_SMODE_SERIALIZE) {
child = xml_serializer_add_child(data, NULL);
data->xmlNode = child;
if (data->xmlNode == NULL) {
error("cant add child");
retVal = WS_ERR_INSUFFICIENT_RESOURCES;
goto DONE;
}
} else if (data->mode == XML_SMODE_DESERIALIZE) {
child = xml_serializer_get_child(data);
if (child == NULL) {
error
("not enough (%d < %d) instances of element %s",
data->index, DATA_COUNT(data),
DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL");
retVal = WS_ERR_XML_PARSING;
goto DONE;
}
data->xmlNode = child;
}
debug("before for loop. Struct %s = %p",
savedElement->name ? savedElement->name : "NULL", DATA_BUF(data));
for (i = 0; retVal > 0 && i < elementCount; i++) {
data->elementInfo = &elements[i];
debug
("handle %d elements %s of struct %s. dstPtr = %p",
DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL",
savedElement->name ? savedElement->name : "NULL", DATA_BUF(data));
if (XML_IS_SKIP(data->elementInfo)) {
data->mode = XML_SMODE_SKIP;
}
tmp = data->elementInfo->proc(data);
debug("retval: %d", tmp);
if (tmp < 0) {
error("handling of element \"%s\" failed = %d",
DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL", tmp);
retVal = tmp;
goto DONE;
}
}
data->elementInfo = savedElement;
data->index = savedLocalIndex;
data->mode = savedMode;
data->xmlNode = savedXmlNode;
data->elementInfo = savedElement;
handle_attrs(data, child, 0);
data->elementBuf = savedLocalElementBuf + struct_size;
}
DONE:
data->stopper = savedStopper;
data->elementInfo = savedElement;
data->index = savedIndex;
data->mode = savedMode;
data->xmlNode = savedXmlNode;
TRACE_EXIT;
return retVal;
}
static void
initialize_xml_serialization_data(XmlSerializationData * data,
WsSerializerContextH serctx,
XmlSerializerInfo * elementInfo,
XML_TYPE_PTR dataBuf,
int mode,
XML_NODE_ATTR * attrs,
WsXmlNodeH xmlNode)
{
debug("Initialize XML Serialization...");
TRACE_ENTER;
memset(data, 0, sizeof(XmlSerializationData));
data->serctx = serctx;
data->elementInfo = elementInfo;
data->elementBuf = dataBuf;
data->mode = mode;
data->attrs = attrs;
data->xmlNode = xmlNode;
debug("Finished initializing XML Serialization...");
TRACE_EXIT;
return;
}
int ws_serialize(WsSerializerContextH serctx,
WsXmlNodeH xmlNode,
XML_TYPE_PTR dataPtr,
XmlSerializerInfo * info,
const char *name,
const char *ns, XML_NODE_ATTR * attrs, int output)
{
int retVal = WS_ERR_INSUFFICIENT_RESOURCES;
XmlSerializerInfo myinfo;
XmlSerializationData data;
TRACE_ENTER;
if (info->proc == NULL) {
error("info->proc == NULL");
goto DONE;
}
memcpy(&myinfo, info, sizeof(XmlSerializerInfo));
if (name == NULL) {
error("name == NULL");
goto DONE;
}
myinfo.name = name;
myinfo.ns = ns;
myinfo.flags |= SER_HEAD;
initialize_xml_serialization_data(&data,
serctx,
&myinfo,
dataPtr,
XML_SMODE_SERIALIZE,
attrs, xmlNode);
data.stopper = (char *) dataPtr + myinfo.size;
if (output) {
data.skipFlag = SER_IN;
} else {
data.skipFlag = SER_OUT;
}
retVal = myinfo.proc(&data);
DONE:
TRACE_EXIT;
return retVal;
}
int ws_serializer_free_mem(WsSerializerContextH serctx, XML_TYPE_PTR buf,
XmlSerializerInfo * info)
{
int retVal;
XmlSerializationData data;
XmlSerializerInfo myinfo;
TRACE_ENTER;
memcpy(&myinfo, info, sizeof(XmlSerializerInfo));
myinfo.flags |= SER_HEAD;
initialize_xml_serialization_data(&data,
serctx,
&myinfo,
buf,
XML_SMODE_FREE_MEM, NULL, NULL);
data.stopper = (char *) buf + myinfo.size;
if ((retVal = info->proc(&data)) >= 0) {
xml_serializer_free(&data, buf);
}
TRACE_EXIT;
return retVal;
}
void *ws_deserialize(WsSerializerContextH serctx,
WsXmlNodeH xmlParent,
XmlSerializerInfo * info,
const char *name,
const char *ns,
XML_NODE_ATTR ** attrs, int index, int output)
{
int size;
void *retPtr = NULL;
XmlSerializationData data;
XmlSerializerInfo myinfo;
TRACE_ENTER;
memcpy(&myinfo, info, sizeof(XmlSerializerInfo));
if (name == NULL) {
error("name == NULL");
}
myinfo.name = name;
myinfo.ns = ns;
myinfo.flags |= SER_HEAD;
initialize_xml_serialization_data(&data, serctx, &myinfo, NULL,
XML_SMODE_DESERIALIZE,
NULL, xmlParent);
data.index = index;
if (output) {
data.skipFlag = SER_IN;
} else {
data.skipFlag = SER_OUT;
}
size = myinfo.size;
if ((data.elementBuf = xml_serializer_alloc(&data, size, 1)) != NULL) {
retPtr = data.elementBuf;
data.stopper = (char *) retPtr + size;
if (myinfo.proc && myinfo.proc(&data) <= 0) {
data.elementBuf = retPtr;
retPtr = NULL;
ws_serializer_free_mem(serctx, data.elementBuf,
&myinfo);
error("Error during serialization");
}
}
TRACE_EXIT;
return retPtr;
}
static void enforce_mustunderstand(WsXmlNodeH node)
{
WsXmlDocH doc = ws_xml_get_node_doc(node);
char *ns = ws_xml_get_node_name_ns(ws_xml_get_doc_root(doc));
ws_xml_add_node_attr(node, ns, SOAP_MUST_UNDERSTAND, "true");
}
int
ws_serialize_str(WsSerializerContextH serctx, WsXmlNodeH parent, const char *str,
const char *nameNs, const char *name, int mustunderstand)
{
WsXmlNodeH node;
TRACE_ENTER;
//printf("mustunderstand flag for %s: %d\n", name, mustunderstand );
node = ws_xml_add_child(parent, nameNs, name, str);
if (node && mustunderstand) {
enforce_mustunderstand(node);
}
TRACE_EXIT;
return (node == NULL);
}
int ws_serialize_uint32(WsSerializerContextH serctx, WsXmlNodeH parent,
unsigned long val, const char *nameNs,
const char *name, int mustunderstand)
{
WsXmlNodeH node = ws_xml_add_child(parent, nameNs, name, NULL);
TRACE_ENTER;
if (node) {
ws_xml_set_node_ulong(node, val);
if (mustunderstand) {
enforce_mustunderstand(node);
}
}
TRACE_EXIT;
return (node == NULL);
}
char *ws_deserialize_str(WsSerializerContextH serctx, WsXmlNodeH parent, int index,
const char *nameNs, const char *name)
{
char *str = NULL;
WsXmlNodeH node = ws_xml_get_child(parent, index, nameNs, name);
TRACE_ENTER;
if (node) {
str = ws_xml_get_node_text(node);
if (serctx && str) {
int len = (int )strlen(str) + 1;
char *tmp = str;
if ((str = ws_serializer_alloc(serctx,
len * sizeof(char))))
strcpy(str, tmp);
}
}
TRACE_EXIT;
return str;
}
unsigned long ws_deserialize_uint32(WsSerializerContextH serctx,
WsXmlNodeH parent, int index,
const char *nameNs, const char *name)
{
unsigned long val = 0;
WsXmlNodeH node = ws_xml_get_child(parent, index, nameNs, name);
TRACE_ENTER;
if (node) {
val = ws_xml_get_node_ulong(node);
}
TRACE_EXIT;
return val;
}
/*
* Returns duration in seconds in <value> argument
*
* the format of OperationTimeout is defined by the
* XML Schema Datatypes Section 3.2.6.1 http://www.w3.org/TR/xmlschema-2/
*
* Sample: P0Y0M0DT0H0M60.00S
*
* (must start with 'P', 'T' separated date from time, seconds may have fraction)
*
* FIXME: handle fractions of seconds (don't return a time_t but a struct timeval)
*
*/
int ws_deserialize_duration(const char *t, time_t * value)
{
long years = 0;
long months = 0;
long days = 0;
long hours = 0;
long mins = 0;
long secs = 0;
time_t vs;
int v;
double f; /* float for fractional second */
char *e; /* end pointer for strtol */
int got = 64; /* bitmask of parsing position, 64==year */
int res = 1; /* final result, 1 == error */
int time_handeled = 0; /* seen 'T' */
int negative = 0;
TRACE_ENTER;
if (t == NULL) {
debug("node text == NULL");
goto DONE;
}
if (*t == '-') {
negative = 1;
t++;
}
if (*t != 'P') {
debug("Wrong begining of duration");
goto DONE;
}
while (*++t) {
if (*t == 'T') {
time_handeled = 1;
continue;
}
v = strtol(t, &e, 10);
if (t == e) {
debug("wrong format, missing numeric value");
goto DONE;
}
if (time_handeled && (*e == '.')) {
f = strtod(t, &e);
if (*e != 'S') {
debug("float but not secs");
goto DONE;
}
if (((int)floor(f+0.5)) > v) {
v++; /* round value up */
}
}
switch (*e) {
case 'Y':
if (got <= 32 || time_handeled) {
debug("wrong order Y");
goto DONE;
}
years = v;
got = 32;
break;
case 'M':
if (!time_handeled) { // months
if (got <= 16) {
debug("wrong order M");
goto DONE;
}
months = v;
got = 16;
break;
}
// minutes
if (got <= 2 || !time_handeled) {
debug("wrong order M");
goto DONE;
}
mins = v;
got = 2;
break;
case 'D':
if (got <= 8 || time_handeled) {
debug("wrong order D");
goto DONE;
}
days = v;
got = 8;
break;
case 'H':
if (got <= 4 || !time_handeled) {
debug("wrong order H");
goto DONE;
}
hours = v;
got = 4;
break;
case 'S':
if (got <= 1 || !time_handeled) {
debug("wrong order S");
goto DONE;
}
secs = v;
got = 1;
break;
default:
debug("wrong format %c", *e);
goto DONE;
}
t = e;
}
// invalid if T found and no HMS, or no time value detected
if ((time_handeled && (got > 4)) || (64 == got)){
debug("wrong format: floating T or no time value detected");
goto DONE;
}
// We don't know exact date and time of the sender.
// For simplicity comsider 1 month = 30days;
vs = secs + 60 * mins + 60 * 60 * hours + 60 * 60 * 24 * days +
60 * 60 * 24 * 30 * months + 60 * 60 * 24 * 30 * 12 * years;
if (negative) {
vs = 0 - vs;
}
*value = vs;
res = 0; // good at this point
DONE:
TRACE_EXIT;
return res;
}
int ws_deserialize_datetime(const char *text, XML_DATETIME * tmx)
{
int res = 0;
int r;
int hours;
int mins;
struct tm tm;
time_t t;
TRACE_ENTER;
if (text == NULL) {
debug("node text == NULL");
res = 1;
goto DONE;
}
bzero(tmx, sizeof(XML_DATETIME));
r = sscanf(text, "%u-%u-%uT%u:%u:%u%d:%u", &tmx->tm.tm_year,
&tmx->tm.tm_mon, &tmx->tm.tm_mday,
&tmx->tm.tm_hour, &tmx->tm.tm_min, &tmx->tm.tm_sec,
&hours, &mins);
if (r != 8) {
debug("wrong body of datetime(%d): %s", r, text);
res = 1;
goto DONE;
}
tmx->tm.tm_year -= 1900;
tmx->tm.tm_mon -= 1;
t = time(NULL);
#ifdef _WIN32
localtime_s(&tm, &t);
#else
localtime_r(&t, &tm);
#endif
tmx->tm.tm_isdst = tm.tm_isdst;
if (hours < 0) {
tmx->tz_min = 60 * hours - mins;
} else {
tmx->tz_min = 60 * hours + mins;
}
DONE:
return res;
}
void *ws_serializer_alloc(WsSerializerContextH serctx, int size)
{
WsSerializerMemEntry *ptr = NULL;
TRACE_ENTER;
if ((ptr = (WsSerializerMemEntry *) u_malloc(sizeof(WsSerializerMemEntry) + size)) != NULL) {
lnode_t *node;
u_lock(serctx);
if ((node = lnode_create(ptr)) == NULL) {
u_free(ptr);
ptr = NULL;
} else {
list_append(serctx->WsSerializerAllocList, node);
}
u_unlock(serctx);
}
TRACE_EXIT;
return ptr ? ptr->buf : NULL;
}
static int do_serializer_free(WsSerializerContextH serctx, void *ptr)
{
lnode_t *node = NULL;
lnode_t *node2 = NULL;
TRACE_ENTER;
if (serctx) {
u_lock(serctx);
node = list_first(serctx->WsSerializerAllocList);
while (node != NULL) {
WsSerializerMemEntry *entry =
(WsSerializerMemEntry *) node->list_data;
if (entry && (!ptr || ptr == entry->buf)) {
u_free(entry);
node2 = node;
node = list_delete2(serctx->WsSerializerAllocList, node);
lnode_destroy (node2);
if (ptr != NULL) {
break;
}
}
else
node = list_next(serctx->WsSerializerAllocList, node);
}
u_unlock(serctx);
}
TRACE_EXIT;
return (node != NULL);
}
int ws_serializer_free(WsSerializerContextH serctx, void *ptr)
{
int retVal = 0;
TRACE_ENTER;
if (ptr != NULL)
retVal = do_serializer_free(serctx, ptr);
TRACE_EXIT;
return retVal;
}
void ws_serializer_free_all(WsSerializerContextH serctx)
{
TRACE_ENTER;
do_serializer_free(serctx, NULL);
TRACE_EXIT;
}
int ws_havenilvalue(XML_NODE_ATTR *attrs)
{
while(attrs) {
if(attrs->ns && attrs->name && attrs->value &&
strcmp(attrs->ns, XML_NS_SCHEMA_INSTANCE) == 0 &&
strcmp(attrs->name, XML_SCHEMA_NIL) == 0 &&
strcasecmp(attrs->value, "true") == 0)
return 1;
attrs = attrs->next;
}
return 0;
}