libFAUDES

Sections

Index

cfl_token.cpp

Go 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