7 dbiIndexSet dbiIndexSetNew(unsigned int sizehint)
9 dbiIndexSet set = xcalloc(1, sizeof(*set));
11 dbiIndexSetGrow(set, sizehint);
16 * Ensure sufficient memory for nrecs of new records in dbiIndexSet.
17 * Allocate in power of two sizes to avoid memory fragmentation, so
18 * realloc is not always needed.
20 void dbiIndexSetGrow(dbiIndexSet set, unsigned int nrecs)
22 size_t need = (set->count + nrecs) * sizeof(*(set->recs));
23 size_t alloced = set->alloced ? set->alloced : 1 << 4;
25 while (alloced < need)
28 if (alloced != set->alloced) {
29 set->recs = xrealloc(set->recs, alloced);
30 set->alloced = alloced;
34 static int hdrNumCmp(const void * one, const void * two)
36 const struct dbiIndexItem_s *a = one, *b = two;
37 if (a->hdrNum - b->hdrNum != 0)
38 return a->hdrNum - b->hdrNum;
39 return a->tagNum - b->tagNum;
42 void dbiIndexSetSort(dbiIndexSet set)
45 * mergesort is much (~10x with lots of identical basenames) faster
46 * than pure quicksort, but glibc uses msort_with_tmp() on stack.
48 if (set && set->recs && set->count > 1) {
50 mergesort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp);
52 qsort(set->recs, set->count, sizeof(*set->recs), hdrNumCmp);
57 void dbiIndexSetUniq(dbiIndexSet set, int sorted)
61 unsigned int num = set->count;
69 for (from = 0; from < num; from++) {
70 if (from > 0 && set->recs[from - 1].hdrNum == set->recs[from].hdrNum) {
75 set->recs[to] = set->recs[from]; /* structure assignment */
80 int dbiIndexSetAppend(dbiIndexSet set, dbiIndexItem recs,
81 unsigned int nrecs, int sortset)
83 if (set == NULL || recs == NULL)
87 dbiIndexSetGrow(set, nrecs);
88 memcpy(set->recs + set->count, recs, nrecs * sizeof(*(set->recs)));
92 if (sortset && set->count > 1)
93 qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp);
98 int dbiIndexSetAppendSet(dbiIndexSet set, dbiIndexSet oset, int sortset)
102 return dbiIndexSetAppend(set, oset->recs, oset->count, sortset);
105 int dbiIndexSetAppendOne(dbiIndexSet set, unsigned int hdrNum,
106 unsigned int tagNum, int sortset)
110 dbiIndexSetGrow(set, 1);
112 set->recs[set->count].hdrNum = hdrNum;
113 set->recs[set->count].tagNum = tagNum;
116 if (sortset && set->count > 1)
117 qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp);
122 int dbiIndexSetPrune(dbiIndexSet set, dbiIndexItem recs,
123 unsigned int nrecs, int sorted)
127 unsigned int num = set->count;
128 unsigned int numCopied = 0;
129 size_t recsize = sizeof(*recs);
131 if (num == 0 || nrecs == 0)
134 if (nrecs > 1 && !sorted)
135 qsort(recs, nrecs, recsize, hdrNumCmp);
137 for (from = 0; from < num; from++) {
138 if (bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) {
143 set->recs[to] = set->recs[from]; /* structure assignment */
147 return (numCopied == num);
150 int dbiIndexSetPruneSet(dbiIndexSet set, dbiIndexSet oset, int sortset)
154 return dbiIndexSetPrune(set, oset->recs, oset->count, sortset);
157 int dbiIndexSetFilter(dbiIndexSet set, dbiIndexItem recs,
158 unsigned int nrecs, int sorted)
162 unsigned int num = set->count;
163 unsigned int numCopied = 0;
164 size_t recsize = sizeof(*recs);
166 if (num == 0 || nrecs == 0) {
170 if (nrecs > 1 && !sorted)
171 qsort(recs, nrecs, recsize, hdrNumCmp);
172 for (from = 0; from < num; from++) {
173 if (!bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) {
178 set->recs[to] = set->recs[from]; /* structure assignment */
182 return (numCopied == num);
185 int dbiIndexSetFilterSet(dbiIndexSet set, dbiIndexSet oset, int sorted)
187 return dbiIndexSetFilter(set, oset->recs, oset->count, sorted);
190 unsigned int dbiIndexSetCount(dbiIndexSet set)
192 return (set != NULL) ? set->count : 0;
195 unsigned int dbiIndexRecordOffset(dbiIndexSet set, unsigned int recno)
197 return set->recs[recno].hdrNum;
200 unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, unsigned int recno)
202 return set->recs[recno].tagNum;
205 dbiIndexSet dbiIndexSetFree(dbiIndexSet set)
209 memset(set, 0, sizeof(*set)); /* trash and burn */