aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llxml/llxmltree.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llxml/llxmltree.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/llxml/llxmltree.cpp690
1 files changed, 690 insertions, 0 deletions
diff --git a/linden/indra/llxml/llxmltree.cpp b/linden/indra/llxml/llxmltree.cpp
new file mode 100644
index 0000000..2b6a6a1
--- /dev/null
+++ b/linden/indra/llxml/llxmltree.cpp
@@ -0,0 +1,690 @@
1/**
2 * @file llxmltree.cpp
3 * @brief LLXmlTree implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include "llxmltree.h"
31#include "v3color.h"
32#include "v4color.h"
33#include "v4coloru.h"
34#include "v3math.h"
35#include "v3dmath.h"
36#include "v4math.h"
37#include "llquaternion.h"
38#include "lluuid.h"
39
40//////////////////////////////////////////////////////////////
41// LLXmlTree
42
43// static
44LLStdStringTable LLXmlTree::sAttributeKeys(1024);
45
46LLXmlTree::LLXmlTree()
47 : mRoot( NULL ),
48 mNodeNames(512)
49{
50}
51
52LLXmlTree::~LLXmlTree()
53{
54 cleanup();
55}
56
57void LLXmlTree::cleanup()
58{
59 delete mRoot;
60 mRoot = NULL;
61 mNodeNames.cleanup();
62}
63
64
65BOOL LLXmlTree::parseFile(const std::string &path, BOOL keep_contents)
66{
67 delete mRoot;
68 mRoot = NULL;
69
70 LLXmlTreeParser parser(this);
71 BOOL success = parser.parseFile( path, &mRoot, keep_contents );
72 if( !success )
73 {
74 S32 line_number = parser.getCurrentLineNumber();
75 const char* error = parser.getErrorString();
76 llwarns << "LLXmlTree parse failed. Line " << line_number << ": " << error << llendl;
77 }
78 return success;
79}
80
81void LLXmlTree::dump()
82{
83 if( mRoot )
84 {
85 dumpNode( mRoot, " " );
86 }
87}
88
89void LLXmlTree::dumpNode( LLXmlTreeNode* node, const LLString& prefix )
90{
91 node->dump( prefix );
92
93 LLString new_prefix = prefix + " ";
94 for( LLXmlTreeNode* child = node->getFirstChild(); child; child = node->getNextChild() )
95 {
96 dumpNode( child, new_prefix );
97 }
98}
99
100//////////////////////////////////////////////////////////////
101// LLXmlTreeNode
102
103LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree )
104 : mName(name),
105 mParent(parent),
106 mTree(tree)
107{
108}
109
110LLXmlTreeNode::~LLXmlTreeNode()
111{
112 attribute_map_t::iterator iter;
113 for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
114 delete iter->second;
115 child_list_t::iterator child_iter;
116 for (child_iter=mChildList.begin(); child_iter != mChildList.end(); child_iter++)
117 delete *child_iter;
118}
119
120void LLXmlTreeNode::dump( const LLString& prefix )
121{
122 llinfos << prefix << mName ;
123 if( !mContents.empty() )
124 {
125 llcont << " contents = \"" << mContents << "\"";
126 }
127 attribute_map_t::iterator iter;
128 for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
129 {
130 LLStdStringHandle key = iter->first;
131 const LLString* value = iter->second;
132 llcont << prefix << " " << key << "=" << (value->empty() ? "NULL" : *value);
133 }
134 llcont << llendl;
135}
136
137BOOL LLXmlTreeNode::hasAttribute(const std::string& name)
138{
139 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
140 attribute_map_t::iterator iter = mAttributes.find(canonical_name);
141 return (iter == mAttributes.end()) ? false : true;
142}
143
144void LLXmlTreeNode::addAttribute(const std::string& name, const std::string& value)
145{
146 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
147 const LLString *newstr = new LLString(value);
148 mAttributes[canonical_name] = newstr; // insert + copy
149}
150
151LLXmlTreeNode* LLXmlTreeNode::getFirstChild()
152{
153 mChildListIter = mChildList.begin();
154 return getNextChild();
155}
156LLXmlTreeNode* LLXmlTreeNode::getNextChild()
157{
158 if (mChildListIter == mChildList.end())
159 return 0;
160 else
161 return *mChildListIter++;
162}
163
164LLXmlTreeNode* LLXmlTreeNode::getChildByName(const std::string& name)
165{
166 LLStdStringHandle tableptr = mTree->mNodeNames.checkString(name);
167 mChildMapIter = mChildMap.lower_bound(tableptr);
168 mChildMapEndIter = mChildMap.upper_bound(tableptr);
169 return getNextNamedChild();
170}
171
172LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild()
173{
174 if (mChildMapIter == mChildMapEndIter)
175 return NULL;
176 else
177 return (mChildMapIter++)->second;
178}
179
180void LLXmlTreeNode::appendContents(const std::string& str)
181{
182 mContents.append( str );
183}
184
185void LLXmlTreeNode::addChild(LLXmlTreeNode* child)
186{
187 llassert( child );
188 mChildList.push_back( child );
189
190 // Add a name mapping to this node
191 LLStdStringHandle tableptr = mTree->mNodeNames.insert(child->mName);
192 mChildMap.insert( child_map_t::value_type(tableptr, child));
193
194 child->mParent = this;
195}
196
197//////////////////////////////////////////////////////////////
198
199// These functions assume that name is already in mAttritrubteKeys
200
201BOOL LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, BOOL& value)
202{
203 const LLString *s = getAttribute( canonical_name );
204 return s && LLString::convertToBOOL( *s, value );
205}
206
207BOOL LLXmlTreeNode::getFastAttributeU8(LLStdStringHandle canonical_name, U8& value)
208{
209 const LLString *s = getAttribute( canonical_name );
210 return s && LLString::convertToU8( *s, value );
211}
212
213BOOL LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& value)
214{
215 const LLString *s = getAttribute( canonical_name );
216 return s && LLString::convertToS8( *s, value );
217}
218
219BOOL LLXmlTreeNode::getFastAttributeS16(LLStdStringHandle canonical_name, S16& value)
220{
221 const LLString *s = getAttribute( canonical_name );
222 return s && LLString::convertToS16( *s, value );
223}
224
225BOOL LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& value)
226{
227 const LLString *s = getAttribute( canonical_name );
228 return s && LLString::convertToU16( *s, value );
229}
230
231BOOL LLXmlTreeNode::getFastAttributeU32(LLStdStringHandle canonical_name, U32& value)
232{
233 const LLString *s = getAttribute( canonical_name );
234 return s && LLString::convertToU32( *s, value );
235}
236
237BOOL LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& value)
238{
239 const LLString *s = getAttribute( canonical_name );
240 return s && LLString::convertToS32( *s, value );
241}
242
243BOOL LLXmlTreeNode::getFastAttributeF32(LLStdStringHandle canonical_name, F32& value)
244{
245 const LLString *s = getAttribute( canonical_name );
246 return s && LLString::convertToF32( *s, value );
247}
248
249BOOL LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& value)
250{
251 const LLString *s = getAttribute( canonical_name );
252 return s && LLString::convertToF64( *s, value );
253}
254
255BOOL LLXmlTreeNode::getFastAttributeColor(LLStdStringHandle canonical_name, LLColor4& value)
256{
257 const LLString *s = getAttribute( canonical_name );
258 return s ? LLColor4::parseColor(s->c_str(), &value) : FALSE;
259}
260
261BOOL LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name, LLColor4& value)
262{
263 const LLString *s = getAttribute( canonical_name );
264 return s ? LLColor4::parseColor4(s->c_str(), &value) : FALSE;
265}
266
267BOOL LLXmlTreeNode::getFastAttributeColor4U(LLStdStringHandle canonical_name, LLColor4U& value)
268{
269 const LLString *s = getAttribute( canonical_name );
270 return s ? LLColor4U::parseColor4U(s->c_str(), &value ) : FALSE;
271}
272
273BOOL LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name, LLVector3& value)
274{
275 const LLString *s = getAttribute( canonical_name );
276 return s ? LLVector3::parseVector3(s->c_str(), &value ) : FALSE;
277}
278
279BOOL LLXmlTreeNode::getFastAttributeVector3d(LLStdStringHandle canonical_name, LLVector3d& value)
280{
281 const LLString *s = getAttribute( canonical_name );
282 return s ? LLVector3d::parseVector3d(s->c_str(), &value ) : FALSE;
283}
284
285BOOL LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name, LLQuaternion& value)
286{
287 const LLString *s = getAttribute( canonical_name );
288 return s ? LLQuaternion::parseQuat(s->c_str(), &value ) : FALSE;
289}
290
291BOOL LLXmlTreeNode::getFastAttributeUUID(LLStdStringHandle canonical_name, LLUUID& value)
292{
293 const LLString *s = getAttribute( canonical_name );
294 return s ? LLUUID::parseUUID(s->c_str(), &value ) : FALSE;
295}
296
297BOOL LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, LLString& value)
298{
299 const LLString *s = getAttribute( canonical_name );
300 if( !s )
301 {
302 return FALSE;
303 }
304
305 value = *s;
306 return TRUE;
307}
308
309
310//////////////////////////////////////////////////////////////
311
312BOOL LLXmlTreeNode::getAttributeBOOL(const std::string& name, BOOL& value)
313{
314 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
315 return getFastAttributeBOOL(canonical_name, value);
316}
317
318BOOL LLXmlTreeNode::getAttributeU8(const std::string& name, U8& value)
319{
320 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
321 return getFastAttributeU8(canonical_name, value);
322}
323
324BOOL LLXmlTreeNode::getAttributeS8(const std::string& name, S8& value)
325{
326 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
327 return getFastAttributeS8(canonical_name, value);
328}
329
330BOOL LLXmlTreeNode::getAttributeS16(const std::string& name, S16& value)
331{
332 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
333 return getFastAttributeS16(canonical_name, value);
334}
335
336BOOL LLXmlTreeNode::getAttributeU16(const std::string& name, U16& value)
337{
338 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
339 return getFastAttributeU16(canonical_name, value);
340}
341
342BOOL LLXmlTreeNode::getAttributeU32(const std::string& name, U32& value)
343{
344 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
345 return getFastAttributeU32(canonical_name, value);
346}
347
348BOOL LLXmlTreeNode::getAttributeS32(const std::string& name, S32& value)
349{
350 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
351 return getFastAttributeS32(canonical_name, value);
352}
353
354BOOL LLXmlTreeNode::getAttributeF32(const std::string& name, F32& value)
355{
356 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
357 return getFastAttributeF32(canonical_name, value);
358}
359
360BOOL LLXmlTreeNode::getAttributeF64(const std::string& name, F64& value)
361{
362 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
363 return getFastAttributeF64(canonical_name, value);
364}
365
366BOOL LLXmlTreeNode::getAttributeColor(const std::string& name, LLColor4& value)
367{
368 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
369 return getFastAttributeColor(canonical_name, value);
370}
371
372BOOL LLXmlTreeNode::getAttributeColor4(const std::string& name, LLColor4& value)
373{
374 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
375 return getFastAttributeColor4(canonical_name, value);
376}
377
378BOOL LLXmlTreeNode::getAttributeColor4U(const std::string& name, LLColor4U& value)
379{
380 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
381 return getFastAttributeColor4U(canonical_name, value);
382}
383
384BOOL LLXmlTreeNode::getAttributeVector3(const std::string& name, LLVector3& value)
385{
386 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
387 return getFastAttributeVector3(canonical_name, value);
388}
389
390BOOL LLXmlTreeNode::getAttributeVector3d(const std::string& name, LLVector3d& value)
391{
392 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
393 return getFastAttributeVector3d(canonical_name, value);
394}
395
396BOOL LLXmlTreeNode::getAttributeQuat(const std::string& name, LLQuaternion& value)
397{
398 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
399 return getFastAttributeQuat(canonical_name, value);
400}
401
402BOOL LLXmlTreeNode::getAttributeUUID(const std::string& name, LLUUID& value)
403{
404 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
405 return getFastAttributeUUID(canonical_name, value);
406}
407
408BOOL LLXmlTreeNode::getAttributeString(const std::string& name, LLString& value)
409{
410 LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
411 return getFastAttributeString(canonical_name, value);
412}
413
414/*
415 The following xml <message> nodes will all return the string from getTextContents():
416 "The quick brown fox\n Jumps over the lazy dog"
417
418 1. HTML paragraph format:
419 <message>
420 <p>The quick brown fox</p>
421 <p> Jumps over the lazy dog</p>
422 </message>
423 2. Each quoted section -> paragraph:
424 <message>
425 "The quick brown fox"
426 " Jumps over the lazy dog"
427 </message>
428 3. Literal text with beginning and trailing whitespace removed:
429 <message>
430The quick brown fox
431 Jumps over the lazy dog
432 </message>
433
434*/
435
436LLString LLXmlTreeNode::getTextContents()
437{
438 std::string msg;
439 LLXmlTreeNode* p = getChildByName("p");
440 if (p)
441 {
442 // Case 1: node has <p>text</p> tags
443 while (p)
444 {
445 msg += p->getContents() + "\n";
446 p = getNextNamedChild();
447 }
448 }
449 else
450 {
451 std::string::size_type n = mContents.find_first_not_of(" \t\n");
452 if (n != std::string::npos && mContents[n] == '\"')
453 {
454 // Case 2: node has quoted text
455 S32 num_lines = 0;
456 while(1)
457 {
458 // mContents[n] == '"'
459 ++n;
460 std::string::size_type t = n;
461 std::string::size_type m = 0;
462 // fix-up escaped characters
463 while(1)
464 {
465 m = mContents.find_first_of("\\\"", t); // find first \ or "
466 if ((m == std::string::npos) || (mContents[m] == '\"'))
467 {
468 break;
469 }
470 mContents.erase(m,1);
471 t = m+1;
472 }
473 if (m == std::string::npos)
474 {
475 break;
476 }
477 // mContents[m] == '"'
478 num_lines++;
479 msg += mContents.substr(n,m-n) + "\n";
480 n = mContents.find_first_of("\"", m+1);
481 if (n == std::string::npos)
482 {
483 if (num_lines == 1)
484 {
485 msg.erase(msg.size()-1); // remove "\n" if only one line
486 }
487 break;
488 }
489 }
490 }
491 else
492 {
493 // Case 3: node has embedded text (beginning and trailing whitespace trimmed)
494 msg = mContents;
495 }
496 }
497 return msg;
498}
499
500
501//////////////////////////////////////////////////////////////
502// LLXmlTreeParser
503
504LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree)
505 : mTree(tree),
506 mRoot( NULL ),
507 mCurrent( NULL ),
508 mDump( FALSE )
509{
510}
511
512LLXmlTreeParser::~LLXmlTreeParser()
513{
514}
515
516BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents)
517{
518 llassert( !mRoot );
519 llassert( !mCurrent );
520
521 mKeepContents = keep_contents;
522
523 BOOL success = LLXmlParser::parseFile(path);
524
525 *root = mRoot;
526 mRoot = NULL;
527
528 if( success )
529 {
530 llassert( !mCurrent );
531 }
532 mCurrent = NULL;
533
534 return success;
535}
536
537
538const std::string& LLXmlTreeParser::tabs()
539{
540 static LLString s;
541 s = "";
542 S32 num_tabs = getDepth() - 1;
543 for( S32 i = 0; i < num_tabs; i++)
544 {
545 s += " ";
546 }
547 return s;
548}
549
550void LLXmlTreeParser::startElement(const char* name, const char **atts)
551{
552 if( mDump )
553 {
554 llinfos << tabs() << "startElement " << name << llendl;
555
556 S32 i = 0;
557 while( atts[i] && atts[i+1] )
558 {
559 llinfos << tabs() << "attribute: " << atts[i] << "=" << atts[i+1] << llendl;
560 i += 2;
561 }
562 }
563
564 LLXmlTreeNode* child = CreateXmlTreeNode( std::string(name), mCurrent );
565
566 S32 i = 0;
567 while( atts[i] && atts[i+1] )
568 {
569 child->addAttribute( atts[i], atts[i+1] );
570 i += 2;
571 }
572
573 if( mCurrent )
574 {
575 mCurrent->addChild( child );
576
577 }
578 else
579 {
580 llassert( !mRoot );
581 mRoot = child;
582 }
583 mCurrent = child;
584}
585
586LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent)
587{
588 return new LLXmlTreeNode(name, parent, mTree);
589}
590
591
592void LLXmlTreeParser::endElement(const char* name)
593{
594 if( mDump )
595 {
596 llinfos << tabs() << "endElement " << name << llendl;
597 }
598
599 if( !mCurrent->mContents.empty() )
600 {
601 LLString::trim(mCurrent->mContents);
602 LLString::removeCRLF(mCurrent->mContents);
603 }
604
605 mCurrent = mCurrent->getParent();
606}
607
608void LLXmlTreeParser::characterData(const char *s, int len)
609{
610 LLString str(s, len);
611 if( mDump )
612 {
613 llinfos << tabs() << "CharacterData " << str << llendl;
614 }
615
616 if (mKeepContents)
617 {
618 mCurrent->appendContents( str );
619 }
620}
621
622void LLXmlTreeParser::processingInstruction(const char *target, const char *data)
623{
624 if( mDump )
625 {
626 llinfos << tabs() << "processingInstruction " << data << llendl;
627 }
628}
629
630void LLXmlTreeParser::comment(const char *data)
631{
632 if( mDump )
633 {
634 llinfos << tabs() << "comment " << data << llendl;
635 }
636}
637
638void LLXmlTreeParser::startCdataSection()
639{
640 if( mDump )
641 {
642 llinfos << tabs() << "startCdataSection" << llendl;
643 }
644}
645
646void LLXmlTreeParser::endCdataSection()
647{
648 if( mDump )
649 {
650 llinfos << tabs() << "endCdataSection" << llendl;
651 }
652}
653
654void LLXmlTreeParser::defaultData(const char *s, int len)
655{
656 if( mDump )
657 {
658 LLString str(s, len);
659 llinfos << tabs() << "defaultData " << str << llendl;
660 }
661}
662
663void LLXmlTreeParser::unparsedEntityDecl(
664 const char* entity_name,
665 const char* base,
666 const char* system_id,
667 const char* public_id,
668 const char* notation_name)
669{
670 if( mDump )
671 {
672 llinfos << tabs() << "unparsed entity:" << llendl;
673 llinfos << tabs() << " entityName " << entity_name << llendl;
674 llinfos << tabs() << " base " << base << llendl;
675 llinfos << tabs() << " systemId " << system_id << llendl;
676 llinfos << tabs() << " publicId " << public_id << llendl;
677 llinfos << tabs() << " notationName " << notation_name<< llendl;
678 }
679}
680
681void test_llxmltree()
682{
683 LLXmlTree tree;
684 BOOL success = tree.parseFile( "test.xml" );
685 if( success )
686 {
687 tree.dump();
688 }
689}
690