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