LTKCPP-- LLRP Toolkit C Plus Plus Library
ltkcpp_xmltextdecode.cpp
Go to the documentation of this file.
1 
2 /*
3  *****************************************************************************
4  * *
5  * IMPINJ CONFIDENTIAL AND PROPRIETARY *
6  * *
7  * This source code is the sole property of Impinj, Inc. Reproduction or *
8  * utilization of this source code in whole or in part is forbidden without *
9  * the prior written consent of Impinj, Inc. *
10  * *
11  * (c) Copyright Impinj, Inc. 2007,2008. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <time.h>
31 #include <stdio.h>
32 
33 #include "ltkcpp_platform.h"
34 #include "ltkcpp_base.h"
35 
36 #include "libxml/parser.h"
37 #include "libxml/tree.h"
38 
39 #include "ltkcpp_xmltext.h"
40 
41 
42 namespace LLRP
43 {
44 
45 CXMLTextDecoder::CXMLTextDecoder (
46  const CTypeRegistry * pTypeRegistry,
47  char * pBuffer,
48  int nBuffer) : CDecoder(pTypeRegistry)
49 
50 {
51  /* set the line numbers for error reporting */
52  xmlLineNumbersDefault(1);
53 
54  /* Read in the XML from the buffer into the XML Reader */
55  m_pDoc = xmlReadMemory((char*) pBuffer, nBuffer, "noName.xml", NULL,
56  XML_PARSE_COMPACT | XML_PARSE_NONET);
57 
58  if(NULL != m_pDoc)
59  {
60  /* Initialize the other decoder state variables */
61  m_pxmlNodeTree = xmlDocGetRootElement(m_pDoc);
62  }
63  else
64  {
65  fprintf(stderr, "could not parse XML memory buffer");
66  }
67 }
68 
69 CXMLTextDecoder::CXMLTextDecoder (
70  const CTypeRegistry * pTypeRegistry,
71  struct _xmlNode * pNodeTree) : CDecoder(pTypeRegistry)
72 {
73  /* set the line numbers for error reporting */
74  xmlLineNumbersDefault(1);
75 
76  /* Read in the XML from the buffer into the XML Reader */
77  m_pDoc = NULL;
78  /* Initialize the other decoder state variables */
79  m_pxmlNodeTree = pNodeTree;
80 }
81 
82 CXMLTextDecoder::CXMLTextDecoder (
83  const CTypeRegistry * pTypeRegistry,
84  char * fname) : CDecoder(pTypeRegistry)
85 {
86  /* set the line numbers for error reporting */
87  xmlLineNumbersDefault(1);
88 
89  /* Read in the XML from the file into the XML Reader */
90  m_pDoc = xmlReadFile(fname,
91  NULL,
92  XML_PARSE_COMPACT | XML_PARSE_NONET);
93 
94  if(NULL != m_pDoc)
95  {
96  /* Initialize the other decoder state variables */
97  m_pxmlNodeTree = xmlDocGetRootElement(m_pDoc);
98  }
99  else
100  {
101  fprintf(stderr, "could not parse XML file");
102  }
103 }
104 
105 CXMLTextDecoder::~CXMLTextDecoder (void)
106 {
107  if(NULL != m_pDoc)
108  {
109  xmlFreeDoc(m_pDoc);
110  m_pDoc = NULL;
111  }
112  m_pxmlNodeTree = NULL;
113 }
114 
115 CMessage *
116 CXMLTextDecoder::decodeMessage (void)
117 {
118  CMessage * pMessage;
119  CXMLTextDecoderStream DecoderStream(this);
120  CErrorDetails *pError = &m_ErrorDetails;
121 
122  if(NULL == m_pxmlNodeTree)
123  {
124  pError->m_eResultCode = RC_MiscError;
125  pError->m_pWhatStr = "Unable to Extract XML Node Tree";
126  pError->m_pRefType = NULL;
127  pError->m_pRefField = NULL;
128  pError->m_OtherDetail = (int) 0;
129  return NULL;
130  }
131  pMessage = (CMessage *) DecoderStream.decodeElement(TRUE, TRUE);
132 
133  return pMessage;
134 }
135 
136 void
137 CXMLTextDecoder::cleanupParser (void)
138 {
139  xmlCleanupParser();
140 }
141 
142 CXMLTextDecoderStream::CXMLTextDecoderStream (
143  CXMLTextDecoder * pDecoder)
144 {
145 
146  m_pDecoder = pDecoder;
147  m_pEnclosingDecoderStream = NULL;
148  m_pRefType = NULL;
149  m_pTargetNode = pDecoder->m_pxmlNodeTree;
150  m_pCurrentChildNode = NULL;
151 }
152 
153 CXMLTextDecoderStream::CXMLTextDecoderStream (
154  CXMLTextDecoderStream * pEnclosingDecoderStream)
155 {
156  m_pDecoder = pEnclosingDecoderStream->m_pDecoder;
157  m_pEnclosingDecoderStream = pEnclosingDecoderStream;
158  m_pRefType = pEnclosingDecoderStream->m_pRefType;
159  m_pTargetNode = pEnclosingDecoderStream->m_pCurrentChildNode;
160  m_pCurrentChildNode = NULL;
161 }
162 
163 CElement *
164 CXMLTextDecoderStream::decodeElement (
165  int bAllowMessage,
166  int bSkipBlanks)
167 {
168  CErrorDetails *pError = &m_pDecoder->m_ErrorDetails;
169  const CTypeDescriptor* pTypeDescriptor;
170  llrp_u32_t MessageID = 0;
171  CElement * pElement;
172 
173  if(RC_OK != pError->m_eResultCode)
174  {
175  return NULL;
176  }
177 
178  /* get the first interesting node as the target node */
179  if(bSkipBlanks)
180  {
181  while ((NULL != m_pTargetNode) &&
182  ( isInsignificantNode(m_pTargetNode) ||
183  xmlIsBlankNode(m_pTargetNode)))
184  {
185  m_pTargetNode = m_pTargetNode->next;
186  }
187  }
188 
189  /* no interestig target node found. THis is OK as its an empty decode */
190  if(NULL == m_pTargetNode)
191  {
192  return NULL;
193  }
194 
195  /* first interesting node had better be an element */
196  if(m_pTargetNode->type != XML_ELEMENT_NODE)
197  {
198  pError->m_eResultCode = RC_XMLInvalidNodeType;
199  pError->m_pWhatStr = "unexpected XML node type";
200  pError->m_pRefType = m_pRefType;
201  pError->m_pRefField = NULL;
202  pError->m_OtherDetail = (int) m_pTargetNode->line;
203  return NULL;
204  }
205 
206  /* look up the type descriptor*/
207  pTypeDescriptor = m_pDecoder->m_pRegistry->lookupByName(
208  (char*) m_pTargetNode->name);
209 
210  if(NULL == pTypeDescriptor)
211  {
212  pError->m_eResultCode = RC_UnknownParameterType;
213  pError->m_pWhatStr = "unknown message or parameter type";
214  pError->m_pRefType = m_pRefType;
215  pError->m_pRefField = NULL;
216  pError->m_OtherDetail = (int) m_pTargetNode->line;
217  return NULL;
218  }
219 
220  m_pRefType = pTypeDescriptor;
221 
222  /* process messages a bit specially */
223  if(pTypeDescriptor->m_bIsMessage)
224  {
225  xmlChar * pMessageIDStr;
226 
227  if(!bAllowMessage)
228  {
229  pError->m_eResultCode = RC_MiscError;
230  pError->m_pWhatStr = "message as subparameter";
231  pError->m_pRefType = m_pRefType;
232  pError->m_pRefField = NULL;
233  pError->m_OtherDetail = (int) m_pTargetNode->line;
234  return NULL;
235  }
236 
237  /* get the messageID Attribute */
238  pMessageIDStr = xmlGetProp(m_pTargetNode,
239  (xmlChar*) "MessageID");
240  if(NULL != pMessageIDStr)
241  {
242  char * pArg = (char *) pMessageIDStr;
243  char * pTail = pArg + strlen((char*) pMessageIDStr);
244  char * pTmp;
245  cleanString((const llrp_u8_t **) &pArg, (const llrp_u8_t **) &pTail);
246  MessageID = strtoul(pArg, &pTmp, 10);
247  xmlFree(pMessageIDStr);
248 
249  if(pTail != pTmp)
250  {
251  /* malformed */
252  pError->m_eResultCode = RC_MiscError;
253  pError->m_pWhatStr = "malformed MessageID";
254  pError->m_pRefType = m_pRefType;
255  pError->m_pRefField = NULL;
256  pError->m_OtherDetail = (int) m_pTargetNode->line;
257  return NULL;
258  }
259  }
260  }
261 
262  /* create our element to hold the information */
263  pElement = pTypeDescriptor->constructElement();
264 
265  if(NULL == pElement)
266  {
267  pError->m_eResultCode = RC_MessageAllocationFailed;
268  pError->m_pWhatStr = "element allocation failed";
269  pError->m_pRefType = m_pRefType;
270  pError->m_pRefField = NULL;
271  pError->m_OtherDetail = (int) m_pTargetNode->line;
272  return NULL;
273  }
274 
275  /* only write the message ID for messages */
276  if(pTypeDescriptor->m_bIsMessage)
277  {
278  ((CMessage *) pElement)->setMessageID(MessageID);
279  }
280 
281  /* now switch to decode the children which are the
282  * fields and sub-parameters of this element */
283  m_pCurrentChildNode = m_pTargetNode->children;
284 
285  /* decode the fields first */
286  pTypeDescriptor->m_pfDecodeFields(this, pElement);
287 
288  if(RC_OK != pError->m_eResultCode)
289  {
290  delete pElement;
291  return NULL;
292  }
293 
294  /*
295  * Subparameters.
296  *
297  * loop through all the remaining children of the target node and try to find sub-parameters.
298  * We are done when we don't have any more or error
299  */
300  for(; m_pCurrentChildNode != NULL;
301  m_pCurrentChildNode = m_pCurrentChildNode->next)
302  {
303  CElement * pSubElement;
304  CParameter * pParameter;
305 
306  if(isInsignificantNode(m_pCurrentChildNode))
307  {
308  continue;
309  }
310 
311  if(xmlIsBlankNode(m_pCurrentChildNode))
312  {
313  continue;
314  }
315 
316  CXMLTextDecoderStream NestStream(this);
317 
318  pSubElement = NestStream.decodeElement(FALSE, FALSE);
319 
320  /* nothing more to decode as a sub-element or failure */
321  if(NULL == pSubElement)
322  {
323  break;
324  }
325 
326  pParameter = (CParameter *) pSubElement;
327 
328  pParameter->m_pParent = pElement;
329  pElement->addSubParameterToAllList(pParameter);
330  }
331 
332  if(RC_OK != pError->m_eResultCode)
333  {
334  delete pElement;
335  return NULL;
336  }
337 
338  pElement->assimilateSubParameters(pError);
339 
340  if(RC_OK != pError->m_eResultCode)
341  {
342  delete pElement;
343  return NULL;
344  }
345 
346  return pElement;
347 }
348 
350 llrp_u8_t
351 CXMLTextDecoderStream::get_u8 (
352  const CFieldDescriptor * pFieldDesc)
353 {
354  llrp_u8_t Value;
355  Value = (llrp_u8_t) getIntegerField(pFieldDesc, MIN_U8, MAX_U8);
356  return Value;
357 }
358 
360 llrp_s8_t
361 CXMLTextDecoderStream::get_s8 (
362  const CFieldDescriptor * pFieldDesc)
363 {
364  llrp_s8_t Value;
365  Value = (llrp_s8_t) getIntegerField(pFieldDesc, MIN_S8, MAX_S8);
366  return Value;
367 }
368 
370 llrp_u8v_t
371 CXMLTextDecoderStream::get_u8v (
372  const CFieldDescriptor * pFieldDesc)
373 {
374  CErrorDetails * pError;
375  llrp_u8v_t Value;
376  llrp_s64v_t Tmp;
377 
378  pError = &m_pDecoder->m_ErrorDetails;
379 
380  switch(pFieldDesc->m_eFieldFormat)
381  {
382  /* assume normal format here is decimal */
383  case CFieldDescriptor::FMT_NORMAL:
384  case CFieldDescriptor::FMT_DEC:
385  Tmp = getSpacedVectorField(pFieldDesc, MIN_U8, MAX_U8);
386  break;
387  case CFieldDescriptor::FMT_HEX:
388  Tmp = getFixedVectorField(pFieldDesc, 2, MIN_U8, MAX_U8);
389  break;
390  default:
391  case CFieldDescriptor::FMT_UTF8:
392  case CFieldDescriptor::FMT_DATETIME:
393  if(NULL != pError)
394  {
395  pError->m_eResultCode = RC_MiscError;
396  pError->m_pWhatStr = "Format type not support for field";
397  pError->m_pRefType = m_pRefType;
398  pError->m_pRefField = pFieldDesc;
399  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
400  }
401  break;
402  }
403 
404  if(Tmp.m_nValue)
405  {
406  llrp_u16_t nValue;
407 
408  nValue = Tmp.m_nValue;
409  Value = llrp_u8v_t(nValue);
410  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
411  {
412  unsigned int Ix;
413 
414  for(Ix = 0; Ix < nValue; Ix++)
415  {
416  Value.m_pValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
417  }
418  }
419  }
420 
421  return Value;
422 }
423 
425 llrp_s8v_t
426 CXMLTextDecoderStream::get_s8v (
427  const CFieldDescriptor * pFieldDesc)
428 {
429  CErrorDetails * pError;
430  llrp_s8v_t Value;
431  llrp_s64v_t Tmp;
432 
433  pError = &m_pDecoder->m_ErrorDetails;
434 
435  switch(pFieldDesc->m_eFieldFormat)
436  {
437  /* assume normal format here is decimal */
438  case CFieldDescriptor::FMT_NORMAL:
439  case CFieldDescriptor::FMT_DEC:
440  Tmp = getSpacedVectorField(pFieldDesc, MIN_S8, MAX_S8);
441  break;
442  case CFieldDescriptor::FMT_HEX:
443  Tmp = getFixedVectorField(pFieldDesc, 2, MIN_S8, MAX_S8);
444  break;
445  default:
446  case CFieldDescriptor::FMT_UTF8:
447  case CFieldDescriptor::FMT_DATETIME:
448  if(NULL != pError)
449  {
450  pError->m_eResultCode = RC_MiscError;
451  pError->m_pWhatStr = "Format type not support for field";
452  pError->m_pRefType = m_pRefType;
453  pError->m_pRefField = pFieldDesc;
454  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
455  }
456  break;
457  }
458 
459  if(Tmp.m_nValue)
460  {
461  llrp_u16_t nValue;
462 
463  nValue = Tmp.m_nValue;
464  Value = llrp_s8v_t(nValue);
465  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
466  {
467  unsigned int Ix;
468 
469  for(Ix = 0; Ix < nValue; Ix++)
470  {
471  Value.m_pValue[Ix] = (llrp_s8_t) Tmp.m_pValue[Ix];
472  }
473  }
474  }
475 
476  return Value;
477 }
478 
479 /*
480  * 16-bit types
481  */
482 
484 llrp_u16_t
485 CXMLTextDecoderStream::get_u16 (
486  const CFieldDescriptor * pFieldDesc)
487 {
488  llrp_u16_t Value;
489  Value = (llrp_u16_t) getIntegerField(pFieldDesc, MIN_U16, MAX_U16);
490  return Value;
491 }
492 
494 llrp_s16_t
495 CXMLTextDecoderStream::get_s16 (
496  const CFieldDescriptor * pFieldDesc)
497 {
498  llrp_s16_t Value;
499  Value = (llrp_s16_t) getIntegerField(pFieldDesc, MIN_S16, MAX_S16);
500  return Value;
501 }
502 
504 llrp_u16v_t
505 CXMLTextDecoderStream::get_u16v (
506  const CFieldDescriptor * pFieldDesc)
507 {
508  CErrorDetails * pError;
509  llrp_u16v_t Value;
510  llrp_s64v_t Tmp;
511 
512  pError = &m_pDecoder->m_ErrorDetails;
513 
514  switch(pFieldDesc->m_eFieldFormat)
515  {
516  /* assume normal format here is decimal */
517  case CFieldDescriptor::FMT_NORMAL:
518  case CFieldDescriptor::FMT_DEC:
519  case CFieldDescriptor::FMT_HEX:
520  Tmp = getSpacedVectorField(pFieldDesc, MIN_U16, MAX_U16);
521  break;
522  default:
523  case CFieldDescriptor::FMT_UTF8:
524  case CFieldDescriptor::FMT_DATETIME:
525  if(NULL != pError)
526  {
527  pError->m_eResultCode = RC_MiscError;
528  pError->m_pWhatStr = "Format type not support for field";
529  pError->m_pRefType = m_pRefType;
530  pError->m_pRefField = pFieldDesc;
531  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
532  }
533  break;
534  }
535 
536  if(Tmp.m_nValue)
537  {
538  llrp_u16_t nValue;
539 
540  nValue = Tmp.m_nValue;
541  Value = llrp_u16v_t(nValue);
542  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
543  {
544  unsigned int Ix;
545 
546  for(Ix = 0; Ix < nValue; Ix++)
547  {
548  Value.m_pValue[Ix] = (llrp_u16_t) Tmp.m_pValue[Ix];
549  }
550  }
551  }
552  return Value;
553 }
554 
556 llrp_s16v_t
557 CXMLTextDecoderStream::get_s16v (
558  const CFieldDescriptor * pFieldDesc)
559 {
560  CErrorDetails * pError;
561  llrp_s16v_t Value;
562  llrp_s64v_t Tmp;
563 
564  pError = &m_pDecoder->m_ErrorDetails;
565 
566  switch(pFieldDesc->m_eFieldFormat)
567  {
568  /* assume normal format here is decimal */
569  case CFieldDescriptor::FMT_NORMAL:
570  case CFieldDescriptor::FMT_DEC:
571  case CFieldDescriptor::FMT_HEX:
572  Tmp = getSpacedVectorField(pFieldDesc, MIN_S16, MAX_S16);
573  break;
574  default:
575  case CFieldDescriptor::FMT_UTF8:
576  case CFieldDescriptor::FMT_DATETIME:
577  if(NULL != pError)
578  {
579  pError->m_eResultCode = RC_MiscError;
580  pError->m_pWhatStr = "Format type not support for field";
581  pError->m_pRefType = m_pRefType;
582  pError->m_pRefField = pFieldDesc;
583  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
584  }
585  break;
586  }
587 
588  if(Tmp.m_nValue)
589  {
590  llrp_u16_t nValue;
591 
592  nValue = Tmp.m_nValue;
593  Value = llrp_s16v_t(nValue);
594  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
595  {
596  unsigned int Ix;
597 
598  for(Ix = 0; Ix < nValue; Ix++)
599  {
600  Value.m_pValue[Ix] = (llrp_s16_t) Tmp.m_pValue[Ix];
601  }
602  }
603  }
604  return Value;
605 }
606 
607 /*
608  * 32-bit types
609  */
610 
612 llrp_u32_t
613 CXMLTextDecoderStream::get_u32 (
614  const CFieldDescriptor * pFieldDesc)
615 {
616  llrp_u32_t Value;
617  Value = (llrp_u32_t) getIntegerField(pFieldDesc, MIN_U32, MAX_U32);
618  return Value;
619 }
620 
622 llrp_s32_t
623 CXMLTextDecoderStream::get_s32 (
624  const CFieldDescriptor * pFieldDesc)
625 {
626  llrp_s32_t Value;
627  Value = (llrp_s32_t) getIntegerField(pFieldDesc, MIN_S32, MAX_S32);
628  return Value;
629 }
630 
632 llrp_u32v_t
633 CXMLTextDecoderStream::get_u32v (
634  const CFieldDescriptor * pFieldDesc)
635 {
636  CErrorDetails * pError;
637  llrp_u32v_t Value;
638  llrp_s64v_t Tmp;
639 
640  pError = &m_pDecoder->m_ErrorDetails;
641 
642  switch(pFieldDesc->m_eFieldFormat)
643  {
644  /* assume normal format here is decimal */
645  case CFieldDescriptor::FMT_NORMAL:
646  case CFieldDescriptor::FMT_DEC:
647  case CFieldDescriptor::FMT_HEX:
648  Tmp = getSpacedVectorField(pFieldDesc, MIN_U32, MAX_U32);
649  break;
650  default:
651  case CFieldDescriptor::FMT_UTF8:
652  case CFieldDescriptor::FMT_DATETIME:
653  if(NULL != pError)
654  {
655  pError->m_eResultCode = RC_MiscError;
656  pError->m_pWhatStr = "Format type not support for field";
657  pError->m_pRefType = m_pRefType;
658  pError->m_pRefField = pFieldDesc;
659  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
660  }
661  break;
662  }
663 
664  if(Tmp.m_nValue)
665  {
666  llrp_u16_t nValue;
667 
668  nValue = Tmp.m_nValue;
669  Value = llrp_u32v_t(nValue);
670  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
671  {
672  unsigned int Ix;
673 
674  for(Ix = 0; Ix < nValue; Ix++)
675  {
676  Value.m_pValue[Ix] = (llrp_u32_t) Tmp.m_pValue[Ix];
677  }
678  }
679  }
680  return Value;
681 }
682 
684 llrp_s32v_t
685 CXMLTextDecoderStream::get_s32v (
686  const CFieldDescriptor * pFieldDesc)
687 {
688  CErrorDetails * pError;
689  llrp_s32v_t Value;
690  llrp_s64v_t Tmp;
691 
692  pError = &m_pDecoder->m_ErrorDetails;
693 
694  switch(pFieldDesc->m_eFieldFormat)
695  {
696  /* assume normal format here is decimal */
697  case CFieldDescriptor::FMT_NORMAL:
698  case CFieldDescriptor::FMT_DEC:
699  case CFieldDescriptor::FMT_HEX:
700  Tmp = getSpacedVectorField(pFieldDesc, MIN_S32, MAX_S32);
701  break;
702  default:
703  case CFieldDescriptor::FMT_UTF8:
704  case CFieldDescriptor::FMT_DATETIME:
705  if(NULL != pError)
706  {
707  pError->m_eResultCode = RC_MiscError;
708  pError->m_pWhatStr = "Format type not support for field";
709  pError->m_pRefType = m_pRefType;
710  pError->m_pRefField = pFieldDesc;
711  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
712  }
713  break;
714  }
715 
716  if(Tmp.m_nValue)
717  {
718  llrp_u16_t nValue;
719 
720  nValue = Tmp.m_nValue;
721  Value = llrp_s32v_t(nValue);
722  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
723  {
724  unsigned int Ix;
725 
726  for(Ix = 0; Ix < nValue; Ix++)
727  {
728  Value.m_pValue[Ix] = (llrp_s32_t) Tmp.m_pValue[Ix];
729  }
730  }
731  }
732  return Value;
733 }
734 
735 /*
736  * 64-bit types
737  */
738 
740 llrp_u64_t
741 CXMLTextDecoderStream::get_u64 (
742  const CFieldDescriptor * pFieldDesc)
743 {
744  llrp_u64_t Value;
745  Value = (llrp_u64_t) getIntegerField(pFieldDesc, MIN_U64, MAX_U64);
746  return Value;
747 }
748 
750 llrp_s64_t
751 CXMLTextDecoderStream::get_s64 (
752  const CFieldDescriptor * pFieldDesc)
753 {
754  llrp_s64_t Value;
755  Value = (llrp_s64_t) getIntegerField(pFieldDesc, MIN_S64, MAX_S64);
756  return Value;
757 }
758 
760 llrp_u64v_t
761 CXMLTextDecoderStream::get_u64v (
762  const CFieldDescriptor * pFieldDesc)
763 {
764  CErrorDetails * pError;
765  llrp_u64v_t Value;
766  llrp_s64v_t Tmp;
767 
768  pError = &m_pDecoder->m_ErrorDetails;
769 
770  switch(pFieldDesc->m_eFieldFormat)
771  {
772  /* assume normal format here is decimal */
773  case CFieldDescriptor::FMT_NORMAL:
774  case CFieldDescriptor::FMT_DEC:
775  case CFieldDescriptor::FMT_HEX:
776  case CFieldDescriptor::FMT_DATETIME:
777  Tmp = getSpacedVectorField(pFieldDesc, MIN_U64, MAX_U64);
778  break;
779  default:
780  case CFieldDescriptor::FMT_UTF8:
781  if(NULL != pError)
782  {
783  pError->m_eResultCode = RC_MiscError;
784  pError->m_pWhatStr = "Format type not support for field";
785  pError->m_pRefType = m_pRefType;
786  pError->m_pRefField = pFieldDesc;
787  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
788  }
789  break;
790  }
791 
792  if(Tmp.m_nValue)
793  {
794  llrp_u16_t nValue;
795 
796  nValue = Tmp.m_nValue;
797  Value = llrp_u64v_t(nValue);
798  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
799  {
800  unsigned int Ix;
801 
802  for(Ix = 0; Ix < nValue; Ix++)
803  {
804  Value.m_pValue[Ix] = (llrp_u64_t) Tmp.m_pValue[Ix];
805  }
806  }
807  }
808  return Value;
809 }
810 
812 llrp_s64v_t
813 CXMLTextDecoderStream::get_s64v (
814  const CFieldDescriptor * pFieldDesc)
815 {
816  llrp_s64v_t Value;
817  Value = getSpacedVectorField(pFieldDesc, MIN_S64, MAX_S64);
818  return Value;
819 }
820 
821 /*
822  * Special types
823  */
824 
826 llrp_u1_t
827 CXMLTextDecoderStream::get_u1 (
828  const CFieldDescriptor * pFieldDesc)
829 {
830  llrp_u1_t Value;
831  Value = (llrp_u1_t) getIntegerField(pFieldDesc, 0, 1);
832  return Value;
833 }
834 
836 llrp_u1v_t
837 CXMLTextDecoderStream::get_u1v (
838  const CFieldDescriptor * pFieldDesc)
839 {
840  CErrorDetails * pError;
841  llrp_u1v_t Value;
842  llrp_s64v_t Tmp;
843 
844  pError = &m_pDecoder->m_ErrorDetails;
845  Tmp = getFixedVectorField(pFieldDesc, 2, 0, 255);
846 
847  if(Tmp.m_nValue)
848  {
849  llrp_u16_t nValue;
850 
851  nValue = Tmp.m_nValue;
852  Value = llrp_u1v_t(nValue*8);
853  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
854  {
855  unsigned int Ix;
856  xmlChar * pCountStr;
857 
858  for(Ix = 0; Ix < nValue; Ix++)
859  {
860  Value.m_pValue[Ix] = (llrp_u1_t) Tmp.m_pValue[Ix];
861  }
862  /* bit length could be shorter than this. Use this if there
863  * is no attribute */
864  Value.m_nBit = Tmp.m_nValue * 8;
865 
866  /* find the XML attribute for Count and fix the array */
867  if(NULL != m_pLastFieldNode)
868  {
869  pCountStr = xmlGetProp(m_pLastFieldNode,
870  (xmlChar*) "Count");
871  if(NULL != pCountStr)
872  {
873  char * pArg = (char *) pCountStr;
874  char * pTail = pArg + strlen((char*) pCountStr);
875  llrp_u16_t nBits;
876 
877  nBits = (llrp_u16_t) strtoul(pArg, &pTail, 10);
878  if( (*pTail != 0) ||
879  (nBits > (Tmp.m_nValue * 8)))
880  {
881  /* malformed */
882  pError->m_eResultCode = RC_MiscError;
883  pError->m_pWhatStr = "malformed Count Attribute";
884  pError->m_pRefType = m_pRefType;
885  pError->m_pRefField = pFieldDesc;
886  pError->m_OtherDetail = (int) m_pLastFieldNode->line;
887  }
888  else
889  {
890  llrp_u16_t lastByteBits;
891  llrp_u8_t lastByteMask;
892 
893  Value.m_nBit = nBits;
894 
895  /* zero off the last bits if they were non-zero */
896  lastByteBits = nBits % 8;
897  if(lastByteBits)
898  {
899  /* convert the bit position to a mask */
900  lastByteBits = 8 - lastByteBits;
901  lastByteMask = (1 << lastByteBits) - 1;
902  /* invert mask */
903  lastByteMask = ~lastByteMask;
904  /* clear bits */
905  Value.m_pValue[Ix] &= lastByteMask;
906  }
907  }
908  xmlFree(pCountStr);
909  }
910  }
911  }
912  }
913  return Value;
914 }
915 
917 llrp_u2_t
918 CXMLTextDecoderStream::get_u2 (
919  const CFieldDescriptor * pFieldDesc)
920 {
921  llrp_u2_t Value;
922  Value = (llrp_u2_t) getIntegerField(pFieldDesc, 0, 3);
923  return Value;
924 }
925 
927 llrp_u96_t
928 CXMLTextDecoderStream::get_u96 (
929  const CFieldDescriptor * pFieldDesc)
930 {
931  CErrorDetails * pError;
932  llrp_u96_t Value;
933  llrp_s64v_t Tmp;
934  unsigned int Ix;
935 
936  pError = &m_pDecoder->m_ErrorDetails;
937 
938  Tmp = getFixedVectorField( pFieldDesc, 2, 0, 255);
939 
940  if((RC_OK != pError->m_eResultCode) && (Tmp.m_nValue != 12))
941  {
942  if(NULL != pError)
943  {
944  pError->m_eResultCode = RC_MiscError;
945  pError->m_pWhatStr = "Illegal length u96 field";
946  pError->m_pRefType = m_pRefType;
947  pError->m_pRefField = pFieldDesc;
948  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
949  }
950  return Value;
951  }
952 
953  /* convert to this type */
954  for(Ix = 0; Ix < Tmp.m_nValue; Ix++)
955  {
956  Value.m_aValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
957  }
958 
959  return Value;
960 }
961 
963 llrp_utf8v_t
964 CXMLTextDecoderStream::get_utf8v (
965  const CFieldDescriptor * pFieldDesc)
966 {
967  llrp_utf8v_t Value;
968  llrp_u16_t nValue;
969  const llrp_u8_t * pbuf;
970  const llrp_u8_t * pend;
971 
972  if(getFieldStringPtr(pFieldDesc, &pbuf, &pend))
973  {
974  nValue = (llrp_u16_t) strlen((char*) pbuf);
975  Value = llrp_utf8v_t(nValue);
976 
977  if(verifyVectorAllocation(Value.m_pValue, pFieldDesc))
978  {
979  unsigned int Ix;
980 
981  for(Ix = 0; Ix < nValue; Ix++)
982  {
983  Value.m_pValue[Ix] = pbuf[Ix];
984  }
985  }
986  }
987  else
988  {
989  /* its valid for UTF8 strings to be empty */
990  Value.m_nValue=0;
991  Value.m_pValue=NULL;
992  }
993  return Value;
994 }
995 
997 llrp_bytesToEnd_t
998 CXMLTextDecoderStream::get_bytesToEnd (
999  const CFieldDescriptor * pFieldDesc)
1000 {
1001  llrp_bytesToEnd_t Value;
1002  llrp_s64v_t Tmp;
1003  unsigned int Ix;
1004 
1005  Tmp = getFixedVectorField( pFieldDesc, 2, 0, 255);
1006 
1007  if(verifyVectorAllocation(Tmp.m_pValue, pFieldDesc))
1008  {
1009  /* build and convert */
1010  Value = llrp_bytesToEnd_t(Tmp.m_nValue);
1011  if(verifyVectorAllocation(Tmp.m_pValue, pFieldDesc))
1012  {
1013  /* convert to this type */
1014  for(Ix = 0; Ix < Tmp.m_nValue; Ix++)
1015  {
1016  Value.m_pValue[Ix] = (llrp_byte_t) Tmp.m_pValue[Ix];
1017  }
1018  Value.m_nValue = Tmp.m_nValue;
1019  }
1020  }
1021  return Value;
1022 }
1023 
1024 /*
1025  * Enumerated types of various sizes
1026  */
1027 
1029 int
1030 CXMLTextDecoderStream::get_e1 (
1031  const CFieldDescriptor * pFieldDesc)
1032 {
1033  int Value;
1034  Value = (int) getIntegerField(pFieldDesc, 0, 1);
1035  return Value;
1036 }
1037 
1039 int
1040 CXMLTextDecoderStream::get_e2 (
1041  const CFieldDescriptor * pFieldDesc)
1042 {
1043  int Value;
1044  Value = (int) getIntegerField(pFieldDesc, 0, 3);
1045  return Value;
1046 }
1047 
1049 int
1050 CXMLTextDecoderStream::get_e8 (
1051  const CFieldDescriptor * pFieldDesc)
1052 {
1053  int Value;
1054  Value = (int) getIntegerField(pFieldDesc, MIN_U8, MAX_U8);
1055  return Value;
1056 }
1057 
1059 int
1060 CXMLTextDecoderStream::get_e16 (
1061  const CFieldDescriptor * pFieldDesc)
1062 {
1063  int Value;
1064  Value = (int) getIntegerField(pFieldDesc, MIN_U16, MAX_U16);
1065  return Value;
1066 }
1067 
1069 int
1070 CXMLTextDecoderStream::get_e32 (
1071  const CFieldDescriptor * pFieldDesc)
1072 {
1073  int Value;
1074  Value = (int) getIntegerField(pFieldDesc, MIN_U32, MAX_U32);
1075  return Value;
1076 }
1077 
1079 llrp_u8v_t
1080 CXMLTextDecoderStream::get_e8v (
1081  const CFieldDescriptor * pFieldDesc)
1082 {
1083  llrp_u8v_t Value;
1084  llrp_s64v_t Tmp;
1085 
1086  Tmp = getSpacedVectorField( pFieldDesc, MIN_U8, MAX_U8);
1087  if(Tmp.m_nValue)
1088  {
1089  llrp_u16_t nValue;
1090 
1091  nValue = Tmp.m_nValue;
1092  Value = llrp_u8v_t(nValue);
1093  if(verifyVectorAllocation(Value.m_pValue,pFieldDesc))
1094  {
1095  unsigned int Ix;
1096 
1097  for(Ix = 0; Ix < nValue; Ix++)
1098  {
1099  Value.m_pValue[Ix] = (llrp_u8_t) Tmp.m_pValue[Ix];
1100  }
1101  }
1102  }
1103  return Value;
1104 }
1105 
1106 /* @brief skips a number of reserved bits and discards during the encode/decode process */
1107 void
1108 CXMLTextDecoderStream::get_reserved (
1109  unsigned int nBits)
1110 {
1111  return;
1112 }
1113 
1114 llrp_bool_t
1115 CXMLTextDecoderStream::verifyVectorAllocation (
1116  const void * pValue,
1117  const CFieldDescriptor * pFieldDescriptor)
1118 {
1119  if(NULL == pValue)
1120  {
1121  CErrorDetails * pError = &m_pDecoder->m_ErrorDetails;
1122 
1123  pError->m_eResultCode = RC_FieldAllocationFailed;
1124  pError->m_pWhatStr = "field allocation failed";
1125  pError->m_pRefType = m_pRefType;
1126  pError->m_pRefField = pFieldDescriptor;
1127  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1128 
1129  return FALSE;
1130  }
1131  else
1132  {
1133  return TRUE;
1134  }
1135 }
1136 
1137 int
1138 CXMLTextDecoderStream::isInsignificantNode (
1139  struct _xmlNode * pnode)
1140 {
1141  switch(pnode->type)
1142  {
1143  /* don't process comments or notations */
1144  case XML_COMMENT_NODE:
1145  case XML_NOTATION_NODE:
1146  /* ignore includes */
1147  case XML_XINCLUDE_START:
1148  case XML_XINCLUDE_END:
1149  /* don't read processing instructions */
1150  case XML_PI_NODE:
1151  return 1;
1152 
1153  /* hopefully we only see these type of nodes */
1154  case XML_ELEMENT_NODE:
1155  case XML_ATTRIBUTE_NODE:
1156  case XML_TEXT_NODE:
1157 
1158  /* we should error if we see a cdata */
1159  case XML_CDATA_SECTION_NODE:
1160 
1161  /* we don't understand entities, so we should error */
1162  case XML_ENTITY_REF_NODE:
1163  case XML_ENTITY_NODE:
1164  case XML_ENTITY_DECL:
1165 
1166  /* we should have already gotten the doc node , but should error out on these*/
1167  case XML_DOCUMENT_NODE:
1168  case XML_DOCUMENT_TYPE_NODE:
1169  case XML_DOCUMENT_FRAG_NODE:
1170  case XML_HTML_DOCUMENT_NODE:
1171  case XML_DTD_NODE:
1172 
1173  /* not sure yet about these, but I think they are irellevant */
1174  case XML_ELEMENT_DECL:
1175  case XML_ATTRIBUTE_DECL:
1176  case XML_NAMESPACE_DECL:
1177 
1178  /* anything new we should error */
1179  default:
1180  return 0;
1181  }
1182 }
1183 
1184 /* some class member field helpers */
1185 int
1186 CXMLTextDecoderStream::getFieldStringPtr(
1187  const CFieldDescriptor * pFieldDescriptor,
1188  const llrp_u8_t ** pbuf,
1189  const llrp_u8_t ** pend)
1190 {
1191  CErrorDetails * pError = &m_pDecoder->m_ErrorDetails;
1192  xmlNode * pSave;
1193 
1194  *pbuf = NULL;
1195  *pend = NULL;
1196 
1197  /* clear this out as its not valid anymore */
1198  m_pLastFieldNode = NULL;
1199 
1200  if(RC_OK != pError->m_eResultCode)
1201  {
1202  return 0;
1203  }
1204 
1205  /* get the first interesting node */
1206  while ((NULL != m_pCurrentChildNode) &&
1207  (isInsignificantNode(m_pCurrentChildNode) ||
1208  xmlIsBlankNode(m_pCurrentChildNode)))
1209  {
1210  m_pCurrentChildNode = m_pCurrentChildNode->next;
1211  }
1212 
1213  if(NULL == m_pCurrentChildNode)
1214  {
1215  pError->m_eResultCode = RC_FieldUnderrun;
1216  pError->m_pWhatStr = "underrun at field";
1217  pError->m_pRefType = m_pRefType;
1218  pError->m_pRefField = pFieldDescriptor;
1219  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1220  return 0;
1221  }
1222 
1223  /* first interesting node had better be an element */
1224  if(m_pCurrentChildNode->type != XML_ELEMENT_NODE)
1225  {
1226  pError->m_eResultCode = RC_XMLInvalidNodeType;
1227  pError->m_pWhatStr = "unexpected field value";
1228  pError->m_pRefType = m_pRefType;
1229  pError->m_pRefField = pFieldDescriptor;
1230  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1231  return 0;
1232  }
1233 
1234  /* better match our field value */
1235  if(0 != strcmp((char*) m_pCurrentChildNode->name,
1236  pFieldDescriptor->m_pName))
1237  {
1238  pError->m_eResultCode = RC_XMLMissingField;
1239  pError->m_pWhatStr = "missing field value";
1240  pError->m_pRefType = m_pRefType;
1241  pError->m_pRefField = pFieldDescriptor;
1242  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1243  return 0;
1244  }
1245 
1246  /* save this in case someone wants to explore attributes */
1247  m_pLastFieldNode = m_pCurrentChildNode;
1248 
1249  /* use this to decode the field values */
1250  pSave = m_pCurrentChildNode->children;
1251 
1252  /* advance to the next one for the next field */
1253  m_pCurrentChildNode = m_pCurrentChildNode->next;
1254 
1255  /* get the first interesting node */
1256  while ((NULL !=pSave) &&
1257  (isInsignificantNode(pSave) ||
1258  xmlIsBlankNode(pSave)))
1259  {
1260  pSave = pSave->next;
1261  }
1262 
1263  if(NULL == pSave)
1264  {
1265  /* its possible that this is an empty field value, which is
1266  * allowed in many cases in LLRP-XML. Let the condition
1267  * percolate and error out specifically where it is not
1268  * allowed */
1269  return 0;
1270  }
1271 
1272  if(XML_TEXT_NODE != pSave->type)
1273  {
1274  pError->m_eResultCode = RC_XMLInvalidNodeType;
1275  pError->m_pWhatStr = "invalid XML Node found during field decode";
1276  pError->m_pRefType = m_pRefType;
1277  pError->m_pRefField = pFieldDescriptor;
1278  pError->m_OtherDetail = (int) pSave->line;
1279  return 0;
1280  }
1281 
1282  *pbuf = pSave->content;
1283 
1284  /* make sure there are no more interesting nodes */
1285  pSave = pSave->next;
1286  while ((NULL !=pSave) &&
1287  (isInsignificantNode(pSave) ||
1288  xmlIsBlankNode(pSave)))
1289  {
1290  pSave = pSave->next;
1291  }
1292 
1293  if(pSave != NULL)
1294  {
1295  pError->m_eResultCode = RC_XMLExtraNode;
1296  pError->m_pWhatStr = "extra XML node found";
1297  pError->m_pRefType = m_pRefType;
1298  pError->m_pRefField = pFieldDescriptor;
1299  pError->m_OtherDetail = (int) pSave->line;
1300  return 0;
1301  }
1302 
1303  *pend = *pbuf + strlen((char*) *pbuf);
1304  return 1;
1305 }
1306 
1307 llrp_s64v_t
1308 CXMLTextDecoderStream::getSpacedVectorField (
1309  const CFieldDescriptor * pFieldDescriptor,
1310  llrp_s64_t minValue,
1311  llrp_s64_t maxValue)
1312 {
1313  CErrorDetails * pError = &m_pDecoder->m_ErrorDetails;
1314  const llrp_u8_t * pTok;
1315  const llrp_u8_t * pEnd;
1316  const llrp_u8_t * pTokEnd;
1317  llrp_u16_t length;
1318  llrp_u16_t elementCount;
1319  llrp_s64v_t Value;
1320  llrp_u16_t count;
1321 
1322  if(RC_OK != pError->m_eResultCode)
1323  {
1324  /* already errd */
1325  return Value;
1326  }
1327 
1328  /* get the NULL terminates string from XML */
1329  if(!getFieldStringPtr(pFieldDescriptor, &pTok, &pEnd))
1330  {
1331  /* many of these (e.g. ReadData) are allowed to be empty */
1332  return Value;
1333  }
1334 
1335  length = cleanString(&pTok, &pEnd);
1336  elementCount = countElements((char *) pTok, length);
1337 
1338  /* create the final storage entity */
1339  Value = llrp_s64v_t(elementCount);
1340 
1341  for(count = 0;count <elementCount ; count++)
1342  {
1343  /* find the next starting token */
1344  while(isspace(*pTok) && (pTok < pEnd))
1345  {
1346  pTok++;
1347  }
1348 
1349  /* find the next ending token */
1350  for(pTokEnd = pTok; (!isspace(*pTokEnd)) && (*pTokEnd != '\0'); pTokEnd++)
1351  {
1352  /* nothing */
1353  }
1354 
1355  /* get a single integer */
1356  Value.m_pValue[count] = getInteger(pFieldDescriptor,
1357  pTok,
1358  pTokEnd,
1359  pError,
1360  minValue,
1361  maxValue);
1362  if(RC_OK != pError->m_eResultCode)
1363  {
1364  break;
1365  }
1366  /* get the next value */
1367  pTok = pTokEnd;
1368  }
1369 
1370  /* mark the length */
1371  Value.m_nValue = count;
1372 
1373  return Value;
1374 }
1375 
1376 llrp_s64v_t
1377 CXMLTextDecoderStream::getFixedVectorField (
1378  const CFieldDescriptor * pFieldDescriptor,
1379  unsigned int vectorSize,
1380  llrp_s64_t minValue,
1381  llrp_s64_t maxValue)
1382 {
1383  CErrorDetails * pError = &m_pDecoder->m_ErrorDetails;
1384  const llrp_u8_t * pTok;
1385  const llrp_u8_t * pEnd;
1386  llrp_u16_t length;
1387  llrp_u16_t elementCount;
1388  llrp_s64v_t Value;
1389  llrp_u16_t count;
1390 
1391  if(RC_OK != pError->m_eResultCode)
1392  {
1393  /* already errd */
1394  return Value;
1395  }
1396 
1397  if(!getFieldStringPtr(pFieldDescriptor, &pTok, &pEnd))
1398  {
1399  /* these values are allowed to be empty */
1400  Value.m_nValue = 0;
1401  Value.m_pValue = NULL;
1402  return Value;
1403  }
1404 
1405  length = cleanString(&pTok, &pEnd);
1406 
1407  /* size should match exactly */
1408  if (length % vectorSize)
1409  {
1410  pError->m_eResultCode = RC_FieldAllocationFailed;
1411  pError->m_pWhatStr = "field size must be multiple of basic type";
1412  pError->m_pRefType = m_pRefType;
1413  pError->m_pRefField = pFieldDescriptor;
1414  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1415  return Value;
1416  }
1417 
1418  /* round up for element count */
1419  elementCount = (length + vectorSize - 1)/vectorSize;
1420 
1421  /* create the final storage entity */
1422  Value = llrp_s64v_t(elementCount);
1423 
1424  for(count = 0;count <elementCount ; count++, pTok += vectorSize)
1425  {
1426  pEnd = pTok + vectorSize;
1427 
1428  /* get a single integer */
1429  Value.m_pValue[count] = getInteger(pFieldDescriptor,
1430  pTok,
1431  pEnd,
1432  pError,
1433  minValue,
1434  maxValue);
1435 
1436  if(RC_OK != pError->m_eResultCode)
1437  {
1438  break;
1439  }
1440  }
1441 
1442  /* mark the length */
1443  Value.m_nValue = count;
1444 
1445  return Value;
1446 }
1447 
1448 
1449 llrp_s64_t
1450 CXMLTextDecoderStream::getIntegerField (
1451  const CFieldDescriptor * pFieldDescriptor,
1452  llrp_s64_t minValue,
1453  llrp_s64_t maxValue)
1454 {
1455  CErrorDetails * pError = &m_pDecoder->m_ErrorDetails;
1456  const llrp_u8_t * pbuf;
1457  const llrp_u8_t * pend;
1458  llrp_s64_t Value;
1459 
1460  memset(&Value, 0x00, sizeof(Value));
1461 
1462  if(RC_OK != pError->m_eResultCode)
1463  {
1464  /* already errd */
1465  return Value;
1466  }
1467 
1468  if(getFieldStringPtr(pFieldDescriptor, &pbuf, &pend))
1469  {
1470  cleanString(&pbuf, &pend);
1471  Value = getInteger(pFieldDescriptor,
1472  pbuf,
1473  pend,
1474  pError,
1475  minValue,
1476  maxValue);
1477  }
1478  else
1479  {
1480  pError->m_eResultCode = RC_FieldUnderrun;
1481  pError->m_pWhatStr = "underrun at field no characters";
1482  pError->m_pRefType = m_pRefType;
1483  pError->m_pRefField = pFieldDescriptor;
1484  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1485  return 0;
1486  }
1487 
1488  return Value;
1489 }
1490 
1491 
1492 llrp_s64_t CXMLTextDecoderStream::getInteger(
1493  const CFieldDescriptor * pFieldDescriptor,
1494  const llrp_u8_t * pbuf,
1495  const llrp_u8_t * pend,
1496  CErrorDetails * pError,
1497  llrp_s64_t minValue,
1498  llrp_s64_t maxValue)
1499 {
1500  llrp_s64_t Value;
1501  const llrp_u8_t * endPtr = NULL;
1502 
1503 
1504  if(pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_U1)
1505  /* special case for U1 types as they can be
1506  * 'true' and 'false' strings */
1507  {
1508  endPtr = getSingleU1(pbuf, pend, &Value);
1509  }
1510  else if((pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E1 ) ||
1511  (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E2 ) ||
1512  (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E8 ) ||
1513  (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E16 ) ||
1514  (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E32 ) ||
1515  (pFieldDescriptor->m_eFieldType == CFieldDescriptor::FT_E8V ) )
1516  /* special case for enumerated fields as they are strings in XML*/
1517  {
1518  endPtr = getSingleEnum(pFieldDescriptor, pbuf, pend, &Value);
1519  }
1520  else switch(pFieldDescriptor->m_eFieldFormat)
1521  {
1522  /* assume default is decimal for new formats */
1523  default:
1524  case CFieldDescriptor::FMT_NORMAL:
1525  case CFieldDescriptor::FMT_DEC:
1526  endPtr = getSingleDecimal(pbuf, pend, &Value);
1527  break;
1528  case CFieldDescriptor::FMT_HEX:
1529  endPtr = getSingleHexidecimal(pbuf, pend, &Value);
1530  break;
1531  case CFieldDescriptor::FMT_UTF8:
1532  {
1533  const llrp_u8_t *ptr;
1534  /* not sure what to do for UTF 8 encoding as integer */
1535  for(ptr = pbuf; ptr < pend; ptr++)
1536  {
1537  Value = 256*Value + *ptr;
1538  }
1539  }
1540  break;
1541  case CFieldDescriptor::FMT_DATETIME:
1542  endPtr = getSingleTimestamp(pbuf, pend, &Value);
1543  break;
1544  }
1545 
1546  if(endPtr == pbuf)
1547  /* if we didn't get any thing, it means there are illegal characters
1548  * and we could not import a field value */
1549  {
1550  pError->m_eResultCode = RC_XMLInvalidFieldCharacters;
1551  pError->m_pWhatStr = "Illegal field value";
1552  pError->m_pRefType = m_pRefType;
1553  pError->m_pRefField = pFieldDescriptor;
1554  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1555  Value = 0;
1556  }
1557  else if (endPtr != pend)
1558  /* if these don't match, there is still extra stuff
1559  * at the end. This is always an error */
1560  {
1561  pError->m_eResultCode = RC_FieldOverrun;
1562  pError->m_pWhatStr = "overrun at field extra characters";
1563  pError->m_pRefType = m_pRefType;
1564  pError->m_pRefField = pFieldDescriptor;
1565  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1566  Value = 0;
1567  }
1568  /* make sure the value is in range */
1569  else if((Value > maxValue) || (Value < minValue))
1570  /* we have an out of range value. This is always an error */
1571  {
1572  pError->m_eResultCode = RC_XMLOutOfRange;
1573  pError->m_pWhatStr = "out of range value";
1574  pError->m_pRefType = m_pRefType;
1575  pError->m_pRefField = pFieldDescriptor;
1576  pError->m_OtherDetail = (int) m_pCurrentChildNode->line;
1577  Value = 0;
1578  }
1579  return Value;
1580 }
1581 
1582 /* static string helpers */
1583 
1584 const llrp_u8_t *
1585 CXMLTextDecoderStream::getSingleU1(
1586  const llrp_u8_t * pbuf,
1587  const llrp_u8_t * pend,
1588  llrp_s64_t * pValue)
1589 {
1590  const llrp_u8_t * endPtr = pbuf;
1591  const int len = (int) (pend - pbuf);
1592 
1593  if((len >= 4) && (0 == strncasecmp("true", (char*) pbuf, 4)))
1594  {
1595  *pValue = 1;
1596  endPtr = pbuf + 4;
1597  }
1598  else if ((len >= 5) && (0 == strncasecmp("false", (char*) pbuf, 5)))
1599  {
1600  *pValue = 0;
1601  endPtr = pbuf + 5;
1602  }
1603  else if ((len >= 1) && (*pbuf == '0'))
1604  {
1605  *pValue = 0;
1606  endPtr = pbuf + 1;
1607  }
1608  else if ((len >= 1) && (*pbuf == '1'))
1609  {
1610  *pValue = 0;
1611  endPtr = pbuf + 1;
1612  }
1613  return endPtr;
1614 }
1615 
1616 const llrp_u8_t *
1617 CXMLTextDecoderStream::getSingleEnum(
1618  const CFieldDescriptor * pFieldDescriptor,
1619  const llrp_u8_t * pbuf,
1620  const llrp_u8_t * pend,
1621  llrp_s64_t * pValue)
1622 {
1623  const llrp_u8_t * endPtr = pbuf;
1624  const int length = (int) (pend - pbuf);
1625  const SEnumTableEntry * pEntry;
1626 
1627  *pValue = 0;
1628 
1629  for(
1630  pEntry = pFieldDescriptor->m_pEnumTable;
1631  NULL != pEntry->pName;
1632  pEntry++)
1633  {
1634  int len = (int) strlen(pEntry->pName);
1635  if((len == length) &&
1636  (memcmp(pbuf, pEntry->pName, len) == 0))
1637  {
1638  break;
1639  }
1640  }
1641 
1642  if(NULL == pEntry->pName)
1643  {
1644  return pbuf;
1645  }
1646 
1647  *pValue = pEntry->Value;
1648  endPtr = pbuf + length;
1649  return endPtr;
1650 }
1651 
1652 const llrp_u8_t *
1653 CXMLTextDecoderStream::getSingleDecimal(
1654  const llrp_u8_t * pbuf,
1655  const llrp_u8_t * pend,
1656  llrp_s64_t * pValue)
1657 {
1658  int bNeg = 0;
1659  const llrp_u8_t * endPtr;
1660 
1661  *pValue = 0;
1662 
1663  for(endPtr = pbuf; endPtr < pend; endPtr++)
1664  {
1665  if(*endPtr == '-')
1666  {
1667  bNeg = 1;
1668  } else if (isdigit(*endPtr))
1669  {
1670  *pValue = 10 * *pValue + (*endPtr - '0');
1671  }
1672  else
1673  {
1674  /* a character not allowed in a decimal integer */
1675  break;
1676  }
1677  }
1678  if(bNeg)
1679  {
1680  *pValue *= -1;
1681  }
1682 
1683  return endPtr;
1684 }
1685 
1686 
1687 const llrp_u8_t *
1688 CXMLTextDecoderStream::getSingleHexidecimal(
1689  const llrp_u8_t * pbuf,
1690  const llrp_u8_t * pend,
1691  llrp_s64_t * pValue)
1692 {
1693  const llrp_u8_t * endPtr;
1694 
1695  *pValue = 0;
1696  for(endPtr = pbuf; endPtr < pend; endPtr++)
1697  {
1698  if(isdigit(*endPtr))
1699  {
1700  *pValue = 16 * *pValue + (*endPtr - '0');
1701  }
1702  else if (*endPtr >= 'A' && *endPtr <= 'F')
1703  {
1704  *pValue = 16 * *pValue + (*endPtr - 'A' + 10);
1705  }
1706  else if (*endPtr >= 'a' && *endPtr <= 'f')
1707  {
1708  *pValue = 16 * *pValue + (*endPtr - 'a' + 10);
1709  }
1710  else
1711  {
1712  /* a character not allowed in a decimal integer */
1713  break;
1714  }
1715  }
1716  return endPtr;
1717 }
1718 
1719 
1720 int
1721 CXMLTextDecoderStream::cleanString(
1722  const llrp_u8_t ** ppbuf,
1723  const llrp_u8_t ** ppend)
1724 {
1725  /* skip leading spaces */
1726  while( isspace(**ppbuf) && (*ppbuf <= *ppend))
1727  {
1728  (*ppbuf)++;
1729  }
1730  /* skip trailing spaces except last separator */
1731  /* last separator could be space or NULL. */
1732  while((*ppend > *ppbuf) && (isspace(*(*ppend-1)) || (*(*ppend-1) == '\0')))
1733  {
1734  (*ppend)--;
1735  }
1736  return (int) (*ppend - *ppbuf);
1737 }
1738 
1739 /* gets a single char value from a non-NULL terminated buffer buffer.
1740  * If it fails to get one, reutrn value should == pbuf, other
1741  * wise EndPtr should point to one past amount consumed */
1742 static const llrp_u8_t *
1743 getSingleChar(
1744  const llrp_u8_t * pbuf,
1745  const llrp_u8_t * pend,
1746  llrp_s64_t * pValue)
1747 {
1748  const llrp_u8_t * endPtr = pbuf;
1749  const int len = pend - pbuf;
1750 
1751  if(len >= 1)
1752  {
1753  *pValue = *pbuf;
1754  endPtr = pbuf + 1;
1755  }
1756 
1757  return endPtr;
1758 }
1759 
1760 const llrp_u8_t *
1761 CXMLTextDecoderStream::getSingleTimestamp(
1762  const llrp_u8_t * pbuf,
1763  const llrp_u8_t * pend,
1764  llrp_s64_t * pValue)
1765 {
1766  const llrp_u8_t * endPtr;
1767  const llrp_u8_t * tmpPtr;
1768  struct tm importTime;
1769  llrp_s64_t micros = 0;
1770  llrp_s64_t temp = 0;
1771  time_t tt;
1772  int utc = 0;
1773  llrp_s64_t offset = 0;
1774 
1775  memset(&importTime, 0x00, sizeof(importTime));
1776 
1777  tmpPtr = pbuf;
1778  endPtr = (llrp_u8_t*) strptime((char*) tmpPtr, "%Y-%m-%dT%T", &importTime);
1779 
1780  if(endPtr == NULL)
1781  {
1782  goto timeParseError;
1783  }
1784 
1785  /* we have a valid timestamp, but there may be more stuff */
1786  tmpPtr = endPtr;
1787  if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr)
1788  {
1789  goto timeParseDone;
1790  }
1791 
1792  if(temp == '.')
1793  {
1794  int length;
1795 
1796  /* try to get the microsecond value */
1797  tmpPtr = endPtr;
1798  if((endPtr = getSingleDecimal(tmpPtr, pend, &micros)) == tmpPtr)
1799  {
1800  goto timeParseError;
1801  }
1802 
1803  length = endPtr - tmpPtr;
1804  /* may not contain 6 decimal places */
1805  while(length < 6)
1806  {
1807  micros *= 10;
1808  length++;
1809  }
1810 
1811  if(length > 6)
1812  {
1813  goto timeParseError;
1814  }
1815 
1816  /* look for more stuff that is optional */
1817  tmpPtr = endPtr;
1818  if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr)
1819  {
1820  goto timeParseDone;
1821  }
1822  }
1823 
1824  /* timestamp could either have offset or Z for UTC (Zulu) */
1825  if(temp == '-' || temp == '+')
1826  {
1827  int scale = 1;
1828  /* offset formats are hh or hh:mm from UTC */
1829  if(temp == '+')
1830  {
1831  scale = -1;
1832  /* The time is offset positively from UTC, which means we have to
1833  ** subtract to get to UTC time */
1834  }
1835  utc = 1;
1836  tmpPtr = endPtr;
1837  if((endPtr = getSingleDecimal(tmpPtr, pend, &temp)) == (tmpPtr+2))
1838  {
1839  goto timeParseError;
1840  }
1841 
1842  offset = scale*temp*60*60;
1843 
1844  tmpPtr = endPtr;
1845  if((endPtr = getSingleChar(tmpPtr, pend, &temp)) == tmpPtr)
1846  {
1847  goto timeParseDone;
1848  }
1849 
1850  if(temp != ':') {
1851  goto timeParseError;
1852  }
1853 
1854  tmpPtr = endPtr;
1855  if((endPtr = getSingleDecimal(tmpPtr, pend, &temp)) == (tmpPtr+2))
1856  {
1857  goto timeParseError;
1858  }
1859 
1860  offset += (scale * temp * 60);
1861 
1862  }
1863  else if ((temp == 'z') || (temp == 'Z'))
1864  {
1865  utc = 1;
1866  }
1867  /* fall through */
1868 
1869 timeParseDone:
1870 
1871  if(utc)
1872  {
1873  tt = timegm(&importTime);
1874  } else
1875  {
1876  tt = timelocal(&importTime);
1877  }
1878 
1879  /* make this into time since epoch at GMT (UTC) */
1880  if(tt != (time_t) -1)
1881  {
1882  /* LLRP format is 64-bit microseconds UTC. Conver */
1883  *pValue = 1000000ll * (llrp_s64_t) (tt + offset) + micros;
1884  return endPtr;
1885  }
1886  /* fall through if time wasn't valid */
1887 timeParseError:
1888  endPtr = pbuf;
1889  return endPtr;
1890 }
1891 
1892 
1893 llrp_u16_t
1894 CXMLTextDecoderStream::countElements(
1895  const char * pval,
1896  int nval)
1897 {
1898  const llrp_u8_t * pTok;
1899  const llrp_u8_t * pEnd;
1900  llrp_u8_t lastChar;
1901  llrp_u16_t elements = 0;
1902 
1903  /* find out how many possible tokens there are.
1904  * This should limit our size of array we need */
1905 
1906  pTok = (llrp_u8_t*) &pval[0];
1907  pEnd = pTok + nval;
1908 
1909  /* skip leading spaces */
1910  for(lastChar = ' '; pTok < pEnd; pTok++)
1911  {
1912  if((!isspace(*pTok)) && (isspace(lastChar)))
1913  {
1914  elements++;
1915  }
1916  lastChar = *pTok;
1917  }
1918 
1919  return elements;
1920 }
1921 
1922 };
Based type descriptions for the LTKCPP library.
Based types for the LKTCPP library.
Classes to encode and decode LTK-XML.
Definition: ltkcpp.h:45