master
c 1,094 lines 34.9 KB
Raw
1 // Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 //
3 // This program is free software; you can redistribute it and/or modify it
4 // under the term of the GNU Lesser General Public License as published by the
5 // Free Software Foundation; either version 2 of the License, or (at your
6 // option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but WITHOUT
9 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 // for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program; if not, write to the Free Software Foundation,
15 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 // _________________
17
18 // @(#) $Revision: 4.43 $ $Source: /judy/src/JudyCommon/JudyGet.c $
19 //
20 // Judy1Test() and JudyLGet() functions for Judy1 and JudyL.
21 // Compile with one of -DJUDY1 or -DJUDYL.
22
23 #if (! (defined(JUDY1) || defined(JUDYL)))
24 #error: One of -DJUDY1 or -DJUDYL must be specified.
25 #endif
26
27 #ifdef JUDY1
28 #include "Judy1.h"
29 #else
30 #include "JudyL.h"
31 #endif
32
33 #include "JudyPrivate1L.h"
34
35 #ifdef TRACEJPR // different macro name, for "retrieval" only.
36 #include "JudyPrintJP.c"
37 #endif
38
39
40 // ****************************************************************************
41 // J U D Y 1 T E S T
42 // J U D Y L G E T
43 //
44 // See the manual entry for details. Note support for "shortcut" entries to
45 // trees known to start with a JPM.
46
47 #ifdef JUDY1
48
49 #ifdef JUDYGETINLINE
50 FUNCTION int j__udy1Test
51 #else
52 FUNCTION int Judy1Test
53 #endif
54
55 #else // JUDYL
56
57 #ifdef JUDYGETINLINE
58 FUNCTION PPvoid_t j__udyLGet
59 #else
60 FUNCTION PPvoid_t JudyLGet
61 #endif
62
63 #endif // JUDYL
64 (
65 #ifdef JUDYGETINLINE
66 Pvoid_t PArray, // from which to retrieve.
67 Word_t Index // to retrieve.
68 #else
69 Pcvoid_t PArray, // from which to retrieve.
70 Word_t Index, // to retrieve.
71 PJError_t PJError // optional, for returning error info.
72 #endif
73 )
74 {
75 Pjp_t Pjp; // current JP while walking the tree.
76 Pjpm_t Pjpm; // for global accounting.
77 uint8_t Digit; // byte just decoded from Index.
78 Word_t Pop1; // leaf population (number of indexes).
79 Pjll_t Pjll; // pointer to LeafL.
80 DBGCODE(uint8_t ParentJPType;)
81
82 #ifndef JUDYGETINLINE
83
84 if (PArray == (Pcvoid_t) NULL) // empty array.
85 {
86 JUDY1CODE(return(0);)
87 JUDYLCODE(return((PPvoid_t) NULL);)
88 }
89
90 // ****************************************************************************
91 // PROCESS TOP LEVEL BRANCHES AND LEAF:
92
93 if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
94 {
95 Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
96 int posidx; // signed offset in leaf.
97
98 Pop1 = Pjlw[0] + 1;
99 posidx = j__udySearchLeafW(Pjlw + 1, Pop1, Index);
100
101 if (posidx >= 0)
102 {
103 JUDY1CODE(return(1);)
104 JUDYLCODE(return((PPvoid_t) (JL_LEAFWVALUEAREA(Pjlw, Pop1) + posidx));)
105 }
106 JUDY1CODE(return(0);)
107 JUDYLCODE(return((PPvoid_t) NULL);)
108 }
109
110 #endif // ! JUDYGETINLINE
111
112 Pjpm = P_JPM(PArray);
113 Pjp = &(Pjpm->jpm_JP); // top branch is below JPM.
114
115 // ****************************************************************************
116 // WALK THE JUDY TREE USING A STATE MACHINE:
117
118 ContinueWalk: // for going down one level; come here with Pjp set.
119
120 #ifdef TRACEJPR
121 JudyPrintJP(Pjp, "g", __LINE__);
122 #endif
123 switch (JU_JPTYPE(Pjp))
124 {
125
126 // Ensure the switch table starts at 0 for speed; otherwise more code is
127 // executed:
128
129 case 0: goto ReturnCorrupt; // save a little code.
130
131
132 // ****************************************************************************
133 // JPNULL*:
134 //
135 // Note: These are legitimate in a BranchU (only) and do not constitute a
136 // fault.
137
138 case cJU_JPNULL1:
139 case cJU_JPNULL2:
140 case cJU_JPNULL3:
141 #ifdef JU_64BIT
142 case cJU_JPNULL4:
143 case cJU_JPNULL5:
144 case cJU_JPNULL6:
145 case cJU_JPNULL7:
146 #endif
147 assert(ParentJPType >= cJU_JPBRANCH_U2);
148 assert(ParentJPType <= cJU_JPBRANCH_U);
149 JUDY1CODE(return(0);)
150 JUDYLCODE(return((PPvoid_t) NULL);)
151
152
153 // ****************************************************************************
154 // JPBRANCH_L*:
155 //
156 // Note: The use of JU_DCDNOTMATCHINDEX() in branches is not strictly
157 // required,since this can be done at leaf level, but it costs nothing to do it
158 // sooner, and it aborts an unnecessary traversal sooner.
159
160 case cJU_JPBRANCH_L2:
161
162 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
163 Digit = JU_DIGITATSTATE(Index, 2);
164 goto JudyBranchL;
165
166 case cJU_JPBRANCH_L3:
167
168 #ifdef JU_64BIT // otherwise its a no-op:
169 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
170 #endif
171 Digit = JU_DIGITATSTATE(Index, 3);
172 goto JudyBranchL;
173
174 #ifdef JU_64BIT
175 case cJU_JPBRANCH_L4:
176
177 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
178 Digit = JU_DIGITATSTATE(Index, 4);
179 goto JudyBranchL;
180
181 case cJU_JPBRANCH_L5:
182
183 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
184 Digit = JU_DIGITATSTATE(Index, 5);
185 goto JudyBranchL;
186
187 case cJU_JPBRANCH_L6:
188
189 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
190 Digit = JU_DIGITATSTATE(Index, 6);
191 goto JudyBranchL;
192
193 case cJU_JPBRANCH_L7:
194
195 // JU_DCDNOTMATCHINDEX() would be a no-op.
196 Digit = JU_DIGITATSTATE(Index, 7);
197 goto JudyBranchL;
198
199 #endif // JU_64BIT
200
201 case cJU_JPBRANCH_L:
202 {
203 Pjbl_t Pjbl;
204 int posidx;
205
206 Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
207
208 // Common code for all BranchLs; come here with Digit set:
209
210 JudyBranchL:
211 Pjbl = P_JBL(Pjp->jp_Addr);
212
213 posidx = 0;
214
215 do {
216 if (Pjbl->jbl_Expanse[posidx] == Digit)
217 { // found Digit; continue traversal:
218 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
219 Pjp = Pjbl->jbl_jp + posidx;
220 goto ContinueWalk;
221 }
222 } while (++posidx != Pjbl->jbl_NumJPs);
223
224 break;
225 }
226
227
228 // ****************************************************************************
229 // JPBRANCH_B*:
230
231 case cJU_JPBRANCH_B2:
232
233 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
234 Digit = JU_DIGITATSTATE(Index, 2);
235 goto JudyBranchB;
236
237 case cJU_JPBRANCH_B3:
238
239 #ifdef JU_64BIT // otherwise its a no-op:
240 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
241 #endif
242 Digit = JU_DIGITATSTATE(Index, 3);
243 goto JudyBranchB;
244
245
246 #ifdef JU_64BIT
247 case cJU_JPBRANCH_B4:
248
249 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
250 Digit = JU_DIGITATSTATE(Index, 4);
251 goto JudyBranchB;
252
253 case cJU_JPBRANCH_B5:
254
255 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
256 Digit = JU_DIGITATSTATE(Index, 5);
257 goto JudyBranchB;
258
259 case cJU_JPBRANCH_B6:
260
261 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
262 Digit = JU_DIGITATSTATE(Index, 6);
263 goto JudyBranchB;
264
265 case cJU_JPBRANCH_B7:
266
267 // JU_DCDNOTMATCHINDEX() would be a no-op.
268 Digit = JU_DIGITATSTATE(Index, 7);
269 goto JudyBranchB;
270
271 #endif // JU_64BIT
272
273 case cJU_JPBRANCH_B:
274 {
275 Pjbb_t Pjbb;
276 Word_t subexp; // in bitmap, 0..7.
277 BITMAPB_t BitMap; // for one subexpanse.
278 BITMAPB_t BitMask; // bit in BitMap for Indexs Digit.
279
280 Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
281
282 // Common code for all BranchBs; come here with Digit set:
283
284 JudyBranchB:
285 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
286 Pjbb = P_JBB(Pjp->jp_Addr);
287 subexp = Digit / cJU_BITSPERSUBEXPB;
288
289 BitMap = JU_JBB_BITMAP(Pjbb, subexp);
290 Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp));
291
292 BitMask = JU_BITPOSMASKB(Digit);
293
294 // No JP in subexpanse for Index => Index not found:
295
296 if (! (BitMap & BitMask)) break;
297
298 // Count JPs in the subexpanse below the one for Index:
299
300 Pjp += j__udyCountBitsB(BitMap & (BitMask - 1));
301
302 goto ContinueWalk;
303
304 } // case cJU_JPBRANCH_B*
305
306
307 // ****************************************************************************
308 // JPBRANCH_U*:
309 //
310 // Notice the reverse order of the cases, and falling through to the next case,
311 // for performance.
312
313 case cJU_JPBRANCH_U:
314
315 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
316 Pjp = JU_JBU_PJP(Pjp, Index, cJU_ROOTSTATE);
317
318 // If not a BranchU, traverse; otherwise fall into the next case, which makes
319 // this very fast code for a large Judy array (mainly BranchUs), especially
320 // when branches are already in the cache, such as for prev/next:
321
322 #ifndef JU_64BIT
323 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
324 #else
325 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U7) goto ContinueWalk;
326 #endif
327
328 #ifdef JU_64BIT
329 case cJU_JPBRANCH_U7:
330
331 // JU_DCDNOTMATCHINDEX() would be a no-op.
332 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
333 Pjp = JU_JBU_PJP(Pjp, Index, 7);
334
335 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U6) goto ContinueWalk;
336 // and fall through.
337
338 case cJU_JPBRANCH_U6:
339
340 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
341 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
342 Pjp = JU_JBU_PJP(Pjp, Index, 6);
343
344 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U5) goto ContinueWalk;
345 // and fall through.
346
347 case cJU_JPBRANCH_U5:
348
349 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
350 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
351 Pjp = JU_JBU_PJP(Pjp, Index, 5);
352
353 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U4) goto ContinueWalk;
354 // and fall through.
355
356 case cJU_JPBRANCH_U4:
357
358 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
359 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
360 Pjp = JU_JBU_PJP(Pjp, Index, 4);
361
362 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
363 // and fall through.
364
365 #endif // JU_64BIT
366
367 case cJU_JPBRANCH_U3:
368
369 #ifdef JU_64BIT // otherwise its a no-op:
370 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
371 #endif
372 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
373 Pjp = JU_JBU_PJP(Pjp, Index, 3);
374
375 if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U2) goto ContinueWalk;
376 // and fall through.
377
378 case cJU_JPBRANCH_U2:
379
380 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
381 DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
382 Pjp = JU_JBU_PJP(Pjp, Index, 2);
383
384 // Note: BranchU2 is a special case that must continue traversal to a leaf,
385 // immed, full, or null type:
386
387 goto ContinueWalk;
388
389
390 // ****************************************************************************
391 // JPLEAF*:
392 //
393 // Note: Here the calls of JU_DCDNOTMATCHINDEX() are necessary and check
394 // whether Index is out of the expanse of a narrow pointer.
395
396 #if (defined(JUDYL) || (! defined(JU_64BIT)))
397
398 case cJU_JPLEAF1:
399 {
400 int posidx; // signed offset in leaf.
401
402 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
403
404 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
405 Pjll = P_JLL(Pjp->jp_Addr);
406
407 if ((posidx = j__udySearchLeaf1(Pjll, Pop1, Index)) < 0) break;
408
409 JUDY1CODE(return(1);)
410 JUDYLCODE(return((PPvoid_t) (JL_LEAF1VALUEAREA(Pjll, Pop1) + posidx));)
411 }
412
413 #endif // (JUDYL || (! JU_64BIT))
414
415 case cJU_JPLEAF2:
416 {
417 int posidx; // signed offset in leaf.
418
419 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
420
421 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
422 Pjll = P_JLL(Pjp->jp_Addr);
423
424 if ((posidx = j__udySearchLeaf2(Pjll, Pop1, Index)) < 0) break;
425
426 JUDY1CODE(return(1);)
427 JUDYLCODE(return((PPvoid_t) (JL_LEAF2VALUEAREA(Pjll, Pop1) + posidx));)
428 }
429 case cJU_JPLEAF3:
430 {
431 int posidx; // signed offset in leaf.
432
433 #ifdef JU_64BIT // otherwise its a no-op:
434 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
435 #endif
436
437 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
438 Pjll = P_JLL(Pjp->jp_Addr);
439
440 if ((posidx = j__udySearchLeaf3(Pjll, Pop1, Index)) < 0) break;
441
442 JUDY1CODE(return(1);)
443 JUDYLCODE(return((PPvoid_t) (JL_LEAF3VALUEAREA(Pjll, Pop1) + posidx));)
444 }
445 #ifdef JU_64BIT
446 case cJU_JPLEAF4:
447 {
448 int posidx; // signed offset in leaf.
449
450 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
451
452 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
453 Pjll = P_JLL(Pjp->jp_Addr);
454
455 if ((posidx = j__udySearchLeaf4(Pjll, Pop1, Index)) < 0) break;
456
457 JUDY1CODE(return(1);)
458 JUDYLCODE(return((PPvoid_t) (JL_LEAF4VALUEAREA(Pjll, Pop1) + posidx));)
459 }
460 case cJU_JPLEAF5:
461 {
462 int posidx; // signed offset in leaf.
463
464 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
465
466 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
467 Pjll = P_JLL(Pjp->jp_Addr);
468
469 if ((posidx = j__udySearchLeaf5(Pjll, Pop1, Index)) < 0) break;
470
471 JUDY1CODE(return(1);)
472 JUDYLCODE(return((PPvoid_t) (JL_LEAF5VALUEAREA(Pjll, Pop1) + posidx));)
473 }
474
475 case cJU_JPLEAF6:
476 {
477 int posidx; // signed offset in leaf.
478
479 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
480
481 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
482 Pjll = P_JLL(Pjp->jp_Addr);
483
484 if ((posidx = j__udySearchLeaf6(Pjll, Pop1, Index)) < 0) break;
485
486 JUDY1CODE(return(1);)
487 JUDYLCODE(return((PPvoid_t) (JL_LEAF6VALUEAREA(Pjll, Pop1) + posidx));)
488 }
489 case cJU_JPLEAF7:
490 {
491 int posidx; // signed offset in leaf.
492
493 // JU_DCDNOTMATCHINDEX() would be a no-op.
494 Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
495 Pjll = P_JLL(Pjp->jp_Addr);
496
497 if ((posidx = j__udySearchLeaf7(Pjll, Pop1, Index)) < 0) break;
498
499 JUDY1CODE(return(1);)
500 JUDYLCODE(return((PPvoid_t) (JL_LEAF7VALUEAREA(Pjll, Pop1) + posidx));)
501 }
502 #endif // JU_64BIT
503
504
505 // ****************************************************************************
506 // JPLEAF_B1:
507
508 case cJU_JPLEAF_B1:
509 {
510 Pjlb_t Pjlb;
511 #ifdef JUDYL
512 int posidx;
513 Word_t subexp; // in bitmap, 0..7.
514 BITMAPL_t BitMap; // for one subexpanse.
515 BITMAPL_t BitMask; // bit in BitMap for Indexs Digit.
516 Pjv_t Pjv;
517 #endif
518 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
519
520 Pjlb = P_JLB(Pjp->jp_Addr);
521
522 #ifdef JUDY1
523
524 // Simply check if Indexs bit is set in the bitmap:
525
526 if (JU_BITMAPTESTL(Pjlb, Index)) return(1);
527 break;
528
529 #else // JUDYL
530
531 // JudyL is much more complicated because of value area subarrays:
532
533 Digit = JU_DIGITATSTATE(Index, 1);
534 subexp = Digit / cJU_BITSPERSUBEXPL;
535 BitMap = JU_JLB_BITMAP(Pjlb, subexp);
536 BitMask = JU_BITPOSMASKL(Digit);
537
538 // No value in subexpanse for Index => Index not found:
539
540 if (! (BitMap & BitMask)) break;
541
542 // Count value areas in the subexpanse below the one for Index:
543
544 Pjv = P_JV(JL_JLB_PVALUE(Pjlb, subexp));
545 assert(Pjv != (Pjv_t) NULL);
546 posidx = j__udyCountBitsL(BitMap & (BitMask - 1));
547
548 return((PPvoid_t) (Pjv + posidx));
549
550 #endif // JUDYL
551
552 } // case cJU_JPLEAF_B1
553
554 #ifdef JUDY1
555
556 // ****************************************************************************
557 // JPFULLPOPU1:
558 //
559 // If the Index is in the expanse, it is necessarily valid (found).
560
561 case cJ1_JPFULLPOPU1:
562
563 if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
564 return(1);
565
566 #ifdef notdef // for future enhancements
567 #ifdef JU_64BIT
568
569 // Note: Need ? if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
570
571 case cJ1_JPFULLPOPU1m15:
572 if (Pjp->jp_1Index[14] == (uint8_t)Index) break;
573 case cJ1_JPFULLPOPU1m14:
574 if (Pjp->jp_1Index[13] == (uint8_t)Index) break;
575 case cJ1_JPFULLPOPU1m13:
576 if (Pjp->jp_1Index[12] == (uint8_t)Index) break;
577 case cJ1_JPFULLPOPU1m12:
578 if (Pjp->jp_1Index[11] == (uint8_t)Index) break;
579 case cJ1_JPFULLPOPU1m11:
580 if (Pjp->jp_1Index[10] == (uint8_t)Index) break;
581 case cJ1_JPFULLPOPU1m10:
582 if (Pjp->jp_1Index[9] == (uint8_t)Index) break;
583 case cJ1_JPFULLPOPU1m9:
584 if (Pjp->jp_1Index[8] == (uint8_t)Index) break;
585 case cJ1_JPFULLPOPU1m8:
586 if (Pjp->jp_1Index[7] == (uint8_t)Index) break;
587 #endif
588 case cJ1_JPFULLPOPU1m7:
589 if (Pjp->jp_1Index[6] == (uint8_t)Index) break;
590 case cJ1_JPFULLPOPU1m6:
591 if (Pjp->jp_1Index[5] == (uint8_t)Index) break;
592 case cJ1_JPFULLPOPU1m5:
593 if (Pjp->jp_1Index[4] == (uint8_t)Index) break;
594 case cJ1_JPFULLPOPU1m4:
595 if (Pjp->jp_1Index[3] == (uint8_t)Index) break;
596 case cJ1_JPFULLPOPU1m3:
597 if (Pjp->jp_1Index[2] == (uint8_t)Index) break;
598 case cJ1_JPFULLPOPU1m2:
599 if (Pjp->jp_1Index[1] == (uint8_t)Index) break;
600 case cJ1_JPFULLPOPU1m1:
601 if (Pjp->jp_1Index[0] == (uint8_t)Index) break;
602
603 return(1); // found, not in exclusion list
604
605 #endif // JUDY1
606 #endif // notdef
607
608 // ****************************************************************************
609 // JPIMMED*:
610 //
611 // Note that the contents of jp_DcdPopO are different for cJU_JPIMMED_*_01:
612
613 case cJU_JPIMMED_1_01:
614 case cJU_JPIMMED_2_01:
615 case cJU_JPIMMED_3_01:
616 #ifdef JU_64BIT
617 case cJU_JPIMMED_4_01:
618 case cJU_JPIMMED_5_01:
619 case cJU_JPIMMED_6_01:
620 case cJU_JPIMMED_7_01:
621 #endif
622 if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) break;
623
624 JUDY1CODE(return(1);)
625 JUDYLCODE(return((PPvoid_t) &(Pjp->jp_Addr));) // immediate value area.
626
627
628 // Macros to make code more readable and avoid dup errors
629
630 #ifdef JUDY1
631
632 #define CHECKINDEXNATIVE(LEAF_T, PJP, IDX, INDEX) \
633 if (((LEAF_T *)((PJP)->jp_1Index))[(IDX) - 1] == (LEAF_T)(INDEX)) \
634 return(1)
635
636 #define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
637 { \
638 Word_t i_ndex; \
639 uint8_t *a_ddr; \
640 a_ddr = (PJP)->jp_1Index + (((IDX) - 1) * (LFBTS)); \
641 COPY(i_ndex, a_ddr); \
642 if (i_ndex == JU_LEASTBYTES((INDEX), (LFBTS))) \
643 return(1); \
644 }
645 #endif
646
647 #ifdef JUDYL
648
649 #define CHECKINDEXNATIVE(LEAF_T, PJP, IDX, INDEX) \
650 if (((LEAF_T *)((PJP)->jp_LIndex))[(IDX) - 1] == (LEAF_T)(INDEX)) \
651 return((PPvoid_t)(P_JV((PJP)->jp_Addr) + (IDX) - 1))
652
653 #define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
654 { \
655 Word_t i_ndex; \
656 uint8_t *a_ddr; \
657 a_ddr = (PJP)->jp_LIndex + (((IDX) - 1) * (LFBTS)); \
658 COPY(i_ndex, a_ddr); \
659 if (i_ndex == JU_LEASTBYTES((INDEX), (LFBTS))) \
660 return((PPvoid_t)(P_JV((PJP)->jp_Addr) + (IDX) - 1)); \
661 }
662 #endif
663
664 #if (defined(JUDY1) && defined(JU_64BIT))
665 case cJ1_JPIMMED_1_15: CHECKINDEXNATIVE(uint8_t, Pjp, 15, Index);
666 case cJ1_JPIMMED_1_14: CHECKINDEXNATIVE(uint8_t, Pjp, 14, Index);
667 case cJ1_JPIMMED_1_13: CHECKINDEXNATIVE(uint8_t, Pjp, 13, Index);
668 case cJ1_JPIMMED_1_12: CHECKINDEXNATIVE(uint8_t, Pjp, 12, Index);
669 case cJ1_JPIMMED_1_11: CHECKINDEXNATIVE(uint8_t, Pjp, 11, Index);
670 case cJ1_JPIMMED_1_10: CHECKINDEXNATIVE(uint8_t, Pjp, 10, Index);
671 case cJ1_JPIMMED_1_09: CHECKINDEXNATIVE(uint8_t, Pjp, 9, Index);
672 case cJ1_JPIMMED_1_08: CHECKINDEXNATIVE(uint8_t, Pjp, 8, Index);
673 #endif
674 #if (defined(JUDY1) || defined(JU_64BIT))
675 case cJU_JPIMMED_1_07: CHECKINDEXNATIVE(uint8_t, Pjp, 7, Index);
676 case cJU_JPIMMED_1_06: CHECKINDEXNATIVE(uint8_t, Pjp, 6, Index);
677 case cJU_JPIMMED_1_05: CHECKINDEXNATIVE(uint8_t, Pjp, 5, Index);
678 case cJU_JPIMMED_1_04: CHECKINDEXNATIVE(uint8_t, Pjp, 4, Index);
679 #endif
680 case cJU_JPIMMED_1_03: CHECKINDEXNATIVE(uint8_t, Pjp, 3, Index);
681 case cJU_JPIMMED_1_02: CHECKINDEXNATIVE(uint8_t, Pjp, 2, Index);
682 CHECKINDEXNATIVE(uint8_t, Pjp, 1, Index);
683 break;
684
685 #if (defined(JUDY1) && defined(JU_64BIT))
686 case cJ1_JPIMMED_2_07: CHECKINDEXNATIVE(uint16_t, Pjp, 7, Index);
687 case cJ1_JPIMMED_2_06: CHECKINDEXNATIVE(uint16_t, Pjp, 6, Index);
688 case cJ1_JPIMMED_2_05: CHECKINDEXNATIVE(uint16_t, Pjp, 5, Index);
689 case cJ1_JPIMMED_2_04: CHECKINDEXNATIVE(uint16_t, Pjp, 4, Index);
690 #endif
691 #if (defined(JUDY1) || defined(JU_64BIT))
692 case cJU_JPIMMED_2_03: CHECKINDEXNATIVE(uint16_t, Pjp, 3, Index);
693 case cJU_JPIMMED_2_02: CHECKINDEXNATIVE(uint16_t, Pjp, 2, Index);
694 CHECKINDEXNATIVE(uint16_t, Pjp, 1, Index);
695 break;
696 #endif
697
698 #if (defined(JUDY1) && defined(JU_64BIT))
699 case cJ1_JPIMMED_3_05:
700 CHECKLEAFNONNAT(3, Pjp, Index, 5, JU_COPY3_PINDEX_TO_LONG);
701 case cJ1_JPIMMED_3_04:
702 CHECKLEAFNONNAT(3, Pjp, Index, 4, JU_COPY3_PINDEX_TO_LONG);
703 case cJ1_JPIMMED_3_03:
704 CHECKLEAFNONNAT(3, Pjp, Index, 3, JU_COPY3_PINDEX_TO_LONG);
705 #endif
706 #if (defined(JUDY1) || defined(JU_64BIT))
707 case cJU_JPIMMED_3_02:
708 CHECKLEAFNONNAT(3, Pjp, Index, 2, JU_COPY3_PINDEX_TO_LONG);
709 CHECKLEAFNONNAT(3, Pjp, Index, 1, JU_COPY3_PINDEX_TO_LONG);
710 break;
711 #endif
712
713 #if (defined(JUDY1) && defined(JU_64BIT))
714
715 case cJ1_JPIMMED_4_03: CHECKINDEXNATIVE(uint32_t, Pjp, 3, Index);
716 case cJ1_JPIMMED_4_02: CHECKINDEXNATIVE(uint32_t, Pjp, 2, Index);
717 CHECKINDEXNATIVE(uint32_t, Pjp, 1, Index);
718 break;
719
720 case cJ1_JPIMMED_5_03:
721 CHECKLEAFNONNAT(5, Pjp, Index, 3, JU_COPY5_PINDEX_TO_LONG);
722 case cJ1_JPIMMED_5_02:
723 CHECKLEAFNONNAT(5, Pjp, Index, 2, JU_COPY5_PINDEX_TO_LONG);
724 CHECKLEAFNONNAT(5, Pjp, Index, 1, JU_COPY5_PINDEX_TO_LONG);
725 break;
726
727 case cJ1_JPIMMED_6_02:
728 CHECKLEAFNONNAT(6, Pjp, Index, 2, JU_COPY6_PINDEX_TO_LONG);
729 CHECKLEAFNONNAT(6, Pjp, Index, 1, JU_COPY6_PINDEX_TO_LONG);
730 break;
731
732 case cJ1_JPIMMED_7_02:
733 CHECKLEAFNONNAT(7, Pjp, Index, 2, JU_COPY7_PINDEX_TO_LONG);
734 CHECKLEAFNONNAT(7, Pjp, Index, 1, JU_COPY7_PINDEX_TO_LONG);
735 break;
736
737 #endif // (JUDY1 && JU_64BIT)
738
739
740 // ****************************************************************************
741 // INVALID JP TYPE:
742
743 default:
744
745 ReturnCorrupt:
746
747 #ifdef JUDYGETINLINE // Pjpm is known to be non-null:
748 JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
749 #else
750 JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
751 #endif
752 JUDY1CODE(return(JERRI );)
753 JUDYLCODE(return(PPJERR);)
754
755 } // switch on JP type
756
757 JUDY1CODE(return(0);)
758 JUDYLCODE(return((PPvoid_t) NULL);)
759
760 } // Judy1Test() / JudyLGet()
761
762
763 #ifndef JUDYGETINLINE // only compile the following function once:
764 #ifdef DEBUG
765
766 // ****************************************************************************
767 // J U D Y C H E C K P O P
768 //
769 // Given a pointer to a Judy array, traverse the entire array to ensure
770 // population counts add up correctly. This can catch various coding errors.
771 //
772 // Since walking the entire tree is probably time-consuming, enable this
773 // function by setting env parameter $CHECKPOP to first call at which to start
774 // checking. Note: This function is called both from insert and delete code.
775 //
776 // Note: Even though this function does nothing useful for LEAFW leaves, its
777 // good practice to call it anyway, and cheap too.
778 //
779 // TBD: This is a debug-only check function similar to JudyCheckSorted(), but
780 // since it walks the tree it is Judy1/JudyL-specific and must live in a source
781 // file that is built both ways.
782 //
783 // TBD: As feared, enabling this code for every insert/delete makes Judy
784 // deathly slow, even for a small tree (10K indexes). Its not so bad if
785 // present but disabled (<1% slowdown measured). Still, should it be ifdefd
786 // other than DEBUG and/or called less often?
787 //
788 // TBD: Should this "population checker" be expanded to a comprehensive tree
789 // checker? It currently detects invalid LEAFW/JP types as well as inconsistent
790 // pop1s. Other possible checks, all based on essentially redundant data in
791 // the Judy tree, include:
792 //
793 // - Zero LS bits in jp_Addr field.
794 //
795 // - Correct Dcd bits.
796 //
797 // - Consistent JP types (always descending down the tree).
798 //
799 // - Sorted linear lists in BranchLs and leaves (using JudyCheckSorted(), but
800 // ideally that function is already called wherever appropriate after any
801 // linear list is modified).
802 //
803 // - Any others possible?
804
805 #include <stdlib.h> // for getenv() and atol().
806
807 static Word_t JudyCheckPopSM(Pjp_t Pjp, Word_t RootPop1);
808
809 FUNCTION void JudyCheckPop(
810 Pvoid_t PArray)
811 {
812 static bool_t checked = FALSE; // already checked env parameter.
813 static bool_t enabled = FALSE; // env parameter set.
814 static bool_t active = FALSE; // calls >= callsmin.
815 static Word_t callsmin; // start point from $CHECKPOP.
816 static Word_t calls = 0; // times called so far.
817
818
819 // CHECK FOR EXTERNAL ENABLING:
820
821 if (! checked) // only check once.
822 {
823 char * value; // for getenv().
824
825 checked = TRUE;
826
827 if ((value = getenv("CHECKPOP")) == (char *) NULL)
828 {
829 #ifdef notdef
830 // Take this out because nightly tests want to be flavor-independent; its not
831 // OK to emit special non-error output from the debug flavor:
832
833 (void) puts("JudyCheckPop() present but not enabled by "
834 "$CHECKPOP env parameter; set it to the number of "
835 "calls at which to begin checking");
836 #endif
837 return;
838 }
839
840 callsmin = atol(value); // note: non-number evaluates to 0.
841 enabled = TRUE;
842
843 (void) printf("JudyCheckPop() present and enabled; callsmin = "
844 "%lu\n", callsmin);
845 }
846 else if (! enabled) return;
847
848 // Previously or just now enabled; check if non-active or newly active:
849
850 if (! active)
851 {
852 if (++calls < callsmin) return;
853
854 (void) printf("JudyCheckPop() activated at call %lu\n", calls);
855 active = TRUE;
856 }
857
858 // IGNORE LEAFW AT TOP OF TREE:
859
860 if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
861 return;
862
863 // Check JPM pop0 against tree, recursively:
864 //
865 // Note: The traversal code in JudyCheckPopSM() is simplest when the case
866 // statement for each JP type compares the pop1 for that JP to its subtree (if
867 // any) after traversing the subtree (thats the hard part) and adding up
868 // actual pop1s. A top branchs JP in the JPM does not have room for a
869 // full-word pop1, so pass it in as a special case.
870
871 {
872 Pjpm_t Pjpm = P_JPM(PArray);
873 (void) JudyCheckPopSM(&(Pjpm->jpm_JP), Pjpm->jpm_Pop0 + 1);
874 return;
875 }
876
877 } // JudyCheckPop()
878
879
880 // ****************************************************************************
881 // J U D Y C H E C K P O P S M
882 //
883 // Recursive state machine (subroutine) for JudyCheckPop(): Given a Pjp (other
884 // than JPNULL*; caller should shortcut) and the root population for top-level
885 // branches, check the subtrees actual pop1 against its nominal value, and
886 // return the total pop1 for the subtree.
887 //
888 // Note: Expect RootPop1 to be ignored at lower levels, so pass down 0, which
889 // should pop an assertion if this expectation is violated.
890
891 FUNCTION static Word_t JudyCheckPopSM(
892 Pjp_t Pjp, // top of subtree.
893 Word_t RootPop1) // whole array, for top-level branches only.
894 {
895 Word_t pop1_jp; // nominal population from the JP.
896 Word_t pop1 = 0; // actual population at this level.
897 Word_t offset; // in a branch.
898
899 #define PREPBRANCH(cPopBytes,Next) \
900 pop1_jp = JU_JPBRANCH_POP0(Pjp, cPopBytes) + 1; goto Next
901
902 assert((((Word_t) (Pjp->jp_Addr)) & 7) == 3);
903 switch (JU_JPTYPE(Pjp))
904 {
905
906 case cJU_JPBRANCH_L2: PREPBRANCH(2, BranchL);
907 case cJU_JPBRANCH_L3: PREPBRANCH(3, BranchL);
908 #ifdef JU_64BIT
909 case cJU_JPBRANCH_L4: PREPBRANCH(4, BranchL);
910 case cJU_JPBRANCH_L5: PREPBRANCH(5, BranchL);
911 case cJU_JPBRANCH_L6: PREPBRANCH(6, BranchL);
912 case cJU_JPBRANCH_L7: PREPBRANCH(7, BranchL);
913 #endif
914 case cJU_JPBRANCH_L: pop1_jp = RootPop1;
915 {
916 Pjbl_t Pjbl;
917 BranchL:
918 Pjbl = P_JBL(Pjp->jp_Addr);
919
920 for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
921 pop1 += JudyCheckPopSM((Pjbl->jbl_jp) + offset, 0);
922
923 assert(pop1_jp == pop1);
924 return(pop1);
925 }
926
927 case cJU_JPBRANCH_B2: PREPBRANCH(2, BranchB);
928 case cJU_JPBRANCH_B3: PREPBRANCH(3, BranchB);
929 #ifdef JU_64BIT
930 case cJU_JPBRANCH_B4: PREPBRANCH(4, BranchB);
931 case cJU_JPBRANCH_B5: PREPBRANCH(5, BranchB);
932 case cJU_JPBRANCH_B6: PREPBRANCH(6, BranchB);
933 case cJU_JPBRANCH_B7: PREPBRANCH(7, BranchB);
934 #endif
935 case cJU_JPBRANCH_B: pop1_jp = RootPop1;
936 {
937 Word_t subexp;
938 Word_t jpcount;
939 Pjbb_t Pjbb;
940 BranchB:
941 Pjbb = P_JBB(Pjp->jp_Addr);
942
943 for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
944 {
945 jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
946
947 for (offset = 0; offset < jpcount; ++offset)
948 {
949 pop1 += JudyCheckPopSM(P_JP(JU_JBB_PJP(Pjbb, subexp))
950 + offset, 0);
951 }
952 }
953
954 assert(pop1_jp == pop1);
955 return(pop1);
956 }
957
958 case cJU_JPBRANCH_U2: PREPBRANCH(2, BranchU);
959 case cJU_JPBRANCH_U3: PREPBRANCH(3, BranchU);
960 #ifdef JU_64BIT
961 case cJU_JPBRANCH_U4: PREPBRANCH(4, BranchU);
962 case cJU_JPBRANCH_U5: PREPBRANCH(5, BranchU);
963 case cJU_JPBRANCH_U6: PREPBRANCH(6, BranchU);
964 case cJU_JPBRANCH_U7: PREPBRANCH(7, BranchU);
965 #endif
966 case cJU_JPBRANCH_U: pop1_jp = RootPop1;
967 {
968 Pjbu_t Pjbu;
969 BranchU:
970 Pjbu = P_JBU(Pjp->jp_Addr);
971
972 for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
973 {
974 if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
975 && ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
976 {
977 continue; // skip null JP to save time.
978 }
979
980 pop1 += JudyCheckPopSM((Pjbu->jbu_jp) + offset, 0);
981 }
982
983 assert(pop1_jp == pop1);
984 return(pop1);
985 }
986
987
988 // -- Cases below here terminate and do not recurse. --
989 //
990 // For all of these cases except JPLEAF_B1, there is no way to check the JPs
991 // pop1 against the object itself; just return the pop1; but for linear leaves,
992 // a bounds check is possible.
993
994 #define CHECKLEAF(MaxPop1) \
995 pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
996 assert(pop1 >= 1); \
997 assert(pop1 <= (MaxPop1)); \
998 return(pop1)
999
1000 #if (defined(JUDYL) || (! defined(JU_64BIT)))
1001 case cJU_JPLEAF1: CHECKLEAF(cJU_LEAF1_MAXPOP1);
1002 #endif
1003 case cJU_JPLEAF2: CHECKLEAF(cJU_LEAF2_MAXPOP1);
1004 case cJU_JPLEAF3: CHECKLEAF(cJU_LEAF3_MAXPOP1);
1005 #ifdef JU_64BIT
1006 case cJU_JPLEAF4: CHECKLEAF(cJU_LEAF4_MAXPOP1);
1007 case cJU_JPLEAF5: CHECKLEAF(cJU_LEAF5_MAXPOP1);
1008 case cJU_JPLEAF6: CHECKLEAF(cJU_LEAF6_MAXPOP1);
1009 case cJU_JPLEAF7: CHECKLEAF(cJU_LEAF7_MAXPOP1);
1010 #endif
1011
1012 case cJU_JPLEAF_B1:
1013 {
1014 Word_t subexp;
1015 Pjlb_t Pjlb;
1016
1017 pop1_jp = JU_JPLEAF_POP0(Pjp) + 1;
1018
1019 Pjlb = P_JLB(Pjp->jp_Addr);
1020
1021 for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
1022 pop1 += j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
1023
1024 assert(pop1_jp == pop1);
1025 return(pop1);
1026 }
1027
1028 JUDY1CODE(case cJ1_JPFULLPOPU1: return(cJU_JPFULLPOPU1_POP0);)
1029
1030 case cJU_JPIMMED_1_01: return(1);
1031 case cJU_JPIMMED_2_01: return(1);
1032 case cJU_JPIMMED_3_01: return(1);
1033 #ifdef JU_64BIT
1034 case cJU_JPIMMED_4_01: return(1);
1035 case cJU_JPIMMED_5_01: return(1);
1036 case cJU_JPIMMED_6_01: return(1);
1037 case cJU_JPIMMED_7_01: return(1);
1038 #endif
1039
1040 case cJU_JPIMMED_1_02: return(2);
1041 case cJU_JPIMMED_1_03: return(3);
1042 #if (defined(JUDY1) || defined(JU_64BIT))
1043 case cJU_JPIMMED_1_04: return(4);
1044 case cJU_JPIMMED_1_05: return(5);
1045 case cJU_JPIMMED_1_06: return(6);
1046 case cJU_JPIMMED_1_07: return(7);
1047 #endif
1048 #if (defined(JUDY1) && defined(JU_64BIT))
1049 case cJ1_JPIMMED_1_08: return(8);
1050 case cJ1_JPIMMED_1_09: return(9);
1051 case cJ1_JPIMMED_1_10: return(10);
1052 case cJ1_JPIMMED_1_11: return(11);
1053 case cJ1_JPIMMED_1_12: return(12);
1054 case cJ1_JPIMMED_1_13: return(13);
1055 case cJ1_JPIMMED_1_14: return(14);
1056 case cJ1_JPIMMED_1_15: return(15);
1057 #endif
1058
1059 #if (defined(JUDY1) || defined(JU_64BIT))
1060 case cJU_JPIMMED_2_02: return(2);
1061 case cJU_JPIMMED_2_03: return(3);
1062 #endif
1063 #if (defined(JUDY1) && defined(JU_64BIT))
1064 case cJ1_JPIMMED_2_04: return(4);
1065 case cJ1_JPIMMED_2_05: return(5);
1066 case cJ1_JPIMMED_2_06: return(6);
1067 case cJ1_JPIMMED_2_07: return(7);
1068 #endif
1069
1070 #if (defined(JUDY1) || defined(JU_64BIT))
1071 case cJU_JPIMMED_3_02: return(2);
1072 #endif
1073 #if (defined(JUDY1) && defined(JU_64BIT))
1074 case cJ1_JPIMMED_3_03: return(3);
1075 case cJ1_JPIMMED_3_04: return(4);
1076 case cJ1_JPIMMED_3_05: return(5);
1077
1078 case cJ1_JPIMMED_4_02: return(2);
1079 case cJ1_JPIMMED_4_03: return(3);
1080 case cJ1_JPIMMED_5_02: return(2);
1081 case cJ1_JPIMMED_5_03: return(3);
1082 case cJ1_JPIMMED_6_02: return(2);
1083 case cJ1_JPIMMED_7_02: return(2);
1084 #endif
1085
1086 } // switch (JU_JPTYPE(Pjp))
1087
1088 assert(FALSE); // unrecognized JP type => corruption.
1089 return(0); // to make some compilers happy.
1090
1091 } // JudyCheckPopSM()
1092
1093 #endif // DEBUG
1094 #endif // ! JUDYGETINLINE