llxmltree.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:18k
源码类别:

游戏引擎

开发平台:

C++ Builder

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