diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llxml/llxmltree.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 690 |
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 | ||
44 | LLStdStringTable LLXmlTree::sAttributeKeys(1024); | ||
45 | |||
46 | LLXmlTree::LLXmlTree() | ||
47 | : mRoot( NULL ), | ||
48 | mNodeNames(512) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | LLXmlTree::~LLXmlTree() | ||
53 | { | ||
54 | cleanup(); | ||
55 | } | ||
56 | |||
57 | void LLXmlTree::cleanup() | ||
58 | { | ||
59 | delete mRoot; | ||
60 | mRoot = NULL; | ||
61 | mNodeNames.cleanup(); | ||
62 | } | ||
63 | |||
64 | |||
65 | BOOL 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 | |||
81 | void LLXmlTree::dump() | ||
82 | { | ||
83 | if( mRoot ) | ||
84 | { | ||
85 | dumpNode( mRoot, " " ); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | void 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 | |||
103 | LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree ) | ||
104 | : mName(name), | ||
105 | mParent(parent), | ||
106 | mTree(tree) | ||
107 | { | ||
108 | } | ||
109 | |||
110 | LLXmlTreeNode::~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 | |||
120 | void 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 | |||
137 | BOOL 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 | |||
144 | void 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 | |||
151 | LLXmlTreeNode* LLXmlTreeNode::getFirstChild() | ||
152 | { | ||
153 | mChildListIter = mChildList.begin(); | ||
154 | return getNextChild(); | ||
155 | } | ||
156 | LLXmlTreeNode* LLXmlTreeNode::getNextChild() | ||
157 | { | ||
158 | if (mChildListIter == mChildList.end()) | ||
159 | return 0; | ||
160 | else | ||
161 | return *mChildListIter++; | ||
162 | } | ||
163 | |||
164 | LLXmlTreeNode* 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 | |||
172 | LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild() | ||
173 | { | ||
174 | if (mChildMapIter == mChildMapEndIter) | ||
175 | return NULL; | ||
176 | else | ||
177 | return (mChildMapIter++)->second; | ||
178 | } | ||
179 | |||
180 | void LLXmlTreeNode::appendContents(const std::string& str) | ||
181 | { | ||
182 | mContents.append( str ); | ||
183 | } | ||
184 | |||
185 | void 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 | |||
201 | BOOL LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, BOOL& value) | ||
202 | { | ||
203 | const LLString *s = getAttribute( canonical_name ); | ||
204 | return s && LLString::convertToBOOL( *s, value ); | ||
205 | } | ||
206 | |||
207 | BOOL LLXmlTreeNode::getFastAttributeU8(LLStdStringHandle canonical_name, U8& value) | ||
208 | { | ||
209 | const LLString *s = getAttribute( canonical_name ); | ||
210 | return s && LLString::convertToU8( *s, value ); | ||
211 | } | ||
212 | |||
213 | BOOL LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& value) | ||
214 | { | ||
215 | const LLString *s = getAttribute( canonical_name ); | ||
216 | return s && LLString::convertToS8( *s, value ); | ||
217 | } | ||
218 | |||
219 | BOOL LLXmlTreeNode::getFastAttributeS16(LLStdStringHandle canonical_name, S16& value) | ||
220 | { | ||
221 | const LLString *s = getAttribute( canonical_name ); | ||
222 | return s && LLString::convertToS16( *s, value ); | ||
223 | } | ||
224 | |||
225 | BOOL LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& value) | ||
226 | { | ||
227 | const LLString *s = getAttribute( canonical_name ); | ||
228 | return s && LLString::convertToU16( *s, value ); | ||
229 | } | ||
230 | |||
231 | BOOL LLXmlTreeNode::getFastAttributeU32(LLStdStringHandle canonical_name, U32& value) | ||
232 | { | ||
233 | const LLString *s = getAttribute( canonical_name ); | ||
234 | return s && LLString::convertToU32( *s, value ); | ||
235 | } | ||
236 | |||
237 | BOOL LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& value) | ||
238 | { | ||
239 | const LLString *s = getAttribute( canonical_name ); | ||
240 | return s && LLString::convertToS32( *s, value ); | ||
241 | } | ||
242 | |||
243 | BOOL LLXmlTreeNode::getFastAttributeF32(LLStdStringHandle canonical_name, F32& value) | ||
244 | { | ||
245 | const LLString *s = getAttribute( canonical_name ); | ||
246 | return s && LLString::convertToF32( *s, value ); | ||
247 | } | ||
248 | |||
249 | BOOL LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& value) | ||
250 | { | ||
251 | const LLString *s = getAttribute( canonical_name ); | ||
252 | return s && LLString::convertToF64( *s, value ); | ||
253 | } | ||
254 | |||
255 | BOOL 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 | |||
261 | BOOL 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 | |||
267 | BOOL 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 | |||
273 | BOOL 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 | |||
279 | BOOL 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 | |||
285 | BOOL 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 | |||
291 | BOOL 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 | |||
297 | BOOL 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 | |||
312 | BOOL 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 | |||
318 | BOOL 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 | |||
324 | BOOL 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 | |||
330 | BOOL 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 | |||
336 | BOOL 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 | |||
342 | BOOL 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 | |||
348 | BOOL 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 | |||
354 | BOOL 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 | |||
360 | BOOL 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 | |||
366 | BOOL 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 | |||
372 | BOOL 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 | |||
378 | BOOL 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 | |||
384 | BOOL 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 | |||
390 | BOOL 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 | |||
396 | BOOL 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 | |||
402 | BOOL 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 | |||
408 | BOOL 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> | ||
430 | The quick brown fox | ||
431 | Jumps over the lazy dog | ||
432 | </message> | ||
433 | |||
434 | */ | ||
435 | |||
436 | LLString 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 | |||
504 | LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree) | ||
505 | : mTree(tree), | ||
506 | mRoot( NULL ), | ||
507 | mCurrent( NULL ), | ||
508 | mDump( FALSE ) | ||
509 | { | ||
510 | } | ||
511 | |||
512 | LLXmlTreeParser::~LLXmlTreeParser() | ||
513 | { | ||
514 | } | ||
515 | |||
516 | BOOL 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 | |||
538 | const 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 | |||
550 | void 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 | |||
586 | LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent) | ||
587 | { | ||
588 | return new LLXmlTreeNode(name, parent, mTree); | ||
589 | } | ||
590 | |||
591 | |||
592 | void 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 | |||
608 | void 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 | |||
622 | void LLXmlTreeParser::processingInstruction(const char *target, const char *data) | ||
623 | { | ||
624 | if( mDump ) | ||
625 | { | ||
626 | llinfos << tabs() << "processingInstruction " << data << llendl; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | void LLXmlTreeParser::comment(const char *data) | ||
631 | { | ||
632 | if( mDump ) | ||
633 | { | ||
634 | llinfos << tabs() << "comment " << data << llendl; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | void LLXmlTreeParser::startCdataSection() | ||
639 | { | ||
640 | if( mDump ) | ||
641 | { | ||
642 | llinfos << tabs() << "startCdataSection" << llendl; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | void LLXmlTreeParser::endCdataSection() | ||
647 | { | ||
648 | if( mDump ) | ||
649 | { | ||
650 | llinfos << tabs() << "endCdataSection" << llendl; | ||
651 | } | ||
652 | } | ||
653 | |||
654 | void 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 | |||
663 | void 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 | |||
681 | void test_llxmltree() | ||
682 | { | ||
683 | LLXmlTree tree; | ||
684 | BOOL success = tree.parseFile( "test.xml" ); | ||
685 | if( success ) | ||
686 | { | ||
687 | tree.dump(); | ||
688 | } | ||
689 | } | ||
690 | |||