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

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen