00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00039 #include "../Include/Globals.h"
00040 #include "../Include/Database.h"
00041 #include "../Include/Pod.h"
00042
00043 using namespace std;
00044
00045
00046 CDatabaseRecord::CDatabaseRecord (void)
00047 {
00048 sequence = 0;
00049 }
00050
00051 void CDatabaseRecord::SetSequence (unsigned long sequence)
00052 {
00053 this->sequence = sequence;
00054 }
00055
00056 void CDatabaseRecord::AddField (CDatabaseField f)
00057 {
00058 field.push_back (f);
00059 }
00060
00061 int CDatabaseRecord::GetNumFields (void)
00062 {
00063 return field.size();
00064 }
00065
00066 CDatabaseField *CDatabaseRecord::GetField (unsigned int i)
00067 {
00068 CDatabaseField *rc = NULL;
00069
00070 if (i < field.size()) {
00071 rc = &(field[i]);
00072 }
00073
00074 return rc;
00075 }
00076
00077
00078 CDatabase::CDatabase (const char* dbtFilename)
00079 {
00080
00081 LoadTemplate (dbtFilename);
00082
00083
00084 cacheRecord = NULL;
00085
00086
00087
00088
00089
00090
00091
00092
00093 state = DB_UNMOUNTED;
00094 podfile = NULL;
00095 recordBuffer = NULL;
00096 }
00097
00101 CDatabase::~CDatabase (void)
00102 {
00103
00104 if (recordBuffer != NULL) delete[] recordBuffer;
00105
00106
00107 if (cacheRecord != NULL) {
00108 delete cacheRecord;
00109 }
00110
00111
00112 vector<CDatabaseIndex*>::iterator i;
00113 for (i=dbi.begin(); i!=dbi.end(); i++) delete *i;
00114
00115 Unmount ();
00116 }
00117
00118
00119
00120
00121
00122 void CDatabase::LoadTemplate (const char* dbtFilename)
00123 {
00124 dbt.Load (dbtFilename);
00125 }
00126
00127 CDatabaseTemplate* CDatabase::GetTemplate (void)
00128 {
00129 return &dbt;
00130 }
00131
00132
00133
00134
00135
00136 void CDatabase::AddIndex (const char *dbiFilename)
00137 {
00138 dbi.push_back (new CDatabaseIndex (dbiFilename));
00139 }
00140
00141 unsigned int CDatabase::GetNumIndexes (void)
00142 {
00143 return dbi.size();
00144 }
00145
00146 CDatabaseIndex* CDatabase::GetIndex (Tag tag)
00147 {
00148 CDatabaseIndex *rc = NULL;
00149
00150 vector<CDatabaseIndex*>::iterator i;
00151 for (i=dbi.begin(); i!=dbi.end(); i++) {
00152 Tag iKey = (*i)->GetKeyId();
00153 if (iKey == tag) {
00154 rc = *i;
00155 }
00156 }
00157
00158 return rc;
00159 }
00160
00161
00162
00163
00164
00165
00166 typedef struct {
00167 unsigned long signature;
00168 unsigned long unknown0;
00169 unsigned long unknown1;
00170 unsigned long checksum;
00171 unsigned long nRecords;
00172 unsigned long recLength;
00173 unsigned long dummy[8];
00174 } DBDHeader;
00175
00176
00177
00178
00179
00180 void CDatabase::Mount (PODFILE *f)
00181 {
00182
00183 int nFields = dbt.GetNumItems();
00184 if (nFields > 0) {
00185
00186 DBDHeader h;
00187 ReadULong (f, &h.signature);
00188 ReadULong (f, &h.unknown0);
00189 ReadULong (f, &h.unknown1);
00190 ReadULong (f, &h.checksum);
00191 ReadULong (f, &h.nRecords);
00192 ReadULong (f, &h.recLength);
00193 for (unsigned int i=0; i<8; i++) ReadULong (f, &h.dummy[i]);
00194
00195 nRecords = h.nRecords;
00196 recLength = h.recLength;
00197 }
00198
00199
00200 state = DB_MOUNTED;
00201 podfile = f;
00202 recordBuffer = new char[recLength];
00203 }
00204
00205 void CDatabase::Mount (const char* dbdFilename)
00206 {
00207 char fullFilename[64];
00208 strcpy (fullFilename, "Database\\");
00209 strcat (fullFilename, dbdFilename);
00210 PODFILE *p = popen (&globals->pfs, fullFilename);
00211 if (p) {
00212
00213 Mount (p);
00214 }
00215 }
00216
00217 void CDatabase::Unmount (void)
00218 {
00219 if (podfile != NULL) {
00220 pclose (podfile);
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 unsigned long CDatabase::GetRawRecordLength (void)
00383 {
00384 return recLength;
00385 }
00386
00387 unsigned long CDatabase::GetNumRecords (void)
00388 {
00389 return nRecords;
00390 }
00391
00392 unsigned long CDatabase::GetNumFields (void)
00393 {
00394 return dbt.GetNumItems();
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 unsigned long CDatabase::Search (Tag tag, const char* key)
00409 {
00410 unsigned long rc = 0;
00411
00412
00413 if (state == DB_MOUNTED) {
00414 search_index = GetIndex (tag);
00415 if (search_index != NULL) {
00416 rc = search_index->Search (key);
00417 }
00418 }
00419
00420 return rc;
00421 }
00422
00423 unsigned long CDatabase::Search (Tag tag, double key)
00424 {
00425 unsigned long rc = 0;
00426
00427
00428 if (state == DB_MOUNTED) {
00429 search_index = GetIndex (tag);
00430 if (search_index != NULL) {
00431 rc = search_index->Search (key);
00432 }
00433 }
00434
00435 return rc;
00436 }
00437
00438 unsigned long CDatabase::Search (Tag tag, long key)
00439 {
00440 unsigned long rc = 0;
00441
00442
00443 if (state == DB_MOUNTED) {
00444 search_index = GetIndex (tag);
00445 if (search_index != NULL) {
00446 rc = search_index->Search (key);
00447 }
00448 }
00449
00450 return rc;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 unsigned long CDatabase::SearchNext (void)
00460 {
00461 unsigned long rc = 0;
00462
00463
00464 if ((state == DB_MOUNTED) && (search_index != NULL)) {
00465 rc = search_index->SearchNext ();
00466 }
00467
00468 return rc;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 void CDatabase::GetRawRecord (unsigned long offset, char* buffer)
00553 {
00554
00555 if (state == DB_MOUNTED) {
00556 pseek (podfile, offset, SEEK_SET);
00557 pread (buffer, recLength, 1, podfile);
00558 }
00559 }
00560
00561 CDatabaseRecord* CDatabase::GetRecordByOffset (unsigned long offset)
00562 {
00563 CDatabaseRecord* rc = new CDatabaseRecord;
00564
00565 GetRawRecord (offset, recordBuffer);
00566 for (unsigned long i=0; i<GetNumFields(); i++) {
00567 CDatabaseField f;
00568 CDatabaseTemplateItem *t = dbt.GetItem (i);
00569 f.type = t->type;
00570 f.length = t->length;
00571 void *pData = recordBuffer + t->start;
00572 switch (t->type) {
00573 case 'C':
00574 if (t->length < 256) {
00575 strncpy (f.data.charData, (char*)pData, t->length);
00576 } else {
00577 gtfo ("CDatabase::GetRecord : Char field length > 255 chars");
00578 }
00579 break;
00580
00581 case 'D':
00582 f.data.doubleData = *((double*)pData);
00583 break;
00584
00585 case 'I':
00586 f.data.intData = *((long*)pData);
00587 break;
00588 }
00589 rc->AddField (f);
00590 }
00591
00592 return rc;
00593 }
00594
00595 unsigned long CDatabase::RecordOffset (unsigned long index)
00596 {
00597 return sizeof(DBDHeader) + (index * recLength);
00598 }
00599
00600 CDatabaseRecord* CDatabase::GetRecordByIndex (unsigned long index)
00601 {
00602 return GetRecordByOffset (RecordOffset (index));
00603 }
00604
00605
00606
00607
00608
00609 void CDatabase::Dump (FILE *f)
00610 {
00611
00612 dbt.Dump (f);
00613 fprintf (f, "\n");
00614
00615
00616 vector<CDatabaseIndex*>::iterator i;
00617 for (i=dbi.begin(); i!=dbi.end(); i++) {
00618 (*i)->Dump (f);
00619 }
00620 fprintf (f, "\n");
00621
00622
00623 fprintf (f, "State : ");
00624 switch (state) {
00625 case DB_UNMOUNTED:
00626 fprintf (f, "UNMOUNTED\n");
00627 break;
00628
00629 case DB_MOUNTED:
00630 fprintf (f, "MOUNTED\n");
00631 break;
00632 }
00633
00634
00635 if (state == DB_MOUNTED) {
00636 int nRecords = GetNumRecords ();
00637 fprintf (f, " nRecords = %d\n", nRecords);
00638 int nFields = GetNumFields ();
00639 fprintf (f, " nFields = %d\n", nFields);
00640
00641 int i, j;
00642 for (i=0; i < nRecords; i++) {
00643 CDatabaseRecord *record = GetRecordByIndex (i);
00644
00645 for (j=0; j < nFields; j++) {
00646 CDatabaseField *field = record->GetField (j);
00647 char s[256];
00648 field->Format (s);
00649 if (j != 0) fprintf (f, ", ");
00650 fprintf (f, "%s", s);
00651 }
00652 fprintf (f, "\n");
00653 }
00654 }
00655 }
00656
00657