xref: /OK3568_Linux_fs/external/xserver/record/set.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1995, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be
12*4882a593Smuzhiyun included in all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15*4882a593Smuzhiyun EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*4882a593Smuzhiyun MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*4882a593Smuzhiyun IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall
23*4882a593Smuzhiyun not be used in advertising or otherwise to promote the sale, use or
24*4882a593Smuzhiyun other dealings in this Software without prior written authorization
25*4882a593Smuzhiyun from The Open Group.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun     See the header set.h for a description of the set ADT.
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun     Implementation Strategy
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun     A bit vector is an obvious choice to represent the set, but may take
36*4882a593Smuzhiyun     too much memory, depending on the numerically largest member in the
37*4882a593Smuzhiyun     set.  One expected common case is for the client to ask for *all*
38*4882a593Smuzhiyun     protocol.  This means it would ask for minor opcodes 0 through 65535.
39*4882a593Smuzhiyun     Representing this as a bit vector takes 8K -- and there may be
40*4882a593Smuzhiyun     multiple minor opcode intervals, as many as one per major (extension)
41*4882a593Smuzhiyun     opcode).  In such cases, a list-of-intervals representation would be
42*4882a593Smuzhiyun     preferable to reduce memory consumption.  Both representations will be
43*4882a593Smuzhiyun     implemented, and RecordCreateSet will decide heuristically which one
44*4882a593Smuzhiyun     to use based on the set members.
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
49*4882a593Smuzhiyun #include <dix-config.h>
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #include <string.h>
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #include "misc.h"
55*4882a593Smuzhiyun #include "set.h"
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun static int
maxMemberInInterval(RecordSetInterval * pIntervals,int nIntervals)58*4882a593Smuzhiyun maxMemberInInterval(RecordSetInterval * pIntervals, int nIntervals)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun     int i;
61*4882a593Smuzhiyun     int maxMember = -1;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun     for (i = 0; i < nIntervals; i++) {
64*4882a593Smuzhiyun         if (maxMember < (int) pIntervals[i].last)
65*4882a593Smuzhiyun             maxMember = pIntervals[i].last;
66*4882a593Smuzhiyun     }
67*4882a593Smuzhiyun     return maxMember;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static void
NoopDestroySet(RecordSetPtr pSet)71*4882a593Smuzhiyun NoopDestroySet(RecordSetPtr pSet)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /***************************************************************************/
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /* set operations for bit vector representation */
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun typedef struct {
80*4882a593Smuzhiyun     RecordSetRec baseSet;
81*4882a593Smuzhiyun     int maxMember;
82*4882a593Smuzhiyun     /* followed by the bit vector itself */
83*4882a593Smuzhiyun } BitVectorSet, *BitVectorSetPtr;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #define BITS_PER_LONG (sizeof(unsigned long) * 8)
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static void
BitVectorDestroySet(RecordSetPtr pSet)88*4882a593Smuzhiyun BitVectorDestroySet(RecordSetPtr pSet)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun     free(pSet);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static unsigned long
BitVectorIsMemberOfSet(RecordSetPtr pSet,int pm)94*4882a593Smuzhiyun BitVectorIsMemberOfSet(RecordSetPtr pSet, int pm)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun     BitVectorSetPtr pbvs = (BitVectorSetPtr) pSet;
97*4882a593Smuzhiyun     unsigned long *pbitvec;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     if ((int) pm > pbvs->maxMember)
100*4882a593Smuzhiyun         return FALSE;
101*4882a593Smuzhiyun     pbitvec = (unsigned long *) (&pbvs[1]);
102*4882a593Smuzhiyun     return (pbitvec[pm / BITS_PER_LONG] &
103*4882a593Smuzhiyun             ((unsigned long) 1 << (pm % BITS_PER_LONG)));
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun static int
BitVectorFindBit(RecordSetPtr pSet,int iterbit,Bool bitval)107*4882a593Smuzhiyun BitVectorFindBit(RecordSetPtr pSet, int iterbit, Bool bitval)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun     BitVectorSetPtr pbvs = (BitVectorSetPtr) pSet;
110*4882a593Smuzhiyun     unsigned long *pbitvec = (unsigned long *) (&pbvs[1]);
111*4882a593Smuzhiyun     int startlong;
112*4882a593Smuzhiyun     int startbit;
113*4882a593Smuzhiyun     int walkbit;
114*4882a593Smuzhiyun     int maxMember;
115*4882a593Smuzhiyun     unsigned long skipval;
116*4882a593Smuzhiyun     unsigned long bits;
117*4882a593Smuzhiyun     unsigned long usefulbits;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun     startlong = iterbit / BITS_PER_LONG;
120*4882a593Smuzhiyun     pbitvec += startlong;
121*4882a593Smuzhiyun     startbit = startlong * BITS_PER_LONG;
122*4882a593Smuzhiyun     skipval = bitval ? 0L : ~0L;
123*4882a593Smuzhiyun     maxMember = pbvs->maxMember;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun     if (startbit > maxMember)
126*4882a593Smuzhiyun         return -1;
127*4882a593Smuzhiyun     bits = *pbitvec;
128*4882a593Smuzhiyun     usefulbits = ~(((unsigned long) 1 << (iterbit - startbit)) - 1);
129*4882a593Smuzhiyun     if ((bits & usefulbits) == (skipval & usefulbits)) {
130*4882a593Smuzhiyun         pbitvec++;
131*4882a593Smuzhiyun         startbit += BITS_PER_LONG;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun         while (startbit <= maxMember && *pbitvec == skipval) {
134*4882a593Smuzhiyun             pbitvec++;
135*4882a593Smuzhiyun             startbit += BITS_PER_LONG;
136*4882a593Smuzhiyun         }
137*4882a593Smuzhiyun         if (startbit > maxMember)
138*4882a593Smuzhiyun             return -1;
139*4882a593Smuzhiyun     }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun     walkbit = (startbit < iterbit) ? iterbit - startbit : 0;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     bits = *pbitvec;
144*4882a593Smuzhiyun     while (walkbit < BITS_PER_LONG &&
145*4882a593Smuzhiyun            ((!(bits & ((unsigned long) 1 << walkbit))) == bitval))
146*4882a593Smuzhiyun         walkbit++;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun     return startbit + walkbit;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun static RecordSetIteratePtr
BitVectorIterateSet(RecordSetPtr pSet,RecordSetIteratePtr pIter,RecordSetInterval * pInterval)152*4882a593Smuzhiyun BitVectorIterateSet(RecordSetPtr pSet, RecordSetIteratePtr pIter,
153*4882a593Smuzhiyun                     RecordSetInterval * pInterval)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun     int iterbit = (int) (long) pIter;
156*4882a593Smuzhiyun     int b;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun     b = BitVectorFindBit(pSet, iterbit, TRUE);
159*4882a593Smuzhiyun     if (b == -1)
160*4882a593Smuzhiyun         return (RecordSetIteratePtr) 0;
161*4882a593Smuzhiyun     pInterval->first = b;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun     b = BitVectorFindBit(pSet, b, FALSE);
164*4882a593Smuzhiyun     pInterval->last = (b < 0) ? ((BitVectorSetPtr) pSet)->maxMember : b - 1;
165*4882a593Smuzhiyun     return (RecordSetIteratePtr) (long) (pInterval->last + 1);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static RecordSetOperations BitVectorSetOperations = {
169*4882a593Smuzhiyun     BitVectorDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static RecordSetOperations BitVectorNoFreeOperations = {
173*4882a593Smuzhiyun     NoopDestroySet, BitVectorIsMemberOfSet, BitVectorIterateSet
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static int
BitVectorSetMemoryRequirements(RecordSetInterval * pIntervals,int nIntervals,int maxMember,int * alignment)177*4882a593Smuzhiyun BitVectorSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals,
178*4882a593Smuzhiyun                                int maxMember, int *alignment)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun     int nlongs;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     *alignment = sizeof(unsigned long);
183*4882a593Smuzhiyun     nlongs = (maxMember + BITS_PER_LONG) / BITS_PER_LONG;
184*4882a593Smuzhiyun     return (sizeof(BitVectorSet) + nlongs * sizeof(unsigned long));
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun static RecordSetPtr
BitVectorCreateSet(RecordSetInterval * pIntervals,int nIntervals,void * pMem,int memsize)188*4882a593Smuzhiyun BitVectorCreateSet(RecordSetInterval * pIntervals, int nIntervals,
189*4882a593Smuzhiyun                    void *pMem, int memsize)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun     BitVectorSetPtr pbvs;
192*4882a593Smuzhiyun     int i, j;
193*4882a593Smuzhiyun     unsigned long *pbitvec;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun     /* allocate all storage needed by this set in one chunk */
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     if (pMem) {
198*4882a593Smuzhiyun         memset(pMem, 0, memsize);
199*4882a593Smuzhiyun         pbvs = (BitVectorSetPtr) pMem;
200*4882a593Smuzhiyun         pbvs->baseSet.ops = &BitVectorNoFreeOperations;
201*4882a593Smuzhiyun     }
202*4882a593Smuzhiyun     else {
203*4882a593Smuzhiyun         pbvs = (BitVectorSetPtr) calloc(1, memsize);
204*4882a593Smuzhiyun         if (!pbvs)
205*4882a593Smuzhiyun             return NULL;
206*4882a593Smuzhiyun         pbvs->baseSet.ops = &BitVectorSetOperations;
207*4882a593Smuzhiyun     }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun     pbvs->maxMember = maxMemberInInterval(pIntervals, nIntervals);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     /* fill in the set */
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun     pbitvec = (unsigned long *) (&pbvs[1]);
214*4882a593Smuzhiyun     for (i = 0; i < nIntervals; i++) {
215*4882a593Smuzhiyun         for (j = pIntervals[i].first; j <= (int) pIntervals[i].last; j++) {
216*4882a593Smuzhiyun             pbitvec[j / BITS_PER_LONG] |=
217*4882a593Smuzhiyun                 ((unsigned long) 1 << (j % BITS_PER_LONG));
218*4882a593Smuzhiyun         }
219*4882a593Smuzhiyun     }
220*4882a593Smuzhiyun     return (RecordSetPtr) pbvs;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /***************************************************************************/
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun /* set operations for interval list representation */
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun typedef struct {
228*4882a593Smuzhiyun     RecordSetRec baseSet;
229*4882a593Smuzhiyun     int nIntervals;
230*4882a593Smuzhiyun     /* followed by the intervals (RecordSetInterval) */
231*4882a593Smuzhiyun } IntervalListSet, *IntervalListSetPtr;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun static void
IntervalListDestroySet(RecordSetPtr pSet)234*4882a593Smuzhiyun IntervalListDestroySet(RecordSetPtr pSet)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun     free(pSet);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun static unsigned long
IntervalListIsMemberOfSet(RecordSetPtr pSet,int pm)240*4882a593Smuzhiyun IntervalListIsMemberOfSet(RecordSetPtr pSet, int pm)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun     IntervalListSetPtr prls = (IntervalListSetPtr) pSet;
243*4882a593Smuzhiyun     RecordSetInterval *pInterval = (RecordSetInterval *) (&prls[1]);
244*4882a593Smuzhiyun     int hi, lo, probe;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun     /* binary search */
247*4882a593Smuzhiyun     lo = 0;
248*4882a593Smuzhiyun     hi = prls->nIntervals - 1;
249*4882a593Smuzhiyun     while (lo <= hi) {
250*4882a593Smuzhiyun         probe = (hi + lo) / 2;
251*4882a593Smuzhiyun         if (pm >= pInterval[probe].first && pm <= pInterval[probe].last)
252*4882a593Smuzhiyun             return 1;
253*4882a593Smuzhiyun         else if (pm < pInterval[probe].first)
254*4882a593Smuzhiyun             hi = probe - 1;
255*4882a593Smuzhiyun         else
256*4882a593Smuzhiyun             lo = probe + 1;
257*4882a593Smuzhiyun     }
258*4882a593Smuzhiyun     return 0;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun static RecordSetIteratePtr
IntervalListIterateSet(RecordSetPtr pSet,RecordSetIteratePtr pIter,RecordSetInterval * pIntervalReturn)262*4882a593Smuzhiyun IntervalListIterateSet(RecordSetPtr pSet, RecordSetIteratePtr pIter,
263*4882a593Smuzhiyun                        RecordSetInterval * pIntervalReturn)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun     RecordSetInterval *pInterval = (RecordSetInterval *) pIter;
266*4882a593Smuzhiyun     IntervalListSetPtr prls = (IntervalListSetPtr) pSet;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     if (pInterval == NULL) {
269*4882a593Smuzhiyun         pInterval = (RecordSetInterval *) (&prls[1]);
270*4882a593Smuzhiyun     }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     if ((pInterval - (RecordSetInterval *) (&prls[1])) < prls->nIntervals) {
273*4882a593Smuzhiyun         *pIntervalReturn = *pInterval;
274*4882a593Smuzhiyun         return (RecordSetIteratePtr) (++pInterval);
275*4882a593Smuzhiyun     }
276*4882a593Smuzhiyun     else
277*4882a593Smuzhiyun         return (RecordSetIteratePtr) NULL;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun static RecordSetOperations IntervalListSetOperations = {
281*4882a593Smuzhiyun     IntervalListDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static RecordSetOperations IntervalListNoFreeOperations = {
285*4882a593Smuzhiyun     NoopDestroySet, IntervalListIsMemberOfSet, IntervalListIterateSet
286*4882a593Smuzhiyun };
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun static int
IntervalListMemoryRequirements(RecordSetInterval * pIntervals,int nIntervals,int maxMember,int * alignment)289*4882a593Smuzhiyun IntervalListMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals,
290*4882a593Smuzhiyun                                int maxMember, int *alignment)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun     *alignment = sizeof(unsigned long);
293*4882a593Smuzhiyun     return sizeof(IntervalListSet) + nIntervals * sizeof(RecordSetInterval);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun static RecordSetPtr
IntervalListCreateSet(RecordSetInterval * pIntervals,int nIntervals,void * pMem,int memsize)297*4882a593Smuzhiyun IntervalListCreateSet(RecordSetInterval * pIntervals, int nIntervals,
298*4882a593Smuzhiyun                       void *pMem, int memsize)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun     IntervalListSetPtr prls;
301*4882a593Smuzhiyun     int i, j, k;
302*4882a593Smuzhiyun     RecordSetInterval *stackIntervals = NULL;
303*4882a593Smuzhiyun     CARD16 first;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (nIntervals > 0) {
306*4882a593Smuzhiyun         stackIntervals = xallocarray(nIntervals, sizeof(RecordSetInterval));
307*4882a593Smuzhiyun         if (!stackIntervals)
308*4882a593Smuzhiyun             return NULL;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun         /* sort intervals, store in stackIntervals (insertion sort) */
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun         for (i = 0; i < nIntervals; i++) {
313*4882a593Smuzhiyun             first = pIntervals[i].first;
314*4882a593Smuzhiyun             for (j = 0; j < i; j++) {
315*4882a593Smuzhiyun                 if (first < stackIntervals[j].first)
316*4882a593Smuzhiyun                     break;
317*4882a593Smuzhiyun             }
318*4882a593Smuzhiyun             for (k = i; k > j; k--) {
319*4882a593Smuzhiyun                 stackIntervals[k] = stackIntervals[k - 1];
320*4882a593Smuzhiyun             }
321*4882a593Smuzhiyun             stackIntervals[j] = pIntervals[i];
322*4882a593Smuzhiyun         }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun         /* merge abutting/overlapping intervals */
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun         for (i = 0; i < nIntervals - 1;) {
327*4882a593Smuzhiyun             if ((stackIntervals[i].last + (unsigned int) 1) <
328*4882a593Smuzhiyun                 stackIntervals[i + 1].first) {
329*4882a593Smuzhiyun                 i++;            /* disjoint intervals */
330*4882a593Smuzhiyun             }
331*4882a593Smuzhiyun             else {
332*4882a593Smuzhiyun                 stackIntervals[i].last = max(stackIntervals[i].last,
333*4882a593Smuzhiyun                                              stackIntervals[i + 1].last);
334*4882a593Smuzhiyun                 nIntervals--;
335*4882a593Smuzhiyun                 for (j = i + 1; j < nIntervals; j++)
336*4882a593Smuzhiyun                     stackIntervals[j] = stackIntervals[j + 1];
337*4882a593Smuzhiyun             }
338*4882a593Smuzhiyun         }
339*4882a593Smuzhiyun     }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     /* allocate and fill in set structure */
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     if (pMem) {
344*4882a593Smuzhiyun         prls = (IntervalListSetPtr) pMem;
345*4882a593Smuzhiyun         prls->baseSet.ops = &IntervalListNoFreeOperations;
346*4882a593Smuzhiyun     }
347*4882a593Smuzhiyun     else {
348*4882a593Smuzhiyun         prls = (IntervalListSetPtr)
349*4882a593Smuzhiyun             malloc(sizeof(IntervalListSet) +
350*4882a593Smuzhiyun                    nIntervals * sizeof(RecordSetInterval));
351*4882a593Smuzhiyun         if (!prls)
352*4882a593Smuzhiyun             goto bailout;
353*4882a593Smuzhiyun         prls->baseSet.ops = &IntervalListSetOperations;
354*4882a593Smuzhiyun     }
355*4882a593Smuzhiyun     memcpy(&prls[1], stackIntervals, nIntervals * sizeof(RecordSetInterval));
356*4882a593Smuzhiyun     prls->nIntervals = nIntervals;
357*4882a593Smuzhiyun  bailout:
358*4882a593Smuzhiyun     free(stackIntervals);
359*4882a593Smuzhiyun     return (RecordSetPtr) prls;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun typedef RecordSetPtr(*RecordCreateSetProcPtr) (RecordSetInterval * pIntervals,
363*4882a593Smuzhiyun                                                int nIntervals,
364*4882a593Smuzhiyun                                                void *pMem, int memsize);
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun static int
_RecordSetMemoryRequirements(RecordSetInterval * pIntervals,int nIntervals,int * alignment,RecordCreateSetProcPtr * ppCreateSet)367*4882a593Smuzhiyun _RecordSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals,
368*4882a593Smuzhiyun                              int *alignment,
369*4882a593Smuzhiyun                              RecordCreateSetProcPtr * ppCreateSet)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun     int bmsize, rlsize, bma, rla;
372*4882a593Smuzhiyun     int maxMember;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun     /* find maximum member of set so we know how big to make the bit vector */
375*4882a593Smuzhiyun     maxMember = maxMemberInInterval(pIntervals, nIntervals);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     bmsize = BitVectorSetMemoryRequirements(pIntervals, nIntervals, maxMember,
378*4882a593Smuzhiyun                                             &bma);
379*4882a593Smuzhiyun     rlsize = IntervalListMemoryRequirements(pIntervals, nIntervals, maxMember,
380*4882a593Smuzhiyun                                             &rla);
381*4882a593Smuzhiyun     if (((nIntervals > 1) && (maxMember <= 255))
382*4882a593Smuzhiyun         || (bmsize < rlsize)) {
383*4882a593Smuzhiyun         *alignment = bma;
384*4882a593Smuzhiyun         *ppCreateSet = BitVectorCreateSet;
385*4882a593Smuzhiyun         return bmsize;
386*4882a593Smuzhiyun     }
387*4882a593Smuzhiyun     else {
388*4882a593Smuzhiyun         *alignment = rla;
389*4882a593Smuzhiyun         *ppCreateSet = IntervalListCreateSet;
390*4882a593Smuzhiyun         return rlsize;
391*4882a593Smuzhiyun     }
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun /***************************************************************************/
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun /* user-visible functions */
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun int
RecordSetMemoryRequirements(RecordSetInterval * pIntervals,int nIntervals,int * alignment)399*4882a593Smuzhiyun RecordSetMemoryRequirements(RecordSetInterval * pIntervals, int nIntervals,
400*4882a593Smuzhiyun                             int *alignment)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun     RecordCreateSetProcPtr pCreateSet;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun     return _RecordSetMemoryRequirements(pIntervals, nIntervals, alignment,
405*4882a593Smuzhiyun                                         &pCreateSet);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun RecordSetPtr
RecordCreateSet(RecordSetInterval * pIntervals,int nIntervals,void * pMem,int memsize)409*4882a593Smuzhiyun RecordCreateSet(RecordSetInterval * pIntervals, int nIntervals, void *pMem,
410*4882a593Smuzhiyun                 int memsize)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun     RecordCreateSetProcPtr pCreateSet;
413*4882a593Smuzhiyun     int alignment;
414*4882a593Smuzhiyun     int size;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun     size = _RecordSetMemoryRequirements(pIntervals, nIntervals, &alignment,
417*4882a593Smuzhiyun                                         &pCreateSet);
418*4882a593Smuzhiyun     if (pMem) {
419*4882a593Smuzhiyun         if (((long) pMem & (alignment - 1)) || memsize < size)
420*4882a593Smuzhiyun             return NULL;
421*4882a593Smuzhiyun     }
422*4882a593Smuzhiyun     return (*pCreateSet) (pIntervals, nIntervals, pMem, size);
423*4882a593Smuzhiyun }
424