LTKCPP-- LLRP Toolkit C Plus Plus Library
xml2llrp.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,2011. All rights reserved.                *
00012  *                                                                           *
00013  *****************************************************************************/
00014 
00037 #include <stdio.h>
00038 #include "ltkcpp.h"
00039 #include "Impinj/impinj_ltkcpp.h"
00040 #include "Impinj/impinjinternal_ltkcpp.h"
00041 #include "dirent.h"
00042 #include "sys/stat.h"
00043 #include "libxml/parser.h"
00044 
00045 using namespace LLRP;
00046 
00047 #define MAX_PATH_LEN            (256)
00048 
00049 CTypeRegistry *             pTypeRegistry;
00050 
00051 
00052 /* This is the message format that is agreed upon when messages fail
00053 ** to decode. It's somewhat arbitrary, but allows us to do easy
00054 ** comparisons */
00055 /* the corresponding binary packet */
00056 unsigned char errMsgBinary[18] = {0x04, 0x64, 0x00, 0x00, 
00057                                   0x00, 0x12, 0x00, 0x00, 
00058                                   0x00, 0x00, 0x01, 0x1F, 
00059                                   0x00, 0x08, 0x00, 0x00, 
00060                                   0x00, 0x00};
00061 
00062 #ifdef WIN32
00063     char                            pathSeparator = '\\';
00064 #else
00065     char                            pathSeparator = '/';
00066 #endif
00067 
00077 void convertFile(char *ifile, char *ofile) {
00078     FILE *                      infp;
00079     FILE *                      outfp;
00080     CMessage *              pMessage;
00081     CXMLTextDecoder *       pDecoder;
00082     puts(ifile);
00083     puts(ofile);
00084     unsigned char *binbuf;
00085     char *xmlbuf;
00086     int xmlLen;
00087     int binLen;
00088 
00089     /*
00090      * Open input file
00091      */
00092 #ifdef WIN32
00093     if(fopen_s(&infp, ifile, "r"))
00094 #else
00095     infp = fopen(ifile, "r");
00096     if(infp == NULL)
00097 #endif
00098     {
00099         perror(ifile);
00100         xmlCleanupParser();
00101         exit(-1);
00102     }
00103 
00104     fseek(infp,0,SEEK_END); //go to end
00105     xmlLen=ftell(infp); //get position at end (length)
00106     fseek(infp,0,SEEK_SET); //go to beg.
00107     xmlbuf=(char *) malloc(xmlLen); //malloc buffer
00108     if (xmlbuf)
00109         fread(xmlbuf,xmlLen,1,infp); //read into buffer
00110     fclose(infp);   
00111 
00112     if(xmlbuf == NULL) {
00113         perror("Could not malloc buffer for LTK-XML message");
00114         xmlCleanupParser();
00115         exit(-2);
00116     }
00117 
00118     /* open the output file for writing */
00119 #ifdef WIN32
00120     if(fopen_s(&outfp, ofile, "wb")) {
00121 #else
00122     outfp = fopen(ofile, "w");
00123     if(outfp == NULL) {
00124 #endif
00125         fprintf(stderr, "Could not open output file %s for writing", ofile);
00126         xmlCleanupParser();
00127         exit(-3);
00128     }
00129 
00130     /*
00131      * Construct a frame decoder. It references the
00132      * type registry and the input buffer.
00133      */
00134     pDecoder = new CXMLTextDecoder(pTypeRegistry, xmlbuf, xmlLen);
00135 
00136     /*
00137      * Now ask the frame decoder to actually decode
00138      * the message. It returns NULL for an error.
00139      */
00140     pMessage = pDecoder->decodeMessage();
00141 
00142     /*
00143      * Did the decode fail?
00144      */
00145     if(NULL == pMessage)
00146     {
00147         const CErrorDetails *pError;
00148  
00149         /* encode error message as binary */
00150         fwrite(errMsgBinary, 1, sizeof(errMsgBinary), outfp);
00151 
00152         pError = &pDecoder->m_ErrorDetails;
00153  
00154 #ifdef XML2LLRP_DEBUG
00155         fprintf(stderr, "ERROR: Decoder error, result=%d\n",
00156                 pError->m_eResultCode);
00157 
00158         if(NULL != pMessageIDStr)
00159         {
00160             fprintf(stderr, "ERROR ... MessageID=%s\n", 
00161                    pMessageIDStr);
00162         }
00163         if(NULL != pError->m_pRefType)
00164         { 
00165             fprintf(stderr, "ERROR ... refType=%s\n",
00166                    pError->m_pRefType->m_pName);
00167         }
00168         if(NULL != pError->m_pRefField)
00169         {
00170             fprintf(stderr, "ERROR ... refField=%s\n",
00171                    pError->m_pRefField->m_pName);
00172         }
00173         if(NULL != pError->m_pWhatStr)
00174         {
00175             fprintf(stderr, "ERROR ... whatStr=%s\n",
00176                    pError->m_pWhatStr); 
00177         }
00178         if(0 != pError->m_OtherDetail)
00179         {
00180             fprintf(stderr, "ERROR ... XML line number %d\n", 
00181                     pError->m_OtherDetail);
00182         }
00183 #endif /* XML2LLRP_DEBUG */
00184 
00185         delete pDecoder;
00186         /* we are done with this buffer */
00187         free(xmlbuf);
00188         return;
00189     }
00190     else
00191     {
00192         CFrameEncoder *         pEncoder;
00193 
00194         /* clean up the xml decoder */
00195         delete pDecoder;
00196         /* we are done with this buffer */
00197         free(xmlbuf);
00198 
00199         /* this is big enough */
00200         binbuf = (unsigned char *) malloc(xmlLen);
00201         if(NULL == binbuf) {
00202             perror("Could not malloc buffer for LLRP Binary packet");
00203             xmlCleanupParser();
00204             exit(-5);            
00205         } 
00206       
00207         memset(binbuf, 0, xmlLen);
00208         pEncoder = new CFrameEncoder(binbuf, xmlLen);
00209 
00210         /*
00211          * Do the encode.
00212          * TODO: check the result, tattle on errors.
00213          */
00214         pEncoder->encodeElement(pMessage);
00215         /*
00216          * Get the byte length of the resulting frame.
00217          */
00218         binLen = pEncoder->getLength();
00219         /*
00220          * Check the status, tattle on errors
00221          */
00222         if(RC_OK != pEncoder->m_ErrorDetails.m_eResultCode)
00223         {
00224             const CErrorDetails *pError;
00225             pError = &pEncoder->m_ErrorDetails;
00226 
00227             /* encode error message as binary */
00228             fwrite(errMsgBinary,1, sizeof(errMsgBinary), outfp);
00229 
00230 #ifdef XML2LLRP_DEBUG
00231             fprintf(stderr, "Failed to Encode XML message\n");
00232             fprintf(stderr, "ERROR: Encoder error, status=%d\n",
00233                    pError->m_eResultCode);
00234             if(NULL != pError->m_pRefType)
00235             {
00236                 fprintf(stderr, "ERROR ... refType=%s\n",
00237                         pError->m_pRefType->m_pName);
00238             }
00239             if(NULL != pError->m_pRefField)
00240             {
00241                 fprintf(stderr, "ERROR ... refField=%s\n",
00242                         pError->m_pRefField->m_pName);
00243             }
00244 #endif /* XML2LLRP_DEBUG */
00245         }
00246         else
00247         {
00248             fwrite(binbuf, 1, binLen, outfp);
00249         }
00250 
00251 
00252         /* free the frame encoder */
00253         free(binbuf);
00254         delete pEncoder;
00255     }
00256 
00257     fclose(outfp);
00258 
00259     /* free the message we built */
00260     delete pMessage;
00261 }
00262 
00263 
00264 void convertDirEntry(char *idir, char *odir, struct dirent *ep) {
00265     char vector[MAX_PATH_LEN];
00266     char iBuf[MAX_PATH_LEN];
00267     char oBuf[MAX_PATH_LEN];
00268     int len;
00269 
00270     if(!ep) 
00271     {
00272         perror("Invalid file endpoint from dirent");
00273     }
00274     
00275     /* string better end in .bin */
00276     len = (int) strlen(ep->d_name);
00277     if(len < 4) 
00278     {
00279         /* if not just ignore this file */
00280         return;
00281     }
00282 
00283     /* call it a success if we don't need to convert */
00284     if(strncmp(&ep->d_name[len-4], ".xml", 4) != 0) {
00285         /* ignore this file */
00286         return;
00287     }
00288 
00289     memset(vector, 0x00, sizeof(vector));
00290 #ifdef WIN32
00291     strncpy_s(vector, ep->d_name, len-4);
00292     sprintf_s(iBuf, "%s%s.xml", idir, vector); 
00293     sprintf_s(oBuf, "%s%s.bin", odir, vector);
00294 #else
00295     strncpy(vector, ep->d_name, len-4);
00296     sprintf(iBuf, "%s%s.xml", idir, vector); 
00297     sprintf(oBuf, "%s%s.bin", odir, vector);
00298 #endif
00299     convertFile(iBuf, oBuf);
00300 }
00301 
00302 int
00303 main (int ac, char *av[])
00304 {
00305     DIR *                       dpin;  
00306     DIR *                       dpout;
00307     char                        idir[MAX_PATH_LEN];
00308     char                        odir[MAX_PATH_LEN];
00309     int                         len;
00310     struct dirent*              ep;
00311 
00312     /*
00313      * Check arg count
00314      */
00315     if(ac != 3)
00316     {
00317         fprintf(stderr, "ERROR: Bad usage\nusage: %s INPUTDIR OUTPUTDIR\n", av[0]);
00318         exit(1);
00319     }
00320 
00321     dpin = opendir (av[1]);  
00322     if (dpin == NULL)  
00323     {    
00324         fprintf(stderr, "ERROR: Could not stat input directory %s\n", av[1]);
00325         exit(-1);
00326     }
00327 
00328     /* make sure the directory has a path separator at the end */
00329 #ifdef WIN32
00330     strcpy_s(idir, av[1]);
00331 #else
00332     strcpy(idir, av[1]);
00333 #endif
00334 
00335     len = (int) strlen(idir);
00336     if(idir[len-1] != pathSeparator) {
00337         idir[len] = pathSeparator;
00338         idir[len + 1] = 0;
00339     }
00340 
00341 
00342     dpout = opendir (av[1]);  
00343     if (dpout == NULL)  
00344     {    
00345         fprintf(stderr, "ERROR: Could not stat output directory %s\n", av[2]);
00346         exit(-1);
00347     }
00348 
00349     /* make sure the directory has a path separator at the end */
00350 #ifdef WIN32
00351     strcpy_s(odir, av[2]);
00352 #else
00353     strcpy(odir, av[2]);
00354 #endif
00355     len = (int) strlen(odir);
00356     if(odir[len-1] != pathSeparator) {
00357         odir[len] = pathSeparator;
00358         odir[len + 1] = 0;
00359     }
00360 
00361     /*
00362      * Construct the type registry. This is needed for decode.
00363      */
00364     pTypeRegistry = getTheTypeRegistry();
00365 
00366     enrollImpinjTypesIntoRegistry(pTypeRegistry);
00367     enrollImpinjInternalTypesIntoRegistry(pTypeRegistry);
00368 
00369 
00370     while((ep=readdir(dpin))) {
00371         convertDirEntry(idir, odir, ep);
00372     }
00373 
00374     (void) closedir(dpin);
00375     (void) closedir(dpout);
00376 
00377     /*
00378      * Done with the type registry.
00379      */
00380     delete pTypeRegistry;
00381     xmlCleanupParser();
00382 }