Advanced Strategic Command
itemrepository.cpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3  itemrepository.cpp - description
4  -------------------
5  begin : Thu Jul 28 2001
6  copyright : (C) 2001 by Martin Bickel
7  email : bickel@asc-hq.org
8  ***************************************************************************/
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
22 #include <map>
23 #include <vector>
24 #include "typen.h"
25 #include "itemrepository.h"
26 #include "textfileparser.h"
27 #include "sgstream.h"
28 #include "textfile_evaluation.h"
29 #include "util/messaginghub.h"
30 #include "packagemanager.h"
31 #include "packagerepository.h"
32 
33 
34 sigc::signal<void> dataLoaderTicker;
35 
36 
37 const char* cacheFileName = "asc2.cache";
38 
39 typedef vector<TextFileDataLoader*> DataLoaders;
42 
43 
44 typedef map<ASCString,TextPropertyList> TextFileRepository;
46 
47 
48 void duplicateIDError ( const ASCString& itemtype, int id, const ASCString& file1, const ASCString& name1, const ASCString& file2, const ASCString& name2 )
49 {
50  fatalError ( "Conflicting IDs !\n"
51  "These two " + itemtype + "s use both the ID of " + strrr ( id ) + "\n" +
52  " " + name1 + " from file " + file1 + "\n" +
53  " " + name2 + " from file " + file2 + "\n\n" +
54  "This is NOT a bug of ASC, it is conflict between two data files.");
55 }
56 
57 
58 template<class T>
60 {
61  typename ObjectMap::iterator i = repository.hash.find ( id );
62  if ( i != repository.hash.end() && i->second )
63  duplicateIDError ( repository.typeName, id, object->location, object->name, i->second->location, i->second->name );
64  repository.hash[ id ] = object;
65 }
66 
67 
68 
69 template<class T>
70 void ItemRepository<T>::add( T* obj )
71 {
72  RegisterID reg(*this, obj);
73  reg( obj->id );
74 
75  for_each ( obj->secondaryIDs.begin(), obj->secondaryIDs.end(), reg );
76 
77 
78  container.push_back( obj );
79 }
80 
81 
82 template<class T>
84 {
85  T* t = new T;
86  t->runTextIO ( prc );
87 
88  t->filename = fileName;
89  t->location = location;
90  t->archive = prc.getArchive();
91  this->add ( t );
92 }
93 
94 
95 template<class T>
97 {
98  int version = stream.readInt();
99  if ( version != 1 )
100  throw tinvalidversion( stream.getLocation(), 1, version );
101  int num = stream.readInt();
102  for ( int i = 0; i< num; ++i ) {
104 
105  T* t = new T;
106  t->read( stream );
107 
108  t->filename = stream.readString();
109  t->location = stream.readString();
110  t->archive = stream.readString();
112 
113  this->add ( t );
114  // add ( T::newFromStream(stream ));
115  }
116 }
117 
118 
119 template<class T>
121 {
122  stream.writeInt( 1 );
123  stream.writeInt( ItemRepository<T>::container.size() );
125  (*i)->write( stream );
126  stream.writeString ( (*i)->filename );
127  stream.writeString ( (*i)->location );
128  stream.writeString ( (*i)->archive );
129  }
130 }
131 
132 
133 template<class T>
134 void ItemRepository<T>::addIdTranslation( int from, int to )
135 {
136  idTranslation[from] = to;
137 }
138 
140 
141 
143 {
144  add( new MineType( cmantipersonnelmine ) );
145  add( new MineType( cmantitankmine ) );
146  add( new MineType( cmmooredmine ) );
147  add( new MineType( cmfloatmine ) );
148 }
149 
150 
156 
158 
159 namespace {
160  class Foo {
161  public:
162  Foo() { objectTypeRepository.addIdTranslation( 12998, 1 ); };
163  } foo;
164 };
165 
167  void readTextFiles(PropertyReadingContainer& prc, const ASCString& fileName, const ASCString& location ) {
168  TechAdapter* ta = new TechAdapter;
169  ta->runTextIO ( prc );
170 
171  ta->filename = fileName;
172  ta->location = location;
173  techAdapterContainer.push_back ( ta );
174  };
175 
176  void read ( tnstream& stream ){
177  readPointerContainer( techAdapterContainer, stream );
178  };
179 
180  void write ( tnstream& stream ){
181  writePointerContainer( techAdapterContainer, stream );
182  };
183  ASCString getTypeName() {
184  return "techadapter";
185  };
186 };
187 
188 
189 void loadalltextfiles ( );
190 
191 const int cacheVersion = 34;
192 
193 class FileCache {
194  vector<tfindfile::FileInfo> actualFileInfo;
195  tnstream* stream;
196  bool current;
197  bool checkForModification ();
198  public:
199  FileCache( );
200  bool isCurrent() { return current; };
201  void load();
202  void write();
203 
204  ~FileCache();
205 };
206 
208  :stream(NULL)
209 {
211  {
213  while ( f.getnextname( fi ))
214  actualFileInfo.push_back ( fi );
215  }
216  {
218  while ( f.getnextname( fi ))
219  actualFileInfo.push_back ( fi );
220  }
221 
222  if ( exist ( cacheFileName )) {
223  stream = new tnfilestream ( cacheFileName, tnstream::reading );
224  int version = stream->readInt();
225 
226  if ( version == cacheVersion )
227  current = checkForModification();
228  else
229  current = false;
230  } else
231  current = false;
232 }
233 
234 bool FileCache::checkForModification ( )
235 {
236  vector<tfindfile::FileInfo> cacheFileInfo;
237  readClassContainer ( cacheFileInfo, *stream );
238 
239  if ( cacheFileInfo.size() != actualFileInfo.size() )
240  return false;
241 
242  for ( vector<tfindfile::FileInfo>::iterator i = actualFileInfo.begin(); i != actualFileInfo.end(); ++i ) {
243  bool found = false;
244  for ( vector<tfindfile::FileInfo>::iterator j = cacheFileInfo.begin(); j != cacheFileInfo.end(); ++j )
245  if ( i->name == j->name ) {
246  found = true;
247  if ( i->size != j->size )
248  return false;
249 
250  if ( i->date != j->date )
251  return false;
252 
253  break;
254  }
255 
256  if ( !found)
257  return false;
258  }
259 
260 
261  return true;
262 }
263 
264 
266 {
267  for ( DataLoaders::iterator i = dataLoaders.begin(); i != dataLoaders.end(); ++i) {
268  displayLogMessage ( 5, "loading all of " + (*i)->getTypeName() + " from cache ... ");
269  (*i)->read ( *stream );
270  (*i)->postChecks();
271  displayLogMessage ( 5, "completed \n ");
272  }
273 }
274 
275 
277 {
278  if ( stream )
279  delete stream;
280 
282 
283  stream->writeInt ( cacheVersion );
284  writeClassContainer ( actualFileInfo, *stream );
285 
286  for ( DataLoaders::iterator i = dataLoaders.begin(); i != dataLoaders.end(); ++i)
287  (*i)->write ( *stream );
288 
289 }
290 
291 
292 
294 {
295  if ( stream ) {
296  delete stream;
297  stream = NULL;
298  }
299  for ( DataLoaders::iterator i = dataLoadersToDelete.begin(); i != dataLoadersToDelete.end(); ++i)
300  delete *i;
301 }
302 
303 
304 
306 {
307  dataLoaders.push_back ( dataLoader );
308  dataLoadersToDelete.push_back ( dataLoader );
309 }
310 
312 {
313  dataLoaders.push_back ( &dataLoader );
314 }
315 
316 
317 void loadAllData( bool useCache )
318 {
319  FileCache cache;
320 
329 
330 
331  if ( cache.isCurrent() && useCache ) {
332  try {
333  cache.load();
334  }
335  catch ( tinvalidversion err ) {
336  fatalError("the cache seems to have been generated with a newer version of ASC than this one.\nPlease upgrade to that version, or delete " + ASCString(cacheFileName) + " and try again");
337  }
338  displayLogMessage ( 4, "loading of cache completed\n");
339  } else {
340  MessagingHub::Instance().statusInformation("rebuilding data cache, please be patient\n"+ listContainer());
341 
343 
344  for ( DataLoaders::iterator dl = dataLoaders.begin(); dl != dataLoaders.end(); ++dl) {
345  TextPropertyList& tpl = textFileRepository[ (*dl)->getTypeName() ];
346  for ( TextPropertyList::iterator i = tpl.begin(); i != tpl.end(); i++ ) {
348 
349  if ( !(*i)->isAbstract() ) {
350  PropertyReadingContainer pc ( (*dl)->getTypeName(), *i );
351 
352  displayLogMessage ( 5, "loading " + (*i)->location );
353  (*dl)->readTextFiles( pc, (*i)->fileName, (*i)->location );
354  displayLogMessage ( 5, " done\n");
355  }
356  }
357  (*dl)->postChecks();
358  displayLogMessage ( 4, "loading all of " + (*dl)->getTypeName() + " completed\n");
359 
360  }
361 
362  if ( useCache ) {
363  try {
364  cache.write();
365  }
366  catch ( tfileerror err ) {
367  fatalError("error writing cache file");
368  }
369  }
370 
371  textFileRepository.clear();
372  }
373 }
374 
375 
376 
377 
378 
380 {
381  tfindfile ff ( "*.asctxt" );
382  ASCString c = ff.getnextname();
383 
384  while( !c.empty() ) {
386 
388 
389  displayLogMessage ( 6, "loadalltextfiles :: loading " + s.getLocation() + ", " );
390 
391  TextFormatParser tfp ( &s );
392 
393  displayLogMessage ( 5, "TFP running... " );
394 
395  TextPropertyGroup* tpg = tfp.run();
396 
397  textFileRepository[tpg->typeName].push_back ( tpg );
398 
399  displayLogMessage ( 5, "done\n" );
400 
401  c = ff.getnextname();
402  }
403  displayLogMessage ( 4, "loadalltextfiles completed\n");
404 
405  displayLogMessage ( 4, "Building inheritance...");
406 
407  displayLogMessage ( 10, " Printing all .ASCTXT files after inheritance and aliases have been resolved\n");
408  for ( TextFileRepository::iterator i = textFileRepository.begin(); i != textFileRepository.end(); i++ ) {
409  i->second.buildIDs();
410  for ( TextPropertyList::iterator j = i->second.begin(); j != i->second.end(); j++ ) {
411  displayLogMessage( 9, "Building inheritance: " + (*j)->location + "\n");
412  (*j)->buildInheritance( i->second );
413  if ( MessagingHub::Instance().getVerbosity() >= 10 )
414  (*j)->print();
415  }
416  }
417  displayLogMessage ( 4, "done\n");
418 }
419 
420 
421 
422 
423 
424 
425 
427 
428 
429 ItemFiltrationSystem::ItemFilter::ItemFilter( const ASCString& _name, const IntRangeArray& unitsetIDs, bool _active )
430 {
431  name = "UnitSet: " + _name;
432  units = unitsetIDs;
433  active = _active;
434 }
435 
436 
438 {
439  if ( pc.find ( "Buildings"))
440  pc.addIntRangeArray ( "Buildings", buildings );
441  if ( pc.find ( "Vehicles"))
442  pc.addIntRangeArray ( "Vehicles", units );
443  if ( pc.find ( "Objects"))
444  pc.addIntRangeArray ( "Objects", objects );
445  if ( pc.find ( "Terrain"))
446  pc.addIntRangeArray ( "Terrain", terrain );
447  if ( pc.find ( "Technologies"))
448  pc.addIntRangeArray ( "Technologies", technologies );
449  pc.addBool ( "activated", active, false );
450  pc.addString ( "name", name );
451 }
452 
454 {
455  int version = stream.readInt();
456  if ( version > 2 )
457  throw tinvalidversion( stream.getDeviceName(), 2, version );
458  readClassContainer ( buildings, stream );
459  readClassContainer ( objects, stream );
460  readClassContainer ( units, stream );
461  readClassContainer ( terrain, stream );
462  if ( version >= 2 )
463  readClassContainer ( technologies, stream );
464 
465  active = stream.readInt();
466  name = stream.readString();
467 }
468 
470 {
471  stream.writeInt ( 2 );
472  writeClassContainer ( buildings, stream );
473  writeClassContainer ( objects, stream );
474  writeClassContainer ( units, stream );
475  writeClassContainer ( terrain, stream );
476  writeClassContainer ( technologies, stream );
477  stream.writeInt ( active );
478  stream.writeString ( name );
479 }
480 
481 
482 
483 bool ItemFiltrationSystem::ItemFilter::isContained ( IntRangeArray& arr, int id )
484 {
485  for ( IntRangeArray::iterator i = arr.begin(); i != arr.end(); i++ )
486  if ( id >= i->from && id <= i->to )
487  return true;
488  return false;
489 }
490 
491 
492 
493 bool ItemFiltrationSystem::ItemFilter::isContained ( ItemFiltrationSystem::Category cat, int id )
494 {
495  switch ( cat ) {
496  case Building: return isContained ( buildings, id );
497  case Vehicle: return isContained ( units, id );
498  case Object: return isContained ( objects, id );
499  case Terrain: return isContained ( terrain, id );
500  case Technology: return isContained ( technologies, id );
501  };
502  return false;
503 }
504 
506 {
507  for ( vector<ItemFilter*>::iterator i = itemFilters.begin(); i != itemFilters.end(); i++ )
508  if ( (*i)->isContained ( cat, id ) )
509  if ( (*i)->isActive() )
510  return true;
511 
512  return false;
513 }
514 
515 
517 {
518  return isFiltered( Vehicle, item->id );
519 }
520 
522 {
523  return isFiltered( Building, item->id );
524 }
525 
527 {
528  return isFiltered( Object, item->id );
529 }
530 
532 {
533  return isFiltered( Terrain, item->id );
534 }
535 
537 {
538  return false;
539 }
540 
541 
543 {
544  ItemFilter* itf = new ItemFilter;
545  itf->runTextIO ( prc );
546 
547  // bmtt->filename = (*i)->fileName;
548  // bmtt->location = (*i)->location;
549  ItemFiltrationSystem::itemFilters.push_back ( itf );
550 }
551 
553 {
554  stream.readInt();
555  readPointerContainer( ItemFiltrationSystem::itemFilters, stream );
556 }
557 
559 {
560  stream.writeInt ( 1 );
561  writePointerContainer( ItemFiltrationSystem::itemFilters, stream );
562 }
map< ASCString, TextPropertyList > TextFileRepository
The type of a field.
Definition: terraintype.h:75
ASCString filename
The name of the file from which the item was loaded.
Definition: typen.h:290
void addIdTranslation(int from, int to)
MineTypeRepository mineTypeRepository
ItemRepositoryLoader< ObjectType > objectTypeRepository("objecttype")
void addBool(const ASCString &name, bool &property)
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
int id
the id of the object, used when referencing objects in files
Definition: objecttype.h:35
const char * cacheFileName
virtual ASCString getLocation()
returns the location of the stream.
Definition: basestrm.cpp:274
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
virtual ASCString getDeviceName()
returns the name of the stream.
Definition: basestrm.cpp:269
ASCString getnextname(int *loc=NULL, bool *inContainer=NULL, ASCString *location=NULL)
Returns the next entry of the internal file list.
Definition: basestrm.cpp:2211
sigc::signal< void > dataLoaderTicker
void runTextIO(PropertyContainer &pc)
void write(tnstream &stream)
TextFileRepository textFileRepository
PackageRepository packageRepository
Functions to evaluate the parsed *.asctxt files.
void loadAllData(bool useCache)
virtual ASCString getArchive()
ItemRepositoryLoader< BuildingType > buildingTypeRepository("buildingtype")
The interface for all kinds of IO stream.
ItemRepositoryLoader< Technology > technologyRepository("technology")
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
virtual void writeString(const string &pc, bool binary=true)
writes the C++ String pc to the stream.
Definition: basestrm.cpp:545
void readTextFiles(PropertyReadingContainer &prc, const ASCString &fileName, const ASCString &location)
vector< TextFileDataLoader * > DataLoaders
The class describing properties that are common to all vehicles of a certain kind.
Definition: vehicletype.h:177
The class describing properties that are common to all buildings of a certain kind.
Definition: buildingtype.h:35
ItemRepositoryLoader< VehicleType > vehicleTypeRepository("vehicletype")
char * strrr(int a)
converts a to a string.
Definition: misc.cpp:66
void duplicateIDError(const ASCString &itemtype, int id, const ASCString &file1, const ASCString &name1, const ASCString &file2, const ASCString &name2)
ItemRepositoryLoader< TerrainType > terrainTypeRepository("terraintype")
TechAdapterContainer techAdapterContainer
static bool isFiltered(Category cat, int id)
DataLoaders dataLoaders
void displayLogMessage(int msgVerbosity, const char *message,...)
An object that can be placed on fields. Roads, pipelines and ditches are examples of objects...
Definition: objecttype.h:30
static deallocating_vector< ItemFilter * > itemFilters
void readPointerContainer(vector< BaseType * > &v, tnstream &stream)
Definition: basestrm.h:714
Searching for files.
Definition: basestrm.h:484
DataLoaders dataLoadersToDelete
ASCString getLocation()
returns the location of the stream.
Definition: basestrm.cpp:1663
map< int, int > idTranslation
bool isCurrent()
The IO for many basic classes and structurs of ACS.
void readClassContainer(C &c, tnstream &stream)
Definition: basestrm.h:752
Parses a .ASCTXT file and returns a TextPropertyGroup.
ASCString listContainer()
Definition: basestrm.cpp:1052
void add(T *obj)
Class that stores all the (preparsed) entries of an .ASCTXT file.
virtual ASCString readString(bool includeCR=false)
Reads and returns a string.
Definition: basestrm.cpp:535
void readTextFiles(PropertyReadingContainer &prc, const ASCString &fileName, const ASCString &location)
tn_c_lzw_filestream tnfilestream
Definition: basestrm.h:429
void registerDataLoader(TextFileDataLoader *dataLoader)
registers a dataLoader . The object is delete after use, so use: registerDataLoader( new MyDataLoader...
void runTextIO(PropertyContainer &pc)
registers the properties of this item for loading/writing into asctxt files
Definition: research.cpp:395
a container that stores pointers and deletes the pointed-to objects on destruction ...
Definition: typen.h:314
void writeClassContainer(const C &c, tnstream &stream)
Definition: basestrm.h:742
ASCString location
The filename and location on disk (including containerfiles) of the object.
Definition: typen.h:296
bool exist(const ASCString &s)
does a file s exist (wildcards allowed)
Definition: basestrm.cpp:2444
An actual building on the map, which references a BuildingType Buildings have an owner,.
Definition: buildings.h:38
void read(tnstream &stream)
an instance of an object type (ObjectType) on the map
Definition: objects.h:46
void addString(const ASCString &name, ASCString &property)
void addIntRangeArray(const ASCString &name, vector< IntRange > &property, bool required=true)
const int cacheVersion
bool find(const ASCString &name)
ASCString typeName
the name of the structure. For example "VehicleType"
void fatalError(const ASCString &string)
void loadalltextfiles()
ItemContainerType container
void writePointerContainer(const C &c, tnstream &stream)
Definition: basestrm.h:704
Functions to parse the *.asctxt files.