32 #include <utf8cpp/utf8.h>
33 #if __has_include(<utf8cpp/cpp17.h>)
34 #include <utf8cpp/cpp17.h>
35 #define LIBXCKS_UTF8CPP_HAS_STRING_VIEW
56 XMLParserException::XMLParserException() noexcept
71 this->message = source.message;
99 XMLParserException::XMLParserException(
const std::string& msg) noexcept
109 XMLParserException::~XMLParserException()
122 string XMLParserException::what() const noexcept
136 string XMLParserException::getMessage() const noexcept
148 void XMLParserException::setMessage(
const string& msg) noexcept
168 void XMLParserAttributes::addAttribute(
const std::string& name,
const std::string& value)
185 attributes.emplace_back(attribute);
193 void XMLParserAttributes::clear()
196 attributes.shrink_to_fit();
207 int XMLParserAttributes::getIndex(
const string& name)
const
209 bool notFound =
true;
210 const int s = attributes.size();
212 while (notFound && i < s)
214 if (name == attributes[i].first)
220 return notFound ? Not_Found : i;
230 size_t XMLParserAttributes::getCount()
const
232 return attributes.size();
245 bool XMLParserAttributes::getName(
size_t index,
string& name)
const
247 if (index < 0 || index >= getCount())
250 name = attributes[index].first;
264 bool XMLParserAttributes::getValue(
size_t index, std::string& value)
const
266 if (index < 0 || index >= getCount())
269 value = attributes[index].second;
284 bool XMLParserAttributes::getValue(
const std::string& name, std::string& value)
const
286 int idx = getIndex(name);
287 if (idx != Not_Found)
289 value = attributes[idx].second;
305 static constexpr
size_t DEF_BUFF_SIZE = 4096;
314 inline static string convXMLCharStrtoUTF8Charset(
const XML_Char* xlmStr)
316 #if defined(XML_UNICODE)
317 assert(
sizeof(XML_Char) == 2);
318 #if defined(LIBXCKS_UTF8CPP_HAS_STRING_VIEW)
319 return utf8::utf16to8(u16string_view(
reinterpret_cast<const char16_t*
>(xlmStr)));
321 return utf8::utf16to8(u16string(
reinterpret_cast<const char16_t*
>(xlmStr)));
324 return string(xlmStr);
333 XMLParser::XMLParser()
343 XMLParser::~XMLParser()
345 if (parser !=
nullptr)
346 XML_ParserFree(parser);
366 bool XMLParser::initParser()
368 if (parser !=
nullptr)
369 XML_ParserFree(parser);
372 parser = XML_ParserCreate(
nullptr);
373 if (parser !=
nullptr)
376 XML_SetUserData(parser,
this);
377 XML_SetElementHandler(parser, XMLParser::startElementHandler, XMLParser::endElementHandler);
378 XML_SetCharacterDataHandler(parser, XMLParser::characterDataHandler);
381 return (parser !=
nullptr);
407 void XMLParser::endElement(
const string& name)
420 void XMLParser::characters(
const string& chars)
436 void XMLParser::fatalError(XML_Error errorCode,
const string& errorMessage,
int line,
int column) noexcept
452 void XMLCALL XMLParser::startElementHandler(
void* userData,
const XML_Char* name,
const XML_Char** atts)
459 for (
int i = 0; atts[i] !=
nullptr; i += 2)
475 void XMLCALL XMLParser::endElementHandler(
void* userData,
const XML_Char* name)
478 XMLParser* p =
reinterpret_cast<XMLParser*
>(userData);
481 p->setDepth(p->getDepth() - 1);
484 p->endElement(convXMLCharStrtoUTF8Charset(name));
493 void XMLCALL XMLParser::characterDataHandler(
void* userData,
const XML_Char* s,
int len)
496 XMLParser* p =
reinterpret_cast<XMLParser*
>(userData);
499 XML_Char* str =
new XML_Char[len + 1];
500 memcpy(str, s,
sizeof(XML_Char) * len);
501 #if defined(XML_UNICODE)
506 string chData = convXMLCharStrtoUTF8Charset(str);
508 p->characters(chData);
518 void XMLParser::setDepth(
int depth)
530 int XMLParser::getDepth()
const
544 bool XMLParser::parse(
const std::string& filename)
546 ifstream is(filename, ios::in | ios::binary);
561 bool XMLParser::parse(std::istream& is)
570 char buff[DEF_BUFF_SIZE];
574 ios::iostate errorState = ios::goodbit;
575 XML_Status lastXMLError = XML_STATUS_OK;
576 bool parserExceptionLaunched =
false;
577 string exceptionMessage;
580 while (!is.eof() && (errorState & ios::goodbit) == ios::goodbit && lastXMLError == XML_STATUS_OK)
582 read = is.read(buff,
sizeof(
char) * DEF_BUFF_SIZE).gcount();
583 if (read > 0 && read <=
sizeof(
char) * DEF_BUFF_SIZE)
584 lastXMLError = XML_Parse(parser, buff,
static_cast<int>(read),
static_cast<int>(XML_FALSE));
585 errorState = is.rdstate();
590 exceptionMessage = e.
what();
591 parserExceptionLaunched =
true;
595 if (parserExceptionLaunched || ((errorState & ios::goodbit) != ios::goodbit && (errorState & ios::eofbit) != ios::eofbit))
596 XML_StopParser(parser, XML_FALSE);
598 if (lastXMLError == XML_STATUS_OK)
599 lastXMLError = XML_Parse(parser, buff, 0,
static_cast<int>(XML_TRUE));
601 if (lastXMLError != XML_STATUS_OK)
603 XML_Error err = XML_GetErrorCode(parser);
604 if (exceptionMessage.empty())
605 fatalError(err, convXMLCharStrtoUTF8Charset(XML_ErrorString(err)), XML_GetCurrentLineNumber(parser), XML_GetCurrentColumnNumber(parser));
607 fatalError(err, exceptionMessage, XML_GetCurrentLineNumber(parser), XML_GetCurrentColumnNumber(parser));
610 return ((!parserExceptionLaunched) && (lastXMLError == XML_STATUS_OK));
Manages elements' attributes.
void addAttribute(const std::string &name, const std::string &value)
Adds an attribute to the end of the list.
An exception class for the XML parser.
virtual std::string what() const noexcept
Returns the explanatory string.
std::string message
The message of the exception.
A very simple XML parser.
virtual void startElement(const std::string &name, const XMLParserAttributes &atts) noexcept(false)
Receives notification of the beginning of an element.
int getDepth() const
Returns the current depth in XML tree structure.
A very simple XML Parser.
std::pair< std::string, std::string > XMLParserAttribute
An attribute and its value.