libFAUDES

Sections

Index

token.cpp

Go 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