1
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
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.
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
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
18
// @(#) $Revision: 4.43 $ $Source: /judy/src/JudyCommon/JudyGet.c $
20
// Judy1Test() and JudyLGet() functions for Judy1 and JudyL.
21
// Compile with one of -DJUDY1 or -DJUDYL.
23
#if (! (defined(JUDY1) || defined(JUDYL)))
24
#error: One of -DJUDY1 or -DJUDYL must be specified.
33
#include "JudyPrivate1L.h"
35
#ifdef TRACEJPR // different macro name, for "retrieval" only.
36
#include "JudyPrintJP.c"
40
// ****************************************************************************
44
// See the manual entry for details. Note support for "shortcut" entries to
45
// trees known to start with a JPM.
50
FUNCTION int j__udy1Test
52
FUNCTION int Judy1Test
58
FUNCTION PPvoid_t j__udyLGet
60
FUNCTION PPvoid_t JudyLGet
66
Pvoid_t PArray, // from which to retrieve.
67
Word_t Index // to retrieve.
69
Pcvoid_t PArray, // from which to retrieve.
70
Word_t Index, // to retrieve.
71
PJError_t PJError // optional, for returning error info.
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;)
84
if (PArray == (Pcvoid_t) NULL) // empty array.
87
JUDYLCODE(return((PPvoid_t) NULL);)
90
// ****************************************************************************
91
// PROCESS TOP LEVEL BRANCHES AND LEAF:
93
if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
95
Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
96
int posidx; // signed offset in leaf.
99
posidx = j__udySearchLeafW(Pjlw + 1, Pop1, Index);
103
JUDY1CODE(return(1);)
104
JUDYLCODE(return((PPvoid_t) (JL_LEAFWVALUEAREA(Pjlw, Pop1) + posidx));)
106
JUDY1CODE(return(0);)
107
JUDYLCODE(return((PPvoid_t) NULL);)
110
#endif // ! JUDYGETINLINE
112
Pjpm = P_JPM(PArray);
113
Pjp = &(Pjpm->jpm_JP); // top branch is below JPM.
115
// ****************************************************************************
116
// WALK THE JUDY TREE USING A STATE MACHINE:
118
ContinueWalk: // for going down one level; come here with Pjp set.
121
JudyPrintJP(Pjp, "g", __LINE__);
123
switch (JU_JPTYPE(Pjp))
126
// Ensure the switch table starts at 0 for speed; otherwise more code is
129
case 0: goto ReturnCorrupt; // save a little code.
132
// ****************************************************************************
135
// Note: These are legitimate in a BranchU (only) and do not constitute a
147
assert(ParentJPType >= cJU_JPBRANCH_U2);
148
assert(ParentJPType <= cJU_JPBRANCH_U);
149
JUDY1CODE(return(0);)
150
JUDYLCODE(return((PPvoid_t) NULL);)
153
// ****************************************************************************
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.
160
case cJU_JPBRANCH_L2:
162
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
163
Digit = JU_DIGITATSTATE(Index, 2);
166
case cJU_JPBRANCH_L3:
168
#ifdef JU_64BIT // otherwise its a no-op:
169
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
171
Digit = JU_DIGITATSTATE(Index, 3);
175
case cJU_JPBRANCH_L4:
177
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
178
Digit = JU_DIGITATSTATE(Index, 4);
181
case cJU_JPBRANCH_L5:
183
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
184
Digit = JU_DIGITATSTATE(Index, 5);
187
case cJU_JPBRANCH_L6:
189
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
190
Digit = JU_DIGITATSTATE(Index, 6);
193
case cJU_JPBRANCH_L7:
195
// JU_DCDNOTMATCHINDEX() would be a no-op.
196
Digit = JU_DIGITATSTATE(Index, 7);
206
Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
208
// Common code for all BranchLs; come here with Digit set:
211
Pjbl = P_JBL(Pjp->jp_Addr);
216
if (Pjbl->jbl_Expanse[posidx] == Digit)
217
{ // found Digit; continue traversal:
218
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
219
Pjp = Pjbl->jbl_jp + posidx;
222
} while (++posidx != Pjbl->jbl_NumJPs);
228
// ****************************************************************************
231
case cJU_JPBRANCH_B2:
233
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
234
Digit = JU_DIGITATSTATE(Index, 2);
237
case cJU_JPBRANCH_B3:
239
#ifdef JU_64BIT // otherwise its a no-op:
240
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
242
Digit = JU_DIGITATSTATE(Index, 3);
247
case cJU_JPBRANCH_B4:
249
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
250
Digit = JU_DIGITATSTATE(Index, 4);
253
case cJU_JPBRANCH_B5:
255
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
256
Digit = JU_DIGITATSTATE(Index, 5);
259
case cJU_JPBRANCH_B6:
261
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
262
Digit = JU_DIGITATSTATE(Index, 6);
265
case cJU_JPBRANCH_B7:
267
// JU_DCDNOTMATCHINDEX() would be a no-op.
268
Digit = JU_DIGITATSTATE(Index, 7);
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.
280
Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
282
// Common code for all BranchBs; come here with Digit set:
285
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
286
Pjbb = P_JBB(Pjp->jp_Addr);
287
subexp = Digit / cJU_BITSPERSUBEXPB;
289
BitMap = JU_JBB_BITMAP(Pjbb, subexp);
290
Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp));
292
BitMask = JU_BITPOSMASKB(Digit);
294
// No JP in subexpanse for Index => Index not found:
296
if (! (BitMap & BitMask)) break;
298
// Count JPs in the subexpanse below the one for Index:
300
Pjp += j__udyCountBitsB(BitMap & (BitMask - 1));
304
} // case cJU_JPBRANCH_B*
307
// ****************************************************************************
310
// Notice the reverse order of the cases, and falling through to the next case,
315
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
316
Pjp = JU_JBU_PJP(Pjp, Index, cJU_ROOTSTATE);
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:
323
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
325
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U7) goto ContinueWalk;
329
case cJU_JPBRANCH_U7:
331
// JU_DCDNOTMATCHINDEX() would be a no-op.
332
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
333
Pjp = JU_JBU_PJP(Pjp, Index, 7);
335
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U6) goto ContinueWalk;
338
case cJU_JPBRANCH_U6:
340
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
341
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
342
Pjp = JU_JBU_PJP(Pjp, Index, 6);
344
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U5) goto ContinueWalk;
347
case cJU_JPBRANCH_U5:
349
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
350
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
351
Pjp = JU_JBU_PJP(Pjp, Index, 5);
353
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U4) goto ContinueWalk;
356
case cJU_JPBRANCH_U4:
358
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
359
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
360
Pjp = JU_JBU_PJP(Pjp, Index, 4);
362
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
367
case cJU_JPBRANCH_U3:
369
#ifdef JU_64BIT // otherwise its a no-op:
370
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
372
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
373
Pjp = JU_JBU_PJP(Pjp, Index, 3);
375
if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U2) goto ContinueWalk;
378
case cJU_JPBRANCH_U2:
380
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
381
DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
382
Pjp = JU_JBU_PJP(Pjp, Index, 2);
384
// Note: BranchU2 is a special case that must continue traversal to a leaf,
385
// immed, full, or null type:
390
// ****************************************************************************
393
// Note: Here the calls of JU_DCDNOTMATCHINDEX() are necessary and check
394
// whether Index is out of the expanse of a narrow pointer.
396
#if (defined(JUDYL) || (! defined(JU_64BIT)))
400
int posidx; // signed offset in leaf.
402
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
404
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
405
Pjll = P_JLL(Pjp->jp_Addr);
407
if ((posidx = j__udySearchLeaf1(Pjll, Pop1, Index)) < 0) break;
409
JUDY1CODE(return(1);)
410
JUDYLCODE(return((PPvoid_t) (JL_LEAF1VALUEAREA(Pjll, Pop1) + posidx));)
413
#endif // (JUDYL || (! JU_64BIT))
417
int posidx; // signed offset in leaf.
419
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
421
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
422
Pjll = P_JLL(Pjp->jp_Addr);
424
if ((posidx = j__udySearchLeaf2(Pjll, Pop1, Index)) < 0) break;
426
JUDY1CODE(return(1);)
427
JUDYLCODE(return((PPvoid_t) (JL_LEAF2VALUEAREA(Pjll, Pop1) + posidx));)
431
int posidx; // signed offset in leaf.
433
#ifdef JU_64BIT // otherwise its a no-op:
434
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
437
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
438
Pjll = P_JLL(Pjp->jp_Addr);
440
if ((posidx = j__udySearchLeaf3(Pjll, Pop1, Index)) < 0) break;
442
JUDY1CODE(return(1);)
443
JUDYLCODE(return((PPvoid_t) (JL_LEAF3VALUEAREA(Pjll, Pop1) + posidx));)
448
int posidx; // signed offset in leaf.
450
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
452
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
453
Pjll = P_JLL(Pjp->jp_Addr);
455
if ((posidx = j__udySearchLeaf4(Pjll, Pop1, Index)) < 0) break;
457
JUDY1CODE(return(1);)
458
JUDYLCODE(return((PPvoid_t) (JL_LEAF4VALUEAREA(Pjll, Pop1) + posidx));)
462
int posidx; // signed offset in leaf.
464
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
466
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
467
Pjll = P_JLL(Pjp->jp_Addr);
469
if ((posidx = j__udySearchLeaf5(Pjll, Pop1, Index)) < 0) break;
471
JUDY1CODE(return(1);)
472
JUDYLCODE(return((PPvoid_t) (JL_LEAF5VALUEAREA(Pjll, Pop1) + posidx));)
477
int posidx; // signed offset in leaf.
479
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
481
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
482
Pjll = P_JLL(Pjp->jp_Addr);
484
if ((posidx = j__udySearchLeaf6(Pjll, Pop1, Index)) < 0) break;
486
JUDY1CODE(return(1);)
487
JUDYLCODE(return((PPvoid_t) (JL_LEAF6VALUEAREA(Pjll, Pop1) + posidx));)
491
int posidx; // signed offset in leaf.
493
// JU_DCDNOTMATCHINDEX() would be a no-op.
494
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
495
Pjll = P_JLL(Pjp->jp_Addr);
497
if ((posidx = j__udySearchLeaf7(Pjll, Pop1, Index)) < 0) break;
499
JUDY1CODE(return(1);)
500
JUDYLCODE(return((PPvoid_t) (JL_LEAF7VALUEAREA(Pjll, Pop1) + posidx));)
505
// ****************************************************************************
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.
518
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
520
Pjlb = P_JLB(Pjp->jp_Addr);
524
// Simply check if Indexs bit is set in the bitmap:
526
if (JU_BITMAPTESTL(Pjlb, Index)) return(1);
531
// JudyL is much more complicated because of value area subarrays:
533
Digit = JU_DIGITATSTATE(Index, 1);
534
subexp = Digit / cJU_BITSPERSUBEXPL;
535
BitMap = JU_JLB_BITMAP(Pjlb, subexp);
536
BitMask = JU_BITPOSMASKL(Digit);
538
// No value in subexpanse for Index => Index not found:
540
if (! (BitMap & BitMask)) break;
542
// Count value areas in the subexpanse below the one for Index:
544
Pjv = P_JV(JL_JLB_PVALUE(Pjlb, subexp));
545
assert(Pjv != (Pjv_t) NULL);
546
posidx = j__udyCountBitsL(BitMap & (BitMask - 1));
548
return((PPvoid_t) (Pjv + posidx));
552
} // case cJU_JPLEAF_B1
556
// ****************************************************************************
559
// If the Index is in the expanse, it is necessarily valid (found).
561
case cJ1_JPFULLPOPU1:
563
if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
566
#ifdef notdef // for future enhancements
569
// Note: Need ? if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
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;
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;
603
return(1); // found, not in exclusion list
608
// ****************************************************************************
611
// Note that the contents of jp_DcdPopO are different for cJU_JPIMMED_*_01:
613
case cJU_JPIMMED_1_01:
614
case cJU_JPIMMED_2_01:
615
case cJU_JPIMMED_3_01:
617
case cJU_JPIMMED_4_01:
618
case cJU_JPIMMED_5_01:
619
case cJU_JPIMMED_6_01:
620
case cJU_JPIMMED_7_01:
622
if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) break;
624
JUDY1CODE(return(1);)
625
JUDYLCODE(return((PPvoid_t) &(Pjp->jp_Addr));) // immediate value area.
628
// Macros to make code more readable and avoid dup errors
632
#define CHECKINDEXNATIVE(LEAF_T, PJP, IDX, INDEX) \
633
if (((LEAF_T *)((PJP)->jp_1Index))[(IDX) - 1] == (LEAF_T)(INDEX)) \
636
#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
640
a_ddr = (PJP)->jp_1Index + (((IDX) - 1) * (LFBTS)); \
641
COPY(i_ndex, a_ddr); \
642
if (i_ndex == JU_LEASTBYTES((INDEX), (LFBTS))) \
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))
653
#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
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)); \
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);
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);
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);
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);
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);
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);
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);
713
#if (defined(JUDY1) && defined(JU_64BIT))
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);
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);
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);
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);
737
#endif // (JUDY1 && JU_64BIT)
740
// ****************************************************************************
747
#ifdef JUDYGETINLINE // Pjpm is known to be non-null:
748
JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
750
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
752
JUDY1CODE(return(JERRI );)
753
JUDYLCODE(return(PPJERR);)
755
} // switch on JP type
757
JUDY1CODE(return(0);)
758
JUDYLCODE(return((PPvoid_t) NULL);)
760
} // Judy1Test() / JudyLGet()
763
#ifndef JUDYGETINLINE // only compile the following function once:
766
// ****************************************************************************
767
// J U D Y C H E C K P O P
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.
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.
776
// Note: Even though this function does nothing useful for LEAFW leaves, its
777
// good practice to call it anyway, and cheap too.
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.
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?
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:
793
// - Zero LS bits in jp_Addr field.
795
// - Correct Dcd bits.
797
// - Consistent JP types (always descending down the tree).
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).
803
// - Any others possible?
805
#include <stdlib.h> // for getenv() and atol().
807
static Word_t JudyCheckPopSM(Pjp_t Pjp, Word_t RootPop1);
809
FUNCTION void JudyCheckPop(
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.
819
// CHECK FOR EXTERNAL ENABLING:
821
if (! checked) // only check once.
823
char * value; // for getenv().
827
if ((value = getenv("CHECKPOP")) == (char *) NULL)
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:
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");
840
callsmin = atol(value); // note: non-number evaluates to 0.
843
(void) printf("JudyCheckPop() present and enabled; callsmin = "
846
else if (! enabled) return;
848
// Previously or just now enabled; check if non-active or newly active:
852
if (++calls < callsmin) return;
854
(void) printf("JudyCheckPop() activated at call %lu\n", calls);
858
// IGNORE LEAFW AT TOP OF TREE:
860
if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
863
// Check JPM pop0 against tree, recursively:
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.
872
Pjpm_t Pjpm = P_JPM(PArray);
873
(void) JudyCheckPopSM(&(Pjpm->jpm_JP), Pjpm->jpm_Pop0 + 1);
880
// ****************************************************************************
881
// J U D Y C H E C K P O P S M
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.
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.
891
FUNCTION static Word_t JudyCheckPopSM(
892
Pjp_t Pjp, // top of subtree.
893
Word_t RootPop1) // whole array, for top-level branches only.
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.
899
#define PREPBRANCH(cPopBytes,Next) \
900
pop1_jp = JU_JPBRANCH_POP0(Pjp, cPopBytes) + 1; goto Next
902
assert((((Word_t) (Pjp->jp_Addr)) & 7) == 3);
903
switch (JU_JPTYPE(Pjp))
906
case cJU_JPBRANCH_L2: PREPBRANCH(2, BranchL);
907
case cJU_JPBRANCH_L3: PREPBRANCH(3, BranchL);
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);
914
case cJU_JPBRANCH_L: pop1_jp = RootPop1;
918
Pjbl = P_JBL(Pjp->jp_Addr);
920
for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
921
pop1 += JudyCheckPopSM((Pjbl->jbl_jp) + offset, 0);
923
assert(pop1_jp == pop1);
927
case cJU_JPBRANCH_B2: PREPBRANCH(2, BranchB);
928
case cJU_JPBRANCH_B3: PREPBRANCH(3, BranchB);
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);
935
case cJU_JPBRANCH_B: pop1_jp = RootPop1;
941
Pjbb = P_JBB(Pjp->jp_Addr);
943
for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
945
jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
947
for (offset = 0; offset < jpcount; ++offset)
949
pop1 += JudyCheckPopSM(P_JP(JU_JBB_PJP(Pjbb, subexp))
954
assert(pop1_jp == pop1);
958
case cJU_JPBRANCH_U2: PREPBRANCH(2, BranchU);
959
case cJU_JPBRANCH_U3: PREPBRANCH(3, BranchU);
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);
966
case cJU_JPBRANCH_U: pop1_jp = RootPop1;
970
Pjbu = P_JBU(Pjp->jp_Addr);
972
for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
974
if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
975
&& ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
977
continue; // skip null JP to save time.
980
pop1 += JudyCheckPopSM((Pjbu->jbu_jp) + offset, 0);
983
assert(pop1_jp == pop1);
988
// -- Cases below here terminate and do not recurse. --
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.
994
#define CHECKLEAF(MaxPop1) \
995
pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
997
assert(pop1 <= (MaxPop1)); \
1000
#if (defined(JUDYL) || (! defined(JU_64BIT)))
1001
case cJU_JPLEAF1: CHECKLEAF(cJU_LEAF1_MAXPOP1);
1003
case cJU_JPLEAF2: CHECKLEAF(cJU_LEAF2_MAXPOP1);
1004
case cJU_JPLEAF3: CHECKLEAF(cJU_LEAF3_MAXPOP1);
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);
1017
pop1_jp = JU_JPLEAF_POP0(Pjp) + 1;
1019
Pjlb = P_JLB(Pjp->jp_Addr);
1021
for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
1022
pop1 += j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
1024
assert(pop1_jp == pop1);
1028
JUDY1CODE(case cJ1_JPFULLPOPU1: return(cJU_JPFULLPOPU1_POP0);)
1030
case cJU_JPIMMED_1_01: return(1);
1031
case cJU_JPIMMED_2_01: return(1);
1032
case cJU_JPIMMED_3_01: return(1);
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);
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);
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);
1059
#if (defined(JUDY1) || defined(JU_64BIT))
1060
case cJU_JPIMMED_2_02: return(2);
1061
case cJU_JPIMMED_2_03: return(3);
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);
1070
#if (defined(JUDY1) || defined(JU_64BIT))
1071
case cJU_JPIMMED_3_02: return(2);
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);
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);
1086
} // switch (JU_JPTYPE(Pjp))
1088
assert(FALSE); // unrecognized JP type => corruption.
1089
return(0); // to make some compilers happy.
1091
} // JudyCheckPopSM()
1094
#endif // ! JUDYGETINLINE