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   mAttributeCount(0)
00036 { 
00037 }
00038 
00039 // copy construct
00040 Token::Token(const Token& rToken) :
00041   mType(rToken.mType), 
00042   mStringValue(rToken.mStringValue), 
00043   mOptionValue(rToken.mOptionValue), 
00044   mIntegerValue(rToken.mIntegerValue), 
00045   mFloatValue(rToken.mFloatValue),
00046   mAttributes(rToken.mAttributes),
00047   mAttributeCount(rToken.mAttributeCount)
00048 { 
00049 }
00050 
00051 
00052 // assignment
00053 Token& Token::operator=(const Token& rToken) {
00054   mType=rToken.mType; 
00055   mStringValue=rToken.mStringValue; 
00056   mOptionValue=rToken.mOptionValue; 
00057   mIntegerValue=rToken.mIntegerValue; 
00058   mFloatValue=rToken.mFloatValue;
00059   mAttributes=rToken.mAttributes;
00060   mAttributeCount=rToken.mAttributeCount;
00061   return *this;
00062 }
00063 
00064 // destructor
00065 Token::~Token(void){
00066 }
00067 
00068 // Token::SetNone()
00069 void Token::SetNone(void ) {
00070   mType=None; 
00071   mStringValue=""; 
00072   mOptionValue=""; 
00073   mIntegerValue=0; 
00074   mFloatValue=0;
00075   mAttributes.clear();
00076   mAttributeCount=0;
00077 }
00078 
00079 // Token::SetString(str)
00080 void Token::SetString(const std::string& rName) {
00081   SetNone();
00082   mType=String; 
00083   mStringValue=rName; 
00084 }
00085 
00086 // Token::SetBegin(str)
00087 void Token::SetBegin(const std::string& rName) {
00088   SetNone();
00089   mType=Begin; 
00090   mStringValue=rName; 
00091 }
00092 
00093 // Token::SetEnd(str)
00094 void Token::SetEnd(const std::string& rName) {
00095   SetNone();
00096   mType=End; 
00097   mStringValue=rName; 
00098 }
00099 
00100 // Token::SetEmpty(str)
00101 void Token::SetEmpty(const std::string& rName) {
00102   SetNone();
00103   mType=End | Begin; 
00104   mStringValue=rName; 
00105 }
00106 
00107 // Token::SetOption(str)
00108 void Token::SetOption(const std::string& rName) {
00109   SetNone();
00110   mType=Option | String; 
00111   mStringValue="+"+rName+"+"; 
00112   mOptionValue=rName; 
00113 }
00114 
00115 // Token::SetInteger(number)
00116 void Token::SetInteger(const long int number) {
00117   SetNone();
00118   mType=Integer | Float; 
00119   mIntegerValue=number; 
00120   mFloatValue=number;
00121 }
00122 
00123 // Token::SetInteger16(number)
00124 void Token::SetInteger16(const long int number) {
00125   SetNone();
00126   mType= Integer16 | Integer | Float; 
00127   mIntegerValue=number; 
00128   mFloatValue=number;
00129 }
00130 
00131 // Token::SetBoolean(number)
00132 void Token::SetBoolean(const long int number) {
00133   SetNone();
00134   mType= Boolean | Integer | Float; 
00135   mIntegerValue=number; 
00136   mFloatValue=number;
00137 }
00138 
00139 // Token::SetFloat(number)
00140 void Token::SetFloat(const double number) {
00141   SetNone();
00142   mType=Float; 
00143   mIntegerValue=(long int) number; 
00144   mFloatValue=number;
00145 }
00146 
00147 // Token::SetBinary
00148 void Token::SetBinary(const char* data, long int len) {
00149   SetNone();
00150   mType=Binary | String;
00151   mStringValue.assign(data,len);
00152 }
00153 
00154 
00155 // access integer
00156 long int Token::IntegerValue(void) const {
00157   return(mIntegerValue);
00158 }
00159 
00160 
00161 // access float
00162 double Token::FloatValue(void) const {
00163   return(mFloatValue);
00164 }
00165 
00166 // access string
00167 const std::string& Token::StringValue(void) const {
00168   if(mType & Option) return(mOptionValue); // compatibility
00169   return(mStringValue);
00170 }
00171 
00172 // access option
00173 const std::string& Token::OptionValue(void) const {
00174   return(mOptionValue);
00175 }
00176 
00177 // access unique type (depreciated!)
00178 Token::TokenType Token::Type(void) const {
00179   if(mType & Begin)  return Begin;
00180   if(mType & End)    return End;
00181   if(mType & Integer16) return Integer16;
00182   if(mType & Boolean) return Boolean;
00183   if(mType & Integer) return Integer;
00184   if(mType & Float) return Float;
00185   if(mType & Option) return Option;
00186   if(mType & Binary) return Binary;
00187   if(mType & String) return String;
00188   return None;
00189 }
00190 
00191 
00192 // test type
00193 bool Token::IsNone(void) const {
00194   return mType == None;
00195 }
00196 
00197 // test type
00198 bool Token::IsInteger(void) const {
00199   return mType & Integer;
00200 }
00201 
00202 // test type
00203 bool Token::IsInteger16(void) const {
00204   return mType & Integer16;
00205 }
00206 
00207 // test type
00208 bool Token::IsBoolean(void) const {
00209   return mType & Boolean;
00210 }
00211 
00212 // test type
00213 bool Token::IsFloat(void) const {
00214   return mType & Float;
00215 }
00216 
00217 // test type
00218 bool Token::IsOption(void) const {
00219   return mType & Option;
00220 }
00221 
00222 // test type
00223 bool Token::IsString(void) const {
00224   return mType & String;
00225 }
00226 
00227 // test type
00228 bool Token::IsBinary(void) const {
00229   return mType & Binary;
00230 }
00231 
00232 // test type
00233 bool Token::IsBegin(void) const {
00234   return mType & Begin;
00235 }
00236 
00237 // test type
00238 bool Token::IsEnd(void) const {
00239   return mType & End;
00240 }
00241 
00242 
00243 // clear attribute
00244 void Token::ClrAttribute(const std::string& name) {
00245   aiterator ait=mAttributes.find(name);
00246   if(ait==mAttributes.end()) return;
00247   mAttributes.erase(ait);
00248 }
00249 
00250 // clear all attributes
00251 void Token::ClearAttributes() {
00252   mAttributes.clear();
00253   mAttributeCount=0;
00254 }
00255 
00256 
00257 // insert attribute for interpretation
00258 void Token::InsAttribute(const std::string& name, const std::string& value) {
00259   AttributeValue aval;
00260   aval.mStringValue=value;
00261   aval.mType=None;
00262   aval.mSort=mAttributeCount++;
00263   mAttributes[name]=aval;
00264 }
00265 
00266 
00267 // insert string attribute
00268 void Token::InsAttributeString(const std::string& name, const std::string& value) {
00269   AttributeValue aval;
00270   aval.mStringValue=value;
00271   aval.mType=String;
00272   aval.mSort=mAttributeCount++;
00273   mAttributes[name]=aval;
00274 }
00275 
00276 // insert integer attribute
00277 void Token::InsAttributeInteger(const std::string& name, long int value) {
00278   AttributeValue aval;
00279   aval.mStringValue=ToStringInteger(value);
00280   aval.mType=Float | Integer;
00281   aval.mSort=mAttributeCount++;
00282   mAttributes[name]=aval;
00283 }
00284 
00285 // insert integer attribute
00286 void Token::InsAttributeInteger16(const std::string& name, long int value) {
00287   AttributeValue aval;
00288   aval.mStringValue=ToStringInteger16(value);
00289   aval.mType=Float | Integer;
00290   aval.mSort=mAttributeCount++;
00291   mAttributes[name]=aval;
00292 }
00293 
00294 // insert integer attribute
00295 void Token::InsAttributeBoolean(const std::string& name, long int value) {
00296   AttributeValue aval;
00297   if(value==0) aval.mStringValue="false";
00298   else aval.mStringValue="true";
00299   aval.mType=Float | Integer;
00300   aval.mSort=mAttributeCount++;
00301   mAttributes[name]=aval;
00302 }
00303 
00304 // insert float attribute
00305 void Token::InsAttributeFloat(const std::string& name, double value) {
00306   AttributeValue aval;
00307   aval.mStringValue=ToStringFloat(value);
00308   aval.mType=Float;
00309   aval.mSort=mAttributeCount++;
00310   mAttributes[name]=aval;
00311 }
00312 
00313 // test attribute type
00314 bool Token::ExistsAttributeString(const std::string& name) {
00315   aiterator ait=mAttributes.find(name);
00316   if(ait==mAttributes.end()) return false;
00317   InterpretAttribute(ait);
00318   if(ait->second.mType & String) return true;
00319   return false;
00320 }
00321 
00322 
00323 // test attribute type
00324 bool Token::ExistsAttributeInteger(const std::string& name) {
00325   aiterator ait=mAttributes.find(name);
00326   if(ait==mAttributes.end()) return false;
00327   InterpretAttribute(ait);
00328   if(ait->second.mType & Integer) return true;
00329   return false;
00330 }
00331 
00332 
00333 // test attribute type
00334 bool Token::ExistsAttributeFloat(const std::string& name) {
00335   aiterator ait=mAttributes.find(name);
00336   if(ait==mAttributes.end()) return false;
00337   InterpretAttribute(ait);
00338   if(ait->second.mType & Float) return true;
00339   return false;
00340 }
00341 
00342 
00343 // access attribute value
00344 const std::string& Token::AttributeStringValue(const std::string& name) {
00345   static const  std::string emptystr="";
00346   aiterator ait=mAttributes.find(name);
00347   if(ait==mAttributes.end()) return emptystr;
00348   InterpretAttribute(ait);
00349   if(!(ait->second.mType & String)) return emptystr;
00350   return ait->second.mStringValue;
00351 }
00352 
00353 
00354 // access attribute value
00355 long int Token::AttributeIntegerValue(const std::string& name) {
00356   aiterator ait=mAttributes.find(name);
00357   if(ait==mAttributes.end()) return 0;
00358   InterpretAttribute(ait);
00359   if(!(ait->second.mType & Integer)) return 0;
00360   return ait->second.mIntegerValue;
00361 }
00362 
00363 
00364 // access attribute value
00365 double Token::AttributeFloatValue(const std::string& name) {
00366   aiterator ait=mAttributes.find(name);
00367   if(ait==mAttributes.end()) return 0;
00368   InterpretAttribute(ait);
00369   if(!(ait->second.mType & Float)) return 0;
00370   return ait->second.mFloatValue;
00371 }
00372 
00373 
00374 // WriteVerbatim(pStream)
00375 void Token::WriteVerbatim(std::ostream* pStream, const std::string& rString) {
00376   // verb marker candidate
00377   std::string verb="__VERBATIM__";
00378   // adjust marker
00379   while(rString.find(verb)!=std::string::npos) {
00380     verb = verb+"#";
00381   }
00382   // do write
00383   *pStream << std::endl;
00384   *pStream << verb << std::endl;
00385   *pStream << rString;
00386   *pStream << verb << std::endl;
00387 }
00388 
00389 
00390 // ReadString(pStream, char)
00391 int Token::ReadVerbatim(std::istream* pStream){
00392   // clear
00393   mStringValue = "";
00394   std::string verb="";
00395   int lc=0;
00396   char c;
00397   // figure mark
00398   while(*pStream) {
00399     // check eof
00400     if(pStream->eof()) {mType=None; return -1;}; 
00401     // get one character
00402     c = pStream->get();
00403     // new line, control and space  breaks
00404     if(c == '\n')  { lc++; break; }
00405     if(iscntrl(c)) break;
00406     if(isblank(c)) break;
00407     // others get appended
00408     verb.append(1,c);
00409   }
00410   // test
00411   if(verb.size()<2) return -1;
00412   if(verb.at(0) !='_') return -1;
00413   if(verb.at(1) !='_') return -1;
00414   // read until mark
00415   while(*pStream) {
00416     // check eof
00417     if (pStream->eof()) {mType=None; return -1;}; 
00418     // get one character
00419     c = pStream->get();
00420     // count the next lines
00421     if (c == '\n') ++lc; 
00422     // append anything
00423     mStringValue.append(1,c);
00424     // if c is _ or #, test for end
00425     if(c== verb.at(verb.size()-1)) { 
00426       unsigned int vpos=mStringValue.find(verb);
00427       if(vpos!=std::string::npos) {
00428         mStringValue = mStringValue.substr(0,vpos);
00429         return lc;
00430        }
00431     }
00432   }
00433   return lc;
00434 }
00435 
00436 // WriteBinary(pStream,data,len)
00437 void Token::WriteBinary(std::ostream* pStream,  const char* pData, long int len) {
00438 
00439   // my encoding (hardcoded in read, however)
00440   static char Base64EncodingTable[]=
00441     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00442 
00443   // start
00444   *pStream << "=";
00445 
00446   // loop vars
00447   const char* src = pData;
00448   long int cnt=len;
00449   int step=0;
00450   unsigned char c0=0,c1=0,c2=0,c3=0;
00451 
00452   // encode and output buffer
00453   while(cnt>0) {
00454     switch(step) {
00455     // collect char for 1st byte
00456     case 0:
00457       c0=  ((*src & 0xFC) >> 2);
00458       c1=  ((*src & 0x03) << 4);
00459       c2=0;
00460       c3=0;
00461       step=1;
00462       break;
00463     // collect char for 2nd byte
00464     case 1:
00465       c1|= ((*src & 0xF0) >> 4);
00466       c2|= ((*src & 0x0F) << 2);
00467       step=2;
00468       break;
00469     // collect char for 3rd byte, plus output
00470     case 2:
00471       c2|= ((*src & 0xC0) >> 6);
00472       c3|= (*src & 0x3F); 
00473       *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 
00474         Base64EncodingTable[c2]  << Base64EncodingTable[c3]; 
00475       step=0;
00476       break;
00477     default: break;
00478     }
00479     cnt--;
00480     src++;
00481   }   
00482   // flush left overs, incl padding
00483   switch(step) {
00484    case 0:
00485      *pStream << "= ";
00486      break;
00487    case 1:
00488      *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << "=== ";
00489      break;
00490    case 2:
00491      *pStream << Base64EncodingTable[c0] << Base64EncodingTable[c1] << 
00492        Base64EncodingTable[c2]  << "== ";
00493      break;
00494   }
00495 }
00496 
00497 // WriteBinary(pStream)
00498 void Token::WriteBinary(std::ostream* pStream) const {
00499   if(mType!=Binary) return;
00500   WriteBinary(pStream,mStringValue.data(),mStringValue.size());
00501 }
00502 
00503 
00504 // ReadBinary ... to mStringValue
00505 int Token::ReadBinary(std::istream* pStream) {
00506   
00507   // line count
00508   int lc;
00509 
00510   // swallow leading '='  
00511   char c1=pStream->get();
00512   if(c1!='=') return -1;
00513 
00514   // read as string, excl. marks '='
00515   lc=ReadString(pStream,'=');
00516 
00517   // swallow one trailing '=' 
00518   c1=pStream->get();
00519   if(c1!='=') return -1;
00520 
00521   // take any extra trailing padding =
00522   while(!pStream->eof()) {
00523     if(pStream->peek()!='=') break;
00524     pStream->get();
00525     mStringValue.append("=");
00526   }
00527 
00528   // loop vars
00529   std::string::iterator src=mStringValue.begin();
00530   std::string::iterator dst=mStringValue.begin();
00531   long int cnt=0;
00532   int c=0, d0=0, d1=0, d2=0;
00533   unsigned char cs[4];
00534   unsigned int step=0;
00535 
00536   // loop
00537   while(true) {
00538     
00539     // get data
00540     while(true) {
00541       // sense eof
00542       if(src==mStringValue.end()) { c = -1; break; }
00543       // get char
00544       c=*(src++);
00545       // decode
00546       if(c>='A' && c <='Z') { c-='A'; break; }
00547       if(c>='a' && c <='z') { c-='a'; c+= ('Z'-'A')+1; break; }
00548       if(c>='0' && c <='9') { c-='0'; c+= 2*('Z'-'A')+2; break; }
00549       if(c=='+') {c= 62; break; }
00550       if(c=='/') {c= 63; break; }
00551       if(c=='=') {c= 0xFF; break; };
00552     }
00553     // pass on eof
00554     if(c== -1) break;
00555     // record and continue
00556     cs[step++] = c;
00557     if(step<=3) continue;
00558     step=0;
00559     // sort bits
00560     d0= ((cs[0] << 2) & 0xFC) | ((cs[1] >> 4) & 0x03);
00561     d1= ((cs[1] << 4) & 0xF0) | ((cs[2] >> 2) & 0x0F);
00562     d2= ((cs[2] << 6) & 0xC0) | (cs[3] & 0x3F);
00563     // record result
00564     if(cs[0]!= 0xFF && cs[1]!=0xFF) {*(dst++)=d0; cnt++;}
00565     if(cs[1]!= 0xFF && cs[2]!=0xFF) {*(dst++)=d1; cnt++;}
00566     if(cs[2]!= 0xFF && cs[3]!=0xFF) {*(dst++)=d2; cnt++;}
00567     // sense end
00568     if(cs[3]==0xFF) break;
00569   }   
00570 
00571   // set data length (sets the length incl termination char??)
00572   mStringValue.resize(cnt);
00573  
00574   // return padding error or line count
00575   return step==0 ? lc : -1;
00576 }
00577 
00578 
00579 
00580 // ReadSpace(pStream)
00581 int Token::ReadSpace(std::istream* pStream){
00582   char c = '\0';
00583   int lc = 0;
00584   FD_DV("Token::ReadSpace()");
00585   // check the whole pStream
00586   while(*pStream) {
00587     while(*pStream) {
00588       // check eof
00589       if (pStream->eof()) return lc; 
00590       // look one character ahead
00591       c = pStream->peek();
00592       // break if the next character is 
00593       // not a space or a control character
00594       if((! isspace(c)) && (! iscntrl(c))) break;
00595       // get the next space or control character
00596       pStream->get();
00597       // count the next lines
00598       if(c == '\n') ++lc;
00599     }
00600     // if the next charakter starts a faudes comment
00601     if(c != '%') break;
00602     while (*pStream) {
00603       // check eof
00604       if (pStream->eof()) {return(lc);}; 
00605       // get the next character
00606       c = pStream->get();
00607       // count the next lines
00608       if (c == '\n') ++lc;
00609       // terminate with the next new line  character
00610       if (c == '\n') break;
00611       if (c == '\r') break;
00612     }
00613   }
00614   // termination if the next character is neither a space, a control, or a '%'.
00615   FD_DV("Token::ReadSpace(): lc " << lc);
00616   return lc; 
00617 }
00618 
00619 // InterpretAttribute(aval)
00620 void Token::InterpretAttribute(aiterator ait) {
00621   if(ait->second.mType != None) return;
00622   InterpretNumber(
00623     ait->second.mStringValue, ait->second.mType, 
00624     ait->second.mIntegerValue, ait->second.mFloatValue);
00625   ait->second.mType |= String; 
00626 }
00627 
00628 // InterpretNumber(string)
00629 bool Token::InterpretNumber(void) {
00630   return InterpretNumber(mStringValue,mType,mIntegerValue,mFloatValue);
00631 }
00632 
00633 // InterpretNumber(string, ...)
00634 bool Token::InterpretNumber(const std::string& numstr, int& type, long int& ival, double& fval) {
00635   char c, vc;
00636   double fv=0;
00637   long int iv=0;
00638   int comma = -1;
00639   bool minus = false;
00640   int  base=10;
00641   bool ok=false;
00642   int cnt=0;
00643   type &= ~(Integer | Integer16 | Float);
00644   // test for special cases
00645   if(numstr=="inf" || numstr=="+inf") {
00646     ival = std::numeric_limits<long int>::max();
00647     fval = ival;
00648     type|= (Integer | Float );
00649     return true;
00650   }
00651   // test for special casess
00652   if(numstr=="-inf") {
00653     ival=std::numeric_limits<long int>::min()+1; 
00654     fval=ival;
00655     type|= (Integer | Float);
00656     return true;
00657   }
00658   // test for special cases
00659   if(numstr=="true" || numstr=="True") {
00660     ival = 1;
00661     fval = ival;
00662     type|= (Integer | Boolean);
00663     return true;
00664   }
00665   // test for special cases
00666   if(numstr=="false" || numstr=="False") {
00667     ival = 0;
00668     fval = ival;
00669     type|= (Integer | Boolean);
00670     return true;
00671   }
00672   // iterate over string
00673   std::string::const_iterator cit=numstr.begin();
00674   for(;cit!=numstr.end(); cit++) {
00675     // check next charakter
00676     c = *cit;
00677     cnt++;
00678     // change base on x
00679     if(c=='x' && iv==0 && cnt==2 && comma<0 && !minus) 
00680       {base = 16; continue;}
00681     // change sign on -
00682     if(c=='-' && cnt==1) 
00683       {minus = true; continue;}
00684     // record comma
00685     if(c=='.' && comma<0 && base==10) 
00686       {comma = 0; continue;}
00687     // break if it is not a digit
00688     if(!isdigit(c) && base==10) break;
00689     if(!isxdigit(c) && base==16) break;
00690     // compute the value of c
00691     vc=0;
00692     if(c>='0' && c<= '9') vc = c-'0';
00693     else if(c>='a' && c<= 'f') vc = c-'a' + 10;
00694     else if(c>='A' && c<= 'F') vc = c-'A' + 10;
00695     // compute the corresponding number
00696     iv = base * iv + vc;
00697     fv = base * fv + vc;
00698     if(comma>=0) comma++;
00699     ok = true; 
00700   } 
00701   // detect error
00702   if(cit!=numstr.end()) ok=false;
00703   // fix sign
00704   if(minus) {
00705     iv=-iv;
00706     fv=-fv;
00707   }
00708   // fix decimal point
00709   for(;comma>0;comma--) {
00710     iv/=base;
00711     fv/=base;
00712   }
00713   // assign the numeric value and type in Token
00714   if(ok) {
00715     ival = iv;
00716     fval = fv;
00717     type |= Float;
00718     if(comma<=0 && !minus) type |= Integer;
00719     if(comma<=0 && !minus && base==16) type |= Integer16;
00720   }
00721   return ok;
00722 }
00723 
00724 // Write(pStream)
00725 void Token::Write(std::ostream* pStream) const {
00726   FD_DV("Token::Write: mType=" << (int) mType 
00727   << "\" mStringValue=\"" << mStringValue 
00728   << "\" mIntegerValue=" <<mIntegerValue 
00729   << "\" mFloatValue=" <<mFloatValue <<"\n");
00730   // numerics first
00731   if(mType & Integer16) {
00732     *pStream << ExpandString(ToStringInteger16(mIntegerValue), FD_NAMELEN) << " ";
00733   } else if(mType & Integer) { 
00734     *pStream << ExpandString(ToStringInteger(mIntegerValue), FD_NAMELEN) << " ";
00735   } else if(mType & Float) { 
00736     *pStream << ExpandString(ToStringFloat(mFloatValue), FD_NAMELEN) << " ";
00737   }
00738   // mark up: begin
00739   else if(mType & Begin) {
00740     *pStream << '<' << mStringValue;
00741     std::map<int,caiterator> sortnames;
00742     for(caiterator ait=mAttributes.begin(); ait!=mAttributes.end(); ait++) 
00743       sortnames[ait->second.mSort]=ait;
00744     std::map<int,caiterator>::iterator sit;
00745     for(sit=sortnames.begin(); sit!=sortnames.end(); sit++) {
00746       caiterator ait=sit->second;
00747       *pStream << " ";
00748       WriteEscapedString(pStream,ait->first);
00749       *pStream << "=\"";
00750       WriteEscapedString(pStream,ait->second.mStringValue);
00751       *pStream << "\"";
00752     }
00753     if(mType & End) *pStream << "/";
00754     *pStream << "> ";
00755   } 
00756   // mark up:end
00757   else if(mType & End) {
00758     *pStream << "</" << mStringValue << "> ";
00759   }
00760   // string
00761   else if(mType & Option) {
00762     WriteString(pStream,""); // '+' is incl. mStringValue
00763   } else if(mType & Binary) {
00764      WriteBinary(pStream);
00765   } else if(mType & String) {
00766     // figure delimiter
00767     bool quote=false;
00768     if(mStringValue.size()==0) quote=true;
00769     if(mStringValue.size()>0)
00770       if(!isalpha(mStringValue[0])) quote=true;
00771     static const std::string white=" \n\r\t\f";
00772     if(mStringValue.find_first_of(white)!=std::string::npos) 
00773       quote=true;
00774     if(quote)
00775       WriteString(pStream,"\"");
00776     else
00777       WriteString(pStream,"");
00778   } 
00779   // error (should we have an exception here?)
00780   else { /*  assert(0) */ };
00781 }
00782 
00783 // WriteEscapedString(pStream)
00784 int Token::WriteEscapedString(std::ostream* pStream, const std::string& outstr) {
00785   // assemble escape character string
00786   std::string escstr="<>&\"";
00787   // no escape characters
00788   if(outstr.find_first_of(escstr)==std::string::npos) {
00789     *pStream << outstr;
00790     return outstr.size();
00791   }
00792   // do escape substitution
00793   int cc=0;
00794   std::string::const_iterator cit=outstr.begin(); 
00795   for(;cit!=outstr.end(); cit++) {
00796     if(*cit=='<') 
00797       { *pStream << "&lt;"; cc+=4; continue;}
00798     if(*cit=='>') 
00799       { *pStream << "&gt;"; cc+=4; continue;}
00800     if(*cit=='&') 
00801       { *pStream << "&amp;"; cc+=5; continue;}
00802     if(*cit=='"')  
00803       { *pStream << "&quot;"; cc+=6; continue;}
00804     *pStream << *cit; cc++;
00805   }
00806   return cc;
00807 }
00808 
00809 // WriteString(pStream, delim)
00810 void Token::WriteString(std::ostream* pStream, const std::string& delim) const {
00811   int cc=0; 
00812   *pStream << delim;
00813   cc+=delim.size();
00814   cc+=WriteEscapedString(pStream,mStringValue);
00815   *pStream << delim << " ";
00816   cc+=delim.size()+1;
00817   while(cc< FD_NAMELEN) {
00818     *pStream << " "; cc++;
00819   }  
00820 }
00821 
00822 // ReadString(pStream, char)
00823 int Token::ReadString(std::istream* pStream, char stop) {
00824   int ll= ReadEscapedString(pStream,stop,mStringValue);
00825   if(ll<0) mType=None; 
00826   return ll;
00827 }
00828 
00829 
00830 // ReadEscapedString(pStream, rString, char)
00831 int Token::ReadEscapedString(std::istream* pStream, char stop, std::string& rString) {
00832   int lc=0;
00833   char c;
00834   std::string entref="";
00835   bool ctrlblank = false;
00836   rString = "";
00837   // check the whole pStream
00838   while (*pStream) {
00839     // check eof
00840     if(pStream->eof()) return -1;
00841     // test one character
00842     c = pStream->peek();
00843     // break on mark up
00844     if(c == '<') break;
00845     // break on stop
00846     if(c == stop) break;
00847     if(isblank(c) && stop==' ') break;
00848     if(iscntrl(c) && stop==' ') break;
00849     // get one character
00850     c = pStream->get();
00851     // count the next lines
00852     if(c=='\n') ++lc;
00853     // replace sequence of control characters by one blanc
00854     if(iscntrl(c) && ctrlblank) continue;
00855     ctrlblank=false;
00856     if(iscntrl(c)) { c=' '; ctrlblank=true;}
00857     // if in escape mode ...
00858     if(entref.size()!=0) {
00859       //record reference
00860       entref.append(1,c);
00861       // error: reference must not contain a white space
00862       if(c == ' ') return -1;
00863       // decode reference
00864       if(c == ';') {
00865         if(entref=="&amp;") rString.append(1,'&'); 
00866         else if(entref=="&quot;") rString.append(1,'"'); 
00867         else if(entref=="&apos;") rString.append(1,'\''); 
00868         else if(entref=="&lt;") rString.append(1,'<');
00869         else if(entref=="&gt;") rString.append(1,'>');
00870         // ignore unknown
00871         entref="";
00872       }
00873       continue;
00874     }
00875     // ... sense escape
00876     if(c == '&') entref.append(1,c);
00877     // ... add character
00878     if(c != '&') rString.append(1,c);
00879     continue;
00880   } 
00881   return lc;
00882 }
00883 
00884 
00885 // ReadAttributes(pStream)
00886 int Token::ReadAttributes(std::istream* pStream) {
00887   int lc=0;
00888   char c=0;
00889   FD_DV("Token::ReadAttributes()");
00890   // scan until excl. '>'
00891   while (*pStream) {
00892     // skip space
00893     char c2=c;
00894     while (*pStream) {
00895       if(pStream->eof()) return -1; 
00896       c2=c;
00897       c = pStream->peek();
00898       if(!(isblank(c) || iscntrl(c))) break;
00899       pStream->get();
00900       if(c=='\n') ++lc;
00901     }
00902     // get attrname
00903     std::string aname;
00904     while (*pStream) {
00905       if(pStream->eof()) return -1; 
00906       c = pStream->peek();
00907       if(isblank(c) || iscntrl(c)) break;
00908       if(c=='=') break;
00909       if(c=='>') break;
00910       if(c=='/') break;
00911       pStream->get();
00912       aname.append(1,c); 
00913     }
00914     FD_DV("Token::ReadAttributes(): aname " << aname);
00915     // no name so we're done
00916     if(aname.size()==0) {
00917       if(c=='/') {
00918         mType |= End;
00919         pStream->get(); 
00920         c=pStream->peek();
00921       }  
00922       if(c=='>') return lc;
00923       return -1;
00924     }
00925     // skip space
00926     while(*pStream) {
00927       if(pStream->eof()) return -1; 
00928       c = pStream->peek();
00929       if(!(isblank(c) || iscntrl(c))) break;
00930       pStream->get();
00931       if(c=='\n') ++lc;
00932     }
00933     // insist in eq
00934     if(c!='=') return -1;
00935     pStream->get();
00936     // skip space
00937     while (*pStream) {
00938       if(pStream->eof()) return -1; 
00939       c = pStream->peek();
00940       if(!(isblank(c) || iscntrl(c))) break;
00941       pStream->get();
00942       if(c=='\n') ++lc;
00943     }
00944     // insist in '"'
00945     if(c != '"') return -1;
00946     pStream->get();
00947     // get attrval
00948     int ll=ReadString(pStream,'"');
00949     if(ll<0) return -1;
00950     pStream->get();
00951     lc+=ll;    
00952     std::string aval=mStringValue;
00953     FD_DV("Token::ReadAttributes(): aval " << aval);
00954     // record attribute
00955     InsAttribute(aname,aval);
00956   }
00957   // done
00958   return lc;
00959 }
00960 
00961 // ReadMarkup(pStream)
00962 int Token::ReadMarkup(std::istream* pStream) {
00963   int lc=0;
00964   int ll;
00965   char c=0;
00966   std::string name;
00967   mStringValue = "";
00968   mType=None;
00969   // figure indicator character
00970   char p1=0;
00971   if(pStream->eof()) return -1; 
00972   c = pStream->peek();
00973   if(!(isalpha(c) || c=='_' || c==':')) 
00974     p1 = pStream->get();
00975   if(pStream->eof()) return -1; 
00976   char p2 = pStream->peek();
00977   // its a begin tag ... 
00978   if(p1==0) {
00979     FD_DV("Token::ReadMarkup: sensed XML tag");
00980     // ... get the name
00981     while (*pStream) {
00982       if(pStream->eof()) return -1; 
00983       c = pStream->peek();
00984       if(c == '>') break;
00985       if(c == '/') break;
00986       if(isblank(c) || iscntrl(c)) break;
00987       pStream->get();
00988       name.append(1,c);
00989     }
00990     if(name.size()==0) return -1;
00991     mType = Begin;
00992     ll=ReadAttributes(pStream);
00993     if(ll<0) return -1;
00994     lc+=ll;
00995     FD_DV("Token::ReadMarkup: sensed XML tag, type " << mType << " name " << name);
00996   }
00997   // its an end tag: get the name
00998   if(p1=='/') {
00999     while(*pStream) {
01000       if(pStream->eof()) return -1; 
01001       c = pStream->peek();
01002       if(c == '>') break;
01003       if(c == '/') break;
01004       if(isblank(c) || iscntrl(c)) break;
01005       pStream->get();
01006       name.append(1,c);
01007     }
01008     if(name.size()==0) return -1;
01009     if(c!='>') return -1;
01010     mType = End;
01011   }
01012   // its an xml comment
01013   if(p1=='!' && p2=='-') {
01014     FD_DV("Token::ReadMarkup: sensed XML comment beg <" << p1 << p2);
01015     c=pStream->get();
01016     if(pStream->eof()) return -1; 
01017     c=pStream->get();
01018     if(c!='-') return -1;
01019     char c2=0;
01020     char c3=0;
01021     while (*pStream) {
01022       c3=c2; c2=c;
01023       if(pStream->eof()) return -1; 
01024       c = pStream->peek();
01025       if(c3== '-' && c2=='-' && c == '>') break;
01026       pStream->get();
01027       if(c=='\n') ++lc;
01028     }
01029     FD_DV("Token::ReadMarkup: sensed XML comment end " << c3 << c2 << c);
01030   }
01031   // its an xml doctypedec (which we cannot handle properly)
01032   if(p1=='!' && (p2=='D' || p2=='d')) {
01033     FD_DV("Token::ReadMarkup doc.type.dec. not implemented (!)");
01034     c=pStream->get();
01035     while(*pStream) {
01036       if(pStream->eof()) return -1; 
01037       c = pStream->peek();
01038       if(c == '>') break;
01039       pStream->get();
01040       if(c=='\n') ++lc;
01041     }
01042   }
01043   // its an xml cdata (interpret as string)
01044   if(p1=='!' && p2=='[' ) {
01045     c=pStream->get();
01046     if(pStream->eof()) return -1; 
01047     if(pStream->get()!='C') return -1;
01048     if(pStream->eof()) return -1; 
01049     if(pStream->get()!='D') return -1;
01050     if(pStream->eof()) return -1; 
01051     if(pStream->get()!='A') return -1;
01052     if(pStream->eof()) return -1; 
01053     if(pStream->get()!='T') return -1;
01054     if(pStream->eof()) return -1; 
01055     if(pStream->get()!='A') return -1;
01056     if(pStream->eof()) return -1; 
01057     if(pStream->get()!='[') return -1;
01058     char c2=0;
01059     char c3=0;
01060     while(*pStream) {
01061       c3=c2; c2=c;
01062       if(pStream->eof()) return -1; 
01063       c = pStream->peek();
01064       if(c3== ']' && c2==']' && c == '>') break;
01065       pStream->get();
01066       if(c=='\n') ++lc;
01067       mStringValue.append(1,c);
01068     }
01069     if(mStringValue.size()>=2)
01070       mStringValue.erase(mStringValue.size()-2);
01071     mType |= String;    
01072     mType |= Binary;    
01073   }
01074   // its an xml proc.intstruction (which we ignore)
01075   if(p1=='?') {
01076     if(pStream->eof()) return -1; 
01077     c = pStream->get();
01078     char c2=0;
01079     while (*pStream) {
01080       c2=c;
01081       if(pStream->eof()) return -1; 
01082       c = pStream->peek();
01083       if(c2=='?' && c == '>') break;
01084       pStream->get();
01085       if(c=='\n') ++lc;
01086     }
01087   }
01088   // error
01089   c = pStream->peek();
01090   if(c!='>') {
01091     FD_DV("Token::ReadMarkup: mismatch (?) " << name);
01092     while (*pStream) {
01093       if(pStream->eof()) return -1; 
01094       c = pStream->peek();
01095       if(c == '>') break;
01096       if(c=='\n') ++lc;
01097       pStream->get();
01098     }
01099   }
01100   // done
01101   pStream->get();
01102   mStringValue=name;
01103   FD_DV("Token::ReadMarkup: return type " << mType << " string " << mStringValue << " lc" << lc);
01104   return lc;
01105 }
01106 
01107 // Read(pStream)
01108 int Token::Read(std::istream* pStream){
01109   char c1;
01110   int lc = 0;
01111   int ll;
01112   // the token is initialized with the type "None"
01113   SetNone();
01114   // check eof
01115   if(pStream->eof()) return(lc); 
01116   // read all spaces in the pStream
01117   lc += ReadSpace(pStream);
01118   // check eof
01119   if(pStream->eof()) return(lc);
01120   // get the first useful character
01121   c1=pStream->peek();
01122   // token is a quoted string if it starts with '"'
01123   if(c1 == '"') {
01124     pStream->get();
01125     // read the string until '"'
01126     ll=ReadString(pStream,'"');
01127     if(ll>=0) {
01128       lc+=ll;
01129       pStream->get();
01130       mType |= String;
01131     }
01132   } 
01133   // token is a quoted string if it starts with '''
01134   else if(c1 == '\'') {
01135     pStream->get();
01136     // read the string until '''
01137     ll=ReadString(pStream,'\'');
01138     if(ll>=0) {
01139       lc+=ll;
01140       pStream->get();
01141       mType |= String;
01142     }
01143   } 
01144   // token is an option string if it starts with '+'
01145   else if(c1 == '+') {
01146     pStream->get();
01147     // read the string until '+'
01148     ll=ReadString(pStream,'+');
01149     mOptionValue=mStringValue;
01150     mStringValue="+" + mOptionValue + "+";
01151     if(ll>=0) {
01152       lc+=ll;
01153       pStream->get();
01154       mType |= (Option | String);
01155     }
01156   } 
01157   // token is a binary string if it starts with '='
01158   else if(c1 == '=') {
01159     // read the string until '=', incl padding
01160     ll=ReadBinary(pStream);
01161     if(ll>=0) lc+=ll;
01162     if(ll>=0) mType |= (Binary | String);
01163   } 
01164   // token is a verbatim string if it starts with '_'
01165   else if(c1 == '_') {
01166     // read the string until the corresponding end marker
01167     ll=ReadVerbatim(pStream);
01168     if(ll>=0) lc+=ll;
01169     if(ll>=0) mType = String;
01170   } 
01171   // token is markup  if it starts with <
01172   else if(c1 == '<') {
01173     pStream->get();
01174     // check eof
01175     if(pStream->eof()) return(lc); 
01176     // read and interpret
01177     ll=ReadMarkup(pStream);
01178     if(ll>=0) lc+=ll;
01179     // if this is not a faudes token, get the next
01180     if(mType==None && ll>=0) {
01181       ll=Read(pStream);
01182       if(ll>=0) lc+=ll;
01183       else mType=None;
01184     }
01185     // error
01186     if(ll<0) return -1;
01187   } 
01188   // token is a space seperated string, perhaps a number
01189   else {
01190     if(ReadString(pStream,' ')>=0) {
01191       pStream->get();
01192       mType |= String;
01193       InterpretNumber();
01194     }
01195   }
01196   // report result
01197   FD_DV("Token::Read: " << Str());
01198   return(lc);
01199 }
01200 
01201 
01202 // Str()
01203 std::string Token::Str(void) const {
01204   std::stringstream ostr;
01205   ostr << "Token( Type=";
01206   if(IsNone()) { ostr << "None)"; return ostr.str();}
01207   if(IsInteger()) ostr << "Integer";
01208   if(IsInteger16()) ostr << "Integer16";
01209   if(IsBoolean()) ostr << "Boolean";
01210   if(IsFloat()) ostr << "Float";
01211   if(IsString()) ostr << "String";
01212   if(IsBegin()) ostr << "Begin";
01213   if(IsEnd()) ostr << "End";
01214   ostr << " Value=\"";
01215   if(IsFloat()) ostr << FloatValue();
01216   else if(IsBegin() || IsEnd()) ostr << StringValue();
01217   else if(IsString()) ostr << StringValue();
01218   ostr << "\"";
01219   caiterator ait;
01220   for(ait=mAttributes.begin(); ait!=mAttributes.end(); ait++)
01221     ostr << "  attr[" << ait->first << "=\"" << ait->second.mStringValue << "\"]";
01222   ostr << ")";
01223   return ostr.str();
01224 }
01225 
01226 
01227 
01228 } // namespace faudes

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3