Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

CTBxmlIStream.cxx

Go to the documentation of this file.
00001 
00006 /*----------------------------------------------------------------------------*/
00007 /* C Tool Box: Designed and implemented by:                                   */
00008 /*    Walter F.J. Mueller   Gesellschaft fuer Schwerionenforschung (GSI)      */
00009 /*                          Planckstrasse 1, D-64291 Darmstadt, Germany       */
00010 /*                  Email:  W.F.J.Mueller@gsi.de                              */
00011 /*                  WWW:    http://www-kp3.gsi.de/www/kp3/people/mueller.html */
00012 /*----------------------------------------------------------------------------*/
00013 
00014 #include <assert.h>
00015 #include <fstream.h>
00016 #include <ctype.h>
00017 
00018 #include "CTB.hxx"
00019 #include "CTB_Trace.hxx"
00020 #include "CTBosFill.hxx"
00021 #include "CTBexceptionBugcheck.hxx"
00022 #include "CTBprintf.hxx"
00023 
00024 #include "CTBxmlIStream.hxx"
00025 
00036 //------------------------------------------+-----------------------------------
00038 
00039 CTBxmlToken::CTBxmlToken(int i_type)
00040   : mi_type(i_type),
00041     m_text(),
00042     m_name(),
00043     m_value(),
00044     m_attribute()
00045 {
00046   CTB_Trace("CTBxmlToken()");
00047 }
00048 
00049 //------------------------------------------+-----------------------------------
00051 
00052 CTBxmlToken::CTBxmlToken(const CTBxmlToken& rhs)
00053   : mi_type(rhs.mi_type),
00054     m_text(rhs.m_text),
00055     m_name(rhs.m_name),
00056     m_value(rhs.m_value),
00057     m_attribute(rhs.m_attribute)
00058 {
00059   CTB_Trace("CTBxmlToken(const CTBxmlToken&)");
00060 }
00061 
00062 //------------------------------------------+-----------------------------------
00064 
00065 CTBxmlToken::CTBxmlToken(CTBxmlToken& rhs, bool b_grab)
00066   : mi_type(rhs.mi_type),
00067     m_text(rhs.m_text,true),
00068     m_name(rhs.m_name,true),
00069     m_value(rhs.m_value,true),
00070     m_attribute(rhs.m_attribute,true)
00071 {
00072   CTB_Trace("CTBxmlToken(CTBxmlToken&, bool)");
00073   rhs.mi_type = invalid;
00074 }
00075 
00076 //------------------------------------------+-----------------------------------
00078 
00079 CTBxmlToken::~CTBxmlToken()
00080 {
00081   CTB_Trace("~CTBxmlToken()");
00082 }
00083 
00084 //------------------------------------------+-----------------------------------
00086 
00087 void CTBxmlToken::Clear()
00088 {
00089   CTB_Trace("CTBxmlToken::Clear()");
00090 
00091   mi_type = invalid;                        // set type to invalid
00092   m_text.Clear();                           // reset all strings
00093   m_name.Clear();
00094   m_value.Clear();
00095   m_attribute.Resize(0);                    // drop attribute list
00096   return;
00097 }
00098 
00099 //------------------------------------------+-----------------------------------
00101 
00102 void CTBxmlToken::Grab(CTBxmlToken& rhs)
00103 {
00104   CTB_Trace("CTBxmlToken::Grab(CTBxmlToken&)");
00105 
00106   mi_type     = rhs.mi_type;
00107   rhs.mi_type = invalid;
00108   m_text.Grab(rhs.m_text);
00109   m_name.Grab(rhs.m_name);
00110   m_value.Grab(rhs.m_value);
00111   m_attribute.Grab(rhs.m_attribute);
00112   return;
00113 }
00114 
00115 //------------------------------------------+-----------------------------------
00117 
00118 void CTBxmlToken::ToStream(ostream& os) const
00119 {
00120   CTBint i_nattr = m_attribute.Size();
00121   
00122   os << "XML token -- ";
00123   switch (mi_type) {
00124   case invalid:
00125     os << "invalid  -- \"" << m_text.Escape()  << "\"\n";
00126     break;
00127   case fail:
00128     os << "fail     --\n";
00129     break;
00130   case eof:
00131     os << "eof      --\n";
00132     break;
00133   case data:
00134     os << "data     -- \"" << m_value.Escape() << "\"\n";
00135     break;
00136   case starttag:
00137     os << "starttag -- <" << m_name << ">\n";
00138     break;
00139   case endtag:
00140     os << "endtag   -- </" << m_name << ">\n";
00141     break;
00142   case emptytag:
00143     os << "emptytag -- <" << m_name << "/>\n";
00144     break;
00145   case comment:
00146     os << "comment  -- " << m_text.Escape()  << "\n";
00147     break;
00148   case xml:
00149     os << "xml      -- <?xml?>\n";
00150     break;
00151   case pi:
00152     os << "pi       -- <?" << m_name << "?>\n";
00153     break;
00154   default:
00155     os << "?? unknown ??\n";
00156     break;
00157   }
00158   
00159   for (CTBint i = 0; i < i_nattr; i++) {
00160     os << "          [" << CTBprintf(i,"d",3) << "]: "
00161        << m_attribute[i].Key();
00162     if (!m_attribute[i].Value().IsNull()) {
00163       os << "=\"" << m_attribute[i].Value() << "\"";
00164     }
00165     os << "\n";
00166   }
00167 
00168   return;
00169 }
00170 
00171 //------------------------------------------+-----------------------------------
00173 
00174 void CTBxmlToken::Dump(int i_indent, ostream& os, const char* p_text) const
00175 {
00176   CTBosFill bl(i_indent);
00177   
00178   os << bl << "--CTBxmlToken ";
00179   if (p_text) os << p_text;
00180   os << " @ " << this << endl;
00181 
00182   os << bl << "    mi_type:     " << mi_type << endl;
00183   m_text.Dump(i_indent+2,os,"m_text");
00184   m_name.Dump(i_indent+2,os,"m_name");
00185   m_value.Dump(i_indent+2,os,"m_value");
00186   m_attribute.Dump(i_indent+2,os,"m_attribute");
00187 
00188   return;
00189 }
00190 
00191 //------------------------------------------+-----------------------------------
00193 
00194 CTBxmlToken& CTBxmlToken::operator=(const CTBxmlToken& rhs)
00195 {
00196   CTB_Trace("CTBxmlToken::operator=(const CTBxmlToken&)");
00197 
00198   mi_type     = rhs.mi_type;
00199   m_text      = rhs.m_text;
00200   m_name      = rhs.m_name;
00201   m_value     = rhs.m_value;
00202   m_attribute = rhs.m_attribute;
00203   return *this;
00204 }
00205 
00206 //##############################################################################
00207 
00213 //------------------------------------------+-----------------------------------
00215 
00216 CTBxmlIStream::CTBxmlIStream()
00217   : mp_is(0),
00218     mb_attached(false),
00219     mb_trimwhite(false),
00220     mb_dropwhite(false),
00221     mb_fail(false),
00222     mb_bad(false),
00223     mb_eof(false),
00224     mp_iss(0),
00225     m_data(),
00226     m_tagstack(8),
00227     mi_taglevel(0),
00228     m_untoken()
00229 {
00230   CTB_Trace("CTBxmlIStream()");
00231 }
00232 
00233 //------------------------------------------+-----------------------------------
00235 
00236 CTBxmlIStream::CTBxmlIStream(istream* p_is)
00237   : mp_is(p_is),
00238     mb_attached(p_is), 
00239     mb_trimwhite(false),
00240     mb_dropwhite(false),
00241     mb_fail(false),
00242     mb_bad(false),
00243     mb_eof(false),
00244     mp_iss(0),
00245     m_data(),
00246     m_tagstack(8),
00247     mi_taglevel(0),
00248     m_untoken()
00249 {
00250   CTB_Trace("CTBxmlIStream(istream*)");
00251 }
00252 
00253 //------------------------------------------+-----------------------------------
00255 
00256 CTBxmlIStream::CTBxmlIStream(const char* c_filename, int i_mode, int i_prot)
00257   : mp_is(0),
00258     mb_attached(false),
00259     mb_trimwhite(false),
00260     mb_dropwhite(false),
00261     mb_fail(false),
00262     mb_bad(false),
00263     mb_eof(false),
00264     mp_iss(0),
00265     m_data(),
00266     m_tagstack(8),
00267     mi_taglevel(0),
00268     m_untoken()
00269 {
00270   CTB_Trace("CTBxmlIStream(const char*, int, int)");
00271   Open(c_filename,i_mode,i_prot);
00272 }
00273 
00274 //------------------------------------------+-----------------------------------
00276 
00277 CTBxmlIStream::~CTBxmlIStream()
00278 {
00279   CTB_Trace("~CTBxmlIStream()");
00280   Close();
00281 }
00282 
00283 //------------------------------------------+-----------------------------------
00285 
00286 void CTBxmlIStream::Attach(istream* p_is)
00287 {
00288   CTB_Trace("CTBxmlIStream::Attach(istream*)");
00289 
00290   Close();
00291   mp_is       = p_is;
00292   mb_attached = p_is;
00293   return;
00294 }
00295 
00296 //------------------------------------------+-----------------------------------
00298 
00299 void CTBxmlIStream::Open(const char* c_filename, int i_mode, int i_prot)
00300 {
00301   CTB_Trace("CTBxmlIStream::Open(const char*, int, int)");
00302 
00303   if (c_filename[0] == '-' && c_filename[1] == 0) { // "-" --> use cout
00304     Attach(&cin);
00305 
00306   } else {
00307     Close();
00308     mp_is = new ifstream(c_filename,i_mode,i_prot);
00309     if (mp_is->bad()) {
00310       delete mp_is;
00311       mp_is   = 0;
00312       mb_fail = true;
00313       mb_bad  = true;
00314     }
00315   }
00316   return;
00317 }
00318 
00319 //------------------------------------------+-----------------------------------
00321 
00322 void CTBxmlIStream::Close()
00323 {
00324   CTB_Trace("CTBxmlIStream::Close()");
00325 
00326   if (mp_is) {                              // is noop if no stream open
00327     if (!mb_attached) delete mp_is;         // ??? how to handle error on close
00328     mp_is       = 0;                        // drop reference
00329     mb_attached = false;
00330     mb_fail     = false;
00331     mb_bad      = false;
00332     mb_eof      = false;
00333     delete mp_iss;
00334     mp_iss = 0;
00335     m_data.Clear();
00336     mi_taglevel = 0;
00337     m_untoken.Clear();
00338     m_token.Clear();
00339   }
00340   return;
00341 }
00342 
00343 //------------------------------------------+-----------------------------------
00345 
00346 void CTBxmlIStream::Get(CTBxmlToken& token)
00347 {
00348   CTB_Trace("CTBxmlIStream::Get(CTBxmlToken&)");
00349 
00350   if (mp_iss) {                             // inspect `old' cdata stream
00351     if (mp_iss->fail() && !mp_iss->eof()) 
00352       SetFail("string stream on fail() and not eof()");
00353     delete mp_iss;
00354     mp_iss = 0;
00355   }
00356   m_data.Clear();                           // clear `last cdata' cache
00357 
00358   token.Clear();                            // reset token AFTER m_data clear !!
00359 
00360   if (!mp_is) {                             // stream not open ...
00361     mb_fail = true;
00362     token.mi_type = CTBxmlToken::fail;
00363     return;
00364   }
00365   
00366   if (mb_fail) {                            // block if in fail state
00367     token.mi_type = CTBxmlToken::fail;
00368     return;
00369   }
00370 
00371   if (m_untoken) {                          // ungotten token available ?
00372     token.Grab(m_untoken);                  // use and clear it
00373     if (token.mi_type == CTBxmlToken::starttag) { // repush tag to stack
00374       assert(m_tagstack[mi_taglevel] == token.m_name); // !?! text already o.k.
00375       mi_taglevel += 1;
00376     } else if (token.mi_type == CTBxmlToken::endtag) { // unpush tag from stack
00377       assert(mi_taglevel > 0);              // !?! stack not empty
00378       mi_taglevel -= 1;
00379     }    
00380 
00381   } else {                                  // otherwise get next one
00382     for (;;) {
00383       if (mp_is->peek() != '<') {           // no '<', data or proper eof
00384         GetDataFromLexer(token);
00385         if (mb_trimwhite) token.m_value.TrimWhite();
00386       } else {                              // handle tags here
00387         GetTagFromLexer(token);
00388       }
00389       if (token.mi_type != CTBxmlToken::data) break;
00390       if (mb_dropwhite) {
00391         if (!token.m_value.IsWhite()) break;
00392       } else {
00393         if (token.m_value.Length() > 0) break;
00394       }
00395       token.Clear();
00396     }
00397   }
00398 
00399   return;
00400 }
00401 
00402 //------------------------------------------+-----------------------------------
00404 
00405 void CTBxmlIStream::GetTagOrData(CTBxmlToken& token)
00406 {
00407   CTB_Trace("CTBxmlIStream::GetTagOrData(CTBxmlToken&)");
00408   for (;;) {
00409     Get(token);
00410     if (token.mi_type != CTBxmlToken::comment &&   // checks consistent with
00411         token.mi_type != CTBxmlToken::pi &&        // PeekTagOrData()
00412         token.mi_type != CTBxmlToken::xml) break;
00413   }
00414   return;
00415 }
00416 
00417 //------------------------------------------+-----------------------------------
00419 
00420 void CTBxmlIStream::GetTagOrNonWhiteData(CTBxmlToken& token)
00421 {
00422   CTB_Trace("CTBxmlIStream::GetTagOrNonWhiteData(CTBxmlToken&)");
00423   for (;;) {
00424     GetTagOrData(token);
00425     if (token.mi_type != CTBxmlToken::data ||
00426         ! token.m_value.IsWhite()) break;
00427   }
00428   return;
00429 }
00430 
00431 //------------------------------------------+-----------------------------------
00433 
00441 void CTBxmlIStream::Unget(CTBxmlToken& token)
00442 {
00443   CTB_Trace("CTBxmlIStream::Unget(CTBxmlToken&)");
00444   if (token) {
00445     if (token.mi_type == CTBxmlToken::starttag) { // unpush tag from stack
00446       assert(mi_taglevel > 0);              // !?! stack not empty
00447       mi_taglevel -= 1;
00448     } else if (token.mi_type == CTBxmlToken::endtag) { // repush tag to stack
00449       assert(m_tagstack[mi_taglevel] == token.m_name); // !?! text already o.k.
00450       mi_taglevel += 1;
00451     }
00452     m_untoken.Grab(token);
00453   }
00454   
00455   return;
00456 }
00457 
00458 //------------------------------------------+-----------------------------------
00460 
00461 const CTBxmlToken& CTBxmlIStream::Peek()
00462 {
00463   CTB_Trace("CTBxmlIStream::Peek()");
00464   if (mb_fail) return FailToken();
00465 
00466   if (!m_untoken) {
00467     Get(m_token);
00468     Unget(m_token);
00469   }
00470 
00471   return m_untoken;
00472 }
00473 
00474 //------------------------------------------+-----------------------------------
00476 
00477 const CTBxmlToken& CTBxmlIStream::PeekTagOrData()
00478 {
00479   CTB_Trace("CTBxmlIStream::PeekTagOrData()");
00480   if (mb_fail) return FailToken();
00481 
00482   if (!m_untoken || 
00483       m_untoken.mi_type == CTBxmlToken::comment || // checks consistent with
00484       m_untoken.mi_type == CTBxmlToken::pi ||      // GetTagOrData()
00485       m_untoken.mi_type == CTBxmlToken::xml) {
00486     GetTagOrData(m_token);
00487     Unget(m_token);
00488   }
00489 
00490   return m_untoken;
00491 }
00492 
00493 //------------------------------------------+-----------------------------------
00495 
00496 const CTBxmlToken& CTBxmlIStream::PeekTagOrNonWhiteData()
00497 {
00498   CTB_Trace("CTBxmlIStream::PeekTagOrNonWhiteData()");
00499   if (mb_fail) return FailToken();
00500 
00501   if (!m_untoken || 
00502       m_untoken.mi_type == CTBxmlToken::comment || // checks consistent with
00503       m_untoken.mi_type == CTBxmlToken::pi ||      // GetTagOrData() and 
00504       m_untoken.mi_type == CTBxmlToken::xml ||     // GetTagOrNonWhiteData()
00505       (m_untoken.mi_type == CTBxmlToken::data &&
00506        m_untoken.m_value.IsWhite()) ) {
00507     GetTagOrNonWhiteData(m_token);
00508     Unget(m_token);
00509   }
00510 
00511   return m_untoken;
00512 }
00513 
00514 //------------------------------------------+-----------------------------------
00516 
00517 bool CTBxmlIStream::CheckElement(const char* c_name)
00518 {
00519   CTB_Trace("CTBxmlIStream::CheckElement(const char*)");
00520   if (m_untoken.mi_type == CTBxmlToken::starttag) // is untoken a start tag ?
00521     return m_untoken.m_name == c_name;
00522 
00523   const CTBxmlToken& tnext = PeekTagOrNonWhiteData(); // otherwise peek more
00524   return tnext.mi_type == CTBxmlToken::starttag && tnext.m_name == c_name;
00525 }
00526 
00527 //------------------------------------------+-----------------------------------
00528 // Expect element with \a c_name tag and convert value into \c int.
00529 
00530 void CTBxmlIStream::GetTaggedValue(const char* c_name, int& i_value)
00531 {
00532   CTB_Trace("CTBxmlIStream::GetTaggedValue(const char*,int&)");
00533 
00534   OpenElement(c_name);
00535   GetTagOrData(m_token);
00536   
00537   if (m_token.mi_type == CTBxmlToken::data) {
00538     bool b_ok = m_token.m_value.Get(i_value);
00539     if (!b_ok) cerr << "conversion error" << endl; // ??? handle conv error
00540   } else {
00541     Unget(m_token);                         // ??? handle structure error
00542     SetFail("GetTaggedValue() called but no data token found");
00543   }
00544 
00545   CloseElement();
00546 
00547   return;
00548 }
00549 
00550 //------------------------------------------+-----------------------------------
00551 // Expect element with \a c_name tag and convert value into \c float.
00552 
00553 void CTBxmlIStream::GetTaggedValue(const char* c_name, float& f_value)
00554 {
00555   CTB_Trace("CTBxmlIStream::GetTaggedValue(const char*,float&)");
00556 
00557   OpenElement(c_name);
00558   GetTagOrData(m_token);
00559   
00560   if (m_token.mi_type == CTBxmlToken::data) {
00561     bool b_ok = m_token.m_value.Get(f_value);
00562     if (!b_ok) cerr << "conversion error" << endl; // ??? handle conv error
00563   } else {
00564     Unget(m_token);                         // ??? handle structure error
00565     SetFail("GetTaggedValue() called but no data token found");
00566   }
00567 
00568   CloseElement();
00569 
00570   return;
00571 }
00572 
00573 //------------------------------------------+-----------------------------------
00574 // Expect element with \a c_name tag and convert value into \c double.
00575 
00576 void CTBxmlIStream::GetTaggedValue(const char* c_name, double& d_value)
00577 {
00578   CTB_Trace("CTBxmlIStream::GetTaggedValue(const char*,double&)");
00579 
00580   OpenElement(c_name);
00581   GetTagOrData(m_token);
00582   
00583   if (m_token.mi_type == CTBxmlToken::data) {
00584     bool b_ok = m_token.m_value.Get(d_value);
00585     if (!b_ok) cerr << "conversion error" << endl; // ??? handle conv error
00586   } else {
00587     Unget(m_token);                         // ??? handle structure error
00588     SetFail("GetTaggedValue() called but no data token found");
00589   }
00590 
00591   CloseElement();
00592 
00593   return;
00594 }
00595 
00596 //------------------------------------------+-----------------------------------
00597 // Expect element with \a c_name tag and convert value into \c CTBstring.
00598 
00599 void CTBxmlIStream::GetTaggedValue(const char* c_name, CTBstring& value)
00600 {
00601   CTB_Trace("CTBxmlIStream::GetTaggedValue(const char*,CTBstring&)");
00602 
00603   OpenElement(c_name);
00604   GetTagOrData(m_token);
00605   
00606   if (m_token.mi_type == CTBxmlToken::data) {
00607     value = m_token.m_value;
00608   } else if (m_token.mi_type == CTBxmlToken::endtag) {
00609     value = CTBstring::EmptyString();
00610     Unget(m_token);
00611   } else {
00612     Unget(m_token);                         // ??? handle structure error
00613     SetFail("GetTaggedValue() called but no data token found");
00614   }
00615 
00616   CloseElement();
00617 
00618   return;
00619 }
00620 
00621 //------------------------------------------+-----------------------------------
00622 // Expect element with \a c_name tag and convert value into \c CTBtime.
00623 
00624 void CTBxmlIStream::GetTaggedValue(const char* c_name, CTBtime& value)
00625 {
00626   CTB_Trace("CTBxmlIStream::GetTaggedValue(const char*,CTBtime&)");
00627 
00628   OpenElement(c_name);
00629   *this >> value;
00630   CloseElement();
00631 
00632   return;
00633 }
00634 
00635 //------------------------------------------+-----------------------------------
00637 
00638 void CTBxmlIStream::OpenElement(const char* c_name)
00639 {
00640   CTB_Trace("CTBxmlIStream::OpenElement(const char*)");
00641 
00642   GetTagOrNonWhiteData(m_token);
00643 
00644   if (m_token.mi_type != CTBxmlToken::starttag ||
00645       (c_name && m_token.m_name != c_name) ) {
00646     Unget(m_token);
00647     SetFail("OpenElement() called but no starttag found or name mismatch");
00648   }
00649 
00650   return ;
00651 }
00652 
00653 //------------------------------------------+-----------------------------------
00655 
00656 void CTBxmlIStream::CloseElement()
00657 {
00658   CTB_Trace("CTBxmlIStream::CloseElement()");
00659   CTBint i_depth = mi_taglevel;
00660 
00661   while (!mb_fail && mi_taglevel >= i_depth) Get(m_token);
00662 
00663   return;
00664 }
00665 
00666 //------------------------------------------+-----------------------------------
00668 
00669 void CTBxmlIStream::DropElement()
00670 {
00671   CTB_Trace("CTBxmlIStream::DropElement()");
00672   OpenElement();
00673   CloseElement();
00674   return;
00675 }
00676 
00677 //------------------------------------------+-----------------------------------
00679 
00680 istream* CTBxmlIStream::GetDataStream()
00681 {
00682   CTB_Trace("CTBxmlIStream::GetDataStream()");
00683   if (mp_iss == 0) {                        // no strstream already active
00684     bool b_ok = false;
00685 
00686     GetTagOrData(m_token);
00687 
00688     if (m_token.mi_type == CTBxmlToken::data) {
00689       m_data = m_token.m_value;
00690       b_ok   = true;
00691     } else if (m_token.mi_type == CTBxmlToken::endtag) {
00692       m_data = CTBstring::EmptyString();
00693       b_ok   = true;
00694     } else {
00695       m_data.Clear();
00696     }
00697 
00698     if (b_ok) 
00699       mp_iss = new istrstream(m_data.Data(),m_data.Length());
00700     else {
00701       SetFail("GetDataStream() called but no data available");
00702       Unget(m_token);
00703     }
00704   }
00705     
00706   return mp_iss;
00707 }
00708 
00709 //------------------------------------------+-----------------------------------
00711 
00712 void CTBxmlIStream::ToStream(ostream& os) const
00713 {
00714   os << "XML input stream is ";
00715   if (mp_is) {
00716     os << (mb_attached ? "attached" : "open");
00717   } else {
00718     os << "closed";
00719   }
00720   os << " and state is ";
00721   if (Eof()) os << "`at eof'";
00722   else os << (Good() ? "`good'" : "`not good'");
00723   os << "\n";
00724 
00725   if (mp_is) {
00726     os << "  at line " << m_lex.NLine() 
00727        << " column " << m_lex.NColumn() << "\n";
00728     if (mi_taglevel > 0) {
00729       os << "  open parent tags:\n";
00730       for (int i = 0; i < mi_taglevel; i++) {
00731         os << "    <" << m_tagstack[i] << ">\n";
00732       }
00733     }
00734   }
00735 
00736   return;
00737 }
00738 
00739 
00740 //------------------------------------------+-----------------------------------
00742 
00743 void CTBxmlIStream::Dump(int i_indent, ostream& os, const char* p_text) const
00744 {
00745   CTBosFill bl(i_indent);
00746   
00747   os << bl << "--CTBxmlIStream ";
00748   if (p_text) os << p_text;
00749   os << " @ " << this << endl;
00750 
00751   os << bl << "    mp_is:        " << mp_is << endl;
00752   os << bl << "    mb_attached:  " << mb_attached << endl;
00753   os << bl << "    mb_trimwhite: " << mb_trimwhite << endl;
00754   os << bl << "    mb_dropwhite: " << mb_dropwhite << endl;
00755   os << bl << "    mb_fail:      " << mb_fail << endl;
00756   os << bl << "    mb_bad:       " << mb_bad << endl;
00757   os << bl << "    mb_eof:       " << mb_eof << endl;
00758   os << bl << "    mp_iss:       " << mp_iss << endl;
00759   m_data.Dump(i_indent+2,os,"mdata");
00760   m_tagstack.Dump(i_indent+2,os,"m_tagstack");
00761   os << bl << "    mi_taglevel:  " << mi_taglevel << endl;
00762   m_untoken.Dump(i_indent+2,os,"m_untoken");
00763   m_token.Dump(i_indent+2,os,"m_token");
00764   m_lex.Dump(i_indent+2,os,"m_lex");
00765 
00766   return;
00767 }
00768 
00769 //------------------------------------------+-----------------------------------
00771 
00772 void CTBxmlIStream::GetDataFromLexer(CTBxmlToken& token)
00773 {  
00774   CTB_Trace("CTBxmlIStream::GetDataFromLexer(CTBxmlToken&)");
00775 
00776   int i_type = GetLexerToken(CTBxmlLexer::tagordata,token);
00777   
00778   if (i_type == CTBxmlLexerToken::eof) {    // proper eof
00779     mb_eof  = true;
00780     mb_fail = true;
00781     token.mi_type = CTBxmlToken::eof;
00782     return;
00783   }
00784     
00785   for (;;) {
00786     
00787     if (i_type == CTBxmlLexerToken::eof) {  // proper eof
00788       token.mi_type = CTBxmlToken::data;
00789       return;
00790     }
00791     
00792     if (i_type == CTBxmlLexerToken::invalid || // handle aborts
00793         i_type == CTBxmlLexerToken::fail) {
00794       mb_fail = true;
00795       token.mi_type = CTBxmlToken::fail;
00796       return;
00797     }
00798     
00799     if (i_type == CTBxmlLexerToken::white || // handle data
00800         i_type == CTBxmlLexerToken::data) {
00801       token.m_value += m_lextoken.Text();
00802     } else if (i_type == CTBxmlLexerToken::charref) {
00803       token.m_value += ConvertCharRef(m_lextoken.Text());
00804     } else if (i_type == CTBxmlLexerToken::entref) {      
00805       token.m_value += ConvertEntityRef(m_lextoken.Text());
00806     } else {
00807       mb_fail = true;
00808       token.mi_type = CTBxmlToken::fail;
00809       return;                               // this is a bugcheck ???
00810     }
00811     
00812     if (mp_is->peek() == '<') {             // next char '<', so a tag is next
00813       token.mi_type = CTBxmlToken::data;
00814       return;
00815     }
00816     
00817     i_type = GetLexerToken(CTBxmlLexer::tagordata,token);
00818   }  
00819 
00820   return;
00821 }
00822 
00823 //------------------------------------------+-----------------------------------
00825 
00826 void CTBxmlIStream::GetTagFromLexer(CTBxmlToken& token)
00827 {
00828   CTB_Trace("CTBxmlIStream::GetTagFromLexer(CTBxmlToken&)");
00829 
00830   int i_type = GetLexerToken(CTBxmlLexer::tagordata,token);
00831 
00832   if (i_type == CTBxmlLexerToken::comment) { // handle comments
00833     token.mi_type  = CTBxmlToken::comment;
00834     return;
00835   }
00836 
00837   if (i_type == CTBxmlLexerToken::tagopen || // handle tags
00838       i_type == CTBxmlLexerToken::etagopen ||
00839       i_type == CTBxmlLexerToken::piopen ||
00840       i_type == CTBxmlLexerToken::defopen) {
00841     
00842     int i_ctype = GetLexerToken(CTBxmlLexer::tagattr,token);
00843     
00844     if (i_ctype == CTBxmlLexerToken::name) {
00845       token.m_name += m_lextoken.Text();
00846     } else {
00847       mb_fail = true;
00848       token.mi_type  = CTBxmlToken::fail;
00849       return;
00850     }
00851     
00852     if (i_type == CTBxmlLexerToken::tagopen || // handle attribute lists
00853         i_type == CTBxmlLexerToken::etagopen ||
00854         (i_type == CTBxmlLexerToken::piopen &&
00855          token.m_name.CompareCaseBlind("xml") == 0)) {
00856       
00857       enum { s_name_end,
00858              s_equal_name_end,
00859              s_quote,
00860              s_data_squote,
00861              s_data_dquote
00862       };
00863       int i_state = s_name_end;
00864       int i_mode_quote;
00865       int i_type_quote;
00866         
00867       for (;;) {          
00868         switch (i_state) {
00869           
00870         case s_name_end:
00871         case s_equal_name_end:
00872           i_ctype = GetLexerToken(CTBxmlLexer::tagattr,token);
00873           
00874           if (i_ctype == CTBxmlLexerToken::white) break;
00875           
00876           if (i_state == s_equal_name_end &&
00877               i_ctype == CTBxmlLexerToken::equal) {
00878             i_state = s_quote;
00879             break;
00880           }
00881           
00882           if (i_ctype == CTBxmlLexerToken::name) {
00883             token.m_attribute << CTBxmlToken::pair_ss_t(m_lextoken.Text());
00884             i_state = s_equal_name_end;
00885             break;
00886           }
00887           
00888           if (i_type  == CTBxmlLexerToken::tagopen &&
00889               i_ctype == CTBxmlLexerToken::tagclose) {
00890             if (mi_taglevel >= m_tagstack.Size()) 
00891               m_tagstack.Resize(CTBmax(mi_taglevel+1,2*m_tagstack.Size()));
00892             m_tagstack[mi_taglevel].Clear();
00893             m_tagstack[mi_taglevel] += token.m_name; // enforce deep copy
00894             mi_taglevel += 1;
00895             token.mi_type = CTBxmlToken::starttag;
00896             return;
00897           }
00898 
00899           if (i_type  == CTBxmlLexerToken::piopen && // if here <?xml ... ?>
00900               i_ctype == CTBxmlLexerToken::piclose) {
00901             token.mi_type = CTBxmlToken::xml;
00902             return;
00903           }
00904           
00905           if (i_type  == CTBxmlLexerToken::etagopen &&
00906               i_ctype == CTBxmlLexerToken::tagclose) {
00907             if (mi_taglevel > 0) {
00908               mi_taglevel -= 1;
00909               if (m_tagstack[mi_taglevel] == token.m_name) {
00910                 token.mi_type = CTBxmlToken::endtag;
00911                 return;
00912               }
00913             }
00914             mb_fail = true;
00915             token.mi_type = CTBxmlToken::fail;
00916             return;
00917           }
00918           
00919           if (i_type  == CTBxmlLexerToken::tagopen &&
00920               i_ctype == CTBxmlLexerToken::etagclose) {
00921             token.mi_type = CTBxmlToken::emptytag;
00922             return;
00923           }
00924           mb_fail = true;
00925           token.mi_type = CTBxmlToken::fail;
00926           return;
00927           
00928         case s_quote:
00929           i_ctype = GetLexerToken(CTBxmlLexer::attrval,token);
00930           
00931           if (i_ctype == CTBxmlLexerToken::squote) {
00932             i_state = s_data_squote;
00933             break;
00934           }
00935           
00936           if (i_ctype == CTBxmlLexerToken::dquote) {
00937             i_state = s_data_dquote;
00938             break;
00939           }
00940           mb_fail = true;
00941           token.mi_type = CTBxmlToken::fail;
00942           return;
00943           
00944         case s_data_squote:
00945         case s_data_dquote:
00946           if (i_state == s_data_squote) {
00947             i_mode_quote = CTBxmlLexer::valsquote;
00948             i_type_quote = CTBxmlLexerToken::squote;
00949           } else {
00950             i_mode_quote = CTBxmlLexer::valdquote;
00951             i_type_quote = CTBxmlLexerToken::dquote;
00952           }
00953           
00954           i_ctype = GetLexerToken(i_mode_quote,token);
00955           
00956           if (i_ctype == i_type_quote) {
00957             i_state = s_name_end;
00958             break;
00959           }
00960           
00961           if (i_ctype == CTBxmlLexerToken::white ||
00962               i_ctype == CTBxmlLexerToken::data) {
00963             CTBint i_nattr = token.m_attribute.Size();
00964             token.m_attribute[i_nattr-1].Value() += m_lextoken.Text();
00965             break;
00966           }
00967 
00968           if (i_ctype == CTBxmlLexerToken::charref) {
00969             CTBint i_nattr = token.m_attribute.Size();
00970             token.m_attribute[i_nattr-1].Value() += ConvertCharRef(m_lextoken.Text());
00971             break;
00972           }
00973           if (i_ctype == CTBxmlLexerToken::entref) {
00974             CTBint i_nattr = token.m_attribute.Size();
00975             token.m_attribute[i_nattr-1].Value() += ConvertEntityRef(m_lextoken.Text());
00976             break;
00977           }
00978 
00979           mb_fail = true;
00980           token.mi_type = CTBxmlToken::fail;
00981           return;
00982           
00983         default:
00984           throw CTBexceptionBugcheck("illegal state","CTBxmlIStream::Get()");
00985         }
00986       }
00987     }
00988   }
00989   
00990   return;
00991 }
00992 
00993 //------------------------------------------+-----------------------------------
00995 
00996 void CTBxmlIStream::SetFail(const char* c_message)
00997 {
00998   CTB_Trace("CTBxmlIStream::SetFail(const char*)");
00999   mb_fail = true;
01000   cerr << c_message << endl;                // ??? to be improved ???
01001   return;
01002 }
01003 
01004 //------------------------------------------+-----------------------------------
01006 
01007 const CTBxmlToken& CTBxmlIStream::FailToken() const
01008 {
01009   CTB_Trace("CTBxmlIStream::FailToken()");
01010   static const CTBxmlToken failtoken(CTBxmlToken::fail);
01011   return failtoken;
01012 }
01013 
01014 //------------------------------------------+-----------------------------------
01016 
01017 CTBstring CTBxmlIStream::ConvertCharRef(const CTBstring& cref)
01018 {
01019   CTB_Trace("CTBxmlIStream::ConvertCharRef(const CTBstring&)");
01020   return cref;                              // ??? TO BE IMPLEMENTED ???
01021 }
01022 
01023 //------------------------------------------+-----------------------------------
01025 
01026 CTBstring CTBxmlIStream::ConvertEntityRef(const CTBstring& eref)
01027 {
01028   CTB_Trace("CTBxmlIStream::ConvertEntityRef(const CTBstring&)");
01029   if (eref.Length() > 2 && eref[0] == '&' && eref[eref.Length()-1] == ';') {
01030     CTBstring ename = eref(1,eref.Length()-2);
01031     if (ename == "lt")   return "<";
01032     if (ename == "gt")   return ">";
01033     if (ename == "amp")  return "&";
01034     if (ename == "apos") return "\'";
01035     if (ename == "quot") return "\"";
01036   }
01037   return eref;
01038 }
01039 
01040 //------------------------------------------+-----------------------------------
01042 
01043 int CTBxmlIStream::GetLexerToken(int i_lexmode, CTBxmlToken& token)
01044 {
01045   CTB_Trace("CTBxmlIStream::GetLexerToken(int,CTBxmlToken&)");
01046 
01047   m_lex.Mode(i_lexmode);
01048   m_lex.Get(*mp_is,m_lextoken);
01049   token.m_text  += m_lextoken.Text();
01050   return m_lextoken.Type();
01051 }

Generated at Fri Oct 24 18:11:31 2003 for CTBbase by doxygen1.2.9-20010812 written by Dimitri van Heesch, © 1997-2001