56 if(expat_parser !=
nullptr) {
57 XML_ParserFree(expat_parser);
58 expat_parser =
nullptr;
60 if(xml_buffer !=
nullptr) {
74 virtual bool Parse(
void) {
79 EXPATMM_SSIZE_T bytes_read;
81 while((bytes_read = read_block()) >= 0) {
83 XML_Status local_status =
84 XML_Parse(expat_parser, getReadBuffer(),
int(bytes_read), XML_FALSE);
86 if(local_status != XML_STATUS_OK) {
87 set_status(local_status);
92 if(getLastError() == XML_ERROR_FINISHED)
98 if((getStatus() == XML_STATUS_OK) || (getLastError() == XML_ERROR_FINISHED)) {
99 XML_Status local_status = XML_Parse(expat_parser, getBuffer(), 0, XML_TRUE);
100 if(local_status != XML_STATUS_OK) {
101 set_status(local_status);
113 virtual bool Ready(
void)
const {
116 virtual XML_Error getLastError(
void)
const {
119 virtual XML_Status getStatus(
void)
const {
122 virtual XML_Size getLastErrorLine(
void)
const {
123 return last_error_line;
125 virtual XML_Size getLastErrorColumn(
void)
const {
126 return last_error_column;
128 virtual std::string getLastErrorMessage(
void)
const {
129 return last_error_message;
135 explicit StackEl(
const char* nm) : name(nm) {}
137 XML_Size start_index;
138 std::map<std::string,std::string> attributes;
141 std::vector<StackEl> m_path;
143 virtual XML_Char *getBuffer(
void) {
146 virtual const char *getReadBuffer(
void) {
149 virtual size_t getBlockSize(
void) {
150 return xml_buffer_size;
179 virtual EXPATMM_SSIZE_T read_block(
void) {
180 last_error = XML_ERROR_NO_ELEMENTS;
181 status = XML_STATUS_ERROR;
185 virtual void setReadiness(
bool ready) {
186 valid_parser = ready;
188 virtual void setStatus(XML_Status new_status) {
191 virtual void setLastError(XML_Error new_last_error) {
192 last_error = new_last_error;
196 virtual void StartElement(
const XML_Char *,
const XML_Char **) {}
197 virtual void EndElement(
const XML_Char *) {}
198 virtual void CharacterData(
const XML_Char *,
int) {}
199 virtual void ProcessingInstruction(
const XML_Char *,
const XML_Char *) {}
200 virtual void CommentData(
const XML_Char *) {}
201 virtual void DefaultHandler(
const XML_Char *,
int) {}
202 virtual void CDataStart(
void) {}
203 virtual void CDataEnd(
void) {}
206 XML_Parser expat_parser;
211 XML_Char *xml_buffer;
212 size_t xml_buffer_size;
218 void set_status(XML_Status ls) {
220 last_error = XML_GetErrorCode(expat_parser);
221 last_error_line = XML_GetCurrentLineNumber(expat_parser);
222 last_error_column= XML_GetCurrentColumnNumber(expat_parser);
223 std::ostringstream oss;
224 oss << XML_ErrorString(last_error) <<
225 " at line " << last_error_line <<
" column " <<
227 last_error_message = oss.str();
231 XML_Error last_error;
232 XML_Size last_error_line{0};
233 XML_Size last_error_column{0};
234 std::string last_error_message;
241 static void _element_start_handler(
void *userData,
const XML_Char *name,
242 const XML_Char **atts) {
245 me->m_path.emplace_back(name);
246 StackEl& lastelt = me->m_path.back();
247 lastelt.start_index = XML_GetCurrentByteIndex(me->expat_parser);
248 for (
int i = 0; atts[i] !=
nullptr; i += 2) {
249 lastelt.attributes[atts[i]] = atts[i+1];
251 me->StartElement(name, atts);
254 static void _element_end_handler(
void *userData,
const XML_Char *name) {
257 me->EndElement(name);
258 me->m_path.pop_back();
261 static void _character_data_handler(
void *userData,
262 const XML_Char *s,
int len) {
264 if(me !=
nullptr) me->CharacterData(s, len);
266 static void _processing_instr_handler(
void *userData,
267 const XML_Char *target,
268 const XML_Char *data) {
270 if(me !=
nullptr) me->ProcessingInstruction(target, data);
272 static void _comment_handler(
void *userData,
const XML_Char *data) {
274 if(me !=
nullptr) me->CommentData(data);
276 static void _default_handler(
void *userData,
const XML_Char *s,
int len) {
278 if(me !=
nullptr) me->DefaultHandler(s, len);
280 static void _cdata_start_handler(
void *userData) {
282 if(me !=
nullptr) me->CDataStart();
284 static void _cdata_end_handler(
void *userData) {
286 if(me !=
nullptr) me->CDataEnd();
289 void register_default_handlers() {
290 XML_SetElementHandler(expat_parser, &_element_start_handler,
291 &_element_end_handler);
292 XML_SetCharacterDataHandler(expat_parser, &_character_data_handler);
293 XML_SetProcessingInstructionHandler(expat_parser,
294 &_processing_instr_handler);
295 XML_SetCommentHandler(expat_parser, &_comment_handler);
296 XML_SetCdataSectionHandler(expat_parser, &_cdata_start_handler,
297 &_cdata_end_handler);
298 XML_SetDefaultHandler(expat_parser, &_default_handler);
301 void init(
size_t chunk_size = 0) {
302 valid_parser =
false;
303 expat_parser =
nullptr;
304 xml_buffer_size = chunk_size ? chunk_size : 10240;
305 xml_buffer =
new XML_Char[xml_buffer_size];
306 if(xml_buffer ==
nullptr)
308 expat_parser = XML_ParserCreate(
nullptr);
310 if(expat_parser ==
nullptr) {
311 delete [] xml_buffer;
312 xml_buffer =
nullptr;
315 status = XML_STATUS_OK;
316 last_error = XML_ERROR_NONE;
318 memset(xml_buffer, 0, xml_buffer_size *
sizeof(XML_Char));
322 XML_SetUserData(expat_parser,
this);
323 register_default_handlers();