/*******************************************************************

Copyright (c) 2004 Open Mobile Alliance, Ltd.  All Rights Reserved.

This software is made available under the usage and distribution terms 
covered by the Common Public License 1.0 and by using this software you
are bound by the terms and conditions of the same.

EXCEPT AS EXPRESSLY SET FORTH IN THE COMMON PUBLIC LICENSE,
THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 
ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   
Each recipient is solely responsible for determining the 
appropriateness of using and distributing this program and assumes 
all risks associated with its exercise of rights under the Common 
Public License, including but not limited to the risks and 
costs of program errors, compliance with applicable laws, 
damage to or loss of data, programs or equipment, and 
unavailability or interruption of operations.

********************************************************************/
/*************************************************************************/
/* module:          Definition of WBXML/XML tags for the en-/decoder     */
/* file:            XLTTags.c                                            */
/* target system:   all                                                  */
/* target OS:       all                                                  */   
/*************************************************************************/

#include "xlttags.h"

#include <libstr.h>
#include <smlerr.h>
#include <libmem.h>
#include <libutil.h>
#include <mgr.h>

#include "xltmetinf.h"
#include "xltdevinf.h"
#include "xlttagtbl.h"


/* local prototypes */
TagPtr_t getTagTable(SmlPcdataExtension_t ext);
//SmlPcdataExtension_t   getByName(String_t ns);
DtdPtr_t getDtdTable();

/**
 * FUNCTION: getDtdTable
 *
 * Returns a copy of the table containing all known (sub) dtd's
 * On error a NULL pointer is returned
 */
DtdPtr_t getDtdTable() {
	DtdPtr_t _tmpPtr;
	Dtd_t XltDtdTbl[] = {
        /*
         * Change to support DM 1.2. 
         */
		{ "SYNCML:SYNCML1.2", SML_EXT_UNDEFINED},
		{ "syncml:dmddf1.2",  SML_EXT_TNDS},
		{ "syncml:metinf",    SML_EXT_METINF},
        { "syncml:devinf",    SML_EXT_DEVINF},
		{ NULL,               SML_EXT_LAST}
	};

	_tmpPtr = NULL; 
	_tmpPtr = (DtdPtr_t)smlLibMalloc(sizeof(XltDtdTbl));
	if (_tmpPtr == NULL) return NULL;
	smlLibMemcpy(_tmpPtr, &XltDtdTbl, sizeof(XltDtdTbl));
	return _tmpPtr;
}


/**
 * FUNCTION: getExtName
 *
 * Returns the official name for a given extention/sub-DTD
 * and stored it in 'name'. If not found name isn't modified
 */
Ret_t getExtName(SmlPcdataExtension_t ext, String_t *name) {
	DtdPtr_t dtdhead = getDtdTable();
	DtdPtr_t dtd = dtdhead;
	if (!dtdhead) return -1;
	for (;dtd->ext != SML_EXT_LAST; dtd++) {
		if (!dtd->name) continue; /* skip empty names (should not appear but better be on the safe side) */
		if (dtd->ext == ext) {
			String_t _tmp = smlLibMalloc(smlLibStrlen(dtd->name)+1);
			if (!_tmp) {
				smlLibFree(dtdhead);
				return SML_ERR_NOT_ENOUGH_SPACE;
			}
			smlLibStrcpy(_tmp, dtd->name);
			smlLibFree(dtdhead);
			*name = _tmp;			
			return SML_ERR_OK;
		}
	}
	smlLibFree(dtdhead);
	return -1;
}

/**
 * FUNCTION: getCpByName
 *
 * Returns the codepage constant assoziated with the name stored in 'ns'
 *
 * RETURN:             a SmlPcdataExtension_t representing the corresponding codepage id.
 *                     If no corresponding codepage is found -1 is returned.
 */
SmlPcdataExtension_t getExtByName(String_t ns) {
	DtdPtr_t dtdhead = getDtdTable();
	DtdPtr_t dtd = dtdhead;
	SmlPcdataExtension_t ext = (SmlPcdataExtension_t) 255;
	if (!dtdhead) return SML_EXT_UNDEFINED;
	for (;dtd->ext != SML_EXT_LAST; dtd++) {
		if (!dtd->name) continue; /* skip empty names (should not appear but better be on the safe side) */
		if (smlLibStrcmp(dtd->name,ns) == 0) {
			ext = dtd->ext;
			break;
		}
	}
	smlLibFree(dtdhead);
	return ext;
}



/* if the commands are not defined we let the functions point to NULL */
#ifndef RESULT_RECEIVE
#define buildResults NULL
#endif

#ifndef MAP_RECEIVE
#define buildMap NULL
#endif

#ifndef EXEC_RECEIVE
#define buildExec NULL
#endif

#if !defined(ATOM_RECEIVE) && !defined(SEQUENCE_RECEIVE)
#define buildAtomOrSeq NULL
#endif

#ifndef SEARCH_RECEIVE
#define buildSearch NULL
#endif


/**
 * FUNCTION: getTagTable
 *
 * Returns the tag table - this function is used to avoid a global
 * tag table variable
 *
 * RETURN:             a pointer to the tag table containing tag ids, 
 *                     codepages, wbxml tags and xml tags
 */
/* T.K. initialized the structure via _TOKEN Macro, to take
 * out the XML name tags when not compiled with XML support.
 * In addtion removed the (unused) pointer for the build functions 
 */
#ifdef __SML_XML__
#define _TOKEN(id, wbxml, xml) (id), (wbxml), (xml)
#else
#define _TOKEN(id, wbxml, xml) (id), (wbxml), ""
#endif
TagPtr_t getTagTable(SmlPcdataExtension_t ext)
{
    int mySize = 0;
    TagPtr_t _tmpTagPtr;
    SyncMLInfoPtr_t pGA = NULL;
    /* standard SyncML codepage */
    static const Tag_t syncml[] =
    {
        { _TOKEN(TN_ADD,            0x05,    "Add")},
        { _TOKEN(TN_ALERT,          0x06,    "Alert")},
        { _TOKEN(TN_ARCHIVE,        0x07,    "Archive")},
        { _TOKEN(TN_ATOMIC,         0x08,    "Atomic")},
        { _TOKEN(TN_CHAL,           0x09,    "Chal")},
        { _TOKEN(TN_CMD,            0x0A,    "Cmd")},
        { _TOKEN(TN_CMDID,          0x0B,    "CmdID")},
        { _TOKEN(TN_CMDREF,         0x0C,    "CmdRef")},
        { _TOKEN(TN_COPY,           0x0D,    "Copy")},
        { _TOKEN(TN_CRED,           0x0E,    "Cred")},
        { _TOKEN(TN_DATA,           0x0F,    "Data")},
        { _TOKEN(TN_DELETE,         0x10,    "Delete")},
        { _TOKEN(TN_EXEC,           0x11,    "Exec")},
        { _TOKEN(TN_FINAL,          0x12,    "Final")},
        { _TOKEN(TN_GET,            0x13,    "Get")},
        { _TOKEN(TN_ITEM,           0x14,    "Item")},
        { _TOKEN(TN_LANG,           0x15,    "Lang")},
        { _TOKEN(TN_LOCNAME,        0x16,    "LocName")},
        { _TOKEN(TN_LOCURI,         0x17,    "LocURI")},
        { _TOKEN(TN_MAP,            0x18,    "Map")},
        { _TOKEN(TN_MAPITEM,        0x19,    "MapItem")},
        { _TOKEN(TN_META,           0x1A,    "Meta")},
        { _TOKEN(TN_MSGID,          0x1B,    "MsgID")},
        { _TOKEN(TN_MSGREF,         0x1C,    "MsgRef")},
        { _TOKEN(TN_NORESP,         0x1D,    "NoResp")},
        { _TOKEN(TN_NORESULTS,      0x1E,    "NoResults")},
        { _TOKEN(TN_PUT,            0x1F,    "Put")},
        { _TOKEN(TN_REPLACE,        0x20,    "Replace")},
        { _TOKEN(TN_RESPURI,        0x21,    "RespURI")},
        { _TOKEN(TN_RESULTS,        0x22,    "Results")},
        { _TOKEN(TN_SEARCH,         0x23,    "Search")},
        { _TOKEN(TN_SEQUENCE,       0x24,    "Sequence")},
        { _TOKEN(TN_SESSIONID,      0x25,    "SessionID")},
        { _TOKEN(TN_SFTDEL,         0x26,    "SftDel")},
        { _TOKEN(TN_SOURCE,         0x27,    "Source")},
        { _TOKEN(TN_SOURCEREF,      0x28,    "SourceRef")},
        { _TOKEN(TN_STATUS,         0x29,    "Status")},
        { _TOKEN(TN_SYNC,           0x2A,    "Sync")},
        { _TOKEN(TN_SYNCBODY,       0x2B,    "SyncBody")},
        { _TOKEN(TN_SYNCHDR,        0x2C,    "SyncHdr")},
        { _TOKEN(TN_SYNCML,         0x2D,    "SyncML")},
        { _TOKEN(TN_TARGET,         0x2E,    "Target")},
        { _TOKEN(TN_TARGETREF,      0x2F,    "TargetRef")},
        { _TOKEN(TN_VERSION,        0x31,    "VerDTD")},
        { _TOKEN(TN_PROTO,          0x32,    "VerProto")},
        { _TOKEN(TN_NUMBEROFCHANGES,0x33,    "NumberOfChanges")},
		{ _TOKEN(TN_MOREDATA,       0x34,    "MoreData")},
        { _TOKEN(TN_CORRELATOR,     0x3C,    "Correlator")},
        { _TOKEN(TN_UNDEF,          0x00,    NULL)}
      };

#ifdef __USE_METINF__
	static const Tag_t metinf[] =  {
        { _TOKEN(TN_METINF_ANCHOR,      0x05,	"Anchor")},
        { _TOKEN(TN_METINF_EMI,		    0x06,   "EMI")},
        { _TOKEN(TN_METINF_FORMAT,		0x07,	"Format")},
        { _TOKEN(TN_METINF_FREEID,		0x08,	"FreeID")},
        { _TOKEN(TN_METINF_FREEMEM,	    0x09,	"FreeMem")},
        { _TOKEN(TN_METINF_LAST,     	0x0A,	"Last")},
        { _TOKEN(TN_METINF_MARK,		0x0B,	"Mark")},
        { _TOKEN(TN_METINF_MAXMSGSIZE,	0x0C,	"MaxMsgSize")},
		/* SCTSTK - 18/03/2002 : SyncML 1.1 */
        { _TOKEN(TN_METINF_MAXOBJSIZE,	0x15,	"MaxObjSize")},
        { _TOKEN(TN_METINF_MEM,		    0x0D,	"Mem")},
        { _TOKEN(TN_METINF_METINF,		0x0E,	"MetInf")},
        { _TOKEN(TN_METINF_NEXT,		0x0F,	"Next")},
        { _TOKEN(TN_METINF_NEXTNONCE,	0x10,	"NextNonce")},
        { _TOKEN(TN_METINF_SHAREDMEM,	0x11,	"SharedMem")},
        { _TOKEN(TN_METINF_SIZE,		0x12,	"Size")},
        { _TOKEN(TN_METINF_TYPE,		0x13,	"Type")},
        { _TOKEN(TN_METINF_VERSION,	    0x14,	"Version")},

        { _TOKEN(TN_UNDEF,				0x00,	NULL)}
	};
#endif


#ifdef __USE_DEVINF__
    static const Tag_t devinf[] = {
        {_TOKEN(TN_DEVINF_CTCAP,       0x05,   "CTCap")},
        {_TOKEN(TN_DEVINF_CTTYPE,      0x06,   "CTType")},
        {_TOKEN(TN_DEVINF_DATASTORE,   0x07,   "DataStore")},
        {_TOKEN(TN_DEVINF_DATATYPE,    0x08,   "DataType")},
        {_TOKEN(TN_DEVINF_DEVID,       0x09,   "DevID")},
        {_TOKEN(TN_DEVINF_DEVINF,      0x0A,   "DevInf")},
        {_TOKEN(TN_DEVINF_DEVTYP,      0x0B,   "DevTyp")},
        {_TOKEN(TN_DEVINF_DISPLAYNAME, 0x0C,   "DisplayName")},
        {_TOKEN(TN_DEVINF_DSMEM,       0x0D,   "DSMem")},
        {_TOKEN(TN_DEVINF_EXT,         0x0E,   "Ext")},
        {_TOKEN(TN_DEVINF_FWV,         0x0F,   "FwV")},
        {_TOKEN(TN_DEVINF_HWV,         0x10,   "HwV")},
        {_TOKEN(TN_DEVINF_MAN,         0x11,   "Man")},
        {_TOKEN(TN_DEVINF_MAXGUIDSIZE, 0x12,   "MaxGUIDSize")},
        {_TOKEN(TN_DEVINF_MAXID,       0x13,   "MaxID")},
        {_TOKEN(TN_DEVINF_MAXMEM,      0x14,   "MaxMem")},
        {_TOKEN(TN_DEVINF_MOD,         0x15,   "Mod")},
        {_TOKEN(TN_DEVINF_OEM,         0x16,   "OEM")},
        {_TOKEN(TN_DEVINF_PARAMNAME,   0x17,   "ParamName")},
        {_TOKEN(TN_DEVINF_PROPNAME,    0x18,   "PropName")},
        {_TOKEN(TN_DEVINF_RX,          0x19,   "Rx")},
        {_TOKEN(TN_DEVINF_RXPREF,      0x1A,   "Rx-Pref")},
        {_TOKEN(TN_DEVINF_SHAREDMEM,   0x1B,   "SharedMem")},
        {_TOKEN(TN_DEVINF_SIZE,        0x1C,   "Size")},
        {_TOKEN(TN_DEVINF_SOURCEREF,   0x1D,   "SourceRef")},
        {_TOKEN(TN_DEVINF_SWV,         0x1E,   "SwV")},
        {_TOKEN(TN_DEVINF_SYNCCAP,     0x1F,   "SyncCap")},
        {_TOKEN(TN_DEVINF_SYNCTYPE,    0x20,   "SyncType")},
        {_TOKEN(TN_DEVINF_TX,          0x21,   "Tx")},
        {_TOKEN(TN_DEVINF_TXPREF,      0x22,   "Tx-Pref")},
        {_TOKEN(TN_DEVINF_VALENUM,     0x23,   "ValEnum")},
        {_TOKEN(TN_DEVINF_VERCT,       0x24,   "VerCT")},
        {_TOKEN(TN_DEVINF_VERDTD,      0x25,   "VerDTD")},
        {_TOKEN(TN_DEVINF_XNAM,        0x26,   "XNam")},
        {_TOKEN(TN_DEVINF_XVAL,        0x27,   "XVal")},
		/* SCTSTK - 18/03/2002 : SyncML 1.1 */
        {_TOKEN(TN_DEVINF_UTC,         0x28,   "UTC")},
        {_TOKEN(TN_DEVINF_NOFM,        0x29,   "SupportNumberOfChanges")},
        {_TOKEN(TN_DEVINF_LARGEOBJECT, 0x2A,   "SupportLargeObjs")},
        { _TOKEN(TN_UNDEF,			   0x00,	NULL)}
    };
#endif

    /*
     * Change to support TNDS. 
     */
    static const Tag_t tnds[] = {
        { _TOKEN(TN_TNDS_SYNCML,             0x2D,    "SyncML")},
        { _TOKEN(TN_TNDS_TREE,               0x20,    "MgmtTree")},
        { _TOKEN(TN_TNDS_MAN,                0x1F,    "Man")},
        { _TOKEN(TN_TNDS_MODE,               0x22,    "Mode")},
    	{ _TOKEN(TN_TNDS_VERSION,            0x37,    "VerDTD")},
        { _TOKEN(TN_TNDS_NODE,               0x24,    "Node")},
        { _TOKEN(TN_TNDS_NODENAME,           0x26,    "NodeName")},
        { _TOKEN(TN_TNDS_NODETITLE,          0x33,    "Title")},
        { _TOKEN(TN_TNDS_NODEPATH,           0x2c,    "Path")},
        { _TOKEN(TN_TNDS_NODESIZE,           0x31,    "Size")},
        { _TOKEN(TN_TNDS_NODEVALUE,          0x36,    "Value")},
        { _TOKEN(TN_TNDS_NODERTPROPERTIES,   0x2F,    "RTProperties")},
        { _TOKEN(TN_TNDS_RTACL,              0x06,    "ACL")},
        { _TOKEN(TN_TNDS_RTFORMAT,           0x1C,    "Format")},
        { _TOKEN(TN_TNDS_RTTSTAMP,           0x34,    "TStamp")},
        { _TOKEN(TN_TNDS_RTTYPE,             0x35,    "Type")},
        { _TOKEN(TN_TNDS_RTVERNO,            0x38,    "VerNo")},
        { _TOKEN(TN_TNDS_FMTCHR,             0x0B,    "chr")},
        { _TOKEN(TN_TNDS_FMTNODE,            0x25,    "node")},
        { _TOKEN(TN_TNDS_FMTNULL,            0x27,    "null")},
        { _TOKEN(TN_TNDS_FMTBIN,             0x09,    "bin")},
        { _TOKEN(TN_TNDS_FMTBOOL,            0x0A,    "bool")},
        { _TOKEN(TN_TNDS_FMTB64,             0x08,    "b64")},
        { _TOKEN(TN_TNDS_FMTINT,             0x1E,    "int")},
        { _TOKEN(TN_TNDS_FMTXML,             0x39,    "xml")},
        { _TOKEN(TN_TNDS_FMTDATE,            0x10,    "date")},
        { _TOKEN(TN_TNDS_FMTTIME,            0x32,    "time")},
        { _TOKEN(TN_TNDS_FMTFLOAT,           0x1B,    "float")},
        { _TOKEN(TN_UNDEF,                   0x00,    NULL)}
    };

    _tmpTagPtr = NULL;
    pGA = mgrGetSyncMLAnchor();
    if (pGA == NULL) return NULL;
    
  /* get the corect codepage */	
  if (ext == SML_EXT_UNDEFINED) {
    _tmpTagPtr = pGA->tokTbl->SyncML;
    if (_tmpTagPtr == NULL) {
		mySize = sizeof(syncml);
		pGA->tokTbl->SyncML = (TagPtr_t)smlLibMalloc(mySize);
		if (pGA->tokTbl->SyncML == NULL) return NULL;
		smlLibMemcpy(pGA->tokTbl->SyncML, &syncml, mySize);
        _tmpTagPtr = pGA->tokTbl->SyncML;
    }
  }

#ifdef __USE_METINF__
	else if (ext == SML_EXT_METINF) {
    _tmpTagPtr = pGA->tokTbl->MetInf;
    if (_tmpTagPtr == NULL) {
		mySize = sizeof(metinf);
		pGA->tokTbl->MetInf = (TagPtr_t)smlLibMalloc(mySize);
		if (pGA->tokTbl->MetInf == NULL) return NULL;
		smlLibMemcpy(pGA->tokTbl->MetInf, &metinf, mySize);
        _tmpTagPtr = pGA->tokTbl->MetInf;
    }
  }
#endif
  
#ifdef __USE_DEVINF__
	else if (ext == SML_EXT_DEVINF) {
    _tmpTagPtr = pGA->tokTbl->DevInf;
    if (_tmpTagPtr == NULL) {
		mySize = sizeof(devinf);
		pGA->tokTbl->DevInf = (TagPtr_t)smlLibMalloc(mySize);
		if (pGA->tokTbl->DevInf == NULL) return NULL;
		smlLibMemcpy(pGA->tokTbl->DevInf, &devinf, mySize);
        _tmpTagPtr = pGA->tokTbl->DevInf;
    }
  }
#endif
    /*
     * Change to support TNDS. 
     */
	else if (ext == SML_EXT_TNDS) {
    _tmpTagPtr = pGA->tokTbl->Tnds;
    if (_tmpTagPtr == NULL) {
		mySize = sizeof(tnds);
		pGA->tokTbl->Tnds = (TagPtr_t)smlLibMalloc(mySize);
		if (pGA->tokTbl->Tnds == NULL) return NULL;
		smlLibMemcpy(pGA->tokTbl->Tnds, &tnds, mySize);
        _tmpTagPtr = pGA->tokTbl->Tnds;
    }
  }

  return _tmpTagPtr;  
}
#undef _TOKEN // we don't need that macro any longer 

/**
 * FUNCTION: getTagString
 *
 * Returns a tag string which belongs to a tag ID. 
 * This function is needed for the XML encoding
 *
 * PRE-Condition:   valid tag ID, the tagSring has to be allocated 
 *
 * POST-Condition:  tag string is returned
 *
 * IN:              tagId, the ID for the tag 
 *
 * IN/OUT:          tagString, allocated string into which the XML 
 *                             tag string will be written
 * 
 * RETURN:          0,if OK
 */
#ifdef __SML_XML__ 
Ret_t getTagString(XltTagID_t tagID, String_t tagString, SmlPcdataExtension_t ext)
{
    int i = 0;
    TagPtr_t pTags = getTagTable(ext);
    if (pTags == NULL) {
      tagString[0] = '\0';
      return SML_ERR_NOT_ENOUGH_SPACE;
    }
    while (((pTags+i)->id) != TN_UNDEF) {
      if ((((pTags+i)->id) == tagID)) {
        String_t _tmp = (pTags+i)->xml;
        smlLibStrcpy(tagString, _tmp); 
        return SML_ERR_OK;
      }    
      i++;
    }        
    //smlLibStrcpy(tagString, '\0'); 
    tagString[0] = '\0';
    return SML_ERR_XLT_INVAL_PROTO_ELEM;
}
#endif

/**
 * FUNCTION: getTagByte
 *
 * Returns a WBXML byte which belongs to a tag ID in a defined codepage. 
 * This function is needed for the WBXML encoding
 *
 * PRE-Condition:   valid tag ID, valid code page
 *
 * POST-Condition:  tag byte is returned
 *
 * IN:              tagId, the ID for the tag 
 *                  cp, code page group for the tag 
 *                  pTagByte, the byte representation of the tag
 * 
 * RETURN:          0, if OK
 */
Ret_t getTagByte(XltTagID_t tagID, SmlPcdataExtension_t ext, Byte_t *pTagByte)
{    
    int i = 0; 
    TagPtr_t pTags = getTagTable(ext);
    if (pTags == NULL)
    {
      return SML_ERR_NOT_ENOUGH_SPACE;
    }
    while (((pTags+i)->id) != TN_UNDEF)
    {
      if (((pTags+i)->id) == tagID)
      {
      	*pTagByte = (pTags+i)->wbxml;
        return SML_ERR_OK;
      }    
      i++;
    }        
    *pTagByte = 0;
    return SML_ERR_XLT_INVAL_PROTO_ELEM;
}

/**
 * FUNCTION: getCodePage
 *
 * Returns the code page which belongs to a certain PCDATA extension type. 
 *
 * PRE-Condition:   valid PCDATA extension type
 *
 * POST-Condition:  the code page is returned
 *
 * IN:              ext, the PCDATA extension type
 * 
 * RETURN:          the code page
 */
Byte_t getCodePage(SmlPcdataExtension_t ext)
{
#ifdef __USE_METINF__
    if (ext == SML_EXT_METINF)
        return 1;
#endif        
#ifdef __USE_DEVINF__
    if (ext == SML_EXT_DEVINF)
        return 0;
#endif        

    return 0;
}

/**
 * FUNCTION: getCodePageById
 *
 * Returns the codepage which belongs to a certain tag ID
 *
 * PRE-Condition:   valid tag ID
 *
 * POST-Condition:  the code page is returned
 *
 * IN:              tagID, the ID of the tag 
 *                  pCp, the codepage/extention of the tag
 *
 * RETURN:          0, if OK
 */
Ret_t getExtById(XltTagID_t tagID,  SmlPcdataExtension_t *pExt)
{
    int i = 0; 
	SmlPcdataExtension_t ext;
	/* Iterate over all defined extensions to find the corresponding TAG.
	 * Empty extensions, e.g. not defined numbers will be skipped.
	 */
	for (ext = SML_EXT_UNDEFINED; ext < SML_EXT_LAST; ext++) {
		TagPtr_t pTags = getTagTable(ext);
		if (pTags == NULL) {
			continue; /* skip empty codepage */
		}
		i = 0;
		while (((pTags+i)->id) != TN_UNDEF) {
			if ((((pTags+i)->id) == tagID)){
       			*pExt = ext;
    			return SML_ERR_OK;
    	    }    
    		i++;
        }        
    }
	/* tag not found in any extension */
  *pExt = (SmlPcdataExtension_t)255;
  return SML_ERR_XLT_INVAL_PROTO_ELEM;
}

/**
 * FUNCTION: getTagIDByStringAndCodepage
 *
 * Returns the tag ID which belongs to a tag string in a certain codepage
 *
 * PRE-Condition:   valid tag string, valid code page
 *
 * POST-Condition:  tag id is returned
 *
 * IN:              tag, the string representation of the tag 
 *                  cp, code page group for the tag 
 *                  pTagID, the tag id of the tag
 * 
 * RETURN:          0, if OK
 */

Ret_t getTagIDByStringAndExt(String_t tag, SmlPcdataExtension_t ext, XltTagID_t *pTagID)
{
    int i = 0; 
    TagPtr_t pTags = getTagTable(ext);
    if (pTags == NULL) {
      return SML_ERR_NOT_ENOUGH_SPACE;
    }
    for (i=0;((pTags+i)->id) != TN_UNDEF; i++) {
	    if (*(pTags+i)->xml != *tag) continue; // if the first char doesn't match we skip the strcmp to speed things up
        if (smlLibStrcmp(((pTags+i)->xml), tag) == 0) {
            *pTagID = (pTags+i)->id;
            return SML_ERR_OK;
        }         
    }        
    *pTagID = TN_UNDEF;
    return SML_ERR_XLT_INVAL_PROTO_ELEM;
}

/**
 * FUNCTION: getTagIDByByteAndCodepage
 *
 * Returns the tag ID which belongs to a tag byte in a certain codepage
 *
 * PRE-Condition:   valid tag byte, valid code page
 *
 * POST-Condition:  tag id is returned
 *
 * IN:              tag, the byte representation of the tag 
 *                  cp, code page group for the tag  
 *                  pTagID, the tag id of the tag
 * 
 * RETURN:          0, if OK
 */
Ret_t getTagIDByByteAndExt(Byte_t tag, SmlPcdataExtension_t ext, XltTagID_t *pTagID)
{

    int i = 0; 
    TagPtr_t pTags = getTagTable(ext);
    if (pTags == NULL)
    {
      return SML_ERR_NOT_ENOUGH_SPACE;
    }
    while (((pTags+i)->id) != TN_UNDEF)
    {
      if (((pTags+i)->wbxml) == tag)
      {
        *pTagID = (pTags+i)->id;
        return SML_ERR_OK;
      }    
      i++;
    }        
    *pTagID = TN_UNDEF;
    return SML_ERR_XLT_INVAL_PROTO_ELEM;
}

/**
 * FUNCTION: getTagIDByStringAndNamespace
 *
 * Returns the tag ID which belongs to a tag string in a certain namespace
 *
 * PRE-Condition:   valid tag string, valid namespace
 *
 * POST-Condition:  tag id is returned
 *
 * IN:              tag, the string representation of the tag 
 *                  ns, namespace group for the tag  
 *                  pTagID, the tag id of the tag
 * 
 * RETURN:          0, if OK
 */
#ifdef __SML_XML__ 
Ret_t getTagIDByStringAndNamespace(String_t tag, String_t ns, XltTagID_t *pTagID)
{
    int i = 0; 
    TagPtr_t pTags = getTagTable(getExtByName(ns));
    if (pTags == NULL)
    {
      return SML_ERR_NOT_ENOUGH_SPACE;
    }
    while (((pTags+i)->id) != TN_UNDEF)
    {
      if ((smlLibStrcmp(((pTags+i)->xml), tag) == 0))
      {
        *pTagID = (pTags+i)->id;
        return SML_ERR_OK;
      }    
      i++;
    }        
    *pTagID = TN_UNDEF;
    return SML_ERR_XLT_INVAL_PROTO_ELEM;
}

#endif
