00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "judo.hpp"
00030 using namespace judo;
00031 using namespace std;
00032
00033
00034 ElementStream::ElementStream(ElementStreamEventListener* l)
00035 : _parser_ready(false), _event_listener(l)
00036 {
00037 reset();
00038 }
00039
00040 ElementStream::~ElementStream()
00041 {
00042 XML_ParserFree(_parser);
00043 }
00044
00050 void ElementStream::push(const char* data, int datasz)
00051 {
00052 assert(_document_ended != true);
00053 if (!XML_Parse(_parser, data, datasz, 0))
00054 {
00055 throw exception::ParserError(XML_GetErrorCode(_parser));
00056 }
00057 }
00058
00062 void ElementStream::reset()
00063 {
00064
00065 _document_started = false;
00066 _document_ended = false;
00067
00068
00069
00070 if (_parser_ready)
00071 XML_ParserFree(_parser);
00072 _parser = XML_ParserCreate(NULL);
00073 _parser_ready = true;
00074
00075
00076 XML_SetUserData(_parser, this);
00077 XML_SetElementHandler(_parser, &ElementStream::onStartElement,
00078 &ElementStream::onEndElement);
00079 XML_SetCharacterDataHandler(_parser, &ElementStream::onCDATA);
00080 }
00081
00082 void ElementStream::onStartElement(void* userdata, const char* name, const char** attribs)
00083 {
00084 ElementStream* ts = (ElementStream*)userdata;
00085
00086
00087 if (ts->_document_started)
00088 {
00089 if (!ts->_element_stack.empty())
00090 ts->_element_stack.push_back(ts->_element_stack.back()->addElement(name, attribs));
00091 else
00092 ts->_element_stack.push_back(new Element(name, attribs));
00093 }
00094
00095
00096 else
00097 {
00098 Element* root = new Element(name, attribs);
00099 ts->_document_started = true;
00100 ts->_event_listener->onDocumentStart(root);
00101 }
00102 }
00103
00104 void ElementStream::onEndElement(void* userdata, const char* name)
00105 {
00106 ElementStream* ts = (ElementStream*)userdata;
00107
00108 switch (ts->_element_stack.size())
00109 {
00110
00111
00112 case 1:
00113 ts->_event_listener->onElement(ts->_element_stack.back());
00114 ts->_element_stack.pop_back();
00115 break;
00116
00117
00118 case 0:
00119 ts->_event_listener->onDocumentEnd();
00120 ts->_document_ended = true;
00121 break;
00122 default:
00123 ts->_element_stack.pop_back();
00124 }
00125 }
00126
00127 void ElementStream::onCDATA(void* userdata, const char* cdata, int cdatasz)
00128 {
00129 ElementStream* ts = (ElementStream*)userdata;
00130
00131 if (!ts->_element_stack.empty())
00132 ts->_element_stack.back()->addCDATA(cdata, cdatasz, true);
00133 else
00134 ts->_event_listener->onCDATA(new CDATA(cdata, cdatasz, true));
00135 }
00136
00137
00138 class BufferParser
00139 : public ElementStreamEventListener
00140 {
00141 public:
00142 BufferParser()
00143 : _finished(false), _root(NULL), _stream(this)
00144 {}
00145 ~BufferParser()
00146 {
00147 if (!_finished && _root != NULL)
00148 delete _root;
00149 }
00150 Element* process(const char* data)
00151 {
00152 _stream.push(data, strlen(data));
00153 if (!_finished)
00154 throw ElementStream::exception::IncompleteParse();
00155 return _root;
00156 }
00157 void onDocumentStart(Element* t)
00158 { _root = t; }
00159 void onElement(Element* t)
00160 { _root->appendChild(t); }
00161 void onCDATA(CDATA* c)
00162 { _root->appendChild(c); }
00163 void onDocumentEnd()
00164 { _finished = true; }
00165 bool isFinished()
00166 { return _finished; }
00167 private:
00168 bool _finished;
00169 Element* _root;
00170 ElementStream _stream;
00171 };
00172
00176 Element* ElementStream::parseAtOnce(const char* data)
00177 {
00178 BufferParser p;
00179 return p.process(data);
00180 }
00181