LTKCPP-- LLRP Toolkit C Plus Plus Library
ltkcpp_xmltextencode.cpp
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 
15 
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <time.h>
19 
20 #include "ltkcpp_platform.h"
21 #include "ltkcpp_base.h"
22 #include "ltkcpp_xmltext.h"
23 
24 
25 
26 namespace LLRP
27 {
28 
29 /*
30  * Structures used by discoverNamespaces() and putElement().
31  */
32 #define MAX_NS 10
33 struct NamespaceList
34 {
35  const CNamespaceDescriptor *apNamespaceDescriptor[MAX_NS];
36  int nNamespaceDescriptor;
37 };
38 typedef struct NamespaceList tNamespaceList;
39 
40 /* forward */
41 static int
42 discoverNamespaces (
43  const CElement * pElement,
44  void * pArg);
45 
46 
47 CXMLTextEncoder::CXMLTextEncoder (
48  char * pBuffer,
49  int nBuffer)
50 {
51  m_pBuffer = pBuffer;
52  m_nBuffer = nBuffer;
53  m_iNext = 0;
54  m_bOverflow = 0;
55 }
56 
57 CXMLTextEncoder::~CXMLTextEncoder (void)
58 {
59 }
60 
61 void
62 CXMLTextEncoder::encodeElement (
63  const CElement * pElement)
64 {
65  CXMLTextEncoderStream MyEncoderStream(this);
66 
67  MyEncoderStream.putElement(pElement);
68 }
69 
70 void
71 CXMLTextEncoderStream::putRequiredSubParameter (
72  const CParameter * pParameter,
73  const CTypeDescriptor * pRefType)
74 {
75  if(NULL == pParameter)
76  {
77  appendFormat("warning: missing %s\n",
78  (NULL == pRefType) ? "<something>" : pRefType->m_pName);
79  return;
80  }
81 
82  CXMLTextEncoderStream NestEncoderStream(this);
83 
84  NestEncoderStream.putElement(pParameter);
85 }
86 
87 void
88 CXMLTextEncoderStream::putOptionalSubParameter (
89  const CParameter * pParameter,
90  const CTypeDescriptor * pRefType)
91 {
92  if(NULL == pParameter)
93  {
94  return;
95  }
96 
97  CXMLTextEncoderStream NestEncoderStream(this);
98 
99  NestEncoderStream.putElement(pParameter);
100 }
101 
102 void
103 CXMLTextEncoderStream::putRequiredSubParameterList (
104  const tListOfParameters * pParameterList,
105  const CTypeDescriptor * pRefType)
106 {
107  if(pParameterList->empty())
108  {
109  appendFormat("warning: missing list of %s\n",
110  (NULL == pRefType) ? "<something>" : pRefType->m_pName);
111  return;
112  }
113 
114  for(
115  tListOfParameters::const_iterator Cur = pParameterList->begin();
116  Cur != pParameterList->end();
117  Cur++)
118  {
119  putRequiredSubParameter(*Cur, pRefType);
120  }
121 }
122 
123 void
124 CXMLTextEncoderStream::putOptionalSubParameterList (
125  const tListOfParameters * pParameterList,
126  const CTypeDescriptor * pRefType)
127 {
128  for(
129  tListOfParameters::const_iterator Cur = pParameterList->begin();
130  Cur != pParameterList->end();
131  Cur++)
132  {
133  putRequiredSubParameter(*Cur, pRefType);
134  }
135 }
136 
137 
138 /*
139  * 8-bit types
140  */
141 
142 void
143 CXMLTextEncoderStream::put_u8 (
144  llrp_u8_t Value,
145  const CFieldDescriptor * pFieldDescriptor)
146 {
147  const char * pFieldName = pFieldDescriptor->m_pName;
148 
149  appendOpenTag(pFieldName);
150  switch(pFieldDescriptor->m_eFieldFormat)
151  {
152  case CFieldDescriptor::FMT_NORMAL:
153  case CFieldDescriptor::FMT_DEC:
154  default:
155  appendFormat("%u", Value);
156  break;
157 
158  case CFieldDescriptor::FMT_HEX:
159  appendFormat("%02X", Value);
160  break;
161  }
162  appendCloseTag(pFieldName);
163 }
164 
165 void
166 CXMLTextEncoderStream::put_s8 (
167  llrp_s8_t Value,
168  const CFieldDescriptor * pFieldDescriptor)
169 {
170  const char * pFieldName = pFieldDescriptor->m_pName;
171 
172  appendOpenTag(pFieldName);
173  switch(pFieldDescriptor->m_eFieldFormat)
174  {
175  case CFieldDescriptor::FMT_NORMAL:
176  case CFieldDescriptor::FMT_DEC:
177  default:
178  appendFormat("%d", Value);
179  break;
180 
181  case CFieldDescriptor::FMT_HEX:
182  appendFormat("%02X", 0xFF & Value);
183  break;
184  }
185  appendCloseTag(pFieldName);
186 }
187 
188 void
189 CXMLTextEncoderStream::put_u8v (
190  llrp_u8v_t Value,
191  const CFieldDescriptor * pFieldDescriptor)
192 {
193  const char * pFieldName = pFieldDescriptor->m_pName;
194 
195  appendOpenTag(pFieldName);
196  for(int i = 0; i < Value.m_nValue; i++)
197  {
198  switch(pFieldDescriptor->m_eFieldFormat)
199  {
200  case CFieldDescriptor::FMT_NORMAL:
201  case CFieldDescriptor::FMT_DEC:
202  default:
203  if(0 < i)
204  {
205  appendFormat(" ");
206  }
207  appendFormat("%u", Value.m_pValue[i]);
208  break;
209 
210  case CFieldDescriptor::FMT_HEX:
211  appendFormat("%02X", 0xFF & Value.m_pValue[i]);
212  break;
213  }
214  }
215  appendCloseTag(pFieldName);
216 }
217 
218 void
219 CXMLTextEncoderStream::put_s8v (
220  llrp_s8v_t Value,
221  const CFieldDescriptor * pFieldDescriptor)
222 {
223  const char * pFieldName = pFieldDescriptor->m_pName;
224 
225  appendOpenTag(pFieldName);
226  for(int i = 0; i < Value.m_nValue; i++)
227  {
228  switch(pFieldDescriptor->m_eFieldFormat)
229  {
230  case CFieldDescriptor::FMT_NORMAL:
231  case CFieldDescriptor::FMT_DEC:
232  default:
233  if(0 < i)
234  {
235  appendFormat(" ");
236  }
237  appendFormat("%d", Value.m_pValue[i]);
238  break;
239 
240  case CFieldDescriptor::FMT_HEX:
241  appendFormat("%02X", 0xFF & Value.m_pValue[i]);
242  break;
243  }
244  }
245  appendCloseTag(pFieldName);
246 }
247 
248 /*
249  * 16-bit types
250  */
251 
252 void
253 CXMLTextEncoderStream::put_u16 (
254  llrp_u16_t Value,
255  const CFieldDescriptor * pFieldDescriptor)
256 {
257  const char * pFieldName = pFieldDescriptor->m_pName;
258 
259  appendOpenTag(pFieldName);
260  switch(pFieldDescriptor->m_eFieldFormat)
261  {
262  case CFieldDescriptor::FMT_NORMAL:
263  case CFieldDescriptor::FMT_DEC:
264  default:
265  appendFormat("%u", Value);
266  break;
267 
268  case CFieldDescriptor::FMT_HEX:
269  appendFormat("%04X", Value);
270  break;
271  }
272  appendCloseTag(pFieldName);
273 }
274 
275 void
276 CXMLTextEncoderStream::put_s16 (
277  llrp_s16_t Value,
278  const CFieldDescriptor * pFieldDescriptor)
279 {
280  const char * pFieldName = pFieldDescriptor->m_pName;
281 
282  appendOpenTag(pFieldName);
283  switch(pFieldDescriptor->m_eFieldFormat)
284  {
285  case CFieldDescriptor::FMT_NORMAL:
286  case CFieldDescriptor::FMT_DEC:
287  default:
288  appendFormat("%d", Value);
289  break;
290 
291  case CFieldDescriptor::FMT_HEX:
292  appendFormat("%04X", 0xFFFF & Value);
293  break;
294  }
295  appendCloseTag(pFieldName);
296 }
297 
298 void
299 CXMLTextEncoderStream::put_u16v (
300  llrp_u16v_t Value,
301  const CFieldDescriptor * pFieldDescriptor)
302 {
303  const char * pFieldName = pFieldDescriptor->m_pName;
304 
305  appendOpenTag(pFieldName);
306  for(int i = 0; i < Value.m_nValue; i++)
307  {
308  if(0 < i)
309  {
310  appendFormat(" ");
311  }
312  switch(pFieldDescriptor->m_eFieldFormat)
313  {
314  case CFieldDescriptor::FMT_NORMAL:
315  case CFieldDescriptor::FMT_DEC:
316  default:
317  appendFormat("%u", Value.m_pValue[i]);
318  break;
319 
320  case CFieldDescriptor::FMT_HEX:
321  appendFormat("%04X", 0xFFFF & Value.m_pValue[i]);
322  break;
323  }
324  }
325  appendCloseTag(pFieldName);
326 }
327 
328 void
329 CXMLTextEncoderStream::put_s16v (
330  llrp_s16v_t Value,
331  const CFieldDescriptor * pFieldDescriptor)
332 {
333  const char * pFieldName = pFieldDescriptor->m_pName;
334 
335  appendOpenTag(pFieldName);
336  for(int i = 0; i < Value.m_nValue; i++)
337  {
338  if(0 < i)
339  {
340  appendFormat(" ");
341  }
342  switch(pFieldDescriptor->m_eFieldFormat)
343  {
344  case CFieldDescriptor::FMT_NORMAL:
345  case CFieldDescriptor::FMT_DEC:
346  default:
347  appendFormat("%d", Value.m_pValue[i]);
348  break;
349 
350  case CFieldDescriptor::FMT_HEX:
351  appendFormat("%04X", 0xFFFF & Value.m_pValue[i]);
352  break;
353  }
354  }
355  appendCloseTag(pFieldName);
356 }
357 
358 /*
359  * 32-bit types
360  */
361 
362 void
363 CXMLTextEncoderStream::put_u32 (
364  llrp_u32_t Value,
365  const CFieldDescriptor * pFieldDescriptor)
366 {
367  const char * pFieldName = pFieldDescriptor->m_pName;
368 
369  appendOpenTag(pFieldName);
370  switch(pFieldDescriptor->m_eFieldFormat)
371  {
372  case CFieldDescriptor::FMT_NORMAL:
373  case CFieldDescriptor::FMT_DEC:
374  default:
375  appendFormat("%u", Value);
376  break;
377 
378  case CFieldDescriptor::FMT_HEX:
379  appendFormat("%08X", Value);
380  break;
381  }
382  appendCloseTag(pFieldName);
383 }
384 
385 void
386 CXMLTextEncoderStream::put_s32 (
387  llrp_s32_t Value,
388  const CFieldDescriptor * pFieldDescriptor)
389 {
390  const char * pFieldName = pFieldDescriptor->m_pName;
391 
392  appendOpenTag(pFieldName);
393  switch(pFieldDescriptor->m_eFieldFormat)
394  {
395  case CFieldDescriptor::FMT_NORMAL:
396  case CFieldDescriptor::FMT_DEC:
397  default:
398  appendFormat("%d", Value);
399  break;
400 
401  case CFieldDescriptor::FMT_HEX:
402  appendFormat("%08X", Value);
403  break;
404  }
405  appendCloseTag(pFieldName);
406 }
407 
408 void
409 CXMLTextEncoderStream::put_u32v (
410  llrp_u32v_t Value,
411  const CFieldDescriptor * pFieldDescriptor)
412 {
413  const char * pFieldName = pFieldDescriptor->m_pName;
414 
415  appendOpenTag(pFieldName);
416  for(int i = 0; i < Value.m_nValue; i++)
417  {
418  if(0 < i)
419  {
420  appendFormat(" ");
421  }
422  switch(pFieldDescriptor->m_eFieldFormat)
423  {
424  case CFieldDescriptor::FMT_NORMAL:
425  case CFieldDescriptor::FMT_DEC:
426  default:
427  appendFormat("%u", Value.m_pValue[i]);
428  break;
429 
430  case CFieldDescriptor::FMT_HEX:
431  appendFormat("%08X", Value.m_pValue[i]);
432  break;
433  }
434  }
435  appendCloseTag(pFieldName);
436 }
437 
438 void
439 CXMLTextEncoderStream::put_s32v (
440  llrp_s32v_t Value,
441  const CFieldDescriptor * pFieldDescriptor)
442 {
443  const char * pFieldName = pFieldDescriptor->m_pName;
444 
445  appendOpenTag(pFieldName);
446  for(int i = 0; i < Value.m_nValue; i++)
447  {
448  if(0 < i)
449  {
450  appendFormat(" ");
451  }
452  switch(pFieldDescriptor->m_eFieldFormat)
453  {
454  case CFieldDescriptor::FMT_NORMAL:
455  case CFieldDescriptor::FMT_DEC:
456  default:
457  appendFormat("%d", Value.m_pValue[i]);
458  break;
459 
460  case CFieldDescriptor::FMT_HEX:
461  appendFormat("%08X", Value.m_pValue[i]);
462  break;
463  }
464  }
465  appendCloseTag(pFieldName);
466 }
467 
468 /*
469  * 64-bit types
470  */
471 
472 void
473 CXMLTextEncoderStream::put_u64 (
474  llrp_u64_t Value,
475  const CFieldDescriptor * pFieldDescriptor)
476 {
477  const char * pFieldName = pFieldDescriptor->m_pName;
478 
479  appendOpenTag(pFieldName);
480  switch(pFieldDescriptor->m_eFieldFormat)
481  {
482  case CFieldDescriptor::FMT_NORMAL:
483  case CFieldDescriptor::FMT_DEC:
484  default:
485 #ifdef WIN32
486  appendFormat("%I64u", Value);
487 #else
488  appendFormat("%llu", Value);
489 #endif
490  break;
491 
492  case CFieldDescriptor::FMT_HEX:
493 #ifdef WIN32
494  appendFormat("%016I64X", Value);
495 #else
496  appendFormat("%016llX", Value);
497 #endif
498  break;
499 
500  case CFieldDescriptor::FMT_DATETIME:
501  {
502  char aBuf[64];
503  time_t CurSec = (time_t)(Value / 1000000u);
504  llrp_u32_t CurUSec = (llrp_u32_t)(Value % 1000000u);
505  struct tm * pGMTime;
506 
507  pGMTime = gmtime(&CurSec);
508  strftime(aBuf, sizeof aBuf, "%Y-%m-%dT%H:%M:%S", pGMTime);
509  appendFormat("%s.%06dZ", aBuf, CurUSec);
510  }
511  break;
512  }
513  appendCloseTag(pFieldName);
514 }
515 
516 void
517 CXMLTextEncoderStream::put_s64 (
518  llrp_s64_t Value,
519  const CFieldDescriptor * pFieldDescriptor)
520 {
521  const char * pFieldName = pFieldDescriptor->m_pName;
522 
523  appendOpenTag(pFieldName);
524  switch(pFieldDescriptor->m_eFieldFormat)
525  {
526  case CFieldDescriptor::FMT_NORMAL:
527  case CFieldDescriptor::FMT_DEC:
528  default:
529 #ifdef WIN32
530  appendFormat("%I64d", Value);
531 #else
532  appendFormat("%lld", Value);
533 #endif
534  break;
535 
536  case CFieldDescriptor::FMT_HEX:
537 #ifdef WIN32
538  appendFormat("%016I64X", Value);
539 #else
540  appendFormat("%016llX", Value);
541 #endif
542  break;
543  }
544  appendCloseTag(pFieldName);
545 }
546 
547 void
548 CXMLTextEncoderStream::put_u64v (
549  llrp_u64v_t Value,
550  const CFieldDescriptor * pFieldDescriptor)
551 {
552  const char * pFieldName = pFieldDescriptor->m_pName;
553 
554  appendOpenTag(pFieldName);
555  for(int i = 0; i < Value.m_nValue; i++)
556  {
557  if(0 < i)
558  {
559  appendFormat(" ");
560  }
561  switch(pFieldDescriptor->m_eFieldFormat)
562  {
563  case CFieldDescriptor::FMT_NORMAL:
564  case CFieldDescriptor::FMT_DEC:
565  default:
566 #ifdef WIN32
567  appendFormat("%I64u", Value.m_pValue[i]);
568 #else
569  appendFormat("%llu", Value.m_pValue[i]);
570 #endif
571  break;
572 
573  case CFieldDescriptor::FMT_HEX:
574 #ifdef WIN32
575  appendFormat("%016I64X", Value.m_pValue[i]);
576 #else
577  appendFormat("%016llX", Value.m_pValue[i]);
578 #endif
579  break;
580  }
581  }
582  appendCloseTag(pFieldName);
583 }
584 
585 void
586 CXMLTextEncoderStream::put_s64v (
587  llrp_s64v_t Value,
588  const CFieldDescriptor * pFieldDescriptor)
589 {
590  const char * pFieldName = pFieldDescriptor->m_pName;
591 
592  appendOpenTag(pFieldName);
593  for(int i = 0; i < Value.m_nValue; i++)
594  {
595  if(0 < i)
596  {
597  appendFormat(" ");
598  }
599  switch(pFieldDescriptor->m_eFieldFormat)
600  {
601  case CFieldDescriptor::FMT_NORMAL:
602  case CFieldDescriptor::FMT_DEC:
603  default:
604 #ifdef WIN32
605  appendFormat("%I64d", Value.m_pValue[i]);
606 #else
607  appendFormat("%lld", Value.m_pValue[i]);
608 #endif
609  break;
610 
611  case CFieldDescriptor::FMT_HEX:
612 #ifdef WIN32
613  appendFormat("%016I64X", Value.m_pValue[i]);
614 #else
615  appendFormat("%016llX", Value.m_pValue[i]);
616 #endif
617  break;
618  }
619  }
620  appendCloseTag(pFieldName);
621 }
622 
623 /*
624  * Special types
625  */
626 
627 void
628 CXMLTextEncoderStream::put_u1 (
629  llrp_u1_t Value,
630  const CFieldDescriptor * pFieldDescriptor)
631 {
632  const char * pFieldName = pFieldDescriptor->m_pName;
633 
634  appendOpenTag(pFieldName);
635  switch(pFieldDescriptor->m_eFieldFormat)
636  {
637  case CFieldDescriptor::FMT_NORMAL:
638  default:
639  appendFormat("%s", (Value & 1) ? "true" : "false");
640  break;
641 
642  case CFieldDescriptor::FMT_DEC:
643  case CFieldDescriptor::FMT_HEX:
644  appendFormat("%d", Value & 1);
645  break;
646  }
647  appendCloseTag(pFieldName);
648 }
649 
650 void
651 CXMLTextEncoderStream::put_u1v (
652  llrp_u1v_t Value,
653  const CFieldDescriptor * pFieldDescriptor)
654 {
655  const char * pFieldName = pFieldDescriptor->m_pName;
656  int nByte;
657 
658  nByte = (Value.m_nBit + 7u) / 8u;
659 
660  indent();
661  appendFormat("<");
662  appendPrefixedTagName(pFieldName);
663  appendFormat(" Count='%d'>", Value.m_nBit);
664 
665  for(int i = 0; i < nByte; i++)
666  {
667  appendFormat("%02X", Value.m_pValue[i]);
668  }
669 
670  appendCloseTag(pFieldName);
671 }
672 
673 void
674 CXMLTextEncoderStream::put_u2 (
675  llrp_u2_t Value,
676  const CFieldDescriptor * pFieldDescriptor)
677 {
678  const char * pFieldName = pFieldDescriptor->m_pName;
679 
680  appendOpenTag(pFieldName);
681  appendFormat("%d", Value & 3);
682  appendCloseTag(pFieldName);
683 }
684 
685 void
686 CXMLTextEncoderStream::put_u96 (
687  llrp_u96_t Value,
688  const CFieldDescriptor * pFieldDescriptor)
689 {
690  const char * pFieldName = pFieldDescriptor->m_pName;
691 
692  appendOpenTag(pFieldName);
693  for(int i = 0; i < 12; i++)
694  {
695  appendFormat("%02X", Value.m_aValue[i]);
696  }
697  appendCloseTag(pFieldName);
698 }
699 
700 void
701 CXMLTextEncoderStream::put_utf8v (
702  llrp_utf8v_t Value,
703  const CFieldDescriptor * pFieldDescriptor)
704 {
705  const char * pFieldName = pFieldDescriptor->m_pName;
706 
707  appendOpenTag(pFieldName);
708  for(int i = 0; i < Value.m_nValue; i++)
709  {
710  int c = Value.m_pValue[i];
711 
712  if(0 == c && i+1 == Value.m_nValue)
713  {
714  continue;
715  }
716  if(' ' <= c && c < 0x7F)
717  {
718  appendFormat("%c", c);
719  }
720  else
721  {
722  appendFormat("\\%03o", c);
723  }
724  }
725  appendCloseTag(pFieldName);
726 }
727 
728 void
729 CXMLTextEncoderStream::put_bytesToEnd (
730  llrp_bytesToEnd_t Value,
731  const CFieldDescriptor * pFieldDescriptor)
732 {
733  const char * pFieldName = pFieldDescriptor->m_pName;
734 
735  appendOpenTag(pFieldName);
736  for(int i = 0; i < Value.m_nValue; i++)
737  {
738  appendFormat("%02X", Value.m_pValue[i]);
739  }
740  appendCloseTag(pFieldName);
741 }
742 
743 /*
744  * Enumerated types of various sizes
745  */
746 
747 void
748 CXMLTextEncoderStream::put_e1 (
749  int eValue,
750  const CFieldDescriptor * pFieldDescriptor)
751 {
752  put_enum(eValue, pFieldDescriptor);
753 }
754 
755 void
756 CXMLTextEncoderStream::put_e2 (
757  int eValue,
758  const CFieldDescriptor * pFieldDescriptor)
759 {
760  put_enum(eValue, pFieldDescriptor);
761 }
762 
763 void
764 CXMLTextEncoderStream::put_e8 (
765  int eValue,
766  const CFieldDescriptor * pFieldDescriptor)
767 {
768  put_enum(eValue, pFieldDescriptor);
769 }
770 
771 void
772 CXMLTextEncoderStream::put_e16 (
773  int eValue,
774  const CFieldDescriptor * pFieldDescriptor)
775 {
776  put_enum(eValue, pFieldDescriptor);
777 }
778 
779 void
780 CXMLTextEncoderStream::put_e32 (
781  int eValue,
782  const CFieldDescriptor * pFieldDescriptor)
783 {
784  put_enum(eValue, pFieldDescriptor);
785 }
786 
787 void
788 CXMLTextEncoderStream::put_e8v (
789  llrp_u8v_t Value,
790  const CFieldDescriptor * pFieldDescriptor)
791 {
792  const char * pFieldName = pFieldDescriptor->m_pName;
793 
794  appendOpenTag(pFieldName);
795  for(int i = 0; i < Value.m_nValue; i++)
796  {
797  int eValue = Value.m_pValue[i];
798  const SEnumTableEntry * pEntry;
799 
800  for(pEntry = pFieldDescriptor->m_pEnumTable;
801  NULL != pEntry->pName;
802  pEntry++)
803  {
804  if(pEntry->Value == eValue)
805  {
806  break;
807  }
808  }
809 
810  if(0 < i)
811  {
812  appendFormat(" ");
813  }
814 
815  if(NULL != pEntry->pName)
816  {
817  appendFormat("%s", pEntry->pName);
818  }
819  else
820  {
821  appendFormat("%d", eValue);
822  }
823  }
824  appendCloseTag(pFieldName);
825 }
826 
827 /*
828  * Reserved types are some number of bits
829  */
830 
831 void
832 CXMLTextEncoderStream::put_reserved (
833  unsigned int nBits)
834 {
835  indent();
836  appendFormat("<!-- reserved %d bits -->\n", nBits);
837 }
838 
839 
840 CXMLTextEncoderStream::CXMLTextEncoderStream (
841  CXMLTextEncoder * pEncoder)
842 {
843  m_pEncoder = pEncoder;
844  m_pEnclosingEncoderStream = NULL;
845  m_pRefType = NULL;
846  m_nDepth = 1;
847 }
848 
849 CXMLTextEncoderStream::CXMLTextEncoderStream (
850  CXMLTextEncoderStream * pEnclosingEncoderStream)
851 {
852  m_pEncoder = pEnclosingEncoderStream->m_pEncoder;
853  m_pEnclosingEncoderStream = pEnclosingEncoderStream;
854  m_pRefType = NULL;
855  m_nDepth = pEnclosingEncoderStream->m_nDepth+1;
856 }
857 
858 void
859 CXMLTextEncoderStream::putElement (
860  const CElement * pElement)
861 {
862  m_pRefType = pElement->m_pType;
863 
864  indent(-1);
865  appendFormat("<");
866  appendPrefixedTagName(m_pRefType->m_pName);
867  if(m_pRefType->m_bIsMessage)
868  {
869  appendFormat(" MessageID='%u'",
870  ((const CMessage *)pElement)->getMessageID());
871  }
872 
873  if(NULL == m_pEnclosingEncoderStream)
874  {
875  tNamespaceList NamespaceList;
876  const CNamespaceDescriptor *pNamespaceDescriptor;
877  int iNSD;
878 
879  memset(&NamespaceList, 0, sizeof NamespaceList);
880 
881  pElement->walk(discoverNamespaces, (void*)&NamespaceList,
882  0, 12);
883 
884  /* Emit the namespace cookie for each */
885  for(iNSD = 0; iNSD < NamespaceList.nNamespaceDescriptor; iNSD++)
886  {
887  pNamespaceDescriptor = NamespaceList.apNamespaceDescriptor[iNSD];
888 
889  appendFormat("\n");
890  indent(0);
891  appendFormat("xmlns:%s='%s'",
892  pNamespaceDescriptor->m_pPrefix,
893  pNamespaceDescriptor->m_pURI);
894  /*
895  * If this is the default namespace then emit the assigment.
896  */
897  if(0 == strcmp(pNamespaceDescriptor->m_pPrefix, "llrp"))
898  {
899  appendFormat("\n");
900  indent(0);
901  appendFormat("xmlns='%s'", pNamespaceDescriptor->m_pURI);
902  }
903  }
904  }
905  appendFormat(">\n");
906 
907  pElement->encode(this);
908 
909  indent(-1);
910  appendCloseTag(m_pRefType->m_pName);
911 }
912 
913 static int
914 discoverNamespaces (
915  const CElement * pElement,
916  void * pArg)
917 {
918  tNamespaceList * pNSL = (tNamespaceList *) pArg;
919  const CNamespaceDescriptor *pNamespaceDescriptor;
920  int iNSD;
921 
922  pNamespaceDescriptor = pElement->m_pType->m_pNamespaceDescriptor;
923 
924  for(iNSD = 0; iNSD < pNSL->nNamespaceDescriptor; iNSD++)
925  {
926  if(pNSL->apNamespaceDescriptor[iNSD] == pNamespaceDescriptor)
927  {
928  /* Already have it */
929  return 0;
930  }
931  }
932 
933  /* if we get here this namespace isn't already in the list */
934  if(MAX_NS > pNSL->nNamespaceDescriptor)
935  {
936  iNSD = pNSL->nNamespaceDescriptor++;
937  pNSL->apNamespaceDescriptor[iNSD] = pNamespaceDescriptor;
938  }
939 
940  return 0;
941 }
942 
943 
944 void
945 CXMLTextEncoderStream::put_enum (
946  int eValue,
947  const CFieldDescriptor * pFieldDescriptor)
948 {
949  const char * pFieldName = pFieldDescriptor->m_pName;
950  const SEnumTableEntry * pEntry;
951 
952  appendOpenTag(pFieldName);
953 
954  for(pEntry = pFieldDescriptor->m_pEnumTable;
955  NULL != pEntry->pName;
956  pEntry++)
957  {
958  if(pEntry->Value == eValue)
959  {
960  break;
961  }
962  }
963 
964  if(NULL != pEntry->pName)
965  {
966  appendFormat("%s", pEntry->pName);
967  }
968  else
969  {
970  appendFormat("%d", eValue);
971  }
972 
973  appendCloseTag(pFieldName);
974 }
975 
976 void
977 CXMLTextEncoderStream::indent (
978  int adjust)
979 {
980  int n = m_nDepth + adjust;
981 
982  for(int i = 0; i < n; i++)
983  {
984  appendFormat(" ");
985  }
986 }
987 
988 void
989 CXMLTextEncoderStream::appendOpenTag (
990  const char * pName)
991 {
992  indent(0);
993  appendFormat("<");
994  appendPrefixedTagName(pName);
995  appendFormat(">");
996 }
997 
998 void
999 CXMLTextEncoderStream::appendCloseTag (
1000  const char * pName)
1001 {
1002  appendFormat("</");
1003  appendPrefixedTagName(pName);
1004  appendFormat(">\n");
1005 }
1006 
1007 void
1008 CXMLTextEncoderStream::appendPrefixedTagName (
1009  const char * pName)
1010 {
1011  const CTypeDescriptor * pRefType = m_pRefType;
1012  const char * pPrefix =
1013  pRefType->m_pNamespaceDescriptor->m_pPrefix;
1014 
1015  if(0 != strcmp("llrp", pPrefix))
1016  {
1017  appendFormat("%s:%s", pPrefix, pName);
1018  }
1019  else
1020  {
1021  appendFormat("%s", pName);
1022  }
1023 }
1024 
1025 void
1026 CXMLTextEncoderStream::appendFormat (
1027  char * pFmtStr,
1028  ...)
1029 {
1030  char aHoldBuf[256u];
1031  int nHoldBuf;
1032  va_list ap;
1033 
1034  /* If overflow already detected, bail */
1035  if(m_pEncoder->m_bOverflow)
1036  {
1037  return;
1038  }
1039 
1040  va_start(ap, pFmtStr);
1041 #ifdef WIN32
1042  _vsnprintf(aHoldBuf, sizeof aHoldBuf, pFmtStr, ap);
1043 #else
1044  vsnprintf(aHoldBuf, sizeof aHoldBuf, pFmtStr, ap);
1045 #endif
1046  va_end(ap);
1047 
1048  nHoldBuf = (int)strlen(aHoldBuf);
1049 
1050  if(m_pEncoder->m_iNext + nHoldBuf >= m_pEncoder->m_nBuffer)
1051  {
1052  m_pEncoder->m_bOverflow = 1;
1053  return;
1054  }
1055 
1056  strcpy(&m_pEncoder->m_pBuffer[m_pEncoder->m_iNext], aHoldBuf);
1057 
1058  m_pEncoder->m_iNext += nHoldBuf;
1059 }
1060 
1061 
1080  char * pBuffer,
1081  int nBuffer)
1082 {
1083  return LLRP::toXMLString(this, pBuffer, nBuffer);
1084 }
1085 
1087 toXMLString (
1088  const CElement * pElement,
1089  char * pBuffer,
1090  int nBuffer)
1091 {
1092  CXMLTextEncoder * pXMLEncoder;
1093  const CErrorDetails * pError;
1094 
1095  /*
1096  * Make sure the element is not NULL.
1097  */
1098  if(NULL == pElement)
1099  {
1100  strcpy(pBuffer, "ERROR: NULL pMessage to printXMLMessage\n");
1101  return RC_MiscError;
1102  }
1103 
1104  /*
1105  * Construct an XML encoder
1106  */
1107  pXMLEncoder = new CXMLTextEncoder(pBuffer, nBuffer);
1108  if(NULL == pXMLEncoder)
1109  {
1110  printf("ERROR: XMLTextEncoder_construct failed\n");
1111  return RC_MiscError;
1112  }
1113 
1114  /*
1115  * Now let the encoding mechanism do its thing.
1116  */
1117  pXMLEncoder->encodeElement(pElement);
1118 
1119  /*
1120  * Check the outcome in the error details.
1121  * If there is a problem, return the error rather
1122  * than the assumed to be useless string.
1123  */
1124  pError = &pXMLEncoder->m_ErrorDetails;
1125 
1126  if(RC_OK != pError->m_eResultCode)
1127  {
1128  sprintf(pBuffer, "ERROR: %s XML text failed, %s\n",
1129  pElement->m_pType->m_pName,
1130  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
1131 
1132  delete pXMLEncoder;
1133 
1134  return pError->m_eResultCode;
1135  }
1136 
1137  /*
1138  * Check if the XML fit in the buffer.
1139  */
1140  if(pXMLEncoder->m_bOverflow)
1141  {
1142  strcpy(pBuffer, "ERROR: Buffer overflow\n");
1143  delete pXMLEncoder;
1144  return RC_MiscError;
1145  }
1146 
1147  /*
1148  * Done with the XML encoder.
1149  */
1150  delete pXMLEncoder;
1151 
1152  return RC_OK;
1153 }
1154 
1155 
1156 }; /* namespace LLRP */
This is the base class for all parameter and message types.
Definition: ltkcpp_base.h:968
const CTypeDescriptor * m_pType
The type descriptor desribing this element.
Definition: ltkcpp_base.h:972
EResultCode m_eResultCode
Result code from operation.
Definition: ltkcpp_base.h:635
Based type descriptions for the LTKCPP library.
const char * m_pWhatStr
Descriptive printable error string.
Definition: ltkcpp_base.h:637
EResultCode toXMLString(char *pBuffer, int nBuffer)
A wrapper around LLRP::toXMLString()
EResultCode
Error result codes for LTK operations.
Definition: ltkcpp_base.h:583
Based types for the LKTCPP library.
Class to return error details in LTKCPP operations.
Definition: ltkcpp_base.h:631
char * m_pName
String name of parameter/message type (e.g. "ROSpec")
Definition: ltkcpp_base.h:762
Classes to encode and decode LTK-XML.
Definition: ltkcpp.h:45