#include "system.h" #include #include #include "dbiset.h" #include "debug.h" dbiIndexSet dbiIndexSetNew(unsigned int sizehint) { dbiIndexSet set = xcalloc(1, sizeof(*set)); if (sizehint > 0) dbiIndexSetGrow(set, sizehint); return set; } /* * Ensure sufficient memory for nrecs of new records in dbiIndexSet. * Allocate in power of two sizes to avoid memory fragmentation, so * realloc is not always needed. */ void dbiIndexSetGrow(dbiIndexSet set, unsigned int nrecs) { size_t need = (set->count + nrecs) * sizeof(*(set->recs)); size_t alloced = set->alloced ? set->alloced : 1 << 4; while (alloced < need) alloced <<= 1; if (alloced != set->alloced) { set->recs = xrealloc(set->recs, alloced); set->alloced = alloced; } } static int hdrNumCmp(const void * one, const void * two) { const struct dbiIndexItem_s *a = one, *b = two; if (a->hdrNum - b->hdrNum != 0) return a->hdrNum - b->hdrNum; return a->tagNum - b->tagNum; } void dbiIndexSetSort(dbiIndexSet set) { /* * mergesort is much (~10x with lots of identical basenames) faster * than pure quicksort, but glibc uses msort_with_tmp() on stack. */ if (set && set->recs && set->count > 1) { #if HAVE_MERGESORT mergesort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp); #else qsort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp); #endif } } void dbiIndexSetUniq(dbiIndexSet set, int sorted) { unsigned int from; unsigned int to = 0; unsigned int num = set->count; if (set->count < 2) return; if (!sorted) dbiIndexSetSort(set); for (from = 0; from < num; from++) { if (from > 0 && set->recs[from - 1].hdrNum == set->recs[from].hdrNum) { set->count--; continue; } if (from != to) set->recs[to] = set->recs[from]; /* structure assignment */ to++; } } int dbiIndexSetAppend(dbiIndexSet set, dbiIndexItem recs, unsigned int nrecs, int sortset) { if (set == NULL || recs == NULL) return 1; if (nrecs) { dbiIndexSetGrow(set, nrecs); memcpy(set->recs + set->count, recs, nrecs * sizeof(*(set->recs))); set->count += nrecs; } if (sortset && set->count > 1) qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp); return 0; } int dbiIndexSetAppendSet(dbiIndexSet set, dbiIndexSet oset, int sortset) { if (oset == NULL) return 1; return dbiIndexSetAppend(set, oset->recs, oset->count, sortset); } int dbiIndexSetAppendOne(dbiIndexSet set, unsigned int hdrNum, unsigned int tagNum, int sortset) { if (set == NULL) return 1; dbiIndexSetGrow(set, 1); set->recs[set->count].hdrNum = hdrNum; set->recs[set->count].tagNum = tagNum; set->count += 1; if (sortset && set->count > 1) qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp); return 0; } int dbiIndexSetPrune(dbiIndexSet set, dbiIndexItem recs, unsigned int nrecs, int sorted) { unsigned int from; unsigned int to = 0; unsigned int num = set->count; unsigned int numCopied = 0; size_t recsize = sizeof(*recs); if (num == 0 || nrecs == 0) return 1; if (nrecs > 1 && !sorted) qsort(recs, nrecs, recsize, hdrNumCmp); for (from = 0; from < num; from++) { if (bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) { set->count--; continue; } if (from != to) set->recs[to] = set->recs[from]; /* structure assignment */ to++; numCopied++; } return (numCopied == num); } int dbiIndexSetPruneSet(dbiIndexSet set, dbiIndexSet oset, int sortset) { if (oset == NULL) return 1; return dbiIndexSetPrune(set, oset->recs, oset->count, sortset); } int dbiIndexSetFilter(dbiIndexSet set, dbiIndexItem recs, unsigned int nrecs, int sorted) { unsigned int from; unsigned int to = 0; unsigned int num = set->count; unsigned int numCopied = 0; size_t recsize = sizeof(*recs); if (num == 0 || nrecs == 0) { set->count = 0; return num ? 0 : 1; } if (nrecs > 1 && !sorted) qsort(recs, nrecs, recsize, hdrNumCmp); for (from = 0; from < num; from++) { if (!bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) { set->count--; continue; } if (from != to) set->recs[to] = set->recs[from]; /* structure assignment */ to++; numCopied++; } return (numCopied == num); } int dbiIndexSetFilterSet(dbiIndexSet set, dbiIndexSet oset, int sorted) { return dbiIndexSetFilter(set, oset->recs, oset->count, sorted); } unsigned int dbiIndexSetCount(dbiIndexSet set) { return (set != NULL) ? set->count : 0; } unsigned int dbiIndexRecordOffset(dbiIndexSet set, unsigned int recno) { return set->recs[recno].hdrNum; } unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, unsigned int recno) { return set->recs[recno].tagNum; } dbiIndexSet dbiIndexSetFree(dbiIndexSet set) { if (set) { free(set->recs); memset(set, 0, sizeof(*set)); /* trash and burn */ free(set); } return NULL; }