|
libFAUDES
Sections
Index
|
cfl_token.cppGo to the documentation of this file.00001 /** @file cfl_token.cpp @brief Class Token */ 00002 00003 /* FAU Discrete Event Systems Library (libfaudes) 00004 00005 Copyright (C) 2006 Bernd Opitz 00006 Exclusive copyright is granted to Klaus Schmidt 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Lesser General Public 00010 License as published by the Free Software Foundation; either 00011 version 2.1 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public 00019 License along with this library; if not, write to the Free Software 00020 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00021 00022 00023 #include "cfl_token.h" 00024 00025 namespace faudes { 00026 00027 00028 // Token::Token() 00029 Token::Token(void) : 00030 mType(None), 00031 mStringValue(""), 00032 mOptionValue(""), 00033 mIntegerValue(0), 00034 mFloatValue(0), 00035 mAttributeCount(0) 00036 { 00037 } 00038 00039 // copy construct 00040 Token::Token(const Token& rToken) : 00041 mType(rToken.mType), 00042 mStringValue(rToken.mStringValue), 00043 mOptionValue(rToken.mOptionValue), 00044 mIntegerValue(rToken.mIntegerValue), 00045 mFloatValue(rToken.mFloatValue), 00046 mAttributes(rToken.mAttributes), 00047 mAttributeCount(rToken.mAttributeCount) 00048 { 00049 } 00050 00051 00052 // assignment 00053 Token& Token::operator=(const Token& rToken) { 00054 mType=rToken.mType; 00055 mStringValue=rToken.mStringValue; 00056 mOptionValue=rToken.mOptionValue; 00057 mIntegerValue=rToken.mIntegerValue; 00058 mFloatValue=rToken.mFloatValue; 00059 mAttributes=rToken.mAttributes; 00060 mAttributeCount=rToken.mAttributeCount; 00061 return *this; 00062 } 00063 00064 // destructor 00065 Token::~Token(void){ 00066 } 00067 00068 // Token::SetNone() 00069 void Token::SetNone(void ) { 00070 mType=None; 00071 mStringValue=""; 00072 mOptionValue=""; 00073 mIntegerValue=0; 00074 mFloatValue=0; 00075 mAttributes.clear(); 00076 mAttributeCount=0; 00077 } 00078 00079 // Token::SetString(str) 00080 void Token::SetString(const std::string& rName) { 00081 SetNone(); 00082 mType=String; 00083 mStringValue=rName; 00084 } 00085 00086 // Token::SetBegin(str) 00087 void Token::SetBegin(const std::string& rName) { 00088 SetNone(); 00089 mType=Begin; 00090 mStringValue=rName; 00091 } 00092 00093 // Token::SetEnd(str) 00094 void Token::SetEnd(const std::string& rName) { 00095 SetNone(); 00096 mType=End; 00097 mStringValue=rName; 00098 } 00099 00100 // Token::SetEmpty(str) 00101 void Token::SetEmpty(const std::string& rName) { 00102 SetNone(); 00103 mType=End | Begin; 00104 mStringValue=rName; 00105 } 00106 00107 // Token::SetOption(str) 00108 void Token::SetOption(const std::string& rName) { 00109 SetNone(); 00110 mType=Option | String; 00111 mStringValue="+"+rName+"+"; 00112 mOptionValue=rName; 00113 } 00114 00115 // Token::SetInteger(number) 00116 void Token::SetInteger(const long int number) { 00117 SetNone(); 00118 mType=Integer | Float; 00119 mIntegerValue=number; 00120 mFloatValue=number; 00121 } 00122 00123 // Token::SetInteger16(number) 00124 void Token::SetInteger16(const long int number) { 00125 SetNone(); 00126 mType= Integer16 | Integer | Float; 00127 mIntegerValue=number; 00128 mFloatValue=number; 00129 } 00130 00131 // Token::SetBoolean(number) 00132 void Token::SetBoolean(const long int number) { 00133 SetNone(); 00134 mType= Boolean | Integer | Float; 00135 mIntegerValue=number; 00136 mFloatValue=number; 00137 } 00138 00139 // Token::SetFloat(number) 00140 void Token::SetFloat(const double number) { 00141 SetNone(); 00142 mType=Float; 00143 mIntegerValue=(long int) number; 00144 mFloatValue=number; 00145 } 00146 00147 // Token::SetBinary 00148 void Token::SetBinary(const char* data, long int len) { 00149 SetNone(); 00150 mType=Binary | String; 00151 mStringValue.assign(data,len); 00152 } 00153 00154 00155 // access integer 00156 long int Token::IntegerValue(void) const { 00157 return(mIntegerValue); 00158 } 00159 00160 00161 // access float 00162 double Token::FloatValue(void) const { 00163 return(mFloatValue); 00164 } 00165 00166 // access string 00167 const std::string& Token::StringValue(void) const { 00168 if(mType & Option) return(mOptionValue); // compatibility 00169 return(mStringValue); 00170 } 00171 00172 // access option 00173 const std::string& Token::OptionValue(void) const { 00174 return(mOptionValue); 00175 } 00176 00177 // access unique type (depreciated!) 00178 Token::TokenType Token::Type(void) const { 00179 if(mType & Begin) return Begin; 00180 if(mType & End) return End; 00181 if(mType & Integer16) return Integer16; 00182 if(mType & Boolean) return Boolean; 00183 if(mType & Integer) return Integer; 00184 if(mType & Float) return Float; 00185 if(mType & Option) return Option; 00186 if(mType & Binary) return Binary; 00187 if(mType & String) return String; 00188 return None; 00189 } 00190 00191 00192 // test type 00193 bool Token::IsNone(void) const { 00194 return mType == None; 00195 } 00196 00197 // test type 00198 bool Token::IsInteger(void) const { 00199 return mType & Integer; 00200 } 00201 00202 // test type 00203 bool Token::IsInteger16(void) const { 00204 return mType & Integer16; 00205 } 00206 00207 // test type 00208 bool Token::IsBoolean(void) const { 00209 return mType & Boolean; 00210 } 00211 00212 // test type 00213 bool Token::IsFloat(void) const { 00214 return mType & Float; 00215 } 00216 00217 // test type 00218 bool Token::IsOption(void) const { 00219 return mType & Option; 00220 } 00221 00222 // test type 00223 bool Token::IsString(void) const { 00224 return mType & String; 00225 } 00226 00227 // test type 00228 bool Token::IsBinary(void) const { 00229 return mType & Binary; 00230 } 00231 00232 // test type 00233 bool Token::IsBegin(void) const { 00234 return mType & Begin; 00235 } 00236 00237 // test type 00238 bool Token::IsEnd(void) const { 00239 return mType & End; 00240 } 00241 00242 00243 // clear attribute 00244 void Token::ClrAttribute(const std::string& name) { 00245 aiterator ait=mAttributes.find(name); 00246 if(ait==mAttributes.end()) return; 00247 mAttributes.erase(ait); 00248 } 00249 00250 // clear all attributes 00251 void Token::ClearAttributes() { 00252 mAttributes.clear(); 00253 mAttributeCount=0; 00254 } 00255 00256 00257 // insert attribute for interpretation 00258 void Token::InsAttribute(const std::string& name, const std::string& value) { 00259 AttributeValue aval; 00260 aval.mStringValue=value; 00261 aval.mType=None; 00262 aval.mSort=mAttributeCount++; 00263 mAttributes[name]=aval; 00264 } 00265 00266 00267 // insert string attribute 00268 void Token::InsAttributeString(const std::string& name, const std::string& value) { 00269 AttributeValue aval; 00270 aval.mStringValue=value; 00271 aval.mType=String; 00272 aval.mSort=mAttributeCount++; 00273 mAttributes[name]=aval; 00274 } 00275 00276 // insert integer attribute 00277 void Token::InsAttributeInteger(const std::string& name, long int value) { 00278 AttributeValue aval; 00279 aval.mStringValue=ToStringInteger(value); 00280 aval.mType=Float | Integer; 00281 aval.mSort=mAttributeCount++; 00282 mAttributes[name]=aval; 00283 } 00284 00285 // insert integer attribute 00286 void Token::InsAttributeInteger16(const std::string& name, long int value) { 00287 AttributeValue aval; 00288 aval.mStringValue=ToStringInteger16(value); 00289 aval.mType=Float | Integer; 00290 aval.mSort=mAttributeCount++; 00291 mAttributes[name]=aval; 00292 } 00293 00294 // insert integer attribute 00295 void Token::InsAttributeBoolean(const std::string& name, long int value) { 00296 AttributeValue aval; 00297 if(value==0) aval.mStringValue="false"; 00298 else aval.mStringValue="true"; 00299 aval.mType=Float | Integer; 00300 aval.mSort=mAttributeCount++; 00301 mAttributes[name]=aval; 00302 } 00303 00304 // insert float attribute 00305 void Token::InsAttributeFloat(const std::string& name, double value) { 00306 AttributeValue aval; 00307 aval.mStringValue=ToStringFloat(value); 00308 aval.mType=Float; 00309 aval.mSort=mAttributeCount++; 00310 mAttributes[name]=aval; 00311 } 00312 00313 // test attribute type 00314 bool Token::ExistsAttributeString(const std::string& name) { 00315 aiterator ait=mAttributes.find(name); 00316 if(ait==mAttributes.end()) return false; 00317 InterpretAttribute(ait); 00318 if(ait->second.mType & String) return true; 00319 return false; 00320 } 00321 00322 00323 // test attribute type 00324 bool Token::ExistsAttributeInteger(const std::string& name) { 00325 aiterator ait=mAttributes.find(name); 00326 if(ait==mAttributes.end()) return false; 00327 InterpretAttribute(ait); 00328 if(ait->second.mType & Integer) return true; 00329 return false; 00330 } 00331 00332 00333 // test attribute type 00334 bool Token::ExistsAttributeFloat(const std::string& name) { 00335 aiterator ait=mAttributes.find(name); 00336 if(ait==mAttributes.end()) return false; 00337 InterpretAttribute(ait); 00338 if(ait->second.mType & Float) return true; 00339 return false; 00340 } 00341 00342 00343 // access attribute value 00344 const std::string& Token::AttributeStringValue(const std::string& name) { 00345 static const std::string emptystr=""; 00346 aiterator ait=mAttributes.find(name); 00347 if(ait==mAttributes.end()) return emptystr; 00348 InterpretAttribute(ait); 00349 if(!(ait->second.mType & String)) return emptystr; 00350 return ait->second.mStringValue; 00351 } 00352 00353 00354 // access attribute value 00355 long int Token::AttributeIntegerValue(const std::string& name) { 00356 aiterator ait=mAttributes.find(name); 00357 if(ait==mAttributes.end()) return 0; 00358 InterpretAttribute(ait); 00359 if(!(ait->second.mType & Integer)) return 0; 00360 return ait->second.mIntegerValue; 00361 } 00362 00363 00364 // access attribute value 00365 double Token::AttributeFloatValue(const std::string& name) { 00366 aiterator ait=mAttributes.find(name); 00367 if(ait==mAttributes.end()) return 0; 00368 InterpretAttribute(ait); 00369 if(!(ait->second.mType & Float)) return 0; 00370 return ait->second.mFloatValue; 00371 } 00372 00373 00374 // WriteVerbatim(pStream) 00375 void Token::WriteVerbatim(std::ostream* pStream, const std::string& rString) { 00376 // verb marker candidate 00377 std::string verb="__VERBATIM__"; 00378 // adjust marker 00379 while(rString.find(verb)!=std::string::npos) { 00380 verb = verb+"#"; 00381 } 00382 // do write 00383 *pStream << std::endl; 00384 *pStream << verb << std::endl; 00385 *pStream << rString; 00386 *pStream << verb << std::endl; 00387 } 00388 00389 00390 // ReadString(pStream, char) 00391 int Token::ReadVerbatim(std::istream* pStream){ 00392 // clear 00393 mStringValue = ""; 00394 std::string verb=""; 00395 int lc=0; 00396 char c; 00397 // figure mark 00398 while(*pStream) { 00399 // check eof 00400 if(pStream->eof()) {mType=None; return -1;}; 00401 // get one character 00402 c = pStream->get(); 00403 // new line, control and space breaks 00404 if(c == '\n') { lc++; break; } 00405 if(iscntrl(c)) break; 00406 if(isblank(c)) break; 00407 // others get appended 00408 verb.append(1,c); 00409 } 00410 // test 00411 if(verb.size()<2) return -1; 00412 if(verb.at(0) !='_') return -1; 00413 if(verb.at(1) !='_') return -1; 00414 // read until mark 00415 while(*pStream) { 00416 // check eof 00417 if (pStream->eof()) {mType=None; return -1;}; 00418 // get one character 00419 c = pStream->get(); 00420 // count the next lines 00421 if (c == '\n') ++lc; 00422 // append anything 00423 mStringValue.append(1,c); 00424 // if c is _ or #, test for end 00425 if(c== verb.at(verb.size()-1)) { 00426 unsigned int vpos=mStringValue.find(verb); 00427 if(vpos!=std::string::npos) { 00428 mStringValue = mStringValue.substr(0,vpos); 00429 return lc; 00430 } 00431 } 00432 } 00433 return lc; 00434 } 00435 00436 // WriteBinary(pStream,data,len) 00437 void Token::WriteBinary(std::ostream* pStream, const char* pData, long int len) { 00438 00439 // my encoding (hardcoded in read, however) 00440 static char Base64EncodingTable[]= 00441 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00442 00443 // start 00444 *pStream << "="; 00445 00446 // loop vars 00447 const char* src = pData; 00448 long int cnt=len; 00449 int step=0; 00450 unsigned char c0=0,c1=0,c2=0,c3=0; 00451 00452 // encode and output buffer 00453 while(cnt>0) { 00454 switch(step) { 00455 // collect char for 1st byte 00456 case 0: 00457 c0= ((*src & 0xFC) >> 2); 00458 c1= ((*src & 0x03) << 4); 00459 c2=0; 00460 c3=0; 00461 step=1; 00462 break; 00463 // collect char for 2nd byte 00464 case 1: 00465 c1|= ((*src & 0xF0) >> 4); 00466 c2|= ((*src & 0x0F) << 2); 00467 step=2; 00468 break; 00469 // collect char for 3rd byte, plus output 00470 case 2: 00471 c2|= ((*src & 0xC0) >> 6); 00472 c3|= (*src & 0x3F); 00473 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 00474 Base64EncodingTable[c2] << Base64EncodingTable[c3]; 00475 step=0; 00476 break; 00477 default: break; 00478 } 00479 cnt--; 00480 src++; 00481 } 00482 // flush left overs, incl padding 00483 switch(step) { 00484 case 0: 00485 *pStream << "= "; 00486 break; 00487 case 1: 00488 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << "=== "; 00489 break; 00490 case 2: 00491 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 00492 Base64EncodingTable[c2] << "== "; 00493 break; 00494 } 00495 } 00496 00497 // WriteBinary(pStream) 00498 void Token::WriteBinary(std::ostream* pStream) const { 00499 if(mType!=Binary) return; 00500 WriteBinary(pStream,mStringValue.data(),mStringValue.size()); 00501 } 00502 00503 00504 // ReadBinary ... to mStringValue 00505 int Token::ReadBinary(std::istream* pStream) { 00506 00507 // line count 00508 int lc; 00509 00510 // swallow leading '=' 00511 char c1=pStream->get(); 00512 if(c1!='=') return -1; 00513 00514 // read as string, excl. marks '=' 00515 lc=ReadString(pStream,'='); 00516 00517 // swallow one trailing '=' 00518 c1=pStream->get(); 00519 if(c1!='=') return -1; 00520 00521 // take any extra trailing padding = 00522 while(!pStream->eof()) { 00523 if(pStream->peek()!='=') break; 00524 pStream->get(); 00525 mStringValue.append("="); 00526 } 00527 00528 // loop vars 00529 std::string::iterator src=mStringValue.begin(); 00530 std::string::iterator dst=mStringValue.begin(); 00531 long int cnt=0; 00532 int c=0, d0=0, d1=0, d2=0; 00533 unsigned char cs[4]; 00534 unsigned int step=0; 00535 00536 // loop 00537 while(true) { 00538 00539 // get data 00540 while(true) { 00541 // sense eof 00542 if(src==mStringValue.end()) { c = -1; break; } 00543 // get char 00544 c=*(src++); 00545 // decode 00546 if(c>='A' && c <='Z') { c-='A'; break; } 00547 if(c>='a' && c <='z') { c-='a'; c+= ('Z'-'A')+1; break; } 00548 if(c>='0' && c <='9') { c-='0'; c+= 2*('Z'-'A')+2; break; } 00549 if(c=='+') {c= 62; break; } 00550 if(c=='/') {c= 63; break; } 00551 if(c=='=') {c= 0xFF; break; }; 00552 } 00553 // pass on eof 00554 if(c== -1) break; 00555 // record and continue 00556 cs[step++] = c; 00557 if(step<=3) continue; 00558 step=0; 00559 // sort bits 00560 d0= ((cs[0] << 2) & 0xFC) | ((cs[1] >> 4) & 0x03); 00561 d1= ((cs[1] << 4) & 0xF0) | ((cs[2] >> 2) & 0x0F); 00562 d2= ((cs[2] << 6) & 0xC0) | (cs[3] & 0x3F); 00563 // record result 00564 if(cs[0]!= 0xFF && cs[1]!=0xFF) {*(dst++)=d0; cnt++;} 00565 if(cs[1]!= 0xFF && cs[2]!=0xFF) {*(dst++)=d1; cnt++;} 00566 if(cs[2]!= 0xFF && cs[3]!=0xFF) {*(dst++)=d2; cnt++;} 00567 // sense end 00568 if(cs[3]==0xFF) break; 00569 } 00570 00571 // set data length (sets the length incl termination char??) 00572 mStringValue.resize(cnt); 00573 00574 // return padding error or line count 00575 return step==0 ? lc : -1; 00576 } 00577 00578 00579 00580 // ReadSpace(pStream) 00581 int Token::ReadSpace(std::istream* pStream){ 00582 char c = '\0'; 00583 int lc = 0; 00584 FD_DV("Token::ReadSpace()"); 00585 // check the whole pStream 00586 while(*pStream) { 00587 while(*pStream) { 00588 // check eof 00589 if (pStream->eof()) return lc; 00590 // look one character ahead 00591 c = pStream->peek(); 00592 // break if the next character is 00593 // not a space or a control character 00594 if((! isspace(c)) && (! iscntrl(c))) break; 00595 // get the next space or control character 00596 pStream->get(); 00597 // count the next lines 00598 if(c == '\n') ++lc; 00599 } 00600 // if the next charakter starts a faudes comment 00601 if(c != '%') break; 00602 while (*pStream) { 00603 // check eof 00604 if (pStream->eof()) {return(lc);}; 00605 // get the next character 00606 c = pStream->get(); 00607 // count the next lines 00608 if (c == '\n') ++lc; 00609 // terminate with the next new line character 00610 if (c == '\n') break; 00611 if (c == '\r') break; 00612 } 00613 } 00614 // termination if the next character is neither a space, a control, or a '%'. 00615 FD_DV("Token::ReadSpace(): lc " << lc); 00616 return lc; 00617 } 00618 00619 // InterpretAttribute(aval) 00620 void Token::InterpretAttribute(aiterator ait) { 00621 if(ait->second.mType != None) return; 00622 InterpretNumber( 00623 ait->second.mStringValue, ait->second.mType, 00624 ait->second.mIntegerValue, ait->second.mFloatValue); 00625 ait->second.mType |= String; 00626 } 00627 00628 // InterpretNumber(string) 00629 bool Token::InterpretNumber(void) { 00630 return InterpretNumber(mStringValue,mType,mIntegerValue,mFloatValue); 00631 } 00632 00633 // InterpretNumber(string, ...) 00634 bool Token::InterpretNumber(const std::string& numstr, int& type, long int& ival, double& fval) { 00635 char c, vc; 00636 double fv=0; 00637 long int iv=0; 00638 int comma = -1; 00639 bool minus = false; 00640 int base=10; 00641 bool ok=false; 00642 int cnt=0; 00643 type &= ~(Integer | Integer16 | Float); 00644 // test for special cases 00645 if(numstr=="inf" || numstr=="+inf") { 00646 ival = std::numeric_limits<long int>::max(); 00647 fval = ival; 00648 type|= (Integer | Float ); 00649 return true; 00650 } 00651 // test for special casess 00652 if(numstr=="-inf") { 00653 ival=std::numeric_limits<long int>::min()+1; 00654 fval=ival; 00655 type|= (Integer | Float); 00656 return true; 00657 } 00658 // test for special cases 00659 if(numstr=="true" || numstr=="True") { 00660 ival = 1; 00661 fval = ival; 00662 type|= (Integer | Boolean); 00663 return true; 00664 } 00665 // test for special cases 00666 if(numstr=="false" || numstr=="False") { 00667 ival = 0; 00668 fval = ival; 00669 type|= (Integer | Boolean); 00670 return true; 00671 } 00672 // iterate over string 00673 std::string::const_iterator cit=numstr.begin(); 00674 for(;cit!=numstr.end(); cit++) { 00675 // check next charakter 00676 c = *cit; 00677 cnt++; 00678 // change base on x 00679 if(c=='x' && iv==0 && cnt==2 && comma<0 && !minus) 00680 {base = 16; continue;} 00681 // change sign on - 00682 if(c=='-' && cnt==1) 00683 {minus = true; continue;} 00684 // record comma 00685 if(c=='.' && comma<0 && base==10) 00686 {comma = 0; continue;} 00687 // break if it is not a digit 00688 if(!isdigit(c) && base==10) break; 00689 if(!isxdigit(c) && base==16) break; 00690 // compute the value of c 00691 vc=0; 00692 if(c>='0' && c<= '9') vc = c-'0'; 00693 else if(c>='a' && c<= 'f') vc = c-'a' + 10; 00694 else if(c>='A' && c<= 'F') vc = c-'A' + 10; 00695 // compute the corresponding number 00696 iv = base * iv + vc; 00697 fv = base * fv + vc; 00698 if(comma>=0) comma++; 00699 ok = true; 00700 } 00701 // detect error 00702 if(cit!=numstr.end()) ok=false; 00703 // fix sign 00704 if(minus) { 00705 iv=-iv; 00706 fv=-fv; 00707 } 00708 // fix decimal point 00709 for(;comma>0;comma--) { 00710 iv/=base; 00711 fv/=base; 00712 } 00713 // assign the numeric value and type in Token 00714 if(ok) { 00715 ival = iv; 00716 fval = fv; 00717 type |= Float; 00718 if(comma<=0 && !minus) type |= Integer; 00719 if(comma<=0 && !minus && base==16) type |= Integer16; 00720 } 00721 return ok; 00722 } 00723 00724 // Write(pStream) 00725 void Token::Write(std::ostream* pStream) const { 00726 FD_DV("Token::Write: mType=" << (int) mType 00727 << "\" mStringValue=\"" << mStringValue 00728 << "\" mIntegerValue=" <<mIntegerValue 00729 << "\" mFloatValue=" <<mFloatValue <<"\n"); 00730 // numerics first 00731 if(mType & Integer16) { 00732 *pStream << ExpandString(ToStringInteger16(mIntegerValue), FD_NAMELEN) << " "; 00733 } else if(mType & Integer) { 00734 *pStream << ExpandString(ToStringInteger(mIntegerValue), FD_NAMELEN) << " "; 00735 } else if(mType & Float) { 00736 *pStream << ExpandString(ToStringFloat(mFloatValue), FD_NAMELEN) << " "; 00737 } 00738 // mark up: begin 00739 else if(mType & Begin) { 00740 *pStream << '<' << mStringValue; 00741 std::map<int,caiterator> sortnames; 00742 for(caiterator ait=mAttributes.begin(); ait!=mAttributes.end(); ait++) 00743 sortnames[ait->second.mSort]=ait; 00744 std::map<int,caiterator>::iterator sit; 00745 for(sit=sortnames.begin(); sit!=sortnames.end(); sit++) { 00746 caiterator ait=sit->second; 00747 *pStream << " "; 00748 WriteEscapedString(pStream,ait->first); 00749 *pStream << "=\""; 00750 WriteEscapedString(pStream,ait->second.mStringValue); 00751 *pStream << "\""; 00752 } 00753 if(mType & End) *pStream << "/"; 00754 *pStream << "> "; 00755 } 00756 // mark up:end 00757 else if(mType & End) { 00758 *pStream << "</" << mStringValue << "> "; 00759 } 00760 // string 00761 else if(mType & Option) { 00762 WriteString(pStream,""); // '+' is incl. mStringValue 00763 } else if(mType & Binary) { 00764 WriteBinary(pStream); 00765 } else if(mType & String) { 00766 // figure delimiter 00767 bool quote=false; 00768 if(mStringValue.size()==0) quote=true; 00769 if(mStringValue.size()>0) 00770 if(!isalpha(mStringValue[0])) quote=true; 00771 static const std::string white=" \n\r\t\f"; 00772 if(mStringValue.find_first_of(white)!=std::string::npos) 00773 quote=true; 00774 if(quote) 00775 WriteString(pStream,"\""); 00776 else 00777 WriteString(pStream,""); 00778 } 00779 // error (should we have an exception here?) 00780 else { /* assert(0) */ }; 00781 } 00782 00783 // WriteEscapedString(pStream) 00784 int Token::WriteEscapedString(std::ostream* pStream, const std::string& outstr) { 00785 // assemble escape character string 00786 std::string escstr="<>&\""; 00787 // no escape characters 00788 if(outstr.find_first_of(escstr)==std::string::npos) { 00789 *pStream << outstr; 00790 return outstr.size(); 00791 } 00792 // do escape substitution 00793 int cc=0; 00794 std::string::const_iterator cit=outstr.begin(); 00795 for(;cit!=outstr.end(); cit++) { 00796 if(*cit=='<') 00797 { *pStream << "<"; cc+=4; continue;} 00798 if(*cit=='>') 00799 { *pStream << ">"; cc+=4; continue;} 00800 if(*cit=='&') 00801 { *pStream << "&"; cc+=5; continue;} 00802 if(*cit=='"') 00803 { *pStream << """; cc+=6; continue;} 00804 *pStream << *cit; cc++; 00805 } 00806 return cc; 00807 } 00808 00809 // WriteString(pStream, delim) 00810 void Token::WriteString(std::ostream* pStream, const std::string& delim) const { 00811 int cc=0; 00812 *pStream << delim; 00813 cc+=delim.size(); 00814 cc+=WriteEscapedString(pStream,mStringValue); 00815 *pStream << delim << " "; 00816 cc+=delim.size()+1; 00817 while(cc< FD_NAMELEN) { 00818 *pStream << " "; cc++; 00819 } 00820 } 00821 00822 // ReadString(pStream, char) 00823 int Token::ReadString(std::istream* pStream, char stop) { 00824 int ll= ReadEscapedString(pStream,stop,mStringValue); 00825 if(ll<0) mType=None; 00826 return ll; 00827 } 00828 00829 00830 // ReadEscapedString(pStream, rString, char) 00831 int Token::ReadEscapedString(std::istream* pStream, char stop, std::string& rString) { 00832 int lc=0; 00833 char c; 00834 std::string entref=""; 00835 bool ctrlblank = false; 00836 rString = ""; 00837 // check the whole pStream 00838 while (*pStream) { 00839 // check eof 00840 if(pStream->eof()) return -1; 00841 // test one character 00842 c = pStream->peek(); 00843 // break on mark up 00844 if(c == '<') break; 00845 // break on stop 00846 if(c == stop) break; 00847 if(isblank(c) && stop==' ') break; 00848 if(iscntrl(c) && stop==' ') break; 00849 // get one character 00850 c = pStream->get(); 00851 // count the next lines 00852 if(c=='\n') ++lc; 00853 // replace sequence of control characters by one blanc 00854 if(iscntrl(c) && ctrlblank) continue; 00855 ctrlblank=false; 00856 if(iscntrl(c)) { c=' '; ctrlblank=true;} 00857 // if in escape mode ... 00858 if(entref.size()!=0) { 00859 //record reference 00860 entref.append(1,c); 00861 // error: reference must not contain a white space 00862 if(c == ' ') return -1; 00863 // decode reference 00864 if(c == ';') { 00865 if(entref=="&") rString.append(1,'&'); 00866 else if(entref==""") rString.append(1,'"'); 00867 else if(entref=="'") rString.append(1,'\''); 00868 else if(entref=="<") rString.append(1,'<'); 00869 else if(entref==">") rString.append(1,'>'); 00870 // ignore unknown 00871 entref=""; 00872 } 00873 continue; 00874 } 00875 // ... sense escape 00876 if(c == '&') entref.append(1,c); 00877 // ... add character 00878 if(c != '&') rString.append(1,c); 00879 continue; 00880 } 00881 return lc; 00882 } 00883 00884 00885 // ReadAttributes(pStream) 00886 int Token::ReadAttributes(std::istream* pStream) { 00887 int lc=0; 00888 char c=0; 00889 FD_DV("Token::ReadAttributes()"); 00890 // scan until excl. '>' 00891 while (*pStream) { 00892 // skip space 00893 char c2=c; 00894 while (*pStream) { 00895 if(pStream->eof()) return -1; 00896 c2=c; 00897 c = pStream->peek(); 00898 if(!(isblank(c) || iscntrl(c))) break; 00899 pStream->get(); 00900 if(c=='\n') ++lc; 00901 } 00902 // get attrname 00903 std::string aname; 00904 while (*pStream) { 00905 if(pStream->eof()) return -1; 00906 c = pStream->peek(); 00907 if(isblank(c) || iscntrl(c)) break; 00908 if(c=='=') break; 00909 if(c=='>') break; 00910 if(c=='/') break; 00911 pStream->get(); 00912 aname.append(1,c); 00913 } 00914 FD_DV("Token::ReadAttributes(): aname " << aname); 00915 // no name so we're done 00916 if(aname.size()==0) { 00917 if(c=='/') { 00918 mType |= End; 00919 pStream->get(); 00920 c=pStream->peek(); 00921 } 00922 if(c=='>') return lc; 00923 return -1; 00924 } 00925 // skip space 00926 while(*pStream) { 00927 if(pStream->eof()) return -1; 00928 c = pStream->peek(); 00929 if(!(isblank(c) || iscntrl(c))) break; 00930 pStream->get(); 00931 if(c=='\n') ++lc; 00932 } 00933 // insist in eq 00934 if(c!='=') return -1; 00935 pStream->get(); 00936 // skip space 00937 while (*pStream) { 00938 if(pStream->eof()) return -1; 00939 c = pStream->peek(); 00940 if(!(isblank(c) || iscntrl(c))) break; 00941 pStream->get(); 00942 if(c=='\n') ++lc; 00943 } 00944 // insist in '"' 00945 if(c != '"') return -1; 00946 pStream->get(); 00947 // get attrval 00948 int ll=ReadString(pStream,'"'); 00949 if(ll<0) return -1; 00950 pStream->get(); 00951 lc+=ll; 00952 std::string aval=mStringValue; 00953 FD_DV("Token::ReadAttributes(): aval " << aval); 00954 // record attribute 00955 InsAttribute(aname,aval); 00956 } 00957 // done 00958 return lc; 00959 } 00960 00961 // ReadMarkup(pStream) 00962 int Token::ReadMarkup(std::istream* pStream) { 00963 int lc=0; 00964 int ll; 00965 char c=0; 00966 std::string name; 00967 mStringValue = ""; 00968 mType=None; 00969 // figure indicator character 00970 char p1=0; 00971 if(pStream->eof()) return -1; 00972 c = pStream->peek(); 00973 if(!(isalpha(c) || c=='_' || c==':')) 00974 p1 = pStream->get(); 00975 if(pStream->eof()) return -1; 00976 char p2 = pStream->peek(); 00977 // its a begin tag ... 00978 if(p1==0) { 00979 FD_DV("Token::ReadMarkup: sensed XML tag"); 00980 // ... get the name 00981 while (*pStream) { 00982 if(pStream->eof()) return -1; 00983 c = pStream->peek(); 00984 if(c == '>') break; 00985 if(c == '/') break; 00986 if(isblank(c) || iscntrl(c)) break; 00987 pStream->get(); 00988 name.append(1,c); 00989 } 00990 if(name.size()==0) return -1; 00991 mType = Begin; 00992 ll=ReadAttributes(pStream); 00993 if(ll<0) return -1; 00994 lc+=ll; 00995 FD_DV("Token::ReadMarkup: sensed XML tag, type " << mType << " name " << name); 00996 } 00997 // its an end tag: get the name 00998 if(p1=='/') { 00999 while(*pStream) { 01000 if(pStream->eof()) return -1; 01001 c = pStream->peek(); 01002 if(c == '>') break; 01003 if(c == '/') break; 01004 if(isblank(c) || iscntrl(c)) break; 01005 pStream->get(); 01006 name.append(1,c); 01007 } 01008 if(name.size()==0) return -1; 01009 if(c!='>') return -1; 01010 mType = End; 01011 } 01012 // its an xml comment 01013 if(p1=='!' && p2=='-') { 01014 FD_DV("Token::ReadMarkup: sensed XML comment beg <" << p1 << p2); 01015 c=pStream->get(); 01016 if(pStream->eof()) return -1; 01017 c=pStream->get(); 01018 if(c!='-') return -1; 01019 char c2=0; 01020 char c3=0; 01021 while (*pStream) { 01022 c3=c2; c2=c; 01023 if(pStream->eof()) return -1; 01024 c = pStream->peek(); 01025 if(c3== '-' && c2=='-' && c == '>') break; 01026 pStream->get(); 01027 if(c=='\n') ++lc; 01028 } 01029 FD_DV("Token::ReadMarkup: sensed XML comment end " << c3 << c2 << c); 01030 } 01031 // its an xml doctypedec (which we cannot handle properly) 01032 if(p1=='!' && (p2=='D' || p2=='d')) { 01033 FD_DV("Token::ReadMarkup doc.type.dec. not implemented (!)"); 01034 c=pStream->get(); 01035 while(*pStream) { 01036 if(pStream->eof()) return -1; 01037 c = pStream->peek(); 01038 if(c == '>') break; 01039 pStream->get(); 01040 if(c=='\n') ++lc; 01041 } 01042 } 01043 // its an xml cdata (interpret as string) 01044 if(p1=='!' && p2=='[' ) { 01045 c=pStream->get(); 01046 if(pStream->eof()) return -1; 01047 if(pStream->get()!='C') return -1; 01048 if(pStream->eof()) return -1; 01049 if(pStream->get()!='D') return -1; 01050 if(pStream->eof()) return -1; 01051 if(pStream->get()!='A') return -1; 01052 if(pStream->eof()) return -1; 01053 if(pStream->get()!='T') return -1; 01054 if(pStream->eof()) return -1; 01055 if(pStream->get()!='A') return -1; 01056 if(pStream->eof()) return -1; 01057 if(pStream->get()!='[') return -1; 01058 char c2=0; 01059 char c3=0; 01060 while(*pStream) { 01061 c3=c2; c2=c; 01062 if(pStream->eof()) return -1; 01063 c = pStream->peek(); 01064 if(c3== ']' && c2==']' && c == '>') break; 01065 pStream->get(); 01066 if(c=='\n') ++lc; 01067 mStringValue.append(1,c); 01068 } 01069 if(mStringValue.size()>=2) 01070 mStringValue.erase(mStringValue.size()-2); 01071 mType |= String; 01072 mType |= Binary; 01073 } 01074 // its an xml proc.intstruction (which we ignore) 01075 if(p1=='?') { 01076 if(pStream->eof()) return -1; 01077 c = pStream->get(); 01078 char c2=0; 01079 while (*pStream) { 01080 c2=c; 01081 if(pStream->eof()) return -1; 01082 c = pStream->peek(); 01083 if(c2=='?' && c == '>') break; 01084 pStream->get(); 01085 if(c=='\n') ++lc; 01086 } 01087 } 01088 // error 01089 c = pStream->peek(); 01090 if(c!='>') { 01091 FD_DV("Token::ReadMarkup: mismatch (?) " << name); 01092 while (*pStream) { 01093 if(pStream->eof()) return -1; 01094 c = pStream->peek(); 01095 if(c == '>') break; 01096 if(c=='\n') ++lc; 01097 pStream->get(); 01098 } 01099 } 01100 // done 01101 pStream->get(); 01102 mStringValue=name; 01103 FD_DV("Token::ReadMarkup: return type " << mType << " string " << mStringValue << " lc" << lc); 01104 return lc; 01105 } 01106 01107 // Read(pStream) 01108 int Token::Read(std::istream* pStream){ 01109 char c1; 01110 int lc = 0; 01111 int ll; 01112 // the token is initialized with the type "None" 01113 SetNone(); 01114 // check eof 01115 if(pStream->eof()) return(lc); 01116 // read all spaces in the pStream 01117 lc += ReadSpace(pStream); 01118 // check eof 01119 if(pStream->eof()) return(lc); 01120 // get the first useful character 01121 c1=pStream->peek(); 01122 // token is a quoted string if it starts with '"' 01123 if(c1 == '"') { 01124 pStream->get(); 01125 // read the string until '"' 01126 ll=ReadString(pStream,'"'); 01127 if(ll>=0) { 01128 lc+=ll; 01129 pStream->get(); 01130 mType |= String; 01131 } 01132 } 01133 // token is a quoted string if it starts with ''' 01134 else if(c1 == '\'') { 01135 pStream->get(); 01136 // read the string until ''' 01137 ll=ReadString(pStream,'\''); 01138 if(ll>=0) { 01139 lc+=ll; 01140 pStream->get(); 01141 mType |= String; 01142 } 01143 } 01144 // token is an option string if it starts with '+' 01145 else if(c1 == '+') { 01146 pStream->get(); 01147 // read the string until '+' 01148 ll=ReadString(pStream,'+'); 01149 mOptionValue=mStringValue; 01150 mStringValue="+" + mOptionValue + "+"; 01151 if(ll>=0) { 01152 lc+=ll; 01153 pStream->get(); 01154 mType |= (Option | String); 01155 } 01156 } 01157 // token is a binary string if it starts with '=' 01158 else if(c1 == '=') { 01159 // read the string until '=', incl padding 01160 ll=ReadBinary(pStream); 01161 if(ll>=0) lc+=ll; 01162 if(ll>=0) mType |= (Binary | String); 01163 } 01164 // token is a verbatim string if it starts with '_' 01165 else if(c1 == '_') { 01166 // read the string until the corresponding end marker 01167 ll=ReadVerbatim(pStream); 01168 if(ll>=0) lc+=ll; 01169 if(ll>=0) mType = String; 01170 } 01171 // token is markup if it starts with < 01172 else if(c1 == '<') { 01173 pStream->get(); 01174 // check eof 01175 if(pStream->eof()) return(lc); 01176 // read and interpret 01177 ll=ReadMarkup(pStream); 01178 if(ll>=0) lc+=ll; 01179 // if this is not a faudes token, get the next 01180 if(mType==None && ll>=0) { 01181 ll=Read(pStream); 01182 if(ll>=0) lc+=ll; 01183 else mType=None; 01184 } 01185 // error 01186 if(ll<0) return -1; 01187 } 01188 // token is a space seperated string, perhaps a number 01189 else { 01190 if(ReadString(pStream,' ')>=0) { 01191 pStream->get(); 01192 mType |= String; 01193 InterpretNumber(); 01194 } 01195 } 01196 // report result 01197 FD_DV("Token::Read: " << Str()); 01198 return(lc); 01199 } 01200 01201 01202 // Str() 01203 std::string Token::Str(void) const { 01204 std::stringstream ostr; 01205 ostr << "Token( Type="; 01206 if(IsNone()) { ostr << "None)"; return ostr.str();} 01207 if(IsInteger()) ostr << "Integer"; 01208 if(IsInteger16()) ostr << "Integer16"; 01209 if(IsBoolean()) ostr << "Boolean"; 01210 if(IsFloat()) ostr << "Float"; 01211 if(IsString()) ostr << "String"; 01212 if(IsBegin()) ostr << "Begin"; 01213 if(IsEnd()) ostr << "End"; 01214 ostr << " Value=\""; 01215 if(IsFloat()) ostr << FloatValue(); 01216 else if(IsBegin() || IsEnd()) ostr << StringValue(); 01217 else if(IsString()) ostr << StringValue(); 01218 ostr << "\""; 01219 caiterator ait; 01220 for(ait=mAttributes.begin(); ait!=mAttributes.end(); ait++) 01221 ostr << " attr[" << ait->first << "=\"" << ait->second.mStringValue << "\"]"; 01222 ostr << ")"; 01223 return ostr.str(); 01224 } 01225 01226 01227 01228 } // namespace faudes |
libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3