315 lines
8.1 KiB
C
315 lines
8.1 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$
|
||
|
|
||
|
// Branch creation functions for Judy1 and JudyL.
|
||
|
// Compile with one of -DJUDY1 or -DJUDYL.
|
||
|
|
||
|
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||
|
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||
|
#endif
|
||
|
|
||
|
#ifdef JUDY1
|
||
|
#include "Judy1.h"
|
||
|
#else
|
||
|
#include "JudyL.h"
|
||
|
#endif
|
||
|
|
||
|
#include "JudyPrivate1L.h"
|
||
|
|
||
|
|
||
|
// ****************************************************************************
|
||
|
// J U D Y C R E A T E B R A N C H L
|
||
|
//
|
||
|
// Build a BranchL from an array of JPs and associated 1 byte digits
|
||
|
// (expanses). Return with Pjp pointing to the BranchL. Caller must
|
||
|
// deallocate passed arrays, if necessary.
|
||
|
//
|
||
|
// We have no idea what kind of BranchL it is, so caller must set the jp_Type.
|
||
|
//
|
||
|
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||
|
|
||
|
FUNCTION int j__udyCreateBranchL(
|
||
|
Pjp_t Pjp, // Build JPs from this place
|
||
|
Pjp_t PJPs, // Array of JPs to put into Bitmap branch
|
||
|
uint8_t Exp[], // Array of expanses to put into bitmap
|
||
|
Word_t ExpCnt, // Number of above JPs and Expanses
|
||
|
Pvoid_t Pjpm)
|
||
|
{
|
||
|
Pjbl_t PjblRaw; // pointer to linear branch.
|
||
|
Pjbl_t Pjbl;
|
||
|
|
||
|
assert(ExpCnt <= cJU_BRANCHLMAXJPS);
|
||
|
|
||
|
PjblRaw = j__udyAllocJBL(Pjpm);
|
||
|
if (PjblRaw == (Pjbl_t) NULL) return(-1);
|
||
|
Pjbl = P_JBL(PjblRaw);
|
||
|
|
||
|
// Build a Linear Branch
|
||
|
Pjbl->jbl_NumJPs = ExpCnt;
|
||
|
|
||
|
// Copy from the Linear branch from splayed leaves
|
||
|
JU_COPYMEM(Pjbl->jbl_Expanse, Exp, ExpCnt);
|
||
|
JU_COPYMEM(Pjbl->jbl_jp, PJPs, ExpCnt);
|
||
|
|
||
|
// Pass back new pointer to the Linear branch in JP
|
||
|
Pjp->jp_Addr = (Word_t) PjblRaw;
|
||
|
|
||
|
return(1);
|
||
|
|
||
|
} // j__udyCreateBranchL()
|
||
|
|
||
|
|
||
|
// ****************************************************************************
|
||
|
// J U D Y C R E A T E B R A N C H B
|
||
|
//
|
||
|
// Build a BranchB from an array of JPs and associated 1 byte digits
|
||
|
// (expanses). Return with Pjp pointing to the BranchB. Caller must
|
||
|
// deallocate passed arrays, if necessary.
|
||
|
//
|
||
|
// We have no idea what kind of BranchB it is, so caller must set the jp_Type.
|
||
|
//
|
||
|
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||
|
|
||
|
FUNCTION int j__udyCreateBranchB(
|
||
|
Pjp_t Pjp, // Build JPs from this place
|
||
|
Pjp_t PJPs, // Array of JPs to put into Bitmap branch
|
||
|
uint8_t Exp[], // Array of expanses to put into bitmap
|
||
|
Word_t ExpCnt, // Number of above JPs and Expanses
|
||
|
Pvoid_t Pjpm)
|
||
|
{
|
||
|
Pjbb_t PjbbRaw; // pointer to bitmap branch.
|
||
|
Pjbb_t Pjbb;
|
||
|
Word_t ii, jj; // Temps
|
||
|
uint8_t CurrSubExp; // Current sub expanse for BM
|
||
|
|
||
|
// This assertion says the number of populated subexpanses is not too large.
|
||
|
// This function is only called when a BranchL overflows to a BranchB or when a
|
||
|
// cascade occurs, meaning a leaf overflows. Either way ExpCnt cant be very
|
||
|
// large, in fact a lot smaller than cJU_BRANCHBMAXJPS. (Otherwise a BranchU
|
||
|
// would be used.) Popping this assertion means something (unspecified) has
|
||
|
// gone very wrong, or else Judys design criteria have changed, although in
|
||
|
// fact there should be no HARM in creating a BranchB with higher actual
|
||
|
// fanout.
|
||
|
|
||
|
assert(ExpCnt <= cJU_BRANCHBMAXJPS);
|
||
|
|
||
|
// Get memory for a Bitmap branch
|
||
|
PjbbRaw = j__udyAllocJBB(Pjpm);
|
||
|
if (PjbbRaw == (Pjbb_t) NULL) return(-1);
|
||
|
Pjbb = P_JBB(PjbbRaw);
|
||
|
|
||
|
// Get 1st "sub" expanse (0..7) of bitmap branch
|
||
|
CurrSubExp = Exp[0] / cJU_BITSPERSUBEXPB;
|
||
|
|
||
|
// Index thru all 1 byte sized expanses:
|
||
|
|
||
|
for (jj = ii = 0; ii <= ExpCnt; ii++)
|
||
|
{
|
||
|
Word_t SubExp; // Cannot be a uint8_t
|
||
|
|
||
|
// Make sure we cover the last one
|
||
|
if (ii == ExpCnt)
|
||
|
{
|
||
|
SubExp = cJU_ALLONES; // Force last one
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Calculate the "sub" expanse of the byte expanse
|
||
|
SubExp = Exp[ii] / cJU_BITSPERSUBEXPB; // Bits 5..7.
|
||
|
|
||
|
// Set the bit that represents the expanse in Exp[]
|
||
|
JU_JBB_BITMAP(Pjbb, SubExp) |= JU_BITPOSMASKB(Exp[ii]);
|
||
|
}
|
||
|
// Check if a new "sub" expanse range needed
|
||
|
if (SubExp != CurrSubExp)
|
||
|
{
|
||
|
// Get number of JPs in this sub expanse
|
||
|
Word_t NumJP = ii - jj;
|
||
|
Pjp_t PjpRaw;
|
||
|
Pjp_t Pjp;
|
||
|
|
||
|
PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm);
|
||
|
Pjp = P_JP(PjpRaw);
|
||
|
|
||
|
if (PjpRaw == (Pjp_t) NULL) // out of memory.
|
||
|
{
|
||
|
|
||
|
// Free any previous allocations:
|
||
|
|
||
|
while(CurrSubExp--)
|
||
|
{
|
||
|
NumJP = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,
|
||
|
CurrSubExp));
|
||
|
if (NumJP)
|
||
|
{
|
||
|
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb,
|
||
|
CurrSubExp), NumJP, Pjpm);
|
||
|
}
|
||
|
}
|
||
|
j__udyFreeJBB(PjbbRaw, Pjpm);
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
// Place the array of JPs in bitmap branch:
|
||
|
|
||
|
JU_JBB_PJP(Pjbb, CurrSubExp) = PjpRaw;
|
||
|
|
||
|
// Copy the JPs to new leaf:
|
||
|
|
||
|
JU_COPYMEM(Pjp, PJPs + jj, NumJP);
|
||
|
|
||
|
// On to the next bitmap branch "sub" expanse:
|
||
|
|
||
|
jj = ii;
|
||
|
CurrSubExp = SubExp;
|
||
|
}
|
||
|
} // for each 1-byte expanse
|
||
|
|
||
|
// Pass back some of the JP to the new Bitmap branch:
|
||
|
|
||
|
Pjp->jp_Addr = (Word_t) PjbbRaw;
|
||
|
|
||
|
return(1);
|
||
|
|
||
|
} // j__udyCreateBranchB()
|
||
|
|
||
|
|
||
|
// ****************************************************************************
|
||
|
// J U D Y C R E A T E B R A N C H U
|
||
|
//
|
||
|
// Build a BranchU from a BranchB. Return with Pjp pointing to the BranchU.
|
||
|
// Free the BranchB and its JP subarrays.
|
||
|
//
|
||
|
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||
|
|
||
|
FUNCTION int j__udyCreateBranchU(
|
||
|
Pjp_t Pjp,
|
||
|
Pvoid_t Pjpm)
|
||
|
{
|
||
|
jp_t JPNull;
|
||
|
Pjbu_t PjbuRaw;
|
||
|
Pjbu_t Pjbu;
|
||
|
Pjbb_t PjbbRaw;
|
||
|
Pjbb_t Pjbb;
|
||
|
Word_t ii, jj;
|
||
|
BITMAPB_t BitMap;
|
||
|
Pjp_t PDstJP;
|
||
|
#ifdef JU_STAGED_EXP
|
||
|
jbu_t BranchU; // Staged uncompressed branch
|
||
|
#else
|
||
|
|
||
|
// Allocate memory for a BranchU:
|
||
|
|
||
|
PjbuRaw = j__udyAllocJBU(Pjpm);
|
||
|
if (PjbuRaw == (Pjbu_t) NULL) return(-1);
|
||
|
Pjbu = P_JBU(PjbuRaw);
|
||
|
#endif
|
||
|
JU_JPSETADT(&JPNull, 0, 0, JU_JPTYPE(Pjp) - cJU_JPBRANCH_B2 + cJU_JPNULL1);
|
||
|
|
||
|
// Get the pointer to the BranchB:
|
||
|
|
||
|
PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
|
||
|
Pjbb = P_JBB(PjbbRaw);
|
||
|
|
||
|
// Set the pointer to the Uncompressed branch
|
||
|
#ifdef JU_STAGED_EXP
|
||
|
PDstJP = BranchU.jbu_jp;
|
||
|
#else
|
||
|
PDstJP = Pjbu->jbu_jp;
|
||
|
#endif
|
||
|
for (ii = 0; ii < cJU_NUMSUBEXPB; ii++)
|
||
|
{
|
||
|
Pjp_t PjpA;
|
||
|
Pjp_t PjpB;
|
||
|
|
||
|
PjpB = PjpA = P_JP(JU_JBB_PJP(Pjbb, ii));
|
||
|
|
||
|
// Get the bitmap for this subexpanse
|
||
|
BitMap = JU_JBB_BITMAP(Pjbb, ii);
|
||
|
|
||
|
// NULL empty subexpanses
|
||
|
if (BitMap == 0)
|
||
|
{
|
||
|
// But, fill with NULLs
|
||
|
for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
|
||
|
{
|
||
|
PDstJP[jj] = JPNull;
|
||
|
}
|
||
|
PDstJP += cJU_BITSPERSUBEXPB;
|
||
|
continue;
|
||
|
}
|
||
|
// Check if Uncompressed subexpanse
|
||
|
if (BitMap == cJU_FULLBITMAPB)
|
||
|
{
|
||
|
// Copy subexpanse to the Uncompressed branch intact
|
||
|
JU_COPYMEM(PDstJP, PjpA, cJU_BITSPERSUBEXPB);
|
||
|
|
||
|
// Bump to next subexpanse
|
||
|
PDstJP += cJU_BITSPERSUBEXPB;
|
||
|
|
||
|
// Set length of subexpanse
|
||
|
jj = cJU_BITSPERSUBEXPB;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
|
||
|
{
|
||
|
// Copy JP or NULLJP depending on bit
|
||
|
if (BitMap & 1) { *PDstJP = *PjpA++; }
|
||
|
else { *PDstJP = JPNull; }
|
||
|
|
||
|
PDstJP++; // advance to next JP
|
||
|
BitMap >>= 1;
|
||
|
}
|
||
|
jj = PjpA - PjpB;
|
||
|
}
|
||
|
|
||
|
// Free the subexpanse:
|
||
|
|
||
|
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, ii), jj, Pjpm);
|
||
|
|
||
|
} // for each JP in BranchU
|
||
|
|
||
|
#ifdef JU_STAGED_EXP
|
||
|
|
||
|
// Allocate memory for a BranchU:
|
||
|
|
||
|
PjbuRaw = j__udyAllocJBU(Pjpm);
|
||
|
if (PjbuRaw == (Pjbu_t) NULL) return(-1);
|
||
|
Pjbu = P_JBU(PjbuRaw);
|
||
|
|
||
|
// Copy staged branch to newly allocated branch:
|
||
|
//
|
||
|
// TBD: I think this code is broken.
|
||
|
|
||
|
*Pjbu = BranchU;
|
||
|
|
||
|
#endif // JU_STAGED_EXP
|
||
|
|
||
|
// Finally free the BranchB and put the BranchU in its place:
|
||
|
|
||
|
j__udyFreeJBB(PjbbRaw, Pjpm);
|
||
|
|
||
|
Pjp->jp_Addr = (Word_t) PjbuRaw;
|
||
|
Pjp->jp_Type += cJU_JPBRANCH_U - cJU_JPBRANCH_B;
|
||
|
|
||
|
return(1);
|
||
|
|
||
|
} // j__udyCreateBranchU()
|