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

libFAUDES 2.22s --- 2013.10.07 --- c++ source docu by doxygen