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