mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2025-04-15 14:02:32 +03:00
136 lines
4.4 KiB
C
136 lines
4.4 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$
|
|
|
|
// BranchL insertion 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"
|
|
|
|
extern int j__udyCreateBranchL(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
|
|
|
|
|
|
// ****************************************************************************
|
|
// __ J U D Y I N S E R T B R A N C H
|
|
//
|
|
// Insert 2-element BranchL in between Pjp and Pjp->jp_Addr.
|
|
//
|
|
// Return -1 if out of memory, otherwise return 1.
|
|
|
|
FUNCTION int j__udyInsertBranch(
|
|
Pjp_t Pjp, // JP containing narrow pointer.
|
|
Word_t Index, // outlier to Pjp.
|
|
Word_t BranchLevel, // of what JP points to, mapped from JP type.
|
|
Pjpm_t Pjpm) // for global accounting.
|
|
{
|
|
jp_t JP2 [2];
|
|
jp_t JP;
|
|
Pjp_t PjpNull;
|
|
Word_t XorExp;
|
|
Word_t Inew, Iold;
|
|
Word_t DCDMask; // initially for original BranchLevel.
|
|
int Ret;
|
|
uint8_t Exp2[2];
|
|
uint8_t DecodeByteN, DecodeByteO;
|
|
|
|
// Get the current mask for the DCD digits:
|
|
|
|
DCDMask = cJU_DCDMASK(BranchLevel);
|
|
|
|
// Obtain Dcd bits that differ between Index and JP, shifted so the
|
|
// digit for BranchLevel is the LSB:
|
|
|
|
XorExp = ((Index ^ JU_JPDCDPOP0(Pjp)) & (cJU_ALLONES >> cJU_BITSPERBYTE))
|
|
>> (BranchLevel * cJU_BITSPERBYTE);
|
|
assert(XorExp); // Index must be an outlier.
|
|
|
|
// Count levels between object under narrow pointer and the level at which
|
|
// the outlier diverges from it, which is always at least initial
|
|
// BranchLevel + 1, to end up with the level (JP type) at which to insert
|
|
// the new intervening BranchL:
|
|
|
|
do { ++BranchLevel; } while ((XorExp >>= cJU_BITSPERBYTE));
|
|
assert((BranchLevel > 1) && (BranchLevel < cJU_ROOTSTATE));
|
|
|
|
// Get the MSB (highest digit) that differs between the old expanse and
|
|
// the new Index to insert:
|
|
|
|
DecodeByteO = JU_DIGITATSTATE(JU_JPDCDPOP0(Pjp), BranchLevel);
|
|
DecodeByteN = JU_DIGITATSTATE(Index, BranchLevel);
|
|
|
|
assert(DecodeByteO != DecodeByteN);
|
|
|
|
// Determine sorted order for old expanse and new Index digits:
|
|
|
|
if (DecodeByteN > DecodeByteO) { Iold = 0; Inew = 1; }
|
|
else { Iold = 1; Inew = 0; }
|
|
|
|
// Copy old JP into staging area for new Branch
|
|
JP2 [Iold] = *Pjp;
|
|
Exp2[Iold] = DecodeByteO;
|
|
Exp2[Inew] = DecodeByteN;
|
|
|
|
// Create a 2 Expanse Linear branch
|
|
//
|
|
// Note: Pjp->jp_Addr is set by j__udyCreateBranchL()
|
|
|
|
Ret = j__udyCreateBranchL(Pjp, JP2, Exp2, 2, Pjpm);
|
|
if (Ret == -1) return(-1);
|
|
|
|
// Get Pjp to the NULL of where to do insert
|
|
PjpNull = ((P_JBL(Pjp->jp_Addr))->jbl_jp) + Inew;
|
|
|
|
// Convert to a cJU_JPIMMED_*_01 at the correct level:
|
|
// Build JP and set type below to: cJU_JPIMMED_X_01
|
|
JU_JPSETADT(PjpNull, 0, Index, cJU_JPIMMED_1_01 - 2 + BranchLevel);
|
|
|
|
// Return pointer to Value area in cJU_JPIMMED_X_01
|
|
JUDYLCODE(Pjpm->jpm_PValue = (Pjv_t) PjpNull;)
|
|
|
|
// The old JP now points to a BranchL that is at higher level. Therefore
|
|
// it contains excess DCD bits (in the least significant position) that
|
|
// must be removed (zeroed); that is, they become part of the Pop0
|
|
// subfield. Note that the remaining (lower) bytes in the Pop0 field do
|
|
// not change.
|
|
//
|
|
// Take from the old DCDMask, which went "down" to a lower BranchLevel,
|
|
// and zero any high bits that are still in the mask at the new, higher
|
|
// BranchLevel; then use this mask to zero the bits in jp_DcdPopO:
|
|
|
|
// Set old JP to a BranchL at correct level
|
|
|
|
Pjp->jp_Type = cJU_JPBRANCH_L2 - 2 + BranchLevel;
|
|
DCDMask ^= cJU_DCDMASK(BranchLevel);
|
|
DCDMask = ~DCDMask & JU_JPDCDPOP0(Pjp);
|
|
JP = *Pjp;
|
|
JU_JPSETADT(Pjp, JP.jp_Addr, DCDMask, JP.jp_Type);
|
|
|
|
return(1);
|
|
|
|
} // j__udyInsertBranch()
|