llxmlparser.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /**
  2. * @file llxmlparser.cpp
  3. * @brief LLXmlParser implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llxmlparser.h"
  34. LLXmlParser::LLXmlParser()
  35. : mParser(NULL),
  36. mDepth(0),
  37. mAuxErrorString("no error")
  38. {
  39. // Override the document's declared encoding.
  40. mParser = XML_ParserCreate(NULL);
  41. XML_SetUserData(mParser, this);
  42. XML_SetElementHandler(mParser, startElementHandler, endElementHandler);
  43. XML_SetCharacterDataHandler(mParser, characterDataHandler);
  44. XML_SetProcessingInstructionHandler(mParser, processingInstructionHandler);
  45. XML_SetCommentHandler(mParser, commentHandler);
  46. XML_SetCdataSectionHandler(mParser, startCdataSectionHandler,
  47. endCdataSectionHandler);
  48. // This sets the default handler but does not inhibit expansion of internal
  49. // entities. The entity reference will not be passed to the default
  50. // handler.
  51. XML_SetDefaultHandlerExpand(mParser, defaultDataHandler);
  52. XML_SetUnparsedEntityDeclHandler(mParser, unparsedEntityDeclHandler);
  53. }
  54. LLXmlParser::~LLXmlParser()
  55. {
  56. if (mParser)
  57. {
  58. XML_ParserFree(mParser);
  59. mParser = NULL;
  60. }
  61. }
  62. bool LLXmlParser::parseFile(const std::string& path)
  63. {
  64. llassert(!mDepth);
  65. bool success = true;
  66. LLFILE* file = LLFile::open(path, "rb");
  67. if (!file)
  68. {
  69. mAuxErrorString = llformat("Couldn't open file %s", path.c_str());
  70. success = false;
  71. }
  72. else
  73. {
  74. S32 bytes_read = 0;
  75. fseek(file, 0L, SEEK_END);
  76. S32 buffer_size = ftell(file);
  77. fseek(file, 0L, SEEK_SET);
  78. void* buffer = XML_GetBuffer(mParser, buffer_size);
  79. if (!buffer)
  80. {
  81. mAuxErrorString =
  82. llformat("Unable to allocate XML buffer while reading file %s",
  83. path.c_str());
  84. success = false;
  85. }
  86. if (success)
  87. {
  88. bytes_read = (S32)fread(buffer, 1, buffer_size, file);
  89. if (bytes_read <= 0)
  90. {
  91. mAuxErrorString = llformat("Error while reading file %s",
  92. path.c_str());
  93. success = false;
  94. }
  95. }
  96. if (success && !XML_ParseBuffer(mParser, bytes_read, true))
  97. {
  98. mAuxErrorString = llformat("Error while parsing file %s",
  99. path.c_str());
  100. success = false;
  101. }
  102. LLFile::close(file);
  103. }
  104. if (success && mDepth)
  105. {
  106. llwarns << "mDepth not null after parsing: " << path << llendl;
  107. llassert(false);
  108. }
  109. mDepth = 0;
  110. if (!success)
  111. {
  112. llwarns << mAuxErrorString << llendl;
  113. }
  114. return success;
  115. }
  116. // Parses some input. Returns 0 if a fatal error is detected. The last call
  117. // must have is_final true; len may be zero for this call (or any other).
  118. S32 LLXmlParser::parse(const char* buf, int len, int is_final)
  119. {
  120. return XML_Parse(mParser, buf, len, is_final);
  121. }
  122. const char* LLXmlParser::getErrorString()
  123. {
  124. const char* error_string = XML_ErrorString(XML_GetErrorCode(mParser));
  125. if (!error_string)
  126. {
  127. error_string = mAuxErrorString.c_str();
  128. }
  129. return error_string;
  130. }
  131. S32 LLXmlParser::getCurrentLineNumber()
  132. {
  133. return XML_GetCurrentLineNumber(mParser);
  134. }
  135. S32 LLXmlParser::getCurrentColumnNumber()
  136. {
  137. return XML_GetCurrentColumnNumber(mParser);
  138. }
  139. ///////////////////////////////////////////////////////////////////////////////
  140. // Pseudo-private methods. These are only used by internal callbacks.
  141. //static
  142. void LLXmlParser::startElementHandler(void* user_data, const XML_Char* name,
  143. const XML_Char** atts)
  144. {
  145. LLXmlParser* self = (LLXmlParser*)user_data;
  146. if (self)
  147. {
  148. self->startElement(name, atts);
  149. ++self->mDepth;
  150. }
  151. }
  152. //static
  153. void LLXmlParser::endElementHandler(void* user_data, const XML_Char* name)
  154. {
  155. LLXmlParser* self = (LLXmlParser*)user_data;
  156. if (self)
  157. {
  158. --self->mDepth;
  159. self->endElement(name);
  160. }
  161. }
  162. // s is not 0 terminated.
  163. //static
  164. void LLXmlParser::characterDataHandler(void* user_data, const XML_Char* s,
  165. int len)
  166. {
  167. LLXmlParser* self = (LLXmlParser*)user_data;
  168. if (self)
  169. {
  170. self->characterData(s, len);
  171. }
  172. }
  173. // target and data are 0 terminated
  174. //static
  175. void LLXmlParser::processingInstructionHandler(void* user_data,
  176. const XML_Char* target,
  177. const XML_Char* data)
  178. {
  179. LLXmlParser* self = (LLXmlParser*)user_data;
  180. if (self)
  181. {
  182. self->processingInstruction(target, data);
  183. }
  184. }
  185. // data is 0 terminated
  186. //static
  187. void LLXmlParser::commentHandler(void* user_data, const XML_Char* data)
  188. {
  189. LLXmlParser* self = (LLXmlParser*)user_data;
  190. if (self)
  191. {
  192. self->comment(data);
  193. }
  194. }
  195. //static
  196. void LLXmlParser::startCdataSectionHandler(void* user_data)
  197. {
  198. LLXmlParser* self = (LLXmlParser*)user_data;
  199. if (self)
  200. {
  201. ++self->mDepth;
  202. self->startCdataSection();
  203. }
  204. }
  205. //static
  206. void LLXmlParser::endCdataSectionHandler(void* user_data)
  207. {
  208. LLXmlParser* self = (LLXmlParser*)user_data;
  209. if (self)
  210. {
  211. self->endCdataSection();
  212. ++self->mDepth;
  213. }
  214. }
  215. // This is called for any characters in the XML document for which there is no
  216. // applicable handler. This includes both characters that are part of markup
  217. // which is of a kind that is not reported (comments, markup declarations), or
  218. // characters that are part of a construct which could be reported but for
  219. // which no handler has been supplied. The characters are passed exactly as
  220. // they were in the XML document except that they will be encoded in UTF-8.
  221. // Line boundaries are not normalized. Note that a byte order mark character is
  222. // not passed to the default handler. There are no guarantees about how
  223. // characters are divided between calls to the default handler: for example, a
  224. // comment might be split between multiple calls.
  225. //static
  226. void LLXmlParser::defaultDataHandler(void* user_data, const XML_Char* s,
  227. int len)
  228. {
  229. LLXmlParser* self = (LLXmlParser*)user_data;
  230. if (self)
  231. {
  232. self->defaultData(s, len);
  233. }
  234. }
  235. // This is called for a declaration of an unparsed (NDATA) entity. The base
  236. // argument is whatever was set by XML_SetBase. The entity_name, system_id and
  237. // notation_name arguments will never be null. The other arguments may be.
  238. //static
  239. void LLXmlParser::unparsedEntityDeclHandler(void* user_data,
  240. const XML_Char* entity_name,
  241. const XML_Char* base,
  242. const XML_Char* system_id,
  243. const XML_Char* public_id,
  244. const XML_Char* notation_name)
  245. {
  246. LLXmlParser* self = (LLXmlParser*)user_data;
  247. if (self)
  248. {
  249. self->unparsedEntityDecl(entity_name, base, system_id, public_id,
  250. notation_name);
  251. }
  252. }