00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010 #include "bxml_read.h"
00011 #include <vcl_deque.h>
00012 #include <vcl_utility.h>
00013 #include <vcl_fstream.h>
00014 #include <vcl_cassert.h>
00015 #include <expatpplib.h>
00016
00017
00018 namespace {
00019
00020 class bxml_expat_parser : public expatpp
00021 {
00022 public:
00023 bxml_expat_parser(bool online = false) : online_mode_(online) {}
00024 virtual void startElement(const XML_Char* name, const XML_Char** atts);
00025 virtual void endElement(const XML_Char* name);
00026 virtual void charData(const XML_Char*, int len);
00027 virtual void xmlDecl( const XML_Char *version,
00028 const XML_Char *encoding,
00029 int standalone);
00030
00031 bxml_document document() const { return document_; }
00032
00033 bool pop_complete_data(bxml_data_sptr& data, unsigned int& depth);
00034
00035 private:
00036 bool online_mode_;
00037 vcl_vector<bxml_data_sptr> stack_;
00038 vcl_deque<vcl_pair<bxml_data_sptr,unsigned int> > complete_;
00039 bxml_document document_;
00040 };
00041
00042 bool bxml_expat_parser::pop_complete_data(bxml_data_sptr& data, unsigned int& depth)
00043 {
00044 if (complete_.empty())
00045 return false;
00046
00047 data = complete_.front().first;
00048 depth = complete_.front().second;
00049 complete_.pop_front();
00050 return true;
00051 }
00052
00053
00054
00055 void bxml_expat_parser::startElement(const XML_Char* name, const XML_Char** atts)
00056 {
00057 bxml_element* element = new bxml_element(name);
00058 bxml_data_sptr data(element);
00059
00060 for (int i=0; atts[i]; i+=2) {
00061 element->set_attribute(atts[i],atts[i+1]);
00062 }
00063
00064
00065 if (stack_.empty()) {
00066 if (!online_mode_) {
00067 document_.set_root_element(data);
00068 stack_.push_back(data);
00069 }
00070 else
00071 stack_.push_back(NULL);
00072 }
00073 else{
00074 if (stack_.back().ptr()) {
00075 bxml_element* parent = static_cast<bxml_element*>(stack_.back().ptr());
00076 parent->append_data(data);
00077 }
00078 stack_.push_back(data);
00079 }
00080 }
00081
00082
00083
00084 void bxml_expat_parser::endElement(const XML_Char* name)
00085 {
00086 if (stack_.back().ptr()) {
00087 bxml_element* element = static_cast<bxml_element*>(stack_.back().ptr());
00088 assert(element->name() == vcl_string(name));
00089 complete_.push_back(vcl_pair<bxml_data_sptr,unsigned int>(stack_.back(),stack_.size()-1));
00090 }
00091 stack_.pop_back();
00092 }
00093
00094
00095
00096 void bxml_expat_parser::charData(const XML_Char* text, int len)
00097 {
00098 assert(!stack_.empty());
00099 if (stack_.back().ptr()) {
00100 bxml_element* parent = static_cast<bxml_element*>(stack_.back().ptr());
00101 parent->append_text(vcl_string(text,len));
00102 }
00103 }
00104
00105
00106
00107 void bxml_expat_parser::xmlDecl( const XML_Char *version,
00108 const XML_Char *encoding,
00109 int standalone)
00110 {
00111 document_.set_version(version);
00112 document_.set_encoding(encoding);
00113 document_.set_standalone(standalone != 0);
00114 }
00115
00116 };
00117
00118
00119
00120 bxml_document bxml_read(const vcl_string& filepath)
00121 {
00122 vcl_ifstream file(filepath.c_str());
00123 return bxml_read(file);
00124 }
00125
00126
00127
00128 bxml_document bxml_read(vcl_istream& is)
00129 {
00130 bxml_expat_parser parser;
00131
00132 char buf[4096];
00133
00134 int done;
00135
00136 while (is.good()) {
00137 is.get(buf,sizeof(buf),0);
00138 unsigned int n = is.gcount();
00139
00140 done = (n+1 < sizeof(buf)) ? 1 : 0;
00141
00142 if (parser.XML_Parse(buf,n,done) != XML_STATUS_OK ) {
00143 vcl_cerr << "Error parsing\n";
00144 break;
00145 }
00146 }
00147 return parser.document();
00148 }
00149
00150
00151 class bxml_stream_read::pimpl
00152 {
00153 public:
00154 pimpl(unsigned int max_depth) : parser(true), depth(max_depth) {}
00155
00156 bxml_expat_parser parser;
00157 unsigned int depth;
00158 };
00159
00160
00161 bxml_stream_read::bxml_stream_read(int max_depth)
00162 : p_(new pimpl(max_depth))
00163 {
00164 }
00165
00166
00167 bxml_stream_read::~bxml_stream_read()
00168 {
00169 delete p_;
00170 }
00171
00172
00173
00174 void bxml_stream_read::reset()
00175 {
00176 if (p_) {
00177 unsigned int depth = p_->depth;
00178 delete p_;
00179 p_ = new pimpl(depth);
00180 }
00181 }
00182
00183
00184
00185 bxml_data_sptr
00186 bxml_stream_read::next_element(vcl_istream& is, unsigned int& depth)
00187 {
00188 char buf[4096];
00189 int done = 0;
00190
00191 bxml_data_sptr data = NULL;
00192 depth = 0;
00193 while ( p_->parser.pop_complete_data(data, depth) )
00194 if (depth <= p_->depth)
00195 return data;
00196
00197 while (is.good()){
00198 is.get(buf,sizeof(buf),0);
00199 int n = is.gcount();
00200 if (p_->parser.XML_Parse(buf,n,done) != XML_STATUS_OK ) {
00201 vcl_cerr << "Error parsing\n";
00202 break;
00203 }
00204
00205 while ( p_->parser.pop_complete_data(data, depth) )
00206 if (depth <= p_->depth)
00207 return data;
00208 }
00209 return NULL;
00210 }
00211