63
72
typedef struct deleteset_s *DELETESET;
66
static BOOLEAN readxrefs(void);
67
static void readrecs(DELETESET set);
75
/*********************************************
76
* local function prototypes
77
*********************************************/
80
static BOOLEAN addxref_impl(CNSTRING key, DUPS dups);
81
static INT find_slot(INT keynum, DELETESET set);
82
static void freexref(DELETESET set);
83
static DELETESET get_deleteset_from_type(char ctype);
68
84
static STRING getxref(DELETESET set);
69
static void addxref(INT key, DELETESET set);
70
85
static void growxrefs(DELETESET set);
86
static STRING newxref(STRING xrefp, BOOLEAN flag, DELETESET set);
71
87
static INT num_set(DELETESET set);
72
static STRING newxref(STRING xrefp, BOOLEAN flag, DELETESET set);
88
static void readrecs(DELETESET set);
89
static BOOLEAN readxrefs(void);
73
90
static INT xref_last(DELETESET set);
91
static BOOLEAN addixref_impl(INT key, DUPS dups);
92
static BOOLEAN addfxref_impl(INT key, DUPS dups);
93
static BOOLEAN addsxref_impl(INT key, DUPS dups);
94
static BOOLEAN addexref_impl(INT key, DUPS dups);
95
static BOOLEAN addxxref_impl(INT key, DUPS dups);
97
/*********************************************
99
*********************************************/
75
101
/* INDI, FAM, EVEN, SOUR, other sets */
76
102
static struct deleteset_s irecs, frecs, srecs, erecs, xrecs;
303
339
/*=====================================
304
* addxref -- Add deleted key to xrefs.
340
* find_slot -- Find slot at which to add key
341
*===================================*/
343
find_slot (INT keynum, DELETESET set)
347
/* binary search to find where to insert key */
349
INT md = (lo + hi)/2;
350
if (keynum > (set->recs)[md])
352
else if (keynum < (set->recs)[md])
360
/*=====================================
361
* add_xref_to_set_impl -- Add deleted key to xrefs.
305
362
* generic for all types
306
363
*===================================*/
308
addxref (INT key, DELETESET set)
365
add_xref_to_set_impl (INT keynum, DELETESET set, DUPS dups)
311
if (key <= 0 || !xreffp || (set->n) < 1) FATAL();
368
if (keynum <= 0 || !xreffp || (set->n) < 1) FATAL();
312
369
if (set->n >= set->max)
314
371
ASSERT(set->n < set->max);
317
/* binary search to find where to insert key */
320
if (key>(set->recs)[md])
322
else if (key<(set->recs)[md])
326
sprintf(msg, "Tried to add already-deleted record (%d) to xref (%c)!"
328
FATAL2(msg); /* deleting a deleted record! */
373
lo = find_slot(keynum, set);
374
if ((set->recs)[lo] == keynum) {
375
/* key is already free */
379
sprintf(msg, "Tried to add already-deleted record (%d) to xref (%c)!"
380
, keynum, set->ctype);
381
FATAL2(msg); /* deleting a deleted record! */
331
383
/* key replaces xrefs[lo] - push lo+ up */
332
384
for (i=set->n-1; i>=lo; --i)
333
385
(set->recs)[i+1] = (set->recs)[i];
334
(set->recs)[lo] = key;
386
(set->recs)[lo] = keynum;
336
388
ASSERT(writexrefs());
339
/*===================================================
340
* add?xref -- Wrappers for each type to addxref (qv)
341
* 5 symmetric versions
342
*=================================================*/
343
void addixref (INT key) { addxref(key, &irecs); }
344
void addfxref (INT key) { addxref(key, &frecs); }
345
void addsxref (INT key) { addxref(key, &srecs); }
346
void addexref (INT key) { addxref(key, &erecs); }
347
void addxxref (INT key) { addxref(key, &xrecs); }
392
/*===================================================
393
* add?xref_impl -- Wrappers for each type to add_xref_to_set (qv)
394
* 5 symmetric versions
395
*=================================================*/
396
static BOOLEAN addixref_impl (INT key, DUPS dups) { return add_xref_to_set_impl(key, &irecs, dups); }
397
static BOOLEAN addfxref_impl (INT key, DUPS dups) { return add_xref_to_set_impl(key, &frecs, dups); }
398
static BOOLEAN addsxref_impl (INT key, DUPS dups) { return add_xref_to_set_impl(key, &srecs, dups); }
399
static BOOLEAN addexref_impl (INT key, DUPS dups) { return add_xref_to_set_impl(key, &erecs, dups); }
400
static BOOLEAN addxxref_impl (INT key, DUPS dups) { return add_xref_to_set_impl(key, &xrecs, dups); }
401
/*===================================================
402
* add?xref -- Wrappers for each type to add_xref_to_set (qv)
403
* 5 symmetric versions
404
*=================================================*/
405
void addixref (INT key) { addixref_impl(key, NODUPS); }
406
void addfxref (INT key) { addfxref_impl(key, NODUPS); }
407
void addsxref (INT key) { addsxref_impl(key, NODUPS); }
408
void addexref (INT key) { addexref_impl(key, NODUPS); }
409
void addxxref (INT key) { addxxref_impl(key, NODUPS); }
410
/*===================================================
411
* addxref_impl -- Mark key free (accepts string key, any type)
412
* key: [IN] key to delete (add to free set)
413
* silent: [IN] if FALSE, ASSERT if record is already free
414
*=================================================*/
416
addxref_impl (CNSTRING key, DUPS dups)
418
INT keyint = atoi(key + 1);
420
case 'I': return addixref_impl(keyint, dups);
421
case 'F': return addfxref_impl(keyint, dups);
422
case 'S': return addsxref_impl(keyint, dups);
423
case 'E': return addexref_impl(keyint, dups);
424
case 'X': return addxxref_impl(keyint, dups);
425
default: ASSERT(0); return FALSE;
428
/*===================================================
429
* addxref -- Mark key free (accepts string key, any type)
430
* ASSERT if key is already free
431
*=================================================*/
432
void addxref (CNSTRING key)
434
addxref_impl(key, NODUPS);
436
/*===================================================
437
* addxref_if_missing -- Mark key free (accepts string key, any type)
438
* Does nothing if key already free
439
*=================================================*/
440
BOOLEAN addxref_if_missing (CNSTRING key)
442
return addxref_impl(key, DUPSOK);
348
444
/*==========================================
349
445
* growxrefs -- Grow memory for xrefs array.
350
446
* generic for all types
366
462
set->recs = newp;
464
/*==========================================
465
* get_deleteset_from_type -- Return deleteset
467
*========================================*/
469
get_deleteset_from_type (char ctype)
472
case 'I': return &irecs;
473
case 'F': return &frecs;
474
case 'S': return &srecs;
475
case 'E': return &erecs;
476
case 'X': return &xrecs;
480
/*==========================================
481
* delete_xref_if_present -- If record is listed
482
* as free, remove it from the free list
483
*========================================*/
485
delete_xref_if_present (CNSTRING key)
492
ASSERT(key && key[0] && key[1]);
493
set = get_deleteset_from_type(key[0]);
494
keynum = atoi(key + 1);
496
lo = find_slot(keynum, set);
497
if ((set->recs)[lo] != keynum)
499
/* removing xrefs[lo] -- move lo+ down */
500
for (i=lo; i+1<set->n-1; ++i)
501
(set->recs)[i] = (set->recs)[i+1];
503
ASSERT(writexrefs());
508
/*==========================================
509
* freexref -- Free memory & clear xrefs array
510
* Called when database is closed
511
*========================================*/
513
freexref (DELETESET set)
522
ASSERT(set->max == 0);
368
526
/*==========================================================
369
527
* num_????s -- Return number of type of things in database.
370
528
* 5 symmetric versions
371
529
*========================================================*/
372
530
static INT num_set (DELETESET set)
374
533
return set->recs[0] - set->n;
376
535
INT num_indis (void) { return num_set(&irecs); }
448
607
return newxref(xrefp, flag, &irecs);
450
/*================================================
451
* newfxref -- Return original or next fxref value
452
* xrefp = key of the individual
453
* flag = use the current key
454
*==============================================*/
456
610
newfxref (STRING xrefp, BOOLEAN flag)
458
612
return newxref(xrefp, flag, &frecs);
460
/*================================================
461
* newsxref -- Return original or next sxref value
462
* xrefp = key of the individual
463
* flag = use the current key
464
*==============================================*/
466
615
newsxref (STRING xrefp, BOOLEAN flag)
468
617
return newxref(xrefp, flag, &srecs);
470
/*================================================
471
* newexref -- Return original or next exref value
472
* xrefp = key of the individual
473
* flag = use the current key
474
*==============================================*/
476
620
newexref (STRING xrefp, BOOLEAN flag)
478
622
return newxref(xrefp, flag, &erecs);
480
/*================================================
481
* newxxref -- Return original or next xxref value
482
* xrefp = key of the individual
483
* flag = use the current key
484
*==============================================*/
486
625
newxxref (STRING xrefp, BOOLEAN flag)
610
749
INT xref_lasts (void) { return xref_last(&srecs); }
611
750
INT xref_laste (void) { return xref_last(&erecs); }
612
751
INT xref_lastx (void) { return xref_last(&xrecs); }
752
/*=======================================
753
* xrefs_get_counts_from_unopened_db --
754
* read record counts out of file on disk
755
* returns FALSE if specified path is not the root of a traditional lifelines database
756
*=====================================*/
758
xrefs_get_counts_from_unopened_db (CNSTRING path, INT *nindis, INT *nfams
759
, INT *nsours, INT *nevens, INT *nothrs)
764
INT ndels[5], nmax[5];
767
sprintf(scratch, "%s/xrefs", path);
768
if (!(fp = fopen(scratch, LLREADBINARY))) {
771
for (i=0; i<5; ++i) {
772
ASSERT(fread(&ndels[i], sizeof(INT), 1, fp) == 1);
774
for (i=0; i<5; ++i) {
776
for (j=0; j<ndels[i]; ++j) {
778
ASSERT(fread(&k, sizeof(INT), 1, fp) == 1);
783
*nindis = nmax[0] - ndels[0];
784
*nfams = nmax[1] - ndels[1];
785
*nevens = nmax[2] - ndels[2];
786
*nsours = nmax[3] - ndels[3];
787
*nothrs = nmax[4] - ndels[4];