1943 lines
55 KiB
C

// Copyright (C) 2000 - 2002 Hewlett-Packard Company
//
// This program is free software; you can redistribute it and/or modify it
// under the term of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
// for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// _________________
// @(#) $Revision$ $Source$
#ifdef JUDY1
#include "Judy1.h"
#else
#include "JudyL.h"
#endif
#include "JudyPrivate1L.h"
extern int j__udyCreateBranchL(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
extern int j__udyCreateBranchB(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)
static const jbb_t StageJBBZero; // zeroed versions of namesake struct.
// TBD: There are multiple copies of (some of) these CopyWto3, Copy3toW,
// CopyWto7 and Copy7toW functions in Judy1Cascade.c, JudyLCascade.c, and
// JudyDecascade.c. These static functions should probably be moved to a
// common place, made macros, or something to avoid having four copies.
// ****************************************************************************
// __ J U D Y C O P Y X T O W
FUNCTION static void j__udyCopy3toW(
PWord_t PDest,
uint8_t * PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY3_PINDEX_TO_LONG(*PDest, PSrc);
PSrc += 3;
PDest += 1;
} while(--LeafIndexes);
} //j__udyCopy3toW()
#ifdef JU_64BIT
FUNCTION static void j__udyCopy4toW(
PWord_t PDest,
uint32_t * PSrc,
Word_t LeafIndexes)
{
do { *PDest++ = *PSrc++;
} while(--LeafIndexes);
} // j__udyCopy4toW()
FUNCTION static void j__udyCopy5toW(
PWord_t PDest,
uint8_t * PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY5_PINDEX_TO_LONG(*PDest, PSrc);
PSrc += 5;
PDest += 1;
} while(--LeafIndexes);
} // j__udyCopy5toW()
FUNCTION static void j__udyCopy6toW(
PWord_t PDest,
uint8_t * PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY6_PINDEX_TO_LONG(*PDest, PSrc);
PSrc += 6;
PDest += 1;
} while(--LeafIndexes);
} // j__udyCopy6toW()
FUNCTION static void j__udyCopy7toW(
PWord_t PDest,
uint8_t * PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY7_PINDEX_TO_LONG(*PDest, PSrc);
PSrc += 7;
PDest += 1;
} while(--LeafIndexes);
} // j__udyCopy7toW()
#endif // JU_64BIT
// ****************************************************************************
// __ J U D Y C O P Y W T O X
FUNCTION static void j__udyCopyWto3(
uint8_t * PDest,
PWord_t PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY3_LONG_TO_PINDEX(PDest, *PSrc);
PSrc += 1;
PDest += 3;
} while(--LeafIndexes);
} // j__udyCopyWto3()
#ifdef JU_64BIT
FUNCTION static void j__udyCopyWto4(
uint8_t * PDest,
PWord_t PSrc,
Word_t LeafIndexes)
{
uint32_t *PDest32 = (uint32_t *)PDest;
do
{
*PDest32 = *PSrc;
PSrc += 1;
PDest32 += 1;
} while(--LeafIndexes);
} // j__udyCopyWto4()
FUNCTION static void j__udyCopyWto5(
uint8_t * PDest,
PWord_t PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY5_LONG_TO_PINDEX(PDest, *PSrc);
PSrc += 1;
PDest += 5;
} while(--LeafIndexes);
} // j__udyCopyWto5()
FUNCTION static void j__udyCopyWto6(
uint8_t * PDest,
PWord_t PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY6_LONG_TO_PINDEX(PDest, *PSrc);
PSrc += 1;
PDest += 6;
} while(--LeafIndexes);
} // j__udyCopyWto6()
FUNCTION static void j__udyCopyWto7(
uint8_t * PDest,
PWord_t PSrc,
Word_t LeafIndexes)
{
do
{
JU_COPY7_LONG_TO_PINDEX(PDest, *PSrc);
PSrc += 1;
PDest += 7;
} while(--LeafIndexes);
} // j__udyCopyWto7()
#endif // JU_64BIT
// ****************************************************************************
// COMMON CODE (MACROS):
//
// Free objects in an array of valid JPs, StageJP[ExpCnt] == last one may
// include Immeds, which are ignored.
#define FREEALLEXIT(ExpCnt,StageJP,Pjpm) \
{ \
Word_t _expct = (ExpCnt); \
while (_expct--) j__udyFreeSM(&((StageJP)[_expct]), Pjpm); \
return(-1); \
}
// Clear the array that keeps track of the number of JPs in a subexpanse:
#define ZEROJP(SubJPCount) \
{ \
int ii; \
for (ii = 0; ii < cJU_NUMSUBEXPB; ii++) (SubJPCount[ii]) = 0; \
}
// ****************************************************************************
// __ J U D Y S T A G E J B B T O J B B
//
// Create a mallocd BranchB (jbb_t) from a staged BranchB while "splaying" a
// single old leaf. Return -1 if out of memory, otherwise 1.
static int j__udyStageJBBtoJBB(
Pjp_t PjpLeaf, // JP of leaf being splayed.
Pjbb_t PStageJBB, // temp jbb_t on stack.
Pjp_t PjpArray, // array of JPs to splayed new leaves.
uint8_t * PSubCount, // count of JPs for each subexpanse.
Pjpm_t Pjpm) // the jpm_t for JudyAlloc*().
{
Pjbb_t PjbbRaw; // pointer to new bitmap branch.
Pjbb_t Pjbb;
Word_t subexp;
// Get memory for new BranchB:
if ((PjbbRaw = j__udyAllocJBB(Pjpm)) == (Pjbb_t) NULL) return(-1);
Pjbb = P_JBB(PjbbRaw);
// Copy staged BranchB into just-allocated BranchB:
*Pjbb = *PStageJBB;
// Allocate the JP subarrays (BJP) for the new BranchB:
for (subexp = 0; subexp < cJU_NUMSUBEXPB; subexp++)
{
Pjp_t PjpRaw;
Pjp_t Pjp;
Word_t NumJP; // number of JPs in each subexpanse.
if ((NumJP = PSubCount[subexp]) == 0) continue; // empty.
// Out of memory, back out previous allocations:
if ((PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm)) == (Pjp_t) NULL)
{
while(subexp--)
{
if ((NumJP = PSubCount[subexp]) == 0) continue;
PjpRaw = JU_JBB_PJP(Pjbb, subexp);
j__udyFreeJBBJP(PjpRaw, NumJP, Pjpm);
}
j__udyFreeJBB(PjbbRaw, Pjpm);
return(-1); // out of memory.
}
Pjp = P_JP(PjpRaw);
// Place the JP subarray pointer in the new BranchB, copy subarray JPs, and
// advance to the next subexpanse:
JU_JBB_PJP(Pjbb, subexp) = PjpRaw;
JU_COPYMEM(Pjp, PjpArray, NumJP);
PjpArray += NumJP;
} // for each subexpanse.
// Change the PjpLeaf from Leaf to BranchB:
PjpLeaf->jp_Addr = (Word_t) PjbbRaw;
PjpLeaf->jp_Type += cJU_JPBRANCH_B2 - cJU_JPLEAF2; // Leaf to BranchB.
return(1);
} // j__udyStageJBBtoJBB()
// ****************************************************************************
// __ J U D Y J L L 2 T O J L B 1
//
// Create a LeafB1 (jlb_t = JLB1) from a Leaf2 (2-byte Indexes and for JudyL,
// Word_t Values). Return NULL if out of memory, else a pointer to the new
// LeafB1.
//
// NOTE: Caller must release the Leaf2 that was passed in.
FUNCTION static Pjlb_t j__udyJLL2toJLB1(
uint16_t * Pjll, // array of 16-bit indexes.
#ifdef JUDYL
Pjv_t Pjv, // array of associated values.
#endif
Word_t LeafPop1, // number of indexes/values.
Pvoid_t Pjpm) // jpm_t for JudyAlloc*()/JudyFree*().
{
Pjlb_t PjlbRaw;
Pjlb_t Pjlb;
int offset;
JUDYLCODE(int subexp;)
// Allocate the LeafB1:
if ((PjlbRaw = j__udyAllocJLB1(Pjpm)) == (Pjlb_t) NULL)
return((Pjlb_t) NULL);
Pjlb = P_JLB(PjlbRaw);
// Copy Leaf2 indexes to LeafB1:
for (offset = 0; offset < LeafPop1; ++offset)
JU_BITMAPSETL(Pjlb, Pjll[offset]);
#ifdef JUDYL
// Build LeafVs from bitmap:
for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
{
struct _POINTER_VALUES
{
Word_t pv_Pop1; // size of value area.
Pjv_t pv_Pjv; // raw pointer to value area.
} pv[cJU_NUMSUBEXPL];
// Get the population of the subexpanse, and if any, allocate a LeafV:
pv[subexp].pv_Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
if (pv[subexp].pv_Pop1)
{
Pjv_t Pjvnew;
// TBD: There is an opportunity to put pop == 1 value in pointer:
pv[subexp].pv_Pjv = j__udyLAllocJV(pv[subexp].pv_Pop1, Pjpm);
// Upon out of memory, free all previously allocated:
if (pv[subexp].pv_Pjv == (Pjv_t) NULL)
{
while(subexp--)
{
if (pv[subexp].pv_Pop1)
{
j__udyLFreeJV(pv[subexp].pv_Pjv, pv[subexp].pv_Pop1,
Pjpm);
}
}
j__udyFreeJLB1(PjlbRaw, Pjpm);
return((Pjlb_t) NULL);
}
Pjvnew = P_JV(pv[subexp].pv_Pjv);
JU_COPYMEM(Pjvnew, Pjv, pv[subexp].pv_Pop1);
Pjv += pv[subexp].pv_Pop1; // advance value pointer.
// Place raw pointer to value array in bitmap subexpanse:
JL_JLB_PVALUE(Pjlb, subexp) = pv[subexp].pv_Pjv;
} // populated subexpanse.
} // each subexpanse.
#endif // JUDYL
return(PjlbRaw); // pointer to LeafB1.
} // j__udyJLL2toJLB1()
// ****************************************************************************
// __ J U D Y C A S C A D E 1
//
// Create bitmap leaf from 1-byte Indexes and Word_t Values.
//
// TBD: There must be a better way.
//
// Only for JudyL 32 bit: (note, unifdef disallows comment on next line)
#if (defined(JUDYL) || (! defined(JU_64BIT)))
FUNCTION int j__udyCascade1(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
Word_t DcdP0;
uint8_t * PLeaf;
Pjlb_t PjlbRaw;
Pjlb_t Pjlb;
Word_t Pop1;
Word_t ii; // temp for loop counter
JUDYLCODE(Pjv_t Pjv;)
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF1);
assert((JU_JPDCDPOP0(Pjp) & 0xFF) == (cJU_LEAF1_MAXPOP1-1));
PjlbRaw = j__udyAllocJLB1(Pjpm);
if (PjlbRaw == (Pjlb_t) NULL) return(-1);
Pjlb = P_JLB(PjlbRaw);
PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
JUDYLCODE(Pjv = JL_LEAF1VALUEAREA(PLeaf, Pop1);)
// Copy 1 byte index Leaf to bitmap Leaf
for (ii = 0; ii < Pop1; ii++) JU_BITMAPSETL(Pjlb, PLeaf[ii]);
#ifdef JUDYL
// Build 8 subexpanse Value leaves from bitmap
for (ii = 0; ii < cJU_NUMSUBEXPL; ii++)
{
// Get number of Indexes in subexpanse
if ((Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, ii))))
{
Pjv_t PjvnewRaw; // value area of new leaf.
Pjv_t Pjvnew;
PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
if (PjvnewRaw == (Pjv_t) NULL) // out of memory.
{
// Free prevously allocated LeafVs:
while(ii--)
{
if ((Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, ii))))
{
PjvnewRaw = JL_JLB_PVALUE(Pjlb, ii);
j__udyLFreeJV(PjvnewRaw, Pop1, Pjpm);
}
}
// Free the bitmap leaf
j__udyLFreeJLB1(PjlbRaw,Pjpm);
return(-1);
}
Pjvnew = P_JV(PjvnewRaw);
JU_COPYMEM(Pjvnew, Pjv, Pop1);
Pjv += Pop1;
JL_JLB_PVALUE(Pjlb, ii) = PjvnewRaw;
}
}
#endif // JUDYL
DcdP0 = JU_JPDCDPOP0(Pjp) | (PLeaf[0] & cJU_DCDMASK(1));
JU_JPSETADT(Pjp, (Word_t)PjlbRaw, DcdP0, cJU_JPLEAF_B1);
return(1); // return success
} // j__udyCascade1()
#endif // (!(JUDY1 && JU_64BIT))
// ****************************************************************************
// __ J U D Y C A S C A D E 2
//
// Entry PLeaf of size LeafPop1 is either compressed or splayed with pointer
// returned in Pjp. Entry Levels sizeof(Word_t) down to level 2.
//
// Splay or compress the 2-byte Index Leaf that Pjp point to. Return *Pjp as a
// (compressed) cJU_LEAFB1 or a cJU_BRANCH_*2
FUNCTION int j__udyCascade2(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint16_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF2_MAXPOP1]; // JPs of new leaves
uint8_t StageExp [cJU_LEAF2_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF2);
assert((JU_JPDCDPOP0(Pjp) & 0xFFFF) == (cJU_LEAF2_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint16_t *) P_JLL(Pjp->jp_Addr);
// And its Value area
JUDYLCODE(Pjv = JL_LEAF2VALUEAREA(PLeaf, cJU_LEAF2_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it to a Bitmap Leaf
CIndex = PLeaf[0];
if (!JU_DIGITATSTATE(CIndex ^ PLeaf[cJU_LEAF2_MAXPOP1-1], 2))
{
// cJU_JPLEAF_B1
Word_t DcdP0;
Pjlb_t PjlbRaw;
PjlbRaw = j__udyJLL2toJLB1(PLeaf,
#ifdef JUDYL
Pjv,
#endif
cJU_LEAF2_MAXPOP1, Pjpm);
if (PjlbRaw == (Pjlb_t)NULL) return(-1); // out of memory
// Merge in another Dcd byte because compressing
DcdP0 = (CIndex & cJU_DCDMASK(1)) | JU_JPDCDPOP0(Pjp);
JU_JPSETADT(Pjp, (Word_t)PjlbRaw, DcdP0, cJU_JPLEAF_B1);
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 2 byte index Leaf to 1 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF2_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ PLeaf[End], 2))
)
{
// Build a leaf below the previous expanse
//
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 2);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 2);
if (Pop1 == 1) // cJU_JPIMMED_1_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(1)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_1_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_1_01);
#endif // JUDYL
}
else if (Pop1 <= cJU_IMMED1_MAXPOP1) // bigger
{
// cJL_JPIMMED_1_02..3: JudyL 32
// cJ1_JPIMMED_1_02..7: Judy1 32
// cJL_JPIMMED_1_02..7: JudyL 64
// cJ1_JPIMMED_1_02..15: Judy1 64
#ifdef JUDYL
Pjv_t PjvnewRaw; // value area of leaf.
Pjv_t Pjvnew;
// Allocate Value area for Immediate Leaf
PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
if (PjvnewRaw == (Pjv_t) NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjvnew = P_JV(PjvnewRaw);
// Copy to Values to Value Leaf
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
PjpJP->jp_Addr = (Word_t) PjvnewRaw;
// Copy to JP as an immediate Leaf
JU_COPYMEM(PjpJP->jp_LIndex, PLeaf + Start,
Pop1);
#else
JU_COPYMEM(PjpJP->jp_1Index, PLeaf + Start,
Pop1);
#endif
// Set Type, Population and Index size
PjpJP->jp_Type = cJU_JPIMMED_1_02 + Pop1 - 2;
}
// 64Bit Judy1 does not have Leaf1: (note, unifdef disallows comment on next
// line)
#if (! (defined(JUDY1) && defined(JU_64BIT)))
else if (Pop1 <= cJU_LEAF1_MAXPOP1) // still bigger
{
// cJU_JPLEAF1
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Get a new Leaf
PjllRaw = j__udyAllocJLL1(Pop1, Pjpm);
if (PjllRaw == (Pjll_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
#ifdef JUDYL
// Copy to Values to new Leaf
Pjvnew = JL_LEAF1VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
// Copy Indexes to new Leaf
JU_COPYMEM((uint8_t *)Pjll, PLeaf+Start, Pop1);
DBGCODE(JudyCheckSorted(Pjll, Pop1, 1);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2))
|
(CIndex & cJU_DCDMASK(2-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF1);
}
#endif // (!(JUDY1 && JU_64BIT)) // Not 64Bit Judy1
else // biggest
{
// cJU_JPLEAF_B1
Word_t DcdP0;
Pjlb_t PjlbRaw;
PjlbRaw = j__udyJLL2toJLB1(
PLeaf + Start,
#ifdef JUDYL
Pjv + Start,
#endif
Pop1, Pjpm);
if (PjlbRaw == (Pjlb_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2))
|
(CIndex & cJU_DCDMASK(2-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjlbRaw, DcdP0,
cJU_JPLEAF_B1);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF2_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = PLeaf[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L2;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade2()
// ****************************************************************************
// __ J U D Y C A S C A D E 3
//
// Return *Pjp as a (compressed) cJU_LEAF2, cJU_BRANCH_L3, cJU_BRANCH_B3.
FUNCTION int j__udyCascade3(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint8_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF3_MAXPOP1]; // JPs of new leaves
Word_t StageA [cJU_LEAF3_MAXPOP1];
uint8_t StageExp [cJU_LEAF3_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF3);
assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFF) == (cJU_LEAF3_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
// Extract leaf to Word_t and insert-sort Index into it
j__udyCopy3toW(StageA, PLeaf, cJU_LEAF3_MAXPOP1);
// Get the address of the Leaf and Value area
JUDYLCODE(Pjv = JL_LEAF3VALUEAREA(PLeaf, cJU_LEAF3_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
CIndex = StageA[0];
if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF3_MAXPOP1-1], 3))
{
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Alloc a 2 byte Index Leaf
PjllRaw = j__udyAllocJLL2(cJU_LEAF3_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy just 2 bytes Indexes to new Leaf
// j__udyCopyWto2((uint16_t *) Pjll, StageA, cJU_LEAF3_MAXPOP1);
JU_COPYMEM ((uint16_t *) Pjll, StageA, cJU_LEAF3_MAXPOP1);
#ifdef JUDYL
// Copy Value area into new Leaf
Pjvnew = JL_LEAF2VALUEAREA(Pjll, cJU_LEAF3_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF3_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF3_MAXPOP1, 2);)
// Form new JP, Pop0 field is unchanged
// Add in another Dcd byte because compressing
DcdP0 = (CIndex & cJU_DCDMASK(2)) | JU_JPDCDPOP0(Pjp);
JU_JPSETADT(Pjp, (Word_t) PjllRaw, DcdP0, cJU_JPLEAF2);
return(1); // Success
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 3 byte index Leaf to 2 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF3_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ StageA[End], 3))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 3);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 3);
if (Pop1 == 1) // cJU_JPIMMED_2_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_2_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_2_01);
#endif // JUDYL
}
#if (defined(JUDY1) || defined(JU_64BIT))
else if (Pop1 <= cJU_IMMED2_MAXPOP1)
{
// cJ1_JPIMMED_2_02..3: Judy1 32
// cJL_JPIMMED_2_02..3: JudyL 64
// cJ1_JPIMMED_2_02..7: Judy1 64
#ifdef JUDYL
// Alloc is 1st in case of malloc fail
Pjv_t PjvnewRaw; // value area of new leaf.
Pjv_t Pjvnew;
// Allocate Value area for Immediate Leaf
PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
if (PjvnewRaw == (Pjv_t) NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjvnew = P_JV(PjvnewRaw);
// Copy to Values to Value Leaf
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
PjpJP->jp_Addr = (Word_t) PjvnewRaw;
// Copy to Index to JP as an immediate Leaf
JU_COPYMEM((uint16_t *) (PjpJP->jp_LIndex),
StageA + Start, Pop1);
#else // JUDY1
JU_COPYMEM((uint16_t *) (PjpJP->jp_1Index),
StageA + Start, Pop1);
#endif // JUDY1
// Set Type, Population and Index size
PjpJP->jp_Type = cJU_JPIMMED_2_02 + Pop1 - 2;
}
#endif // (JUDY1 || JU_64BIT)
else // Make a linear leaf2
{
// cJU_JPLEAF2
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
PjllRaw = j__udyAllocJLL2(Pop1, Pjpm);
if (PjllRaw == (Pjll_t) NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
#ifdef JUDYL
// Copy to Values to new Leaf
Pjvnew = JL_LEAF2VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
// Copy least 2 bytes per Index of Leaf to new Leaf
JU_COPYMEM((uint16_t *) Pjll, StageA+Start,
Pop1);
DBGCODE(JudyCheckSorted(Pjll, Pop1, 2);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(3))
|
(CIndex & cJU_DCDMASK(3-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF2);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF3_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = StageA[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L3;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade3()
#ifdef JU_64BIT // JudyCascade[4567]
// ****************************************************************************
// __ J U D Y C A S C A D E 4
//
// Cascade from a cJU_JPLEAF4 to one of the following:
// 1. if leaf is in 1 expanse:
// compress it into a JPLEAF3
// 2. if leaf contains multiple expanses:
// create linear or bitmap branch containing
// each new expanse is either a:
// JPIMMED_3_01 branch
// JPIMMED_3_02 branch
// JPLEAF3
FUNCTION int j__udyCascade4(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint32_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF4_MAXPOP1]; // JPs of new leaves
Word_t StageA [cJU_LEAF4_MAXPOP1];
uint8_t StageExp [cJU_LEAF4_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF4);
assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFF) == (cJU_LEAF4_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint32_t *) P_JLL(Pjp->jp_Addr);
// Extract 4 byte index Leaf to Word_t
j__udyCopy4toW(StageA, PLeaf, cJU_LEAF4_MAXPOP1);
// Get the address of the Leaf and Value area
JUDYLCODE(Pjv = JL_LEAF4VALUEAREA(PLeaf, cJU_LEAF4_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
CIndex = StageA[0];
if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF4_MAXPOP1-1], 4))
{
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new Leaf.
// Alloc a 3 byte Index Leaf
PjllRaw = j__udyAllocJLL3(cJU_LEAF4_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy Index area into new Leaf
j__udyCopyWto3((uint8_t *) Pjll, StageA, cJU_LEAF4_MAXPOP1);
#ifdef JUDYL
// Copy Value area into new Leaf
Pjvnew = JL_LEAF3VALUEAREA(Pjll, cJU_LEAF4_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF4_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF4_MAXPOP1, 3);)
DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(3));
JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF3);
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 4 byte index Leaf to 3 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF4_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ StageA[End], 4))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 4);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 4);
if (Pop1 == 1) // cJU_JPIMMED_3_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(3)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_3_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_3_01);
#endif // JUDYL
}
else if (Pop1 <= cJU_IMMED3_MAXPOP1)
{
// cJ1_JPIMMED_3_02 : Judy1 32
// cJL_JPIMMED_3_02 : JudyL 64
// cJ1_JPIMMED_3_02..5: Judy1 64
#ifdef JUDYL
// Alloc is 1st in case of malloc fail
Pjv_t PjvnewRaw; // value area of new leaf.
Pjv_t Pjvnew;
// Allocate Value area for Immediate Leaf
PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
if (PjvnewRaw == (Pjv_t) NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjvnew = P_JV(PjvnewRaw);
// Copy to Values to Value Leaf
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
PjpJP->jp_Addr = (Word_t) PjvnewRaw;
// Copy to Index to JP as an immediate Leaf
j__udyCopyWto3(PjpJP->jp_LIndex,
StageA + Start, Pop1);
#else
j__udyCopyWto3(PjpJP->jp_1Index,
StageA + Start, Pop1);
#endif
// Set type, population and Index size
PjpJP->jp_Type = cJU_JPIMMED_3_02 + Pop1 - 2;
}
else
{
// cJU_JPLEAF3
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
PjllRaw = j__udyAllocJLL3(Pop1, Pjpm);
if (PjllRaw == (Pjll_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
// Copy Indexes to new Leaf
j__udyCopyWto3((uint8_t *) Pjll, StageA + Start,
Pop1);
#ifdef JUDYL
// Copy to Values to new Leaf
Pjvnew = JL_LEAF3VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
DBGCODE(JudyCheckSorted(Pjll, Pop1, 3);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(4))
|
(CIndex & cJU_DCDMASK(4-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF3);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF4_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = StageA[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L4;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade4()
// ****************************************************************************
// __ J U D Y C A S C A D E 5
//
// Cascade from a cJU_JPLEAF5 to one of the following:
// 1. if leaf is in 1 expanse:
// compress it into a JPLEAF4
// 2. if leaf contains multiple expanses:
// create linear or bitmap branch containing
// each new expanse is either a:
// JPIMMED_4_01 branch
// JPLEAF4
FUNCTION int j__udyCascade5(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint8_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF5_MAXPOP1]; // JPs of new leaves
Word_t StageA [cJU_LEAF5_MAXPOP1];
uint8_t StageExp [cJU_LEAF5_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF5);
assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFFFF) == (cJU_LEAF5_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
// Extract 5 byte index Leaf to Word_t
j__udyCopy5toW(StageA, PLeaf, cJU_LEAF5_MAXPOP1);
// Get the address of the Leaf and Value area
JUDYLCODE(Pjv = JL_LEAF5VALUEAREA(PLeaf, cJU_LEAF5_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
CIndex = StageA[0];
if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF5_MAXPOP1-1], 5))
{
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Alloc a 4 byte Index Leaf
PjllRaw = j__udyAllocJLL4(cJU_LEAF5_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy Index area into new Leaf
j__udyCopyWto4((uint8_t *) Pjll, StageA, cJU_LEAF5_MAXPOP1);
#ifdef JUDYL
// Copy Value area into new Leaf
Pjvnew = JL_LEAF4VALUEAREA(Pjll, cJU_LEAF5_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF5_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF5_MAXPOP1, 4);)
DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(4));
JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF4);
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 5 byte index Leaf to 4 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF5_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ StageA[End], 5))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 5);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 5);
if (Pop1 == 1) // cJU_JPIMMED_4_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(4)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_4_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_4_01);
#endif // JUDYL
}
#ifdef JUDY1
else if (Pop1 <= cJ1_IMMED4_MAXPOP1)
{
// cJ1_JPIMMED_4_02..3: Judy1 64
// Copy to Index to JP as an immediate Leaf
j__udyCopyWto4(PjpJP->jp_1Index,
StageA + Start, Pop1);
// Set pointer, type, population and Index size
PjpJP->jp_Type = cJ1_JPIMMED_4_02 + Pop1 - 2;
}
#endif
else
{
// cJU_JPLEAF4
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Get a new Leaf
PjllRaw = j__udyAllocJLL4(Pop1, Pjpm);
if (PjllRaw == (Pjll_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
// Copy Indexes to new Leaf
j__udyCopyWto4((uint8_t *) Pjll, StageA + Start,
Pop1);
#ifdef JUDYL
// Copy to Values to new Leaf
Pjvnew = JL_LEAF4VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
DBGCODE(JudyCheckSorted(Pjll, Pop1, 4);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(5))
|
(CIndex & cJU_DCDMASK(5-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF4);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF5_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = StageA[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L5;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade5()
// ****************************************************************************
// __ J U D Y C A S C A D E 6
//
// Cascade from a cJU_JPLEAF6 to one of the following:
// 1. if leaf is in 1 expanse:
// compress it into a JPLEAF5
// 2. if leaf contains multiple expanses:
// create linear or bitmap branch containing
// each new expanse is either a:
// JPIMMED_5_01 ... JPIMMED_5_03 branch
// JPIMMED_5_01 branch
// JPLEAF5
FUNCTION int j__udyCascade6(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint8_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF6_MAXPOP1]; // JPs of new leaves
Word_t StageA [cJU_LEAF6_MAXPOP1];
uint8_t StageExp [cJU_LEAF6_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF6);
assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFFFFFF) == (cJU_LEAF6_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
// Extract 6 byte index Leaf to Word_t
j__udyCopy6toW(StageA, PLeaf, cJU_LEAF6_MAXPOP1);
// Get the address of the Leaf and Value area
JUDYLCODE(Pjv = JL_LEAF6VALUEAREA(PLeaf, cJU_LEAF6_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
CIndex = StageA[0];
if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF6_MAXPOP1-1], 6))
{
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Alloc a 5 byte Index Leaf
PjllRaw = j__udyAllocJLL5(cJU_LEAF6_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy Index area into new Leaf
j__udyCopyWto5((uint8_t *) Pjll, StageA, cJU_LEAF6_MAXPOP1);
#ifdef JUDYL
// Copy Value area into new Leaf
Pjvnew = JL_LEAF5VALUEAREA(Pjll, cJU_LEAF6_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF6_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF6_MAXPOP1, 5);)
DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(5));
JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF5);
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 6 byte index Leaf to 5 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF6_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ StageA[End], 6))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 6);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 6);
if (Pop1 == 1) // cJU_JPIMMED_5_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(5)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_5_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_5_01);
#endif // JUDYL
}
#ifdef JUDY1
else if (Pop1 <= cJ1_IMMED5_MAXPOP1)
{
// cJ1_JPIMMED_5_02..3: Judy1 64
// Copy to Index to JP as an immediate Leaf
j__udyCopyWto5(PjpJP->jp_1Index,
StageA + Start, Pop1);
// Set pointer, type, population and Index size
PjpJP->jp_Type = cJ1_JPIMMED_5_02 + Pop1 - 2;
}
#endif
else
{
// cJU_JPLEAF5
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Get a new Leaf
PjllRaw = j__udyAllocJLL5(Pop1, Pjpm);
if (PjllRaw == (Pjll_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
// Copy Indexes to new Leaf
j__udyCopyWto5((uint8_t *) Pjll, StageA + Start,
Pop1);
// Copy to Values to new Leaf
#ifdef JUDYL
Pjvnew = JL_LEAF5VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
DBGCODE(JudyCheckSorted(Pjll, Pop1, 5);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(6))
|
(CIndex & cJU_DCDMASK(6-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF5);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF6_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = StageA[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L6;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade6()
// ****************************************************************************
// __ J U D Y C A S C A D E 7
//
// Cascade from a cJU_JPLEAF7 to one of the following:
// 1. if leaf is in 1 expanse:
// compress it into a JPLEAF6
// 2. if leaf contains multiple expanses:
// create linear or bitmap branch containing
// each new expanse is either a:
// JPIMMED_6_01 ... JPIMMED_6_02 branch
// JPIMMED_6_01 branch
// JPLEAF6
FUNCTION int j__udyCascade7(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
uint8_t * PLeaf; // pointer to leaf, explicit type.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAF7_MAXPOP1]; // JPs of new leaves
Word_t StageA [cJU_LEAF7_MAXPOP1];
uint8_t StageExp [cJU_LEAF7_MAXPOP1]; // Expanses of new leaves
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
assert(JU_JPTYPE(Pjp) == cJU_JPLEAF7);
assert(JU_JPDCDPOP0(Pjp) == (cJU_LEAF7_MAXPOP1-1));
// Get the address of the Leaf
PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
// Extract 7 byte index Leaf to Word_t
j__udyCopy7toW(StageA, PLeaf, cJU_LEAF7_MAXPOP1);
// Get the address of the Leaf and Value area
JUDYLCODE(Pjv = JL_LEAF7VALUEAREA(PLeaf, cJU_LEAF7_MAXPOP1);)
// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
CIndex = StageA[0];
if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF7_MAXPOP1-1], 7))
{
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Alloc a 6 byte Index Leaf
PjllRaw = j__udyAllocJLL6(cJU_LEAF7_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy Index area into new Leaf
j__udyCopyWto6((uint8_t *) Pjll, StageA, cJU_LEAF7_MAXPOP1);
#ifdef JUDYL
// Copy Value area into new Leaf
Pjvnew = JL_LEAF6VALUEAREA(Pjll, cJU_LEAF7_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF7_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF7_MAXPOP1, 6);)
DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(6));
JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF6);
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 7 byte index Leaf to 6 byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAF7_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ StageA[End], 7))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, 7);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 7);
if (Pop1 == 1) // cJU_JPIMMED_6_01
{
Word_t DcdP0;
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(6)) |
CIndex;
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_6_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
cJL_JPIMMED_6_01);
#endif // JUDYL
}
#ifdef JUDY1
else if (Pop1 == cJ1_IMMED6_MAXPOP1)
{
// cJ1_JPIMMED_6_02: Judy1 64
// Copy to Index to JP as an immediate Leaf
j__udyCopyWto6(PjpJP->jp_1Index,
StageA + Start, 2);
// Set pointer, type, population and Index size
PjpJP->jp_Type = cJ1_JPIMMED_6_02;
}
#endif
else
{
// cJU_JPLEAF6
Word_t DcdP0;
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Get a new Leaf
PjllRaw = j__udyAllocJLL6(Pop1, Pjpm);
if (PjllRaw == (Pjll_t)NULL)
FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjll = P_JLL(PjllRaw);
// Copy Indexes to new Leaf
j__udyCopyWto6((uint8_t *) Pjll, StageA + Start,
Pop1);
#ifdef JUDYL
// Copy to Values to new Leaf
Pjvnew = JL_LEAF6VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif
DBGCODE(JudyCheckSorted(Pjll, Pop1, 6);)
DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(7))
|
(CIndex & cJU_DCDMASK(7-1))
|
(Pop1 - 1);
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
cJU_JPLEAF6);
}
ExpCnt++;
// Done?
if (End == cJU_LEAF7_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = StageA[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L7;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
}
return(1);
} // j__udyCascade7()
#endif // JU_64BIT
// ****************************************************************************
// __ J U D Y C A S C A D E L
//
// (Compressed) cJU_LEAF3[7], cJ1_JPBRANCH_L.
//
// Cascade from a LEAFW (under Pjp) to one of the following:
// 1. if LEAFW is in 1 expanse:
// create linear branch with a JPLEAF3[7] under it
// 2. LEAFW contains multiple expanses:
// create linear or bitmap branch containing new expanses
// each new expanse is either a: 32 64
// JPIMMED_3_01 branch Y N
// JPIMMED_7_01 branch N Y
// JPLEAF3 Y N
// JPLEAF7 N Y
FUNCTION int j__udyCascadeL(
Pjp_t Pjp,
Pvoid_t Pjpm)
{
Pjlw_t Pjlw; // leaf to work on.
Word_t End, Start; // temporaries.
Word_t ExpCnt; // count of expanses of splay.
Word_t CIndex; // current Index word.
JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
// Temp staging for parts(Leaves) of newly splayed leaf
jp_t StageJP [cJU_LEAFW_MAXPOP1];
uint8_t StageExp[cJU_LEAFW_MAXPOP1];
uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
jbb_t StageJBB; // staged bitmap branch
// Get the address of the Leaf
Pjlw = P_JLW(Pjp->jp_Addr);
assert(Pjlw[0] == (cJU_LEAFW_MAXPOP1 - 1));
// Get pointer to Value area of old Leaf
JUDYLCODE(Pjv = JL_LEAFWVALUEAREA(Pjlw, cJU_LEAFW_MAXPOP1);)
Pjlw++; // Now point to Index area
// If Leaf is in 1 expanse -- first compress it (compare 1st, last & Index):
CIndex = Pjlw[0]; // also used far below
if (!JU_DIGITATSTATE(CIndex ^ Pjlw[cJU_LEAFW_MAXPOP1 - 1],
cJU_ROOTSTATE))
{
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
// Get the common expanse to all elements in Leaf
StageExp[0] = JU_DIGITATSTATE(CIndex, cJU_ROOTSTATE);
// Alloc a 3[7] byte Index Leaf
#ifdef JU_64BIT
PjllRaw = j__udyAllocJLL7(cJU_LEAFW_MAXPOP1, Pjpm);
if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
Pjll = P_JLL(PjllRaw);
// Copy LEAFW to a cJU_JPLEAF7
j__udyCopyWto7((uint8_t *) Pjll, Pjlw, cJU_LEAFW_MAXPOP1);
#ifdef JUDYL
// Get the Value area of new Leaf
Pjvnew = JL_LEAF7VALUEAREA(Pjll, cJU_LEAFW_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAFW_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAFW_MAXPOP1, 7);)
#else // 32 Bit
PjllRaw = j__udyAllocJLL3(cJU_LEAFW_MAXPOP1, Pjpm);
if (PjllRaw == (Pjll_t) NULL) return(-1);
Pjll = P_JLL(PjllRaw);
// Copy LEAFW to a cJU_JPLEAF3
j__udyCopyWto3((uint8_t *) Pjll, Pjlw, cJU_LEAFW_MAXPOP1);
#ifdef JUDYL
// Get the Value area of new Leaf
Pjvnew = JL_LEAF3VALUEAREA(Pjll, cJU_LEAFW_MAXPOP1);
JU_COPYMEM(Pjvnew, Pjv, cJU_LEAFW_MAXPOP1);
#endif
DBGCODE(JudyCheckSorted(Pjll, cJU_LEAFW_MAXPOP1, 3);)
#endif // 32 Bit
// Following not needed because cJU_DCDMASK(3[7]) is == 0
////// StageJP[0].jp_DcdPopO |= (CIndex & cJU_DCDMASK(3[7]));
#ifdef JU_64BIT
JU_JPSETADT(&(StageJP[0]), (Word_t)PjllRaw, cJU_LEAFW_MAXPOP1-1,
cJU_JPLEAF7);
#else // 32BIT
JU_JPSETADT(&(StageJP[0]), (Word_t)PjllRaw, cJU_LEAFW_MAXPOP1-1,
cJU_JPLEAF3);
#endif // 32BIT
// Create a 1 element Linear branch
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, 1, Pjpm) == -1)
return(-1);
// Change the type of callers JP
Pjp->jp_Type = cJU_JPBRANCH_L;
return(1);
}
// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
StageJBB = StageJBBZero; // zero staged bitmap branch
ZEROJP(SubJPCount);
// Splay the 4[8] byte Index Leaf to 3[7] byte Index Leaves
for (ExpCnt = Start = 0, End = 1; ; End++)
{
// Check if new expanse or last one
if ( (End == cJU_LEAFW_MAXPOP1)
||
(JU_DIGITATSTATE(CIndex ^ Pjlw[End], cJU_ROOTSTATE))
)
{
// Build a leaf below the previous expanse
Pjp_t PjpJP = StageJP + ExpCnt;
Word_t Pop1 = End - Start;
Word_t expanse = JU_DIGITATSTATE(CIndex, cJU_ROOTSTATE);
Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
//
// set the bit that is the current expanse
JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
#ifdef SUBEXPCOUNTS
StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
#endif
// count number of expanses in each subexpanse
SubJPCount[subexp]++;
// Save byte expanse of leaf
StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex,
cJU_ROOTSTATE);
if (Pop1 == 1) // cJU_JPIMMED_3[7]_01
{
#ifdef JU_64BIT
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, CIndex, cJ1_JPIMMED_7_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], CIndex,
cJL_JPIMMED_7_01);
#endif // JUDYL
#else // JU_32BIT
#ifdef JUDY1
JU_JPSETADT(PjpJP, 0, CIndex, cJ1_JPIMMED_3_01);
#else // JUDYL
JU_JPSETADT(PjpJP, Pjv[Start], CIndex,
cJL_JPIMMED_3_01);
#endif // JUDYL
#endif // JU_32BIT
}
#ifdef JUDY1
#ifdef JU_64BIT
else if (Pop1 <= cJ1_IMMED7_MAXPOP1)
#else
else if (Pop1 <= cJ1_IMMED3_MAXPOP1)
#endif
{
// cJ1_JPIMMED_3_02 : Judy1 32
// cJ1_JPIMMED_7_02 : Judy1 64
// Copy to JP as an immediate Leaf
#ifdef JU_64BIT
j__udyCopyWto7(PjpJP->jp_1Index, Pjlw+Start, 2);
PjpJP->jp_Type = cJ1_JPIMMED_7_02;
#else
j__udyCopyWto3(PjpJP->jp_1Index, Pjlw+Start, 2);
PjpJP->jp_Type = cJ1_JPIMMED_3_02;
#endif // 32 Bit
}
#endif // JUDY1
else // Linear Leaf JPLEAF3[7]
{
// cJU_JPLEAF3[7]
Pjll_t PjllRaw; // pointer to new leaf.
Pjll_t Pjll;
JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
#ifdef JU_64BIT
PjllRaw = j__udyAllocJLL7(Pop1, Pjpm);
if (PjllRaw == (Pjll_t) NULL) return(-1);
Pjll = P_JLL(PjllRaw);
j__udyCopyWto7((uint8_t *) Pjll, Pjlw + Start,
Pop1);
#ifdef JUDYL
Pjvnew = JL_LEAF7VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif // JUDYL
DBGCODE(JudyCheckSorted(Pjll, Pop1, 7);)
#else // JU_64BIT - 32 Bit
PjllRaw = j__udyAllocJLL3(Pop1, Pjpm);
if (PjllRaw == (Pjll_t) NULL) return(-1);
Pjll = P_JLL(PjllRaw);
j__udyCopyWto3((uint8_t *) Pjll, Pjlw + Start,
Pop1);
#ifdef JUDYL
Pjvnew = JL_LEAF3VALUEAREA(Pjll, Pop1);
JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
#endif // JUDYL
DBGCODE(JudyCheckSorted(Pjll, Pop1, 3);)
#endif // 32 Bit
#ifdef JU_64BIT
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, Pop1 - 1,
cJU_JPLEAF7);
#else // JU_64BIT - 32 Bit
JU_JPSETADT(PjpJP, (Word_t)PjllRaw, Pop1 - 1,
cJU_JPLEAF3);
#endif // 32 Bit
}
ExpCnt++;
// Done?
if (End == cJU_LEAFW_MAXPOP1) break;
// New Expanse, Start and Count
CIndex = Pjlw[End];
Start = End;
}
}
// Now put all the Leaves below a BranchL or BranchB:
if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
{
if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_L;
}
else
{
if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
== -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
Pjp->jp_Type = cJU_JPBRANCH_B; // cJU_LEAFW is out of sequence
}
return(1);
} // j__udyCascadeL()