LTKCPP-- LLRP Toolkit C Plus Plus Library
xml2llrp.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,2011. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
37 #include <stdio.h>
38 #include "ltkcpp.h"
39 #include "impinj_ltkcpp.h"
40 #include "impinjinternal_ltkcpp.h"
41 #include "dirent.h"
42 #include "sys/stat.h"
43 #include "libxml/parser.h"
44 
45 using namespace LLRP;
46 
47 #define MAX_PATH_LEN (256)
48 
49 CTypeRegistry * pTypeRegistry;
50 
51 
52 /* This is the message format that is agreed upon when messages fail
53 ** to decode. It's somewhat arbitrary, but allows us to do easy
54 ** comparisons */
55 /* the corresponding binary packet */
56 unsigned char errMsgBinary[18] = {0x04, 0x64, 0x00, 0x00,
57  0x00, 0x12, 0x00, 0x00,
58  0x00, 0x00, 0x01, 0x1F,
59  0x00, 0x08, 0x00, 0x00,
60  0x00, 0x00};
61 
62 #ifdef WIN32
63  char pathSeparator = '\\';
64 #else
65  char pathSeparator = '/';
66 #endif
67 
77 void convertFile(char *ifile, char *ofile) {
78  FILE * infp;
79  FILE * outfp;
80  CMessage * pMessage;
81  CXMLTextDecoder * pDecoder;
82  puts(ifile);
83  puts(ofile);
84  unsigned char *binbuf;
85  char *xmlbuf;
86  int xmlLen;
87  int binLen;
88 
89  /*
90  * Open input file
91  */
92 #ifdef WIN32
93  if(fopen_s(&infp, ifile, "r"))
94 #else
95  infp = fopen(ifile, "r");
96  if(infp == NULL)
97 #endif
98  {
99  perror(ifile);
100  xmlCleanupParser();
101  exit(-1);
102  }
103 
104  fseek(infp,0,SEEK_END); //go to end
105  xmlLen=ftell(infp); //get position at end (length)
106  fseek(infp,0,SEEK_SET); //go to beg.
107  xmlbuf=(char *) malloc(xmlLen); //malloc buffer
108  if (xmlbuf)
109  fread(xmlbuf,xmlLen,1,infp); //read into buffer
110  fclose(infp);
111 
112  if(xmlbuf == NULL) {
113  perror("Could not malloc buffer for LTK-XML message");
114  xmlCleanupParser();
115  exit(-2);
116  }
117 
118  /* open the output file for writing */
119 #ifdef WIN32
120  if(fopen_s(&outfp, ofile, "wb")) {
121 #else
122  outfp = fopen(ofile, "w");
123  if(outfp == NULL) {
124 #endif
125  fprintf(stderr, "Could not open output file %s for writing", ofile);
126  xmlCleanupParser();
127  exit(-3);
128  }
129 
130  /*
131  * Construct a frame decoder. It references the
132  * type registry and the input buffer.
133  */
134  pDecoder = new CXMLTextDecoder(pTypeRegistry, xmlbuf, xmlLen);
135 
136  /*
137  * Now ask the frame decoder to actually decode
138  * the message. It returns NULL for an error.
139  */
140  pMessage = pDecoder->decodeMessage();
141 
142  /*
143  * Did the decode fail?
144  */
145  if(NULL == pMessage)
146  {
147  const CErrorDetails *pError;
148 
149  /* encode error message as binary */
150  fwrite(errMsgBinary, 1, sizeof(errMsgBinary), outfp);
151 
152  pError = &pDecoder->m_ErrorDetails;
153 
154 #ifdef XML2LLRP_DEBUG
155  fprintf(stderr, "ERROR: Decoder error, result=%d\n",
156  pError->m_eResultCode);
157 
158  if(NULL != pMessageIDStr)
159  {
160  fprintf(stderr, "ERROR ... MessageID=%s\n",
161  pMessageIDStr);
162  }
163  if(NULL != pError->m_pRefType)
164  {
165  fprintf(stderr, "ERROR ... refType=%s\n",
166  pError->m_pRefType->m_pName);
167  }
168  if(NULL != pError->m_pRefField)
169  {
170  fprintf(stderr, "ERROR ... refField=%s\n",
171  pError->m_pRefField->m_pName);
172  }
173  if(NULL != pError->m_pWhatStr)
174  {
175  fprintf(stderr, "ERROR ... whatStr=%s\n",
176  pError->m_pWhatStr);
177  }
178  if(0 != pError->m_OtherDetail)
179  {
180  fprintf(stderr, "ERROR ... XML line number %d\n",
181  pError->m_OtherDetail);
182  }
183 #endif /* XML2LLRP_DEBUG */
184 
185  delete pDecoder;
186  /* we are done with this buffer */
187  free(xmlbuf);
188  return;
189  }
190  else
191  {
192  CFrameEncoder * pEncoder;
193 
194  /* clean up the xml decoder */
195  delete pDecoder;
196  /* we are done with this buffer */
197  free(xmlbuf);
198 
199  /* this is big enough */
200  binbuf = (unsigned char *) malloc(xmlLen);
201  if(NULL == binbuf) {
202  perror("Could not malloc buffer for LLRP Binary packet");
203  xmlCleanupParser();
204  exit(-5);
205  }
206 
207  memset(binbuf, 0, xmlLen);
208  pEncoder = new CFrameEncoder(binbuf, xmlLen);
209 
210  /*
211  * Do the encode.
212  * TODO: check the result, tattle on errors.
213  */
214  pEncoder->encodeElement(pMessage);
215  /*
216  * Get the byte length of the resulting frame.
217  */
218  binLen = pEncoder->getLength();
219  /*
220  * Check the status, tattle on errors
221  */
222  if(RC_OK != pEncoder->m_ErrorDetails.m_eResultCode)
223  {
224  const CErrorDetails *pError;
225  pError = &pEncoder->m_ErrorDetails;
226 
227  /* encode error message as binary */
228  fwrite(errMsgBinary,1, sizeof(errMsgBinary), outfp);
229 
230 #ifdef XML2LLRP_DEBUG
231  fprintf(stderr, "Failed to Encode XML message\n");
232  fprintf(stderr, "ERROR: Encoder error, status=%d\n",
233  pError->m_eResultCode);
234  if(NULL != pError->m_pRefType)
235  {
236  fprintf(stderr, "ERROR ... refType=%s\n",
237  pError->m_pRefType->m_pName);
238  }
239  if(NULL != pError->m_pRefField)
240  {
241  fprintf(stderr, "ERROR ... refField=%s\n",
242  pError->m_pRefField->m_pName);
243  }
244 #endif /* XML2LLRP_DEBUG */
245  }
246  else
247  {
248  fwrite(binbuf, 1, binLen, outfp);
249  }
250 
251 
252  /* free the frame encoder */
253  free(binbuf);
254  delete pEncoder;
255  }
256 
257  fclose(outfp);
258 
259  /* free the message we built */
260  delete pMessage;
261 }
262 
263 
264 void convertDirEntry(char *idir, char *odir, struct dirent *ep) {
265  char vector[MAX_PATH_LEN];
266  char iBuf[MAX_PATH_LEN];
267  char oBuf[MAX_PATH_LEN];
268  int len;
269 
270  if(!ep)
271  {
272  perror("Invalid file endpoint from dirent");
273  }
274 
275  /* string better end in .bin */
276  len = (int) strlen(ep->d_name);
277  if(len < 4)
278  {
279  /* if not just ignore this file */
280  return;
281  }
282 
283  /* call it a success if we don't need to convert */
284  if(strncmp(&ep->d_name[len-4], ".xml", 4) != 0) {
285  /* ignore this file */
286  return;
287  }
288 
289  memset(vector, 0x00, sizeof(vector));
290 #ifdef WIN32
291  strncpy_s(vector, ep->d_name, len-4);
292  sprintf_s(iBuf, "%s%s.xml", idir, vector);
293  sprintf_s(oBuf, "%s%s.bin", odir, vector);
294 #else
295  strncpy(vector, ep->d_name, len-4);
296  sprintf(iBuf, "%s%s.xml", idir, vector);
297  sprintf(oBuf, "%s%s.bin", odir, vector);
298 #endif
299  convertFile(iBuf, oBuf);
300 }
301 
302 int
303 main (int ac, char *av[])
304 {
305  DIR * dpin;
306  DIR * dpout;
307  char idir[MAX_PATH_LEN];
308  char odir[MAX_PATH_LEN];
309  int len;
310  struct dirent* ep;
311 
312  /*
313  * Check arg count
314  */
315  if(ac != 3)
316  {
317  fprintf(stderr, "ERROR: Bad usage\nusage: %s INPUTDIR OUTPUTDIR\n", av[0]);
318  exit(1);
319  }
320 
321  dpin = opendir (av[1]);
322  if (dpin == NULL)
323  {
324  fprintf(stderr, "ERROR: Could not stat input directory %s\n", av[1]);
325  exit(-1);
326  }
327 
328  /* make sure the directory has a path separator at the end */
329 #ifdef WIN32
330  strcpy_s(idir, av[1]);
331 #else
332  strcpy(idir, av[1]);
333 #endif
334 
335  len = (int) strlen(idir);
336  if(idir[len-1] != pathSeparator) {
337  idir[len] = pathSeparator;
338  idir[len + 1] = 0;
339  }
340 
341 
342  dpout = opendir (av[1]);
343  if (dpout == NULL)
344  {
345  fprintf(stderr, "ERROR: Could not stat output directory %s\n", av[2]);
346  exit(-1);
347  }
348 
349  /* make sure the directory has a path separator at the end */
350 #ifdef WIN32
351  strcpy_s(odir, av[2]);
352 #else
353  strcpy(odir, av[2]);
354 #endif
355  len = (int) strlen(odir);
356  if(odir[len-1] != pathSeparator) {
357  odir[len] = pathSeparator;
358  odir[len + 1] = 0;
359  }
360 
361  /*
362  * Construct the type registry. This is needed for decode.
363  */
364  pTypeRegistry = getTheTypeRegistry();
365 
366  enrollImpinjTypesIntoRegistry(pTypeRegistry);
367  enrollImpinjInternalTypesIntoRegistry(pTypeRegistry);
368 
369 
370  while((ep=readdir(dpin))) {
371  convertDirEntry(idir, odir, ep);
372  }
373 
374  (void) closedir(dpin);
375  (void) closedir(dpout);
376 
377  /*
378  * Done with the type registry.
379  */
380  delete pTypeRegistry;
381  xmlCleanupParser();
382 }
char * m_pName
String name of field (e.g. "ROSpecID")
Definition: ltkcpp_base.h:840
const CFieldDescriptor * m_pRefField
If non-NULL this is the field descriptors for the errored field.
Definition: ltkcpp_base.h:641
const CTypeDescriptor * m_pRefType
If non-NULL this is the type descriptors for the errored type.
Definition: ltkcpp_base.h:639
EResultCode m_eResultCode
Result code from operation.
Definition: ltkcpp_base.h:635
void enrollImpinjTypesIntoRegistry(CTypeRegistry *pTypeRegistry)
Enrolls the types for Impinj into the LTKCPP registry.
const char * m_pWhatStr
Descriptive printable error string.
Definition: ltkcpp_base.h:637
A collection of pointers to CTypeDescriptors.
Definition: ltkcpp_base.h:885
File that includes all Impinj Custom extension classes and types.
void convertFile(char *ifile, char *ofile)
Definition: xml2llrp.cpp:77
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
File that includes all LLRP classes and types.
Base Class for All LLRP LTK Messages.
Definition: ltkcpp_base.h:1088
Definition: ltkcpp.h:45