contrib/brl/bbas/bxml/bxml_read.cxx

Go to the documentation of this file.
00001 // This is brl/bbas/bxml/bxml_read.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Matt Leotta
00008 // \date   October 5, 2006
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 // anonymous namespace
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 //: Handle the start of elements
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   // set all the attributes
00060   for (int i=0; atts[i]; i+=2) {
00061     element->set_attribute(atts[i],atts[i+1]);
00062   }
00063 
00064   // add this element to the current element or document
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 //: Handle the start of elements
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 //: Handle character data
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 //: Handle the XML declaration
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 }; // end anonymous namespace
00117 
00118 
00119 //: Read the entire contents of \p filepath into an XML document class
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 //: Read the entire data stream \p is into an XML document class
00128 bxml_document bxml_read(vcl_istream& is)
00129 {
00130   bxml_expat_parser parser;
00131 
00132   char buf[4096];
00133   //char buf[9096];
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 //: Constructor
00161 bxml_stream_read::bxml_stream_read(int max_depth)
00162   : p_(new pimpl(max_depth))
00163 {
00164 }
00165 
00166 //: Destructor
00167 bxml_stream_read::~bxml_stream_read()
00168 {
00169   delete p_;
00170 }
00171 
00172 
00173 //: Reset the state of the reader
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 //: Read the next element
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 

Generated on Sun Sep 7 05:21:10 2008 for contrib/brl/bbas/bxml by  doxygen 1.5.1