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 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 long int number) { 00125 SetNone(); 00126 mType=Integer | Float; 00127 mIntegerValue=number; 00128 mFloatValue=number; 00129 } 00130 00131 // Token::SetInteger16(number) 00132 void Token::SetInteger16(const long int number) { 00133 SetNone(); 00134 mType= Integer16 | Integer | Float; 00135 mIntegerValue=number; 00136 mFloatValue=number; 00137 } 00138 00139 // Token::SetBoolean(number) 00140 void Token::SetBoolean(const long int number) { 00141 SetNone(); 00142 mType= Boolean | Integer | Float; 00143 mIntegerValue=number; 00144 mFloatValue=number; 00145 } 00146 00147 // Token::SetFloat(number) 00148 void Token::SetFloat(const double number) { 00149 SetNone(); 00150 mType=Float; 00151 mIntegerValue=(long int) number; 00152 mFloatValue=number; 00153 } 00154 00155 // Token::SetBinary 00156 void Token::SetBinary(const char* data, long int 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 long int Token::IntegerValue(void) const { 00171 return(mIntegerValue); 00172 } 00173 00174 00175 // access float 00176 double 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 & Float) return Float; 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 & Float; 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, long int value) { 00308 AttributeValue aval; 00309 aval.mStringValue=ToStringInteger(value); 00310 aval.mType=Float | Integer; 00311 aval.mSort=mAttributeCount++; 00312 mAttributes[name]=aval; 00313 } 00314 00315 // insert integer attribute 00316 void Token::InsAttributeInteger16(const std::string& name, long int value) { 00317 AttributeValue aval; 00318 aval.mStringValue=ToStringInteger16(value); 00319 aval.mType=Float | Integer; 00320 aval.mSort=mAttributeCount++; 00321 mAttributes[name]=aval; 00322 } 00323 00324 // insert integer attribute 00325 void Token::InsAttributeBoolean(const std::string& name, long int value) { 00326 AttributeValue aval; 00327 if(value==0) aval.mStringValue="false"; 00328 else aval.mStringValue="true"; 00329 aval.mType=Float | Integer; 00330 aval.mSort=mAttributeCount++; 00331 mAttributes[name]=aval; 00332 } 00333 00334 // insert float attribute 00335 void Token::InsAttributeFloat(const std::string& name, double value) { 00336 AttributeValue aval; 00337 aval.mStringValue=ToStringFloat(value); 00338 aval.mType=Float; 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 & Float) 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 long 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 double 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 & Float)) 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, long int 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 long int 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 long int 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, long int& ival, double& fval) { 00719 char c, vc; 00720 double fv=0; 00721 long 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 | Float); 00728 // test for special cases 00729 if(numstr=="inf" || numstr=="+inf") { 00730 ival = std::numeric_limits<long int>::max(); 00731 fval = ival; 00732 type|= (Integer | Float ); 00733 return true; 00734 } 00735 // test for special casess 00736 if(numstr=="-inf") { 00737 ival=std::numeric_limits<long int>::min()+1; 00738 fval=ival; 00739 type|= (Integer | Float); 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 |= Float; 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 & Float) { 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 char c2=c; 01021 while (*pStream) { 01022 if(pStream->eof()) return -1; 01023 c2=c; 01024 c = pStream->peek(); 01025 if(!(isblank(c) || iscntrl(c))) break; 01026 pStream->get(); 01027 if(c=='\n') ++lc; 01028 } 01029 // get attrname 01030 std::string aname; 01031 while (*pStream) { 01032 if(pStream->eof()) return -1; 01033 c = pStream->peek(); 01034 if(isblank(c) || iscntrl(c)) break; 01035 if(c=='=') break; 01036 if(c=='>') break; 01037 if(c=='/') break; 01038 pStream->get(); 01039 aname.append(1,c); 01040 } 01041 FD_DV("Token::ReadAttributes(): aname " << aname); 01042 // no name so we're done 01043 if(aname.size()==0) { 01044 return lc; 01045 } 01046 // skip space 01047 while(*pStream) { 01048 if(pStream->eof()) return -1; 01049 c = pStream->peek(); 01050 if(!(isblank(c) || iscntrl(c))) break; 01051 pStream->get(); 01052 if(c=='\n') ++lc; 01053 } 01054 // insist in eq 01055 if(c!='=') return -1; 01056 pStream->get(); 01057 // skip space 01058 while (*pStream) { 01059 if(pStream->eof()) return -1; 01060 c = pStream->peek(); 01061 if(!(isblank(c) || iscntrl(c))) break; 01062 pStream->get(); 01063 if(c=='\n') ++lc; 01064 } 01065 // strict version, value by '"' 01066 if(c == '"') { 01067 pStream->get(); 01068 int ll=ReadString(pStream,'"'); 01069 if(ll<0) return -1; 01070 pStream->get(); 01071 lc+=ll; 01072 } 01073 // relaxed version, value by "space" 01074 else { 01075 int ll=ReadString(pStream,' '); 01076 if(ll<0) return -1; 01077 lc+=ll; 01078 } 01079 std::string aval=mStringValue; 01080 FD_DV("Token::ReadAttributes(): aval " << aval); 01081 // record attribute 01082 InsAttribute(aname,aval); 01083 } 01084 // done 01085 return lc; 01086 } 01087 01088 // ReadMarkup(pStream) 01089 // (leading "<" has allready been read) 01090 int Token::ReadMarkup(std::istream* pStream) { 01091 int lc=0; 01092 int ll; 01093 char c=0; 01094 mStringValue = ""; 01095 mType=None; 01096 // figure indicator character 01097 char p1=0; 01098 char p2=0; 01099 if(pStream->eof()) return -1; 01100 c = pStream->peek(); 01101 if(!(isalpha(c) || c=='_' || c==':')) { 01102 p1 = pStream->get(); 01103 if(pStream->eof()) return -1; 01104 p2 = pStream->peek(); 01105 } 01106 FD_DV("Token::ReadMarkup: " << c << "-" << p1 << "-" << p2); 01107 // its a begin tag ... 01108 if(p1==0) { 01109 FD_DV("Token::ReadMarkup: sensed XML tag"); 01110 // ... get the name 01111 std::string name; 01112 while (*pStream) { 01113 if(pStream->eof()) return -1; 01114 c = pStream->peek(); 01115 if(c == '>') break; 01116 if(c == '/') break; 01117 if(isblank(c) || iscntrl(c)) break; 01118 pStream->get(); 01119 name.append(1,c); 01120 } 01121 if(name.size()==0) return -1; 01122 mType = Begin; 01123 ll=ReadAttributes(pStream); 01124 if(ll<0) return -1; 01125 if(pStream->eof()) return -1; 01126 c = pStream->peek(); 01127 if(c=='/') mType |= End; 01128 lc+=ll; 01129 mStringValue=name; 01130 FD_DV("Token::ReadMarkup: sensed XML tag, type " << mType << " name " << mStringValue); 01131 } 01132 // its an end tag: get the name 01133 if(p1=='/') { 01134 std::string name; 01135 while(*pStream) { 01136 if(pStream->eof()) return -1; 01137 c = pStream->peek(); 01138 if(c == '>') break; 01139 if(c == '/') break; 01140 if(isblank(c) || iscntrl(c)) break; 01141 pStream->get(); 01142 name.append(1,c); 01143 } 01144 if(name.size()==0) return -1; 01145 if(c!='>') return -1; 01146 mType = End; 01147 mStringValue=name; 01148 } 01149 // its an xml comment 01150 if(p1=='!' && p2=='-') { 01151 FD_DV("Token::ReadMarkup: sensed XML comment <" << p1 << p2); 01152 c=pStream->get(); 01153 if(pStream->eof()) return -1; 01154 c=pStream->get(); 01155 if(c!='-') return -1; 01156 char c2=0; 01157 char c3=0; 01158 while (*pStream) { 01159 c3=c2; c2=c; 01160 if(pStream->eof()) return -1; 01161 c = pStream->peek(); 01162 if(c3== '-' && c2=='-' && c == '>') break; 01163 pStream->get(); 01164 if(c=='\n') ++lc; 01165 } 01166 FD_DV("Token::ReadMarkup: sensed XML comment end " << c3 << c2 << c); 01167 } 01168 // its an xml doctypedec (which we cannot handle properly) 01169 if(p1=='!' && (p2=='D' || p2=='d')) { 01170 FD_DV("Token::ReadMarkup doc.type.dec. not implemented (!)"); 01171 c=pStream->get(); 01172 while(*pStream) { 01173 if(pStream->eof()) return -1; 01174 c = pStream->peek(); 01175 if(c == '>') break; 01176 pStream->get(); 01177 if(c=='\n') ++lc; 01178 } 01179 } 01180 // its an xml cdata (interpret as string) 01181 if(p1=='!' && p2=='[' ) { 01182 FD_DV("Token::ReadMarkup: sense CDATA?"); 01183 // sense "<![CDATA[" 01184 c=pStream->get(); 01185 if(pStream->eof()) return -1; 01186 if(pStream->get()!='C') return -1; 01187 if(pStream->eof()) return -1; 01188 if(pStream->get()!='D') return -1; 01189 if(pStream->eof()) return -1; 01190 if(pStream->get()!='A') return -1; 01191 if(pStream->eof()) return -1; 01192 if(pStream->get()!='T') return -1; 01193 if(pStream->eof()) return -1; 01194 if(pStream->get()!='A') return -1; 01195 if(pStream->eof()) return -1; 01196 if(pStream->get()!='[') return -1; 01197 // read until "]]>" 01198 FD_DV("Token::ReadMarkup: sense CDATA!"); 01199 char c2=0; 01200 char c3=0; 01201 while(*pStream) { 01202 c3=c2; c2=c; 01203 if(pStream->eof()) return -1; 01204 c = pStream->peek(); 01205 if(c3== ']' && c2==']' && c == '>') break; 01206 if(pStream->eof()) return -1; 01207 pStream->get(); 01208 if(c=='\n') ++lc; 01209 mStringValue.append(1,c); 01210 } 01211 FD_DV("Token::ReadMarkup: sense CDATA:" << mStringValue); 01212 // drop "]]" 01213 if(mStringValue.size()>=2) 01214 mStringValue.erase(mStringValue.size()-2); 01215 // drop leading endl 01216 if(mStringValue.size()>=2) 01217 if(mStringValue.at(0)=='\r') 01218 if(mStringValue.at(1)=='\n') 01219 mStringValue=mStringValue.substr(2); 01220 if(mStringValue.size()>=1) 01221 if(mStringValue.at(0)=='\n') 01222 mStringValue=mStringValue.substr(1); 01223 // drop tailing endl 01224 if(mStringValue.size()>=1) 01225 if(mStringValue.at(mStringValue.size()-1)=='\n') 01226 mStringValue=mStringValue.substr(0,mStringValue.size()-1); 01227 if(mStringValue.size()>=1) 01228 if(mStringValue.at(mStringValue.size()-1)=='\r') 01229 mStringValue=mStringValue.substr(0,mStringValue.size()-1); 01230 mType |= String; 01231 mType |= Cdata; 01232 FD_DV("Token::ReadMarkup: sense CDATA:" << mStringValue); 01233 } 01234 // its an xml proc.intstruction (which we ignore) 01235 if(p1=='?') { 01236 if(pStream->eof()) return -1; 01237 c = pStream->get(); 01238 char c2=0; 01239 while (*pStream) { 01240 c2=c; 01241 if(pStream->eof()) return -1; 01242 c = pStream->peek(); 01243 if(c2=='?' && c == '>') break; 01244 pStream->get(); 01245 if(c=='\n') ++lc; 01246 } 01247 } 01248 // error 01249 if(pStream->eof()) return -1; 01250 c = pStream->peek(); 01251 if(c!='>') { 01252 FD_DV("Token::ReadMarkup: mismatch (?) " << mStringValue); 01253 while (*pStream) { 01254 if(pStream->eof()) return -1; 01255 c = pStream->peek(); 01256 if(c == '>') break; 01257 if(c=='\n') ++lc; 01258 pStream->get(); 01259 } 01260 } 01261 // done 01262 pStream->get(); 01263 FD_DV("Token::ReadMarkup: return type " << mType << " string " << mStringValue << " lc" << lc); 01264 return lc; 01265 } 01266 01267 // Read(pStream) 01268 int Token::Read(std::istream* pStream){ 01269 char c1; 01270 int lc = 0; 01271 int ll; 01272 // the token is initialized with the type "None" 01273 SetNone(); 01274 // check eof 01275 if(pStream->eof()) return(lc); 01276 // read all spaces in the pStream 01277 lc += ReadSpace(pStream); 01278 // check eof 01279 if(pStream->eof()) return(lc); 01280 // get the first useful character 01281 c1=pStream->peek(); 01282 // token is a quoted string if it starts with '"' 01283 if(c1 == '"') { 01284 pStream->get(); 01285 // read the string until '"' 01286 ll=ReadString(pStream,'"'); 01287 if(ll>=0) { 01288 lc+=ll; 01289 pStream->get(); 01290 mType |= String; 01291 } 01292 } 01293 // token is a quoted string if it starts with ''' 01294 else if(c1 == '\'') { 01295 pStream->get(); 01296 // read the string until ''' 01297 ll=ReadString(pStream,'\''); 01298 if(ll>=0) { 01299 lc+=ll; 01300 pStream->get(); 01301 mType |= String; 01302 } 01303 } 01304 // token is an option string if it starts with '+' 01305 else if(c1 == '+') { 01306 pStream->get(); 01307 // read the string until '+' 01308 ll=ReadString(pStream,'+'); 01309 mOptionValue=mStringValue; 01310 mStringValue="+" + mOptionValue + "+"; 01311 if(ll>=0) { 01312 lc+=ll; 01313 pStream->get(); 01314 mType |= (Option | String); 01315 } 01316 } 01317 // token is a binary string if it starts with '=' 01318 else if(c1 == '=') { 01319 // read the string until '=', incl padding 01320 ll=ReadBinary(pStream); 01321 if(ll>=0) lc+=ll; 01322 if(ll>=0) mType |= (Binary | String); 01323 } 01324 // token is a verbatim string if it starts with '_' 01325 else if(c1 == '_') { 01326 // read the string until the corresponding end marker (2.18 compatibility) 01327 ll=ReadVerbatim(pStream); 01328 if(ll>=0) lc+=ll; 01329 if(ll>=0) mType = String; 01330 } 01331 // token is markup if it starts with < 01332 else if(c1 == '<') { 01333 pStream->get(); 01334 // check eof 01335 if(pStream->eof()) return(lc); 01336 // read and interpret 01337 ll=ReadMarkup(pStream); 01338 if(ll>=0) lc+=ll; 01339 // if this is not a faudes token, get the next 01340 if(mType==None && ll>=0) { 01341 ll=Read(pStream); 01342 if(ll>=0) lc+=ll; 01343 else mType=None; 01344 } 01345 // error 01346 if(ll<0) return -1; 01347 } 01348 // token is a space seperated string, perhaps a number 01349 else { 01350 if(ReadString(pStream,' ')>=0) { 01351 // pStream->get(); 20101218: dont get the seperator, could be "<" of starting markup 01352 mType |= String; 01353 InterpretNumber(); 01354 } 01355 } 01356 // report result 01357 FD_DV("Token::Read: " << Str()); 01358 return(lc); 01359 } 01360 01361 01362 // Str() 01363 std::string Token::Str(void) const { 01364 std::stringstream ostr; 01365 ostr << "Token( Type="; 01366 if(IsNone()) { ostr << "None)"; return ostr.str();} 01367 if(IsInteger()) ostr << "Integer"; 01368 if(IsInteger16()) ostr << "Integer16"; 01369 if(IsBoolean()) ostr << "Boolean"; 01370 if(IsFloat()) ostr << "Float"; 01371 if(IsString()) ostr << "String"; 01372 if(IsBegin()) ostr << "Begin"; 01373 if(IsEnd()) ostr << "End"; 01374 ostr << " Value=\""; 01375 if(IsFloat()) ostr << FloatValue(); 01376 else if(IsBegin() || IsEnd()) ostr << StringValue(); 01377 else if(IsString()) ostr << StringValue(); 01378 ostr << "\""; 01379 caiterator ait; 01380 for(ait=mAttributes.begin(); ait!=mAttributes.end(); ait++) 01381 ostr << " attr[" << ait->first << "=\"" << ait->second.mStringValue << "\"]"; 01382 ostr << " spacing=" << mPreceedingSpace << "/"<< mPreceedingNewline; 01383 ostr << ")"; 01384 return ostr.str(); 01385 } 01386 01387 01388 01389 } // namespace faudes |
libFAUDES 2.22s --- 2013.10.07 --- c++ source docu by doxygen