• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21100551564

17 Jan 2026 08:40PM UTC coverage: 60.504% (+0.01%) from 60.492%
21100551564

Pull #857

github

turleypol
fixed scope
Pull Request #857: ClangTidy readability-else-after-return

837 of 1874 new or added lines in 151 files covered. (44.66%)

48 existing lines in 26 files now uncovered.

44445 of 73458 relevant lines covered (60.5%)

515341.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.16
/pol-core/pol/module/datastore.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/11/26 Shinigami: changed "strcmp" into "stricmp" to suppress Script Errors
5
 * - 2006/09/26 Shinigami: GCC 3.4.x fix - added "template<>" to TmplExecutorModule
6
 * - 2007/06/17 Shinigami: added config.world_data_path
7
 * - 2009/12/21 Turley:    ._method() call fix
8
 */
9

10

11
#include "datastore.h"
12
#include <exception>
13
#include <filesystem>
14
#include <fstream>
15
#include <stddef.h>
16

17
#include "../../bscript/berror.h"
18
#include "../../bscript/bobject.h"
19
#include "../../bscript/bstruct.h"
20
#include "../../bscript/executor.h"
21
#include "../../bscript/impstr.h"
22
#include "../../bscript/objmethods.h"
23
#include "../../clib/cfgelem.h"
24
#include "../../clib/cfgfile.h"
25
#include "../../clib/fileutil.h"
26
#include "../../clib/rawtypes.h"
27
#include "../../clib/stlutil.h"
28
#include "../../clib/streamsaver.h"
29
#include "../../plib/pkg.h"
30
#include "../../plib/systemstate.h"
31
#include "../globals/ucfg.h"
32
#include "../proplist.h"
33
#include "datastoreimp.h"
34

35
#include <module_defs/datafile.h>
36

37

38
namespace Pol::Module
39
{
40
///
41
/// Datastore
42
///
43
///  datastore files are stored in
44
///     config.world_data_path + ds/fname.txt
45
///     config.world_data_path + ds/{pkgname}/fname.txt
46
///
47

48
Bscript::BApplicObjType datafileref_type;
49
Bscript::BApplicObjType datafileelem_type;
50

51
DataFileContents::DataFileContents( DataStoreFile* dsf ) : dsf( dsf ), dirty( false ) {}
5✔
52

53
DataFileContents::~DataFileContents()
10✔
54
{
55
  elements_by_integer.clear();
5✔
56
  elements_by_string.clear();
5✔
57
}
10✔
58

59
size_t DataFileContents::estimateSize() const
×
60
{
61
  size_t size = sizeof( DataStoreFile* ) /*dsf*/
×
62
                + sizeof( bool );        /*dirty*/
63

64
  size += Clib::memsize( elements_by_string );
×
65
  for ( const auto& ele : elements_by_string )
×
66
  {
67
    if ( ele.second.get() != nullptr )
×
68
      size += ele.second->proplist.estimatedSize();
×
69
  }
70
  size += Clib::memsize( elements_by_integer );
×
71
  return size;
×
72
}
73

74
void DataFileContents::load( Clib::ConfigFile& cf )
2✔
75
{
76
  Clib::ConfigElem elem;
2✔
77

78
  while ( cf.read( elem ) )
6✔
79
  {
80
    DataFileElement* delem = new DataFileElement( elem );
4✔
81

82
    if ( dsf->flags & DF_KEYTYPE_INTEGER )
4✔
83
    {
84
      elements_by_integer[atol( elem.rest() )].set( delem );
2✔
85
    }
86
    else
87
    {
88
      elements_by_string[elem.rest()].set( delem );
2✔
89
    }
90
  }
91
}
2✔
92

93
void DataFileContents::save( Clib::StreamWriter& sw )
3✔
94
{
95
  for ( const auto& element : elements_by_string )
5✔
96
  {
97
    sw.begin( "Element", element.first );
2✔
98
    element.second->printOn( sw );
2✔
99
    sw.end();
2✔
100
  }
101

102
  for ( const auto& element : elements_by_integer )
5✔
103
  {
104
    sw.begin( "Element", element.first );
2✔
105
    element.second->printOn( sw );
2✔
106
    sw.end();
2✔
107
  }
108
}
3✔
109

110
Bscript::BObjectImp* DataFileContents::methodCreateElement( int key )
2✔
111
{
112
  ElementsByInteger::iterator itr = elements_by_integer.find( key );
2✔
113
  DataFileElementRef dfelem;
2✔
114
  if ( itr == elements_by_integer.end() )
2✔
115
  {
116
    dfelem.set( new DataFileElement );
2✔
117
    elements_by_integer[key] = dfelem;
2✔
118
    dirty = true;
2✔
119
  }
120
  else
121
  {
122
    dfelem = ( *itr ).second;
×
123
  }
124
  return new DataElemRefObjImp( DataFileContentsRef( this ), dfelem );
4✔
125
}
2✔
126

127
Bscript::BObjectImp* DataFileContents::methodCreateElement( const std::string& key )
2✔
128
{
129
  ElementsByString::iterator itr = elements_by_string.find( key );
2✔
130
  DataFileElementRef dfelem;
2✔
131
  if ( itr == elements_by_string.end() )
2✔
132
  {
133
    dfelem.set( new DataFileElement );
2✔
134
    elements_by_string[key] = dfelem;
2✔
135
    dirty = true;
2✔
136
  }
137
  else
138
  {
139
    dfelem = ( *itr ).second;
×
140
  }
141
  return new DataElemRefObjImp( DataFileContentsRef( this ), dfelem );
4✔
142
}
2✔
143

144

145
Bscript::BObjectImp* DataFileContents::methodFindElement( int key )
2✔
146
{
147
  ElementsByInteger::iterator itr = elements_by_integer.find( key );
2✔
148
  if ( itr != elements_by_integer.end() )
2✔
149
  {
150
    DataFileElementRef dfelem = ( *itr ).second;
2✔
151
    return new DataElemRefObjImp( DataFileContentsRef( this ), dfelem );
2✔
152
  }
2✔
153

NEW
154
  return new Bscript::BError( "Element not found" );
×
155
}
156

157
Bscript::BObjectImp* DataFileContents::methodFindElement( const std::string& key )
2✔
158
{
159
  ElementsByString::iterator itr = elements_by_string.find( key );
2✔
160
  if ( itr != elements_by_string.end() )
2✔
161
  {
162
    DataFileElementRef dfelem = ( *itr ).second;
2✔
163
    return new DataElemRefObjImp( DataFileContentsRef( this ), dfelem );
2✔
164
  }
2✔
165

NEW
166
  return new Bscript::BError( "Element not found" );
×
167
}
168

169

170
Bscript::BObjectImp* DataFileContents::methodDeleteElement( int key )
×
171
{
172
  if ( elements_by_integer.erase( key ) )
×
173
  {
174
    dirty = true;
×
175
    return new Bscript::BLong( 1 );
×
176
  }
NEW
177
  return new Bscript::BError( "Element not found" );
×
178
}
179

180
Bscript::BObjectImp* DataFileContents::methodDeleteElement( const std::string& key )
×
181
{
182
  if ( elements_by_string.erase( key ) )
×
183
  {
184
    dirty = true;
×
185
    return new Bscript::BLong( 1 );
×
186
  }
NEW
187
  return new Bscript::BError( "Element not found" );
×
188
}
189

190
Bscript::BObjectImp* DataFileContents::methodKeys() const
2✔
191
{
192
  std::unique_ptr<Bscript::ObjArray> arr( new Bscript::ObjArray );
2✔
193

194
  for ( ElementsByString::const_iterator citr = elements_by_string.begin();
2✔
195
        citr != elements_by_string.end(); ++citr )
4✔
196
  {
197
    arr->addElement( new Bscript::String( ( *citr ).first ) );
2✔
198
  }
199

200
  for ( ElementsByInteger::const_iterator citr = elements_by_integer.begin();
2✔
201
        citr != elements_by_integer.end(); ++citr )
4✔
202
  {
203
    arr->addElement( new Bscript::BLong( ( *citr ).first ) );
2✔
204
  }
205

206
  return arr.release();
4✔
207
}
2✔
208

209

210
DataFileRefObjImp::DataFileRefObjImp( DataFileContentsRef dfcontents )
6✔
211
    : DataFileRefObjImpBase( &datafileref_type, dfcontents )
6✔
212
{
213
}
6✔
214

215
const char* DataFileRefObjImp::typeOf() const
×
216
{
217
  return "DataFileRef";
×
218
}
219
u8 DataFileRefObjImp::typeOfInt() const
×
220
{
221
  return OTDataFileRef;
×
222
}
223

224
Bscript::BObjectImp* DataFileRefObjImp::copy() const
×
225
{
226
  return new DataFileRefObjImp( obj_ );
×
227
}
228

229
Bscript::BObjectImp* DataFileRefObjImp::call_method_id( const int id, Bscript::Executor& ex,
10✔
230
                                                        bool /*forcebuiltin*/ )
231
{
232
  switch ( id )
10✔
233
  {
234
  case Bscript::MTH_CREATEELEMENT:
4✔
235
  {
236
    if ( !ex.hasParams( 1 ) )
4✔
237
    {
238
      return new Bscript::BError( "not enough parameters to datafile.createelement(key)" );
×
239
    }
240
    if ( obj_->dsf->flags & DF_KEYTYPE_INTEGER )
4✔
241
    {
242
      int key;
243
      if ( !ex.getParam( 0, key ) )
2✔
244
      {
245
        return new Bscript::BError( "datafile.createelement(key): key must be an Integer" );
×
246
      }
247
      return obj_->methodCreateElement( key );
2✔
248
    }
249
    const Bscript::String* key;
250
    if ( !ex.getStringParam( 0, key ) )
2✔
251
    {
NEW
252
      return new Bscript::BError( "datafile.createelement(key): key must be a String" );
×
253
    }
254
    return obj_->methodCreateElement( key->value() );
2✔
255
  }
256
  case Bscript::MTH_FINDELEMENT:
4✔
257
  {
258
    if ( !ex.hasParams( 1 ) )
4✔
259
    {
260
      return new Bscript::BError( "not enough parameters to datafile.findelement(key)" );
×
261
    }
262
    if ( obj_->dsf->flags & DF_KEYTYPE_INTEGER )
4✔
263
    {
264
      int key;
265
      if ( !ex.getParam( 0, key ) )
2✔
266
      {
267
        return new Bscript::BError( "datafile.findelement(key): key must be an Integer" );
×
268
      }
269
      return obj_->methodFindElement( key );
2✔
270
    }
271
    const Bscript::String* key;
272
    if ( !ex.getStringParam( 0, key ) )
2✔
273
    {
NEW
274
      return new Bscript::BError( "datafile.findelement(key): key must be a String" );
×
275
    }
276
    return obj_->methodFindElement( key->value() );
2✔
277
  }
278
  case Bscript::MTH_DELETEELEMENT:
×
279
  {
UNCOV
280
    if ( !ex.hasParams( 1 ) )
×
281
    {
282
      return new Bscript::BError( "not enough parameters to datafile.deleteelement(key)" );
×
283
    }
284
    if ( obj_->dsf->flags & DF_KEYTYPE_INTEGER )
×
285
    {
286
      int key;
287
      if ( !ex.getParam( 0, key ) )
×
288
      {
289
        return new Bscript::BError( "datafile.deleteelement(key): key must be an Integer" );
×
290
      }
291
      return obj_->methodDeleteElement( key );
×
292
    }
293
    const Bscript::String* key;
NEW
294
    if ( !ex.getStringParam( 0, key ) )
×
295
    {
NEW
296
      return new Bscript::BError( "datafile.deleteelement(key): key must be a String" );
×
297
    }
NEW
298
    return obj_->methodDeleteElement( key->value() );
×
299
  }
300
  case Bscript::MTH_KEYS:
2✔
301
    return obj_->methodKeys();
2✔
302
  default:
×
303
    return nullptr;
×
304
  }
305
}
306

307
Bscript::BObjectImp* DataFileRefObjImp::call_method( const char* methodname, Bscript::Executor& ex )
×
308
{
309
  Bscript::ObjMethod* objmethod = Bscript::getKnownObjMethod( methodname );
×
310
  if ( objmethod != nullptr )
×
311
    return this->call_method_id( objmethod->id, ex );
×
NEW
312
  return nullptr;
×
313
}
314

315

316
DataElemRefObjImp::DataElemRefObjImp( DataFileContentsRef dfcontents, DataFileElementRef dfelem )
8✔
317
    : DataElemRefObjImpBase( &datafileelem_type, DataFileElemObj( dfcontents, dfelem ) )
8✔
318
{
319
}
8✔
320
const char* DataElemRefObjImp::typeOf() const
×
321
{
322
  return "DataElemRef";
×
323
}
324
u8 DataElemRefObjImp::typeOfInt() const
×
325
{
326
  return OTDataElemRef;
×
327
}
328
Bscript::BObjectImp* DataElemRefObjImp::copy() const
×
329
{
330
  return new DataElemRefObjImp( obj_.dfcontents, obj_.dfelem );
×
331
}
332

333
Bscript::BObjectImp* DataElemRefObjImp::call_method_id( const int id, Bscript::Executor& ex,
12✔
334
                                                        bool /*forcebuiltin*/ )
335
{
336
  bool changed = false;
12✔
337
  Bscript::BObjectImp* res = CallPropertyListMethod_id( obj_.dfelem->proplist, id, ex, changed );
12✔
338
  if ( changed )
12✔
339
    obj_.dfcontents->dirty = true;
6✔
340
  return res;
12✔
341
}
342

343
Bscript::BObjectImp* DataElemRefObjImp::call_method( const char* methodname, Bscript::Executor& ex )
×
344
{
345
  bool changed = false;
×
346
  Bscript::BObjectImp* res =
347
      CallPropertyListMethod( obj_.dfelem->proplist, methodname, ex, changed );
×
348
  if ( changed )
×
349
    obj_.dfcontents->dirty = true;
×
350
  return res;
×
351
}
352

353
DataFileExecutorModule::DataFileExecutorModule( Bscript::Executor& exec )
2,356✔
354
    : Bscript::TmplExecutorModule<DataFileExecutorModule, Bscript::ExecutorModule>( exec )
2,356✔
355
{
356
}
2,356✔
357

358
DataStoreFile* DataFileExecutorModule::GetDataStoreFile( const std::string& inspec )
×
359
{
360
  std::string descriptor;
×
361

362
  const Plib::Package* spec_pkg = nullptr;
×
363
  std::string spec_filename;
×
364
  if ( !Plib::pkgdef_split( inspec, exec.prog()->pkg, &spec_pkg, &spec_filename ) )
×
365
  {
366
    return nullptr;  // new BError( "Error in descriptor" );
×
367
  }
368
  if ( spec_pkg == nullptr )
×
369
  {
370
    // ::filename
371
    descriptor = "::" + spec_filename;
×
372
  }
373
  else
374
  {
375
    // :somepkg:filename
376
    descriptor = ":" + spec_pkg->name() + ":" + spec_filename;
×
377
  }
378

379
  Core::DataStore::iterator itr = Core::configurationbuffer.datastore.find( descriptor );
×
380
  if ( itr != Core::configurationbuffer.datastore.end() )
×
381
  {
382
    DataStoreFile* dsf = ( *itr ).second;
×
383
    return dsf;
×
384
  }
385

NEW
386
  return nullptr;
×
UNCOV
387
}
×
388

389
Bscript::BObjectImp* DataFileExecutorModule::mf_ListDataFiles()
×
390
{
391
  std::unique_ptr<Bscript::ObjArray> file_list( new Bscript::ObjArray );
×
392
  for ( Core::DataStore::iterator itr = Core::configurationbuffer.datastore.begin();
×
393
        itr != Core::configurationbuffer.datastore.end(); ++itr )
×
394
  {
395
    DataStoreFile* dsf = ( *itr ).second;
×
396
    std::unique_ptr<Bscript::BStruct> file_name( new Bscript::BStruct );
×
397
    file_name->addMember( "pkg", new Bscript::String( dsf->pkgname ) );
×
398
    file_name->addMember( "name", new Bscript::String( dsf->name ) );
×
399
    file_name->addMember( "descriptor", new Bscript::String( dsf->descriptor ) );
×
400

401
    file_list->addElement( file_name.release() );
×
402
  }
×
403
  return file_list.release();
×
404
}
×
405

406
Bscript::BObjectImp* DataFileExecutorModule::mf_CreateDataFile()
3✔
407
{
408
  const Bscript::String* strob;
409
  int flags;
410
  if ( getStringParam( 0, strob ) && getParam( 1, flags ) )
3✔
411
  {
412
    try
413
    {
414
      std::string descriptor;
3✔
415
      std::string directory;
3✔
416
      std::string d_ds;
3✔
417
      const std::string& inspec = strob->value();
3✔
418

419
      const Plib::Package* spec_pkg = nullptr;
3✔
420
      std::string spec_filename;
3✔
421
      if ( !Plib::pkgdef_split( inspec, exec.prog()->pkg, &spec_pkg, &spec_filename ) )
3✔
422
      {
423
        return new Bscript::BError( "Error in descriptor" );
×
424
      }
425
      if ( spec_pkg == nullptr )
3✔
426
      {
427
        // ::filename
428
        descriptor = "::" + spec_filename;
×
429
        directory = Plib::systemstate.config.world_data_path + "ds/";
×
430
      }
431
      else
432
      {
433
        // :somepkg:filename
434
        descriptor = ":" + spec_pkg->name() + ":" + spec_filename;
3✔
435
        d_ds = Plib::systemstate.config.world_data_path + "ds/";
3✔
436
        directory = Plib::systemstate.config.world_data_path + "ds/" + spec_pkg->name() + "/";
3✔
437
      }
438
      if ( !Clib::FileExists( directory.c_str() ) )
3✔
439
      {
440
        if ( !d_ds.empty() )
1✔
441
          Clib::MakeDirectory( d_ds.c_str() );
1✔
442
        Clib::MakeDirectory( directory.c_str() );
1✔
443
      }
444

445
      DataStoreFile* dsf = nullptr;
3✔
446

447
      Core::DataStore::iterator itr = Core::configurationbuffer.datastore.find( descriptor );
3✔
448
      if ( itr != Core::configurationbuffer.datastore.end() )
3✔
449
      {
450
        dsf = ( *itr ).second;
×
451
      }
452
      else
453
      {
454
        // create a new one
455
        dsf = new DataStoreFile( descriptor, spec_pkg, spec_filename, flags );
3✔
456
        Core::configurationbuffer.datastore[descriptor] = dsf;
3✔
457
      }
458

459
      // didn't find it, time to go open or create.
460
      if ( !dsf->loaded() )
3✔
461
        dsf->load();
3✔
462

463
      return new DataFileRefObjImp( dsf->dfcontents );
3✔
464
    }
3✔
465
    catch ( std::exception& ex )
×
466
    {
467
      std::string message = std::string( "An exception occurred: " ) + ex.what();
×
468
      return new Bscript::BError( message );
×
469
    }
×
470
  }
471
  else
472
  {
473
    return new Bscript::BError( "Invalid parameter type" );
×
474
  }
475
}
476

477
Bscript::BObjectImp* DataFileExecutorModule::mf_OpenDataFile()
3✔
478
{
479
  const Bscript::String* strob;
480
  if ( getStringParam( 0, strob ) )
3✔
481
  {
482
    try
483
    {
484
      std::string descriptor;
3✔
485
      //      string directory;
486
      const std::string& inspec = strob->value();
3✔
487

488
      const Plib::Package* spec_pkg = nullptr;
3✔
489
      std::string spec_filename;
3✔
490
      if ( !Plib::pkgdef_split( inspec, exec.prog()->pkg, &spec_pkg, &spec_filename ) )
3✔
491
      {
492
        return new Bscript::BError( "Error in descriptor" );
×
493
      }
494
      if ( spec_pkg == nullptr )
3✔
495
      {
496
        // ::filename
497
        descriptor = "::" + spec_filename;
×
498
      }
499
      else
500
      {
501
        // :somepkg:filename
502
        descriptor = ":" + spec_pkg->name() + ":" + spec_filename;
3✔
503
      }
504

505
      Core::DataStore::iterator itr = Core::configurationbuffer.datastore.find( descriptor );
3✔
506
      if ( itr != Core::configurationbuffer.datastore.end() )
3✔
507
      {
508
        DataStoreFile* dsf = ( *itr ).second;
3✔
509
        // didn't find it, time to go open or create.
510
        if ( !dsf->loaded() )
3✔
511
          dsf->load();
2✔
512
        return new DataFileRefObjImp( dsf->dfcontents );
3✔
513
      }
514

NEW
515
      return new Bscript::BError( "Datafile does not exist" );
×
516
    }
3✔
517
    catch ( std::exception& ex )
×
518
    {
519
      return new Bscript::BError( std::string( "An exception occurred" ) + ex.what() );
×
520
    }
×
521
  }
522
  else
523
  {
524
    return new Bscript::BError( "Invalid parameter type" );
×
525
  }
526
}
527

528
Bscript::BObjectImp* DataFileExecutorModule::mf_UnloadDataFile()
×
529
{
530
  const Bscript::String* strob;
531
  if ( getStringParam( 0, strob ) )
×
532
  {
533
    DataStoreFile* dsf = GetDataStoreFile( strob->value() );
×
534
    if ( !dsf )
×
535
      return new Bscript::BError( "Unable to find data store file" );
×
536

537
    dsf->unload = true;
×
538
    return new Bscript::BLong( 1 );
×
539
  }
540

NEW
541
  return new Bscript::BError( "Invalid parameter type" );
×
542
}
543

544
DataStoreFile::DataStoreFile( Clib::ConfigElem& elem )
3✔
545
    : descriptor( elem.remove_string( "Descriptor" ) ),
3✔
546
      name( elem.remove_string( "name" ) ),
3✔
547
      pkgname( elem.remove_string( "package", "" ) ),
3✔
548
      pkg( Plib::find_package( pkgname ) ),
3✔
549
      version( elem.remove_ushort( "Version" ) ),
3✔
550
      oldversion( elem.remove_ushort( "OldVersion" ) ),
3✔
551
      flags( elem.remove_ulong( "Flags" ) ),
3✔
552
      unload( false ),
3✔
553
      delversion( 0 )
3✔
554
{
555
}
3✔
556

557
DataStoreFile::DataStoreFile( const std::string& descriptor, const Plib::Package* pkg,
3✔
558
                              const std::string& name, int flags )
3✔
559
    : descriptor( descriptor ),
3✔
560
      name( name ),
3✔
561
      pkgname( "" ),
3✔
562
      pkg( pkg ),
3✔
563
      version( 0 ),
3✔
564
      oldversion( 0 ),
3✔
565
      flags( flags ),
3✔
566
      unload( false ),
3✔
567
      delversion( 0 )
3✔
568
{
569
  if ( pkg != nullptr )
3✔
570
    pkgname = pkg->name();
3✔
571
}
3✔
572

573
bool DataStoreFile::loaded() const
11✔
574
{
575
  return dfcontents.get() != nullptr;
11✔
576
}
577

578
void DataStoreFile::load()
5✔
579
{
580
  if ( loaded() )
5✔
581
    return;
×
582

583
  dfcontents.set( new DataFileContents( this ) );
5✔
584

585
  std::string fn = filename();
5✔
586
  if ( Clib::FileExists( fn.c_str() ) )
5✔
587
  {
588
    Clib::ConfigFile cf( filename().c_str(), "Element" );
2✔
589
    dfcontents->load( cf );
2✔
590
  }
2✔
591
  else
592
  {
593
    // just force an empty file to be written
594
    dfcontents->dirty = true;
3✔
595
  }
596
}
5✔
597

598
DataStoreFile::~DataStoreFile()
6✔
599
{
600
  dfcontents.clear();
6✔
601
}
6✔
602

603
void DataStoreFile::printOn( Clib::StreamWriter& sw ) const
6✔
604
{
605
  sw.begin( "DataFile" );
6✔
606
  sw.add( "Descriptor", descriptor );
6✔
607
  sw.add( "Name", name );
6✔
608

609
  if ( !pkgname.empty() )
6✔
610
    sw.add( "Package", pkgname );
6✔
611

612
  sw.add( "Flags", flags );
6✔
613
  sw.add( "Version", version );
6✔
614
  sw.add( "OldVersion", oldversion );
6✔
615
  sw.end();
6✔
616
}
6✔
617

618
std::string DataStoreFile::filename( unsigned ver ) const
19✔
619
{
620
  std::string tmp = Plib::systemstate.config.world_data_path + "ds/";
19✔
621
  if ( pkg != nullptr )
19✔
622
    tmp += pkg->name() + "/";
19✔
623
  tmp += name + "." + Clib::tostring( ver % 10 ) + ".txt";
19✔
624
  return tmp;
19✔
625
}
×
626

627
std::string DataStoreFile::filename() const
16✔
628
{
629
  return filename( version );
16✔
630
}
631

632
void DataStoreFile::save() const
3✔
633
{
634
  auto path = std::filesystem::path( filename() );
3✔
635
  path.remove_filename();
3✔
636
  if ( !std::filesystem::exists( path ) )
3✔
637
    std::filesystem::create_directories( path );
×
638

639
  Clib::StreamWriter sw( filename() );
3✔
640
  dfcontents->save( sw );
3✔
641
}
3✔
642

643
size_t DataStoreFile::estimateSize() const
×
644
{
645
  size_t size = descriptor.capacity() + name.capacity() + pkgname.capacity() +
×
646
                sizeof( Plib::Package* ) /*pkg*/
647
                + 3 * sizeof( unsigned ) /*version oldversion delversion*/
648
                + sizeof( int )          /*flags*/
649
                + sizeof( bool )         /*unload*/
650
                + sizeof( DataFileContentsRef );
×
651
  if ( dfcontents.get() )
×
652
    size += dfcontents->estimateSize();
×
653
  return size;
×
654
}
655

656

657
DataFileElement::DataFileElement() : proplist( Core::CPropProfiler::Type::DATAFILEELEMENT ) {}
4✔
658

659
DataFileElement::DataFileElement( Clib::ConfigElem& elem )
4✔
660
    : proplist( Core::CPropProfiler::Type::DATAFILEELEMENT )
4✔
661
{
662
  proplist.readRemainingPropertiesAsStrings( elem );
4✔
663
}
4✔
664

665
void DataFileElement::printOn( Clib::StreamWriter& sw ) const
4✔
666
{
667
  proplist.printPropertiesAsStrings( sw );
4✔
668
}
4✔
669

670
void read_datastore_dat()
2✔
671
{
672
  std::string datastorefile = Plib::systemstate.config.world_data_path + "datastore.txt";
2✔
673

674
  if ( !Clib::FileExists( datastorefile ) )
2✔
675
    return;
1✔
676

677
  Clib::ConfigFile cf( datastorefile, "DataFile" );
1✔
678
  Clib::ConfigElem elem;
1✔
679

680
  while ( cf.read( elem ) )
4✔
681
  {
682
    DataStoreFile* dsf = new DataStoreFile( elem );
3✔
683
    auto path = std::filesystem::path( dsf->filename() );
3✔
684
    if ( !std::filesystem::exists( path ) )
3✔
685
      throw std::runtime_error(
×
686
          fmt::format( "datafile '{}' does not exist, but should due to 'datastore.txt' entry '{}'",
×
687
                       dsf->filename(), dsf->descriptor ) );
×
688
    Core::configurationbuffer.datastore[dsf->descriptor] = dsf;
3✔
689
  }
3✔
690
}
2✔
691

692
void write_datastore( Clib::StreamWriter& sw )
4✔
693
{
694
  for ( Core::DataStore::iterator itr = Core::configurationbuffer.datastore.begin();
4✔
695
        itr != Core::configurationbuffer.datastore.end(); ++itr )
10✔
696
  {
697
    DataStoreFile* dsf = ( *itr ).second;
6✔
698

699
    dsf->delversion = dsf->oldversion;
6✔
700
    dsf->oldversion = dsf->version;
6✔
701

702
    if ( dsf->dfcontents.get() && dsf->dfcontents->dirty )
6✔
703
    {
704
      // make a new generation of file and write it.
705
      ++dsf->version;
3✔
706

707
      dsf->save();
3✔
708

709
      dsf->dfcontents->dirty = false;
3✔
710
    }
711

712
    dsf->printOn( sw );
6✔
713
  }
714
}
4✔
715

716
void commit_datastore()
4✔
717
{
718
  for ( Core::DataStore::iterator itr = Core::configurationbuffer.datastore.begin();
4✔
719
        itr != Core::configurationbuffer.datastore.end(); ++itr )
10✔
720
  {
721
    DataStoreFile* dsf = ( *itr ).second;
6✔
722

723
    if ( dsf->delversion != dsf->version && dsf->delversion != dsf->oldversion )
6✔
724
    {
725
      Clib::RemoveFile( dsf->filename( dsf->delversion ) );
3✔
726
    }
727

728
    if ( dsf->unload )
6✔
729
    {
730
      if ( dsf->dfcontents.get() != nullptr )
×
731
      {
732
        if ( dsf->dfcontents->count() == 1 )
×
733
        {
734
          dsf->dfcontents.clear();
×
735
        }
736
      }
737
      dsf->unload = false;
×
738
    }
739
  }
740
}
4✔
741
}  // namespace Pol::Module
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc