00001
00006
00007
00008
00009
00010
00011
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;
00092 m_text.Clear();
00093 m_name.Clear();
00094 m_value.Clear();
00095 m_attribute.Resize(0);
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) {
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) {
00327 if (!mb_attached) delete mp_is;
00328 mp_is = 0;
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) {
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();
00357
00358 token.Clear();
00359
00360 if (!mp_is) {
00361 mb_fail = true;
00362 token.mi_type = CTBxmlToken::fail;
00363 return;
00364 }
00365
00366 if (mb_fail) {
00367 token.mi_type = CTBxmlToken::fail;
00368 return;
00369 }
00370
00371 if (m_untoken) {
00372 token.Grab(m_untoken);
00373 if (token.mi_type == CTBxmlToken::starttag) {
00374 assert(m_tagstack[mi_taglevel] == token.m_name);
00375 mi_taglevel += 1;
00376 } else if (token.mi_type == CTBxmlToken::endtag) {
00377 assert(mi_taglevel > 0);
00378 mi_taglevel -= 1;
00379 }
00380
00381 } else {
00382 for (;;) {
00383 if (mp_is->peek() != '<') {
00384 GetDataFromLexer(token);
00385 if (mb_trimwhite) token.m_value.TrimWhite();
00386 } else {
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 &&
00411 token.mi_type != CTBxmlToken::pi &&
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) {
00446 assert(mi_taglevel > 0);
00447 mi_taglevel -= 1;
00448 } else if (token.mi_type == CTBxmlToken::endtag) {
00449 assert(m_tagstack[mi_taglevel] == token.m_name);
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 ||
00484 m_untoken.mi_type == CTBxmlToken::pi ||
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 ||
00503 m_untoken.mi_type == CTBxmlToken::pi ||
00504 m_untoken.mi_type == CTBxmlToken::xml ||
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)
00521 return m_untoken.m_name == c_name;
00522
00523 const CTBxmlToken& tnext = PeekTagOrNonWhiteData();
00524 return tnext.mi_type == CTBxmlToken::starttag && tnext.m_name == c_name;
00525 }
00526
00527
00528
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;
00540 } else {
00541 Unget(m_token);
00542 SetFail("GetTaggedValue() called but no data token found");
00543 }
00544
00545 CloseElement();
00546
00547 return;
00548 }
00549
00550
00551
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;
00563 } else {
00564 Unget(m_token);
00565 SetFail("GetTaggedValue() called but no data token found");
00566 }
00567
00568 CloseElement();
00569
00570 return;
00571 }
00572
00573
00574
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;
00586 } else {
00587 Unget(m_token);
00588 SetFail("GetTaggedValue() called but no data token found");
00589 }
00590
00591 CloseElement();
00592
00593 return;
00594 }
00595
00596
00597
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);
00613 SetFail("GetTaggedValue() called but no data token found");
00614 }
00615
00616 CloseElement();
00617
00618 return;
00619 }
00620
00621
00622
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) {
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) {
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) {
00788 token.mi_type = CTBxmlToken::data;
00789 return;
00790 }
00791
00792 if (i_type == CTBxmlLexerToken::invalid ||
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 ||
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;
00810 }
00811
00812 if (mp_is->peek() == '<') {
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) {
00833 token.mi_type = CTBxmlToken::comment;
00834 return;
00835 }
00836
00837 if (i_type == CTBxmlLexerToken::tagopen ||
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 ||
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;
00894 mi_taglevel += 1;
00895 token.mi_type = CTBxmlToken::starttag;
00896 return;
00897 }
00898
00899 if (i_type == CTBxmlLexerToken::piopen &&
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;
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;
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 }