llxmlparser.cpp

Go to the documentation of this file.
00001 
00032 // llxmlparser.cpp
00033 //              
00034 // copyright 2002, linden research inc
00035 
00036 
00037 #include "linden_common.h"
00038 
00039 #include "llxmlparser.h"
00040 #include "llerror.h"
00041 
00042 
00043 LLXmlParser::LLXmlParser()
00044         :
00045         mParser( NULL ),
00046         mDepth( 0 )
00047 {
00048         strcpy( mAuxErrorString, "no error" );          /* Flawfinder: ignore */
00049 
00050         // Override the document's declared encoding.
00051         mParser = XML_ParserCreate(NULL);
00052 
00053         XML_SetUserData(mParser, this);
00054         XML_SetElementHandler(                                  mParser,        startElementHandler, endElementHandler);
00055         XML_SetCharacterDataHandler(                    mParser,        characterDataHandler);
00056         XML_SetProcessingInstructionHandler(    mParser,        processingInstructionHandler);
00057         XML_SetCommentHandler(                                  mParser,        commentHandler);
00058 
00059         XML_SetCdataSectionHandler(                             mParser,        startCdataSectionHandler, endCdataSectionHandler);
00060 
00061         // This sets the default handler but does not inhibit expansion of internal entities.
00062         // The entity reference will not be passed to the default handler.
00063         XML_SetDefaultHandlerExpand(                    mParser,        defaultDataHandler);
00064         
00065         XML_SetUnparsedEntityDeclHandler(               mParser,        unparsedEntityDeclHandler);
00066 }
00067 
00068 LLXmlParser::~LLXmlParser()
00069 {
00070         XML_ParserFree( mParser );
00071 }
00072 
00073 
00074 BOOL LLXmlParser::parseFile(const std::string &path)
00075 {
00076         llassert( !mDepth );
00077         
00078         BOOL success = TRUE;
00079 
00080         FILE* file = LLFile::fopen(path.c_str(), "rb");         /* Flawfinder: ignore */
00081         if( !file )
00082         {
00083                 snprintf( mAuxErrorString, sizeof(mAuxErrorString), "Couldn't open file %s", path.c_str());     /* Flawfinder: ignore */
00084                 success = FALSE;
00085         }
00086         else
00087         {
00088                 S32 bytes_read = 0;
00089                 
00090                 fseek(file, 0L, SEEK_END);
00091                 S32 buffer_size = ftell(file);
00092                 fseek(file, 0L, SEEK_SET);
00093 
00094                 void* buffer = XML_GetBuffer(mParser, buffer_size);
00095                 if( !buffer ) 
00096                 {
00097                         snprintf( mAuxErrorString, sizeof(mAuxErrorString), "Unable to allocate XML buffer while reading file %s", path.c_str() );      /* Flawfinder: ignore */
00098                         success = FALSE;
00099                         goto exit_label;
00100                 }
00101                 
00102                 bytes_read = (S32)fread(buffer, 1, buffer_size, file);
00103                 if( bytes_read <= 0 )
00104                 {
00105                         snprintf( mAuxErrorString, sizeof(mAuxErrorString), "Error while reading file  %s", path.c_str() );     /* Flawfinder: ignore */
00106                         success = FALSE;
00107                         goto exit_label;
00108                 }
00109                 
00110                 if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
00111                 {
00112                         snprintf( mAuxErrorString, sizeof(mAuxErrorString), "Error while parsing file  %s", path.c_str() );     /* Flawfinder: ignore */
00113                         success = FALSE;
00114                 }
00115 
00116 exit_label: 
00117                 fclose( file );
00118         }
00119 
00120 
00121         if( success )
00122         {
00123                 llassert( !mDepth );
00124         }
00125         mDepth = 0;
00126 
00127         if( !success )
00128         {
00129                 llwarns << mAuxErrorString << llendl;
00130         }
00131 
00132         return success;
00133 }
00134 
00135 
00136 //      Parses some input. Returns 0 if a fatal error is detected.
00137 //      The last call must have isFinal true;
00138 //      len may be zero for this call (or any other).
00139 S32 LLXmlParser::parse( const char* buf, int len, int isFinal )
00140 {
00141         return XML_Parse(mParser, buf, len, isFinal);
00142 }
00143 
00144 const char* LLXmlParser::getErrorString()
00145 {
00146         const char* error_string = XML_ErrorString(XML_GetErrorCode( mParser ));
00147         if( !error_string )
00148         {
00149                 error_string = mAuxErrorString;
00150         }
00151         return error_string;
00152 }
00153 
00154 S32 LLXmlParser::getCurrentLineNumber()
00155 {
00156         return XML_GetCurrentLineNumber( mParser );
00157 }
00158 
00159 S32 LLXmlParser::getCurrentColumnNumber()
00160 {
00161         return XML_GetCurrentColumnNumber(mParser);
00162 }
00163 
00165 // Pseudo-private methods.  These are only used by internal callbacks.
00166 
00167 // static 
00168 void LLXmlParser::startElementHandler(
00169          void *userData,
00170          const XML_Char *name,
00171          const XML_Char **atts)
00172 {
00173         LLXmlParser* self = (LLXmlParser*) userData;
00174         self->startElement( name, atts );
00175         self->mDepth++;
00176 }
00177 
00178 // static 
00179 void LLXmlParser::endElementHandler(
00180         void *userData,
00181         const XML_Char *name)
00182 {
00183         LLXmlParser* self = (LLXmlParser*) userData;
00184         self->mDepth--;
00185         self->endElement( name );
00186 }
00187 
00188 // s is not 0 terminated.
00189 // static 
00190 void LLXmlParser::characterDataHandler(
00191         void *userData,
00192         const XML_Char *s,
00193         int len)
00194 {
00195         LLXmlParser* self = (LLXmlParser*) userData;
00196         self->characterData( s, len );
00197 }
00198 
00199 // target and data are 0 terminated
00200 // static 
00201 void LLXmlParser::processingInstructionHandler(
00202         void *userData,
00203         const XML_Char *target,
00204         const XML_Char *data)
00205 {
00206         LLXmlParser* self = (LLXmlParser*) userData;
00207         self->processingInstruction( target, data );
00208 }
00209 
00210 // data is 0 terminated 
00211 // static
00212 void LLXmlParser::commentHandler(void *userData, const XML_Char *data)
00213 {
00214         LLXmlParser* self = (LLXmlParser*) userData;
00215         self->comment( data );
00216 }
00217 
00218 // static
00219 void LLXmlParser::startCdataSectionHandler(void *userData)
00220 {
00221         LLXmlParser* self = (LLXmlParser*) userData;
00222         self->mDepth++;
00223         self->startCdataSection();
00224 }
00225 
00226 // static
00227 void LLXmlParser::endCdataSectionHandler(void *userData)
00228 {
00229         LLXmlParser* self = (LLXmlParser*) userData;
00230         self->endCdataSection();
00231         self->mDepth++;
00232 }
00233 
00234 //      This is called for any characters in the XML document for
00235 //      which there is no applicable handler.  This includes both
00236 //      characters that are part of markup which is of a kind that is
00237 //      not reported (comments, markup declarations), or characters
00238 //      that are part of a construct which could be reported but
00239 //      for which no handler has been supplied. The characters are passed
00240 //      exactly as they were in the XML document except that
00241 //      they will be encoded in UTF-8.  Line boundaries are not normalized.
00242 //      Note that a byte order mark character is not passed to the default handler.
00243 //      There are no guarantees about how characters are divided between calls
00244 //      to the default handler: for example, a comment might be split between
00245 //      multiple calls.
00246 
00247 // static 
00248 void LLXmlParser::defaultDataHandler(
00249         void *userData,
00250         const XML_Char *s,
00251         int len)
00252 {
00253         LLXmlParser* self = (LLXmlParser*) userData;
00254         self->defaultData( s, len );
00255 }
00256 
00257 //      This is called for a declaration of an unparsed (NDATA)
00258 //      entity.  The base argument is whatever was set by XML_SetBase.
00259 //      The entityName, systemId and notationName arguments will never be null.
00260 //      The other arguments may be.
00261 // static 
00262 void LLXmlParser::unparsedEntityDeclHandler(
00263         void *userData,
00264         const XML_Char *entityName,
00265         const XML_Char *base,
00266         const XML_Char *systemId,
00267         const XML_Char *publicId,
00268         const XML_Char *notationName)
00269 {
00270         LLXmlParser* self = (LLXmlParser*) userData;
00271         self->unparsedEntityDecl( entityName, base, systemId, publicId, notationName );
00272 }
00273 
00274 
00275 
00276 
00278 // Test code.
00279 
00280 /*
00281 class LLXmlDOMParser : public LLXmlParser
00282 {
00283 public:
00284 
00285         LLXmlDOMParser() {}
00286         virtual ~LLXmlDOMParser() {}
00287 
00288         void tabs()
00289         {
00290                 for ( int i = 0; i < getDepth(); i++)
00291                 {
00292                         putchar(' ');
00293                 }
00294         }
00295 
00296         virtual void startElement(const char *name, const char **atts) 
00297         {
00298                 tabs();
00299                 printf("startElement %s\n", name);
00300                 
00301                 S32 i = 0;
00302                 while( atts[i] && atts[i+1] )
00303                 {
00304                         tabs();
00305                         printf( "\t%s=%s\n", atts[i], atts[i+1] );
00306                         i += 2;
00307                 }
00308 
00309                 if( atts[i] )
00310                 {
00311                         tabs();
00312                         printf( "\ttrailing attribute: %s\n", atts[i] );
00313                 }
00314         }
00315 
00316         virtual void endElement(const char *name) 
00317         {
00318                 tabs();
00319                 printf("endElement %s\n", name);
00320         }
00321 
00322         virtual void characterData(const char *s, int len) 
00323         {
00324                 tabs();
00325 
00326                 char* str = new char[len+1];
00327                 strncpy( str, s, len );
00328                 str[len] = '\0';
00329                 printf("CharacterData %s\n", str);
00330                 delete str;
00331         }
00332 
00333         virtual void processingInstruction(const char *target, const char *data)
00334         {
00335                 tabs();
00336                 printf("processingInstruction %s\n", data);
00337         }
00338         virtual void comment(const char *data)
00339         {
00340                 tabs();
00341                 printf("comment %s\n", data);
00342         }
00343 
00344         virtual void startCdataSection()
00345         {
00346                 tabs();
00347                 printf("startCdataSection\n");
00348         }
00349 
00350         virtual void endCdataSection()
00351         {
00352                 tabs();
00353                 printf("endCdataSection\n");
00354         }
00355 
00356         virtual void defaultData(const char *s, int len)
00357         {
00358                 tabs();
00359 
00360                 char* str = new char[len+1];
00361                 strncpy( str, s, len );
00362                 str[len] = '\0';
00363                 printf("defaultData %s\n", str);
00364                 delete str;
00365         }
00366 
00367         virtual void unparsedEntityDecl(
00368                 const char *entityName,
00369                 const char *base,
00370                 const char *systemId,
00371                 const char *publicId,
00372                 const char *notationName)
00373         {
00374                 tabs();
00375 
00376                 printf(
00377                         "unparsed entity:\n"
00378                                 "\tentityName %s\n"
00379                                 "\tbase %s\n"
00380                                 "\tsystemId %s\n"
00381                                 "\tpublicId %s\n"
00382                                 "\tnotationName %s\n",
00383                         entityName,
00384                         base,
00385                         systemId,
00386                         publicId,
00387                         notationName );
00388         }
00389 };
00390 
00391 
00392 int main()
00393 {
00394   char buf[1024];
00395 
00396   FILE* file = LLFile::fopen("test.xml", "rb");
00397   if( !file )
00398   {
00399           return 1;
00400   }
00401 
00402   LLXmlDOMParser parser;
00403   int done;
00404   do {
00405     size_t len = fread(buf, 1, sizeof(buf), file);
00406     done = len < sizeof(buf);
00407     if( 0 == parser.parse( buf, len, done) )
00408         {
00409       fprintf(stderr,
00410               "%s at line %d\n",
00411               parser.getErrorString(),
00412               parser.getCurrentLineNumber() );
00413       return 1;
00414     }
00415   } while (!done);
00416 
00417   fclose( file );
00418   return 0;
00419 }
00420 */
00421 

Generated on Thu Jul 1 06:09:48 2010 for Second Life Viewer by  doxygen 1.4.7