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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llxmlnode.cpp
  3.  * @author Tom Yedwab
  4.  * @brief LLXMLNode implementation
  5.  *
  6.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2005-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "linden_common.h"
  34. #include <iostream>
  35. #include <map>
  36. #include "llxmlnode.h"
  37. #include "v3color.h"
  38. #include "v4color.h"
  39. #include "v4coloru.h"
  40. #include "v3math.h"
  41. #include "v3dmath.h"
  42. #include "v4math.h"
  43. #include "llquaternion.h"
  44. #include "llstring.h"
  45. #include "lluuid.h"
  46. #include "lldir.h"
  47. const S32 MAX_COLUMN_WIDTH = 80;
  48. // static
  49. BOOL LLXMLNode::sStripEscapedStrings = TRUE;
  50. BOOL LLXMLNode::sStripWhitespaceValues = FALSE;
  51. LLXMLNode::LLXMLNode() : 
  52. mID(""),
  53. mParser(NULL),
  54. mIsAttribute(FALSE),
  55. mVersionMajor(0), 
  56. mVersionMinor(0), 
  57. mLength(0), 
  58. mPrecision(64),
  59. mType(TYPE_CONTAINER),
  60. mEncoding(ENCODING_DEFAULT),
  61. mLineNumber(-1),
  62. mParent(NULL),
  63. mChildren(NULL),
  64. mAttributes(),
  65. mPrev(NULL),
  66. mNext(NULL),
  67. mName(NULL), 
  68. mValue(""), 
  69. mDefault(NULL)
  70. {
  71. }
  72. LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) : 
  73. mID(""),
  74. mParser(NULL),
  75. mIsAttribute(is_attribute),
  76. mVersionMajor(0), 
  77. mVersionMinor(0), 
  78. mLength(0), 
  79. mPrecision(64),
  80. mType(TYPE_CONTAINER), 
  81. mEncoding(ENCODING_DEFAULT),
  82. mLineNumber(-1),
  83. mParent(NULL),
  84. mChildren(NULL),
  85. mAttributes(),
  86. mPrev(NULL),
  87. mNext(NULL),
  88. mValue(""), 
  89. mDefault(NULL)
  90. {
  91.     mName = gStringTable.addStringEntry(name);
  92. }
  93. LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) : 
  94. mID(""),
  95. mParser(NULL),
  96. mIsAttribute(is_attribute),
  97. mVersionMajor(0), 
  98. mVersionMinor(0), 
  99. mLength(0), 
  100. mPrecision(64),
  101. mType(TYPE_CONTAINER), 
  102. mEncoding(ENCODING_DEFAULT),
  103. mLineNumber(-1),
  104. mParent(NULL),
  105. mChildren(NULL),
  106. mAttributes(),
  107. mPrev(NULL),
  108. mNext(NULL),
  109. mName(name),
  110. mValue(""), 
  111. mDefault(NULL)
  112. {
  113. }
  114. // copy constructor (except for the children)
  115. LLXMLNode::LLXMLNode(const LLXMLNode& rhs) : 
  116. mID(rhs.mID),
  117. mIsAttribute(rhs.mIsAttribute),
  118. mVersionMajor(rhs.mVersionMajor), 
  119. mVersionMinor(rhs.mVersionMinor), 
  120. mLength(rhs.mLength), 
  121. mPrecision(rhs.mPrecision),
  122. mType(rhs.mType),
  123. mEncoding(rhs.mEncoding),
  124. mLineNumber(0),
  125. mParser(NULL),
  126. mParent(NULL),
  127. mChildren(NULL),
  128. mAttributes(),
  129. mPrev(NULL),
  130. mNext(NULL),
  131. mName(rhs.mName), 
  132. mValue(rhs.mValue), 
  133. mDefault(rhs.mDefault)
  134. {
  135. }
  136. // returns a new copy of this node and all its children
  137. LLXMLNodePtr LLXMLNode::deepCopy()
  138. {
  139. LLXMLNodePtr newnode = LLXMLNodePtr(new LLXMLNode(*this));
  140. if (mChildren.notNull())
  141. {
  142. for (LLXMLChildList::iterator iter = mChildren->map.begin();
  143.  iter != mChildren->map.end(); ++iter)
  144. {
  145. newnode->addChild(iter->second->deepCopy());
  146. }
  147. }
  148. for (LLXMLAttribList::iterator iter = mAttributes.begin();
  149.  iter != mAttributes.end(); ++iter)
  150. {
  151. newnode->addChild(iter->second->deepCopy());
  152. }
  153. return newnode;
  154. }
  155. // virtual
  156. LLXMLNode::~LLXMLNode()
  157. {
  158. // Strictly speaking none of this should be required execept 'delete mChildren'...
  159. // Sadly, that's only true if we hadn't had reference-counted smart pointers linked
  160. // in three different directions. This entire class is a frightening, hard-to-maintain
  161. // mess.
  162. if (mChildren.notNull())
  163. {
  164. for (LLXMLChildList::iterator iter = mChildren->map.begin();
  165.  iter != mChildren->map.end(); ++iter)
  166. {
  167. LLXMLNodePtr child = iter->second;
  168. child->mParent = NULL;
  169. child->mNext = NULL;
  170. child->mPrev = NULL;
  171. }
  172. mChildren->map.clear();
  173. mChildren->head = NULL;
  174. mChildren->tail = NULL;
  175. mChildren = NULL;
  176. }
  177. for (LLXMLAttribList::iterator iter = mAttributes.begin();
  178.  iter != mAttributes.end(); ++iter)
  179. {
  180. LLXMLNodePtr attr = iter->second;
  181. attr->mParent = NULL;
  182. attr->mNext = NULL;
  183. attr->mPrev = NULL;
  184. }
  185. llassert(mParent == NULL);
  186. mDefault = NULL;
  187. }
  188. BOOL LLXMLNode::isNull()
  189. {
  190. return (mName == NULL);
  191. }
  192. // protected
  193. BOOL LLXMLNode::removeChild(LLXMLNode *target_child) 
  194. {
  195. if (!target_child)
  196. {
  197. return FALSE;
  198. }
  199. if (target_child->mIsAttribute)
  200. {
  201. LLXMLAttribList::iterator children_itr = mAttributes.find(target_child->mName);
  202. if (children_itr != mAttributes.end())
  203. {
  204. target_child->mParent = NULL;
  205. mAttributes.erase(children_itr);
  206. return TRUE;
  207. }
  208. }
  209. else if (mChildren.notNull())
  210. {
  211. LLXMLChildList::iterator children_itr = mChildren->map.find(target_child->mName);
  212. while (children_itr != mChildren->map.end())
  213. {
  214. if (target_child == children_itr->second)
  215. {
  216. if (target_child == mChildren->head)
  217. {
  218. mChildren->head = target_child->mNext;
  219. }
  220. if (target_child == mChildren->tail)
  221. {
  222. mChildren->tail = target_child->mPrev;
  223. }
  224. LLXMLNodePtr prev = target_child->mPrev;
  225. LLXMLNodePtr next = target_child->mNext;
  226. if (prev.notNull()) prev->mNext = next;
  227. if (next.notNull()) next->mPrev = prev;
  228. target_child->mPrev = NULL;
  229. target_child->mNext = NULL;
  230. target_child->mParent = NULL;
  231. mChildren->map.erase(children_itr);
  232. if (mChildren->map.empty())
  233. {
  234. mChildren = NULL;
  235. }
  236. return TRUE;
  237. }
  238. else if (children_itr->first != target_child->mName)
  239. {
  240. break;
  241. }
  242. else
  243. {
  244. ++children_itr;
  245. }
  246. }
  247. }
  248. return FALSE;
  249. }
  250. void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)
  251. {
  252. if (new_child->mParent != NULL)
  253. {
  254. if (new_child->mParent == this)
  255. {
  256. return;
  257. }
  258. new_child->mParent->removeChild(new_child);
  259. }
  260. new_child->mParent = this;
  261. if (new_child->mIsAttribute)
  262. {
  263. mAttributes.insert(std::make_pair(new_child->mName, new_child));
  264. }
  265. else
  266. {
  267. if (mChildren.isNull())
  268. {
  269. mChildren = new LLXMLChildren();
  270. mChildren->head = new_child;
  271. mChildren->tail = new_child;
  272. }
  273. mChildren->map.insert(std::make_pair(new_child->mName, new_child));
  274. // if after_child is specified, it damn well better be in the list of children
  275. // for this node. I'm not going to assert that, because it would be expensive,
  276. // but don't specify that parameter if you didn't get the value for it from the
  277. // list of children of this node!
  278. if (after_child.isNull())
  279. {
  280. if (mChildren->tail != new_child)
  281. {
  282. mChildren->tail->mNext = new_child;
  283. new_child->mPrev = mChildren->tail;
  284. mChildren->tail = new_child;
  285. }
  286. }
  287. // if after_child == parent, then put new_child at beginning
  288. else if (after_child == this)
  289. {
  290. // add to front of list
  291. new_child->mNext = mChildren->head;
  292. if (mChildren->head)
  293. {
  294. mChildren->head->mPrev = new_child;
  295. mChildren->head = new_child;
  296. }
  297. else // no children
  298. {
  299. mChildren->head = new_child;
  300. mChildren->tail = new_child;
  301. }
  302. }
  303. else
  304. {
  305. if (after_child->mNext.notNull())
  306. {
  307. // if after_child was not the last item, fix up some pointers
  308. after_child->mNext->mPrev = new_child;
  309. new_child->mNext = after_child->mNext;
  310. }
  311. new_child->mPrev = after_child;
  312. after_child->mNext = new_child;
  313. if (mChildren->tail == after_child)
  314. {
  315. mChildren->tail = new_child;
  316. }
  317. }
  318. }
  319. new_child->updateDefault();
  320. }
  321. // virtual 
  322. LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute)
  323. {
  324. return createChild(gStringTable.addStringEntry(name), is_attribute);
  325. }
  326. // virtual 
  327. LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute)
  328. {
  329. LLXMLNode* ret = new LLXMLNode(name, is_attribute);
  330. ret->mID.clear();
  331. addChild(ret);
  332. return ret;
  333. }
  334. BOOL LLXMLNode::deleteChild(LLXMLNode *child)
  335. {
  336. if (removeChild(child))
  337. {
  338. return TRUE;
  339. }
  340. return FALSE;
  341. }
  342. void LLXMLNode::setParent(LLXMLNodePtr new_parent)
  343. {
  344. if (new_parent.notNull())
  345. {
  346. new_parent->addChild(this);
  347. }
  348. else
  349. {
  350. if (mParent != NULL)
  351. {
  352.     LLXMLNodePtr old_parent = mParent;
  353. mParent = NULL;
  354. old_parent->removeChild(this);
  355. }
  356. }
  357. }
  358. void LLXMLNode::updateDefault()
  359. {
  360. if (mParent != NULL && !mParent->mDefault.isNull())
  361. {
  362. mDefault = NULL;
  363. // Find default value in parent's default tree
  364. if (!mParent->mDefault.isNull())
  365. {
  366. findDefault(mParent->mDefault);
  367. }
  368. }
  369. if (mChildren.notNull())
  370. {
  371. LLXMLChildList::const_iterator children_itr;
  372. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  373. for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr)
  374. {
  375. LLXMLNodePtr child = (*children_itr).second;
  376. child->updateDefault();
  377. }
  378. }
  379. }
  380. void XMLCALL StartXMLNode(void *userData,
  381.                           const XML_Char *name,
  382.                           const XML_Char **atts)
  383. {
  384. // Create a new node
  385. LLXMLNode *new_node_ptr = new LLXMLNode(name, FALSE);
  386. LLXMLNodePtr new_node = new_node_ptr;
  387. new_node->mID.clear();
  388. LLXMLNodePtr ptr_new_node = new_node;
  389. // Set the parent-child relationship with the current active node
  390. LLXMLNode* parent = (LLXMLNode *)userData;
  391. if (NULL == parent)
  392. {
  393. llwarns << "parent (userData) is NULL; aborting function" << llendl;
  394. return;
  395. }
  396. new_node_ptr->mParser = parent->mParser;
  397. new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
  398. // Set the current active node to the new node
  399. XML_Parser *parser = parent->mParser;
  400. XML_SetUserData(*parser, (void *)new_node_ptr);
  401. // Parse attributes
  402. U32 pos = 0;
  403. while (atts[pos] != NULL)
  404. {
  405. std::string attr_name = atts[pos];
  406. std::string attr_value = atts[pos+1];
  407. // Special cases
  408. if ('i' == attr_name[0] && "id" == attr_name)
  409. {
  410. new_node->mID = attr_value;
  411. }
  412. else if ('v' == attr_name[0] && "version" == attr_name)
  413. {
  414. U32 version_major = 0;
  415. U32 version_minor = 0;
  416. if (sscanf(attr_value.c_str(), "%d.%d", &version_major, &version_minor) > 0)
  417. {
  418. new_node->mVersionMajor = version_major;
  419. new_node->mVersionMinor = version_minor;
  420. }
  421. }
  422. else if (('s' == attr_name[0] && "size" == attr_name) || ('l' == attr_name[0] && "length" == attr_name))
  423. {
  424. U32 length;
  425. if (sscanf(attr_value.c_str(), "%d", &length) > 0)
  426. {
  427. new_node->mLength = length;
  428. }
  429. }
  430. else if ('p' == attr_name[0] && "precision" == attr_name)
  431. {
  432. U32 precision;
  433. if (sscanf(attr_value.c_str(), "%d", &precision) > 0)
  434. {
  435. new_node->mPrecision = precision;
  436. }
  437. }
  438. else if ('t' == attr_name[0] && "type" == attr_name)
  439. {
  440. if ("boolean" == attr_value)
  441. {
  442. new_node->mType = LLXMLNode::TYPE_BOOLEAN;
  443. }
  444. else if ("integer" == attr_value)
  445. {
  446. new_node->mType = LLXMLNode::TYPE_INTEGER;
  447. }
  448. else if ("float" == attr_value)
  449. {
  450. new_node->mType = LLXMLNode::TYPE_FLOAT;
  451. }
  452. else if ("string" == attr_value)
  453. {
  454. new_node->mType = LLXMLNode::TYPE_STRING;
  455. }
  456. else if ("uuid" == attr_value)
  457. {
  458. new_node->mType = LLXMLNode::TYPE_UUID;
  459. }
  460. else if ("noderef" == attr_value)
  461. {
  462. new_node->mType = LLXMLNode::TYPE_NODEREF;
  463. }
  464. }
  465. else if ('e' == attr_name[0] && "encoding" == attr_name)
  466. {
  467. if ("decimal" == attr_value)
  468. {
  469. new_node->mEncoding = LLXMLNode::ENCODING_DECIMAL;
  470. }
  471. else if ("hex" == attr_value)
  472. {
  473. new_node->mEncoding = LLXMLNode::ENCODING_HEX;
  474. }
  475. /*else if (attr_value == "base32")
  476. {
  477. new_node->mEncoding = LLXMLNode::ENCODING_BASE32;
  478. }*/
  479. }
  480. // only one attribute child per description
  481. LLXMLNodePtr attr_node;
  482. if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE))
  483. {
  484. attr_node = new LLXMLNode(attr_name.c_str(), TRUE);
  485. attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
  486. }
  487. attr_node->setValue(attr_value);
  488. new_node->addChild(attr_node);
  489. pos += 2;
  490. }
  491. if (parent)
  492. {
  493. parent->addChild(new_node);
  494. }
  495. }
  496. void XMLCALL EndXMLNode(void *userData,
  497.                         const XML_Char *name)
  498. {
  499. // [FUGLY] Set the current active node to the current node's parent
  500. LLXMLNode *node = (LLXMLNode *)userData;
  501. XML_Parser *parser = node->mParser;
  502. XML_SetUserData(*parser, (void *)node->mParent);
  503. // SJB: total hack:
  504. if (LLXMLNode::sStripWhitespaceValues)
  505. {
  506. std::string value = node->getValue();
  507. BOOL is_empty = TRUE;
  508. for (std::string::size_type s = 0; s < value.length(); s++)
  509. {
  510. char c = value[s];
  511. if (c != ' ' && c != 't' && c != 'n')
  512. {
  513. is_empty = FALSE;
  514. break;
  515. }
  516. }
  517. if (is_empty)
  518. {
  519. value.clear();
  520. node->setValue(value);
  521. }
  522. }
  523. }
  524. void XMLCALL XMLData(void *userData,
  525.                      const XML_Char *s,
  526.                      int len)
  527. {
  528. LLXMLNode* current_node = (LLXMLNode *)userData;
  529. std::string value = current_node->getValue();
  530. if (LLXMLNode::sStripEscapedStrings)
  531. {
  532. if (s[0] == '"' && s[len-1] == '"')
  533. {
  534. // Special-case: Escaped string.
  535. std::string unescaped_string;
  536. for (S32 pos=1; pos<len-1; ++pos)
  537. {
  538. if (s[pos] == '\' && s[pos+1] == '\')
  539. {
  540. unescaped_string.append("\");
  541. ++pos;
  542. }
  543. else if (s[pos] == '\' && s[pos+1] == '"')
  544. {
  545. unescaped_string.append(""");
  546. ++pos;
  547. }
  548. else
  549. {
  550. unescaped_string.append(&s[pos], 1);
  551. }
  552. }
  553. value.append(unescaped_string);
  554. current_node->setValue(value);
  555. return;
  556. }
  557. }
  558. value.append(std::string(s, len));
  559. current_node->setValue(value);
  560. }
  561. // static 
  562. bool LLXMLNode::updateNode(
  563. LLXMLNodePtr& node,
  564. LLXMLNodePtr& update_node)
  565. {
  566. if (!node || !update_node)
  567. {
  568. llwarns << "Node invalid" << llendl;
  569. return FALSE;
  570. }
  571. //update the node value
  572. node->mValue = update_node->mValue;
  573. //update all attribute values
  574. LLXMLAttribList::const_iterator itor;
  575. for(itor = update_node->mAttributes.begin(); itor != update_node->mAttributes.end(); ++itor)
  576. {
  577. const LLStringTableEntry* attribNameEntry = (*itor).first;
  578. LLXMLNodePtr updateAttribNode = (*itor).second;
  579. LLXMLNodePtr attribNode;
  580. node->getAttribute(attribNameEntry, attribNode, 0);
  581. if (attribNode)
  582. {
  583. attribNode->mValue = updateAttribNode->mValue;
  584. }
  585. }
  586. //update all of node's children with updateNodes children that match name
  587. LLXMLNodePtr child;
  588. LLXMLNodePtr updateChild;
  589. for (updateChild = update_node->getFirstChild(); updateChild.notNull(); 
  590.  updateChild = updateChild->getNextSibling())
  591. {
  592. for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
  593. {
  594. std::string nodeName;
  595. std::string updateName;
  596. updateChild->getAttributeString("name", updateName);
  597. child->getAttributeString("name", nodeName);
  598. //if it's a combobox there's no name, but there is a value
  599. if (updateName.empty())
  600. {
  601. updateChild->getAttributeString("value", updateName);
  602. child->getAttributeString("value", nodeName);
  603. }
  604. if ((nodeName != "") && (updateName == nodeName))
  605. {
  606. updateNode(child, updateChild);
  607. break;
  608. }
  609. }
  610. }
  611. return TRUE;
  612. }
  613. // static 
  614. LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node)
  615. {
  616. if (!node || !update_node)
  617. {
  618. llwarns << "Node invalid" << llendl;
  619. return node;
  620. }
  621. LLXMLNodePtr cloned_node = update_node->deepCopy();
  622. node->mParent->addChild(cloned_node, node); // add after node
  623. LLXMLNodePtr parent = node->mParent;
  624. parent->removeChild(node);
  625. parent->updateDefault();
  626. return cloned_node;
  627. }
  628. // static
  629. bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree)
  630. {
  631. // Read file
  632. LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL;
  633. LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
  634. if (fp == NULL)
  635. {
  636. node = new LLXMLNode();
  637. return false;
  638. }
  639. fseek(fp, 0, SEEK_END);
  640. U32 length = ftell(fp);
  641. fseek(fp, 0, SEEK_SET);
  642. U8* buffer = new U8[length+1];
  643. size_t nread = fread(buffer, 1, length, fp);
  644. buffer[nread] = 0;
  645. fclose(fp);
  646. bool rv = parseBuffer(buffer, nread, node, defaults_tree);
  647. delete [] buffer;
  648. return rv;
  649. }
  650. // static
  651. bool LLXMLNode::parseBuffer(
  652. U8* buffer,
  653. U32 length,
  654. LLXMLNodePtr& node, 
  655. LLXMLNode* defaults)
  656. {
  657. // Init
  658. XML_Parser my_parser = XML_ParserCreate(NULL);
  659. XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode);
  660. XML_SetCharacterDataHandler(my_parser, XMLData);
  661. // Create a root node
  662. LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE);
  663. LLXMLNodePtr file_node = file_node_ptr;
  664. file_node->mParser = &my_parser;
  665. XML_SetUserData(my_parser, (void *)file_node_ptr);
  666. // Do the parsing
  667. if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK)
  668. {
  669. llwarns << "Error parsing xml error code: "
  670. << XML_ErrorString(XML_GetErrorCode(my_parser))
  671. << " on line " << XML_GetCurrentLineNumber(my_parser)
  672. << llendl;
  673. }
  674. // Deinit
  675. XML_ParserFree(my_parser);
  676. if (!file_node->mChildren || file_node->mChildren->map.size() != 1)
  677. {
  678. llwarns << "Parse failure - wrong number of top-level nodes xml."
  679. << llendl;
  680. node = new LLXMLNode();
  681. return false;
  682. }
  683. LLXMLNode *return_node = file_node->mChildren->map.begin()->second;
  684. return_node->setDefault(defaults);
  685. return_node->updateDefault();
  686. node = return_node;
  687. return true;
  688. }
  689. // static
  690. bool LLXMLNode::parseStream(
  691. std::istream& str,
  692. LLXMLNodePtr& node, 
  693. LLXMLNode* defaults)
  694. {
  695. // Init
  696. XML_Parser my_parser = XML_ParserCreate(NULL);
  697. XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode);
  698. XML_SetCharacterDataHandler(my_parser, XMLData);
  699. // Create a root node
  700. LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE);
  701. LLXMLNodePtr file_node = file_node_ptr;
  702. file_node->mParser = &my_parser;
  703. XML_SetUserData(my_parser, (void *)file_node_ptr);
  704. const int BUFSIZE = 1024; 
  705. U8* buffer = new U8[BUFSIZE];
  706. while(str.good())
  707. {
  708. str.read((char*)buffer, BUFSIZE);
  709. int count = str.gcount();
  710. if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK)
  711. {
  712. llwarns << "Error parsing xml error code: "
  713. << XML_ErrorString(XML_GetErrorCode(my_parser))
  714. << " on lne " << XML_GetCurrentLineNumber(my_parser)
  715. << llendl;
  716. break;
  717. }
  718. }
  719. delete [] buffer;
  720. // Deinit
  721. XML_ParserFree(my_parser);
  722. if (!file_node->mChildren || file_node->mChildren->map.size() != 1)
  723. {
  724. llwarns << "Parse failure - wrong number of top-level nodes xml."
  725. << llendl;
  726. node = new LLXMLNode();
  727. return false;
  728. }
  729. LLXMLNode *return_node = file_node->mChildren->map.begin()->second;
  730. return_node->setDefault(defaults);
  731. return_node->updateDefault();
  732. node = return_node;
  733. return true;
  734. }
  735. BOOL LLXMLNode::isFullyDefault()
  736. {
  737. if (mDefault.isNull())
  738. {
  739. return FALSE;
  740. }
  741. BOOL has_default_value = (mValue == mDefault->mValue);
  742. BOOL has_default_attribute = (mIsAttribute == mDefault->mIsAttribute);
  743. BOOL has_default_type = mIsAttribute || (mType == mDefault->mType);
  744. BOOL has_default_encoding = mIsAttribute || (mEncoding == mDefault->mEncoding);
  745. BOOL has_default_precision = mIsAttribute || (mPrecision == mDefault->mPrecision);
  746. BOOL has_default_length = mIsAttribute || (mLength == mDefault->mLength);
  747. if (has_default_value 
  748. && has_default_type 
  749. && has_default_encoding 
  750. && has_default_precision
  751. && has_default_length
  752. && has_default_attribute)
  753. {
  754. if (mChildren.notNull())
  755. {
  756. LLXMLChildList::const_iterator children_itr;
  757. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  758. for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr)
  759. {
  760. LLXMLNodePtr child = (*children_itr).second;
  761. if (!child->isFullyDefault())
  762. {
  763. return FALSE;
  764. }
  765. }
  766. }
  767. return TRUE;
  768. }
  769. return FALSE;
  770. }
  771. // static
  772. bool LLXMLNode::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
  773.   const std::vector<std::string>& paths)
  774. {
  775. std::string full_filename = gDirUtilp->findSkinnedFilename(paths.front(), xui_filename);
  776. if (full_filename.empty())
  777. {
  778. return false;
  779. }
  780. if (!LLXMLNode::parseFile(full_filename, root, NULL))
  781. {
  782. // try filename as passed in since sometimes we load an xml file from a user-supplied path
  783. if (!LLXMLNode::parseFile(xui_filename, root, NULL))
  784. {
  785. llwarns << "Problem reading UI description file: " << xui_filename << llendl;
  786. return false;
  787. }
  788. }
  789. LLXMLNodePtr updateRoot;
  790. std::vector<std::string>::const_iterator itor;
  791. for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
  792. {
  793. std::string nodeName;
  794. std::string updateName;
  795. std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename);
  796. if(layer_filename.empty())
  797. {
  798. // no localized version of this file, that's ok, keep looking
  799. continue;
  800. }
  801. if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
  802. {
  803. llwarns << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
  804. return false;
  805. }
  806. updateRoot->getAttributeString("name", updateName);
  807. root->getAttributeString("name", nodeName);
  808. if (updateName == nodeName)
  809. {
  810. LLXMLNode::updateNode(root, updateRoot);
  811. }
  812. }
  813. return true;
  814. }
  815. // static
  816. void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
  817. {
  818. fprintf(out_file, "<?xml version="1.0" encoding="utf-8" standalone="yes" ?>n");
  819. }
  820. void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations)
  821. {
  822. if (isFullyDefault())
  823. {
  824. // Don't write out nodes that are an exact match to defaults
  825. return;
  826. }
  827. std::ostringstream ostream;
  828. writeToOstream(ostream, indent, use_type_decorations);
  829. std::string outstring = ostream.str();
  830. size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);
  831. if (written != outstring.length())
  832. {
  833. llwarns << "Short write" << llendl;
  834. }
  835. }
  836. void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations)
  837. {
  838. if (isFullyDefault())
  839. {
  840. // Don't write out nodes that are an exact match to defaults
  841. return;
  842. }
  843. BOOL has_default_type = mDefault.isNull()?FALSE:(mType == mDefault->mType);
  844. BOOL has_default_encoding = mDefault.isNull()?FALSE:(mEncoding == mDefault->mEncoding);
  845. BOOL has_default_precision = mDefault.isNull()?FALSE:(mPrecision == mDefault->mPrecision);
  846. BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength);
  847. // stream the name
  848. output_stream << indent << "<" << mName->mString << "n";
  849. if (use_type_decorations)
  850. {
  851. // ID
  852. if (mID != "")
  853. {
  854. output_stream << indent << " id="" << mID << ""n";
  855. }
  856. // Type
  857. if (!has_default_type)
  858. {
  859. switch (mType)
  860. {
  861. case TYPE_BOOLEAN:
  862. output_stream << indent << " type="boolean"n";
  863. break;
  864. case TYPE_INTEGER:
  865. output_stream << indent << " type="integer"n";
  866. break;
  867. case TYPE_FLOAT:
  868. output_stream << indent << " type="float"n";
  869. break;
  870. case TYPE_STRING:
  871. output_stream << indent << " type="string"n";
  872. break;
  873. case TYPE_UUID:
  874. output_stream << indent << " type="uuid"n";
  875. break;
  876. case TYPE_NODEREF:
  877. output_stream << indent << " type="noderef"n";
  878. break;
  879. default:
  880. // default on switch(enum) eliminates a warning on linux
  881. break;
  882. };
  883. }
  884. // Encoding
  885. if (!has_default_encoding)
  886. {
  887. switch (mEncoding)
  888. {
  889. case ENCODING_DECIMAL:
  890. output_stream << indent << " encoding="decimal"n";
  891. break;
  892. case ENCODING_HEX:
  893. output_stream << indent << " encoding="hex"n";
  894. break;
  895. /*case ENCODING_BASE32:
  896. output_stream << indent << " encoding="base32"n";
  897. break;*/
  898. default:
  899. // default on switch(enum) eliminates a warning on linux
  900. break;
  901. };
  902. }
  903. // Precision
  904. if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
  905. {
  906. output_stream << indent << " precision="" << mPrecision << ""n";
  907. }
  908. // Version
  909. if (mVersionMajor > 0 || mVersionMinor > 0)
  910. {
  911. output_stream << indent << " version="" << mVersionMajor << "." << mVersionMinor << ""n";
  912. }
  913. // Array length
  914. if (!has_default_length && mLength > 0)
  915. {
  916. output_stream << indent << " length="" << mLength << ""n";
  917. }
  918. }
  919. {
  920. // Write out attributes
  921. LLXMLAttribList::const_iterator attr_itr;
  922. LLXMLAttribList::const_iterator attr_end = mAttributes.end();
  923. for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr)
  924. {
  925. LLXMLNodePtr child = (*attr_itr).second;
  926. if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue)
  927. {
  928. std::string attr = child->mName->mString;
  929. if (use_type_decorations
  930. && (attr == "id" ||
  931. attr == "type" ||
  932. attr == "encoding" ||
  933. attr == "precision" ||
  934. attr == "version" ||
  935. attr == "length"))
  936. {
  937. continue; // skip built-in attributes
  938. }
  939. std::string attr_str = llformat(" %s="%s"",
  940.  attr.c_str(),
  941.  escapeXML(child->mValue).c_str());
  942. output_stream << indent << attr_str << "n";
  943. }
  944. }
  945. }
  946. // erase last n before attaching final > or />
  947. output_stream.seekp(-1, std::ios::cur);
  948. if (mChildren.isNull() && mValue == "")
  949. {
  950. output_stream << " />n";
  951. return;
  952. }
  953. else
  954. {
  955. output_stream << ">n";
  956. if (mChildren.notNull())
  957. {
  958. // stream non-attributes
  959. std::string next_indent = indent + "    ";
  960. for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())
  961. {
  962. child->writeToOstream(output_stream, next_indent, use_type_decorations);
  963. }
  964. }
  965. if (!mValue.empty())
  966. {
  967. std::string contents = getTextContents();
  968. output_stream << indent << "    " << escapeXML(contents) << "n";
  969. }
  970. output_stream << indent << "</" << mName->mString << ">n";
  971. }
  972. }
  973. void LLXMLNode::findName(const std::string& name, LLXMLNodeList &results)
  974. {
  975.     LLStringTableEntry* name_entry = gStringTable.checkStringEntry(name);
  976. if (name_entry == mName)
  977. {
  978. results.insert(std::make_pair(this->mName->mString, this));
  979. return;
  980. }
  981. if (mChildren.notNull())
  982. {
  983. LLXMLChildList::const_iterator children_itr;
  984. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  985. for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr)
  986. {
  987. LLXMLNodePtr child = (*children_itr).second;
  988. child->findName(name_entry, results);
  989. }
  990. }
  991. }
  992. void LLXMLNode::findName(LLStringTableEntry* name, LLXMLNodeList &results)
  993. {
  994. if (name == mName)
  995. {
  996. results.insert(std::make_pair(this->mName->mString, this));
  997. return;
  998. }
  999. if (mChildren.notNull())
  1000. {
  1001. LLXMLChildList::const_iterator children_itr;
  1002. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  1003. for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr)
  1004. {
  1005. LLXMLNodePtr child = (*children_itr).second;
  1006. child->findName(name, results);
  1007. }
  1008. }
  1009. }
  1010. void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results)
  1011. {
  1012. if (id == mID)
  1013. {
  1014. results.insert(std::make_pair(this->mName->mString, this));
  1015. return;
  1016. }
  1017. if (mChildren.notNull())
  1018. {
  1019. LLXMLChildList::const_iterator children_itr;
  1020. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  1021. for (children_itr = mChildren->map.begin(); children_itr != children_end; ++children_itr)
  1022. {
  1023. LLXMLNodePtr child = (*children_itr).second;
  1024. child->findID(id, results);
  1025. }
  1026. }
  1027. }
  1028. void LLXMLNode::scrubToTree(LLXMLNode *tree)
  1029. {
  1030. if (!tree || tree->mChildren.isNull())
  1031. {
  1032. return;
  1033. }
  1034. if (mChildren.notNull())
  1035. {
  1036. std::vector<LLXMLNodePtr> to_delete_list;
  1037. LLXMLChildList::iterator itor = mChildren->map.begin();
  1038. while (itor != mChildren->map.end())
  1039. {
  1040. LLXMLNodePtr child = itor->second;
  1041. LLXMLNodePtr child_tree = NULL;
  1042. // Look for this child in the default's children
  1043. bool found = false;
  1044. LLXMLChildList::iterator itor2 = tree->mChildren->map.begin();
  1045. while (itor2 != tree->mChildren->map.end())
  1046. {
  1047. if (child->mName == itor2->second->mName)
  1048. {
  1049. child_tree = itor2->second;
  1050. found = true;
  1051. }
  1052. ++itor2;
  1053. }
  1054. if (!found)
  1055. {
  1056. to_delete_list.push_back(child);
  1057. }
  1058. else
  1059. {
  1060. child->scrubToTree(child_tree);
  1061. }
  1062. ++itor;
  1063. }
  1064. std::vector<LLXMLNodePtr>::iterator itor3;
  1065. for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3)
  1066. {
  1067. (*itor3)->setParent(NULL);
  1068. }
  1069. }
  1070. }
  1071. bool LLXMLNode::getChild(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
  1072. {
  1073.     return getChild(gStringTable.checkStringEntry(name), node, use_default_if_missing);
  1074. }
  1075. bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
  1076. {
  1077. if (mChildren.notNull())
  1078. {
  1079. LLXMLChildList::const_iterator child_itr = mChildren->map.find(name);
  1080. if (child_itr != mChildren->map.end())
  1081. {
  1082. node = (*child_itr).second;
  1083. return true;
  1084. }
  1085. }
  1086. if (use_default_if_missing && !mDefault.isNull())
  1087. {
  1088. return mDefault->getChild(name, node, FALSE);
  1089. }
  1090. node = new LLXMLNode();
  1091. return false;
  1092. }
  1093. void LLXMLNode::getChildren(const char* name, LLXMLNodeList &children, BOOL use_default_if_missing) const
  1094. {
  1095.     getChildren(gStringTable.checkStringEntry(name), children, use_default_if_missing);
  1096. }
  1097. void LLXMLNode::getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, BOOL use_default_if_missing) const
  1098. {
  1099. if (mChildren.notNull())
  1100. {
  1101. LLXMLChildList::const_iterator child_itr = mChildren->map.find(name);
  1102. if (child_itr != mChildren->map.end())
  1103. {
  1104. LLXMLChildList::const_iterator children_end = mChildren->map.end();
  1105. while (child_itr != children_end)
  1106. {
  1107. LLXMLNodePtr child = (*child_itr).second;
  1108. if (name != child->mName)
  1109. {
  1110. break;
  1111. }
  1112. children.insert(std::make_pair(child->mName->mString, child));
  1113. child_itr++;
  1114. }
  1115. }
  1116. }
  1117. if (children.size() == 0 && use_default_if_missing && !mDefault.isNull())
  1118. {
  1119. mDefault->getChildren(name, children, FALSE);
  1120. }
  1121. }
  1122. // recursively walks the tree and returns all children at all nesting levels matching the name
  1123. void LLXMLNode::getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const
  1124. {
  1125. if (mChildren.notNull())
  1126. {
  1127. for (LLXMLChildList::const_iterator child_itr = mChildren->map.begin();
  1128.  child_itr != mChildren->map.end(); ++child_itr)
  1129. {
  1130. LLXMLNodePtr child = (*child_itr).second;
  1131. if (name == child->mName)
  1132. {
  1133. children.insert(std::make_pair(child->mName->mString, child));
  1134. }
  1135. // and check each child as well
  1136. child->getDescendants(name, children);
  1137. }
  1138. }
  1139. }
  1140. bool LLXMLNode::getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
  1141. {
  1142.     return getAttribute(gStringTable.checkStringEntry(name), node, use_default_if_missing);
  1143. }
  1144. bool LLXMLNode::getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
  1145. {
  1146. LLXMLAttribList::const_iterator child_itr = mAttributes.find(name);
  1147. if (child_itr != mAttributes.end())
  1148. {
  1149. node = (*child_itr).second;
  1150. return true;
  1151. }
  1152. if (use_default_if_missing && !mDefault.isNull())
  1153. {
  1154. return mDefault->getAttribute(name, node, FALSE);
  1155. }
  1156. node = new LLXMLNode();
  1157. return false;
  1158. }
  1159. bool LLXMLNode::setAttributeString(const char* attr, const std::string& value)
  1160. {
  1161. LLStringTableEntry* name = gStringTable.checkStringEntry(attr);
  1162. LLXMLAttribList::const_iterator child_itr = mAttributes.find(name);
  1163. if (child_itr != mAttributes.end())
  1164. {
  1165. LLXMLNodePtr node = (*child_itr).second;
  1166. node->setValue(value);
  1167. return true;
  1168. }
  1169. return false;
  1170. }
  1171. BOOL LLXMLNode::hasAttribute(const char* name )
  1172. {
  1173. LLXMLNodePtr node;
  1174. return getAttribute(name, node);
  1175. }
  1176. // the structure of these getAttribute_ functions is ugly, but it's because the
  1177. // underlying system is based on BOOL and LLString; if we change
  1178. // so that they're based on more generic mechanisms, these will be
  1179. // simplified.
  1180. bool LLXMLNode::getAttribute_bool(const char* name, bool& value )
  1181. {
  1182. LLXMLNodePtr node;
  1183.     if (!getAttribute(name, node))
  1184.     {
  1185.         return false;
  1186.     }
  1187.     BOOL temp;
  1188. bool retval = node->getBoolValue(1, &temp);
  1189.     value = temp;
  1190.     return retval;
  1191. }
  1192. BOOL LLXMLNode::getAttributeBOOL(const char* name, BOOL& value )
  1193. {
  1194. LLXMLNodePtr node;
  1195. return (getAttribute(name, node) && node->getBoolValue(1, &value));
  1196. }
  1197. BOOL LLXMLNode::getAttributeU8(const char* name, U8& value )
  1198. {
  1199. LLXMLNodePtr node;
  1200. return (getAttribute(name, node) && node->getByteValue(1, &value));
  1201. }
  1202. BOOL LLXMLNode::getAttributeS8(const char* name, S8& value )
  1203. {
  1204. LLXMLNodePtr node;
  1205. S32 val;
  1206. if (!(getAttribute(name, node) && node->getIntValue(1, &val)))
  1207. {
  1208. return false;
  1209. }
  1210. value = val;
  1211. return true;
  1212. }
  1213. BOOL LLXMLNode::getAttributeU16(const char* name, U16& value )
  1214. {
  1215. LLXMLNodePtr node;
  1216. U32 val;
  1217. if (!(getAttribute(name, node) && node->getUnsignedValue(1, &val)))
  1218. {
  1219. return false;
  1220. }
  1221. value = val;
  1222. return true;
  1223. }
  1224. BOOL LLXMLNode::getAttributeS16(const char* name, S16& value )
  1225. {
  1226. LLXMLNodePtr node;
  1227. S32 val;
  1228. if (!(getAttribute(name, node) && node->getIntValue(1, &val)))
  1229. {
  1230. return false;
  1231. }
  1232. value = val;
  1233. return true;
  1234. }
  1235. BOOL LLXMLNode::getAttributeU32(const char* name, U32& value )
  1236. {
  1237. LLXMLNodePtr node;
  1238. return (getAttribute(name, node) && node->getUnsignedValue(1, &value));
  1239. }
  1240. BOOL LLXMLNode::getAttributeS32(const char* name, S32& value )
  1241. {
  1242. LLXMLNodePtr node;
  1243. return (getAttribute(name, node) && node->getIntValue(1, &value));
  1244. }
  1245. BOOL LLXMLNode::getAttributeF32(const char* name, F32& value )
  1246. {
  1247. LLXMLNodePtr node;
  1248. return (getAttribute(name, node) && node->getFloatValue(1, &value));
  1249. }
  1250. BOOL LLXMLNode::getAttributeF64(const char* name, F64& value )
  1251. {
  1252. LLXMLNodePtr node;
  1253. return (getAttribute(name, node) && node->getDoubleValue(1, &value));
  1254. }
  1255. BOOL LLXMLNode::getAttributeColor(const char* name, LLColor4& value )
  1256. {
  1257. LLXMLNodePtr node;
  1258. return (getAttribute(name, node) && node->getFloatValue(4, value.mV));
  1259. }
  1260. BOOL LLXMLNode::getAttributeColor4(const char* name, LLColor4& value )
  1261. {
  1262. LLXMLNodePtr node;
  1263. return (getAttribute(name, node) && node->getFloatValue(4, value.mV));
  1264. }
  1265. BOOL LLXMLNode::getAttributeColor4U(const char* name, LLColor4U& value )
  1266. {
  1267. LLXMLNodePtr node;
  1268. return (getAttribute(name, node) && node->getByteValue(4, value.mV));
  1269. }
  1270. BOOL LLXMLNode::getAttributeVector3(const char* name, LLVector3& value )
  1271. {
  1272. LLXMLNodePtr node;
  1273. return (getAttribute(name, node) && node->getFloatValue(3, value.mV));
  1274. }
  1275. BOOL LLXMLNode::getAttributeVector3d(const char* name, LLVector3d& value )
  1276. {
  1277. LLXMLNodePtr node;
  1278. return (getAttribute(name, node) && node->getDoubleValue(3, value.mdV));
  1279. }
  1280. BOOL LLXMLNode::getAttributeQuat(const char* name, LLQuaternion& value )
  1281. {
  1282. LLXMLNodePtr node;
  1283. return (getAttribute(name, node) && node->getFloatValue(4, value.mQ));
  1284. }
  1285. BOOL LLXMLNode::getAttributeUUID(const char* name, LLUUID& value )
  1286. {
  1287. LLXMLNodePtr node;
  1288. return (getAttribute(name, node) && node->getUUIDValue(1, &value));
  1289. }
  1290. BOOL LLXMLNode::getAttributeString(const char* name, std::string& value )
  1291. {
  1292. LLXMLNodePtr node;
  1293. if (!getAttribute(name, node))
  1294. {
  1295. return false;
  1296. }
  1297. value = node->getValue();
  1298. return true;
  1299. }
  1300. LLXMLNodePtr LLXMLNode::getRoot()
  1301. {
  1302. if (mParent == NULL)
  1303. {
  1304. return this;
  1305. }
  1306. return mParent->getRoot();
  1307. }
  1308. /*static */
  1309. const char *LLXMLNode::skipWhitespace(const char *str)
  1310. {
  1311. // skip whitespace characters
  1312. while (str[0] == ' ' || str[0] == 't' || str[0] == 'n') ++str;
  1313. return str;
  1314. }
  1315. /*static */
  1316. const char *LLXMLNode::skipNonWhitespace(const char *str)
  1317. {
  1318. // skip non-whitespace characters
  1319. while (str[0] != ' ' && str[0] != 't' && str[0] != 'n' && str[0] != 0) ++str;
  1320. return str;
  1321. }
  1322. /*static */
  1323. const char *LLXMLNode::parseInteger(const char *str, U64 *dest, BOOL *is_negative, U32 precision, Encoding encoding)
  1324. {
  1325. *dest = 0;
  1326. *is_negative = FALSE;
  1327. str = skipWhitespace(str);
  1328. if (str[0] == 0) return NULL;
  1329. if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT)
  1330. {
  1331. if (str[0] == '+')
  1332. {
  1333. ++str;
  1334. }
  1335. if (str[0] == '-')
  1336. {
  1337. *is_negative = TRUE;
  1338. ++str;
  1339. }
  1340. str = skipWhitespace(str);
  1341. U64 ret = 0;
  1342. while (str[0] >= '0' && str[0] <= '9')
  1343. {
  1344. ret *= 10;
  1345. ret += str[0] - '0';
  1346. ++str;
  1347. }
  1348. if (str[0] == '.')
  1349. {
  1350. // If there is a fractional part, skip it
  1351. str = skipNonWhitespace(str);
  1352. }
  1353. *dest = ret;
  1354. return str;
  1355. }
  1356. if (encoding == ENCODING_HEX)
  1357. {
  1358. U64 ret = 0;
  1359. str = skipWhitespace(str);
  1360. for (U32 pos=0; pos<(precision/4); ++pos)
  1361. {
  1362. ret <<= 4;
  1363. str = skipWhitespace(str);
  1364. if (str[0] >= '0' && str[0] <= '9')
  1365. {
  1366. ret += str[0] - '0';
  1367. else if (str[0] >= 'a' && str[0] <= 'f')
  1368. {
  1369. ret += str[0] - 'a' + 10;
  1370. }
  1371. else if (str[0] >= 'A' && str[0] <= 'F')
  1372. {
  1373. ret += str[0] - 'A' + 10;
  1374. }
  1375. else
  1376. {
  1377. return NULL;
  1378. }
  1379. ++str;
  1380. }
  1381. *dest = ret;
  1382. return str;
  1383. }
  1384. return NULL;
  1385. }
  1386. // 25 elements - decimal expansions of 1/(2^n), multiplied by 10 each iteration
  1387. const U64 float_coeff_table[] = 
  1388. { 5, 25, 125, 625, 3125, 
  1389.   15625, 78125, 390625, 1953125, 9765625,
  1390.   48828125, 244140625, 1220703125, 6103515625LL, 30517578125LL,
  1391.   152587890625LL, 762939453125LL, 3814697265625LL, 19073486328125LL, 95367431640625LL,
  1392.   476837158203125LL, 2384185791015625LL, 11920928955078125LL, 59604644775390625LL, 298023223876953125LL };
  1393. // 36 elements - decimal expansions of 1/(2^n) after the last 28, truncated, no multiply each iteration
  1394. const U64 float_coeff_table_2[] =
  1395. {  149011611938476562LL,74505805969238281LL,
  1396.    37252902984619140LL, 18626451492309570LL, 9313225746154785LL, 4656612873077392LL,
  1397.    2328306436538696LL,  1164153218269348LL,  582076609134674LL,  291038304567337LL,
  1398.    145519152283668LL,   72759576141834LL,    36379788070917LL,   18189894035458LL,
  1399.    9094947017729LL,     4547473508864LL,     2273736754432LL,    1136868377216LL,
  1400.    568434188608LL,      284217094304LL,      142108547152LL,     71054273576LL,
  1401.    35527136788LL,       17763568394LL,       8881784197LL,       4440892098LL,
  1402.    2220446049LL,        1110223024LL,        555111512LL,        277555756LL,
  1403.    138777878,         69388939,          34694469,         17347234,
  1404.    8673617,           4336808,           2168404,          1084202,
  1405.    542101,            271050,            135525,           67762,
  1406. };
  1407. /*static */
  1408. const char *LLXMLNode::parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding)
  1409. {
  1410. str = skipWhitespace(str);
  1411. if (str[0] == 0) return NULL;
  1412. if (encoding == ENCODING_DECIMAL || encoding == ENCODING_DEFAULT)
  1413. {
  1414. str = skipWhitespace(str);
  1415. if (memcmp(str, "inf", 3) == 0)
  1416. {
  1417. *(U64 *)dest = 0x7FF0000000000000ll;
  1418. return str + 3;
  1419. }
  1420. if (memcmp(str, "-inf", 4) == 0)
  1421. {
  1422. *(U64 *)dest = 0xFFF0000000000000ll;
  1423. return str + 4;
  1424. }
  1425. if (memcmp(str, "1.#INF", 6) == 0)
  1426. {
  1427. *(U64 *)dest = 0x7FF0000000000000ll;
  1428. return str + 6;
  1429. }
  1430. if (memcmp(str, "-1.#INF", 7) == 0)
  1431. {
  1432. *(U64 *)dest = 0xFFF0000000000000ll;
  1433. return str + 7;
  1434. }
  1435. F64 negative = 1.0f;
  1436. if (str[0] == '+')
  1437. {
  1438. ++str;
  1439. }
  1440. if (str[0] == '-')
  1441. {
  1442. negative = -1.0f;
  1443. ++str;
  1444. }
  1445. const char* base_str = str;
  1446. str = skipWhitespace(str);
  1447. // Parse the integer part of the expression
  1448. U64 int_part = 0;
  1449. while (str[0] >= '0' && str[0] <= '9')
  1450. {
  1451. int_part *= 10;
  1452. int_part += U64(str[0] - '0');
  1453. ++str;
  1454. }
  1455. U64 f_part = 0;//, f_decimal = 1;
  1456. if (str[0] == '.')
  1457. {
  1458. ++str;
  1459. U64 remainder = 0;
  1460. U32 pos = 0;
  1461. // Parse the decimal part of the expression
  1462. while (str[0] >= '0' && str[0] <= '9' && pos < 25)
  1463. {
  1464. remainder = (remainder*10) + U64(str[0] - '0');
  1465. f_part <<= 1;
  1466. //f_decimal <<= 1;
  1467. // Check the n'th bit
  1468. if (remainder >= float_coeff_table[pos])
  1469. {
  1470. remainder -= float_coeff_table[pos];
  1471. f_part |= 1;
  1472. }
  1473. ++pos;
  1474. ++str;
  1475. }
  1476. if (pos == 25)
  1477. {
  1478. // Drop any excessive digits
  1479. while (str[0] >= '0' && str[0] <= '9')
  1480. {
  1481. ++str;
  1482. }
  1483. }
  1484. else
  1485. {
  1486. while (pos < 25)
  1487. {
  1488. remainder *= 10;
  1489. f_part <<= 1;
  1490. //f_decimal <<= 1;
  1491. // Check the n'th bit
  1492. if (remainder >= float_coeff_table[pos])
  1493. {
  1494. remainder -= float_coeff_table[pos];
  1495. f_part |= 1;
  1496. }
  1497. ++pos;
  1498. }
  1499. }
  1500. pos = 0;
  1501. while (pos < 36)
  1502. {
  1503. f_part <<= 1;
  1504. //f_decimal <<= 1;
  1505. if (remainder >= float_coeff_table_2[pos])
  1506. {
  1507. remainder -= float_coeff_table_2[pos];
  1508. f_part |= 1;
  1509. }
  1510. ++pos;
  1511. }
  1512. }
  1513. F64 ret = F64(int_part) + (F64(f_part)/F64(1LL<<61));
  1514. F64 exponent = 1.f;
  1515. if (str[0] == 'e')
  1516. {
  1517. // Scientific notation!
  1518. ++str;
  1519. U64 exp;
  1520. BOOL is_negative;
  1521. str = parseInteger(str, &exp, &is_negative, 64, ENCODING_DECIMAL);
  1522. if (str == NULL)
  1523. {
  1524. exp = 1;
  1525. }
  1526. F64 exp_d = F64(exp) * (is_negative?-1:1);
  1527. exponent = pow(10.0, exp_d);
  1528. }
  1529. if (str == base_str)
  1530. {
  1531. // no digits parsed
  1532. return NULL;
  1533. }
  1534. else
  1535. {
  1536. *dest = ret*negative*exponent;
  1537. return str;
  1538. }
  1539. }
  1540. if (encoding == ENCODING_HEX)
  1541. {
  1542. U64 bytes_dest;
  1543. BOOL is_negative;
  1544. str = parseInteger(str, (U64 *)&bytes_dest, &is_negative, precision, ENCODING_HEX);
  1545. // Upcast to F64
  1546. switch (precision)
  1547. {
  1548. case 32:
  1549. {
  1550. U32 short_dest = (U32)bytes_dest;
  1551. F32 ret_val = *(F32 *)&short_dest;
  1552. *dest = ret_val;
  1553. }
  1554. break;
  1555. case 64:
  1556. *dest = *(F64 *)&bytes_dest;
  1557. break;
  1558. default:
  1559. return NULL;
  1560. }
  1561. return str;
  1562. }
  1563. return NULL;
  1564. }
  1565. U32 LLXMLNode::getBoolValue(U32 expected_length, BOOL *array)
  1566. {
  1567. llassert(array);
  1568. // Check type - accept booleans or strings
  1569. if (mType != TYPE_BOOLEAN && mType != TYPE_STRING && mType != TYPE_UNKNOWN)
  1570. {
  1571. return 0;
  1572. }
  1573. std::string *str_array = new std::string[expected_length];
  1574. U32 length = getStringValue(expected_length, str_array);
  1575. U32 ret_length = 0;
  1576. for (U32 i=0; i<length; ++i)
  1577. {
  1578. LLStringUtil::toLower(str_array[i]);
  1579. if (str_array[i] == "false")
  1580. {
  1581. array[ret_length++] = FALSE;
  1582. }
  1583. else if (str_array[i] == "true")
  1584. {
  1585. array[ret_length++] = TRUE;
  1586. }
  1587. }
  1588. delete[] str_array;
  1589. #if LL_DEBUG
  1590. if (ret_length != expected_length)
  1591. {
  1592. lldebugs << "LLXMLNode::getBoolValue() failed for node named '" 
  1593. << mName->mString << "' -- expected " << expected_length << " but "
  1594. << "only found " << ret_length << llendl;
  1595. }
  1596. #endif
  1597. return ret_length;
  1598. }
  1599. U32 LLXMLNode::getByteValue(U32 expected_length, U8 *array, Encoding encoding)
  1600. {
  1601. llassert(array);
  1602. // Check type - accept bytes or integers (below 256 only)
  1603. if (mType != TYPE_INTEGER 
  1604. && mType != TYPE_UNKNOWN)
  1605. {
  1606. return 0;
  1607. }
  1608. if (mLength > 0 && mLength != expected_length)
  1609. {
  1610. llwarns << "XMLNode::getByteValue asked for " << expected_length 
  1611. << " elements, while node has " << mLength << llendl;
  1612. return 0;
  1613. }
  1614. if (encoding == ENCODING_DEFAULT)
  1615. {
  1616. encoding = mEncoding;
  1617. }
  1618. const char *value_string = mValue.c_str();
  1619. U32 i;
  1620. for (i=0; i<expected_length; ++i)
  1621. {
  1622. U64 value;
  1623. BOOL is_negative;
  1624. value_string = parseInteger(value_string, &value, &is_negative, 8, encoding);
  1625. if (value_string == NULL)
  1626. {
  1627. break;
  1628. }
  1629. if (value > 255 || is_negative)
  1630. {
  1631. llwarns << "getByteValue: Value outside of valid range." << llendl;
  1632. break;
  1633. }
  1634. array[i] = U8(value);
  1635. }
  1636. #if LL_DEBUG
  1637. if (i != expected_length)
  1638. {
  1639. lldebugs << "LLXMLNode::getByteValue() failed for node named '" 
  1640. << mName->mString << "' -- expected " << expected_length << " but "
  1641. << "only found " << i << llendl;
  1642. }
  1643. #endif
  1644. return i;
  1645. }
  1646. U32 LLXMLNode::getIntValue(U32 expected_length, S32 *array, Encoding encoding)
  1647. {
  1648. llassert(array);
  1649. // Check type - accept bytes or integers
  1650. if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN)
  1651. {
  1652. return 0;
  1653. }
  1654. if (mLength > 0 && mLength != expected_length)
  1655. {
  1656. llwarns << "XMLNode::getIntValue asked for " << expected_length 
  1657. << " elements, while node has " << mLength << llendl;
  1658. return 0;
  1659. }
  1660. if (encoding == ENCODING_DEFAULT)
  1661. {
  1662. encoding = mEncoding;
  1663. }
  1664. const char *value_string = mValue.c_str();
  1665. U32 i = 0;
  1666. for (i=0; i<expected_length; ++i)
  1667. {
  1668. U64 value;
  1669. BOOL is_negative;
  1670. value_string = parseInteger(value_string, &value, &is_negative, 32, encoding);
  1671. if (value_string == NULL)
  1672. {
  1673. break;
  1674. }
  1675. if (value > 0x7fffffff)
  1676. {
  1677. llwarns << "getIntValue: Value outside of valid range." << llendl;
  1678. break;
  1679. }
  1680. array[i] = S32(value) * (is_negative?-1:1);
  1681. }
  1682. #if LL_DEBUG
  1683. if (i != expected_length)
  1684. {
  1685. lldebugs << "LLXMLNode::getIntValue() failed for node named '" 
  1686. << mName->mString << "' -- expected " << expected_length << " but "
  1687. << "only found " << i << llendl;
  1688. }
  1689. #endif
  1690. return i;
  1691. }
  1692. U32 LLXMLNode::getUnsignedValue(U32 expected_length, U32 *array, Encoding encoding)
  1693. {
  1694. llassert(array);
  1695. // Check type - accept bytes or integers
  1696. if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN)
  1697. {
  1698. return 0;
  1699. }
  1700. if (mLength > 0 && mLength != expected_length)
  1701. {
  1702. llwarns << "XMLNode::getUnsignedValue asked for " << expected_length 
  1703. << " elements, while node has " << mLength << llendl;
  1704. return 0;
  1705. }
  1706. if (encoding == ENCODING_DEFAULT)
  1707. {
  1708. encoding = mEncoding;
  1709. }
  1710. const char *value_string = mValue.c_str();
  1711. U32 i = 0;
  1712. // Int type
  1713. for (i=0; i<expected_length; ++i)
  1714. {
  1715. U64 value;
  1716. BOOL is_negative;
  1717. value_string = parseInteger(value_string, &value, &is_negative, 32, encoding);
  1718. if (value_string == NULL)
  1719. {
  1720. break;
  1721. }
  1722. if (is_negative || value > 0xffffffff)
  1723. {
  1724. llwarns << "getUnsignedValue: Value outside of valid range." << llendl;
  1725. break;
  1726. }
  1727. array[i] = U32(value);
  1728. }
  1729. #if LL_DEBUG
  1730. if (i != expected_length)
  1731. {
  1732. lldebugs << "LLXMLNode::getUnsignedValue() failed for node named '" 
  1733. << mName->mString << "' -- expected " << expected_length << " but "
  1734. << "only found " << i << llendl;
  1735. }
  1736. #endif
  1737. return i;
  1738. }
  1739. U32 LLXMLNode::getLongValue(U32 expected_length, U64 *array, Encoding encoding)
  1740. {
  1741. llassert(array);
  1742. // Check type - accept bytes or integers
  1743. if (mType != TYPE_INTEGER && mType != TYPE_UNKNOWN)
  1744. {
  1745. return 0;
  1746. }
  1747. if (mLength > 0 && mLength != expected_length)
  1748. {
  1749. llwarns << "XMLNode::getLongValue asked for " << expected_length << " elements, while node has " << mLength << llendl;
  1750. return 0;
  1751. }
  1752. if (encoding == ENCODING_DEFAULT)
  1753. {
  1754. encoding = mEncoding;
  1755. }
  1756. const char *value_string = mValue.c_str();
  1757. U32 i = 0;
  1758. // Int type
  1759. for (i=0; i<expected_length; ++i)
  1760. {
  1761. U64 value;
  1762. BOOL is_negative;
  1763. value_string = parseInteger(value_string, &value, &is_negative, 64, encoding);
  1764. if (value_string == NULL)
  1765. {
  1766. break;
  1767. }
  1768. if (is_negative)
  1769. {
  1770. llwarns << "getLongValue: Value outside of valid range." << llendl;
  1771. break;
  1772. }
  1773. array[i] = value;
  1774. }
  1775. #if LL_DEBUG
  1776. if (i != expected_length)
  1777. {
  1778. lldebugs << "LLXMLNode::getLongValue() failed for node named '" 
  1779. << mName->mString << "' -- expected " << expected_length << " but "
  1780. << "only found " << i << llendl;
  1781. }
  1782. #endif
  1783. return i;
  1784. }
  1785. U32 LLXMLNode::getFloatValue(U32 expected_length, F32 *array, Encoding encoding)
  1786. {
  1787. llassert(array);
  1788. // Check type - accept only floats or doubles
  1789. if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN)
  1790. {
  1791. return 0;
  1792. }
  1793. if (mLength > 0 && mLength != expected_length)
  1794. {
  1795. llwarns << "XMLNode::getFloatValue asked for " << expected_length << " elements, while node has " << mLength << llendl;
  1796. return 0;
  1797. }
  1798. if (encoding == ENCODING_DEFAULT)
  1799. {
  1800. encoding = mEncoding;
  1801. }
  1802. const char *value_string = mValue.c_str();
  1803. U32 i;
  1804. for (i=0; i<expected_length; ++i)
  1805. {
  1806. F64 value;
  1807. value_string = parseFloat(value_string, &value, 32, encoding);
  1808. if (value_string == NULL)
  1809. {
  1810. break;
  1811. }
  1812. array[i] = F32(value);
  1813. }
  1814. #if LL_DEBUG
  1815. if (i != expected_length)
  1816. {
  1817. lldebugs << "LLXMLNode::getFloatValue() failed for node named '" 
  1818. << mName->mString << "' -- expected " << expected_length << " but "
  1819. << "only found " << i << llendl;
  1820. }
  1821. #endif
  1822. return i;
  1823. }
  1824. U32 LLXMLNode::getDoubleValue(U32 expected_length, F64 *array, Encoding encoding)
  1825. {
  1826. llassert(array);
  1827. // Check type - accept only floats or doubles
  1828. if (mType != TYPE_FLOAT && mType != TYPE_UNKNOWN)
  1829. {
  1830. return 0;
  1831. }
  1832. if (mLength > 0 && mLength != expected_length)
  1833. {
  1834. llwarns << "XMLNode::getDoubleValue asked for " << expected_length << " elements, while node has " << mLength << llendl;
  1835. return 0;
  1836. }
  1837. if (encoding == ENCODING_DEFAULT)
  1838. {
  1839. encoding = mEncoding;
  1840. }
  1841. const char *value_string = mValue.c_str();
  1842. U32 i;
  1843. for (i=0; i<expected_length; ++i)
  1844. {
  1845. F64 value;
  1846. value_string = parseFloat(value_string, &value, 64, encoding);
  1847. if (value_string == NULL)
  1848. {
  1849. break;
  1850. }
  1851. array[i] = value;
  1852. }
  1853. #if LL_DEBUG
  1854. if (i != expected_length)
  1855. {
  1856. lldebugs << "LLXMLNode::getDoubleValue() failed for node named '" 
  1857. << mName->mString << "' -- expected " << expected_length << " but "
  1858. << "only found " << i << llendl;
  1859. }
  1860. #endif
  1861. return i;
  1862. }
  1863. U32 LLXMLNode::getStringValue(U32 expected_length, std::string *array)
  1864. {
  1865. llassert(array);
  1866. // Can always return any value as a string
  1867. if (mLength > 0 && mLength != expected_length)
  1868. {
  1869. llwarns << "XMLNode::getStringValue asked for " << expected_length << " elements, while node has " << mLength << llendl;
  1870. return 0;
  1871. }
  1872. U32 num_returned_strings = 0;
  1873. // Array of strings is whitespace-separated
  1874. const std::string sep(" nt");
  1875. std::string::size_type n = 0;
  1876. std::string::size_type m = 0;
  1877. while(1)
  1878. {
  1879. if (num_returned_strings >= expected_length)
  1880. {
  1881. break;
  1882. }
  1883. n = mValue.find_first_not_of(sep, m);
  1884. m = mValue.find_first_of(sep, n);
  1885. if (m == std::string::npos)
  1886. {
  1887. break;
  1888. }
  1889. array[num_returned_strings++] = mValue.substr(n,m-n);
  1890. }
  1891. if (n != std::string::npos && num_returned_strings < expected_length)
  1892. {
  1893. array[num_returned_strings++] = mValue.substr(n);
  1894. }
  1895. #if LL_DEBUG
  1896. if (num_returned_strings != expected_length)
  1897. {
  1898. lldebugs << "LLXMLNode::getStringValue() failed for node named '" 
  1899. << mName->mString << "' -- expected " << expected_length << " but "
  1900. << "only found " << num_returned_strings << llendl;
  1901. }
  1902. #endif
  1903. return num_returned_strings;
  1904. }
  1905. U32 LLXMLNode::getUUIDValue(U32 expected_length, LLUUID *array)
  1906. {
  1907. llassert(array);
  1908. // Check type
  1909. if (mType != TYPE_UUID && mType != TYPE_UNKNOWN)
  1910. {
  1911. return 0;
  1912. }
  1913. const char *value_string = mValue.c_str();
  1914. U32 i;
  1915. for (i=0; i<expected_length; ++i)
  1916. {
  1917. LLUUID uuid_value;
  1918. value_string = skipWhitespace(value_string);
  1919. if (strlen(value_string) < (UUID_STR_LENGTH-1)) /* Flawfinder: ignore */
  1920. {
  1921. break;
  1922. }
  1923. char uuid_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */
  1924. memcpy(uuid_string, value_string, (UUID_STR_LENGTH-1)); /* Flawfinder: ignore */
  1925. uuid_string[(UUID_STR_LENGTH-1)] = 0;
  1926. if (!LLUUID::parseUUID(std::string(uuid_string), &uuid_value))
  1927. {
  1928. break;
  1929. }
  1930. value_string = &value_string[(UUID_STR_LENGTH-1)];
  1931. array[i] = uuid_value;
  1932. }
  1933. #if LL_DEBUG
  1934. if (i != expected_length)
  1935. {
  1936. lldebugs << "LLXMLNode::getUUIDValue() failed for node named '" 
  1937. << mName->mString << "' -- expected " << expected_length << " but "
  1938. << "only found " << i << llendl;
  1939. }
  1940. #endif
  1941. return i;
  1942. }
  1943. U32 LLXMLNode::getNodeRefValue(U32 expected_length, LLXMLNode **array)
  1944. {
  1945. llassert(array);
  1946. // Check type
  1947. if (mType != TYPE_NODEREF && mType != TYPE_UNKNOWN)
  1948. {
  1949. return 0;
  1950. }
  1951. std::string *string_array = new std::string[expected_length];
  1952. U32 num_strings = getStringValue(expected_length, string_array);
  1953. U32 num_returned_refs = 0;
  1954. LLXMLNodePtr root = getRoot();
  1955. for (U32 strnum=0; strnum<num_strings; ++strnum)
  1956. {
  1957. LLXMLNodeList node_list;
  1958. root->findID(string_array[strnum], node_list);
  1959. if (node_list.empty())
  1960. {
  1961. llwarns << "XML: Could not find node ID: " << string_array[strnum] << llendl;
  1962. }
  1963. else if (node_list.size() > 1)
  1964. {
  1965. llwarns << "XML: Node ID not unique: " << string_array[strnum] << llendl;
  1966. }
  1967. else
  1968. {
  1969. LLXMLNodeList::const_iterator list_itr = node_list.begin(); 
  1970. if (list_itr != node_list.end())
  1971. {
  1972. LLXMLNode* child = (*list_itr).second;
  1973. array[num_returned_refs++] = child;
  1974. }
  1975. }
  1976. }
  1977. delete[] string_array;
  1978. return num_returned_refs;
  1979. }
  1980. void LLXMLNode::setBoolValue(U32 length, const BOOL *array)
  1981. {
  1982. if (length == 0) return;
  1983. std::string new_value;
  1984. for (U32 pos=0; pos<length; ++pos)
  1985. {
  1986. if (pos > 0)
  1987. {
  1988. new_value = llformat("%s %s", new_value.c_str(), array[pos]?"true":"false");
  1989. }
  1990. else
  1991. {
  1992. new_value = array[pos]?"true":"false";
  1993. }
  1994. }
  1995. mValue = new_value;
  1996. mEncoding = ENCODING_DEFAULT;
  1997. mLength = length;
  1998. mType = TYPE_BOOLEAN;
  1999. }
  2000. void LLXMLNode::setByteValue(U32 length, const U8* const array, Encoding encoding)
  2001. {
  2002. if (length == 0) return;
  2003. std::string new_value;
  2004. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2005. {
  2006. for (U32 pos=0; pos<length; ++pos)
  2007. {
  2008. if (pos > 0)
  2009. {
  2010. new_value.append(llformat(" %u", array[pos]));
  2011. }
  2012. else
  2013. {
  2014. new_value = llformat("%u", array[pos]);
  2015. }
  2016. }
  2017. }
  2018. if (encoding == ENCODING_HEX)
  2019. {
  2020. for (U32 pos=0; pos<length; ++pos)
  2021. {
  2022. if (pos > 0 && pos % 16 == 0)
  2023. {
  2024. new_value.append(llformat(" %02X", array[pos]));
  2025. }
  2026. else
  2027. {
  2028. new_value.append(llformat("%02X", array[pos]));
  2029. }
  2030. }
  2031. }
  2032. // TODO -- Handle Base32
  2033. mValue = new_value;
  2034. mEncoding = encoding;
  2035. mLength = length;
  2036. mType = TYPE_INTEGER;
  2037. mPrecision = 8;
  2038. }
  2039. void LLXMLNode::setIntValue(U32 length, const S32 *array, Encoding encoding)
  2040. {
  2041. if (length == 0) return;
  2042. std::string new_value;
  2043. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2044. {
  2045. for (U32 pos=0; pos<length; ++pos)
  2046. {
  2047. if (pos > 0)
  2048. {
  2049. new_value.append(llformat(" %d", array[pos]));
  2050. }
  2051. else
  2052. {
  2053. new_value = llformat("%d", array[pos]);
  2054. }
  2055. }
  2056. mValue = new_value;
  2057. }
  2058. else if (encoding == ENCODING_HEX)
  2059. {
  2060. for (U32 pos=0; pos<length; ++pos)
  2061. {
  2062. if (pos > 0 && pos % 16 == 0)
  2063. {
  2064. new_value.append(llformat(" %08X", ((U32 *)array)[pos]));
  2065. }
  2066. else
  2067. {
  2068. new_value.append(llformat("%08X", ((U32 *)array)[pos]));
  2069. }
  2070. }
  2071. mValue = new_value;
  2072. }
  2073. else
  2074. {
  2075. mValue = new_value;
  2076. }
  2077. // TODO -- Handle Base32
  2078. mEncoding = encoding;
  2079. mLength = length;
  2080. mType = TYPE_INTEGER;
  2081. mPrecision = 32;
  2082. }
  2083. void LLXMLNode::setUnsignedValue(U32 length, const U32* array, Encoding encoding)
  2084. {
  2085. if (length == 0) return;
  2086. std::string new_value;
  2087. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2088. {
  2089. for (U32 pos=0; pos<length; ++pos)
  2090. {
  2091. if (pos > 0)
  2092. {
  2093. new_value.append(llformat(" %u", array[pos]));
  2094. }
  2095. else
  2096. {
  2097. new_value = llformat("%u", array[pos]);
  2098. }
  2099. }
  2100. }
  2101. if (encoding == ENCODING_HEX)
  2102. {
  2103. for (U32 pos=0; pos<length; ++pos)
  2104. {
  2105. if (pos > 0 && pos % 16 == 0)
  2106. {
  2107. new_value.append(llformat(" %08X", array[pos]));
  2108. }
  2109. else
  2110. {
  2111. new_value.append(llformat("%08X", array[pos]));
  2112. }
  2113. }
  2114. mValue = new_value;
  2115. }
  2116. // TODO -- Handle Base32
  2117. mValue = new_value;
  2118. mEncoding = encoding;
  2119. mLength = length;
  2120. mType = TYPE_INTEGER;
  2121. mPrecision = 32;
  2122. }
  2123. #if LL_WINDOWS
  2124. #define PU64 "I64u"
  2125. #else
  2126. #define PU64 "llu"
  2127. #endif
  2128. void LLXMLNode::setLongValue(U32 length, const U64* array, Encoding encoding)
  2129. {
  2130. if (length == 0) return;
  2131. std::string new_value;
  2132. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2133. {
  2134. for (U32 pos=0; pos<length; ++pos)
  2135. {
  2136. if (pos > 0)
  2137. {
  2138. new_value.append(llformat(" %" PU64, array[pos]));
  2139. }
  2140. else
  2141. {
  2142. new_value = llformat("%" PU64, array[pos]);
  2143. }
  2144. }
  2145. mValue = new_value;
  2146. }
  2147. if (encoding == ENCODING_HEX)
  2148. {
  2149. for (U32 pos=0; pos<length; ++pos)
  2150. {
  2151. U32 upper_32 = U32(array[pos]>>32);
  2152. U32 lower_32 = U32(array[pos]&0xffffffff);
  2153. if (pos > 0 && pos % 8 == 0)
  2154. {
  2155. new_value.append(llformat(" %08X%08X", upper_32, lower_32));
  2156. }
  2157. else
  2158. {
  2159. new_value.append(llformat("%08X%08X", upper_32, lower_32));
  2160. }
  2161. }
  2162. mValue = new_value;
  2163. }
  2164. else
  2165. {
  2166. mValue = new_value;
  2167. }
  2168. // TODO -- Handle Base32
  2169. mEncoding = encoding;
  2170. mLength = length;
  2171. mType = TYPE_INTEGER;
  2172. mPrecision = 64;
  2173. }
  2174. void LLXMLNode::setFloatValue(U32 length, const F32 *array, Encoding encoding, U32 precision)
  2175. {
  2176. if (length == 0) return;
  2177. std::string new_value;
  2178. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2179. {
  2180. std::string format_string;
  2181. if (precision > 0)
  2182. {
  2183. if (precision > 25)
  2184. {
  2185. precision = 25;
  2186. }
  2187. format_string = llformat( "%%.%dg", precision);
  2188. }
  2189. else
  2190. {
  2191. format_string = llformat( "%%g");
  2192. }
  2193. for (U32 pos=0; pos<length; ++pos)
  2194. {
  2195. if (pos > 0)
  2196. {
  2197. new_value.append(" ");
  2198. new_value.append(llformat(format_string.c_str(), array[pos]));
  2199. }
  2200. else
  2201. {
  2202. new_value.assign(llformat(format_string.c_str(), array[pos]));
  2203. }
  2204. }
  2205. mValue = new_value;
  2206. }
  2207. else if (encoding == ENCODING_HEX)
  2208. {
  2209. U32 *byte_array = (U32 *)array;
  2210. setUnsignedValue(length, byte_array, ENCODING_HEX);
  2211. }
  2212. else
  2213. {
  2214. mValue = new_value;
  2215. }
  2216. mEncoding = encoding;
  2217. mLength = length;
  2218. mType = TYPE_FLOAT;
  2219. mPrecision = 32;
  2220. }
  2221. void LLXMLNode::setDoubleValue(U32 length, const F64 *array, Encoding encoding, U32 precision)
  2222. {
  2223. if (length == 0) return;
  2224. std::string new_value;
  2225. if (encoding == ENCODING_DEFAULT || encoding == ENCODING_DECIMAL)
  2226. {
  2227. std::string format_string;
  2228. if (precision > 0)
  2229. {
  2230. if (precision > 25)
  2231. {
  2232. precision = 25;
  2233. }
  2234. format_string = llformat( "%%.%dg", precision);
  2235. }
  2236. else
  2237. {
  2238. format_string = llformat( "%%g");
  2239. }
  2240. for (U32 pos=0; pos<length; ++pos)
  2241. {
  2242. if (pos > 0)
  2243. {
  2244. new_value.append(" ");
  2245. new_value.append(llformat(format_string.c_str(), array[pos]));
  2246. }
  2247. else
  2248. {
  2249. new_value.assign(llformat(format_string.c_str(), array[pos]));
  2250. }
  2251. }
  2252. mValue = new_value;
  2253. }
  2254. if (encoding == ENCODING_HEX)
  2255. {
  2256. U64 *byte_array = (U64 *)array;
  2257. setLongValue(length, byte_array, ENCODING_HEX);
  2258. }
  2259. else
  2260. {
  2261. mValue = new_value;
  2262. }
  2263. // TODO -- Handle Base32
  2264. mEncoding = encoding;
  2265. mLength = length;
  2266. mType = TYPE_FLOAT;
  2267. mPrecision = 64;
  2268. }
  2269. // static
  2270. std::string LLXMLNode::escapeXML(const std::string& xml)
  2271. {
  2272. std::string out;
  2273. for (std::string::size_type i = 0; i < xml.size(); ++i)
  2274. {
  2275. char c = xml[i];
  2276. switch(c)
  2277. {
  2278. case '"': out.append("&quot;"); break;
  2279. case ''': out.append("&apos;"); break;
  2280. case '&': out.append("&amp;"); break;
  2281. case '<': out.append("&lt;"); break;
  2282. case '>': out.append("&gt;"); break;
  2283. default: out.push_back(c); break;
  2284. }
  2285. }
  2286. return out;
  2287. }
  2288. void LLXMLNode::setStringValue(U32 length, const std::string *strings)
  2289. {
  2290. if (length == 0) return;
  2291. std::string new_value;
  2292. for (U32 pos=0; pos<length; ++pos)
  2293. {
  2294. // *NOTE: Do not escape strings here - do it on output
  2295. new_value.append( strings[pos] );
  2296. if (pos < length-1) new_value.append(" ");
  2297. }
  2298. mValue = new_value;
  2299. mEncoding = ENCODING_DEFAULT;
  2300. mLength = length;
  2301. mType = TYPE_STRING;
  2302. }
  2303. void LLXMLNode::setUUIDValue(U32 length, const LLUUID *array)
  2304. {
  2305. if (length == 0) return;
  2306. std::string new_value;
  2307. for (U32 pos=0; pos<length; ++pos)
  2308. {
  2309. new_value.append(array[pos].asString());
  2310. if (pos < length-1) new_value.append(" ");
  2311. }
  2312. mValue = new_value;
  2313. mEncoding = ENCODING_DEFAULT;
  2314. mLength = length;
  2315. mType = TYPE_UUID;
  2316. }
  2317. void LLXMLNode::setNodeRefValue(U32 length, const LLXMLNode **array)
  2318. {
  2319. if (length == 0) return;
  2320. std::string new_value;
  2321. for (U32 pos=0; pos<length; ++pos)
  2322. {
  2323. if (array[pos]->mID != "")
  2324. {
  2325. new_value.append(array[pos]->mID);
  2326. }
  2327. else
  2328. {
  2329. new_value.append("(null)");
  2330. }
  2331. if (pos < length-1) new_value.append(" ");
  2332. }
  2333. mValue = new_value;
  2334. mEncoding = ENCODING_DEFAULT;
  2335. mLength = length;
  2336. mType = TYPE_NODEREF;
  2337. }
  2338. void LLXMLNode::setValue(const std::string& value)
  2339. {
  2340. if (TYPE_CONTAINER == mType)
  2341. {
  2342. mType = TYPE_UNKNOWN;
  2343. }
  2344. mValue = value;
  2345. }
  2346. void LLXMLNode::setDefault(LLXMLNode *default_node)
  2347. {
  2348. mDefault = default_node;
  2349. }
  2350. void LLXMLNode::findDefault(LLXMLNode *defaults_list)
  2351. {
  2352. if (defaults_list)
  2353. {
  2354. LLXMLNodeList children;
  2355. defaults_list->getChildren(mName->mString, children);
  2356. LLXMLNodeList::const_iterator children_itr;
  2357. LLXMLNodeList::const_iterator children_end = children.end();
  2358. for (children_itr = children.begin(); children_itr != children_end; ++children_itr)
  2359. {
  2360. LLXMLNode* child = (*children_itr).second;
  2361. if (child->mVersionMajor == mVersionMajor &&
  2362. child->mVersionMinor == mVersionMinor)
  2363. {
  2364. mDefault = child;
  2365. return;
  2366. }
  2367. }
  2368. }
  2369. mDefault = NULL;
  2370. }
  2371. BOOL LLXMLNode::deleteChildren(const std::string& name)
  2372. {
  2373. U32 removed_count = 0;
  2374. LLXMLNodeList node_list;
  2375. findName(name, node_list);
  2376. if (!node_list.empty())
  2377. {
  2378. // TODO -- use multimap::find()
  2379. // TODO -- need to watch out for invalid iterators
  2380. LLXMLNodeList::iterator children_itr;
  2381. for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr)
  2382. LLXMLNode* child = (*children_itr).second;
  2383. if (deleteChild(child))
  2384. {
  2385. removed_count++;
  2386. }
  2387. }
  2388. }
  2389. return removed_count > 0 ? TRUE : FALSE;
  2390. }
  2391. BOOL LLXMLNode::deleteChildren(LLStringTableEntry* name)
  2392. {
  2393. U32 removed_count = 0;
  2394. LLXMLNodeList node_list;
  2395. findName(name, node_list);
  2396. if (!node_list.empty())
  2397. {
  2398. // TODO -- use multimap::find()
  2399. // TODO -- need to watch out for invalid iterators
  2400. LLXMLNodeList::iterator children_itr;
  2401. for (children_itr = node_list.begin(); children_itr != node_list.end(); ++children_itr)
  2402. LLXMLNode* child = (*children_itr).second;
  2403. if (deleteChild(child))
  2404. {
  2405. removed_count++;
  2406. }
  2407. }
  2408. }
  2409. return removed_count > 0 ? TRUE : FALSE;
  2410. }
  2411. void LLXMLNode::setAttributes(LLXMLNode::ValueType type, U32 precision, LLXMLNode::Encoding encoding, U32 length)
  2412. {
  2413. mType = type;
  2414. mEncoding = encoding;
  2415. mPrecision = precision;
  2416. mLength = length;
  2417. }
  2418. void LLXMLNode::setName(const std::string& name)
  2419. {
  2420. setName(gStringTable.addStringEntry(name));
  2421. }
  2422. void LLXMLNode::setName(LLStringTableEntry* name)
  2423. {
  2424. LLXMLNode* old_parent = mParent;
  2425. if (mParent)
  2426. {
  2427. // we need to remove and re-add to the parent so that
  2428. // the multimap key agrees with this node's name
  2429. mParent->removeChild(this);
  2430. }
  2431. mName = name;
  2432. if (old_parent)
  2433. {
  2434. old_parent->addChild(this);
  2435. }
  2436. }
  2437. // Unused
  2438. // void LLXMLNode::appendValue(const std::string& value)
  2439. // {
  2440. //  mValue.append(value);
  2441. // }
  2442. U32 LLXMLNode::getChildCount() const 
  2443. if (mChildren.notNull())
  2444. {
  2445. return mChildren->map.size(); 
  2446. }
  2447. return 0;
  2448. }
  2449. //***************************************************
  2450. //  UNIT TESTING 
  2451. //***************************************************
  2452. U32 get_rand(U32 max_value)
  2453. {
  2454. U32 random_num = rand() + ((U32)rand() << 16);
  2455. return (random_num % max_value);
  2456. }
  2457. LLXMLNode *get_rand_node(LLXMLNode *node)
  2458. {
  2459. if (node->mChildren.notNull())
  2460. {
  2461. U32 num_children = node->mChildren->map.size();
  2462. if (get_rand(2) == 0)
  2463. {
  2464. while (true)
  2465. {
  2466. S32 child_num = S32(get_rand(num_children*2)) - num_children;
  2467. LLXMLChildList::iterator itor = node->mChildren->map.begin();
  2468. while (child_num > 0)
  2469. {
  2470. --child_num;
  2471. ++itor;
  2472. }
  2473. if (!itor->second->mIsAttribute)
  2474. {
  2475. return get_rand_node(itor->second);
  2476. }
  2477. }
  2478. }
  2479. }
  2480. return node;
  2481. }
  2482. void LLXMLNode::createUnitTest(S32 max_num_children)
  2483. {
  2484. // Random ID
  2485. std::string rand_id;
  2486. U32 rand_id_len = get_rand(10)+5;
  2487. for (U32 pos = 0; pos<rand_id_len; ++pos)
  2488. {
  2489. char c = 'a' + get_rand(26);
  2490. rand_id.append(1, c);
  2491. }
  2492. mID = rand_id;
  2493. if (max_num_children < 2)
  2494. {
  2495. setStringValue(1, &mID);
  2496. return;
  2497. }
  2498. // Checksums
  2499. U32 integer_checksum = 0;
  2500. U64 long_checksum = 0;
  2501. U32 bool_true_count = 0;
  2502. LLUUID uuid_checksum;
  2503. U32 noderef_checksum = 0;
  2504. U32 float_checksum = 0;
  2505. // Create a random number of children
  2506. U32 num_children = get_rand(max_num_children)+1;
  2507. for (U32 child_num=0; child_num<num_children; ++child_num)
  2508. {
  2509. // Random Name
  2510. std::string child_name;
  2511. U32 child_name_len = get_rand(10)+5;
  2512. for (U32 pos = 0; pos<child_name_len; ++pos)
  2513. {
  2514. char c = 'a' + get_rand(26);
  2515. child_name.append(1, c);
  2516. }
  2517. LLXMLNode *new_child = createChild(child_name.c_str(), FALSE);
  2518. // Random ID
  2519. std::string child_id;
  2520. U32 child_id_len = get_rand(10)+5;
  2521. for (U32 pos=0; pos<child_id_len; ++pos)
  2522. {
  2523. char c = 'a' + get_rand(26);
  2524. child_id.append(1, c);
  2525. }
  2526. new_child->mID = child_id;
  2527. // Random Length
  2528. U32 array_size = get_rand(28)+1;
  2529. // Random Encoding
  2530. Encoding new_encoding = get_rand(2)?ENCODING_DECIMAL:ENCODING_HEX;
  2531. // Random Type
  2532. int type = get_rand(8);
  2533. switch (type)
  2534. {
  2535. case 0: // TYPE_CONTAINER
  2536. new_child->createUnitTest(max_num_children/2);
  2537. break;
  2538. case 1: // TYPE_BOOLEAN
  2539. {
  2540. BOOL random_bool_values[30];
  2541. for (U32 value=0; value<array_size; ++value)
  2542. {
  2543. random_bool_values[value] = get_rand(2);
  2544. if (random_bool_values[value])
  2545. {
  2546. ++bool_true_count;
  2547. }
  2548. }
  2549. new_child->setBoolValue(array_size, random_bool_values);
  2550. }
  2551. break;
  2552. case 2: // TYPE_INTEGER (32-bit)
  2553. {
  2554. U32 random_int_values[30];
  2555. for (U32 value=0; value<array_size; ++value)
  2556. {
  2557. random_int_values[value] = get_rand(0xffffffff);
  2558. integer_checksum ^= random_int_values[value];
  2559. }
  2560. new_child->setUnsignedValue(array_size, random_int_values, new_encoding);
  2561. }
  2562. break;
  2563. case 3: // TYPE_INTEGER (64-bit)
  2564. {
  2565. U64 random_int_values[30];
  2566. for (U64 value=0; value<array_size; ++value)
  2567. {
  2568. random_int_values[value] = (U64(get_rand(0xffffffff)) << 32) + get_rand(0xffffffff);
  2569. long_checksum ^= random_int_values[value];
  2570. }
  2571. new_child->setLongValue(array_size, random_int_values, new_encoding);
  2572. }
  2573. break;
  2574. case 4: // TYPE_FLOAT (32-bit)
  2575. {
  2576. F32 random_float_values[30];
  2577. for (U32 value=0; value<array_size; ++value)
  2578. {
  2579. S32 exponent = get_rand(256) - 128;
  2580. S32 fractional_part = get_rand(0xffffffff);
  2581. S32 sign = get_rand(2) * 2 - 1;
  2582. random_float_values[value] = F32(fractional_part) / F32(0xffffffff) * exp(F32(exponent)) * F32(sign);
  2583. U32 *float_bits = &((U32 *)random_float_values)[value];
  2584. if (*float_bits == 0x80000000)
  2585. {
  2586. *float_bits = 0x00000000;
  2587. }
  2588. float_checksum ^= (*float_bits & 0xfffff000);
  2589. }
  2590. new_child->setFloatValue(array_size, random_float_values, new_encoding, 12);
  2591. }
  2592. break;
  2593. case 5: // TYPE_FLOAT (64-bit)
  2594. {
  2595. F64 random_float_values[30];
  2596. for (U32 value=0; value<array_size; ++value)
  2597. {
  2598. S32 exponent = get_rand(2048) - 1024;
  2599. S32 fractional_part = get_rand(0xffffffff);
  2600. S32 sign = get_rand(2) * 2 - 1;
  2601. random_float_values[value] = F64(fractional_part) / F64(0xffffffff) * exp(F64(exponent)) * F64(sign);
  2602. U64 *float_bits = &((U64 *)random_float_values)[value];
  2603. if (*float_bits == 0x8000000000000000ll)
  2604. {
  2605. *float_bits = 0x0000000000000000ll;
  2606. }
  2607. float_checksum ^= ((*float_bits & 0xfffffff000000000ll) >> 32);
  2608. }
  2609. new_child->setDoubleValue(array_size, random_float_values, new_encoding, 12);
  2610. }
  2611. break;
  2612. case 6: // TYPE_UUID
  2613. {
  2614. LLUUID random_uuid_values[30];
  2615. for (U32 value=0; value<array_size; ++value)
  2616. {
  2617. random_uuid_values[value].generate();
  2618. for (S32 byte=0; byte<UUID_BYTES; ++byte)
  2619. {
  2620. uuid_checksum.mData[byte] ^= random_uuid_values[value].mData[byte];
  2621. }
  2622. }
  2623. new_child->setUUIDValue(array_size, random_uuid_values);
  2624. }
  2625. break;
  2626. case 7: // TYPE_NODEREF
  2627. {
  2628. LLXMLNode *random_node_array[30];
  2629. LLXMLNode *root = getRoot();
  2630. for (U32 value=0; value<array_size; ++value)
  2631. {
  2632. random_node_array[value] = get_rand_node(root);
  2633. const char *node_name = random_node_array[value]->mName->mString;
  2634. for (U32 pos=0; pos<strlen(node_name); ++pos) /* Flawfinder: ignore */
  2635. {
  2636. U32 hash_contrib = U32(node_name[pos]) << ((pos % 4) * 8);
  2637. noderef_checksum ^= hash_contrib;
  2638. }
  2639. }
  2640. new_child->setNodeRefValue(array_size, (const LLXMLNode **)random_node_array);
  2641. }
  2642. break;
  2643. }
  2644. }
  2645. createChild("integer_checksum", TRUE)->setUnsignedValue(1, &integer_checksum, LLXMLNode::ENCODING_HEX);
  2646. createChild("long_checksum", TRUE)->setLongValue(1, &long_checksum, LLXMLNode::ENCODING_HEX);
  2647. createChild("bool_true_count", TRUE)->setUnsignedValue(1, &bool_true_count, LLXMLNode::ENCODING_HEX);
  2648. createChild("uuid_checksum", TRUE)->setUUIDValue(1, &uuid_checksum);
  2649. createChild("noderef_checksum", TRUE)->setUnsignedValue(1, &noderef_checksum, LLXMLNode::ENCODING_HEX);
  2650. createChild("float_checksum", TRUE)->setUnsignedValue(1, &float_checksum, LLXMLNode::ENCODING_HEX);
  2651. }
  2652. BOOL LLXMLNode::performUnitTest(std::string &error_buffer)
  2653. {
  2654. if (mChildren.isNull())
  2655. {
  2656. error_buffer.append(llformat("ERROR Node %s: No children found.n", mName->mString));
  2657. return FALSE;
  2658. }
  2659. // Checksums
  2660. U32 integer_checksum = 0;
  2661. U32 bool_true_count = 0;
  2662. LLUUID uuid_checksum;
  2663. U32 noderef_checksum = 0;
  2664. U32 float_checksum = 0;
  2665. U64 long_checksum = 0;
  2666. LLXMLChildList::iterator itor;
  2667. for (itor=mChildren->map.begin(); itor!=mChildren->map.end(); ++itor)
  2668. {
  2669. LLXMLNode *node = itor->second;
  2670. if (node->mIsAttribute)
  2671. {
  2672. continue;
  2673. }
  2674. if (node->mType == TYPE_CONTAINER)
  2675. {
  2676. if (!node->performUnitTest(error_buffer))
  2677. {
  2678. error_buffer.append(llformat("Child test failed for %s.n", mName->mString));
  2679. //return FALSE;
  2680. }
  2681. continue;
  2682. }
  2683. if (node->mLength < 1 || node->mLength > 30)
  2684. {
  2685. error_buffer.append(llformat("ERROR Node %s: Invalid array length %d, child %s.n", mName->mString, node->mLength, node->mName->mString));
  2686. return FALSE;
  2687. }
  2688. switch (node->mType)
  2689. {
  2690. case TYPE_CONTAINER:
  2691. case TYPE_UNKNOWN:
  2692. break;
  2693. case TYPE_BOOLEAN:
  2694. {
  2695. BOOL bool_array[30];
  2696. if (node->getBoolValue(node->mLength, bool_array) < node->mLength)
  2697. {
  2698. error_buffer.append(llformat("ERROR Node %s: Could not read boolean array, child %s.n", mName->mString, node->mName->mString));
  2699. return FALSE;
  2700. }
  2701. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2702. {
  2703. if (bool_array[pos])
  2704. {
  2705. ++bool_true_count;
  2706. }
  2707. }
  2708. }
  2709. break;
  2710. case TYPE_INTEGER:
  2711. {
  2712. if (node->mPrecision == 32)
  2713. {
  2714. U32 integer_array[30];
  2715. if (node->getUnsignedValue(node->mLength, integer_array, node->mEncoding) < node->mLength)
  2716. {
  2717. error_buffer.append(llformat("ERROR Node %s: Could not read integer array, child %s.n", mName->mString, node->mName->mString));
  2718. return FALSE;
  2719. }
  2720. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2721. {
  2722. integer_checksum ^= integer_array[pos];
  2723. }
  2724. }
  2725. else
  2726. {
  2727. U64 integer_array[30];
  2728. if (node->getLongValue(node->mLength, integer_array, node->mEncoding) < node->mLength)
  2729. {
  2730. error_buffer.append(llformat("ERROR Node %s: Could not read long integer array, child %s.n", mName->mString, node->mName->mString));
  2731. return FALSE;
  2732. }
  2733. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2734. {
  2735. long_checksum ^= integer_array[pos];
  2736. }
  2737. }
  2738. }
  2739. break;
  2740. case TYPE_FLOAT:
  2741. {
  2742. if (node->mPrecision == 32)
  2743. {
  2744. F32 float_array[30];
  2745. if (node->getFloatValue(node->mLength, float_array, node->mEncoding) < node->mLength)
  2746. {
  2747. error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.n", mName->mString, node->mName->mString));
  2748. return FALSE;
  2749. }
  2750. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2751. {
  2752. U32 float_bits = ((U32 *)float_array)[pos];
  2753. float_checksum ^= (float_bits & 0xfffff000);
  2754. }
  2755. }
  2756. else
  2757. {
  2758. F64 float_array[30];
  2759. if (node->getDoubleValue(node->mLength, float_array, node->mEncoding) < node->mLength)
  2760. {
  2761. error_buffer.append(llformat("ERROR Node %s: Could not read float array, child %s.n", mName->mString, node->mName->mString));
  2762. return FALSE;
  2763. }
  2764. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2765. {
  2766. U64 float_bits = ((U64 *)float_array)[pos];
  2767. float_checksum ^= ((float_bits & 0xfffffff000000000ll) >> 32);
  2768. }
  2769. }
  2770. }
  2771. break;
  2772. case TYPE_STRING:
  2773. break;
  2774. case TYPE_UUID:
  2775. {
  2776. LLUUID uuid_array[30];
  2777. if (node->getUUIDValue(node->mLength, uuid_array) < node->mLength)
  2778. {
  2779. error_buffer.append(llformat("ERROR Node %s: Could not read uuid array, child %s.n", mName->mString, node->mName->mString));
  2780. return FALSE;
  2781. }
  2782. for (U32 pos=0; pos<(U32)node->mLength; ++pos)
  2783. {
  2784. for (S32 byte=0; byte<UUID_BYTES; ++byte)
  2785. {
  2786. uuid_checksum.mData[byte] ^= uuid_array[pos].mData[byte];
  2787. }
  2788. }
  2789. }
  2790. break;
  2791. case TYPE_NODEREF:
  2792. {
  2793. LLXMLNode *node_array[30];
  2794. if (node->getNodeRefValue(node->mLength, node_array) < node->mLength)
  2795. {
  2796. error_buffer.append(llformat("ERROR Node %s: Could not read node ref array, child %s.n", mName->mString, node->mName->mString));
  2797. return FALSE;
  2798. }
  2799. for (U32 pos=0; pos<node->mLength; ++pos)
  2800. {
  2801. const char *node_name = node_array[pos]->mName->mString;
  2802. for (U32 pos2=0; pos2<strlen(node_name); ++pos2) /* Flawfinder: ignore */
  2803. {
  2804. U32 hash_contrib = U32(node_name[pos2]) << ((pos2 % 4) * 8);
  2805. noderef_checksum ^= hash_contrib;
  2806. }
  2807. }
  2808. }
  2809. break;
  2810. }
  2811. }
  2812. LLXMLNodePtr checksum_node;
  2813. // Compare checksums
  2814. {
  2815. U32 node_integer_checksum = 0;
  2816. if (!getAttribute("integer_checksum", checksum_node, FALSE) || 
  2817. checksum_node->getUnsignedValue(1, &node_integer_checksum, ENCODING_HEX) != 1)
  2818. {
  2819. error_buffer.append(llformat("ERROR Node %s: Integer checksum missing.n", mName->mString));
  2820. return FALSE;
  2821. }
  2822. if (node_integer_checksum != integer_checksum)
  2823. {
  2824. error_buffer.append(llformat("ERROR Node %s: Integer checksum mismatch: read %X / calc %X.n", mName->mString, node_integer_checksum, integer_checksum));
  2825. return FALSE;
  2826. }
  2827. }
  2828. {
  2829. U64 node_long_checksum = 0;
  2830. if (!getAttribute("long_checksum", checksum_node, FALSE) || 
  2831. checksum_node->getLongValue(1, &node_long_checksum, ENCODING_HEX) != 1)
  2832. {
  2833. error_buffer.append(llformat("ERROR Node %s: Long Integer checksum missing.n", mName->mString));
  2834. return FALSE;
  2835. }
  2836. if (node_long_checksum != long_checksum)
  2837. {
  2838. U32 *pp1 = (U32 *)&node_long_checksum;
  2839. U32 *pp2 = (U32 *)&long_checksum;
  2840. error_buffer.append(llformat("ERROR Node %s: Long Integer checksum mismatch: read %08X%08X / calc %08X%08X.n", mName->mString, pp1[1], pp1[0], pp2[1], pp2[0]));
  2841. return FALSE;
  2842. }
  2843. }
  2844. {
  2845. U32 node_bool_true_count = 0;
  2846. if (!getAttribute("bool_true_count", checksum_node, FALSE) || 
  2847. checksum_node->getUnsignedValue(1, &node_bool_true_count, ENCODING_HEX) != 1)
  2848. {
  2849. error_buffer.append(llformat("ERROR Node %s: Boolean checksum missing.n", mName->mString));
  2850. return FALSE;
  2851. }
  2852. if (node_bool_true_count != bool_true_count)
  2853. {
  2854. error_buffer.append(llformat("ERROR Node %s: Boolean checksum mismatch: read %X / calc %X.n", mName->mString, node_bool_true_count, bool_true_count));
  2855. return FALSE;
  2856. }
  2857. }
  2858. {
  2859. LLUUID node_uuid_checksum;
  2860. if (!getAttribute("uuid_checksum", checksum_node, FALSE) || 
  2861. checksum_node->getUUIDValue(1, &node_uuid_checksum) != 1)
  2862. {
  2863. error_buffer.append(llformat("ERROR Node %s: UUID checksum missing.n", mName->mString));
  2864. return FALSE;
  2865. }
  2866. if (node_uuid_checksum != uuid_checksum)
  2867. {
  2868. error_buffer.append(llformat("ERROR Node %s: UUID checksum mismatch: read %s / calc %s.n", mName->mString, node_uuid_checksum.asString().c_str(), uuid_checksum.asString().c_str()));
  2869. return FALSE;
  2870. }
  2871. }
  2872. {
  2873. U32 node_noderef_checksum = 0;
  2874. if (!getAttribute("noderef_checksum", checksum_node, FALSE) || 
  2875. checksum_node->getUnsignedValue(1, &node_noderef_checksum, ENCODING_HEX) != 1)
  2876. {
  2877. error_buffer.append(llformat("ERROR Node %s: Node Ref checksum missing.n", mName->mString));
  2878. return FALSE;
  2879. }
  2880. if (node_noderef_checksum != noderef_checksum)
  2881. {
  2882. error_buffer.append(llformat("ERROR Node %s: Node Ref checksum mismatch: read %X / calc %X.n", mName->mString, node_noderef_checksum, noderef_checksum));
  2883. return FALSE;
  2884. }
  2885. }
  2886. {
  2887. U32 node_float_checksum = 0;
  2888. if (!getAttribute("float_checksum", checksum_node, FALSE) || 
  2889. checksum_node->getUnsignedValue(1, &node_float_checksum, ENCODING_HEX) != 1)
  2890. {
  2891. error_buffer.append(llformat("ERROR Node %s: Float checksum missing.n", mName->mString));
  2892. return FALSE;
  2893. }
  2894. if (node_float_checksum != float_checksum)
  2895. {
  2896. error_buffer.append(llformat("ERROR Node %s: Float checksum mismatch: read %X / calc %X.n", mName->mString, node_float_checksum, float_checksum));
  2897. return FALSE;
  2898. }
  2899. }
  2900. return TRUE;
  2901. }
  2902. LLXMLNodePtr LLXMLNode::getFirstChild() const
  2903. {
  2904. if (mChildren.isNull()) return NULL;
  2905. LLXMLNodePtr ret = mChildren->head;
  2906. return ret;
  2907. }
  2908. LLXMLNodePtr LLXMLNode::getNextSibling() const
  2909. {
  2910. LLXMLNodePtr ret = mNext;
  2911. return ret;
  2912. }
  2913. std::string LLXMLNode::getSanitizedValue() const 
  2914. if (mIsAttribute) 
  2915. {
  2916. return getValue() ;
  2917. }
  2918. else 
  2919. {
  2920. return getTextContents(); 
  2921. }
  2922. }
  2923. std::string LLXMLNode::getTextContents() const
  2924. {
  2925. std::string msg;
  2926. std::string contents = mValue;
  2927. std::string::size_type n = contents.find_first_not_of(" tn");
  2928. if (n != std::string::npos && contents[n] == '"')
  2929. {
  2930. // Case 1: node has quoted text
  2931. S32 num_lines = 0;
  2932. while(1)
  2933. {
  2934. // mContents[n] == '"'
  2935. ++n;
  2936. std::string::size_type t = n;
  2937. std::string::size_type m = 0;
  2938. // fix-up escaped characters
  2939. while(1)
  2940. {
  2941. m = contents.find_first_of("\"", t); // find first  or "
  2942. if ((m == std::string::npos) || (contents[m] == '"'))
  2943. {
  2944. break;
  2945. }
  2946. contents.erase(m,1);
  2947. t = m+1;
  2948. }
  2949. if (m == std::string::npos)
  2950. {
  2951. break;
  2952. }
  2953. // mContents[m] == '"'
  2954. num_lines++;
  2955. msg += contents.substr(n,m-n) + "n";
  2956. n = contents.find_first_of(""", m+1);
  2957. if (n == std::string::npos)
  2958. {
  2959. if (num_lines == 1)
  2960. {
  2961. msg.erase(msg.size()-1); // remove "n" if only one line
  2962. }
  2963. break;
  2964. }
  2965. }
  2966. }
  2967. else
  2968. {
  2969. // Case 2: node has embedded text (beginning and trailing whitespace trimmed)
  2970. std::string::size_type start = mValue.find_first_not_of(" tn");
  2971. if (start != mValue.npos)
  2972. {
  2973. std::string::size_type end = mValue.find_last_not_of(" tn");
  2974. if (end != mValue.npos)
  2975. {
  2976. msg = mValue.substr(start, end+1-start);
  2977. }
  2978. else
  2979. {
  2980. msg = mValue.substr(start);
  2981. }
  2982. }
  2983. // Convert any internal CR to LF
  2984. msg = utf8str_removeCRLF(msg);
  2985. }
  2986. return msg;
  2987. }
  2988. void LLXMLNode::setLineNumber(S32 line_number)
  2989. {
  2990. mLineNumber = line_number;
  2991. }
  2992. S32 LLXMLNode::getLineNumber()
  2993. {
  2994. return mLineNumber;
  2995. }