LTKCPP-- LLRP Toolkit C Plus Plus Library
ltkcpp_xmltextdecode.cpp
Go to the documentation of this file.
00001 
00002 /*
00003  *****************************************************************************
00004  *                                                                           *
00005  *                 IMPINJ CONFIDENTIAL AND PROPRIETARY                       *
00006  *                                                                           *
00007  * This source code is the sole property of Impinj, Inc.  Reproduction or    *
00008  * utilization of this source code in whole or in part is forbidden without  *
00009  * the prior written consent of Impinj, Inc.                                 *
00010  *                                                                           *
00011  * (c) Copyright Impinj, Inc. 2007,2008. All rights reserved.                *
00012  *                                                                           *
00013  *****************************************************************************/
00014 
00027 #include <assert.h>
00028 #include <ctype.h>
00029 #include <string.h>
00030 #include <time.h>
00031 #include <stdio.h>
00032 
00033 #include "ltkcpp_platform.h"
00034 #include "ltkcpp_base.h"
00035 
00036 #include "libxml/parser.h"
00037 #include "libxml/tree.h"
00038 
00039 #include "ltkcpp_xmltext.h"
00040 
00041 
00042 namespace LLRP
00043 {
00044 
00045 CXMLTextDecoder::CXMLTextDecoder (
00046   const CTypeRegistry *         pTypeRegistry,
00047   char *                        pBuffer,
00048   int                           nBuffer) : CDecoder(pTypeRegistry)
00049 
00050 {
00051     /* set the line numbers for error reporting */
00052     xmlLineNumbersDefault(1);
00053 
00054     /* Read in the XML from the buffer into the XML Reader */
00055     m_pDoc = xmlReadMemory((char*) pBuffer, nBuffer, "noName.xml", NULL, 
00056                                   XML_PARSE_COMPACT | XML_PARSE_NONET);
00057 
00058     if(NULL != m_pDoc)
00059     {
00060         /* Initialize the other decoder state variables */
00061         m_pxmlNodeTree = xmlDocGetRootElement(m_pDoc);
00062     }
00063     else
00064     {
00065         fprintf(stderr, "could not parse XML memory buffer");
00066     }
00067 }
00068 
00069 CXMLTextDecoder::CXMLTextDecoder (
00070   const CTypeRegistry *         pTypeRegistry,
00071   struct _xmlNode *             pNodeTree) : CDecoder(pTypeRegistry)
00072 {
00073     /* set the line numbers for error reporting */
00074     xmlLineNumbersDefault(1);
00075 
00076     /* Read in the XML from the buffer into the XML Reader */
00077     m_pDoc = NULL; 
00078     /* Initialize the other decoder state variables */
00079     m_pxmlNodeTree = pNodeTree;
00080 }
00081 
00082 CXMLTextDecoder::CXMLTextDecoder (
00083   const CTypeRegistry *         pTypeRegistry,
00084   char *                        fname) : CDecoder(pTypeRegistry)
00085 {
00086     /* set the line numbers for error reporting */
00087     xmlLineNumbersDefault(1);
00088 
00089     /* Read in the XML from the file into the XML Reader */
00090     m_pDoc = xmlReadFile(fname, 
00091                          NULL, 
00092                          XML_PARSE_COMPACT | XML_PARSE_NONET);
00093 
00094     if(NULL != m_pDoc)
00095     {
00096         /* Initialize the other decoder state variables */
00097         m_pxmlNodeTree = xmlDocGetRootElement(m_pDoc);
00098     }
00099     else
00100     {
00101         fprintf(stderr, "could not parse XML file");
00102     }
00103 }
00104 
00105 CXMLTextDecoder::~CXMLTextDecoder (void)
00106 {
00107     if(NULL != m_pDoc)
00108     {
00109         xmlFreeDoc(m_pDoc);    
00110         m_pDoc = NULL;
00111     }
00112     m_pxmlNodeTree = NULL;
00113 }
00114 
00115 CMessage *
00116 CXMLTextDecoder::decodeMessage (void)
00117 {
00118     CMessage *                  pMessage;
00119     CXMLTextDecoderStream       DecoderStream(this);
00120     CErrorDetails              *pError = &m_ErrorDetails;
00121   
00122     if(NULL == m_pxmlNodeTree)
00123     {
00124         pError->m_eResultCode = RC_MiscError;
00125         pError->m_pWhatStr    = "Unable to Extract XML Node Tree";
00126         pError->m_pRefType    = NULL;
00127         pError->m_pRefField   = NULL;
00128         pError->m_OtherDetail = (int) 0;
00129         return NULL;
00130     }
00131     pMessage = (CMessage *) DecoderStream.decodeElement(TRUE, TRUE);
00132 
00133     return pMessage;
00134 }
00135 
00136 void 
00137 CXMLTextDecoder::cleanupParser (void)
00138 {
00139     xmlCleanupParser();
00140 }
00141 
00142 CXMLTextDecoderStream::CXMLTextDecoderStream (
00143   CXMLTextDecoder *             pDecoder)
00144 {
00145 
00146     m_pDecoder                = pDecoder;
00147     m_pEnclosingDecoderStream = NULL;
00148     m_pRefType                = NULL;
00149     m_pTargetNode             = pDecoder->m_pxmlNodeTree;
00150     m_pCurrentChildNode       = NULL;
00151 }
00152 
00153 CXMLTextDecoderStream::CXMLTextDecoderStream (
00154   CXMLTextDecoderStream *       pEnclosingDecoderStream)
00155 {
00156     m_pDecoder                = pEnclosingDecoderStream->m_pDecoder;
00157     m_pEnclosingDecoderStream = pEnclosingDecoderStream;
00158     m_pRefType                = pEnclosingDecoderStream->m_pRefType;
00159     m_pTargetNode             = pEnclosingDecoderStream->m_pCurrentChildNode; 
00160     m_pCurrentChildNode       = NULL;
00161 }
00162 
00163 CElement *
00164 CXMLTextDecoderStream::decodeElement (
00165   int                           bAllowMessage,
00166   int                           bSkipBlanks)
00167 {
00168     CErrorDetails              *pError = &m_pDecoder->m_ErrorDetails;
00169     const CTypeDescriptor*      pTypeDescriptor;
00170     llrp_u32_t                  MessageID = 0;
00171     CElement *                  pElement;
00172 
00173     if(RC_OK != pError->m_eResultCode)
00174     {
00175         return NULL;
00176     }
00177 
00178     /* get the first interesting node as the target node */
00179     if(bSkipBlanks)
00180     {
00181         while ((NULL != m_pTargetNode) &&
00182                ( isInsignificantNode(m_pTargetNode) || 
00183                  xmlIsBlankNode(m_pTargetNode)))
00184         {
00185             m_pTargetNode = m_pTargetNode->next;
00186         }
00187     }
00188 
00189     /* no interestig target node found. THis is OK as its an empty decode */
00190     if(NULL == m_pTargetNode)
00191     {
00192         return NULL;
00193     }
00194 
00195     /* first interesting node had better be an element */
00196     if(m_pTargetNode->type != XML_ELEMENT_NODE)
00197     {
00198         pError->m_eResultCode = RC_XMLInvalidNodeType;
00199         pError->m_pWhatStr    = "unexpected XML node type";
00200         pError->m_pRefType    = m_pRefType;
00201         pError->m_pRefField   = NULL;
00202         pError->m_OtherDetail = (int) m_pTargetNode->line;
00203         return NULL;
00204     }
00205 
00206     /* look up the type descriptor*/
00207     pTypeDescriptor = m_pDecoder->m_pRegistry->lookupByName(
00208                                            (char*) m_pTargetNode->name);
00209 
00210     if(NULL == pTypeDescriptor)
00211     {
00212         pError->m_eResultCode = RC_UnknownParameterType;
00213         pError->m_pWhatStr    = "unknown message or parameter type";
00214         pError->m_pRefType    = m_pRefType;
00215         pError->m_pRefField   = NULL;
00216         pError->m_OtherDetail = (int) m_pTargetNode->line;
00217         return NULL;
00218     }
00219 
00220     m_pRefType = pTypeDescriptor;
00221 
00222     /* process messages a bit specially */
00223     if(pTypeDescriptor->m_bIsMessage)
00224     {
00225         xmlChar *               pMessageIDStr;
00226 
00227         if(!bAllowMessage)
00228         {
00229             pError->m_eResultCode = RC_MiscError;
00230             pError->m_pWhatStr    = "message as subparameter";
00231             pError->m_pRefType    = m_pRefType;
00232             pError->m_pRefField   = NULL;
00233             pError->m_OtherDetail = (int) m_pTargetNode->line;
00234             return NULL;
00235         }
00236 
00237         /* get the messageID Attribute */
00238         pMessageIDStr = xmlGetProp(m_pTargetNode, 
00239                                    (xmlChar*) "MessageID");
00240         if(NULL != pMessageIDStr)
00241         {
00242             char *                  pArg = (char *) pMessageIDStr;
00243             char *                  pTail = pArg + strlen((char*) pMessageIDStr);
00244             char *                  pTmp;
00245             cleanString((const llrp_u8_t **) &pArg, (const llrp_u8_t **) &pTail);
00246             MessageID = strtoul(pArg, &pTmp, 10);
00247             xmlFree(pMessageIDStr);
00248 
00249             if(pTail != pTmp)
00250             {
00251                 /* malformed */
00252                 pError->m_eResultCode = RC_MiscError;
00253                 pError->m_pWhatStr    = "malformed MessageID";
00254                 pError->m_pRefType    = m_pRefType;
00255                 pError->m_pRefField   = NULL;
00256                 pError->m_OtherDetail = (int) m_pTargetNode->line;
00257                 return NULL;
00258             }
00259         }
00260     }
00261 
00262     /* create our element to hold the information */
00263     pElement = pTypeDescriptor->constructElement();
00264 
00265     if(NULL == pElement)
00266     {
00267         pError->m_eResultCode = RC_MessageAllocationFailed;
00268         pError->m_pWhatStr    = "element allocation failed";
00269         pError->m_pRefType    = m_pRefType;
00270         pError->m_pRefField   = NULL;
00271         pError->m_OtherDetail = (int) m_pTargetNode->line;
00272         return NULL;
00273     }
00274 
00275     /* only write the message ID for messages */
00276     if(pTypeDescriptor->m_bIsMessage)
00277     {
00278         ((CMessage *) pElement)->setMessageID(MessageID);
00279     }
00280 
00281     /* now switch to decode the children which are the
00282      * fields and sub-parameters of this element */
00283     m_pCurrentChildNode = m_pTargetNode->children;
00284 
00285     /* decode the fields first */
00286     pTypeDescriptor->m_pfDecodeFields(this, pElement);
00287 
00288     if(RC_OK != pError->m_eResultCode)
00289     {
00290         delete pElement;
00291         return NULL;
00292     }
00293 
00294     /*
00295      * Subparameters.
00296      *
00297      * loop through all the remaining children of the target node and try to find sub-parameters.
00298      * We are done when we don't have any more or error
00299      */
00300     for(; m_pCurrentChildNode != NULL; 
00301             m_pCurrentChildNode = m_pCurrentChildNode->next)
00302     {
00303         CElement *              pSubElement;
00304         CParameter *            pParameter;
00305 
00306         if(isInsignificantNode(m_pCurrentChildNode))
00307         {
00308                 continue;
00309         }
00310 
00311         if(xmlIsBlankNode(m_pCurrentChildNode))
00312         {
00313                 continue;
00314         }
00315 
00316         CXMLTextDecoderStream   NestStream(this);
00317 
00318         pSubElement = NestStream.decodeElement(FALSE, FALSE);
00319 
00320         /* nothing more to decode as a sub-element or failure */
00321         if(NULL == pSubElement)
00322         {
00323             break;
00324         }
00325 
00326         pParameter = (CParameter *) pSubElement;
00327 
00328         pParameter->m_pParent = pElement;
00329         pElement->addSubParameterToAllList(pParameter);
00330     }
00331 
00332     if(RC_OK != pError->m_eResultCode)
00333     {
00334         delete pElement;
00335         return NULL;
00336     }
00337 
00338     pElement->assimilateSubParameters(pError);
00339 
00340     if(RC_OK != pError->m_eResultCode)
00341     {
00342         delete pElement;
00343         return NULL;
00344     }
00345 
00346     return pElement;
00347 }
00348 
00350 llrp_u8_t
00351 CXMLTextDecoderStream::get_u8 (
00352   const CFieldDescriptor *      pFieldDesc)
00353 {
00354     llrp_u8_t Value;
00355     Value = (llrp_u8_t) getIntegerField(pFieldDesc, MIN_U8, MAX_U8);
00356     return Value;
00357 }
00358 
00360 llrp_s8_t
00361 CXMLTextDecoderStream::get_s8 (
00362   const CFieldDescriptor *      pFieldDesc)
00363 {
00364     llrp_s8_t Value;
00365     Value = (llrp_s8_t) getIntegerField(pFieldDesc, MIN_S8, MAX_S8);
00366     return Value;
00367 }
00368 
00370 llrp_u8v_t
00371 CXMLTextDecoderStream::get_u8v (
00372   const CFieldDescriptor *      pFieldDesc)
00373 {
00374     CErrorDetails *             pError;
00375     llrp_u8v_t                  Value;
00376     llrp_s64v_t                 Tmp;
00377 
00378     pError = &m_pDecoder->m_ErrorDetails;
00379 
00380     switch(pFieldDesc->m_eFieldFormat)
00381     {
00382         /* assume normal format here is decimal */
00383         case CFieldDescriptor::FMT_NORMAL:
00384         case CFieldDescriptor::FMT_DEC:
00385         Tmp = getSpacedVectorField(pFieldDesc, MIN_U8, MAX_U8);
00386         break;
00387         case CFieldDescriptor::FMT_HEX:
00388         Tmp = getFixedVectorField(pFieldDesc, 2, MIN_U8, MAX_U8);       
00389         break;
00390         default:
00391         case CFieldDescriptor::FMT_UTF8:
00392         case CFieldDescriptor::FMT_DATETIME:
00393             if(NULL != pError)
00394             {
00395                 pError->m_eResultCode = RC_MiscError;
00396                 pError->m_pWhatStr    = "Format type not support for field";
00397                 pError->m_pRefType    = m_pRefType;
00398                 pError->m_pRefField   = pFieldDesc;
00399                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00400             }       
00401         break;
00402     }    
00403 
00404     if(Tmp.m_nValue)
00405     {
00406         llrp_u16_t              nValue;
00407 
00408         nValue = Tmp.m_nValue;
00409         Value = llrp_u8v_t(nValue);
00410         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00411         {
00412             unsigned int    Ix;
00413 
00414             for(Ix = 0; Ix < nValue; Ix++)
00415             {
00416                 Value.m_pValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
00417             }
00418         }
00419     }
00420 
00421     return Value;
00422 }
00423 
00425 llrp_s8v_t
00426 CXMLTextDecoderStream::get_s8v (
00427   const CFieldDescriptor *      pFieldDesc)
00428 {
00429     CErrorDetails *             pError;
00430     llrp_s8v_t                  Value;
00431     llrp_s64v_t                 Tmp;
00432 
00433     pError = &m_pDecoder->m_ErrorDetails;
00434 
00435     switch(pFieldDesc->m_eFieldFormat)
00436     {
00437         /* assume normal format here is decimal */
00438         case CFieldDescriptor::FMT_NORMAL:
00439         case CFieldDescriptor::FMT_DEC:
00440         Tmp = getSpacedVectorField(pFieldDesc, MIN_S8, MAX_S8);
00441         break;
00442         case CFieldDescriptor::FMT_HEX:
00443         Tmp = getFixedVectorField(pFieldDesc, 2, MIN_S8, MAX_S8);       
00444         break;
00445         default:
00446         case CFieldDescriptor::FMT_UTF8:
00447         case CFieldDescriptor::FMT_DATETIME:
00448             if(NULL != pError)
00449             {
00450                 pError->m_eResultCode = RC_MiscError;
00451                 pError->m_pWhatStr    = "Format type not support for field";
00452                 pError->m_pRefType    = m_pRefType;
00453                 pError->m_pRefField   = pFieldDesc;
00454                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00455             }       
00456         break;
00457     }    
00458 
00459     if(Tmp.m_nValue)
00460     {
00461         llrp_u16_t              nValue;
00462 
00463         nValue = Tmp.m_nValue;
00464         Value = llrp_s8v_t(nValue);
00465         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00466         {
00467             unsigned int    Ix;
00468 
00469             for(Ix = 0; Ix < nValue; Ix++)
00470             {
00471                 Value.m_pValue[Ix] = (llrp_s8_t) Tmp.m_pValue[Ix];
00472             }
00473         }
00474     }
00475 
00476     return Value;
00477 }
00478 
00479 /*
00480  * 16-bit types
00481  */
00482 
00484 llrp_u16_t
00485 CXMLTextDecoderStream::get_u16 (
00486   const CFieldDescriptor *      pFieldDesc)
00487 {
00488     llrp_u16_t Value;
00489     Value = (llrp_u16_t) getIntegerField(pFieldDesc, MIN_U16, MAX_U16);
00490     return Value;
00491 }
00492 
00494 llrp_s16_t
00495 CXMLTextDecoderStream::get_s16 (
00496   const CFieldDescriptor *      pFieldDesc)
00497 {
00498     llrp_s16_t Value;
00499     Value = (llrp_s16_t) getIntegerField(pFieldDesc, MIN_S16, MAX_S16);
00500     return Value;
00501 }
00502 
00504 llrp_u16v_t
00505 CXMLTextDecoderStream::get_u16v (
00506   const CFieldDescriptor *      pFieldDesc)
00507 {
00508     CErrorDetails *             pError;
00509     llrp_u16v_t                  Value;
00510     llrp_s64v_t                 Tmp;
00511 
00512     pError = &m_pDecoder->m_ErrorDetails;
00513 
00514     switch(pFieldDesc->m_eFieldFormat)
00515     {
00516         /* assume normal format here is decimal */
00517         case CFieldDescriptor::FMT_NORMAL:
00518         case CFieldDescriptor::FMT_DEC:
00519         case CFieldDescriptor::FMT_HEX:
00520             Tmp = getSpacedVectorField(pFieldDesc, MIN_U16, MAX_U16);
00521             break;
00522         default:
00523         case CFieldDescriptor::FMT_UTF8:
00524         case CFieldDescriptor::FMT_DATETIME:
00525             if(NULL != pError)
00526             {
00527                 pError->m_eResultCode = RC_MiscError;
00528                 pError->m_pWhatStr    = "Format type not support for field";
00529                 pError->m_pRefType    = m_pRefType;
00530                 pError->m_pRefField   = pFieldDesc;
00531                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00532             }       
00533         break;
00534     }    
00535 
00536     if(Tmp.m_nValue)
00537     {
00538         llrp_u16_t              nValue;
00539 
00540         nValue = Tmp.m_nValue;
00541         Value = llrp_u16v_t(nValue);
00542         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00543         {
00544             unsigned int    Ix;
00545 
00546             for(Ix = 0; Ix < nValue; Ix++)
00547             {
00548                 Value.m_pValue[Ix] = (llrp_u16_t) Tmp.m_pValue[Ix];
00549             }
00550         }
00551     }
00552     return Value;
00553 }
00554 
00556 llrp_s16v_t
00557 CXMLTextDecoderStream::get_s16v (
00558   const CFieldDescriptor *      pFieldDesc)
00559 {
00560     CErrorDetails *             pError;
00561     llrp_s16v_t                  Value;
00562     llrp_s64v_t                 Tmp;
00563 
00564     pError = &m_pDecoder->m_ErrorDetails;
00565 
00566     switch(pFieldDesc->m_eFieldFormat)
00567     {
00568         /* assume normal format here is decimal */
00569         case CFieldDescriptor::FMT_NORMAL:
00570         case CFieldDescriptor::FMT_DEC:
00571         case CFieldDescriptor::FMT_HEX:
00572             Tmp = getSpacedVectorField(pFieldDesc, MIN_S16, MAX_S16);
00573             break;
00574         default:
00575         case CFieldDescriptor::FMT_UTF8:
00576         case CFieldDescriptor::FMT_DATETIME:
00577             if(NULL != pError)
00578             {
00579                 pError->m_eResultCode = RC_MiscError;
00580                 pError->m_pWhatStr    = "Format type not support for field";
00581                 pError->m_pRefType    = m_pRefType;
00582                 pError->m_pRefField   = pFieldDesc;
00583                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00584             }       
00585         break;
00586     }    
00587 
00588     if(Tmp.m_nValue)
00589     {
00590         llrp_u16_t              nValue;
00591 
00592         nValue = Tmp.m_nValue;
00593         Value = llrp_s16v_t(nValue);
00594         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00595         {
00596             unsigned int    Ix;
00597 
00598             for(Ix = 0; Ix < nValue; Ix++)
00599             {
00600                 Value.m_pValue[Ix] = (llrp_s16_t) Tmp.m_pValue[Ix];
00601             }
00602         }
00603     }
00604     return Value;
00605 }
00606 
00607 /*
00608  * 32-bit types
00609  */
00610 
00612 llrp_u32_t
00613 CXMLTextDecoderStream::get_u32 (
00614   const CFieldDescriptor *      pFieldDesc)
00615 {
00616     llrp_u32_t Value;
00617     Value = (llrp_u32_t) getIntegerField(pFieldDesc, MIN_U32, MAX_U32);
00618     return Value;
00619 }
00620 
00622 llrp_s32_t
00623 CXMLTextDecoderStream::get_s32 (
00624   const CFieldDescriptor *      pFieldDesc)
00625 {
00626     llrp_s32_t Value;
00627     Value = (llrp_s32_t) getIntegerField(pFieldDesc, MIN_S32, MAX_S32);
00628     return Value;
00629 }
00630 
00632 llrp_u32v_t
00633 CXMLTextDecoderStream::get_u32v (
00634   const CFieldDescriptor *      pFieldDesc)
00635 {
00636     CErrorDetails *             pError;
00637     llrp_u32v_t                 Value;
00638     llrp_s64v_t                 Tmp;
00639 
00640     pError = &m_pDecoder->m_ErrorDetails;
00641 
00642     switch(pFieldDesc->m_eFieldFormat)
00643     {
00644         /* assume normal format here is decimal */
00645         case CFieldDescriptor::FMT_NORMAL:
00646         case CFieldDescriptor::FMT_DEC:
00647         case CFieldDescriptor::FMT_HEX:
00648             Tmp = getSpacedVectorField(pFieldDesc, MIN_U32, MAX_U32);
00649             break;
00650         default:
00651         case CFieldDescriptor::FMT_UTF8:
00652         case CFieldDescriptor::FMT_DATETIME:
00653             if(NULL != pError)
00654             {
00655                 pError->m_eResultCode = RC_MiscError;
00656                 pError->m_pWhatStr    = "Format type not support for field";
00657                 pError->m_pRefType    = m_pRefType;
00658                 pError->m_pRefField   = pFieldDesc;
00659                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00660             }       
00661         break;
00662     }    
00663 
00664     if(Tmp.m_nValue)
00665     {
00666         llrp_u16_t              nValue;
00667 
00668         nValue = Tmp.m_nValue;
00669         Value = llrp_u32v_t(nValue);
00670         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00671         {
00672             unsigned int    Ix;
00673 
00674             for(Ix = 0; Ix < nValue; Ix++)
00675             {
00676                 Value.m_pValue[Ix] = (llrp_u32_t) Tmp.m_pValue[Ix];
00677             }
00678         }
00679     }
00680     return Value;
00681 }
00682 
00684 llrp_s32v_t
00685 CXMLTextDecoderStream::get_s32v (
00686   const CFieldDescriptor *      pFieldDesc)
00687 {
00688     CErrorDetails *             pError;
00689     llrp_s32v_t                 Value;
00690     llrp_s64v_t                 Tmp;
00691 
00692     pError = &m_pDecoder->m_ErrorDetails;
00693 
00694     switch(pFieldDesc->m_eFieldFormat)
00695     {
00696         /* assume normal format here is decimal */
00697         case CFieldDescriptor::FMT_NORMAL:
00698         case CFieldDescriptor::FMT_DEC:
00699         case CFieldDescriptor::FMT_HEX:
00700             Tmp = getSpacedVectorField(pFieldDesc, MIN_S32, MAX_S32);
00701             break;
00702         default:
00703         case CFieldDescriptor::FMT_UTF8:
00704         case CFieldDescriptor::FMT_DATETIME:
00705             if(NULL != pError)
00706             {
00707                 pError->m_eResultCode = RC_MiscError;
00708                 pError->m_pWhatStr    = "Format type not support for field";
00709                 pError->m_pRefType    = m_pRefType;
00710                 pError->m_pRefField   = pFieldDesc;
00711                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00712             }       
00713         break;
00714     }    
00715 
00716     if(Tmp.m_nValue)
00717     {
00718         llrp_u16_t              nValue;
00719 
00720         nValue = Tmp.m_nValue;
00721         Value = llrp_s32v_t(nValue);
00722         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00723         {
00724             unsigned int    Ix;
00725 
00726             for(Ix = 0; Ix < nValue; Ix++)
00727             {
00728                 Value.m_pValue[Ix] = (llrp_s32_t) Tmp.m_pValue[Ix];
00729             }
00730         }
00731     }
00732     return Value;
00733 }
00734 
00735 /*
00736  * 64-bit types
00737  */
00738 
00740 llrp_u64_t
00741 CXMLTextDecoderStream::get_u64 (
00742   const CFieldDescriptor *      pFieldDesc)
00743 {
00744     llrp_u64_t Value;
00745     Value = (llrp_u64_t) getIntegerField(pFieldDesc, MIN_U64, MAX_U64);
00746     return Value;
00747 }
00748 
00750 llrp_s64_t
00751 CXMLTextDecoderStream::get_s64 (
00752   const CFieldDescriptor *      pFieldDesc)
00753 {
00754     llrp_s64_t Value;
00755     Value = (llrp_s64_t) getIntegerField(pFieldDesc, MIN_S64, MAX_S64);
00756     return Value;
00757 }
00758 
00760 llrp_u64v_t
00761 CXMLTextDecoderStream::get_u64v (
00762   const CFieldDescriptor *      pFieldDesc)
00763 {
00764     CErrorDetails *             pError;
00765     llrp_u64v_t                 Value;
00766     llrp_s64v_t                 Tmp;
00767 
00768     pError = &m_pDecoder->m_ErrorDetails;
00769 
00770     switch(pFieldDesc->m_eFieldFormat)
00771     {
00772         /* assume normal format here is decimal */
00773         case CFieldDescriptor::FMT_NORMAL:
00774         case CFieldDescriptor::FMT_DEC:
00775         case CFieldDescriptor::FMT_HEX:
00776         case CFieldDescriptor::FMT_DATETIME:
00777             Tmp = getSpacedVectorField(pFieldDesc, MIN_U64, MAX_U64);
00778             break;
00779         default:
00780         case CFieldDescriptor::FMT_UTF8:
00781             if(NULL != pError)
00782             {
00783                 pError->m_eResultCode = RC_MiscError;
00784                 pError->m_pWhatStr    = "Format type not support for field";
00785                 pError->m_pRefType    = m_pRefType;
00786                 pError->m_pRefField   = pFieldDesc;
00787                 pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00788             }       
00789         break;
00790     }    
00791 
00792     if(Tmp.m_nValue)
00793     {
00794         llrp_u16_t              nValue;
00795 
00796         nValue = Tmp.m_nValue;
00797         Value = llrp_u64v_t(nValue);
00798         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00799         {
00800             unsigned int    Ix;
00801 
00802             for(Ix = 0; Ix < nValue; Ix++)
00803             {
00804                 Value.m_pValue[Ix] = (llrp_u64_t) Tmp.m_pValue[Ix];
00805             }
00806         }
00807     }
00808     return Value;
00809 }
00810 
00812 llrp_s64v_t
00813 CXMLTextDecoderStream::get_s64v (
00814   const CFieldDescriptor *      pFieldDesc)
00815 {
00816     llrp_s64v_t Value;
00817     Value = getSpacedVectorField(pFieldDesc, MIN_S64, MAX_S64); 
00818     return Value;
00819 }
00820 
00821 /*
00822  * Special types
00823  */
00824 
00826 llrp_u1_t
00827 CXMLTextDecoderStream::get_u1 (
00828   const CFieldDescriptor *      pFieldDesc)
00829 {
00830     llrp_u1_t Value;
00831     Value = (llrp_u1_t) getIntegerField(pFieldDesc, 0, 1);
00832     return Value;
00833 }
00834 
00836 llrp_u1v_t
00837 CXMLTextDecoderStream::get_u1v (
00838   const CFieldDescriptor *      pFieldDesc)
00839 {
00840     CErrorDetails *             pError;
00841     llrp_u1v_t                  Value;
00842     llrp_s64v_t                 Tmp;
00843 
00844     pError = &m_pDecoder->m_ErrorDetails;
00845     Tmp = getFixedVectorField(pFieldDesc, 2, 0, 255);
00846 
00847     if(Tmp.m_nValue)
00848     {
00849         llrp_u16_t              nValue;
00850 
00851         nValue = Tmp.m_nValue;
00852         Value = llrp_u1v_t(nValue*8);
00853         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00854         {
00855             unsigned int        Ix;
00856             xmlChar *           pCountStr;
00857 
00858             for(Ix = 0; Ix < nValue; Ix++)
00859             {
00860                 Value.m_pValue[Ix] = (llrp_u1_t) Tmp.m_pValue[Ix];
00861             }
00862             /* bit length could be shorter than this. Use this if there
00863              * is no attribute */
00864             Value.m_nBit = Tmp.m_nValue * 8;
00865 
00866             /* find the XML attribute for Count and fix the array */
00867             if(NULL != m_pLastFieldNode)
00868             {
00869                 pCountStr = xmlGetProp(m_pLastFieldNode, 
00870                                        (xmlChar*) "Count");
00871                 if(NULL != pCountStr)
00872                 {
00873                     char *      pArg = (char *) pCountStr;
00874                     char *      pTail = pArg + strlen((char*) pCountStr);
00875                     llrp_u16_t  nBits;
00876 
00877                     nBits = (llrp_u16_t) strtoul(pArg, &pTail, 10);
00878                     if( (*pTail != 0) ||
00879                         (nBits > (Tmp.m_nValue * 8)))
00880                     {
00881                         /* malformed */
00882                         pError->m_eResultCode = RC_MiscError;
00883                         pError->m_pWhatStr    = "malformed Count Attribute";
00884                         pError->m_pRefType    = m_pRefType;
00885                         pError->m_pRefField   = pFieldDesc;
00886                         pError->m_OtherDetail = (int) m_pLastFieldNode->line;
00887                     }                
00888                     else
00889                     {
00890                         llrp_u16_t lastByteBits;
00891                         llrp_u8_t  lastByteMask;
00892                                     
00893                         Value.m_nBit = nBits;           
00894 
00895                         /* zero off the last bits if they were non-zero */
00896                         lastByteBits = nBits % 8;           
00897                         if(lastByteBits)
00898                         {
00899                             /* convert the bit position to a mask */
00900                             lastByteBits = 8 - lastByteBits;
00901                             lastByteMask = (1 << lastByteBits) - 1;
00902                             /* invert mask */
00903                             lastByteMask = ~lastByteMask;
00904                             /* clear bits */
00905                             Value.m_pValue[Ix] &= lastByteMask;
00906                         }
00907                     }
00908                     xmlFree(pCountStr);
00909                 }
00910             }
00911         }
00912     }
00913     return Value;
00914 }
00915 
00917 llrp_u2_t
00918 CXMLTextDecoderStream::get_u2 (
00919   const CFieldDescriptor *      pFieldDesc)
00920 {
00921     llrp_u2_t Value;
00922     Value = (llrp_u2_t) getIntegerField(pFieldDesc, 0, 3);
00923     return Value;
00924 }
00925 
00927 llrp_u96_t
00928 CXMLTextDecoderStream::get_u96 (
00929   const CFieldDescriptor *      pFieldDesc)
00930 {
00931     CErrorDetails *             pError; 
00932     llrp_u96_t                  Value;
00933     llrp_s64v_t                 Tmp;
00934     unsigned int    Ix;
00935 
00936     pError = &m_pDecoder->m_ErrorDetails;
00937 
00938     Tmp = getFixedVectorField( pFieldDesc, 2, 0, 255);
00939 
00940     if((RC_OK != pError->m_eResultCode) && (Tmp.m_nValue != 12))
00941     {
00942         if(NULL != pError)
00943         {
00944             pError->m_eResultCode = RC_MiscError;
00945             pError->m_pWhatStr    = "Illegal length u96 field";
00946             pError->m_pRefType    = m_pRefType;
00947             pError->m_pRefField   = pFieldDesc;
00948             pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
00949         }
00950         return Value;    
00951     }
00952 
00953     /* convert to this type */
00954     for(Ix = 0; Ix < Tmp.m_nValue; Ix++)
00955     {
00956         Value.m_aValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
00957     }
00958   
00959     return Value;
00960 }
00961 
00963 llrp_utf8v_t
00964 CXMLTextDecoderStream::get_utf8v (
00965   const CFieldDescriptor *      pFieldDesc)
00966 {
00967     llrp_utf8v_t                Value;
00968     llrp_u16_t                  nValue;
00969     const llrp_u8_t *           pbuf;
00970     const llrp_u8_t *           pend;
00971 
00972     if(getFieldStringPtr(pFieldDesc, &pbuf, &pend))
00973     {
00974         nValue = (llrp_u16_t) strlen((char*) pbuf);
00975         Value = llrp_utf8v_t(nValue);
00976 
00977         if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
00978         {
00979             unsigned int    Ix;
00980 
00981             for(Ix = 0; Ix < nValue; Ix++)
00982             {
00983                 Value.m_pValue[Ix] = pbuf[Ix];
00984             }
00985         }    
00986     }
00987     else
00988     {
00989         /* its valid for UTF8 strings to be empty */
00990         Value.m_nValue=0;
00991         Value.m_pValue=NULL;
00992     }
00993     return Value;
00994 }
00995 
00997 llrp_bytesToEnd_t
00998 CXMLTextDecoderStream::get_bytesToEnd (
00999   const CFieldDescriptor *      pFieldDesc)
01000 {
01001     llrp_bytesToEnd_t           Value;
01002     llrp_s64v_t                 Tmp;
01003     unsigned int                Ix;
01004 
01005     Tmp = getFixedVectorField( pFieldDesc, 2, 0, 255);
01006 
01007     if(verifyVectorAllocation(Tmp.m_pValue, pFieldDesc))
01008     {
01009         /* build and convert */
01010         Value = llrp_bytesToEnd_t(Tmp.m_nValue);
01011         if(verifyVectorAllocation(Tmp.m_pValue, pFieldDesc))
01012         {
01013             /* convert to this type */
01014             for(Ix = 0; Ix < Tmp.m_nValue; Ix++)
01015             {
01016                 Value.m_pValue[Ix] = (llrp_byte_t) Tmp.m_pValue[Ix];
01017             }
01018             Value.m_nValue = Tmp.m_nValue;
01019         }
01020     }
01021     return Value;
01022 }
01023 
01024 /*
01025  * Enumerated types of various sizes
01026  */
01027 
01029 int
01030 CXMLTextDecoderStream::get_e1 (
01031   const CFieldDescriptor *      pFieldDesc)
01032 {
01033     int                         Value;
01034     Value = (int) getIntegerField(pFieldDesc, 0, 1);
01035     return Value;
01036 }
01037 
01039 int
01040 CXMLTextDecoderStream::get_e2 (
01041   const CFieldDescriptor *      pFieldDesc)
01042 {
01043     int                         Value;
01044     Value = (int) getIntegerField(pFieldDesc, 0, 3);
01045     return Value;
01046 }
01047 
01049 int
01050 CXMLTextDecoderStream::get_e8 (
01051   const CFieldDescriptor *      pFieldDesc)
01052 {
01053     int                         Value;
01054     Value = (int) getIntegerField(pFieldDesc, MIN_U8, MAX_U8);
01055     return Value;
01056 }
01057 
01059 int
01060 CXMLTextDecoderStream::get_e16 (
01061   const CFieldDescriptor *      pFieldDesc)
01062 {
01063     int                         Value;
01064     Value = (int) getIntegerField(pFieldDesc, MIN_U16, MAX_U16);
01065     return Value;
01066 }
01067 
01069 int
01070 CXMLTextDecoderStream::get_e32 (
01071   const CFieldDescriptor *      pFieldDesc)
01072 {
01073     int                         Value;
01074     Value = (int) getIntegerField(pFieldDesc, MIN_U32, MAX_U32);
01075     return Value;
01076 }
01077 
01079 llrp_u8v_t
01080 CXMLTextDecoderStream::get_e8v (
01081   const CFieldDescriptor *      pFieldDesc)
01082 {
01083     llrp_u8v_t                  Value;
01084     llrp_s64v_t                 Tmp;
01085 
01086     Tmp = getSpacedVectorField( pFieldDesc, MIN_U8, MAX_U8);
01087     if(Tmp.m_nValue)
01088     {
01089         llrp_u16_t              nValue;
01090 
01091         nValue = Tmp.m_nValue;
01092         Value = llrp_u8v_t(nValue);
01093         if(verifyVectorAllocation(Value.m_pValue,pFieldDesc))
01094         {
01095             unsigned int    Ix;
01096 
01097             for(Ix = 0; Ix < nValue; Ix++)
01098             {
01099                 Value.m_pValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
01100             }
01101         }
01102     }
01103     return Value;
01104 }
01105 
01106 /* @brief skips a number of reserved bits and discards during the encode/decode process */
01107 void
01108 CXMLTextDecoderStream::get_reserved (
01109   unsigned int                  nBits)
01110 {
01111     return;
01112 }
01113 
01114 llrp_bool_t
01115 CXMLTextDecoderStream::verifyVectorAllocation (
01116   const void *                  pValue,
01117   const CFieldDescriptor *      pFieldDescriptor)
01118 {
01119     if(NULL == pValue)
01120     {
01121         CErrorDetails *         pError = &m_pDecoder->m_ErrorDetails;
01122 
01123         pError->m_eResultCode = RC_FieldAllocationFailed;
01124         pError->m_pWhatStr    = "field allocation failed";
01125         pError->m_pRefType    = m_pRefType;
01126         pError->m_pRefField   = pFieldDescriptor;
01127         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
01128 
01129         return FALSE;
01130     }
01131     else
01132     {
01133         return TRUE;
01134     }
01135 }
01136 
01137 int
01138 CXMLTextDecoderStream::isInsignificantNode (
01139   struct _xmlNode *             pnode)
01140 {
01141     switch(pnode->type)
01142     {
01143         /* don't process comments or notations */
01144         case XML_COMMENT_NODE:
01145         case XML_NOTATION_NODE:
01146         /* ignore includes */
01147         case XML_XINCLUDE_START:
01148        case XML_XINCLUDE_END:       
01149        /* don't read processing instructions */
01150         case XML_PI_NODE:
01151         return 1;
01152 
01153         /* hopefully we only see these type of nodes */
01154         case XML_ELEMENT_NODE:
01155         case XML_ATTRIBUTE_NODE:
01156         case XML_TEXT_NODE:
01157 
01158         /* we should error if we see a cdata  */
01159         case XML_CDATA_SECTION_NODE:
01160 
01161         /* we don't understand entities, so we should error */
01162         case XML_ENTITY_REF_NODE:
01163         case XML_ENTITY_NODE:
01164         case XML_ENTITY_DECL:
01165 
01166         /* we should have already gotten the doc node , but should error out on these*/
01167         case XML_DOCUMENT_NODE:
01168         case XML_DOCUMENT_TYPE_NODE:
01169         case XML_DOCUMENT_FRAG_NODE:
01170         case XML_HTML_DOCUMENT_NODE:
01171         case XML_DTD_NODE:
01172 
01173         /* not sure yet about these, but I think they are irellevant */
01174         case XML_ELEMENT_DECL:
01175         case XML_ATTRIBUTE_DECL:
01176         case XML_NAMESPACE_DECL:
01177 
01178         /* anything new we should error */
01179         default:
01180             return 0;
01181     }
01182 }
01183 
01184 /* some class member field helpers */
01185 int 
01186 CXMLTextDecoderStream::getFieldStringPtr(
01187   const CFieldDescriptor *      pFieldDescriptor,
01188   const llrp_u8_t **            pbuf,
01189   const llrp_u8_t **            pend)
01190 {
01191     CErrorDetails *             pError = &m_pDecoder->m_ErrorDetails;
01192     xmlNode *                   pSave;
01193 
01194     *pbuf = NULL;
01195     *pend = NULL;
01196 
01197     /* clear this out as its not valid anymore */
01198     m_pLastFieldNode = NULL;
01199 
01200     if(RC_OK != pError->m_eResultCode)
01201     {
01202         return 0;
01203     }
01204 
01205    /* get the first interesting node */
01206     while ((NULL != m_pCurrentChildNode) &&
01207            (isInsignificantNode(m_pCurrentChildNode) || 
01208             xmlIsBlankNode(m_pCurrentChildNode)))
01209     {
01210         m_pCurrentChildNode = m_pCurrentChildNode->next;
01211     }    
01212 
01213     if(NULL == m_pCurrentChildNode)
01214     {
01215         pError->m_eResultCode = RC_FieldUnderrun;
01216         pError->m_pWhatStr    = "underrun at field";
01217         pError->m_pRefType    = m_pRefType;
01218         pError->m_pRefField   = pFieldDescriptor;
01219         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
01220         return 0;
01221     }
01222 
01223     /* first interesting node had better be an element */
01224     if(m_pCurrentChildNode->type != XML_ELEMENT_NODE)
01225     {
01226         pError->m_eResultCode = RC_XMLInvalidNodeType;
01227         pError->m_pWhatStr    = "unexpected field value";
01228         pError->m_pRefType    = m_pRefType;
01229         pError->m_pRefField   = pFieldDescriptor;
01230         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;        
01231         return 0;
01232     }
01233 
01234     /* better match our field value */
01235     if(0 != strcmp((char*) m_pCurrentChildNode->name, 
01236                     pFieldDescriptor->m_pName))
01237     {
01238         pError->m_eResultCode = RC_XMLMissingField;
01239         pError->m_pWhatStr    = "missing field value";
01240         pError->m_pRefType    = m_pRefType;
01241         pError->m_pRefField   = pFieldDescriptor;
01242         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;        
01243         return 0;
01244     }
01245 
01246     /* save this in case someone wants to explore attributes */
01247     m_pLastFieldNode = m_pCurrentChildNode;
01248 
01249     /* use this to decode the field values */
01250     pSave = m_pCurrentChildNode->children;
01251 
01252     /* advance to the next one for the next field */
01253     m_pCurrentChildNode = m_pCurrentChildNode->next;
01254 
01255    /* get the first interesting node */
01256     while ((NULL !=pSave) &&
01257            (isInsignificantNode(pSave) ||
01258          xmlIsBlankNode(pSave)))
01259     {
01260         pSave = pSave->next;
01261     }    
01262 
01263     if(NULL == pSave)
01264     {
01265         /* its possible that this is an empty field value, which is
01266          * allowed in many cases in LLRP-XML. Let the condition
01267          * percolate and error out specifically where it is not
01268          * allowed */
01269         return 0;   
01270     }
01271 
01272     if(XML_TEXT_NODE != pSave->type)
01273     {
01274         pError->m_eResultCode = RC_XMLInvalidNodeType;
01275         pError->m_pWhatStr    = "invalid XML Node found during field decode";
01276         pError->m_pRefType    = m_pRefType;
01277         pError->m_pRefField   = pFieldDescriptor;
01278         pError->m_OtherDetail = (int) pSave->line;
01279         return 0;           
01280     }
01281 
01282     *pbuf = pSave->content;
01283 
01284     /* make sure there are no more interesting nodes */
01285     pSave = pSave->next;
01286     while ((NULL !=pSave) &&
01287            (isInsignificantNode(pSave) ||
01288             xmlIsBlankNode(pSave)))
01289     {
01290         pSave = pSave->next;
01291     }   
01292 
01293     if(pSave != NULL)
01294     {
01295         pError->m_eResultCode = RC_XMLExtraNode;
01296         pError->m_pWhatStr    = "extra XML node found";
01297         pError->m_pRefType    = m_pRefType;
01298         pError->m_pRefField   = pFieldDescriptor;
01299         pError->m_OtherDetail = (int) pSave->line;
01300         return 0;    
01301     }
01302 
01303     *pend = *pbuf + strlen((char*) *pbuf);
01304     return 1;
01305 }
01306 
01307 llrp_s64v_t
01308 CXMLTextDecoderStream::getSpacedVectorField (
01309   const CFieldDescriptor *      pFieldDescriptor,
01310   llrp_s64_t                    minValue,
01311   llrp_s64_t                    maxValue)
01312 {
01313     CErrorDetails *             pError = &m_pDecoder->m_ErrorDetails;
01314     const llrp_u8_t *           pTok;
01315     const llrp_u8_t *           pEnd;    
01316     const llrp_u8_t *           pTokEnd;    
01317     llrp_u16_t                  length;
01318     llrp_u16_t                  elementCount;
01319     llrp_s64v_t                 Value;
01320     llrp_u16_t                  count;
01321 
01322     if(RC_OK != pError->m_eResultCode)
01323     {
01324     /* already errd */
01325         return Value;
01326     }
01327 
01328     /* get the NULL terminates string from XML */
01329     if(!getFieldStringPtr(pFieldDescriptor, &pTok, &pEnd))
01330     {
01331       /* many of these (e.g. ReadData) are allowed to be empty */
01332        return Value;
01333     }
01334 
01335     length = cleanString(&pTok, &pEnd);
01336     elementCount = countElements((char *) pTok, length);
01337 
01338     /* create the final storage entity */ 
01339     Value = llrp_s64v_t(elementCount);
01340 
01341     for(count = 0;count <elementCount ; count++)
01342     {
01343     /* find the next starting token */
01344         while(isspace(*pTok) && (pTok < pEnd))
01345         {
01346             pTok++;
01347         }
01348 
01349         /* find the next ending token */
01350         for(pTokEnd = pTok; (!isspace(*pTokEnd)) && (*pTokEnd != '\0'); pTokEnd++)
01351         {
01352            /* nothing */
01353         } 
01354 
01355         /* get a single integer */
01356         Value.m_pValue[count] = getInteger(pFieldDescriptor, 
01357                                            pTok, 
01358                                            pTokEnd, 
01359                                            pError, 
01360                                            minValue, 
01361                                            maxValue);
01362         if(RC_OK != pError->m_eResultCode)
01363         {
01364             break;
01365         }
01366         /* get the next value */
01367         pTok = pTokEnd;
01368     }
01369 
01370     /* mark the length */
01371     Value.m_nValue = count;
01372 
01373     return Value;
01374 }
01375 
01376 llrp_s64v_t
01377 CXMLTextDecoderStream::getFixedVectorField (
01378   const CFieldDescriptor *      pFieldDescriptor,
01379   unsigned int                  vectorSize,
01380   llrp_s64_t                    minValue,
01381   llrp_s64_t                    maxValue)
01382 {
01383     CErrorDetails *             pError = &m_pDecoder->m_ErrorDetails;
01384     const llrp_u8_t *           pTok;
01385     const llrp_u8_t *           pEnd;    
01386     llrp_u16_t                  length;
01387     llrp_u16_t                  elementCount;
01388     llrp_s64v_t                 Value;
01389     llrp_u16_t                  count;
01390 
01391     if(RC_OK != pError->m_eResultCode)
01392     {
01393     /* already errd */
01394         return Value;
01395     }
01396 
01397     if(!getFieldStringPtr(pFieldDescriptor, &pTok, &pEnd))
01398     {
01399         /* these values are allowed to be empty */
01400         Value.m_nValue = 0;
01401         Value.m_pValue = NULL;
01402         return Value;
01403     }
01404 
01405     length = cleanString(&pTok, &pEnd);
01406 
01407     /* size should match exactly */
01408     if (length % vectorSize)
01409     {
01410         pError->m_eResultCode = RC_FieldAllocationFailed;
01411         pError->m_pWhatStr    = "field size must be multiple of basic type";
01412         pError->m_pRefType    = m_pRefType;
01413         pError->m_pRefField   = pFieldDescriptor;
01414         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
01415         return Value;
01416     }
01417 
01418     /* round up for element count */
01419     elementCount = (length +  vectorSize - 1)/vectorSize;
01420 
01421     /* create the final storage entity */ 
01422     Value = llrp_s64v_t(elementCount);
01423 
01424     for(count = 0;count <elementCount ; count++, pTok += vectorSize)
01425     {
01426         pEnd = pTok + vectorSize;
01427 
01428         /* get a single integer */
01429         Value.m_pValue[count] = getInteger(pFieldDescriptor, 
01430                                            pTok, 
01431                                            pEnd, 
01432                                            pError, 
01433                                            minValue, 
01434                                            maxValue);
01435 
01436         if(RC_OK != pError->m_eResultCode)
01437         {
01438             break;
01439         }
01440     }
01441 
01442     /* mark the length */
01443     Value.m_nValue = count;
01444 
01445     return Value;
01446 }
01447 
01448 
01449 llrp_s64_t
01450 CXMLTextDecoderStream::getIntegerField (
01451   const CFieldDescriptor *      pFieldDescriptor,
01452   llrp_s64_t                    minValue,
01453   llrp_s64_t                    maxValue)
01454 {
01455     CErrorDetails *             pError = &m_pDecoder->m_ErrorDetails;
01456     const llrp_u8_t *           pbuf;
01457     const llrp_u8_t *           pend;
01458     llrp_s64_t                  Value;
01459 
01460     memset(&Value, 0x00, sizeof(Value));
01461 
01462     if(RC_OK != pError->m_eResultCode)
01463     {
01464         /* already errd */
01465         return Value;
01466     }
01467 
01468     if(getFieldStringPtr(pFieldDescriptor, &pbuf, &pend))
01469     {
01470         cleanString(&pbuf, &pend);
01471         Value = getInteger(pFieldDescriptor, 
01472                            pbuf, 
01473                            pend, 
01474                            pError, 
01475                            minValue, 
01476                            maxValue);
01477     }
01478     else
01479     {
01480         pError->m_eResultCode = RC_FieldUnderrun;
01481         pError->m_pWhatStr    = "underrun at field no characters";
01482         pError->m_pRefType    = m_pRefType;
01483         pError->m_pRefField   = pFieldDescriptor;
01484         pError->m_OtherDetail = (int) m_pCurrentChildNode->line; 
01485         return 0;   
01486     }
01487 
01488     return Value;
01489 }
01490 
01491 
01492 llrp_s64_t CXMLTextDecoderStream::getInteger(
01493   const CFieldDescriptor *      pFieldDescriptor,
01494   const llrp_u8_t *             pbuf,
01495   const llrp_u8_t *             pend,
01496   CErrorDetails *               pError,
01497   llrp_s64_t                    minValue,
01498   llrp_s64_t                    maxValue)
01499 {
01500     llrp_s64_t                  Value;
01501     const llrp_u8_t           * endPtr = NULL;
01502 
01503 
01504     if(pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_U1)
01505     /* special case for U1 types as they can be
01506      * 'true' and 'false' strings */
01507     {
01508         endPtr = getSingleU1(pbuf, pend, &Value);
01509     }
01510     else if((pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E1 ) || 
01511             (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E2 ) ||
01512             (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E8 ) || 
01513             (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E16 ) || 
01514             (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E32 ) ||
01515             (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E8V ) )
01516     /* special case for enumerated fields as they are strings in XML*/
01517     {
01518         endPtr = getSingleEnum(pFieldDescriptor, pbuf, pend, &Value);  
01519     }
01520     else switch(pFieldDescriptor->m_eFieldFormat)
01521     {
01522         /* assume default is decimal for new formats */
01523         default:
01524         case CFieldDescriptor::FMT_NORMAL:
01525         case CFieldDescriptor::FMT_DEC:
01526             endPtr = getSingleDecimal(pbuf, pend, &Value);
01527         break;
01528         case CFieldDescriptor::FMT_HEX:
01529             endPtr = getSingleHexidecimal(pbuf, pend, &Value);
01530         break;
01531         case CFieldDescriptor::FMT_UTF8:
01532         {
01533             const llrp_u8_t  *ptr;
01534             /* not sure what to do for UTF 8 encoding as integer */
01535             for(ptr = pbuf; ptr < pend; ptr++)
01536             {
01537                 Value = 256*Value + *ptr;
01538             } 
01539         }
01540         break;
01541         case CFieldDescriptor::FMT_DATETIME:
01542             endPtr = getSingleTimestamp(pbuf, pend, &Value);
01543         break;
01544     }    
01545 
01546     if(endPtr == pbuf)
01547     /* if we didn't get any thing, it means there are illegal characters
01548      * and we could not import a field value */
01549     {
01550         pError->m_eResultCode = RC_XMLInvalidFieldCharacters;
01551         pError->m_pWhatStr    = "Illegal field value";
01552         pError->m_pRefType    = m_pRefType;
01553         pError->m_pRefField   = pFieldDescriptor;
01554         pError->m_OtherDetail = (int) m_pCurrentChildNode->line; 
01555         Value = 0;      
01556     }
01557     else if (endPtr != pend)
01558     /* if these don't match, there is still extra stuff
01559      * at the end.  This is always an error */
01560     {
01561         pError->m_eResultCode = RC_FieldOverrun;
01562         pError->m_pWhatStr    = "overrun at field extra characters";
01563         pError->m_pRefType    = m_pRefType;
01564         pError->m_pRefField   = pFieldDescriptor;
01565         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
01566         Value = 0;      
01567     }
01568     /* make sure the value is in range */ 
01569     else if((Value > maxValue) || (Value < minValue))
01570     /* we have an out of range value. This is always an error */
01571     {
01572         pError->m_eResultCode = RC_XMLOutOfRange;
01573         pError->m_pWhatStr    = "out of range value";
01574         pError->m_pRefType    = m_pRefType;
01575         pError->m_pRefField   = pFieldDescriptor;
01576         pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
01577         Value = 0;
01578     }    
01579     return Value;
01580 }
01581 
01582 /* static string helpers */
01583 
01584 const llrp_u8_t *
01585 CXMLTextDecoderStream::getSingleU1(
01586   const llrp_u8_t *             pbuf,
01587   const llrp_u8_t *             pend,
01588   llrp_s64_t *                  pValue)
01589 {
01590     const llrp_u8_t *           endPtr = pbuf;
01591     const int                   len = (int) (pend - pbuf);
01592 
01593     if((len >= 4) && (0 == strncasecmp("true", (char*) pbuf, 4)))
01594     {
01595         *pValue = 1;
01596         endPtr = pbuf + 4; 
01597     }
01598     else if ((len >= 5) && (0 == strncasecmp("false", (char*) pbuf, 5)))
01599     {
01600         *pValue = 0;
01601         endPtr = pbuf + 5; 
01602     } 
01603     else if ((len >= 1) && (*pbuf == '0'))
01604     {
01605         *pValue = 0;
01606         endPtr = pbuf + 1;
01607     }
01608     else if ((len >= 1) && (*pbuf == '1'))
01609     {
01610         *pValue = 0;
01611         endPtr = pbuf + 1;
01612     }
01613     return endPtr;  
01614 }
01615 
01616 const llrp_u8_t *
01617 CXMLTextDecoderStream::getSingleEnum(
01618   const CFieldDescriptor *      pFieldDescriptor,
01619   const llrp_u8_t *             pbuf,
01620   const llrp_u8_t *             pend,
01621   llrp_s64_t *                  pValue)
01622 {
01623     const llrp_u8_t *           endPtr = pbuf;
01624     const int                   length = (int) (pend - pbuf);
01625     const SEnumTableEntry *     pEntry;    
01626 
01627     *pValue = 0;
01628 
01629     for(
01630         pEntry = pFieldDescriptor->m_pEnumTable;
01631         NULL != pEntry->pName;
01632         pEntry++)
01633     {
01634         int len = (int) strlen(pEntry->pName);
01635         if((len == length) && 
01636            (memcmp(pbuf, pEntry->pName, len) == 0))
01637         {
01638             break;
01639         }
01640     }
01641 
01642     if(NULL == pEntry->pName)
01643     {
01644         return pbuf;
01645     }
01646    
01647     *pValue = pEntry->Value;
01648     endPtr = pbuf + length;     
01649     return endPtr;
01650 }
01651 
01652 const llrp_u8_t *
01653 CXMLTextDecoderStream::getSingleDecimal(
01654   const llrp_u8_t *             pbuf,
01655   const llrp_u8_t *             pend,
01656   llrp_s64_t *                  pValue)
01657 {
01658     int bNeg = 0;
01659     const llrp_u8_t *           endPtr;
01660 
01661     *pValue = 0;
01662 
01663     for(endPtr = pbuf; endPtr < pend; endPtr++)
01664     {
01665         if(*endPtr == '-')
01666         {
01667            bNeg = 1;
01668         } else if (isdigit(*endPtr))
01669         {
01670            *pValue = 10 * *pValue + (*endPtr - '0');
01671         }
01672         else
01673         {
01674            /* a character not allowed in a decimal integer */
01675            break;        
01676         }
01677     }
01678     if(bNeg)
01679     {
01680         *pValue *= -1;
01681     }
01682 
01683     return endPtr;
01684 }
01685 
01686 
01687 const llrp_u8_t *
01688 CXMLTextDecoderStream::getSingleHexidecimal(
01689   const llrp_u8_t *             pbuf,
01690   const llrp_u8_t *             pend,
01691   llrp_s64_t *                  pValue)
01692 {
01693     const llrp_u8_t *           endPtr;
01694 
01695     *pValue = 0;
01696     for(endPtr = pbuf; endPtr < pend; endPtr++)
01697     {
01698         if(isdigit(*endPtr))
01699         {
01700            *pValue = 16 * *pValue + (*endPtr - '0');
01701         }
01702         else if (*endPtr >= 'A' && *endPtr <= 'F')
01703         {
01704             *pValue = 16 * *pValue + (*endPtr - 'A' + 10);
01705         }
01706         else if (*endPtr >= 'a' && *endPtr <= 'f')
01707         {
01708             *pValue = 16 * *pValue + (*endPtr - 'a' + 10);
01709         }
01710         else 
01711         {
01712            /* a character not allowed in a decimal integer */
01713            break;         
01714         }
01715     }
01716     return endPtr;
01717 }
01718 
01719 
01720 int
01721 CXMLTextDecoderStream::cleanString(
01722   const llrp_u8_t **            ppbuf,
01723   const llrp_u8_t **            ppend)
01724 {
01725     /* skip leading spaces */
01726     while( isspace(**ppbuf) && (*ppbuf <= *ppend))
01727     {
01728       (*ppbuf)++;
01729     }
01730     /* skip trailing spaces except last separator */
01731     /* last separator could be space or NULL. */
01732     while((*ppend > *ppbuf) && (isspace(*(*ppend-1)) || (*(*ppend-1) == '\0')))
01733     {
01734        (*ppend)--;
01735     }
01736     return (int) (*ppend - *ppbuf);
01737 }
01738 
01739 /* gets a single char value from a non-NULL terminated buffer buffer.
01740  * If it fails to get one, reutrn value should == pbuf, other
01741  * wise EndPtr should point to one past amount consumed */
01742 static const llrp_u8_t *
01743 getSingleChar(
01744   const llrp_u8_t *             pbuf,
01745   const llrp_u8_t *             pend,
01746   llrp_s64_t *                  pValue)
01747 {
01748     const llrp_u8_t *           endPtr = pbuf;
01749     const int                   len = pend - pbuf;
01750 
01751     if(len >= 1) 
01752     {
01753         *pValue = *pbuf;
01754          endPtr = pbuf + 1;
01755     }
01756 
01757     return endPtr;
01758 }
01759 
01760 const llrp_u8_t *
01761 CXMLTextDecoderStream::getSingleTimestamp(
01762   const llrp_u8_t *             pbuf,
01763   const llrp_u8_t *             pend,
01764   llrp_s64_t *                  pValue)
01765 {
01766     const llrp_u8_t *           endPtr;
01767     const llrp_u8_t *           tmpPtr;
01768     struct tm importTime;
01769     llrp_s64_t micros = 0;
01770     llrp_s64_t temp = 0;
01771     time_t tt;
01772     int utc = 0;
01773     llrp_s64_t offset = 0;
01774 
01775     memset(&importTime, 0x00, sizeof(importTime));
01776 
01777     tmpPtr = pbuf;
01778     endPtr = (llrp_u8_t*) strptime((char*) tmpPtr, "%Y-%m-%dT%T", &importTime);
01779 
01780     if(endPtr == NULL) 
01781     {
01782         goto timeParseError;
01783     }
01784     
01785     /* we have a valid timestamp, but there may be more stuff */
01786     tmpPtr = endPtr;
01787     if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr) 
01788     {
01789         goto timeParseDone;
01790     }
01791 
01792     if(temp == '.')
01793     { 
01794         int length;
01795 
01796         /* try to get the microsecond value */
01797         tmpPtr = endPtr;
01798         if((endPtr = getSingleDecimal(tmpPtr, pend, &micros)) == tmpPtr)
01799         {
01800             goto timeParseError;
01801         }
01802 
01803         length = endPtr - tmpPtr;
01804         /* may not contain 6 decimal places */
01805         while(length < 6)
01806         {
01807             micros *= 10;
01808             length++;
01809         }
01810 
01811         if(length > 6) 
01812         {
01813             goto timeParseError;
01814         }
01815 
01816         /* look for more stuff that is optional */
01817         tmpPtr = endPtr;
01818         if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr) 
01819         {
01820             goto timeParseDone;
01821         }
01822     }
01823 
01824     /* timestamp could either have offset or Z for UTC (Zulu) */
01825     if(temp == '-' || temp == '+') 
01826     {
01827         int scale = 1;
01828         /* offset formats are hh or hh:mm from UTC */
01829     if(temp == '+')
01830         {
01831             scale = -1;
01832             /* The time is offset positively from UTC, which means we have to 
01833             ** subtract to get to UTC time */
01834         }
01835     utc = 1;
01836         tmpPtr = endPtr;
01837         if((endPtr = getSingleDecimal(tmpPtr, pend, &temp)) == (tmpPtr+2))
01838         {
01839             goto timeParseError;
01840         }
01841    
01842         offset = scale*temp*60*60;
01843        
01844         tmpPtr = endPtr;
01845         if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr) 
01846         {
01847             goto timeParseDone;
01848         }
01849      
01850         if(temp != ':') {
01851             goto timeParseError;
01852         }
01853 
01854         tmpPtr = endPtr;
01855         if((endPtr = getSingleDecimal(tmpPtr, pend, &temp)) == (tmpPtr+2))
01856         {
01857             goto timeParseError;
01858         }
01859 
01860         offset += (scale * temp * 60);
01861         
01862     }
01863     else if ((temp == 'z') || (temp == 'Z')) 
01864     {
01865     utc = 1;
01866     }
01867     /* fall through */
01868 
01869 timeParseDone:
01870 
01871     if(utc) 
01872     {
01873         tt = timegm(&importTime);
01874     } else 
01875     {
01876         tt = timelocal(&importTime);
01877     }
01878 
01879     /* make this into time since epoch at GMT (UTC) */
01880     if(tt != (time_t) -1)
01881     {
01882         /* LLRP format is 64-bit microseconds UTC. Conver  */
01883         *pValue = 1000000ll * (llrp_s64_t) (tt + offset) + micros;
01884         return endPtr;
01885     }
01886     /* fall through if time wasn't valid */
01887 timeParseError:
01888     endPtr = pbuf;
01889     return endPtr;
01890 }
01891 
01892 
01893 llrp_u16_t 
01894 CXMLTextDecoderStream::countElements(
01895   const char *                  pval, 
01896   int                           nval)
01897 {
01898     const llrp_u8_t *           pTok;
01899     const llrp_u8_t *           pEnd;
01900     llrp_u8_t                   lastChar;
01901     llrp_u16_t                  elements = 0;
01902 
01903     /* find out how many possible tokens there are.
01904      * This should limit our size of array we need */
01905 
01906     pTok = (llrp_u8_t*) &pval[0];
01907     pEnd = pTok + nval;
01908 
01909     /* skip leading spaces */
01910     for(lastChar = ' '; pTok < pEnd; pTok++)
01911     {
01912         if((!isspace(*pTok)) && (isspace(lastChar)))
01913         {
01914             elements++;
01915         }
01916         lastChar = *pTok;
01917     } 
01918 
01919     return elements;
01920 }
01921 
01922 };