/**************************************************************************
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
*** ***
*** This software is property of TransNexus, Inc. ***
*** This software is freely available under license from TransNexus. ***
*** The license terms and conditions for free use of this software by ***
*** third parties are defined in the OSP Toolkit Software License ***
*** Agreement (LICENSE.txt). Any use of this software by third ***
*** parties, which does not comply with the terms and conditions of the ***
*** OSP Toolkit Software License Agreement is prohibited without ***
*** the prior, express, written consent of TransNexus, Inc. ***
*** ***
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
*** suggestions or feedback to support@transnexus.com ***
*** ***
**************************************************************************/
/*
* osptoken.c - OSP token functions
*/
#include "osp/osp.h"
#include "osp/osperrno.h"
#include "osp/osplist.h"
#include "osp/ospxmldoc.h"
#include "osp/ospxmlattr.h"
#include "osp/ospxmlelem.h"
#include "osp/ospmsgattr.h"
#include "osp/ospmsgelem.h"
#include "osp/osptoken.h"
#include "osp/ospmsg.h"
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenNew() - create a new token object
*-----------------------------------------------------------------------*/
OSPTTOKEN * /* returns ptr to token or null */
OSPPTokenNew(
unsigned ospvLen, /* size of token */
const unsigned char *ospvValue /* token value */
)
{
OSPTTOKEN *ospvToken = OSPC_OSNULL;
unsigned char *valptr;
/*
* Token objects are actually two parts -- the first is the Token
* structure and the second is the token value. The two parts are
* contiguous in memory, and are created (and destroyed) at the same
* time. Here's a rough picture:
*
* Memory:
* +--------+
* | | This part is the structure itself. It's actually
* | | visible to the functions (and macros).
* +--------+
* | |
* | | This part contains the actual value. It's not directly
* | | accessible, but pointers to the value within
* | | the structure are set to point to it.
* +--------+
*
* We do it this way to conveniently manage variable size tokens
* If we put the value in a visible part of the structure,
* then we'd have to define that field, and that would require
* defining a size for it. Since we can't predict the size of
* token values , picking the size for the structure would be pretty
* difficult.
*
* Note that this technique does use dynamic memory allocation.
* If memory fragmentation is a concern, one possible optimization
* would be to define a pool of Token objects in which the name and
* value sizes were fixed to some reasonable size. Then you could
* allocate from the pool in most cases, and fall back to this
* approach only if the name/value was too big for the pool objects
* (or, perhaps, if the pool was empty).
*/
if (ospvLen > 0)
{
if (ospvValue != OSPC_OSNULL)
{
/* try to allocate the memory for the entire object */
OSPM_MALLOC(ospvToken, OSPTTOKEN,sizeof(OSPTTOKEN) + ospvLen + 1);
/* make sure the allocation succeeded before proceeding */
if (ospvToken != OSPC_OSNULL)
{
/* calculate where the "hidden" values will go */
valptr = ((unsigned char *)ospvToken) + sizeof(OSPTTOKEN);
/* copy the values into their hidden location */
OSPM_MEMCPY(valptr, ospvValue, ospvLen);
/* fill in the structure fields */
OSPPListLinkNew(&(ospvToken->ospmTokenLink));
ospvToken->ospmTokenLen = ospvLen;
ospvToken->ospmTokenVal = valptr;
ospvToken->ospmTokenVal[ospvLen] = '\0';
}
}
}
return(ospvToken);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenFromElement() - create a token from an XML element
*-----------------------------------------------------------------------*/
unsigned /* returns error code */
OSPPTokenFromElement(
OSPTXMLELEM *ospvElem, /* input is XML element */
OSPTTOKEN **ospvToken /* where to put token pointer */
)
{
unsigned ospvErrCode = OSPC_ERR_NO_ERROR;
unsigned char *tokenValue = OSPC_OSNULL;
unsigned tokenLen = 0;
/* start by assuming we will fail */
*ospvToken = OSPC_OSNULL;
if (ospvElem == OSPC_OSNULL)
{
ospvErrCode = OSPC_ERR_XML_NO_ELEMENT;
}
if (ospvToken == OSPC_OSNULL)
{
ospvErrCode = OSPC_ERR_DATA_NO_TOKEN;
}
if (OSPPMsgGetElemPart(OSPPXMLElemGetName(ospvElem)) !=
ospeElemToken)
{
ospvErrCode = OSPC_ERR_DATA_INVALID_TYPE;
}
if (ospvErrCode == OSPC_ERR_NO_ERROR)
{
ospvErrCode = OSPPMsgBinFromElement(ospvElem, &tokenLen, &tokenValue);
}
/* create the Token structure */
if (ospvErrCode == OSPC_ERR_NO_ERROR)
{
*ospvToken = OSPPTokenNew(tokenLen, tokenValue);
if (*ospvToken == OSPC_OSNULL)
{
ospvErrCode = OSPC_ERR_DATA_NO_TOKEN;
}
}
if(tokenValue != OSPC_OSNULL)
{
OSPM_FREE(tokenValue);
}
return(ospvErrCode);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenDelete() - destroy a token object
*-----------------------------------------------------------------------*/
void /* no return */
OSPPTokenDelete(
OSPTTOKEN **ospvToken /* Token to destroy */
)
{
if (*ospvToken != OSPC_OSNULL)
{
OSPM_FREE(*ospvToken);
*ospvToken = OSPC_OSNULL;
}
}
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenGetSize() - returns size of token value
*-----------------------------------------------------------------------*/
unsigned
OSPPTokenGetSize(
OSPTTOKEN *ospvToken
)
{
unsigned ospvSize = 0;
if (ospvToken != OSPC_OSNULL)
{
ospvSize = ospvToken->ospmTokenLen;
}
return(ospvSize);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenGetValue() - returns pointer to token value
*-----------------------------------------------------------------------*/
const unsigned char *
OSPPTokenGetValue(
OSPTTOKEN *ospvToken
)
{
const unsigned char *ospvVal = OSPC_OSNULL;
if (ospvToken != OSPC_OSNULL)
{
ospvVal = ospvToken->ospmTokenVal;
}
return(ospvVal);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPTokenToElement() - create an XML element from a token
*-----------------------------------------------------------------------*/
unsigned /* returns error code */
OSPPTokenToElement(
OSPTTOKEN *ospvToken, /* token */
OSPTXMLELEM **ospvElem /* where to put XML element pointer */
)
{
unsigned ospvErrCode = OSPC_ERR_NO_ERROR;
if (ospvElem == OSPC_OSNULL)
{
ospvErrCode = OSPC_ERR_XML_NO_ELEMENT;
}
if (ospvToken == OSPC_OSNULL)
{
ospvErrCode = OSPC_ERR_DATA_NO_TOKEN;
}
if (ospvErrCode == OSPC_ERR_NO_ERROR)
{
ospvErrCode = OSPPMsgBinToElement(OSPPTokenGetSize(ospvToken),
(unsigned char *) OSPPTokenGetValue(ospvToken),
(const unsigned char *)OSPPMsgGetElemName(ospeElemToken),
ospvElem, OSPC_TRUE);
}
return(ospvErrCode);
}