mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2025-04-15 14:02:32 +03:00
780 lines
27 KiB
C
780 lines
27 KiB
C
#ifndef _JUDY_PRIVATE_BRANCH_INCLUDED
|
|
#define _JUDY_PRIVATE_BRANCH_INCLUDED
|
|
// _________________
|
|
//
|
|
// 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$
|
|
//
|
|
// Header file for all Judy sources, for global but private (non-exported)
|
|
// declarations specific to branch support.
|
|
//
|
|
// See also the "Judy Shop Manual" (try judy/doc/int/JudyShopManual.*).
|
|
|
|
|
|
// ****************************************************************************
|
|
// JUDY POINTER (JP) SUPPORT
|
|
// ****************************************************************************
|
|
//
|
|
// This "rich pointer" object is pivotal to Judy execution.
|
|
//
|
|
// JP CONTAINING OTHER THAN IMMEDIATE INDEXES:
|
|
//
|
|
// If the JP points to a linear or bitmap leaf, jp_DcdPopO contains the
|
|
// Population-1 in LSbs and Decode (Dcd) bytes in the MSBs. (In practice the
|
|
// Decode bits are masked off while accessing the Pop0 bits.)
|
|
//
|
|
// The Decode Size, the number of Dcd bytes available, is encoded in jpo_Type.
|
|
// It can also be thought of as the number of states "skipped" in the SM, where
|
|
// each state decodes 8 bits = 1 byte.
|
|
//
|
|
// TBD: Dont need two structures, except possibly to force jp_Type to highest
|
|
// address!
|
|
//
|
|
// Note: The jpo_u union is not required by HP-UX or Linux but Win32 because
|
|
// the cl.exe compiler otherwise refuses to pack a bitfield (DcdPopO) with
|
|
// anything else, even with the -Zp option. This is pretty ugly, but
|
|
// fortunately portable, and its all hide-able by macros (see below).
|
|
|
|
typedef struct J_UDY_POINTER_OTHERS // JPO.
|
|
{
|
|
Word_t j_po_Addr; // first word: Pjp_t, Word_t, etc.
|
|
union {
|
|
// Word_t j_po_DcdPop0:cJU_BITSPERWORD-cJU_BITSPERBYTE;
|
|
uint8_t j_po_DcdP0[sizeof(Word_t) - 1];
|
|
uint8_t j_po_Bytes[sizeof(Word_t)]; // last byte = jp_Type.
|
|
} jpo_u;
|
|
} jpo_t;
|
|
|
|
|
|
// JP CONTAINING IMMEDIATE INDEXES:
|
|
//
|
|
// j_pi_1Index[] plus j_pi_LIndex[] together hold as many N-byte (1..3-byte
|
|
// [1..7-byte]) Indexes as will fit in sizeof(jpi_t) less 1 byte for j_pi_Type
|
|
// (that is, 7..1 [15..1] Indexes).
|
|
//
|
|
// For Judy1, j_pi_1Index[] is used and j_pi_LIndex[] is not used.
|
|
// For JudyL, j_pi_LIndex[] is used and j_pi_1Index[] is not used.
|
|
//
|
|
// Note: Actually when Pop1 = 1, jpi_t is not used, and the least bytes of the
|
|
// single Index are stored in j_po_DcdPopO, for both Judy1 and JudyL, so for
|
|
// JudyL the j_po_Addr field can hold the target value.
|
|
//
|
|
// TBD: Revise this structure to not overload j_po_DcdPopO this way? The
|
|
// current arrangement works, its just confusing.
|
|
|
|
typedef struct _JUDY_POINTER_IMMED // JPI.
|
|
{
|
|
uint8_t j_pi_1Index[sizeof(Word_t)]; // see above.
|
|
uint8_t j_pi_LIndex[sizeof(Word_t) - 1]; // see above.
|
|
uint8_t j_pi_Type; // JP type, 1 of cJ*_JPIMMED*.
|
|
} jpi_t;
|
|
|
|
|
|
// UNION OF JP TYPES:
|
|
//
|
|
// A branch is an array of cJU_BRANCHUNUMJPS (256) of this object, or an
|
|
// alternate data type such as: A linear branch which is a list of 2..7 JPs,
|
|
// or a bitmap branch which contains 8 lists of 0..32 JPs. JPs reside only in
|
|
// branches of a Judy SM.
|
|
|
|
typedef union J_UDY_POINTER // JP.
|
|
{
|
|
jpo_t j_po; // other than immediate indexes.
|
|
jpi_t j_pi; // immediate indexes.
|
|
} jp_t, *Pjp_t;
|
|
|
|
// For coding convenience:
|
|
//
|
|
// Note, jp_Type has the same bits in jpo_t and jpi_t.
|
|
|
|
#define jp_1Index j_pi.j_pi_1Index // for storing Indexes in first word.
|
|
#define jp_LIndex j_pi.j_pi_LIndex // for storing Indexes in second word.
|
|
#define jp_Addr j_po.j_po_Addr
|
|
//#define jp_DcdPop0 j_po.jpo_u.j_po_DcdPop0
|
|
#define jp_Type j_po.jpo_u.j_po_Bytes[sizeof(Word_t) - 1]
|
|
#define jp_DcdP0 j_po.jpo_u.j_po_DcdP0
|
|
|
|
|
|
// ****************************************************************************
|
|
// JUDY POINTER (JP) -- RELATED MACROS AND CONSTANTS
|
|
// ****************************************************************************
|
|
|
|
// EXTRACT VALUES FROM JP:
|
|
//
|
|
// Masks for the bytes in the Dcd and Pop0 parts of jp_DcdPopO:
|
|
//
|
|
// cJU_DCDMASK() consists of a mask that excludes the (LSb) Pop0 bytes and
|
|
// also, just to be safe, the top byte of the word, since jp_DcdPopO is 1 byte
|
|
// less than a full word.
|
|
//
|
|
// Note: These are constant macros (cJU) because cPopBytes should be a
|
|
// constant. Also note cPopBytes == state in the SM.
|
|
|
|
#define cJU_POP0MASK(cPopBytes) JU_LEASTBYTESMASK(cPopBytes)
|
|
|
|
#define cJU_DCDMASK(cPopBytes) \
|
|
((cJU_ALLONES >> cJU_BITSPERBYTE) & (~cJU_POP0MASK(cPopBytes)))
|
|
|
|
// Mask off the high byte from INDEX to it can be compared to DcdPopO:
|
|
|
|
#define JU_TRIMTODCDSIZE(INDEX) ((cJU_ALLONES >> cJU_BITSPERBYTE) & (INDEX))
|
|
|
|
// Get from jp_DcdPopO the Pop0 for various branch JP Types:
|
|
//
|
|
// Note: There are no simple macros for cJU_BRANCH* Types because their
|
|
// populations must be added up and dont reside in an already-calculated
|
|
// place.
|
|
|
|
#define JU_JPBRANCH_POP0(PJP,cPopBytes) \
|
|
(JU_JPDCDPOP0(PJP) & cJU_POP0MASK(cPopBytes))
|
|
|
|
// METHOD FOR DETERMINING IF OBJECTS HAVE ROOM TO GROW:
|
|
//
|
|
// J__U_GROWCK() is a generic method to determine if an object can grow in
|
|
// place, based on whether the next population size (one more) would use the
|
|
// same space.
|
|
|
|
#define J__U_GROWCK(POP1,MAXPOP1,POPTOWORDS) \
|
|
(((POP1) != (MAXPOP1)) && (POPTOWORDS[POP1] == POPTOWORDS[(POP1) + 1]))
|
|
|
|
#define JU_BRANCHBJPGROWINPLACE(NumJPs) \
|
|
J__U_GROWCK(NumJPs, cJU_BITSPERSUBEXPB, j__U_BranchBJPPopToWords)
|
|
|
|
|
|
// DETERMINE IF AN INDEX IS (NOT) IN A JPS EXPANSE:
|
|
|
|
#define JU_DCDNOTMATCHINDEX(INDEX,PJP,POP0BYTES) \
|
|
(((INDEX) ^ JU_JPDCDPOP0(PJP)) & cJU_DCDMASK(POP0BYTES))
|
|
|
|
|
|
// NUMBER OF JPs IN AN UNCOMPRESSED BRANCH:
|
|
//
|
|
// An uncompressed branch is simply an array of 256 Judy Pointers (JPs). It is
|
|
// a minimum cacheline fill object. Define it here before its first needed.
|
|
|
|
#define cJU_BRANCHUNUMJPS cJU_SUBEXPPERSTATE
|
|
|
|
|
|
// ****************************************************************************
|
|
// JUDY BRANCH LINEAR (JBL) SUPPORT
|
|
// ****************************************************************************
|
|
//
|
|
// A linear branch is a way of compressing empty expanses (null JPs) out of an
|
|
// uncompressed 256-way branch, when the number of populated expanses is so
|
|
// small that even a bitmap branch is excessive.
|
|
//
|
|
// The maximum number of JPs in a Judy linear branch:
|
|
//
|
|
// Note: This number results in a 1-cacheline sized structure. Previous
|
|
// versions had a larger struct so a linear branch didnt become a bitmap
|
|
// branch until the memory consumed was even, but for speed, its better to
|
|
// switch "sooner" and keep a linear branch fast.
|
|
|
|
#define cJU_BRANCHLMAXJPS 7
|
|
|
|
|
|
// LINEAR BRANCH STRUCT:
|
|
//
|
|
// 1-byte count, followed by array of byte-sized expanses, followed by JPs.
|
|
|
|
typedef struct J__UDY_BRANCH_LINEAR
|
|
{
|
|
uint8_t jbl_NumJPs; // num of JPs (Pjp_t), 1..N.
|
|
uint8_t jbl_Expanse[cJU_BRANCHLMAXJPS]; // 1..7 MSbs of pop exps.
|
|
jp_t jbl_jp [cJU_BRANCHLMAXJPS]; // JPs for populated exps.
|
|
} jbl_t, * Pjbl_t;
|
|
|
|
|
|
// ****************************************************************************
|
|
// JUDY BRANCH BITMAP (JBB) SUPPORT
|
|
// ****************************************************************************
|
|
//
|
|
// A bitmap branch is a way of compressing empty expanses (null JPs) out of
|
|
// uncompressed 256-way branch. This costs 1 additional cache line fill, but
|
|
// can save a lot of memory when it matters most, near the leaves, and
|
|
// typically there will be only one at most in the path to any Index (leaf).
|
|
//
|
|
// The bitmap indicates which of the cJU_BRANCHUNUMJPS (256) JPs in the branch
|
|
// are NOT null, that is, their expanses are populated. The jbb_t also
|
|
// contains N pointers to "mini" Judy branches ("subexpanses") of up to M JPs
|
|
// each (see BITMAP_BRANCHMxN, for example, BITMAP_BRANCH32x8), where M x N =
|
|
// cJU_BRANCHUNUMJPS. These are dynamically allocated and never contain
|
|
// cJ*_JPNULL* jp_Types. An empty subexpanse is represented by no bit sets in
|
|
// the corresponding subexpanse bitmap, in which case the corresponding
|
|
// jbbs_Pjp pointers value is unused.
|
|
//
|
|
// Note that the number of valid JPs in each 1-of-N subexpanses is determined
|
|
// by POPULATION rather than by EXPANSE -- the desired outcome to save memory
|
|
// when near the leaves. Note that the memory required for 185 JPs is about as
|
|
// much as an uncompressed 256-way branch, therefore 184 is set as the maximum.
|
|
// However, it is expected that a conversion to an uncompressed 256-way branch
|
|
// will normally take place before this limit is reached for other reasons,
|
|
// such as improving performance when the "wasted" memory is well amortized by
|
|
// the population under the branch, preserving an acceptable overall
|
|
// bytes/Index in the Judy array.
|
|
//
|
|
// The number of pointers to arrays of JPs in the Judy bitmap branch:
|
|
//
|
|
// Note: The numbers below are the same in both 32 and 64 bit systems.
|
|
|
|
#define cJU_BRANCHBMAXJPS 184 // maximum JPs for bitmap branches.
|
|
|
|
// Convenience wrappers for referencing BranchB bitmaps or JP subarray
|
|
// pointers:
|
|
//
|
|
// Note: JU_JBB_PJP produces a "raw" memory address that must pass through
|
|
// P_JP before use, except when freeing memory:
|
|
|
|
#define JU_JBB_BITMAP(Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Bitmap)
|
|
#define JU_JBB_PJP( Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Pjp)
|
|
|
|
#define JU_SUBEXPB(Digit) (((Digit) / cJU_BITSPERSUBEXPB) & (cJU_NUMSUBEXPB-1))
|
|
|
|
#define JU_BITMAPTESTB(Pjbb, Index) \
|
|
(JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) & JU_BITPOSMASKB(Index))
|
|
|
|
#define JU_BITMAPSETB(Pjbb, Index) \
|
|
(JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) |= JU_BITPOSMASKB(Index))
|
|
|
|
// Note: JU_BITMAPCLEARB is not defined because the code does it a faster way.
|
|
|
|
typedef struct J__UDY_BRANCH_BITMAP_SUBEXPANSE
|
|
{
|
|
BITMAPB_t jbbs_Bitmap;
|
|
Pjp_t jbbs_Pjp;
|
|
|
|
} jbbs_t;
|
|
|
|
typedef struct J__UDY_BRANCH_BITMAP
|
|
{
|
|
jbbs_t jbb_jbbs [cJU_NUMSUBEXPB];
|
|
#ifdef SUBEXPCOUNTS
|
|
Word_t jbb_subPop1[cJU_NUMSUBEXPB];
|
|
#endif
|
|
} jbb_t, * Pjbb_t;
|
|
|
|
#define JU_BRANCHJP_NUMJPSTOWORDS(NumJPs) (j__U_BranchBJPPopToWords[NumJPs])
|
|
|
|
#ifdef SUBEXPCOUNTS
|
|
#define cJU_NUMSUBEXPU 16 // number of subexpanse counts.
|
|
#endif
|
|
|
|
|
|
// ****************************************************************************
|
|
// JUDY BRANCH UNCOMPRESSED (JBU) SUPPORT
|
|
// ****************************************************************************
|
|
|
|
// Convenience wrapper for referencing BranchU JPs:
|
|
//
|
|
// Note: This produces a non-"raw" address already passed through P_JBU().
|
|
|
|
#define JU_JBU_PJP(Pjp,Index,Level) \
|
|
(&((P_JBU((Pjp)->jp_Addr))->jbu_jp[JU_DIGITATSTATE(Index, Level)]))
|
|
#define JU_JBU_PJP0(Pjp) \
|
|
(&((P_JBU((Pjp)->jp_Addr))->jbu_jp[0]))
|
|
|
|
typedef struct J__UDY_BRANCH_UNCOMPRESSED
|
|
{
|
|
jp_t jbu_jp [cJU_BRANCHUNUMJPS]; // JPs for populated exp.
|
|
#ifdef SUBEXPCOUNTS
|
|
Word_t jbu_subPop1[cJU_NUMSUBEXPU];
|
|
#endif
|
|
} jbu_t, * Pjbu_t;
|
|
|
|
|
|
// ****************************************************************************
|
|
// OTHER SUPPORT FOR JUDY STATE MACHINES (SMs)
|
|
// ****************************************************************************
|
|
|
|
// OBJECT SIZES IN WORDS:
|
|
//
|
|
// Word_ts per various JudyL structures that have constant sizes.
|
|
// cJU_WORDSPERJP should always be 2; this is fundamental to the Judy
|
|
// structures.
|
|
|
|
#define cJU_WORDSPERJP (sizeof(jp_t) / cJU_BYTESPERWORD)
|
|
#define cJU_WORDSPERCL (cJU_BYTESPERCL / cJU_BYTESPERWORD)
|
|
|
|
|
|
// OPPORTUNISTIC UNCOMPRESSION:
|
|
//
|
|
// Define populations at which a BranchL or BranchB must convert to BranchU.
|
|
// Earlier conversion is possible with good memory efficiency -- see below.
|
|
|
|
#ifndef NO_BRANCHU
|
|
|
|
// Max population below BranchL, then convert to BranchU:
|
|
|
|
#define JU_BRANCHL_MAX_POP 1000
|
|
|
|
// Minimum global population increment before next conversion of a BranchB to a
|
|
// BranchU:
|
|
//
|
|
// This is was done to allow malloc() to coalesce memory before the next big
|
|
// (~512 words) allocation.
|
|
|
|
#define JU_BTOU_POP_INCREMENT 300
|
|
|
|
// Min/max population below BranchB, then convert to BranchU:
|
|
|
|
#define JU_BRANCHB_MIN_POP 135
|
|
#define JU_BRANCHB_MAX_POP 750
|
|
|
|
#else // NO_BRANCHU
|
|
|
|
// These are set up to have conservative conversion schedules to BranchU:
|
|
|
|
#define JU_BRANCHL_MAX_POP (-1UL)
|
|
#define JU_BTOU_POP_INCREMENT 300
|
|
#define JU_BRANCHB_MIN_POP 1000
|
|
#define JU_BRANCHB_MAX_POP (-1UL)
|
|
|
|
#endif // NO_BRANCHU
|
|
|
|
|
|
// MISCELLANEOUS MACROS:
|
|
|
|
// Get N most significant bits from the shifted Index word:
|
|
//
|
|
// As Index words are decoded, they are shifted left so only relevant,
|
|
// undecoded Index bits remain.
|
|
|
|
#define JU_BITSFROMSFTIDX(SFTIDX, N) ((SFTIDX) >> (cJU_BITSPERWORD - (N)))
|
|
|
|
// TBD: I have my doubts about the necessity of these macros (dlb):
|
|
|
|
// Produce 1-digit mask at specified state:
|
|
|
|
#define cJU_MASKATSTATE(State) (0xffL << (((State) - 1) * cJU_BITSPERBYTE))
|
|
|
|
// Get byte (digit) from Index at the specified state, right justified:
|
|
//
|
|
// Note: State must be 1..cJU_ROOTSTATE, and Digits must be 1..(cJU_ROOTSTATE
|
|
// - 1), but theres no way to assert these within an expression.
|
|
|
|
#define JU_DIGITATSTATE(Index,cState) \
|
|
((uint8_t)((Index) >> (((cState) - 1) * cJU_BITSPERBYTE)))
|
|
|
|
// Similarly, place byte (digit) at correct position for the specified state:
|
|
//
|
|
// Note: Cast digit to a Word_t first so there are no complaints or problems
|
|
// about shifting it more than 32 bits on a 64-bit system, say, when it is a
|
|
// uint8_t from jbl_Expanse[]. (Believe it or not, the C standard says to
|
|
// promote an unsigned char to a signed int; -Ac does not do this, but -Ae
|
|
// does.)
|
|
//
|
|
// Also, to make lint happy, cast the whole result again because apparently
|
|
// shifting a Word_t does not result in a Word_t!
|
|
|
|
#define JU_DIGITTOSTATE(Digit,cState) \
|
|
((Word_t) (((Word_t) (Digit)) << (((cState) - 1) * cJU_BITSPERBYTE)))
|
|
|
|
#endif // ! _JUDY_PRIVATE_BRANCH_INCLUDED
|
|
|
|
|
|
#ifdef TEST_INSDEL
|
|
|
|
// ****************************************************************************
|
|
// TEST CODE FOR INSERT/DELETE MACROS
|
|
// ****************************************************************************
|
|
//
|
|
// To use this, compile a temporary *.c file containing:
|
|
//
|
|
// #define DEBUG
|
|
// #define JUDY_ASSERT
|
|
// #define TEST_INSDEL
|
|
// #include "JudyPrivate.h"
|
|
// #include "JudyPrivateBranch.h"
|
|
//
|
|
// Use a command like this: cc -Ae +DD64 -I. -I JudyCommon -o t t.c
|
|
// For best results, include +DD64 on a 64-bit system.
|
|
//
|
|
// This test code exercises some tricky macros, but the output must be studied
|
|
// manually to verify it. Assume that for even-index testing, whole words
|
|
// (Word_t) suffices.
|
|
|
|
#include <stdio.h>
|
|
|
|
#define INDEXES 3 // in each array.
|
|
|
|
|
|
// ****************************************************************************
|
|
// I N I T
|
|
//
|
|
// Set up variables for next test. See usage.
|
|
|
|
FUNCTION void Init (
|
|
int base,
|
|
PWord_t PeIndex,
|
|
PWord_t PoIndex,
|
|
PWord_t Peleaf, // always whole words.
|
|
#ifndef JU_64BIT
|
|
uint8_t * Poleaf3)
|
|
#else
|
|
uint8_t * Poleaf3,
|
|
uint8_t * Poleaf5,
|
|
uint8_t * Poleaf6,
|
|
uint8_t * Poleaf7)
|
|
#endif
|
|
{
|
|
int offset;
|
|
|
|
*PeIndex = 99;
|
|
|
|
for (offset = 0; offset <= INDEXES; ++offset)
|
|
Peleaf[offset] = base + offset;
|
|
|
|
for (offset = 0; offset < (INDEXES + 1) * 3; ++offset)
|
|
Poleaf3[offset] = base + offset;
|
|
|
|
#ifndef JU_64BIT
|
|
*PoIndex = (91 << 24) | (92 << 16) | (93 << 8) | 94;
|
|
#else
|
|
|
|
*PoIndex = (91L << 56) | (92L << 48) | (93L << 40) | (94L << 32)
|
|
| (95L << 24) | (96L << 16) | (97L << 8) | 98L;
|
|
|
|
for (offset = 0; offset < (INDEXES + 1) * 5; ++offset)
|
|
Poleaf5[offset] = base + offset;
|
|
|
|
for (offset = 0; offset < (INDEXES + 1) * 6; ++offset)
|
|
Poleaf6[offset] = base + offset;
|
|
|
|
for (offset = 0; offset < (INDEXES + 1) * 7; ++offset)
|
|
Poleaf7[offset] = base + offset;
|
|
#endif
|
|
|
|
} // Init()
|
|
|
|
|
|
// ****************************************************************************
|
|
// P R I N T L E A F
|
|
//
|
|
// Print the byte values in a leaf.
|
|
|
|
FUNCTION void PrintLeaf (
|
|
char * Label, // for output.
|
|
int IOffset, // insertion offset in array.
|
|
int Indsize, // index size in bytes.
|
|
uint8_t * PLeaf) // array of Index bytes.
|
|
{
|
|
int offset; // in PLeaf.
|
|
int byte; // in one word.
|
|
|
|
(void) printf("%s %u: ", Label, IOffset);
|
|
|
|
for (offset = 0; offset <= INDEXES; ++offset)
|
|
{
|
|
for (byte = 0; byte < Indsize; ++byte)
|
|
(void) printf("%2d", PLeaf[(offset * Indsize) + byte]);
|
|
|
|
(void) printf(" ");
|
|
}
|
|
|
|
(void) printf("\n");
|
|
|
|
} // PrintLeaf()
|
|
|
|
|
|
// ****************************************************************************
|
|
// M A I N
|
|
//
|
|
// Test program.
|
|
|
|
FUNCTION main()
|
|
{
|
|
Word_t eIndex; // even, to insert.
|
|
Word_t oIndex; // odd, to insert.
|
|
Word_t eleaf [ INDEXES + 1]; // even leaf, index size 4.
|
|
uint8_t oleaf3[(INDEXES + 1) * 3]; // odd leaf, index size 3.
|
|
#ifdef JU_64BIT
|
|
uint8_t oleaf5[(INDEXES + 1) * 5]; // odd leaf, index size 5.
|
|
uint8_t oleaf6[(INDEXES + 1) * 6]; // odd leaf, index size 6.
|
|
uint8_t oleaf7[(INDEXES + 1) * 7]; // odd leaf, index size 7.
|
|
#endif
|
|
Word_t eleaf_2 [ INDEXES + 1]; // same, but second arrays:
|
|
uint8_t oleaf3_2[(INDEXES + 1) * 3];
|
|
#ifdef JU_64BIT
|
|
uint8_t oleaf5_2[(INDEXES + 1) * 5];
|
|
uint8_t oleaf6_2[(INDEXES + 1) * 6];
|
|
uint8_t oleaf7_2[(INDEXES + 1) * 7];
|
|
#endif
|
|
int ioffset; // index insertion offset.
|
|
|
|
#ifndef JU_64BIT
|
|
#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3)
|
|
#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2)
|
|
#else
|
|
#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3, \
|
|
oleaf5, oleaf6, oleaf7)
|
|
#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2, \
|
|
oleaf5_2, oleaf6_2, oleaf7_2)
|
|
#endif
|
|
|
|
#define WSIZE sizeof (Word_t) // shorthand.
|
|
|
|
#ifdef PRINTALL // to turn on "noisy" printouts.
|
|
#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
|
|
PrintLeaf(Label,IOffset,Indsize,PLeaf)
|
|
#else
|
|
#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
|
|
if (ioffset == 0) \
|
|
PrintLeaf(Label,IOffset,Indsize,PLeaf)
|
|
#endif
|
|
|
|
(void) printf(
|
|
"In each case, tests operate on an initial array of %d indexes. Even-index\n"
|
|
"tests set index values to 0,1,2...; odd-index tests set byte values to\n"
|
|
"0,1,2... Inserted indexes have a value of 99 or else byte values 91,92,...\n",
|
|
INDEXES);
|
|
|
|
(void) puts("\nJU_INSERTINPLACE():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
JU_INSERTINPLACE(eleaf, INDEXES, ioffset, eIndex);
|
|
PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTINPLACE3():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 3, oleaf3);
|
|
JU_INSERTINPLACE3(oleaf3, INDEXES, ioffset, oIndex);
|
|
PrintLeaf("After ", ioffset, 3, oleaf3);
|
|
}
|
|
|
|
#ifdef JU_64BIT
|
|
(void) puts("\nJU_INSERTINPLACE5():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 5, oleaf5);
|
|
JU_INSERTINPLACE5(oleaf5, INDEXES, ioffset, oIndex);
|
|
PrintLeaf("After ", ioffset, 5, oleaf5);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTINPLACE6():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 6, oleaf6);
|
|
JU_INSERTINPLACE6(oleaf6, INDEXES, ioffset, oIndex);
|
|
PrintLeaf("After ", ioffset, 6, oleaf6);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTINPLACE7():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 7, oleaf7);
|
|
JU_INSERTINPLACE7(oleaf7, INDEXES, ioffset, oIndex);
|
|
PrintLeaf("After ", ioffset, 7, oleaf7);
|
|
}
|
|
#endif // JU_64BIT
|
|
|
|
(void) puts("\nJU_DELETEINPLACE():");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
JU_DELETEINPLACE(eleaf, INDEXES, ioffset);
|
|
PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETEINPLACE_ODD(3):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 3, oleaf3);
|
|
JU_DELETEINPLACE_ODD(oleaf3, INDEXES, ioffset, 3);
|
|
PrintLeaf("After ", ioffset, 3, oleaf3);
|
|
}
|
|
|
|
#ifdef JU_64BIT
|
|
(void) puts("\nJU_DELETEINPLACE_ODD(5):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 5, oleaf5);
|
|
JU_DELETEINPLACE_ODD(oleaf5, INDEXES, ioffset, 5);
|
|
PrintLeaf("After ", ioffset, 5, oleaf5);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETEINPLACE_ODD(6):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 6, oleaf6);
|
|
JU_DELETEINPLACE_ODD(oleaf6, INDEXES, ioffset, 6);
|
|
PrintLeaf("After ", ioffset, 6, oleaf6);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETEINPLACE_ODD(7):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT;
|
|
PRINTLEAF("Before", ioffset, 7, oleaf7);
|
|
JU_DELETEINPLACE_ODD(oleaf7, INDEXES, ioffset, 7);
|
|
PrintLeaf("After ", ioffset, 7, oleaf7);
|
|
}
|
|
#endif // JU_64BIT
|
|
|
|
(void) puts("\nJU_INSERTCOPY():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
|
JU_INSERTCOPY(eleaf_2, eleaf, INDEXES, ioffset, eIndex);
|
|
PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTCOPY3():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
|
|
PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
|
|
JU_INSERTCOPY3(oleaf3_2, oleaf3, INDEXES, ioffset, oIndex);
|
|
PRINTLEAF("After, src ", ioffset, 3, oleaf3);
|
|
PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
|
|
}
|
|
|
|
#ifdef JU_64BIT
|
|
(void) puts("\nJU_INSERTCOPY5():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
|
|
PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
|
|
JU_INSERTCOPY5(oleaf5_2, oleaf5, INDEXES, ioffset, oIndex);
|
|
PRINTLEAF("After, src ", ioffset, 5, oleaf5);
|
|
PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTCOPY6():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
|
|
PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
|
|
JU_INSERTCOPY6(oleaf6_2, oleaf6, INDEXES, ioffset, oIndex);
|
|
PRINTLEAF("After, src ", ioffset, 6, oleaf6);
|
|
PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
|
|
}
|
|
|
|
(void) puts("\nJU_INSERTCOPY7():");
|
|
|
|
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
|
|
PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
|
|
JU_INSERTCOPY7(oleaf7_2, oleaf7, INDEXES, ioffset, oIndex);
|
|
PRINTLEAF("After, src ", ioffset, 7, oleaf7);
|
|
PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
|
|
}
|
|
#endif // JU_64BIT
|
|
|
|
(void) puts("\nJU_DELETECOPY():");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
|
JU_DELETECOPY(eleaf_2, eleaf, INDEXES, ioffset, ignore);
|
|
PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
|
PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETECOPY_ODD(3):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
|
|
PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
|
|
JU_DELETECOPY_ODD(oleaf3_2, oleaf3, INDEXES, ioffset, 3);
|
|
PRINTLEAF("After, src ", ioffset, 3, oleaf3);
|
|
PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
|
|
}
|
|
|
|
#ifdef JU_64BIT
|
|
(void) puts("\nJU_DELETECOPY_ODD(5):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
|
|
PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
|
|
JU_DELETECOPY_ODD(oleaf5_2, oleaf5, INDEXES, ioffset, 5);
|
|
PRINTLEAF("After, src ", ioffset, 5, oleaf5);
|
|
PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETECOPY_ODD(6):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
|
|
PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
|
|
JU_DELETECOPY_ODD(oleaf6_2, oleaf6, INDEXES, ioffset, 6);
|
|
PRINTLEAF("After, src ", ioffset, 6, oleaf6);
|
|
PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
|
|
}
|
|
|
|
(void) puts("\nJU_DELETECOPY_ODD(7):");
|
|
|
|
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
|
{
|
|
INIT2;
|
|
PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
|
|
PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
|
|
JU_DELETECOPY_ODD(oleaf7_2, oleaf7, INDEXES, ioffset, 7);
|
|
PRINTLEAF("After, src ", ioffset, 7, oleaf7);
|
|
PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
|
|
}
|
|
#endif // JU_64BIT
|
|
|
|
return(0);
|
|
|
|
} // main()
|
|
|
|
#endif // TEST_INSDEL
|