|
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 mIntegerValue(0), 00033 mFloatValue(0) 00034 { 00035 } 00036 00037 // copy construct 00038 Token::Token(const Token& rToken) : 00039 mType(rToken.mType), 00040 mStringValue(rToken.mStringValue), 00041 mIntegerValue(rToken.mIntegerValue), 00042 mFloatValue(rToken.mFloatValue) 00043 { 00044 } 00045 00046 00047 // assignment 00048 Token& Token::operator=(const Token& rToken) { 00049 mType=rToken.mType; 00050 mStringValue=rToken.mStringValue; 00051 mIntegerValue=rToken.mIntegerValue; 00052 mFloatValue=rToken.mFloatValue; 00053 return *this; 00054 } 00055 00056 // destructor 00057 Token::~Token(void){ 00058 } 00059 00060 // Token::SetNone() 00061 void Token::SetNone(void ) { 00062 mType=None; mStringValue=""; mIntegerValue=0; mFloatValue=0; 00063 } 00064 00065 // Token::SetString(str) 00066 void Token::SetString(const std::string& rName) { 00067 mType=String; mStringValue=rName; mIntegerValue=0; mFloatValue=0; 00068 } 00069 00070 // Token::SetBegin(str) 00071 void Token::SetBegin(const std::string& rName) { 00072 mType=Begin; mStringValue=rName; mIntegerValue=0; mFloatValue=0; 00073 } 00074 00075 // Token::SetEnd(str) 00076 void Token::SetEnd(const std::string& rName) { 00077 mType=End; mStringValue=rName; mIntegerValue=0; mFloatValue=0; 00078 } 00079 00080 // Token::SetOption(str) 00081 void Token::SetOption(const std::string& rName) { 00082 mType=Option; mStringValue=rName; mIntegerValue=0; mFloatValue=0; 00083 } 00084 00085 // Token::SetInteger(number) 00086 void Token::SetInteger(const long int number) { 00087 mType=Integer; mStringValue=""; mIntegerValue=number; mFloatValue=number; 00088 } 00089 00090 // Token::SetInteger16(number) 00091 void Token::SetInteger16(const long int number) { 00092 mType=Integer16; mStringValue=""; mIntegerValue=number; mFloatValue=number; 00093 } 00094 00095 // Token::SetFloat(number) 00096 void Token::SetFloat(const double number) { 00097 mType=Float; mStringValue=""; mIntegerValue=(long int) number; mFloatValue=number; 00098 } 00099 00100 // Token::SetBinary 00101 void Token::SetBinary(const char* data, long int len) { 00102 mStringValue.assign(data,len); 00103 mType=Binary; 00104 } 00105 00106 00107 // ReadNumber(pStream) 00108 bool Token::ReadNumber(std::istream* pStream){ 00109 char c, vc; 00110 double fv=0; 00111 long int iv=0; 00112 int comma = -1; 00113 bool minus = false; 00114 int base=10; 00115 bool ok=false; 00116 int cnt=0; 00117 // check the whole pStream 00118 while(*pStream){ 00119 // check eof 00120 if (pStream->eof()) 00121 {mType=None; return(false);}; 00122 // check next charakter 00123 c = pStream->peek(); 00124 cnt++; 00125 // break if space 00126 if (isspace(c)) break; 00127 // change base on x 00128 if(c=='x' && iv==0 && cnt==2 && comma<0 && !minus) 00129 {pStream->get(); base = 16; continue;} 00130 // change sign on - 00131 if(c=='-' && cnt==1) 00132 {pStream->get(); minus = true; continue;} 00133 // record comma 00134 if(c=='.' && comma<0 && base==10) 00135 {pStream->get(); comma = 0; continue;} 00136 // read +infinity 00137 if(c=='i' && cnt==1) { 00138 ReadString(pStream,' '); 00139 if(mStringValue=="inf") 00140 {iv= std::numeric_limits<long int>::max(); fv= iv; break;} 00141 } 00142 // read -infinity 00143 if(c=='i' && cnt==2 && minus) { 00144 ReadString(pStream,' '); 00145 if(mStringValue=="inf") 00146 {iv=std::numeric_limits<long int>::min()+1; fv=iv; break;} 00147 } 00148 // break if it is not a digit 00149 if (!isdigit(c) && base==10) break; 00150 if (!isxdigit(c) && base==16) break; 00151 // get the next charakter 00152 pStream->get(); 00153 // compute the value of c 00154 vc=0; 00155 if(c>='0' && c<= '9') vc = c-'0'; 00156 else if(c>='a' && c<= 'f') vc = c-'a' + 10; 00157 else if(c>='A' && c<= 'F') vc = c-'A' + 10; 00158 // compute the corresponding number 00159 iv = base * iv + vc; 00160 fv = base * fv + vc; 00161 if(comma>=0) comma++; 00162 ok = true; 00163 } // termination with the end of the pStream or a non-digit or a space 00164 // fix sign 00165 if(minus) { 00166 iv=-iv; 00167 fv=-fv; 00168 } 00169 // fix decimal point 00170 for(;comma>0;comma--) { 00171 iv/=base; 00172 fv/=base; 00173 } 00174 // assign the numeric value and type in Token 00175 mIntegerValue = iv; 00176 mFloatValue = fv; 00177 mType= (comma>0 || minus) ? Float : Integer; 00178 if(base == 16) mType = Integer16; 00179 return(ok); 00180 } 00181 00182 // Write(pStream) 00183 void Token::Write(std::ostream* pStream){ 00184 FD_DV("Token::Write: mType=" << (int) mType 00185 << "\" mStringValue=\"" << mStringValue 00186 << "\" mIntegerValue=" <<mIntegerValue 00187 << "\" mFloatValue=" <<mFloatValue <<"\n"); 00188 // distuingish the token type 00189 switch (mType) { 00190 // <mStringValue> 00191 case Begin: 00192 *pStream << '<' << mStringValue << '>'; 00193 break; 00194 // </mStringValue> 00195 case End: 00196 *pStream << "</" << mStringValue << '>'; 00197 break; 00198 // "mStringValue" 00199 case String: 00200 WriteString(pStream,'"'); 00201 break; 00202 // +mStringValue+ 00203 case Option: 00204 *pStream << ExpandString("+"+mStringValue+"+", FD_NAMELEN); 00205 break; 00206 // mIntegerValue 00207 case Integer: 00208 *pStream << ExpandString(ToStringInteger(mIntegerValue), FD_NAMELEN); 00209 break; 00210 // mIntegerValue 00211 case Integer16: 00212 *pStream << ExpandString(ToStringInteger16(mIntegerValue), FD_NAMELEN); 00213 break; 00214 // mFloatValue 00215 case Float: 00216 *pStream << ExpandString(ToStringFloat(mFloatValue), FD_NAMELEN); 00217 break; 00218 // =BinaryData= 00219 case Binary: 00220 WriteBinary(pStream); 00221 break; 00222 // all other unexpected cases 00223 default: 00224 assert(0); 00225 } 00226 } 00227 00228 // WriteString(pStream, char) 00229 void Token::WriteString(std::ostream* pStream, char stop){ 00230 // assemble escape character string 00231 std::string escstr="\\"; 00232 escstr.append(1,stop); 00233 std::string stopstr; 00234 stopstr.append(1,stop); 00235 // no escape characters 00236 if(mStringValue.find_first_of(escstr)==std::string::npos) { 00237 *pStream << ExpandString(stopstr+mStringValue+stopstr, FD_NAMELEN); 00238 return; 00239 } 00240 // do escape substitution 00241 *pStream << stopstr; 00242 std::string::iterator cit=mStringValue.begin(); 00243 while(cit!=mStringValue.end()) { 00244 if(escstr.find_first_of(*cit)!=std::string::npos) *pStream << '\\'; 00245 *pStream << *cit; 00246 cit++; 00247 } 00248 *pStream << stopstr; 00249 *pStream << " "; 00250 } 00251 00252 // ReadString(pStream, char) 00253 int Token::ReadString(std::istream* pStream, char stop){ 00254 int lc=0; 00255 char c; 00256 bool escape=false; 00257 bool ctrlblank = false; 00258 mStringValue = ""; 00259 // check the whole pStream 00260 while (*pStream) { 00261 // check eof 00262 if (pStream->eof()) {mType=None; return -1;}; 00263 // get one character 00264 c = pStream->get(); 00265 // count the next lines 00266 if (c == '\n') ++lc; 00267 //replace sequence of control characters by one blanc 00268 if(iscntrl(c) && ctrlblank) continue; 00269 ctrlblank=false; 00270 if(iscntrl(c)) { c=' '; ctrlblank=true;} 00271 // if not in escape mode ... 00272 if(!escape) { 00273 // ... sense stop 00274 if(c == stop) break; 00275 // ... sense escape 00276 if(c == '\\') escape=true; 00277 // ... add character 00278 if(c != '\\') mStringValue.append(1,c); 00279 continue; 00280 } 00281 // else we are in escape mode: add verb and clear 00282 mStringValue.append(1,c); 00283 escape=false; 00284 } 00285 return lc; 00286 } 00287 00288 00289 // WriteVerbatim(pStream) 00290 void Token::WriteVerbatim(std::ostream* pStream, const std::string& rString){ 00291 // verb marker candidate 00292 std::string verb="__VERBATIM__"; 00293 // adjust marker 00294 while(rString.find(verb)!=std::string::npos) { 00295 verb = verb+"#"; 00296 } 00297 // do write 00298 *pStream << std::endl; 00299 *pStream << verb << std::endl; 00300 *pStream << rString; 00301 *pStream << verb << std::endl; 00302 } 00303 00304 00305 // ReadString(pStream, char) 00306 int Token::ReadVerbatim(std::istream* pStream){ 00307 // clear 00308 mStringValue = ""; 00309 std::string verb="_"; 00310 int lc=0; 00311 char c; 00312 // figure mark 00313 while(*pStream) { 00314 // check eof 00315 if(pStream->eof()) {mType=None; return -1;}; 00316 // get one character 00317 c = pStream->get(); 00318 // new line, control and space breaks 00319 if(c == '\n') { lc++; break; } 00320 if(iscntrl(c)) break; 00321 if(isblank(c)) break; 00322 // others get appended 00323 verb.append(1,c); 00324 } 00325 // read until mark 00326 while (*pStream) { 00327 // check eof 00328 if (pStream->eof()) {mType=None; return -1;}; 00329 // get one character 00330 c = pStream->get(); 00331 // count the next lines 00332 if (c == '\n') ++lc; 00333 // append anything 00334 mStringValue.append(1,c); 00335 // if c is _ or #, test for end 00336 if(c== verb.at(verb.size()-1)) { 00337 unsigned int vpos=mStringValue.find(verb); 00338 if(vpos!=std::string::npos) { 00339 mStringValue = mStringValue.substr(0,vpos); 00340 return lc; 00341 } 00342 } 00343 } 00344 return lc; 00345 } 00346 00347 // WriteBinary(pStream,data,len) 00348 void Token::WriteBinary(std::ostream* pStream, const char* pData, long int len) { 00349 00350 // my encoding (hardcoded in read, however) 00351 static char Base64EncodingTable[]= 00352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00353 00354 // start 00355 *pStream << "="; 00356 00357 // loop vars 00358 const char* src = pData; 00359 long int cnt=len; 00360 int step=0; 00361 unsigned char c0=0,c1=0,c2=0,c3=0; 00362 00363 // encode and output buffer 00364 while(cnt>0) { 00365 switch(step) { 00366 // collect char for 1st byte 00367 case 0: 00368 c0= ((*src & 0xFC) >> 2); 00369 c1= ((*src & 0x03) << 4); 00370 c2=0; 00371 c3=0; 00372 step=1; 00373 break; 00374 // collect char for 2nd byte 00375 case 1: 00376 c1|= ((*src & 0xF0) >> 4); 00377 c2|= ((*src & 0x0F) << 2); 00378 step=2; 00379 break; 00380 // collect char for 3rd byte, plus output 00381 case 2: 00382 c2|= ((*src & 0xC0) >> 6); 00383 c3|= (*src & 0x3F); 00384 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 00385 Base64EncodingTable[c2] << Base64EncodingTable[c3]; 00386 step=0; 00387 break; 00388 default: break; 00389 } 00390 cnt--; 00391 src++; 00392 } 00393 // flush left overs, incl padding 00394 switch(step) { 00395 case 0: 00396 *pStream << "= "; 00397 break; 00398 case 1: 00399 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << "=== "; 00400 break; 00401 case 2: 00402 *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 00403 Base64EncodingTable[c2] << "== "; 00404 break; 00405 } 00406 } 00407 00408 // WriteBinary(pStream) 00409 void Token::WriteBinary(std::ostream* pStream){ 00410 if(mType!=Binary) return; 00411 WriteBinary(pStream,mStringValue.data(),mStringValue.size()); 00412 } 00413 00414 00415 // ReadBinary ... to mStringValue 00416 int Token::ReadBinary(std::istream* pStream) { 00417 00418 // line count 00419 int lc; 00420 00421 // read as string, excl. marks '=' 00422 lc=ReadString(pStream,'='); 00423 00424 // take extra trailing padding = 00425 while(!pStream->eof()) { 00426 if(pStream->peek()!='=') break; 00427 pStream->get(); 00428 mStringValue.append("="); 00429 } 00430 00431 // loop vars 00432 std::string::iterator src=mStringValue.begin(); 00433 std::string::iterator dst=mStringValue.begin(); 00434 long int cnt=0; 00435 int c=0, d0=0, d1=0, d2=0; 00436 unsigned char cs[4]; 00437 unsigned int step=0; 00438 00439 // loop 00440 while(true) { 00441 00442 // get data 00443 while(true) { 00444 // sense eof 00445 if(src==mStringValue.end()) { c = -1; break; } 00446 // get char 00447 c=*(src++); 00448 // decode 00449 if(c>='A' && c <='Z') { c-='A'; break; } 00450 if(c>='a' && c <='z') { c-='a'; c+= ('Z'-'A')+1; break; } 00451 if(c>='0' && c <='9') { c-='0'; c+= 2*('Z'-'A')+2; break; } 00452 if(c=='+') {c= 62; break; } 00453 if(c=='/') {c= 63; break; } 00454 if(c=='=') {c= 0xFF; break; }; 00455 } 00456 // pass on eof 00457 if(c== -1) break; 00458 // record and continue 00459 cs[step++] = c; 00460 if(step<=3) continue; 00461 step=0; 00462 // sort bits 00463 d0= ((cs[0] << 2) & 0xFC) | ((cs[1] >> 4) & 0x03); 00464 d1= ((cs[1] << 4) & 0xF0) | ((cs[2] >> 2) & 0x0F); 00465 d2= ((cs[2] << 6) & 0xC0) | (cs[3] & 0x3F); 00466 // record result 00467 if(cs[0]!= 0xFF && cs[1]!=0xFF) {*(dst++)=d0; cnt++;} 00468 if(cs[1]!= 0xFF && cs[2]!=0xFF) {*(dst++)=d1; cnt++;} 00469 if(cs[2]!= 0xFF && cs[3]!=0xFF) {*(dst++)=d2; cnt++;} 00470 // sense end 00471 if(cs[3]==0xFF) break; 00472 } 00473 00474 // set data length (sets the length incl termination char??) 00475 mStringValue.resize(cnt); 00476 00477 // return padding error or line count 00478 return step==0 ? lc : -1; 00479 } 00480 00481 00482 00483 // ReadSpace(pStream) 00484 int Token::ReadSpace(std::istream* pStream){ 00485 char c = '\0'; 00486 int lc = 0; 00487 // check the whole pStream 00488 while (*pStream) { 00489 while (*pStream) { 00490 // check eof 00491 if (pStream->eof()) {return(lc);}; 00492 // look one character ahead 00493 c = pStream->peek(); 00494 // break if the next character is 00495 if((! isspace(c)) && (! iscntrl(c))) break; 00496 // not a space or a control character 00497 // get the next space or control character 00498 pStream->get(); 00499 // count the next lines 00500 if(c == '\n') ++lc; 00501 } 00502 // if the next charakter starts a comment 00503 if (c != '%') break; 00504 while (*pStream) { 00505 // check eof 00506 if (pStream->eof()) {return(lc);}; 00507 // get the next character 00508 c = pStream->get(); 00509 // count the next lines 00510 if (c == '\n') ++lc; 00511 // terminate with the next new line character 00512 if (c == '\n') break; 00513 if (c == '\r') break; 00514 } 00515 } 00516 // termination if the next character is not a space, a control character 00517 //or a '%'. 00518 return (lc); 00519 } 00520 00521 // Read(pStream) 00522 int Token::Read(std::istream* pStream){ 00523 char c1, c2; 00524 int lc = 0; 00525 int ll; 00526 // the token is initialized with the type "None" 00527 SetNone(); 00528 // check eof 00529 if (pStream->eof()) return(lc); 00530 // read all spaces in the pStream 00531 lc += ReadSpace(pStream); 00532 // check eof 00533 if (pStream->eof()) return(lc); 00534 // get the first useful character 00535 c1 = pStream->peek(); 00536 if (isdigit(c1) || (c1=='-') || (c1=='i') ) { 00537 // token is a number if the character is a digit, a sign or i(nfinity) 00538 ReadNumber(pStream); 00539 } 00540 // token is a string if it starts with '"' 00541 else if (c1 == '"') { 00542 pStream->get(); 00543 // read the string until '"' 00544 ll=ReadString(pStream,'"'); 00545 lc+=ll; 00546 if(ll>=0) mType = String; 00547 } 00548 // token is an option string if it starts with '+' 00549 else if (c1 == '+') { 00550 pStream->get(); 00551 // read the string until '+' 00552 ll=ReadString(pStream,'+'); 00553 lc+=ll; 00554 if(ll>=0) mType = Option; 00555 } 00556 // token is a binary string if it starts with '=' 00557 else if (c1 == '=') { 00558 pStream->get(); 00559 // read the string until '=', incl padding 00560 ll=ReadBinary(pStream); 00561 lc+=ll; 00562 if(ll>=0) mType = Binary; 00563 } 00564 // token is a string if it starts with '_' 00565 else if (c1 == '_') { 00566 pStream->get(); 00567 // read the string until the corresponding end marker 00568 ll=ReadVerbatim(pStream); 00569 lc+=ll; 00570 if(ll>=0) mType = String; 00571 } 00572 // token is of type begin or end if it starts with < 00573 else if (c1 == '<') { 00574 pStream->get(); 00575 // check eof 00576 if (pStream->eof()) return(lc); 00577 c2 = pStream->peek(); 00578 // token is of type "begin" if it starts with < 00579 if(c2 != '/') { 00580 if(ReadString(pStream,'>')>=0) mType = Begin; 00581 } 00582 else { 00583 // token is of type "end" if it starts with </ 00584 pStream->get(); 00585 // read the string until '>' 00586 if(ReadString(pStream,'>')>=0) mType = End; 00587 } 00588 } 00589 FD_DV("Token::Read: char1='" << c1 << "' mType=" << (int) mType 00590 << "\" mStringValue=\"" << mStringValue 00591 << "\" mIntegerValue=" << mIntegerValue 00592 << "\" mFloatValue=" << mFloatValue <<"\n"); 00593 return(lc); 00594 } 00595 00596 } // namespace faudes |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3