00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00210
00211
00212
00213
00214
00215
00216
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
00232
00233
00234
00235
00236
00237
00238
00239
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
00258
00259
00260
00261
00262
00263
00264
00265
00266
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)
00716 value.erase(0,1);
00717
00718
00719 int res = strtol ( value.c_str(), &p, 0 );
00720 if ( *p != 0 && *p != ';' ) {
00721 ASCString s = name + ": value "+ entry.value +" is no numerical value \n" ;
00722
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() );
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
00808
00809
00810
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
00972
00973
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[