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