PageRenderTime 53ms CodeModel.GetById 23ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llxml/llxmlparser.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 416 lines | 162 code | 47 blank | 207 comment | 7 complexity | 7eb08cb350ddb953b59be1bd6d89add2 MD5 | raw file
  1/** 
  2 * @file llxmlparser.cpp
  3 * @brief LLXmlParser implementation
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27// llxmlparser.cpp
 28//              
 29// copyright 2002, linden research inc
 30
 31
 32#include "linden_common.h"
 33
 34#include "llxmlparser.h"
 35#include "llerror.h"
 36
 37
 38LLXmlParser::LLXmlParser()
 39	:
 40	mParser( NULL ),
 41	mDepth( 0 )
 42{
 43	mAuxErrorString = "no error";
 44
 45	// Override the document's declared encoding.
 46	mParser = XML_ParserCreate(NULL);
 47
 48	XML_SetUserData(mParser, this);
 49	XML_SetElementHandler(					mParser,	startElementHandler, endElementHandler);
 50	XML_SetCharacterDataHandler(			mParser,	characterDataHandler);
 51	XML_SetProcessingInstructionHandler(	mParser,	processingInstructionHandler);
 52	XML_SetCommentHandler(					mParser,	commentHandler);
 53
 54	XML_SetCdataSectionHandler(				mParser,	startCdataSectionHandler, endCdataSectionHandler);
 55
 56	// This sets the default handler but does not inhibit expansion of internal entities.
 57	// The entity reference will not be passed to the default handler.
 58	XML_SetDefaultHandlerExpand(			mParser,	defaultDataHandler);
 59	
 60	XML_SetUnparsedEntityDeclHandler(		mParser,	unparsedEntityDeclHandler);
 61}
 62
 63LLXmlParser::~LLXmlParser()
 64{
 65	XML_ParserFree( mParser );
 66}
 67
 68
 69BOOL LLXmlParser::parseFile(const std::string &path)
 70{
 71	llassert( !mDepth );
 72	
 73	BOOL success = TRUE;
 74
 75	LLFILE* file = LLFile::fopen(path, "rb");		/* Flawfinder: ignore */
 76	if( !file )
 77	{
 78		mAuxErrorString = llformat( "Couldn't open file %s", path.c_str());
 79		success = FALSE;
 80	}
 81	else
 82	{
 83		S32 bytes_read = 0;
 84		
 85		fseek(file, 0L, SEEK_END);
 86		S32 buffer_size = ftell(file);
 87		fseek(file, 0L, SEEK_SET);
 88
 89		void* buffer = XML_GetBuffer(mParser, buffer_size);
 90		if( !buffer ) 
 91		{
 92			mAuxErrorString = llformat( "Unable to allocate XML buffer while reading file %s", path.c_str() );
 93			success = FALSE;
 94			goto exit_label;
 95		}
 96		
 97		bytes_read = (S32)fread(buffer, 1, buffer_size, file);
 98		if( bytes_read <= 0 )
 99		{
100			mAuxErrorString = llformat( "Error while reading file  %s", path.c_str() );
101			success = FALSE;
102			goto exit_label;
103		}
104		
105		if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
106		{
107			mAuxErrorString = llformat( "Error while parsing file  %s", path.c_str() );
108			success = FALSE;
109		}
110
111exit_label: 
112		fclose( file );
113	}
114
115
116	if( success )
117	{
118		llassert( !mDepth );
119	}
120	mDepth = 0;
121
122	if( !success )
123	{
124		llwarns << mAuxErrorString << llendl;
125	}
126
127	return success;
128}
129
130
131//	Parses some input. Returns 0 if a fatal error is detected.
132//	The last call must have isFinal true;
133//	len may be zero for this call (or any other).
134S32 LLXmlParser::parse( const char* buf, int len, int isFinal )
135{
136	return XML_Parse(mParser, buf, len, isFinal);
137}
138
139const char* LLXmlParser::getErrorString()
140{
141	const char* error_string = XML_ErrorString(XML_GetErrorCode( mParser ));
142	if( !error_string )
143	{
144		error_string = mAuxErrorString.c_str();
145	}
146	return error_string;
147}
148
149S32 LLXmlParser::getCurrentLineNumber()
150{
151	return XML_GetCurrentLineNumber( mParser );
152}
153
154S32 LLXmlParser::getCurrentColumnNumber()
155{
156	return XML_GetCurrentColumnNumber(mParser);
157}
158
159///////////////////////////////////////////////////////////////////////////////
160// Pseudo-private methods.  These are only used by internal callbacks.
161
162// static 
163void LLXmlParser::startElementHandler(
164	 void *userData,
165	 const XML_Char *name,
166	 const XML_Char **atts)
167{
168	LLXmlParser* self = (LLXmlParser*) userData;
169	self->startElement( name, atts );
170	self->mDepth++;
171}
172
173// static 
174void LLXmlParser::endElementHandler(
175	void *userData,
176	const XML_Char *name)
177{
178	LLXmlParser* self = (LLXmlParser*) userData;
179	self->mDepth--;
180	self->endElement( name );
181}
182
183// s is not 0 terminated.
184// static 
185void LLXmlParser::characterDataHandler(
186	void *userData,
187	const XML_Char *s,
188	int len)
189{
190	LLXmlParser* self = (LLXmlParser*) userData;
191	self->characterData( s, len );
192}
193
194// target and data are 0 terminated
195// static 
196void LLXmlParser::processingInstructionHandler(
197	void *userData,
198	const XML_Char *target,
199	const XML_Char *data)
200{
201	LLXmlParser* self = (LLXmlParser*) userData;
202	self->processingInstruction( target, data );
203}
204
205// data is 0 terminated 
206// static
207void LLXmlParser::commentHandler(void *userData, const XML_Char *data)
208{
209	LLXmlParser* self = (LLXmlParser*) userData;
210	self->comment( data );
211}
212
213// static
214void LLXmlParser::startCdataSectionHandler(void *userData)
215{
216	LLXmlParser* self = (LLXmlParser*) userData;
217	self->mDepth++;
218	self->startCdataSection();
219}
220
221// static
222void LLXmlParser::endCdataSectionHandler(void *userData)
223{
224	LLXmlParser* self = (LLXmlParser*) userData;
225	self->endCdataSection();
226	self->mDepth++;
227}
228
229//	This is called for any characters in the XML document for
230//	which there is no applicable handler.  This includes both
231//	characters that are part of markup which is of a kind that is
232//	not reported (comments, markup declarations), or characters
233//	that are part of a construct which could be reported but
234//	for which no handler has been supplied. The characters are passed
235//	exactly as they were in the XML document except that
236//	they will be encoded in UTF-8.  Line boundaries are not normalized.
237//	Note that a byte order mark character is not passed to the default handler.
238//	There are no guarantees about how characters are divided between calls
239//	to the default handler: for example, a comment might be split between
240//	multiple calls.
241
242// static 
243void LLXmlParser::defaultDataHandler(
244	void *userData,
245	const XML_Char *s,
246	int len)
247{
248	LLXmlParser* self = (LLXmlParser*) userData;
249	self->defaultData( s, len );
250}
251
252//	This is called for a declaration of an unparsed (NDATA)
253//	entity.  The base argument is whatever was set by XML_SetBase.
254//	The entityName, systemId and notationName arguments will never be null.
255//	The other arguments may be.
256// static 
257void LLXmlParser::unparsedEntityDeclHandler(
258	void *userData,
259	const XML_Char *entityName,
260	const XML_Char *base,
261	const XML_Char *systemId,
262	const XML_Char *publicId,
263	const XML_Char *notationName)
264{
265	LLXmlParser* self = (LLXmlParser*) userData;
266	self->unparsedEntityDecl( entityName, base, systemId, publicId, notationName );
267}
268
269
270
271
272////////////////////////////////////////////////////////////////////
273// Test code.
274
275/*
276class LLXmlDOMParser : public LLXmlParser
277{
278public:
279
280	LLXmlDOMParser() {}
281	virtual ~LLXmlDOMParser() {}
282
283	void tabs()
284	{
285		for ( int i = 0; i < getDepth(); i++)
286		{
287			putchar(' ');
288		}
289	}
290
291	virtual void startElement(const char *name, const char **atts) 
292	{
293		tabs();
294		printf("startElement %s\n", name);
295		
296		S32 i = 0;
297		while( atts[i] && atts[i+1] )
298		{
299			tabs();
300			printf( "\t%s=%s\n", atts[i], atts[i+1] );
301			i += 2;
302		}
303
304		if( atts[i] )
305		{
306			tabs();
307			printf( "\ttrailing attribute: %s\n", atts[i] );
308		}
309	}
310
311	virtual void endElement(const char *name) 
312	{
313		tabs();
314		printf("endElement %s\n", name);
315	}
316
317	virtual void characterData(const char *s, int len) 
318	{
319		tabs();
320
321		char* str = new char[len+1];
322		strncpy( str, s, len );
323		str[len] = '\0';
324		printf("CharacterData %s\n", str);
325		delete str;
326	}
327
328	virtual void processingInstruction(const char *target, const char *data)
329	{
330		tabs();
331		printf("processingInstruction %s\n", data);
332	}
333	virtual void comment(const char *data)
334	{
335		tabs();
336		printf("comment %s\n", data);
337	}
338
339	virtual void startCdataSection()
340	{
341		tabs();
342		printf("startCdataSection\n");
343	}
344
345	virtual void endCdataSection()
346	{
347		tabs();
348		printf("endCdataSection\n");
349	}
350
351	virtual void defaultData(const char *s, int len)
352	{
353		tabs();
354
355		char* str = new char[len+1];
356		strncpy( str, s, len );
357		str[len] = '\0';
358		printf("defaultData %s\n", str);
359		delete str;
360	}
361
362	virtual void unparsedEntityDecl(
363		const char *entityName,
364		const char *base,
365		const char *systemId,
366		const char *publicId,
367		const char *notationName)
368	{
369		tabs();
370
371		printf(
372			"unparsed entity:\n"
373				"\tentityName %s\n"
374				"\tbase %s\n"
375				"\tsystemId %s\n"
376				"\tpublicId %s\n"
377				"\tnotationName %s\n",
378			entityName,
379			base,
380			systemId,
381			publicId,
382			notationName );
383	}
384};
385
386
387int main()
388{
389  char buf[1024];
390
391  LLFILE* file = LLFile::fopen("test.xml", "rb");
392  if( !file )
393  {
394	  return 1;
395  }
396
397  LLXmlDOMParser parser;
398  int done;
399  do {
400    size_t len = fread(buf, 1, sizeof(buf), file);
401    done = len < sizeof(buf);
402    if( 0 == parser.parse( buf, len, done) )
403	{
404      fprintf(stderr,
405	      "%s at line %d\n",
406	      parser.getErrorString(),
407	      parser.getCurrentLineNumber() );
408      return 1;
409    }
410  } while (!done);
411
412  fclose( file );
413  return 0;
414}
415*/
416