Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

textfile_evaluation.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           textfile_evaluation.cpp  -  description
00003                              -------------------
00004     begin                : Thu Oct 06 2002
00005     copyright            : (C) 2002 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <vector>
00019 #include <algorithm>
00020 #include <iostream>
00021 #include "global.h"
00022 #include "ascstring.h"
00023 #include "textfileparser.h"
00024 #include "textfile_evaluation.h"
00025 #include "stringtokenizer.h"
00026 #ifdef ParserLoadImages
00027  #include <SDL_image.h>
00028  // #include "basegfx.h"
00029  #include "typen.h"
00030  #include "graphics/blitter.h"
00031  #include "fieldimageloader.h"
00032  #include "graphics/surface2png.h"
00033 #endif
00034 
00035 #ifdef WIN32
00036 #include "Windows.h"
00037 #endif
00038 
00039 #include <boost/regex.hpp>
00040 
00041 
00042          template <class T>
00043          class PropertyTemplate: public PropertyContainer::Property  {
00044                void operation_not_defined( const TextPropertyGroup::Entry& entry ) const;
00045             protected:
00046 
00047                T& property;
00048                T defaultValue;
00049 
00050                virtual T parse ( const TextPropertyGroup::Entry& entry ) const;
00051                virtual T operation_mult ( const TextPropertyGroup::Entry& entry ) const;
00052                virtual T operation_add ( const TextPropertyGroup::Entry& entry ) const;
00053                virtual T operation_sub ( const TextPropertyGroup::Entry& entry ) const;
00054                virtual T operation_eq ( const TextPropertyGroup::Entry& entry ) const;
00055 
00056 
00057             public:
00058                void evaluate ( );
00059 
00060                PropertyTemplate ( T& property_ ) : PropertyContainer::Property ( false ), property ( property_ ) {};
00061                PropertyTemplate ( T& property_, const T& defaultValue_ ) : PropertyContainer::Property ( true ), property ( property_ ), defaultValue ( defaultValue_)  {};
00062          };
00063 
00064 
00065          typedef PropertyTemplate<int> PTI;
00066          class IntegerProperty : public PTI {
00067             protected:
00068               ASCString toString ( ) const ;
00069               int operation_eq  ( const TextPropertyGroup::Entry& entry ) const;
00070               int operation_add ( const TextPropertyGroup::Entry& entry ) const;
00071               int operation_sub ( const TextPropertyGroup::Entry& entry ) const;
00072               int operation_mult ( const TextPropertyGroup::Entry& entry ) const;
00073             public:
00074                IntegerProperty ( int& property_ ) : PTI ( property_ ) {};
00075                IntegerProperty ( int& property_, int defaultValue_ ) : PTI ( property_, defaultValue_ ) {};
00076          };
00077 
00078          typedef PropertyTemplate<double> PTD;
00079          class FloatProperty : public PTD {
00080             protected:
00081               ASCString toString ( ) const ;
00082               double operation_eq  ( const TextPropertyGroup::Entry& entry ) const;
00083               double operation_add ( const TextPropertyGroup::Entry& entry ) const;
00084               double operation_mult ( const TextPropertyGroup::Entry& entry ) const;
00085             public:
00086                FloatProperty ( double& property_ ) : PTD ( property_ ) {};
00087                FloatProperty ( double& property_, double defaultValue_ ) : PTD ( property_, defaultValue_ ) {};
00088          };
00089 
00090 
00091          typedef PropertyTemplate<bool> PTB;
00092          class BoolProperty : public PTB {
00093             protected:
00094               ASCString toString ( ) const;
00095               bool operation_eq ( const TextPropertyGroup::Entry& entry ) const;
00096             public:
00097                BoolProperty ( bool& property_ ) : PTB ( property_ ) {};
00098                BoolProperty ( bool& property_, bool defaultValue_ ) : PTB ( property_, defaultValue_ ) {};
00099          };
00100 
00101          typedef PropertyTemplate<ASCString> PTS;
00102          class StringProperty : public PTS {
00103             protected:
00104               ASCString toString ( ) const;
00105               ASCString operation_eq  ( const TextPropertyGroup::Entry& entry ) const;
00106               ASCString operation_add ( const TextPropertyGroup::Entry& entry ) const;
00107             public:
00108                StringProperty ( ASCString& property_ ) : PTS ( property_ ) {};
00109                StringProperty ( ASCString& property_, const ASCString& defaultValue ) : PTS ( property_, defaultValue ) {};
00110          };
00111 
00112          typedef PropertyTemplate< vector<ASCString> > PTSA;
00113          class StringArrayProperty : public PTSA {
00114               typedef vector<ASCString> PropertyType;
00115             protected:
00116               ASCString toString ( ) const;
00117               PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00118             public:
00119                StringArrayProperty ( vector<ASCString>& property_ ) : PTSA ( property_ ) {};
00120          };
00121 
00122 
00123          template <class T>
00124          class ValArrayProperty: public PropertyTemplate< vector<T> > {
00125             protected:
00126               typedef vector<T> PropertyType;
00127               PropertyType operation_add ( const TextPropertyGroup::Entry& entry ) const;
00128               PropertyType operation_sub ( const TextPropertyGroup::Entry& entry ) const;
00129               PropertyType operation_mult ( const TextPropertyGroup::Entry& entry ) const;
00130               ValArrayProperty ( PropertyType& property_ ) : PropertyTemplate<vector<T> > ( property_ ) {};
00131 
00132          };
00133 
00134          typedef ValArrayProperty<int> PTIA;
00135          class IntegerArrayProperty : public PTIA {
00136             protected:
00137               PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00138               ASCString toString ( ) const;
00139               bool required;
00140               bool hasDefault() {return !required; };
00141             public:
00142                IntegerArrayProperty ( vector<int>& property_, bool _required ) : PTIA ( property_ ), required(_required) {};
00143          };
00144 
00145          typedef ValArrayProperty<double> PTDA;
00146          class DoubleArrayProperty : public PTDA {
00147             protected:
00148               PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00149               ASCString toString ( ) const;
00150             public:
00151                DoubleArrayProperty ( vector<double>& property_ ) : PTDA ( property_ ) {};
00152          };
00153 
00154 
00155          typedef PropertyTemplate< vector<IntRange> > PTIRA;
00156          class IntRangeArrayProperty : public PTIRA {
00157               typedef vector<IntRange> PropertyType;
00158               bool required;
00159               bool hasDefault() {return !required; };
00160             protected:
00161               PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00162               ASCString toString ( ) const;
00163             public:
00164                IntRangeArrayProperty ( vector<IntRange>& property_, bool _required ) : PTIRA ( property_ ), required(_required) {};
00165          };
00166 
00167          typedef PropertyTemplate< BitSet > PTTA;
00168          class TagArrayProperty : public PTTA {
00169               int tagNum;
00170               const char** tags;
00171               bool inverted;
00172             protected:
00173               BitSet operation_eq ( const TextPropertyGroup::Entry& entry ) const;
00174               BitSet operation_add ( const TextPropertyGroup::Entry& entry ) const;
00175               BitSet operation_sub ( const TextPropertyGroup::Entry& entry ) const;
00176               ASCString toString ( ) const;
00177             public:
00178                TagArrayProperty ( BitSet& property_, int tagNum_, const char** tags_, bool inverted_  ) : PTTA ( property_ ), tagNum (tagNum_), tags ( tags_ ), inverted ( inverted_ ) {};
00179          };
00180 
00181          typedef PropertyTemplate<int> PTTI;
00182          class TagIntProperty : public PTTI {
00183               int tagNum;
00184               const char** tags;
00185               bool inverted;
00186             protected:
00187               int operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00188               int operation_add ( const TextPropertyGroup::Entry& entry ) const ;
00189               int operation_sub ( const TextPropertyGroup::Entry& entry ) const ;
00190               ASCString toString ( ) const;
00191             public:
00192                TagIntProperty ( int& property_, int tagNum_, const char** tags_, bool inverted_  ) : PTTI ( property_ ), tagNum (tagNum_), tags ( tags_ ), inverted ( inverted_ ) {};
00193                TagIntProperty ( int& property_, int tagNum_, const char** tags_, int defaultValue_, bool inverted_  ) : PTTI ( property_, defaultValue_ ), tagNum (tagNum_), tags ( tags_ ), inverted ( inverted_ ) {};
00194          };
00195 
00196          typedef PropertyTemplate<int> PTNI;
00197          class NamedIntProperty : public PTNI {
00198               int tagNum;
00199               const char** tags;
00200             protected:
00201               int operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00202               ASCString toString ( ) const;
00203             public:
00204                NamedIntProperty ( int& property_, int tagNum_, const char** tags_ ) : PTNI ( property_ ), tagNum (tagNum_), tags ( tags_ ) {};
00205                NamedIntProperty ( int& property_, int tagNum_, const char** tags_, int defaultValue_ ) : PTNI ( property_, defaultValue_ ), tagNum (tagNum_), tags ( tags_ ) {};
00206          };
00207 
00208 /*
00209          typedef PropertyTemplate<void*> PTIMG;
00210          class ImageProperty : public PTIMG {
00211                ASCString fileName;
00212             protected:
00213                void* operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00214                ASCString toString ( ) const;
00215             public:
00216                ImageProperty ( void* &property_, const ASCString& fileName_ ) : PTIMG ( property_ ), fileName ( fileName_ ) {};
00217          };
00218 */
00219          typedef PropertyTemplate<Surface> PTIMG2;
00220          class ASCImageProperty : public PTIMG2 {
00221                typedef Surface PropertyType;
00222                ASCString fileName;
00223                bool fieldMask;
00224             protected:
00225                PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00226                ASCString toString ( ) const;
00227             public:
00228                ASCImageProperty ( Surface &property_, const ASCString& fileName_, bool applyFieldMask ) : PTIMG2 ( property_ ), fileName ( fileName_ ), fieldMask( applyFieldMask ) {};
00229          };
00230 /*
00231          typedef PropertyTemplate< vector<void*> > PTIMGA;
00232          class ImageArrayProperty : public PTIMGA {
00233                typedef vector<void*> PropertyType;
00234                ASCString fileName;
00235             protected:
00236                PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00237                ASCString toString ( ) const;
00238             public:
00239                ImageArrayProperty ( PropertyType &property_, const ASCString& fileName_ ) : PTIMGA ( property_ ), fileName ( fileName_ ) {};
00240          };
00241 */
00242 
00243          typedef PropertyTemplate< vector<Surface> > PTIMGA2;
00244          class ASCImageArrayProperty : public PTIMGA2 {
00245                typedef vector<Surface> PropertyType;
00246                ASCString fileName;
00247             protected:
00248                PropertyType operation_eq ( const TextPropertyGroup::Entry& entry ) const ;
00249                ASCString toString ( ) const;
00250             public:
00251                ASCImageArrayProperty ( PropertyType &property_, const ASCString& fileName_ ) : PTIMGA2 ( property_ ), fileName ( fileName_ ) {};
00252          };
00253 
00254 
00255 
00256 /*
00257 void PropertyContainer :: run ( )
00258 {
00259    if ( isReading() )
00260       for ( Properties::iterator i = properties.begin(); i != properties.end(); i++ )
00261          if ( !(*i)->evaluated )
00262             (*i)->evaluate();
00263 
00264    closeBracket();
00265    if ( levelDepth )
00266       error ( "PropertyReadingContainer :: ~PropertyReadingContainer - still brackets open" );
00267 }
00268 */
00269 
00270 void PropertyReadingContainer :: writeProperty ( Property& p, const ASCString& value )
00271 {
00272    fatalError ( "Attempt to use PropertyReadingContainer :: writeProperty !");
00273 }
00274 
00275 void PropertyWritingContainer :: writeProperty ( Property& p, const ASCString& value )
00276 {
00277    ASCString output;
00278    for ( int i = 0; i < levelDepth; i++ )
00279       output += "   ";
00280 
00281    output += p.getLastName();
00282    output +=  " = ";
00283 
00284    size_t indent = output.length();
00285    ASCString::size_type pos = value.find ( "\n" );
00286    if ( pos != ASCString::npos ) {
00287       output += "[";
00288       ASCString::size_type oldpos = 0;
00289       do {
00290          output += value.substr( oldpos, pos-oldpos+1 );
00291          oldpos = pos+1;
00292          for ( int i = 0; i < indent; i++ )
00293             output += " ";
00294          if ( pos+1 < value.length() )
00295             pos = value.find ( "\n", pos+1 );
00296          else
00297             pos = ASCString::npos;
00298       } while ( pos != ASCString::npos );
00299       output += value.substr( oldpos );
00300       output += "]";
00301    } else
00302       output += value;
00303 
00304    output += "\n";
00305 
00306    stream.writeString ( output, false );
00307 }
00308 
00309 
00310 ASCString PropertyContainer :: getNameStack()
00311 {
00312    ASCString s;
00313    for ( Level::iterator i = level.begin(); i != level.end(); ++i ) {
00314       if ( s.length() )
00315          s += ".";
00316       s += *i;
00317    }
00318    return s;
00319 }
00320 
00321 void PropertyContainer :: openBracket( const ASCString& name )
00322 {
00323    level.push_back ( name );
00324    levelDepth++;
00325 }
00326 
00327 void PropertyContainer :: closeBracket(  )
00328 {
00329    level.pop_back();
00330    levelDepth--;
00331 }
00332 
00333 
00334 void PropertyWritingContainer :: openBracket( const ASCString& name )
00335 {
00336    for ( int i = 0; i < levelDepth; i++ )
00337       stream.writeString ( "   ", false );
00338    stream.writeString ( name + " { \n", false );
00339 
00340    PropertyContainer :: openBracket ( name );
00341 }
00342 
00343 void PropertyWritingContainer :: closeBracket(  )
00344 {
00345    ASCString name = level.back();
00346 
00347    PropertyContainer :: closeBracket ( );
00348 
00349    for ( int i = 0; i < levelDepth; i++ )
00350       stream.writeString ( "   ", false );
00351    stream.writeString ( "} " + name + "\n", false );
00352 }
00353 
00354 
00355 void PropertyContainer::setup ( Property* p, const ASCString& name_ )
00356 {
00357    ASCString name;
00358    for ( Level::iterator i = level.begin(); i != level.end(); i++ )
00359       name += *i + ".";
00360    name += name_;
00361    p->setName( name, name_ );
00362    p->setPropertyContainer ( this );
00363    properties.push_back ( p );
00364 
00365    p->evaluate();
00366 }
00367 
00368 
00369 void PropertyContainer::addInteger ( const ASCString& name, int& property )
00370 {
00371    IntegerProperty* ip = new IntegerProperty ( property );
00372    setup ( ip, name );
00373 }
00374 
00375 void PropertyContainer::addInteger ( const ASCString& name, int& property, int defaultValue )
00376 {
00377    IntegerProperty* ip = new IntegerProperty ( property, defaultValue );
00378    setup ( ip, name );
00379 }
00380 
00381 void PropertyContainer::addDFloat ( const ASCString& name, double& property )
00382 {
00383    FloatProperty* ip = new FloatProperty ( property );
00384    setup ( ip, name );
00385 }
00386 
00387 void PropertyContainer::addDFloat ( const ASCString& name, double& property, double defaultValue )
00388 {
00389    FloatProperty* ip = new FloatProperty ( property, defaultValue );
00390    setup ( ip, name );
00391 }
00392 
00393 
00394 
00395 void PropertyContainer::addBool ( const ASCString& name, bool& property )
00396 {
00397    BoolProperty* ip = new BoolProperty ( property );
00398    setup ( ip, name );
00399 }
00400 
00401 void PropertyContainer::addBool ( const ASCString& name, bool& property, bool defaultValue )
00402 {
00403    BoolProperty* ip = new BoolProperty ( property, defaultValue );
00404    setup ( ip, name );
00405 }
00406 
00407 void PropertyContainer::addString ( const ASCString& name, ASCString& property )
00408 {
00409    StringProperty* ip = new StringProperty ( property );
00410    setup ( ip, name );
00411 }
00412 
00413 void PropertyContainer::addString ( const ASCString& name, ASCString& property, const ASCString& defaultValue )
00414 {
00415    StringProperty* ip = new StringProperty ( property, defaultValue );
00416    setup ( ip, name );
00417 }
00418 
00419 
00420 void PropertyContainer::addStringArray ( const ASCString& name, vector<ASCString>& property )
00421 {
00422    StringArrayProperty* ip = new StringArrayProperty ( property );
00423    setup ( ip, name );
00424 }
00425 
00426 
00427 void PropertyContainer::addIntegerArray ( const ASCString& name, vector<int>& property, bool required )
00428 {
00429    IntegerArrayProperty* ip = new IntegerArrayProperty ( property, required );
00430    setup ( ip, name );
00431 }
00432 
00433 void PropertyContainer::addDFloatArray ( const ASCString& name, vector<double>& property )
00434 {
00435    DoubleArrayProperty* dp = new DoubleArrayProperty ( property );
00436    setup ( dp, name );
00437 }
00438 
00439 void PropertyContainer::addDFloatArray ( const ASCString& name, vector<int>& property )
00440 {
00441    vector<double> dproperty;
00442    for ( vector<int>::iterator i = property.begin(); i != property.end(); i++ )
00443        dproperty.push_back (*i);
00444    DoubleArrayProperty* dp = new DoubleArrayProperty ( dproperty );
00445    setup ( dp, name );
00446 
00447    property.clear();
00448    for ( vector<double>::iterator i = dproperty.begin(); i != dproperty.end(); i++ )
00449        property.push_back ( int(*i) );
00450 }
00451 
00452 
00453 void PropertyContainer::addIntRangeArray ( const ASCString& name, vector<IntRange>& property, bool required )
00454 {
00455    IntRangeArrayProperty* ip = new IntRangeArrayProperty ( property, required );
00456    setup ( ip, name );
00457 }
00458 
00459 
00460 void PropertyContainer::addTagArray ( const ASCString& name, BitSet& property, int tagNum, const char** tags, bool inverted )
00461 {
00462    TagArrayProperty* ip = new TagArrayProperty ( property, tagNum, tags, inverted );
00463    setup ( ip, name );
00464 }
00465 
00466 void PropertyContainer::addTagInteger ( const ASCString& name, int& property, int tagNum, const char** tags, bool inverted )
00467 {
00468    TagIntProperty* ip = new TagIntProperty ( property, tagNum, tags, inverted );
00469    setup ( ip, name );
00470 }
00471 
00472 void PropertyContainer::addTagInteger ( const ASCString& name, int& property, int tagNum, const char** tags, int defaultValue, bool inverted )
00473 {
00474    TagIntProperty* ip = new TagIntProperty ( property, tagNum, tags, defaultValue, inverted );
00475    setup ( ip, name );
00476 }
00477 
00478 void PropertyContainer::addNamedInteger ( const ASCString& name, int& property, int tagNum, const char** tags )
00479 {
00480    NamedIntProperty* ip = new NamedIntProperty ( property, tagNum, tags );
00481    setup ( ip, name );
00482 }
00483 
00484 void PropertyContainer::addNamedInteger ( const ASCString& name, int& property, int tagNum, const char** tags, int defaultValue )
00485 {
00486    NamedIntProperty* ip = new NamedIntProperty ( property, tagNum, tags, defaultValue );
00487    setup ( ip, name );
00488 }
00489 
00490 void PropertyContainer::addBreakpoint ()
00491 {
00492    bool breakpoint = false;
00493    if ( isReading() ) {
00494       addBool( "breakpoint", breakpoint, false);
00495       if ( breakpoint ) {
00496         #ifdef WIN32
00497         DebugBreak();
00498         #else
00499         cerr << "breakpoint hit";
00500         #endif
00501       }
00502    }
00503 }
00504 
00505 
00506 void PropertyContainer::storeContext( const ASCString& label )
00507 {
00508    storedContext[label] = make_pair( levelDepth, level );
00509 }
00510 
00511 bool PropertyContainer::restoreContext( const ASCString& label )
00512 {
00513    StoredContext::iterator pos = storedContext.find( label );
00514    if ( pos != storedContext.end() ) {
00515       levelDepth = pos->second.first;
00516       level = pos->second.second;
00517       return true;
00518    }
00519    return false;
00520 }
00521 
00522 
00523 #ifdef ParserLoadImages
00524 
00525 void PropertyContainer::addImageArray ( const ASCString& name, vector<Surface> &property, const ASCString& filename )
00526 {
00527    ASCImageArrayProperty* ip = new ASCImageArrayProperty ( property, filename );
00528    setup ( ip, name );
00529 }
00530 
00531 
00532 void PropertyContainer::addImage ( const ASCString& name, Surface &property, const ASCString& filename, bool applyFieldMask )
00533 {
00534    ASCImageProperty* ip = new ASCImageProperty ( property, filename, applyFieldMask );
00535    setup ( ip, name );
00536 }
00537 
00538 
00539 #endif
00540 
00541 void PropertyContainer::warning ( const ASCString& errmsg )
00542 {
00543    #ifdef converter
00544    fatalError ( errmsg );
00545    #else
00546    ::warning( "file " + textPropertyGroup->fileName+ ": " + errmsg );
00547    #endif
00548 }
00549 
00550 void PropertyContainer::error ( const ASCString& errmsg )
00551 {
00552    displayLogMessage ( 0, getLocation() + " : " + errmsg  + "\n" );
00553    throw ParsingError ( getLocation() + " : " + errmsg );
00554 }
00555 
00556 bool PropertyContainer::find ( const ASCString& name )
00557 {
00558    ASCString n;
00559    for ( Level::iterator i = level.begin(); i != level.end(); i++ )
00560       n += *i + ".";
00561    n += name;
00562    n.toLower();
00563 
00564    return textPropertyGroup->find ( n ) != NULL;
00565 }
00566 
00567 
00568 
00569 PropertyReadingContainer :: PropertyReadingContainer ( const ASCString& baseName, TextPropertyGroup* tpg ) : PropertyContainer ( baseName, tpg, true )
00570 {
00571    openBracket ( baseName );
00572 }
00573 
00574 
00575 PropertyReadingContainer :: ~PropertyReadingContainer (  )
00576 {
00577 }
00578 
00579 PropertyWritingContainer :: PropertyWritingContainer ( const ASCString& baseName, tnstream& stream ) : PropertyContainer ( baseName, NULL, false ), stream ( stream )
00580 {
00581    textPropertyGroup = new TextPropertyGroup();
00582    textPropertyGroup->fileName = stream.getDeviceName();
00583    textPropertyGroup->location = stream.getLocation();
00584    openBracket ( baseName );
00585 }
00586 
00587 PropertyWritingContainer :: ~PropertyWritingContainer()
00588 {
00589    closeBracket();
00590    if ( levelDepth )
00591       error ( "PropertyWritingContainer :: ~PropertyWritingContainer - still brackets open" );
00592    delete textPropertyGroup;
00593 }
00594 
00595 
00597 
00598 
00599 void PropertyContainer::Property::setName ( const ASCString& name_, const ASCString& lastName_ )
00600 {
00601   name = name_ ;
00602   name.toLower();
00603   lastName = lastName_;
00604 }
00605 
00606 void PropertyContainer::Property::findEntry ()
00607 {
00608    if ( !propertyContainer )
00609       fatalError ( "PropertyContainer::Property::evaluate - no propertyContainer ");
00610 
00611    name.toLower();
00612 
00613    if (!entry )
00614       entry = propertyContainer->textPropertyGroup->find ( name );
00615 
00616    if ( !entry && !hasDefault() )
00617       propertyContainer->error ( "entry " + name +" not found" );
00618 }
00619 
00620 void PropertyContainer::Property::writeProperty( )
00621 {
00622    propertyContainer->writeProperty ( *this, toString() );
00623 }
00624 
00625 
00626 template <class T>
00627 T PropertyTemplate<T>::parse ( const TextPropertyGroup::Entry& entry ) const
00628 {
00629    if ( entry.op == TextPropertyGroup::Entry::eq )
00630       return operation_eq( entry );
00631 
00632    if ( entry.op == TextPropertyGroup::Entry::alias_all )
00633       operation_not_defined( entry );
00634 
00635    if ( !entry.parent )
00636       propertyContainer->error ( ASCString("PropertyContainer::PropertyTemplate::parse - no parent for operator ") + TextFormatParser::operations[entry.op] + " at entry " + entry.propertyName + " !");
00637 
00638    switch ( entry.op ) {
00639       case TextPropertyGroup::Entry::mult_eq : return operation_mult ( entry );
00640       case TextPropertyGroup::Entry::add_eq :  return operation_add ( entry );
00641       case TextPropertyGroup::Entry::sub_eq :  return operation_sub ( entry );
00642       default:;
00643    }
00644 
00645    propertyContainer->error ( "PropertyTemplate::parse - invalid operator !");
00646    return defaultValue;
00647 }
00648 
00649 template <class T>
00650 void PropertyTemplate<T>::operation_not_defined(const TextPropertyGroup::Entry& entry) const
00651 {
00652    propertyContainer->error ( ASCString("operator ") + TextFormatParser::operations[entry.op] + " not defined for this type !\nEntry " + entry.propertyName);
00653 }
00654 
00655 
00656 template <class T>
00657 T PropertyTemplate<T>::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00658 {
00659    operation_not_defined( entry );
00660    return T();
00661 }
00662 
00663 template <class T>
00664 T PropertyTemplate<T>::operation_mult ( const TextPropertyGroup::Entry& entry ) const
00665 {
00666    operation_not_defined( entry );
00667    return T();
00668 }
00669 
00670 template <class T>
00671 T PropertyTemplate<T>::operation_add ( const TextPropertyGroup::Entry& entry ) const
00672 {
00673    operation_not_defined( entry );
00674    return T();
00675 }
00676 
00677 template <class T>
00678 T PropertyTemplate<T>::operation_sub ( const TextPropertyGroup::Entry& entry ) const
00679 {
00680    operation_not_defined( entry );
00681    return T();
00682 }
00683 
00684 
00685 template <class T>
00686 void PropertyTemplate<T>::evaluate ()
00687 {
00688    if ( evaluated )
00689       return;
00690 
00691    if ( propertyContainer->isReading() ) {
00692       findEntry();
00693 
00694       if ( entry ) {
00695          property = parse ( *entry );
00696       } else
00697          property = defaultValue;
00698 
00699       evaluated = true;
00700    } else {
00701       writeProperty();
00702       evaluated = true;
00703    }
00704 }
00705 
00706 int IntegerProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00707 {
00708    char* p = NULL;
00709 
00710    ASCString value = entry.value;
00711    ASCString::size_type i;
00712    while ( (i = value.find_first_of( " \t\n\r" )) != ASCString::npos )
00713       value.erase( i, 1 );
00714 
00715    while ( value.find( "0") == 0 && value.find( "0x") != 0)  // removing leading zeroes
00716       value.erase(0,1);
00717 
00718 
00719    int res =  strtol ( value.c_str(), &p, 0  );    //   strtol(nptr, NULL, 10);
00720    if ( *p != 0 && *p != ';' ) {
00721       ASCString s = name + ": value "+ entry.value +" is no numerical value \n" ;
00722       // propertyContainer->error ( s );
00723       fprintf(stderr, s.c_str()  );
00724    }
00725    
00726    return res;
00727 }
00728 
00729 
00730 int IntegerProperty::operation_add ( const TextPropertyGroup::Entry& entry ) const
00731 {
00732    return parse ( *entry.parent ) + operation_eq ( entry );
00733 }
00734 
00735 int IntegerProperty::operation_sub ( const TextPropertyGroup::Entry& entry ) const
00736 {
00737    return parse ( *entry.parent ) - operation_eq ( entry );
00738 }
00739 
00740 
00741 int IntegerProperty::operation_mult ( const TextPropertyGroup::Entry& entry ) const
00742 {
00743    return int ( double ( parse ( *entry.parent )) *  atof ( entry.value.c_str() ));
00744 }
00745 
00746 
00747 ASCString IntegerProperty::toString ( ) const
00748 {
00749    return strrr ( property );
00750 }
00751 
00752 
00753 
00754 double FloatProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00755 {
00756    return atof ( entry.value.c_str() );    //   strtol(nptr, NULL, 10);
00757 }
00758 
00759 
00760 double FloatProperty::operation_add ( const TextPropertyGroup::Entry& entry ) const
00761 {
00762    return parse ( *entry.parent ) + operation_eq ( entry );
00763 }
00764 
00765 double FloatProperty::operation_mult ( const TextPropertyGroup::Entry& entry ) const
00766 {
00767    return double ( parse ( *entry.parent )) *  atof ( entry.value.c_str() );
00768 }
00769 
00770 
00771 ASCString FloatProperty::toString ( ) const
00772 {
00773    ASCString s;
00774    s.format("%f", property );
00775    return s;
00776 }
00777 
00778 
00779 bool BoolProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00780 {
00781     StringTokenizer st ( entry.value );
00782     ASCString s = st.getNextToken();
00783     if ( s.compare_ci ( "true" )==0 || s.compare_ci ( "1" )==0 )
00784        return true;
00785     else
00786        if ( s.compare_ci ( "false" )==0 || s.compare_ci ( "0" )==0 )
00787           return false;
00788        else {
00789           propertyContainer->error ( name + ": token "+ s +" unknown" );
00790           return false;
00791        }
00792 }
00793 
00794 
00795 ASCString BoolProperty::toString ( ) const
00796 {
00797    if ( property )
00798       return "true";
00799    else
00800       return "false";
00801 }
00802 
00803 
00804 
00805 ASCString StringProperty::operation_add ( const TextPropertyGroup::Entry& entry ) const
00806 {
00807 /*   ASCString s = entry.value;
00808    while ( s.find ( "%s" ) != ASCString::npos )
00809       s.replace ( s.find ( "%s" ), 2, parse ( *entry.parent ));
00810    return s;
00811    */
00812    return parse( *entry.parent ) + entry.value;
00813 }
00814 
00815 ASCString StringProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00816 {
00817     ASCString s = entry.value;
00818     ASCString::size_type pos = s.find_first_not_of ( TextFormatParser::whiteSpace );
00819     if ( pos == ASCString::npos )
00820        s.erase();                            
00821     else
00822        s.erase ( 0, pos );
00823 
00824     pos = s.find_last_not_of ( TextFormatParser::whiteSpace );
00825     if ( pos != ASCString::npos )
00826        s.erase ( pos+1 );
00827 
00828     return s;
00829 }
00830 
00831 
00832 ASCString StringProperty::toString ( ) const
00833 {
00834    ASCString valueToWrite = property ;
00835 
00836    ASCString::size_type pos = 0;
00837    static const int linewidth = 60;
00838    do {
00839       if ( pos + linewidth < valueToWrite.length() ) {
00840          pos = valueToWrite.find_first_of ( TextFormatParser::whiteSpace, pos + linewidth );
00841          if ( pos != ASCString::npos )
00842             valueToWrite[pos] = '\n';
00843       } else
00844          pos = ASCString::npos;
00845    } while ( pos != ASCString::npos );
00846 
00847    return valueToWrite;
00848 }
00849 
00850 
00851 StringArrayProperty::PropertyType StringArrayProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00852 {
00853    PropertyType sa;
00854    StringTokenizer st ( entry.value, true );
00855    ASCString s = st.getNextToken();
00856    while ( !s.empty() ) {
00857       sa.push_back ( s );
00858       s = st.getNextToken();
00859    }
00860    return sa;
00861 }
00862 
00863 ASCString StringArrayProperty::toString ( ) const
00864 {
00865    ASCString valueToWrite;
00866    for ( PropertyType::iterator i = property.begin(); i != property.end(); i++ ) {
00867       valueToWrite += *i;
00868       valueToWrite += " ";
00869    }
00870    return valueToWrite;
00871 }
00872 
00873 
00874 template<class T>
00875 typename ValArrayProperty<T>::PropertyType ValArrayProperty<T>::operation_add ( const TextPropertyGroup::Entry& entry ) const
00876 {
00877    PropertyType child = this->operation_eq( entry );
00878    PropertyType parent = this->parse ( *entry.parent );
00879 
00880    if ( child.size() == parent.size() ) {
00881       PropertyType res;
00882       for ( int i = 0; i < child.size(); i++ )
00883          res.push_back ( parent[i] + child[i] );
00884       return res;
00885    }
00886    if ( child.size() == 1 ) {
00887       PropertyType res;
00888       for ( int i = 0; i < parent.size(); i++ )
00889          res.push_back ( parent[i] + child[0] );
00890       return res;
00891    }
00892    if ( parent.size() == 1 ) {
00893       PropertyType res;
00894       for ( int i = 0; i < child.size(); i++ )
00895          res.push_back ( parent[0] + child[i] );
00896       return res;
00897    }
00898 
00899    this->propertyContainer->error ( this->name + ": array dimensions do not agree" );
00900    return child;
00901 }
00902 
00903 template<class T>
00904 typename ValArrayProperty<T>::PropertyType ValArrayProperty<T>::operation_sub ( const TextPropertyGroup::Entry& entry ) const
00905 {
00906    PropertyType child = this->operation_eq( entry );
00907    PropertyType parent = this->parse ( *entry.parent );
00908 
00909    if ( child.size() == parent.size() ) {
00910       PropertyType res;
00911       for ( int i = 0; i < child.size(); i++ )
00912          res.push_back ( parent[i] - child[i] );
00913       return res;
00914    }
00915    if ( child.size() == 1 ) {
00916       PropertyType res;
00917       for ( int i = 0; i < parent.size(); i++ )
00918          res.push_back ( parent[i] - child[0] );
00919       return res;
00920    }
00921    if ( parent.size() == 1 ) {
00922       PropertyType res;
00923       for ( int i = 0; i < child.size(); i++ )
00924          res.push_back ( parent[0] - child[i] );
00925       return res;
00926    }
00927 
00928    this->propertyContainer->error ( this->name + ": array dimensions do not agree" );
00929    return child;
00930 }
00931 
00932 
00933 template<class T>
00934 typename ValArrayProperty<T>::PropertyType ValArrayProperty<T>::operation_mult ( const TextPropertyGroup::Entry& entry ) const
00935 {
00936    PropertyType child = this->operation_eq( entry );
00937    PropertyType parent = this->parse ( *entry.parent );
00938 
00939    if ( child.size() == parent.size() ) {
00940       PropertyType res;
00941       for ( int i = 0; i < child.size(); i++ )
00942          res.push_back ( int( double(parent[i]) * child[i]) );
00943       return res;
00944    }
00945    if ( child.size() == 1 ) {
00946       PropertyType res;
00947       for ( int i = 0; i < parent.size(); i++ )
00948          res.push_back ( int( double(parent[i]) * child[0]) );
00949       return res;
00950    }
00951    if ( parent.size() == 1 ) {
00952       PropertyType res;
00953       for ( int i = 0; i < child.size(); i++ )
00954          res.push_back ( int( double(parent[0]) * child[i]) );
00955       return res;
00956    }
00957 
00958    this->propertyContainer->error ( this->name + ": array dimensions do not agree" );
00959    return parent;
00960 }
00961 
00962 
00963 IntegerArrayProperty::PropertyType IntegerArrayProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00964 {
00965    PropertyType ia;
00966    StringTokenizer st ( entry.value, true );
00967    ASCString s = st.getNextToken();
00968    while ( !s.empty() ) {
00969 
00970       /*
00971       if ( s.find( ";") == 0 ) 
00972          st.skipTill('\n');
00973       else
00974       */
00975          ia.push_back ( atoi ( s.c_str() ));
00976 
00977       s = st.getNextToken();
00978    }
00979    return ia;
00980 }
00981 
00982 
00983 
00984 ASCString DoubleArrayProperty::toString ( ) const
00985 {
00986    ASCString valueToWrite;
00987    for ( PropertyType::iterator i = property.begin(); i != property.end(); i++ ) {
00988       ASCString s;
00989       s.format ( "%f", *i );
00990       valueToWrite += s;
00991       valueToWrite += " ";
00992    }
00993    return valueToWrite;
00994 }
00995 
00996 
00997 DoubleArrayProperty::PropertyType DoubleArrayProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
00998 {
00999    PropertyType ia;
01000    StringTokenizer st ( entry.value, true );
01001    ASCString s = st.getNextToken();
01002    while ( !s.empty() ) {
01003       ia.push_back ( atof ( s.c_str() ));
01004       s = st.getNextToken();
01005    }
01006    return ia;
01007 }
01008 
01009 
01010 
01011 ASCString IntegerArrayProperty::toString ( ) const
01012 {
01013    ASCString valueToWrite;
01014    for ( PropertyType::iterator i = property.begin(); i != property.end(); i++ ) {
01015       valueToWrite += strrr ( *i );
01016       valueToWrite += " ";
01017    }
01018    return valueToWrite;
01019 }
01020 
01021 
01022 
01023 
01024 IntRangeArrayProperty::PropertyType IntRangeArrayProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
01025 {
01026    return String2IntRangeVector( entry.value );
01027 }
01028 
01029 ASCString IntRangeArrayProperty::toString() const
01030 {
01031    ASCString valueToWrite;
01032    for ( PropertyType::iterator i = property.begin(); i != property.end(); i++ ) {
01033       if ( i->from != i->to ) {
01034          valueToWrite += strrr ( i->from );
01035          valueToWrite += "-";
01036          valueToWrite += strrr ( i->to );
01037       } else
01038          valueToWrite += strrr ( i->from );
01039       valueToWrite += " ";
01040    }
01041    return valueToWrite;
01042 }
01043 
01044 
01045 BitSet TagArrayProperty::operation_add ( const TextPropertyGroup::Entry& entry ) const
01046 {
01047    return parse ( *entry.parent ) | operation_eq ( entry );
01048 }
01049 
01050 BitSet TagArrayProperty::operation_sub ( const TextPropertyGroup::Entry& entry ) const
01051 {
01052    return parse ( *entry.parent ) & ~operation_eq ( entry );
01053 }
01054 
01055 
01056 BitSet TagArrayProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
01057 {
01058    BitSet bs;
01059 
01060    if ( inverted )
01061       bs.set();
01062    else
01063       bs.reset();
01064    StringTokenizer st ( entry.value );
01065    ASCString s = st.getNextToken();
01066    while ( !s.empty() ) {
01067       bool found = false;
01068       for ( int i = 0; i < tagNum; i++ )
01069          if ( s.compare_ci ( tags[i] )==0  ) {
01070             if ( inverted )
01071                bs.reset ( i );
01072             else
01073                bs.set ( i );
01074             found = true;
01075             break;
01076          }
01077 
01078       if ( !found )
01079          propertyContainer->error ( name + ": token "+ s +" unknown" );
01080       s = st.getNextToken();
01081    }
01082 
01083    return bs;
01084 }
01085 
01086 ASCString TagArrayProperty::toString() const
01087 {
01088    ASCString valueToWrite;
01089    for ( int i = 0; i < tagNum; i++ )
01090       if ( property.test(i) != inverted ) {
01091          valueToWrite += tags[i];
01092          valueToWrite += " ";
01093       }
01094    return valueToWrite;
01095 }
01096 
01097 
01098 int TagIntProperty::operation_add ( const TextPropertyGroup::Entry& entry ) const
01099 {
01100    return parse ( *entry.parent ) | operation_eq ( entry );
01101 }
01102 
01103 int TagIntProperty::operation_sub ( const TextPropertyGroup::Entry& entry ) const
01104 {
01105    return parse ( *entry.parent ) & ~operation_eq ( entry );
01106 }
01107 
01108 
01109 int TagIntProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
01110 {
01111    int i;
01112 
01113    if ( inverted )
01114       i = -1;
01115    else
01116       i = 0;
01117 
01118    StringTokenizer st ( entry.value );
01119    ASCString s = st.getNextToken();
01120    while ( !s.empty() ) {
01121       bool found = false;
01122       for ( int j = 0; j < tagNum; j++ )
01123          if ( s.compare_ci ( tags[j] )==0  ) {
01124             i ^= 1 << j;
01125             found = true;
01126             break;
01127          }
01128 
01129       if ( !found )
01130          propertyContainer->error ( name + ": token "+ s +" unknown" );
01131       s = st.getNextToken();
01132    }
01133    return i;
01134 }
01135 
01136 
01137 ASCString TagIntProperty::toString() const
01138 {
01139    ASCString valueToWrite;
01140    for ( int i = 0; i < tagNum; i++ )
01141       if ( !!(property & (1 << i)) != inverted ) {
01142          valueToWrite += tags[i];
01143          valueToWrite += " ";
01144       }
01145    return valueToWrite;
01146 }
01147 
01148 
01149 int NamedIntProperty::operation_eq ( const TextPropertyGroup::Entry& entry ) const
01150 {
01151    int i = 0;
01152 
01153    StringTokenizer st ( entry.value );
01154    ASCString s = st.getNextToken();
01155    if ( !s.empty() ) {
01156       bool found = false;
01157       for ( int j = 0; j < tagNum; j++ )
01158          if ( s.compare_ci ( tags[j] )==0  ) {
01159             i = j;
01160             found = true;
01161             break;
01162          }
01163 
01164       if ( !found )
01165          propertyContainer->error ( name + ": token "+ s +" unknown" );
01166    }
01167 
01168    return i;
01169 }
01170 
01171 ASCString NamedIntProperty::toString() const
01172 {
01173    return tags[