Files
microser/mmslib/util/sx_dec.c
2026-06-15 15:48:16 +08:00

2521 lines
74 KiB
C

/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1999 - 2008, All Rights Reserved */
/* */
/* MODULE NAME : sx_dec.c */
/* PRODUCT(S) : */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 02/06/08 EJV 88 Added SX_PARSING_OK, sx_err_str* (for slogs).*/
/* 01/14/08 MDE 87 Fixed numOcc multithread problem */
/* 10/04/07 MDE 86 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */
/* For early MODLOGS see previous revision of this file on PVCS. */
/************************************************************************/
#if defined (_WIN32)
#pragma warning(disable : 4996)
#endif
#include "glbtypes.h"
#include "sysincs.h"
#include "mem_chk.h"
#include "sx_defs.h"
#include "sx_log.h"
#include "time_str.h"
#include "str_util.h"
/************************************************************************/
/* For debug version, use a static pointer to avoid duplication of */
/* __FILE__ strings. */
#ifdef DEBUG_SISCO
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
#endif
#if defined(USE_EXPAT)
/* Assume linking to Expat "static" library. Must define XML_STATIC */
/* before including "expat.h". */
#define XML_STATIC
#include "expat.h"
#define EXPAT_BUF_SIZE 8192 /* parse buffer size if reading from file*/
#define ENTITY_BUF_SIZE 2000 /* initial size to alloc for entity buffer*/
/* reallocate larger if needed */
static void XMLCALL expatHandlerStartSkip(void *userData, const char *el, const char **attr);
static void XMLCALL expatHandlerEndSkip(void *userData, const char *el);
#endif
/************************************************************************/
SD_CONST ST_CHAR *SD_CONST _sx_log_dec_logstr = "SX_LOG_DEC";
SD_CONST ST_CHAR *SD_CONST _sx_log_enc_logstr = "SX_LOG_ENC";
SD_CONST ST_CHAR *SD_CONST _sx_log_flow_logstr = "SX_LOG_FLOW";
SD_CONST ST_CHAR *SD_CONST _sx_log_debug_logstr = "SX_LOG_DEBUG";
SD_CONST ST_CHAR *SD_CONST _sx_log_err_logstr = "SX_LOG_ERR";
SD_CONST ST_CHAR *SD_CONST _sx_log_nerr_logstr = "SX_LOG_NERR";
ST_UINT sx_debug_sel = SX_LOG_ERR | SX_LOG_NERR;
ST_UINT sx_debug_sel_cfg = SX_LOG_ERR | SX_LOG_NERR; /* saves SX masks while logging configuration is parsed */
#ifdef DEBUG_SISCO
LOGCFGX_VALUE_MAP sxLogMaskMaps[] =
{
{"SX_LOG_ERR", SX_LOG_ERR, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"},
{"SX_LOG_NERR", SX_LOG_NERR, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"},
{"SX_LOG_FLOW", SX_LOG_FLOW, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"},
{"SX_LOG_DEC", SX_LOG_DEC, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Decode"},
{"SX_LOG_ENC", SX_LOG_ENC, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Encode"},
{"SX_LOG_DEBUG", SX_LOG_DEBUG, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Debug"},
};
LOGCFG_VALUE_GROUP sxLogMaskMapCtrl =
{
{NULL,NULL},
"SxLogMasks", /* Parent Tag */
sizeof(sxLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP),
sxLogMaskMaps
};
/* tbl of error strings, used in slogs */
ST_CHAR *sx_err_str[] =
{
"SX_PARSING_OK", /* 0 */
"SX_USER_ERROR", /* 1 */
"SX_STRUCT_NOT_FOUND", /* 2 */
"SX_REQUIRED_TAG_NOT_FOUND", /* 3 */
"SX_DUPLICATE_NOT_ALLOWED", /* 4 */
"SX_EMPTY_TAG_NOT_ALLOWED", /* 5 */
"SX_XML_NEST_TOO_DEEP", /* 6 */
"SX_XML_BUFFER_OVER_MAX", /* 7 */
"SX_XML_MALFORMED", /* 8 */
"SX_FILE_NOT_FOUND", /* 9 */
"SX_END_PARSING", /* 10 */
"SX_ELEMENT_TBL_TOO_BIG" /* 11 */
};
ST_INT sx_err_str_cnt = sizeof (sx_err_str)/sizeof (ST_CHAR *);
#endif /* DEBUG_SISCO */
/************************************************************************/
ST_BOOLEAN sxUseSax;
ST_BOOLEAN sxIgnoreNS;
ST_RET sx_rip_xml (SX_DEC_CTRL *sxDecCtrl);
ST_RET sx_rip_xml_file (SX_DEC_CTRL *sxDecCtrl);
ST_RET sx_rip_xml_mem (SX_DEC_CTRL *sxDecCtrl);
SX_ELEMENT *_uibed_find_element (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, ST_INT **numOccOut);
static ST_VOID _sx_pop (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN auto_pop);
/************************************************************************/
/* sx_parseExx_mt */
/* Note: when making changes/correction to this function revise also */
/* other sx_parse functions. */
/* Decode the XML located in file by loading the whole thing into */
/* memory first ... */
/************************************************************************/
ST_RET sx_parseExx_mt (ST_CHAR *fileName, ST_INT numItems,
SX_ELEMENT *itemTbl, ST_VOID *usr,
ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag),
ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag))
{
ST_RET rc;
ST_LONG fileSize;
ST_LONG bytesRead;
ST_CHAR *cfgData;
struct stat buf;
int result;
FILE *fp;
/* Get the size of the file */
fp = fopen (fileName, "r");
if (fp == NULL)
{
/*
SXLOG_FLOW2 ("XML File (%s) Open Error (errno=%d)", fileName, errno);
printf ("XML File (%s) Open Error (errno=%d)\n", fileName, errno);
*/
return (SX_FILE_NOT_FOUND);
}
result = fstat (fileno (fp), &buf);
if (result != 0)
return (SD_FAILURE);
/* Allocate a buffer and read all into memory */
fileSize = buf.st_size;
cfgData = (ST_CHAR *) chk_malloc (fileSize);
bytesRead = fread (cfgData, 1, fileSize, fp);
fclose (fp);
if (bytesRead <= 0)
{
chk_free (cfgData);
SXLOG_FLOW1 ("Error: Could not read from '%s'", fileName);
return (SX_FILE_NOT_FOUND);
}
rc = sx_parse_mt (bytesRead, cfgData, numItems, itemTbl, usr,
u_sx_el_start_fun, u_sx_el_end_fun);
if (rc != SD_SUCCESS)
{
SXLOG_FLOW1 ("ERROR: parsing failed, return code: '%d'", rc);
}
chk_free (cfgData);
return (rc);
}
/************************************************************************/
/* sx_parse_mt */
/* Note: when making changes/correction to this function revise also */
/* other sx_parse functions. */
/* Decode the XML located in memory (thread safe version). */
/************************************************************************/
ST_RET sx_parse_mt (ST_LONG lMsgLen, ST_CHAR *xml, ST_INT numItems,
SX_ELEMENT *itemTbl, ST_VOID *usr,
ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag),
ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag))
{
SX_DEC_CTRL *sxDecCtrl;
ST_RET rc;
SXLOG_FLOW0 ("Start Decoding XML");
SXLOG_FLOWH ((ST_INT) lMsgLen, xml);
sxDecCtrl = (SX_DEC_CTRL *) calloc (1, sizeof (SX_DEC_CTRL));
/* !we need to use here the system calloc */
sx_push (sxDecCtrl, numItems, itemTbl, SD_FALSE);
sxDecCtrl->xmlStart = xml;
sxDecCtrl->xmlLen = lMsgLen;
sxDecCtrl->ignoreNS = sxIgnoreNS;
sxDecCtrl->useFp = SD_FALSE;
sxDecCtrl->usr = usr;
sxDecCtrl->u_sx_el_start = u_sx_el_start_fun;
sxDecCtrl->u_sx_el_end = u_sx_el_end_fun;
#if defined(USE_EXPAT)
sx_rip_xml_mem (sxDecCtrl);
#else
sx_rip_xml (sxDecCtrl);
#endif
if (sxDecCtrl->xmlNestLevel != 0 && sxDecCtrl->errCode == SD_SUCCESS)
{
sxDecCtrl->errCode = SX_XML_MALFORMED;
SXLOG_NERR0 ("Invalid XML nesting");
}
rc = sxDecCtrl->errCode;
free (sxDecCtrl);
return (rc);
}
/************************************************************************/
/* sx_parseEx_mt */
/* Note: when making changes/correction to this function revise also */
/* other sx_parse functions. */
/* Decode the XML located in file (thread safe version). */
/************************************************************************/
ST_RET sx_parseEx_mt (ST_CHAR *fileName, ST_INT numItems,
SX_ELEMENT *itemTbl, ST_VOID *usr,
ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag),
ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag))
{
SX_DEC_CTRL *sxDecCtrl;
ST_RET rc;
FILE *fp;
SXLOG_FLOW1 ("Start Decoding XML file %s", fileName);
if ((fp = fopen (fileName,"r"))==NULL)
{
SXLOG_FLOW1 ("XML File (%s) Open Error",fileName);
return (SX_FILE_NOT_FOUND);
}
sxDecCtrl = (SX_DEC_CTRL *) calloc (1, sizeof (SX_DEC_CTRL));
/* !we need to use here the system calloc */
sx_push (sxDecCtrl, numItems, itemTbl, SD_FALSE);
sxDecCtrl->fp = fp;
sxDecCtrl->ignoreNS = sxIgnoreNS;
sxDecCtrl->useFp = SD_TRUE;
sxDecCtrl->usr = usr;
sxDecCtrl->u_sx_el_start = u_sx_el_start_fun;
sxDecCtrl->u_sx_el_end = u_sx_el_end_fun;
#if defined(USE_EXPAT)
sx_rip_xml_file (sxDecCtrl);
#else
sx_rip_xml (sxDecCtrl);
#endif
if (sxDecCtrl->errCode == 0)
{
if (sxDecCtrl->xmlNestLevel != 0)
{
sxDecCtrl->errCode = SX_XML_MALFORMED;
SXLOG_NERR0 ("Invalid XML nesting");
}
}
rc = sxDecCtrl->errCode;
free (sxDecCtrl);
fclose (fp);
return (rc);
}
/************************************************************************/
/* sxStartElement */
/************************************************************************/
ST_VOID sxStartElement (SX_DEC_CTRL *sxDecCtrl)
{
SX_ELEMENT *item;
SX_DEC_ELEMENT_INFO *sxDecElInfo;
ST_CHAR *tag;
ST_RET rc = SD_FAILURE;
ST_INT stackLevelSave;
ST_INT *numOccPtr;
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
tag = sxDecElInfo->tag;
SXLOG_DEC1 ("Start element '%s'", tag);
if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT)
{
return;
}
item = _uibed_find_element (sxDecCtrl, tag, &numOccPtr);
stackLevelSave = sxDecCtrl->itemStackLevel;
while (item == NULL && sxDecCtrl->itemStackLevel > 0)
{
if (sxDecCtrl->auto_pop[sxDecCtrl->itemStackLevel-1] == SD_TRUE)
{
_sx_pop (sxDecCtrl, SD_TRUE);
item = _uibed_find_element (sxDecCtrl, tag, &numOccPtr);
}
else
break;
}
if (item != NULL)
{
if (*numOccPtr != 0 && ((item->elementFlags & SX_ELF_RPT) == 0))
{
sxDecCtrl->errCode = SX_DUPLICATE_NOT_ALLOWED;
SXLOG_NERR1 ("Duplicate of element '%s' not allowed", tag);
return;
}
++(*numOccPtr);
if (*numOccPtr > 1)
{
SXLOG_CDEC1 ("Number occurences: %d", *numOccPtr);
}
/* Save the item for later */
++sxDecCtrl->xmlNestLevel;
sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel] = item;
/* Call the user function, if there is one ... */
sxDecCtrl->item = item;
sxDecCtrl->reason = SX_ELEMENT_START;
if ((item->elementFlags & SX_ELF_CSTART) != 0)
{
if (item->funcPtr != NULL)
{
sxDecCtrl->elUser = item->user;
(item->funcPtr)(sxDecCtrl);
}
else
{
SXLOG_CDEC0 ("No state function for this element");
}
}
}
else if (sxDecCtrl->u_sx_el_start != NULL)
{
sxDecCtrl->itemStackLevel = stackLevelSave;
if (sxDecCtrl->u_sx_el_start != NULL)
rc = (*(sxDecCtrl->u_sx_el_start)) (sxDecCtrl, tag);
if (rc == SD_SUCCESS)
{
++sxDecCtrl->xmlNestLevel;
sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel] = NULL;
}
else
{
sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND;
SXLOG_CDEC1 ("u_sx_el_start failed for element '%s'", tag);
}
}
else
{
sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND;
SXLOG_NERR1 ("Could not find element '%s' in element table", tag);
}
}
/************************************************************************/
/* sxEndElement */
/************************************************************************/
ST_VOID sxEndElement (SX_DEC_CTRL *sxDecCtrl)
{
SX_DEC_ELEMENT_INFO *sxDecElInfo;
SX_ELEMENT *item;
ST_CHAR *tag;
ST_RET rc = SD_FAILURE;
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
tag = sxDecElInfo->tag;
SXLOG_DEC1 ("End element '%s'", tag);
if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT)
{
return;
}
item = sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel];
--sxDecCtrl->xmlNestLevel;
if (item != NULL)
{
if (strcmp (tag, item->tag) != 0) /* verify end tag */
{
sxDecCtrl->errCode = SX_XML_MALFORMED;
SXLOG_NERR2 ("XML malformed: found </%s>, expected </%s>", tag, item->tag);
}
else
{
if ((item->elementFlags & SX_ELF_CEND) != 0)
{
sxDecCtrl->item = item;
sxDecCtrl->reason = SX_ELEMENT_END;
if (item->funcPtr != NULL)
{
sxDecCtrl->elUser = item->user;
(item->funcPtr)(sxDecCtrl);
}
else
{
SXLOG_CDEC0 ("No state function for this element");
}
}
}
}
else
{
if (sxDecCtrl->u_sx_el_end != NULL)
{
rc = (*(sxDecCtrl->u_sx_el_end)) (sxDecCtrl, sxDecCtrl->sxDecElInfo.tag);
if (rc != SD_SUCCESS)
{
sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND;
SXLOG_NERR1 ("u_sx_el_end failed for element '%s'", tag);
}
}
}
}
/************************************************************************/
/************************************************************************/
/* sx_push */
/************************************************************************/
ST_VOID sx_push (SX_DEC_CTRL *sxDecCtrl, ST_INT numItems, SX_ELEMENT *itemTbl,
ST_BOOLEAN auto_pop)
{
ST_INT i;
SX_ELEMENT_TBL_CTRL *itemTblCtrl;
ST_INT *numOccTbl;
/* Do some sanity checks first */
if (sxDecCtrl->itemStackLevel >= SX_MAX_STACK_LEVEL)
{
sxDecCtrl->errCode = SX_XML_NEST_TOO_DEEP;
return;
}
if (numItems > SX_MAX_ITEMS_PER_TABLE)
{
sxDecCtrl->errCode = SX_ELEMENT_TBL_TOO_BIG;
return;
}
itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel];
numOccTbl = itemTblCtrl->numOccTbl;
itemTblCtrl->itemTbl= itemTbl;
itemTblCtrl->numItems= numItems;
sxDecCtrl->auto_pop[sxDecCtrl->itemStackLevel] = auto_pop;
++sxDecCtrl->itemStackLevel;
/* reset the numOCc elements */
for (i = 0; i < numItems; ++i)
numOccTbl[i] = 0;
}
/************************************************************************/
/* sx_pop */
/************************************************************************/
ST_VOID sx_pop (SX_DEC_CTRL *sxDecCtrl)
{
_sx_pop (sxDecCtrl, SD_FALSE);
}
/************************************************************************/
/* _sx_pop */
/************************************************************************/
static ST_VOID _sx_pop (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN auto_pop)
{
SX_ELEMENT_TBL_CTRL *itemTblCtrl;
SX_ELEMENT *item;
ST_INT i;
ST_INT *numOccTbl;
/* Check for mandatory elements */
if (sxDecCtrl->itemStackLevel > 0)
{
--sxDecCtrl->itemStackLevel;
/* If auto-popping AND have a unknown element handler, don't check mandatory */
if (auto_pop && sxDecCtrl->u_sx_el_start != NULL)
return;
itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel];
numOccTbl = itemTblCtrl->numOccTbl;
for (i = 0; i < itemTblCtrl->numItems; ++i)
{
item = &itemTblCtrl->itemTbl[i];
if (numOccTbl[i] == 0 && ((item->elementFlags & SX_ELF_OPT) == 0))
{
sxDecCtrl->errCode = SX_REQUIRED_TAG_NOT_FOUND;
SXLOG_NERR1 ("Mandatory element '%s' not found", item->tag);
break;
}
}
}
}
/************************************************************************/
/************************************************************************/
SX_ELEMENT *_uibed_find_element (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, ST_INT **numOccPtrOut)
{
SX_ELEMENT_TBL_CTRL *itemTblCtrl;
ST_INT numItems;
SX_ELEMENT *item;
ST_INT i;
itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel-1];
item = itemTblCtrl->itemTbl;
numItems = itemTblCtrl->numItems;
/* See if this element is in our table */
for (i = 0; i < numItems; ++i, ++item)
{
if (strcmp (tag, item->tag) == 0)
{
*numOccPtrOut = &itemTblCtrl->numOccTbl[i];
return (item);
}
}
return (NULL);
}
/************************************************************************/
/************************************************************************/
/************************************************************************/
ST_RET sx_get_element_contents (SX_DEC_CTRL *sxDecCtrl,
ST_CHAR *destBuf, ST_INT destLen,
ST_INT *lenOut)
{
ST_CHAR *src;
ST_INT len;
ST_INT rc;
rc = sx_find_element_contents (sxDecCtrl, &src, &len);
if (rc != SD_SUCCESS)
return (rc);
if (destLen < len)
{
SXLOG_NERR0("sx_get_element_contents: dest too small");
SXLOG_NERR1 ("Error: sx_get_element_contents: dest too small for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
memcpy (destBuf, src, len);
*lenOut = len;
return (SD_SUCCESS);
}
/************************************************************************/
ST_RET sx_find_element_contents (SX_DEC_CTRL *sxDecCtrl,
ST_CHAR **elStartOut, ST_INT *lenOut)
{
SX_DEC_ELEMENT_INFO *sxDecElInfo;
ST_CHAR *start;
ST_CHAR *end;
ST_CHAR endTagBuf[100];
ST_INT len;
#if defined(USE_EXPAT)
int offset;
int size;
const char *ptr;
/* Doesn't work if reading one buffer at a time from a file. */
if (sxDecCtrl->fp)
{
SXLOG_ERR0 ("sx_find_element_contents only works if entire XML is in memory. Use sx_parseExx_mt or sx_parse_mt.");
return (SD_FAILURE);
}
/* Set "start" ptr to point after end of this start tag. */
ptr = XML_GetInputContext(sxDecCtrl->parser, &offset, &size);
ptr += offset; /* point to current position in XML buffer */
/* should be beginning of start tag */
start = strchr (ptr, '>') + 1; /* point after end of start tag */
/* save nest level to help find corresponding end tag */
sxDecCtrl->skipNestLevel = sxDecCtrl->xmlNestLevel;
/* Change handlers to skip to end of this element (look for end tag). */
XML_SetCharacterDataHandler(sxDecCtrl->parser, NULL); /* ignore element data */
XML_SetElementHandler(sxDecCtrl->parser, expatHandlerStartSkip, expatHandlerEndSkip);
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
#else
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
start = sxDecCtrl->xmlPos;
#endif
/* Check to see if this is an empty element */
if (*(start - 2) == '/')
{
*lenOut = 0;
return (SD_SUCCESS);
}
*elStartOut = start;
len = sxDecCtrl->xmlLen - (start - sxDecCtrl->xmlStart);
/* We need to find the closing element for this start element */
endTagBuf[0] = '<';
endTagBuf[1] = '/';
strcpy (&endTagBuf[2], sxDecElInfo->tag);
strcat (endTagBuf, ">");
end = strnstr (start, endTagBuf, len);
if (end == NULL)
{
SXLOG_NERR1("Can't find end tag '%s'", sxDecElInfo->tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
*lenOut = end - start;
#if !defined(USE_EXPAT) /* with Expat, can't set or use xmlPos */
sxDecCtrl->xmlPos = end;
#endif
SXLOG_CDEC0("sx_find_element_contents got data:");
SXLOG_DECH (*lenOut, *elStartOut);
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
/* sx_get_entity */
/************************************************************************/
ST_RET sx_get_entity (SX_DEC_CTRL *sxDecCtrl,
ST_CHAR *destBuf, ST_INT destLen,
ST_INT *lenOut)
{
#if defined(USE_EXPAT)
if (destLen < sxDecCtrl->entityLen)
{
SXLOG_NERR2 ("Error: sx_get_entity: dest too small (max %d bytes expected) for tag '%s'", destLen, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
*lenOut = 0; /* return empty buf */
return (SD_FAILURE);
}
else
{
memcpy (destBuf, sxDecCtrl->entityBuf, sxDecCtrl->entityLen);
*lenOut = sxDecCtrl->entityLen;
}
if (*lenOut == 0)
SXLOG_CDEC0("sx_get_entity (no data)");
else
{
SXLOG_CDEC0("sx_get_entity got data:");
SXLOG_DECH (*lenOut, destBuf);
}
return (SD_SUCCESS);
#else /* !USE_EXPAT */
SX_DEC_ELEMENT_INFO *sxDecElInfo;
ST_INT i;
ST_CHAR *dest;
ST_CHAR *src;
ST_CHAR *end;
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
src = sxDecElInfo->entityStart;
dest = destBuf;
end = sxDecElInfo->entityEnd;
for (i = 0; i < destLen && src < end; ++i, ++src, ++dest)
*dest = *src;
*lenOut = i;
if (src < end)
{
SXLOG_NERR2 ("Error: sx_get_entity: dest too small (max %d bytes expected) for tag '%s'", destLen, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SXLOG_CDEC0("sx_get_entity got data:");
SXLOG_DECH (i, destBuf);
return (SD_SUCCESS);
#endif /* !USE_EXPAT */
}
/************************************************************************/
/* sx_get_bool */
/************************************************************************/
ST_RET sx_get_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *out_ptr)
{
ST_INT d;
ST_RET rc;
rc = sx_get_value (sxDecCtrl, "%d", &d);
if (rc != SD_SUCCESS)
return (rc);
if (d == 0)
*out_ptr = SD_FALSE;
else
*out_ptr = SD_TRUE;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_int */
/************************************************************************/
ST_RET sx_get_int (SX_DEC_CTRL *sxDecCtrl, ST_INT *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%d", out_ptr));
}
/************************************************************************/
/* sx_get_float */
/************************************************************************/
ST_RET sx_get_float (SX_DEC_CTRL *sxDecCtrl, ST_FLOAT *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%f", out_ptr));
}
/************************************************************************/
/* sx_get_double */
/************************************************************************/
ST_RET sx_get_double (SX_DEC_CTRL *sxDecCtrl, ST_DOUBLE *out_ptr)
{
/* Note: must use the '%le' format specifier for double */
return (sx_get_value (sxDecCtrl, "%le", out_ptr));
}
/************************************************************************/
/* sx_get_uchar */
/************************************************************************/
ST_RET sx_get_uchar (SX_DEC_CTRL *sxDecCtrl, ST_UCHAR *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%c", out_ptr));
}
/************************************************************************/
/* sx_get_int16 */
/************************************************************************/
ST_RET sx_get_int16 (SX_DEC_CTRL *sxDecCtrl, ST_INT16 *out_ptr)
{
ST_INT i;
ST_RET rc;
if ((rc = sx_get_value (sxDecCtrl, "%d", &i)) == SD_SUCCESS)
*out_ptr = (ST_INT16) i;
return (rc);
}
/************************************************************************/
/* sx_get_uint16 */
/************************************************************************/
ST_RET sx_get_uint16 (SX_DEC_CTRL *sxDecCtrl, ST_UINT16 *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%hu", out_ptr));
}
/************************************************************************/
/* sx_get_uint32 */
/************************************************************************/
ST_RET sx_get_uint32 (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr)
{
ST_ULONG ul;
ST_RET rc;
if ((rc = sx_get_value (sxDecCtrl, "%lu", &ul)) == SD_SUCCESS)
*out_ptr = (ST_UINT32) ul;
return (rc);
}
/************************************************************************/
/* sx_get_uint32_hex */
/************************************************************************/
ST_RET sx_get_uint32_hex (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr)
{
ST_ULONG ul;
ST_RET rc;
if ((rc = sx_get_value (sxDecCtrl, "0x%lx", &ul)) == SD_SUCCESS)
*out_ptr = (ST_UINT32) ul;
return (rc);
}
/************************************************************************/
/* sx_get_int32 */
/************************************************************************/
ST_RET sx_get_int32 (SX_DEC_CTRL *sxDecCtrl, ST_INT32 *out_ptr)
{
ST_LONG sl;
ST_RET rc;
if ((rc = sx_get_value (sxDecCtrl, "%ld", &sl)) == SD_SUCCESS)
*out_ptr = (ST_INT32) sl;
return (rc);
}
/************************************************************************/
/* sx_get_long */
/************************************************************************/
ST_RET sx_get_long (SX_DEC_CTRL *sxDecCtrl, ST_LONG *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%ld", out_ptr));
}
/************************************************************************/
/* sx_get_ulong */
/************************************************************************/
ST_RET sx_get_ulong (SX_DEC_CTRL *sxDecCtrl, ST_ULONG *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%lu", out_ptr));
}
/************************************************************************/
/* sx_get_uint */
/************************************************************************/
ST_RET sx_get_uint (SX_DEC_CTRL *sxDecCtrl, ST_UINT *out_ptr)
{
return (sx_get_value (sxDecCtrl, "%u", out_ptr));
}
/************************************************************************/
/* sx_get_value */
/************************************************************************/
ST_RET sx_get_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *format_string, ST_VOID *out_ptr)
{
ST_CHAR *str;
ST_INT strLen;
ST_RET rc;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
/* Convert to desired data format*/
/* Note: sscanf may return 'bad' value if the number in the str */
/* exceeds the max value in format_string. */
if (sscanf (str, format_string, out_ptr) != 1)
/* we just want to get one value out of the string, any other ret is an error */
{
SXLOG_NERR1 ("Data Conversion Error for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* *sx_get_alloc_string */
/************************************************************************/
ST_RET sx_get_alloc_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut)
{
ST_CHAR *str;
ST_INT strLen;
ST_RET rc;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
*strOut = M_STRDUP(NULL,str);
return (SD_SUCCESS);
}
/************************************************************************/
/* *sx_get_string */
/************************************************************************/
ST_RET sx_get_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *dest, ST_INT *lenOut)
{
ST_CHAR *str;
ST_INT strLen;
ST_RET rc;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
if (*lenOut != 0)
{
if (strLen > *lenOut)
{
SXLOG_NERR1 ("Error: String too long for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
}
sx_format_string_dec (dest, str);
*lenOut = strLen;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_format_string_dec */
/************************************************************************/
ST_VOID sx_format_string_dec (ST_CHAR *dest, ST_CHAR *src)
{
ST_CHAR *srcPtr;
ST_CHAR *srcPtrLast;
ST_CHAR *dstPtr;
ST_INT diff;
dstPtr = dest;
srcPtrLast = src;
srcPtr = strchr (src, '&');
if (srcPtr == NULL)
{
strcpy (dest, src);
return;
}
diff = srcPtr - srcPtrLast;
strncpy (dstPtr, srcPtrLast, diff);
dstPtr += diff;
/* parse the source string and generate the dest string */
while (srcPtr != NULL)
{
/* srcPtr points at a & */
/* lets find out if the following characters are what we are looking for */
if (strncmp (srcPtr, CODE_APOS, CODE_APOS_LEN) == 0)
{
*dstPtr++ = CHAR_APOS;
srcPtr += CODE_APOS_LEN;
}
else if (strncmp (srcPtr, CODE_QUOT, CODE_QUOT_LEN) == 0)
{
*dstPtr++ = CHAR_QUOT;
srcPtr += CODE_QUOT_LEN;
}
else if (strncmp (srcPtr, CODE_AMP, CODE_AMP_LEN) == 0)
{
*dstPtr++ = CHAR_AMP;
srcPtr += CODE_AMP_LEN;
}
else if (strncmp (srcPtr, CODE_LT, CODE_LT_LEN) == 0)
{
*dstPtr++ = CHAR_LT;
srcPtr += CODE_LT_LEN;
}
else if (strncmp (srcPtr, CODE_GT, CODE_GT_LEN) == 0)
{
*dstPtr++ = CHAR_GT;
srcPtr += CODE_GT_LEN;
}
else
{
*dstPtr++ = '&';
srcPtr++;
}
srcPtrLast = srcPtr;
srcPtr = strchr (srcPtr, '&');
if (srcPtr == NULL)
{
/* copy the remaining section of the string */
strcpy (dstPtr, srcPtrLast);
}
else
{
diff = srcPtr - srcPtrLast;
strncpy (dstPtr, srcPtrLast, diff);
dstPtr += diff;
}
}
}
/************************************************************************/
/************************************************************************/
/************************************************************************/
/* sx_get_bool_attr */
/************************************************************************/
ST_RET sx_get_bool_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_BOOLEAN *out_ptr)
{
ST_INT d;
ST_RET rc;
rc = sx_get_attr_value (sxDecCtrl, name, "%d", &d);
if (rc != SD_SUCCESS)
return (rc);
if (d == 0)
*out_ptr = SD_FALSE;
else
*out_ptr = SD_TRUE;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_int_attr */
/************************************************************************/
ST_RET sx_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%d", out_ptr));
}
/************************************************************************/
/* sx_get_float_attr */
/************************************************************************/
ST_RET sx_get_float_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_FLOAT *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%f", out_ptr));
}
/************************************************************************/
/* sx_get_double_attr */
/************************************************************************/
ST_RET sx_get_double_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_DOUBLE *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%le", out_ptr));
}
/************************************************************************/
/* sx_get_uchar_attr */
/************************************************************************/
ST_RET sx_get_uchar_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UCHAR *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%c", out_ptr));
}
/************************************************************************/
/* sx_get_int16_attr */
/************************************************************************/
ST_RET sx_get_int16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT16 *out_ptr)
{
ST_INT i;
ST_RET rc;
if ((rc = sx_get_attr_value (sxDecCtrl, name, "%d", &i)) == SD_SUCCESS)
*out_ptr = (ST_INT16) i;
return (rc);
}
/************************************************************************/
/* sx_get_uint16_attr */
/************************************************************************/
ST_RET sx_get_uint16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT16 *out_ptr)
{
ST_UINT i;
ST_RET rc;
if ((rc = sx_get_attr_value (sxDecCtrl, name, "%u", &i)) == SD_SUCCESS)
*out_ptr = (ST_UINT16) i;
return (rc);
}
/************************************************************************/
/* sx_get_uint32_attr */
/************************************************************************/
ST_RET sx_get_uint32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT32 *out_ptr)
{
ST_ULONG ul;
ST_RET rc;
if ((rc = sx_get_attr_value (sxDecCtrl, name, "%lu", &ul)) == SD_SUCCESS)
*out_ptr = (ST_UINT32) ul;
return (rc);
}
/************************************************************************/
/* sx_get_int32_attr */
/************************************************************************/
ST_RET sx_get_int32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT32 *out_ptr)
{
ST_LONG sl;
ST_RET rc;
if ((rc = sx_get_attr_value (sxDecCtrl, name, "%ld", &sl)) == SD_SUCCESS)
*out_ptr = (ST_INT32) sl;
return (rc);
}
/************************************************************************/
/* sx_get_long_attr */
/************************************************************************/
ST_RET sx_get_long_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_LONG *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%ld", out_ptr));
}
/************************************************************************/
/* sx_get_ulong_attr */
/************************************************************************/
ST_RET sx_get_ulong_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_ULONG *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%lu", out_ptr));
}
/************************************************************************/
/* sx_get_uint_attr */
/************************************************************************/
ST_RET sx_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT *out_ptr)
{
return (sx_get_attr_value (sxDecCtrl, name, "%u", out_ptr));
}
/************************************************************************/
/* XmlStringToDuration */
/************************************************************************/
ST_RET XmlStringToDuration (ST_CHAR *src, SX_DURATION *out_ptr)
{
ST_CHAR *p;
ST_CHAR temp[50]; /* arbitrary length */
ST_CHAR temp2[50]; /* arbitrary length */
ST_BOOLEAN foundP = SD_FALSE;
ST_BOOLEAN foundT = SD_FALSE;
ST_BOOLEAN foundDot = SD_FALSE;
ST_UINT i;
ST_BOOLEAN something = SD_FALSE; /* Make sure we got SOMETHING out of */
/* this, any of the fields can be missing */
out_ptr->inUse = SD_TRUE;
p = src;
memset (temp, 0, sizeof(temp));
memset (temp2, 0, sizeof(temp2));
for (i = 0; i < strlen(src); i++, p++)
{
/* check all error conditions I can think of */
if ((*p == '-' && foundP) ||
(isdigit(*p) && !foundP) ||
(*p == 'Y' && !foundP) ||
(*p == 'M' && !foundP) ||
(*p == 'D' && !foundP) ||
(!foundP && foundT) ||
(*p == 'H' && !foundT) ||
(*p == 'S' && !foundT) ||
(*p != 'P' && *p != 'T' && isalpha(*p) && strlen(temp) == 0))
return (SD_FAILURE);
/* check for negative */
else if (*p == '-')
out_ptr->negative = SD_TRUE;
else if (*p == '.')
foundDot = SD_TRUE;
/* We found a number */
else if (isdigit(*p))
{
if (foundDot)
strncat (temp2, p, 1);
else
strncat (temp, p, 1);
}
/* We found a letter */
else if (isalpha(*p))
{
switch (*p)
{
case 'P':
foundP = SD_TRUE;
break;
case 'T':
foundT = SD_TRUE;
break;
case 'Y':
sscanf(temp, "%d", &out_ptr->years);
temp[0] = 0;
something = SD_TRUE;
break;
case 'M':
if (foundT)
sscanf(temp, "%d", &out_ptr->minutes);
else
sscanf(temp, "%d", &out_ptr->months);
temp[0] = 0;
something = SD_TRUE;
break;
case 'D':
sscanf(temp, "%d", &out_ptr->days);
temp[0] = 0;
something = SD_TRUE;
break;
case 'H':
sscanf(temp, "%d", &out_ptr->hours);
temp[0] = 0;
something = SD_TRUE;
break;
case 'S':
sscanf(temp, "%d", &out_ptr->seconds);
temp[0] = 0;
sscanf(temp2, "%ld", &out_ptr->microseconds);
temp2[0] = 0;
something = SD_TRUE;
break;
default:
return (SD_FAILURE);
}
}
}
if (something == SD_FALSE)
return (SD_FAILURE);
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_duration_attr */
/************************************************************************/
ST_RET sx_get_duration_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DURATION *out_ptr)
{
ST_RET rc;
ST_CHAR *sxDuration;
memset (out_ptr, 0, sizeof (*out_ptr));
rc = sx_get_attr_ptr (sxDecCtrl, &sxDuration, name);
if (rc)
return (rc);
rc = XmlStringToDuration (sxDuration, out_ptr);
if (rc != SD_SUCCESS)
{
SXLOG_NERR1 ("Error: String to Duration conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_xtime_attr */
/************************************************************************/
ST_RET sx_get_xtime_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DATE_TIME *out_ptr)
{
ST_RET rc;
ST_CHAR *sxDateTime;
memset (out_ptr, 0, sizeof (*out_ptr));
rc = sx_get_attr_ptr (sxDecCtrl, &sxDateTime, name);
if (rc)
return (rc);
rc = XmlStringToUtcValue (sxDateTime, out_ptr);
if (rc != SD_SUCCESS)
{
SXLOG_NERR1 ("Error: String to Value date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_tm_attr */
/************************************************************************/
ST_RET sx_get_tm_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, struct tm *out_ptr)
{
ST_RET rc;
ST_CHAR *theTime;
memset (out_ptr, 0, sizeof (*out_ptr));
rc = sx_get_attr_ptr (sxDecCtrl, &theTime, name);
if (rc)
return (rc);
rc = tstrStringToTm (theTime, out_ptr);
if (rc != SD_SUCCESS)
{
SXLOG_NERR1 ("Error: String to Value (struct tm) date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_attr_value */
/************************************************************************/
ST_RET sx_get_attr_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name,
ST_CHAR *format_string, ST_VOID *out_ptr)
{
ST_UINT i;
for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i)
{
if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0)
{
/* Convert to desired data format*/
if (!sscanf (sxDecCtrl->sxDecElInfo.attr[i].value,
format_string, out_ptr))
{
SXLOG_NERR1 ("Error: Attribute Data Conversion Error for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
return (SD_SUCCESS);
}
}
return (SD_FAILURE);
}
/************************************************************************/
/* sx_get_attr */
/************************************************************************/
ST_RET sx_get_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *value, ST_CHAR *name)
{
ST_UINT i;
for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i)
{
if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0)
{
strcpy (value, sxDecCtrl->sxDecElInfo.attr[i].value);
return (SD_SUCCESS);
}
}
return (SD_FAILURE);
}
/************************************************************************/
/* sx_get_attr_ptr */
/************************************************************************/
ST_RET sx_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **ptrOut, ST_CHAR *name)
{
ST_UINT i;
for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i)
{
if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0)
{
*ptrOut = sxDecCtrl->sxDecElInfo.attr[i].value;
return (SD_SUCCESS);
}
}
return (SD_FAILURE);
}
/************************************************************************/
/* *sx_get_bitstring */
/************************************************************************/
ST_RET sx_get_bitstring (SX_DEC_CTRL *sxDecCtrl, ST_INT *dest, ST_INT *lenOut)
{
ST_CHAR *str;
ST_INT strLen;
ST_INT *bits;
ST_CHAR *pStr;
ST_RET rc;
ST_INT i;
strLen = 0;
bits = dest;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
if (*lenOut != 0)
{
if (strLen > *lenOut)
{
SXLOG_NERR1 ("Error: String too long for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
}
pStr = str;
pStr += strlen(str) - 1;
for (i=0;i<(ST_INT)strlen(str);++i,--pStr)
{
if (strncmp(pStr, "0", 1) != 0 &&
strncmp(pStr, "1", 1) != 0)
{
SXLOG_NERR1 ("Error: Not a bitstring for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
if (strncmp(pStr, "1", 1) == 0)
{
*bits |= (1 << i);
}
}
*lenOut = strLen;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_string_ptr */
/************************************************************************/
ST_RET sx_get_string_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut, ST_INT *lenOut)
{
ST_INT vLen;
ST_RET rc;
rc = sx_get_entity (sxDecCtrl, sxDecCtrl->elemBuf, sizeof(sxDecCtrl->elemBuf), &vLen);
if (rc != SD_SUCCESS)
return (SD_FAILURE);
/* Convert to desired data format*/
sxDecCtrl->elemBuf[vLen] = 0;
*strOut = sxDecCtrl->elemBuf;
*lenOut = vLen;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_string_YesNo */
/*----------------------------------------------------------------------*/
/* This user helper function parses element value for the string */
/* "Yes"/"No" and sets the dest to SD_TRUE/SD_FALSE respectively. */
/* The string comparison is not case sensitive. */
/* Parameters: */
/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */
/* ST_BOOLEAN *dest pointer to dest to SD_TRUE/SD_FALSE */
/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/
/* in case of invalid element value, */
/* SX_ERR_CONVERT allows continue parsing. */
/* Return: */
/* SD_SUCCESS if function successful */
/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */
/* set to errCode. */
/************************************************************************/
ST_RET sx_get_string_YesNo (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest,
ST_RET errCode)
{
ST_RET rc;
ST_CHAR *str;
ST_INT strLen;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc == SD_SUCCESS)
{
if (stricmp (str, "Yes") == 0)
*dest = SD_TRUE;
else if (stricmp (str, "No") == 0)
*dest = SD_FALSE;
else
{
SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (Yes/No expected)",
sxDecCtrl->sxDecElInfo.tag, str);
sxDecCtrl->errCode = errCode;
rc = SD_FAILURE;
}
}
return (rc);
}
/************************************************************************/
/* sx_get_string_OnOff_mask */
/*----------------------------------------------------------------------*/
/* This user helper function parses element value for the string */
/* "On"/"Off" and sets/resets a maskBit in the mask. */
/* The string comparison is not case sensitive. */
/* Parameters: */
/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */
/* ST_UINT *mask pointer to mask to set/reset a bit */
/* ST_UINT maskBit mask bit to set/reset if ON/OFF found */
/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/
/* in case of invalid element value, */
/* SX_ERR_CONVERT allows continue parsing. */
/* Return: */
/* SD_SUCCESS if function successful */
/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */
/* set to errCode */
/************************************************************************/
ST_RET sx_get_string_OnOff_mask (SX_DEC_CTRL *sxDecCtrl, ST_UINT *mask,
ST_UINT maskBit, ST_RET errCode)
{
ST_RET rc;
ST_CHAR *str;
ST_INT strLen;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc == SD_SUCCESS)
{
if (stricmp (str, "On") == 0)
{
*mask |= maskBit; /* turn on this bit in the mask */
}
else if (stricmp (str, "Off") == 0)
{
*mask &= ~maskBit; /* turn off this bit in the mask */
}
else
{
SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (On/Off expected)",
sxDecCtrl->sxDecElInfo.tag, str);
sxDecCtrl->errCode = errCode;
rc = SD_FAILURE;
}
}
return (rc);
}
/************************************************************************/
/* sx_get_string_OnOff_bool */
/*----------------------------------------------------------------------*/
/* This user helper function parses element value for the string */
/* "On"/"Off" and sets the dest to SD_TRUE/SD_FALSE respectively. */
/* The string comparison is not case sensitive. */
/* Parameters: */
/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */
/* ST_BOOLEAN *dest pointer to dest to SD_TRUE/SD_FALSE */
/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/
/* in case of invalid element value, */
/* SX_ERR_CONVERT allows continue parsing. */
/* Return: */
/* SD_SUCCESS if function successful */
/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */
/* set to errCode */
/************************************************************************/
ST_RET sx_get_string_OnOff_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest,
ST_RET errCode)
{
ST_RET rc;
ST_CHAR *str;
ST_INT strLen;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc == SD_SUCCESS)
{
if (stricmp (str, "On") == 0)
*dest = SD_TRUE;
else if (stricmp (str, "Off") == 0)
*dest = SD_FALSE;
else
{
SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (On/Off expected)",
sxDecCtrl->sxDecElInfo.tag, str);
sxDecCtrl->errCode = errCode;
rc = SD_FAILURE;
}
}
return (rc);
}
/************************************************************************/
/* sx_get_time */
/************************************************************************/
ST_RET sx_get_time (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr)
{
ST_CHAR *str;
ST_RET rc;
time_t t;
ST_INT strLen;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
rc = tstrStringToTime (str, &t);
if (rc != SD_SUCCESS)
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
*out_ptr = t;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_tm */
/************************************************************************/
ST_RET sx_get_tm (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr)
{
ST_CHAR *str;
ST_RET rc;
ST_INT strLen;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
rc = tstrStringToTm (str, out_ptr);
if (rc != SD_SUCCESS)
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_tm_ex */
/************************************************************************/
ST_RET sx_get_tm_ex (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr, ST_LONG *microseconds)
{
ST_CHAR *str;
ST_RET rc;
ST_INT strLen;
ST_CHAR *strMicro = NULL; /* init to invalid value*/
char *periodLoc;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
periodLoc = strchr (str, '.');
if (periodLoc != NULL)
{
if ((periodLoc + 1) == '\0')
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
*periodLoc = '\0';
strMicro = periodLoc + 1;
}
rc = tstrStringToTm (str, out_ptr);
if (rc != SD_SUCCESS)
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
if (strMicro != NULL)
{
while (strlen(strMicro) < 6)
strcat (strMicro, "0");
while (strlen(strMicro) > 6)
strMicro[strlen(strMicro)-1] = '\0';
*microseconds = atol(strMicro);
}
else
*microseconds = 0;
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_duration */
/************************************************************************/
/* Store duration string found in an xml file into the structure */
/* "SX_DURATION". */
/************************************************************************/
ST_RET sx_get_duration (SX_DEC_CTRL *sxDecCtrl, SX_DURATION *sxDuration)
{
ST_CHAR *str;
ST_RET rc;
ST_INT strLen;
memset (sxDuration, 0, sizeof (*sxDuration));
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
rc = XmlStringToDuration (str, sxDuration);
if (rc != SD_SUCCESS)
{
SXLOG_NERR1 ("Error: String to Duration for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_xtime */
/************************************************************************/
/* Store date and time string found in an xml file into the structure */
/* "SX_DATE_TIME" specifying the number of seconds from */
/* 1/1/1970 (UTC time), the number of microseconds in a decimal */
/* fraction if it is specified and the number of minutes in the time */
/* zone offset if it is specified. */
/************************************************************************/
ST_RET sx_get_xtime (SX_DEC_CTRL *sxDecCtrl, SX_DATE_TIME *sxDateTime)
{
ST_CHAR *str;
ST_RET rc;
ST_INT strLen;
memset (sxDateTime, 0, sizeof (*sxDateTime));
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
/* convert input xml string to date and time */
/* store data in "SX_DATE_TIME" structure */
rc = XmlStringToUtcValue (str, sxDateTime);
if (rc != SD_SUCCESS)
{
SXLOG_NERR1 ("Error: String to Value date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* sx_get_time_ex */
/************************************************************************/
ST_RET sx_get_time_ex (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr, ST_LONG *microseconds)
{
ST_CHAR *str;
ST_CHAR strMicro[10];
char *periodLoc;
ST_RET rc;
time_t t;
ST_INT strLen;
strLen = 0;
rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen);
if (rc != SD_SUCCESS)
return (rc);
periodLoc = strchr (str, '.');
if (periodLoc != NULL)
{
if ((periodLoc + 1) == '\0')
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
strcpy(strMicro, periodLoc + 1);
*periodLoc = '\0';
}
rc = tstrStringToTime (str, &t);
if (rc != SD_SUCCESS)
{
SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag);
sxDecCtrl->errCode = SD_FAILURE;
return (rc);
}
*out_ptr = t;
if (periodLoc != NULL)
{
while (strlen(strMicro) < 6)
strcat (strMicro, "0");
while (strlen(strMicro) > 6)
strMicro[strlen(strMicro)-1] = '\0';
*microseconds = atol(strMicro);
}
else
*microseconds = 0;
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
#define MAX_BYTES_IN_CHUNK (2*SX_MAX_ELEM_LEN) /* MUST BE EVEN */
#define SX_LOAD_CHAR(a) {\
if (sxDecCtrl->useFp == SD_TRUE)\
{\
sx_load_characters (lineBuf, &eof, sxDecCtrl->fp, a);\
sxDecElInfo->entityStart-= a;\
sxDecElInfo->entityEnd-= a;\
}\
else\
{\
xml+= a;\
}\
}
#define SX_RIP_NOT_DONE (!sxDecCtrl->termFlag && (((sxDecCtrl->useFp == SD_FALSE) && (xml < xmlEnd)) || ((sxDecCtrl->useFp == SD_TRUE) && (*xml != '\0'))))
#define SX_RIP_DONE (sxDecCtrl->termFlag || ((sxDecCtrl->useFp == SD_FALSE) && (xml >= xmlEnd)) || ((sxDecCtrl->useFp == SD_TRUE) && (*xml == '\0')))
#if !defined(USE_EXPAT)
/************************************************************************/
/* sx_rip_xml */
/************************************************************************/
ST_RET sx_rip_xml (SX_DEC_CTRL *sxDecCtrl)
{
SX_DEC_ELEMENT_INFO *sxDecElInfo;
ST_CHAR *xml;
ST_INT nestLevel;
ST_CHAR *tagDest;
ST_CHAR *attribNameDest;
ST_CHAR *attribValDest;
ST_CHAR attribValCopy[SX_MAX_ATTR_VALUE];
ST_INT len;
ST_INT midBuff;
ST_INT numChRead;
ST_LONG xmlLen;
ST_CHAR *xmlEnd = NULL; /* init to avoid compiler warning */
ST_CHAR c;
ST_BOOLEAN bEmptyTag;
ST_BOOLEAN eof;
ST_BOOLEAN sawStartTag = SD_FALSE;
ST_CHAR lineBuf[MAX_BYTES_IN_CHUNK];
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
bEmptyTag = SD_FALSE;
if (sxDecCtrl->useFp == SD_TRUE)
{
memset (lineBuf, 0, MAX_BYTES_IN_CHUNK);
eof = SD_FALSE;
midBuff = MAX_BYTES_IN_CHUNK / 2;
/* get the first (MAX_BTYES_IN_CHUNK / 2) chunk from the file */
numChRead = fread(lineBuf + midBuff, 1, MAX_BYTES_IN_CHUNK - midBuff, sxDecCtrl->fp);
if (numChRead > 0)
xml = lineBuf + midBuff;
else
{
SXLOG_NERR0 ("SX decode error: could not read xml from file");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
}
else
{
sxDecElInfo = &sxDecCtrl->sxDecElInfo;
xml = sxDecCtrl->xmlStart;
xmlLen = sxDecCtrl->xmlLen;
xmlEnd = xml + xmlLen;
}
while (SX_RIP_NOT_DONE)
{
/* Find a begin or end tag */
while (*xml != '<' && SX_RIP_NOT_DONE)
SX_LOAD_CHAR (1);
if (SX_RIP_DONE)
break;
sawStartTag = SD_TRUE;
sxDecElInfo->tagStart = xml;
/* OK, this should be the start of a start tag, an end tag, or a comment */
/* or block of binary CDATA */
SX_LOAD_CHAR (1);
if (strncmp (xml, "!--", 3) == 0 || *xml == '?') /* Comment */
{
while (strncmp (xml, "-->", 3) != 0 &&
strncmp (xml, "?>", 2) != 0 &&
SX_RIP_NOT_DONE)
{
SX_LOAD_CHAR (1);
}
}
else if (strncmp (xml, "![CDATA[", 8) == 0) /* CDATA */
{
while (strncmp (xml, "]]>", 3) != 0 &&
SX_RIP_NOT_DONE)
{
SX_LOAD_CHAR (1);
}
}
else if (strncmp (xml, "!DOCTYPE", 8) == 0) /* DocType */
{
nestLevel = 0;
while (SD_TRUE)
{
if (*xml == '>')
{
if (nestLevel == 0)
break;
else
--nestLevel;
}
if (*xml == '<')
++nestLevel;
SX_LOAD_CHAR (1);
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find DOCTYPE end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
}
SX_LOAD_CHAR (1);
}
else if (*xml != '/') /* Begin tag */
{
/* We have a element tag start, get the tag first */
tagDest = sxDecElInfo->tag;
len = 0;
while (SX_RIP_NOT_DONE)
{
c = *xml;
if (c == '>' || c == ' ' || c == '/' || c == 10 || c == 9 || c == 13) /* Found the end of the tag */
break;
*(tagDest++) = c;
++len;
if (len >= SX_MAX_TAG_LEN)
{
SXLOG_NERR0 ("SX decode error: tag too long");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
if (sxDecCtrl->ignoreNS && c == ':')
{
tagDest = sxDecElInfo->tag;
len = 0;
}
}
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find tag end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
*tagDest = 0; /* terminate the tag */
/* Now look for attributes */
sxDecElInfo->attrCount = 0;
while (*xml != '>' && *xml != '/') /* we could have attributes! */
{
/* skip any whitespace before the start of the attribute name */
while (*xml == ' ' && SX_RIP_NOT_DONE)
SX_LOAD_CHAR (1);
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find attribute name");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
if (*xml != '>' && *xml != '/')
{
if (sxDecElInfo->attrCount >= SX_MAX_ATTRIB)
{
SXLOG_NERR0 ("SX decode error: too many attributes. Look at SX_MAX_ATTRIB define");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
/* This should be the start of an attribute name */
attribNameDest = sxDecElInfo->attr[sxDecElInfo->attrCount].name;
len = 0;
while (SX_RIP_NOT_DONE)
{
c = *xml;
if (c == '=' || c == ' ') /* Found the end of the name */
break;
if (c == '>') /* this isn't really an attribute like we first thought */
break;
if (c != 9 && c != 10 && c != 13) /* dont include these characters */
{
*(attribNameDest++) = c;
++len;
}
if (len >= SX_MAX_ATTR_NAME)
{
SXLOG_NERR0 ("SX decode error: attribute name too long");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
if (sxDecCtrl->ignoreNS && c == ':')
{
attribNameDest = sxDecElInfo->attr[sxDecElInfo->attrCount].name;
len = 0;
}
}
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find attribute name end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
if (*xml == '>') /* this isn't really an attribute like we first thought */
break;
*attribNameDest = 0; /* terminate the attrib name */
/* skip to the attribute '=' */
while (*xml != '=' && SX_RIP_NOT_DONE)
SX_LOAD_CHAR (1);
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find attribute '='");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
/* skip white space */
while ((*xml == ' ' || *xml == '\t') && SX_RIP_NOT_DONE)
SX_LOAD_CHAR (1);
/* OK, get the attrib value */
if (*(xml) != '"' && *(xml) != '\'') /* skip the opening " */
{
SXLOG_NERR0 ("SX decode error: could not find leading attribute value '\"'");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
/* At the start of the attribute value */
attribValDest = sxDecElInfo->attr[sxDecElInfo->attrCount].value;
len = 0;
while (SX_RIP_NOT_DONE)
{
c = *xml;
if (c == '"' || c == '\'') /* Found the end of the attrib */
break;
if (c != 9 && c != 10 && c != 13) /* dont include these characters */
{
*(attribValDest++) = c;
++len;
}
if (len >= SX_MAX_ATTR_VALUE)
{
SXLOG_NERR0 ("SX decode error: attribute value too long");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
}
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find closing attribute value '\"'");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
if (*(xml) != '"' && *(xml) != '\'') /* skip the closing " */
{
SXLOG_NERR0 ("SX decode error: could not find closing attribute value '\"'");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
*attribValDest = 0; /* terminate the attrib value */
strcpy (attribValCopy, sxDecElInfo->attr[sxDecElInfo->attrCount].value);
sx_format_string_dec (sxDecElInfo->attr[sxDecElInfo->attrCount].value, attribValCopy);
++sxDecElInfo->attrCount;
}
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find tag end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
}
/* Could be empty tag */
if (*xml == '/')
{
bEmptyTag = SD_TRUE;
while (*xml != '>')
SX_LOAD_CHAR (1);
}
SX_LOAD_CHAR (1); /* skip the '>' */
/* OK, now call the element start function */
sxDecElInfo->entityStart = xml;
sxDecElInfo->entityEnd = xml;
sxDecCtrl->xmlPos = xml; /* Save current dec position */
sxStartElement (sxDecCtrl);
/* Fail on any error except convert error */
if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT)
{
return (SD_FAILURE);
}
if (bEmptyTag)
{
/* OK, now call the element end function */
sxEndElement (sxDecCtrl);
bEmptyTag = SD_FALSE;
}
SX_LOAD_CHAR (sxDecCtrl->xmlPos - xml);
sxDecCtrl->xmlPos = xml; /* Save current dec position */
}
else /* End tag */
{
sxDecElInfo->entityEnd = xml - 1;
SX_LOAD_CHAR (1);
tagDest = sxDecElInfo->tag;
len = 0;
while (SX_RIP_NOT_DONE)
{
c = *xml;
if (c == '>' || c == ' ') /* Found the end of the tag */
break;
*(tagDest++) = c;
++len;
if (len >= SX_MAX_TAG_LEN)
{
SXLOG_NERR0 ("SX decode error: tag too long");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
if (sxDecCtrl->ignoreNS && c == ':')
{
tagDest = sxDecElInfo->tag;
len = 0;
}
}
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find tag end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
*tagDest = 0; /* terminate the tag */
/* any white space up to the end of the tag name */
while (*xml != '>' && SX_RIP_NOT_DONE)
SX_LOAD_CHAR (1);
if (SX_RIP_DONE)
{
SXLOG_NERR0 ("SX decode error: could not find tag end");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
SX_LOAD_CHAR (1);
sxDecCtrl->xmlPos = xml; /* Save current dec position */
/* OK, now call the element end function */
sxEndElement (sxDecCtrl);
/* Fail on any error except convert error */
if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT)
{
return (SD_FAILURE);
}
}
}
if (!sawStartTag)
{
SXLOG_ERR0 ("SX decode error: could not find start tag");
sxDecCtrl->errCode = SD_FAILURE;
return (SD_FAILURE);
}
else
return (SD_SUCCESS);
}
ST_VOID sx_load_characters (ST_CHAR *lineBuf, ST_BOOLEAN *eof, FILE *fp, ST_INT numToRead)
{
ST_LONG numChRead;
ST_LONG i;
if (numToRead > 0)
{
/* first shift the characters by numToRead */
memmove (lineBuf, &lineBuf[numToRead], MAX_BYTES_IN_CHUNK - numToRead);
if (*eof != SD_TRUE)
{
numChRead = fread(lineBuf + (MAX_BYTES_IN_CHUNK - numToRead), 1, numToRead, fp);
if (numChRead == 0)
{
*eof = SD_TRUE;
for (i = 1; i < numToRead + 1; i++)
{
lineBuf[MAX_BYTES_IN_CHUNK - i] = '\0';
}
}
}
}
}
#else /* USE_EXPAT */
/************************************************************************/
/* expatHandlerStart */
/* Normal 'start tag' handler. */
/* Log and set "errCode" if any string is too long to be stored. */
/************************************************************************/
static void XMLCALL expatHandlerStart(void *userData, const char *el, const char **attr)
{
SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData;
int i;
const ST_CHAR *ptr;
if (!sxDecCtrl->termFlag)
{
/* Copy tag to sxDecCtrl */
/* If ignoreNS flag set, ignore namespace prefix on tag. */
if (sxDecCtrl->ignoreNS)
{
/* If ':' in the string, copy only text after ':' */
if ((ptr = strrchr (el, ':')) != NULL)
ptr += 1; /* point after ':' */
else
ptr = el;
}
else
ptr = el;
if (strlen (ptr) < SX_MAX_TAG_LEN)
strcpy (sxDecCtrl->sxDecElInfo.tag, ptr);
else
{
SXLOG_ERR1 ("start tag '%s' too long. Can't be stored.", ptr);
sxDecCtrl->errCode = SD_FAILURE;
}
/* Copy attributes to sxDecCtrl */
for (i = 0; attr[i]; i += 2)
{
if (strlen (attr[i]) < SX_MAX_ATTR_NAME)
strcpy (sxDecCtrl->sxDecElInfo.attr[i/2].name, attr[i]);
else
{
SXLOG_ERR1 ("attr name '%s' too long. Can't be stored.", ptr);
sxDecCtrl->errCode = SD_FAILURE;
}
if (strlen (attr[i+1]) < SX_MAX_ATTR_VALUE)
strcpy (sxDecCtrl->sxDecElInfo.attr[i/2].value, attr[i+1]);
else
{
SXLOG_ERR1 ("attr value '%s' too long. Can't be stored.", ptr);
sxDecCtrl->errCode = SD_FAILURE;
}
}
sxDecCtrl->sxDecElInfo.attrCount = i/2;
sxDecCtrl->entityLen = 0; /* reset entityLen */
sxStartElement (sxDecCtrl);
} /* !termFlag */
}
/************************************************************************/
/* expatHandlerEnd */
/* Normal 'end tag' handler. */
/************************************************************************/
static void XMLCALL expatHandlerEnd(void *userData, const char *el)
{
SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData;
if (!sxDecCtrl->termFlag)
{
strcpy (sxDecCtrl->sxDecElInfo.tag, el);
sxEndElement (sxDecCtrl);
sxDecCtrl->entityLen = 0; /* reset entityLen */
} /* !termFlag */
}
/************************************************************************/
/* expatHandlerData */
/* Normal data handler. */
/* Log and set "errCode" if data is too long to be stored. */
/************************************************************************/
static void XMLCALL expatHandlerData(void *userData,
const XML_Char *s,
int len)
{
SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData;
ST_INT sizeNeeded; /* buffer size needed to store this data */
if (!sxDecCtrl->termFlag)
{
sizeNeeded = len + sxDecCtrl->entityLen;
/* Save data to access with "sx_get_entity" later. */
if (sizeNeeded > sxDecCtrl->entityBufSize)
{
/* Reallocate buffer twice as big as currently needed. */
sxDecCtrl->entityBufSize = sizeNeeded * 2;
SXLOG_FLOW1 ("entity buffer too small. Reallocating entity buffer size = %d", sxDecCtrl->entityBufSize);
sxDecCtrl->entityBuf = chk_realloc (sxDecCtrl->entityBuf, sxDecCtrl->entityBufSize);
}
memcpy (&(sxDecCtrl->entityBuf [sxDecCtrl->entityLen]), s, len);
sxDecCtrl->entityLen += len;
} /* !termFlag */
}
/************************************************************************/
/* expatHandlerStartSkip */
/* The 'start tag' handler when tags are being skipped. */
/************************************************************************/
static void XMLCALL expatHandlerStartSkip(void *userData, const char *el, const char **attr)
{
SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData;
if (!sxDecCtrl->termFlag)
{
/* Not calling normal start funct, so must increment nest level here*/
sxDecCtrl->xmlNestLevel++;
} /* !termFlag */
}
/************************************************************************/
/* expatHandlerEndSkip */
/* The 'end tag' handler when tags are being skipped. */
/************************************************************************/
static void XMLCALL expatHandlerEndSkip(void *userData, const char *el)
{
SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData;
if (!sxDecCtrl->termFlag)
{
if (sxDecCtrl->xmlNestLevel == sxDecCtrl->skipNestLevel)
{
SXLOG_DEC1 ("End element '%s' (contents skipped)", el);
/* Go back to normal handlers. */
XML_SetCharacterDataHandler(sxDecCtrl->parser, expatHandlerData);
XML_SetElementHandler(sxDecCtrl->parser, expatHandlerStart, expatHandlerEnd);
}
/* Not calling normal end funct, so must decrement nest level here*/
sxDecCtrl->xmlNestLevel--;
} /* !termFlag */
}
/************************************************************************/
/* setup_expat */
/* NOTE: If "sxDecCtrl->termFlag" is set by user (i.e. error found), */
/* let parse complete, but ignore data (see "expatHandler*"). */
/************************************************************************/
static XML_Parser setup_expat(SX_DEC_CTRL *sxDecCtrl)
{
XML_Parser parser = XML_ParserCreate(NULL);
if (! parser)
{
SXLOG_ERR0 ("Couldn't allocate memory for XML parser");
return (parser);
}
XML_SetUserData (parser, sxDecCtrl); /* passes sxDecCtrl to handlers */
XML_SetCharacterDataHandler(parser, expatHandlerData);
XML_SetElementHandler(parser, expatHandlerStart, expatHandlerEnd);
sxDecCtrl->parser = parser; /* CRITICAL: save parser to use in callbacks*/
return (parser);
}
/************************************************************************/
/* sx_rip_xml_file */
/* Parse XML from a file. The caller must open a file */
/* and store the file ptr in "sxDecCtrl->fp". It reads one segment */
/* at a time from the file and passes it to XML_Parse. */
/************************************************************************/
ST_RET sx_rip_xml_file (SX_DEC_CTRL *sxDecCtrl)
{
XML_Parser parser; /* Expat parser control structure */
ST_RET retcode = SD_SUCCESS;
char *parseBuf; /* temporary buffer to store text read from input file */
if (!(parser = setup_expat (sxDecCtrl)))
retcode = SD_FAILURE; /* error already logged in setup_expat */
else
{
/* Allocate a reasonable size entity buffer. */
/* This may be reallocated later if it is too small. */
sxDecCtrl->entityBufSize = ENTITY_BUF_SIZE;
sxDecCtrl->entityBuf = chk_malloc (sxDecCtrl->entityBufSize);
parseBuf = chk_malloc (EXPAT_BUF_SIZE);
/* In a loop, read the file one segment at a time & pass to parser. */
for (;;)
{
int done;
int len;
len = fread(parseBuf, 1, EXPAT_BUF_SIZE, sxDecCtrl->fp);
if (ferror(sxDecCtrl->fp))
{
fprintf(stderr, "Read error\n");
retcode = SD_FAILURE;
break; /* stop now */
}
done = feof(sxDecCtrl->fp);
if (XML_Parse(parser, parseBuf, len, done) == XML_STATUS_ERROR)
{
SXLOG_ERR2 ("XML parse error at line %d: %s\n",
XML_GetCurrentLineNumber(parser),
XML_ErrorString(XML_GetErrorCode(parser)));
retcode = SD_FAILURE;
break; /* stop now */
}
if (done)
break;
} /* end main loop */
chk_free (parseBuf);
chk_free (sxDecCtrl->entityBuf);
}
return (retcode);
}
/************************************************************************/
/* sx_rip_xml_mem */
/* Parse XML from a memory buffer. The caller must set */
/* the following members of sxDecCtrl before calling this function: */
/* sxDecCtrl->xmlStart points to the buffer. */
/* sxDecCtrl->xmlLen contains the length of the buffer. */
/* It simply sets up the parse and passes the buffer to XML_Parse. */
/************************************************************************/
ST_RET sx_rip_xml_mem (SX_DEC_CTRL *sxDecCtrl)
{
XML_Parser parser; /* Expat parser control structure */
int done = SD_TRUE; /* indicates to parser that all data is being passed*/
ST_RET retcode = SD_SUCCESS;
if (!(parser = setup_expat (sxDecCtrl)))
retcode = SD_FAILURE; /* error already logged in setup_expat */
else
{
/* Allocate a reasonable size entity buffer. */
/* This may be reallocated later if it is too small. */
sxDecCtrl->entityBufSize = ENTITY_BUF_SIZE;
sxDecCtrl->entityBuf = chk_malloc (sxDecCtrl->entityBufSize);
/* Just pass data all at once to XML_Parse. */
if (XML_Parse(parser, sxDecCtrl->xmlStart, sxDecCtrl->xmlLen, done) == XML_STATUS_ERROR)
{
SXLOG_ERR2 ("XML parse error at line %d: %s\n",
XML_GetCurrentLineNumber(parser),
XML_ErrorString(XML_GetErrorCode(parser)));
retcode = SD_FAILURE;
}
chk_free (sxDecCtrl->entityBuf);
}
return (retcode);
}
#endif /* USE_EXPAT */