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