@cryptotaxi247 / netdata-1 / commits / 014c9f325

include Judy into our source tree (#13362)

Timotej S committed Jul 22, 2022 at 16:55 UTC 014c9f3259264f54d939958449477504dff6133e
54 files changed +26708 -239
.gitignore
+4
@@ -228,3 +228,7 @@ Session.*.vim
228
229 # Jupyter notebook checkpoints
230 .ipynb_checkpoints
231 +
232 +# Judy stuff
233 +JudyLTables.c
234 +judyltablesgen
.travis.yml
+1 -1
@@ -17,7 +17,7 @@ before_install:
17 # Install dependencies for all, once
18 #
19 install:
20 - - sudo apt-get install -y libuv1-dev liblz4-dev libjudy-dev libcap2-bin zlib1g-dev uuid-dev fakeroot libipmimonitoring-dev libmnl-dev libnetfilter-acct-dev gnupg python3-pip
20 + - sudo apt-get install -y libuv1-dev liblz4-dev libcap2-bin zlib1g-dev uuid-dev fakeroot libipmimonitoring-dev libmnl-dev libnetfilter-acct-dev gnupg python3-pip
21 - sudo pip3 install git-semver==0.3.2 # 11/Sep/2019: git-semver tip was broken, so we had to force last good run of it
22 - source tests/installer/slack.sh
23 - export NOTIF_CHANNEL="automation-beta"
CMakeLists.txt
+83 -14
@@ -102,20 +102,7 @@ set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${LIBLZ4_INCLUDE_
102 # -----------------------------------------------------------------------------
103 # Judy General purpose dynamic array
104
105 -# pkgconfig not working in Ubuntu, why? upstream package broken?
106 -#pkg_check_modules(JUDY REQUIRED Judy)
107 -#set(NETDATA_COMMON_CFLAGS ${NETDATA_COMMON_CFLAGS} ${JUDY_CFLAGS_OTHER})
108 -#set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} ${JUDY_LIBRARIES})
109 -#set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${JUDY_INCLUDE_DIRS})
110 -set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} "-lJudy")
111 -set(CMAKE_REQUIRED_LIBRARIES "Judy")
112 -include(CheckSymbolExists)
113 -check_symbol_exists("JudyLLast" "Judy.h" HAVE_JUDY)
114 -IF(HAVE_JUDY)
115 - message(STATUS "Judy library found")
116 -ELSE()
117 - message( FATAL_ERROR "libJudy required but not found. Try installing 'libjudy-dev' or 'Judy-devel'." )
118 -ENDIF()
105 +set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} judy)
106
107 # -----------------------------------------------------------------------------
108 # OpenSSL Cryptography and SSL/TLS Toolkit
@@ -362,6 +349,88 @@ ELSE()
349 set(ENABLE_ML False)
350 ENDIF()
351
352 +set(LIBJUDY_SOURCES
353 + libnetdata/libjudy/src/Judy.h
354 + libnetdata/libjudy/src/JudyCommon/JudyMalloc.c
355 + libnetdata/libjudy/src/JudyCommon/JudyPrivate.h
356 + libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h
357 + libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h
358 + libnetdata/libjudy/src/JudyL/JudyL.h
359 + libnetdata/libjudy/src/JudyL/JudyLByCount.c
360 + libnetdata/libjudy/src/JudyL/JudyLCascade.c
361 + libnetdata/libjudy/src/JudyL/JudyLCount.c
362 + libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c
363 + libnetdata/libjudy/src/JudyL/JudyLDecascade.c
364 + libnetdata/libjudy/src/JudyL/JudyLDel.c
365 + libnetdata/libjudy/src/JudyL/JudyLFirst.c
366 + libnetdata/libjudy/src/JudyL/JudyLFreeArray.c
367 + libnetdata/libjudy/src/JudyL/j__udyLGet.c
368 + libnetdata/libjudy/src/JudyL/JudyLGet.c
369 + libnetdata/libjudy/src/JudyL/JudyLInsArray.c
370 + libnetdata/libjudy/src/JudyL/JudyLIns.c
371 + libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c
372 + libnetdata/libjudy/src/JudyL/JudyLMallocIF.c
373 + libnetdata/libjudy/src/JudyL/JudyLMemActive.c
374 + libnetdata/libjudy/src/JudyL/JudyLMemUsed.c
375 + libnetdata/libjudy/src/JudyL/JudyLNext.c
376 + libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c
377 + libnetdata/libjudy/src/JudyL/JudyLPrev.c
378 + libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c
379 + JudyLTables.c
380 + libnetdata/libjudy/src/JudyHS/JudyHS.c)
381 +
382 +ADD_LIBRARY(judy STATIC
383 + ${LIBJUDY_SOURCES})
384 +
385 +ADD_EXECUTABLE(judyltablesgen
386 + libnetdata/libjudy/src/JudyL/JudyLTablesGen.c)
387 +
388 +target_include_directories(judyltablesgen PUBLIC
389 + libnetdata/libjudy/src
390 + libnetdata/libjudy/src/JudyCommon)
391 +
392 +target_compile_options(judyltablesgen PUBLIC
393 + -Wno-format
394 + -Wno-format-security)
395 +
396 +include_directories(BEFORE ${CMAKE_SOURCE_DIR}/libnetdata/libjudy/src)
397 +
398 +target_compile_definitions(judyltablesgen PUBLIC
399 + JU_64BIT
400 + JUDYL)
401 +
402 +add_custom_command(
403 + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/JudyLTables.c
404 + COMMAND judyltablesgen
405 + DEPENDS judyltablesgen
406 + )
407 +
408 +target_include_directories(judy PUBLIC
409 + libnetdata/libjudy/src
410 + libnetdata/libjudy/src/JudyCommon)
411 +
412 +target_compile_definitions(judy PUBLIC
413 + JU_64BIT
414 + JUDYL)
415 +
416 +target_compile_options(judy PUBLIC
417 + -Wno-sign-compare
418 + -Wno-implicit-fallthrough)
419 +
420 +set(LIBJUDY_PREV_FILES
421 + libnetdata/libjudy/src/JudyL/JudyLPrev.c
422 + libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c)
423 +
424 +set(LIBJUDY_NEXT_FILES
425 + libnetdata/libjudy/src/JudyL/JudyLNext.c
426 + libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c)
427 +
428 +set_source_files_properties(${LIBJUDY_PREV_FILES} PROPERTIES COMPILE_OPTIONS "-DJUDYPREV")
429 +set_source_files_properties(${LIBJUDY_NEXT_FILES} PROPERTIES COMPILE_OPTIONS "-DJUDYNEXT")
430 +set_source_files_properties(libnetdata/libjudy/src/JudyL/j__udyLGet.c PROPERTIES COMPILE_OPTIONS "-DJUDYGETINLINE")
431 +set_source_files_properties(libnetdata/libjudy/src/JudyL/JudyLByCount.c PROPERTIES COMPILE_OPTIONS "-DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB")
432 +set_source_files_properties(JudyLTables.c PROPERTIES COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/libnetdata/libjudy/src/JudyL")
433 +
434 # -----------------------------------------------------------------------------
435 # netdata files
436
Makefile.am
+63 -3
@@ -61,7 +61,6 @@ dist_noinst_DATA = \
61 netdata.spec \
62 packaging/bundle-ebpf.sh \
63 packaging/bundle-ebpf-co-re.sh \
64 - packaging/bundle-judy.sh \
64 packaging/bundle-libbpf.sh \
65 packaging/check-kernel-config.sh \
66 packaging/ebpf.checksums \
@@ -75,8 +74,6 @@ dist_noinst_DATA = \
74 packaging/installer/UPDATE.md \
75 packaging/jsonc.checksums \
76 packaging/jsonc.version \
78 - packaging/judy.checksums \
79 - packaging/judy.version \
77 packaging/libbpf.checksums \
78 packaging/libbpf.version \
79 packaging/protobuf.checksums \
@@ -480,6 +477,64 @@ database/sqlite/sqlite3.$(OBJEXT) : CFLAGS += -Wno-cast-function-type
477 database/KolmogorovSmirnovDist.$(OBJEXT) : CFLAGS += -Wno-maybe-uninitialized
478
479 if ENABLE_DBENGINE
480 + noinst_LIBRARIES = libjudy.a
481 +
482 + libjudy_a_SOURCES = libnetdata/libjudy/src/Judy.h \
483 + libnetdata/libjudy/src/JudyCommon/JudyMalloc.c \
484 + libnetdata/libjudy/src/JudyCommon/JudyPrivate.h \
485 + libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h \
486 + libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h \
487 + libnetdata/libjudy/src/JudyL/JudyL.h \
488 + libnetdata/libjudy/src/JudyL/JudyLByCount.c \
489 + libnetdata/libjudy/src/JudyL/JudyLCascade.c \
490 + libnetdata/libjudy/src/JudyL/JudyLCount.c \
491 + libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c \
492 + libnetdata/libjudy/src/JudyL/JudyLDecascade.c \
493 + libnetdata/libjudy/src/JudyL/JudyLDel.c \
494 + libnetdata/libjudy/src/JudyL/JudyLFirst.c \
495 + libnetdata/libjudy/src/JudyL/JudyLFreeArray.c \
496 + libnetdata/libjudy/src/JudyL/j__udyLGet.c \
497 + libnetdata/libjudy/src/JudyL/JudyLGet.c \
498 + libnetdata/libjudy/src/JudyL/JudyLInsArray.c \
499 + libnetdata/libjudy/src/JudyL/JudyLIns.c \
500 + libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c \
501 + libnetdata/libjudy/src/JudyL/JudyLMallocIF.c \
502 + libnetdata/libjudy/src/JudyL/JudyLMemActive.c \
503 + libnetdata/libjudy/src/JudyL/JudyLMemUsed.c \
504 + libnetdata/libjudy/src/JudyL/JudyLNext.c \
505 + libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c \
506 + libnetdata/libjudy/src/JudyL/JudyLPrev.c \
507 + libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c \
508 + libnetdata/libjudy/src/JudyHS/JudyHS.c \
509 + $(NULL)
510 +
511 + nodist_libjudy_a_SOURCES = JudyLTables.c
512 +
513 + BUILT_SOURCES += JudyLTables.c
514 +
515 + CLEANFILES += JudyLTables.c
516 +
517 + libjudy_a_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
518 +
519 + libnetdata/libjudy/src/JudyL/libjudy_a-JudyLPrev.$(OBJEXT) : CFLAGS += -DJUDYPREV
520 + libnetdata/libjudy/src/JudyL/libjudy_a-JudyLPrevEmpty.$(OBJEXT) : CFLAGS += -DJUDYPREV
521 + libnetdata/libjudy/src/JudyL/libjudy_a-JudyLNext.$(OBJEXT) : CFLAGS += -DJUDYNEXT
522 + libnetdata/libjudy/src/JudyL/libjudy_a-JudyLNextEmpty.$(OBJEXT) : CFLAGS += -DJUDYNEXT
523 + libnetdata/libjudy/src/JudyL/libjudy_a-JudyLByCount.$(OBJEXT) : CFLAGS += -DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB
524 + libnetdata/libjudy/src/JudyL/libjudy_a-j__udyLGet.$(OBJEXT) : CFLAGS += -DJUDYGETINLINE
525 +
526 + noinst_PROGRAMS = judyltablesgen
527 +
528 + judyltablesgen_SOURCES = libnetdata/libjudy/src/JudyL/JudyLTablesGen.c
529 + judyltablesgen_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
530 +
531 + judyltablesgen$(EXEEXT) : CFLAGS += -Wno-format -Wno-format-security
532 +
533 +JudyLTables.c: $(abs_top_srcdir)/libnetdata/libjudy/src/JudyL/JudyLTablesGen.c $(builddir)/judyltablesgen$(EXEEXT)
534 + $(builddir)/judyltablesgen$(EXEEXT)
535 +
536 + libjudy_a-JudyLTables.$(OBJEXT) : CFLAGS += -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyL
537 +
538 RRD_PLUGIN_FILES += \
539 database/engine/rrdengine.c \
540 database/engine/rrdengine.h \
@@ -925,6 +980,11 @@ NETDATA_COMMON_LIBS = \
980 $(OPTIONAL_ATOMIC_LIBS) \
981 $(NULL)
982
983 +if ENABLE_DBENGINE
984 + NETDATA_COMMON_LIBS += libjudy.a \
985 + $(NULL)
986 +endif
987 +
988 if LINK_STATIC_JSONC
989 NETDATA_COMMON_LIBS += $(abs_top_srcdir)/externaldeps/jsonc/libjson-c.a
990 endif
configure.ac
+16 -41
@@ -42,6 +42,7 @@ AC_PROG_CXX
42 AC_PROG_INSTALL
43 PKG_PROG_PKG_CONFIG
44 AC_USE_SYSTEM_EXTENSIONS
45 +AC_PROG_RANLIB
46
47 # -----------------------------------------------------------------------------
48 # configurable options
@@ -468,45 +469,22 @@ OPTIONAL_JSONC_LIBS="${JSONC_LIBS}"
469 test "${enable_dbengine}" = "yes" -a -z "${LZ4_LIBS}" && \
470 AC_MSG_ERROR([liblz4 required but not found. Try installing 'liblz4-dev' or 'lz4-devel'.])
471
471 -
472 -AC_ARG_WITH([bundled-libJudy],
473 - [AS_HELP_STRING([--with-bundled-libJudy],[Use the bundled version of Judy library (default is system-library)])],
474 - [
475 - AC_MSG_CHECKING(for libJudy in $withval)
476 - if test -f "externaldeps/libJudy/libJudy.a" -a -f "externaldeps/libJudy/Judy.h"; then
477 - LIBS_BACKUP="${LIBS}"
478 - LIBS="externaldeps/libJudy/libJudy.a"
479 - AC_LINK_IFELSE([AC_LANG_SOURCE([[#include "externaldeps/libJudy/Judy.h"
480 - int main (int argc, char **argv) {
481 - Pvoid_t PJLArray = (Pvoid_t) NULL;
482 - Word_t * PValue;
483 - Word_t Index;
484 - JLI(PValue, PJLArray, Index);
485 - }]])],
486 - [HAVE_libJudy_a="yes"],
487 - [HAVE_libJudy_a="no"])
488 - LIBS="${LIBS_BACKUP}"
489 - JUDY_LIBS="\$(abs_top_srcdir)/externaldeps/libJudy/libJudy.a"
490 - JUDY_CFLAGS="-I \$(abs_top_srcdir)/externaldeps/libJudy"
491 - AC_MSG_RESULT([$HAVE_libJudy_a])
492 - else
493 - libjudy_dir=""
494 - HAVE_libJudy_a="no"
495 - AC_MSG_RESULT([$HAVE_libJudy_a])
496 - fi
497 - ],
498 - [HAVE_libJudy_a="no"])
499 -
500 -if test "${HAVE_libJudy_a}" = "no"; then
501 - AC_CHECK_LIB(
502 - [Judy],
503 - [JudyLIns],
504 - [JUDY_LIBS="-lJudy"]
505 - )
472 +AC_C_BIGENDIAN([],
473 + [LIBJUDY_CFLAGS="-DJU_LITTLE_ENDIAN"],
474 + [AC_MSG_ERROR([Could not find out system endiannnes])])
475 +
476 +AC_CHECK_SIZEOF(void *)
477 +if test "$ac_cv_sizeof_void_p" = 8; then
478 + AC_MSG_RESULT(Detected 64-bit Build Environment)
479 + LIBJUDY_CFLAGS="$LIBJUDY_CFLAGS -DJU_64BIT"
480 +else
481 + AC_MSG_RESULT(Detected 32-bit Build Environment)
482 + LIBJUDY_CFLAGS="$LIBJUDY_CFLAGS -UJU_64BIT"
483 fi
484
508 -test "${enable_dbengine}" = "yes" -a -z "${JUDY_LIBS}" && \
509 - AC_MSG_ERROR([libJudy required but not found. Try installing 'libjudy-dev' or 'Judy-devel'.])
485 +AC_SUBST([LIBJUDY_CFLAGS])
486 +
487 +JUDY_CFLAGS="-I \$(abs_top_srcdir)/libnetdata/libjudy/src"
488
489 test "${enable_https}" = "yes" -a -z "${SSL_LIBS}" && \
490 AC_MSG_ERROR([OpenSSL required for HTTPS but not found. Try installing 'libssl-dev' or 'openssl-devel'.])
@@ -515,13 +493,12 @@ test "${enable_dbengine}" = "yes" -a -z "${SSL_LIBS}" && \
493 AC_MSG_ERROR([OpenSSL required for DBENGINE but not found. Try installing 'libssl-dev' or 'openssl-devel'.])
494
495 AC_MSG_CHECKING([if netdata dbengine should be used])
518 -if test "${enable_dbengine}" != "no" -a "${UV_LIBS}" -a "${LZ4_LIBS}" -a "${JUDY_LIBS}" -a "${SSL_LIBS}"; then
496 +if test "${enable_dbengine}" != "no" -a "${UV_LIBS}" -a "${LZ4_LIBS}" -a "${SSL_LIBS}"; then
497 enable_dbengine="yes"
498 AC_DEFINE([ENABLE_DBENGINE], [1], [netdata dbengine usability])
499 OPTIONAL_LZ4_CFLAGS="${LZ4_CFLAGS}"
500 OPTIONAL_LZ4_LIBS="${LZ4_LIBS}"
501 OPTIONAL_JUDY_CFLAGS="${JUDY_CFLAGS}"
524 - OPTIONAL_JUDY_LIBS="${JUDY_LIBS}"
502 OPTIONAL_SSL_CFLAGS="${SSL_CFLAGS}"
503 OPTIONAL_SSL_LIBS="${SSL_LIBS}"
504 else
@@ -1600,8 +1577,6 @@ AC_SUBST([OPTIONAL_MATH_CFLAGS])
1577 AC_SUBST([OPTIONAL_MATH_LIBS])
1578 AC_SUBST([OPTIONAL_UV_LIBS])
1579 AC_SUBST([OPTIONAL_LZ4_LIBS])
1603 -AC_SUBST([OPTIONAL_JUDY_CFLAGS])
1604 -AC_SUBST([OPTIONAL_JUDY_LIBS])
1580 AC_SUBST([OPTIONAL_SSL_LIBS])
1581 AC_SUBST([OPTIONAL_JSONC_LIBS])
1582 AC_SUBST([OPTIONAL_NFACCT_CFLAGS])
contrib/debian/control
-1
@@ -7,7 +7,6 @@ Build-Depends: debhelper (>= 9.20160709),
7 libelf-dev,
8 libuv1-dev,
9 liblz4-dev,
10 - libjudy-dev,
10 libssl-dev,
11 libmnl-dev,
12 libjson-c-dev,
contrib/debian/control.xenial
-1
@@ -8,7 +8,6 @@ Build-Depends: debhelper (>= 9),
8 libelf-dev,
9 libuv1-dev,
10 liblz4-dev,
11 - libjudy-dev,
11 libssl-dev,
12 libmnl-dev,
13 libjson-c-dev,
libnetdata/libjudy/src/Judy.h new
+622
@@ -0,0 +1,622 @@
1 +#ifndef _JUDY_INCLUDED
2 +#define _JUDY_INCLUDED
3 +// _________________
4 +//
5 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
6 +//
7 +// This program is free software; you can redistribute it and/or modify it
8 +// under the term of the GNU Lesser General Public License as published by the
9 +// Free Software Foundation; either version 2 of the License, or (at your
10 +// option) any later version.
11 +//
12 +// This program is distributed in the hope that it will be useful, but WITHOUT
13 +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 +// for more details.
16 +//
17 +// You should have received a copy of the GNU Lesser General Public License
18 +// along with this program; if not, write to the Free Software Foundation,
19 +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 +// _________________
21 +
22 +// @(#) $Revision: 4.52 $ $Source: /judy/src/Judy.h $
23 +//
24 +// HEADER FILE FOR EXPORTED FEATURES IN JUDY LIBRARY, libJudy.*
25 +//
26 +// See the manual entries for details.
27 +//
28 +// Note: This header file uses old-style comments on #-directive lines and
29 +// avoids "()" on macro names in comments for compatibility with older cc -Aa
30 +// and some tools on some platforms.
31 +
32 +
33 +// PLATFORM-SPECIFIC
34 +
35 +#ifdef JU_WIN /* =============================================== */
36 +
37 +typedef __int8 int8_t;
38 +typedef __int16 int16_t;
39 +typedef __int32 int32_t;
40 +typedef __int64 int64_t;
41 +
42 +typedef unsigned __int8 uint8_t;
43 +typedef unsigned __int16 uint16_t;
44 +typedef unsigned __int32 uint32_t;
45 +typedef unsigned __int64 uint64_t;
46 +
47 +#else /* ================ ! JU_WIN ============================= */
48 +
49 +// ISO C99: 7.8 Format conversion of integer types <inttypes.h>
50 +#include <inttypes.h> /* if this FAILS, try #include <stdint.h> */
51 +
52 +// ISO C99: 7.18 Integer types uint*_t
53 +//#include <stdint.h>
54 +
55 +#endif /* ================ ! JU_WIN ============================= */
56 +
57 +// ISO C99 Standard: 7.20 General utilities
58 +#include <stdlib.h>
59 +
60 +// ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types
61 +#include <limits.h>
62 +
63 +#ifdef __cplusplus /* support use by C++ code */
64 +extern "C" {
65 +#endif
66 +
67 +
68 +// ****************************************************************************
69 +// DECLARE SOME BASE TYPES IN CASE THEY ARE MISSING:
70 +//
71 +// These base types include "const" where appropriate, but only where of
72 +// interest to the caller. For example, a caller cares that a variable passed
73 +// by reference will not be modified, such as, "const void * Pindex", but not
74 +// that the called function internally does not modify the pointer itself, such
75 +// as, "void * const Pindex".
76 +//
77 +// Note that its OK to pass a Pvoid_t to a Pcvoid_t; the latter is the same,
78 +// only constant. Callers need to do this so they can also pass & Pvoid_t to
79 +// PPvoid_t (non-constant).
80 +
81 +#ifndef _PCVOID_T
82 +#define _PCVOID_T
83 +typedef const void * Pcvoid_t;
84 +#endif
85 +
86 +#ifndef _PVOID_T
87 +#define _PVOID_T
88 +typedef void * Pvoid_t;
89 +typedef void ** PPvoid_t;
90 +#endif
91 +
92 +#ifndef _WORD_T
93 +#define _WORD_T
94 +typedef unsigned long Word_t, * PWord_t; // expect 32-bit or 64-bit words.
95 +#endif
96 +
97 +#ifndef NULL
98 +#define NULL 0
99 +#endif
100 +
101 +
102 +// ****************************************************************************
103 +// SUPPORT FOR ERROR HANDLING:
104 +//
105 +// Judy error numbers:
106 +//
107 +// Note: These are an enum so theres a related typedef, but the numbers are
108 +// spelled out so you can map a number back to its name.
109 +
110 +typedef enum // uint8_t -- but C does not support this type of enum.
111 +{
112 +
113 +// Note: JU_ERRNO_NONE and JU_ERRNO_FULL are not real errors. They specify
114 +// conditions which are otherwise impossible return values from 32-bit
115 +// Judy1Count, which has 2^32 + 1 valid returns (0..2^32) plus one error
116 +// return. These pseudo-errors support the return values that cannot otherwise
117 +// be unambiguously represented in a 32-bit word, and will never occur on a
118 +// 64-bit system.
119 +
120 + JU_ERRNO_NONE = 0,
121 + JU_ERRNO_FULL = 1,
122 + JU_ERRNO_NFMAX = JU_ERRNO_FULL,
123 +
124 +// JU_ERRNO_NOMEM comes from malloc(3C) when Judy cannot obtain needed memory.
125 +// The system errno value is also set to ENOMEM. This error can be recoverable
126 +// if the calling application frees other memory.
127 +//
128 +// TBD: Currently there is no guarantee the Judy array has no memory leaks
129 +// upon JU_ERRNO_NOMEM.
130 +
131 + JU_ERRNO_NOMEM = 2,
132 +
133 +// Problems with parameters from the calling program:
134 +//
135 +// JU_ERRNO_NULLPPARRAY means PPArray was null; perhaps PArray was passed where
136 +// &PArray was intended. Similarly, JU_ERRNO_NULLPINDEX means PIndex was null;
137 +// perhaps &Index was intended. Also, JU_ERRNO_NONNULLPARRAY,
138 +// JU_ERRNO_NULLPVALUE, and JU_ERRNO_UNSORTED, all added later (hence with
139 +// higher numbers), mean: A non-null array was passed in where a null pointer
140 +// was required; PValue was null; and unsorted indexes were detected.
141 +
142 + JU_ERRNO_NULLPPARRAY = 3, // see above.
143 + JU_ERRNO_NONNULLPARRAY = 10, // see above.
144 + JU_ERRNO_NULLPINDEX = 4, // see above.
145 + JU_ERRNO_NULLPVALUE = 11, // see above.
146 + JU_ERRNO_NOTJUDY1 = 5, // PArray is not to a Judy1 array.
147 + JU_ERRNO_NOTJUDYL = 6, // PArray is not to a JudyL array.
148 + JU_ERRNO_NOTJUDYSL = 7, // PArray is not to a JudySL array.
149 + JU_ERRNO_UNSORTED = 12, // see above.
150 +
151 +// Errors below this point are not recoverable; further tries to access the
152 +// Judy array might result in EFAULT and a core dump:
153 +//
154 +// JU_ERRNO_OVERRUN occurs when Judy detects, upon reallocation, that a block
155 +// of memory in its own freelist was modified since being freed.
156 +
157 + JU_ERRNO_OVERRUN = 8,
158 +
159 +// JU_ERRNO_CORRUPT occurs when Judy detects an impossible value in a Judy data
160 +// structure:
161 +//
162 +// Note: The Judy data structure contains some redundant elements that support
163 +// this type of checking.
164 +
165 + JU_ERRNO_CORRUPT = 9
166 +
167 +// Warning: At least some C or C++ compilers do not tolerate a trailing comma
168 +// above here. At least we know of one case, in aCC; see JAGad58928.
169 +
170 +} JU_Errno_t;
171 +
172 +
173 +// Judy errno structure:
174 +//
175 +// WARNING: For compatibility with possible future changes, the fields of this
176 +// struct should not be referenced directly. Instead use the macros supplied
177 +// below.
178 +
179 +// This structure should be declared on the stack in a threaded process.
180 +
181 +typedef struct J_UDY_ERROR_STRUCT
182 +{
183 + JU_Errno_t je_Errno; // one of the enums above.
184 + int je_ErrID; // often an internal source line number.
185 + Word_t je_reserved[4]; // for future backward compatibility.
186 +
187 +} JError_t, * PJError_t;
188 +
189 +
190 +// Related macros:
191 +//
192 +// Fields from error struct:
193 +
194 +#define JU_ERRNO(PJError) ((PJError)->je_Errno)
195 +#define JU_ERRID(PJError) ((PJError)->je_ErrID)
196 +
197 +// For checking return values from various Judy functions:
198 +//
199 +// Note: Define JERR as -1, not as the seemingly more portable (Word_t)
200 +// (~0UL), to avoid a compiler "overflow in implicit constant conversion"
201 +// warning.
202 +
203 +#define JERR (-1) /* functions returning int or Word_t */
204 +#define PJERR ((Pvoid_t) (~0UL)) /* mainly for use here, see below */
205 +#define PPJERR ((PPvoid_t) (~0UL)) /* functions that return PPvoid_t */
206 +
207 +// Convenience macro for when detailed error information (PJError_t) is not
208 +// desired by the caller; a purposely short name:
209 +
210 +#define PJE0 ((PJError_t) NULL)
211 +
212 +
213 +// ****************************************************************************
214 +// JUDY FUNCTIONS:
215 +//
216 +// P_JE is a shorthand for use below:
217 +
218 +#define P_JE PJError_t PJError
219 +
220 +// ****************************************************************************
221 +// JUDY1 FUNCTIONS:
222 +
223 +extern int Judy1Test( Pcvoid_t PArray, Word_t Index, P_JE);
224 +extern int Judy1Set( PPvoid_t PPArray, Word_t Index, P_JE);
225 +extern int Judy1SetArray( PPvoid_t PPArray, Word_t Count,
226 + const Word_t * const PIndex,
227 + P_JE);
228 +extern int Judy1Unset( PPvoid_t PPArray, Word_t Index, P_JE);
229 +extern Word_t Judy1Count( Pcvoid_t PArray, Word_t Index1,
230 + Word_t Index2, P_JE);
231 +extern int Judy1ByCount( Pcvoid_t PArray, Word_t Count,
232 + Word_t * PIndex, P_JE);
233 +extern Word_t Judy1FreeArray( PPvoid_t PPArray, P_JE);
234 +extern Word_t Judy1MemUsed( Pcvoid_t PArray);
235 +extern Word_t Judy1MemActive( Pcvoid_t PArray);
236 +extern int Judy1First( Pcvoid_t PArray, Word_t * PIndex, P_JE);
237 +extern int Judy1Next( Pcvoid_t PArray, Word_t * PIndex, P_JE);
238 +extern int Judy1Last( Pcvoid_t PArray, Word_t * PIndex, P_JE);
239 +extern int Judy1Prev( Pcvoid_t PArray, Word_t * PIndex, P_JE);
240 +extern int Judy1FirstEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
241 +extern int Judy1NextEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
242 +extern int Judy1LastEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
243 +extern int Judy1PrevEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
244 +
245 +extern PPvoid_t JudyLGet( Pcvoid_t PArray, Word_t Index, P_JE);
246 +extern PPvoid_t JudyLIns( PPvoid_t PPArray, Word_t Index, P_JE);
247 +extern int JudyLInsArray( PPvoid_t PPArray, Word_t Count,
248 + const Word_t * const PIndex,
249 + const Word_t * const PValue,
250 +
251 +// ****************************************************************************
252 +// JUDYL FUNCTIONS:
253 + P_JE);
254 +extern int JudyLDel( PPvoid_t PPArray, Word_t Index, P_JE);
255 +extern Word_t JudyLCount( Pcvoid_t PArray, Word_t Index1,
256 + Word_t Index2, P_JE);
257 +extern PPvoid_t JudyLByCount( Pcvoid_t PArray, Word_t Count,
258 + Word_t * PIndex, P_JE);
259 +extern Word_t JudyLFreeArray( PPvoid_t PPArray, P_JE);
260 +extern Word_t JudyLMemUsed( Pcvoid_t PArray);
261 +extern Word_t JudyLMemActive( Pcvoid_t PArray);
262 +extern PPvoid_t JudyLFirst( Pcvoid_t PArray, Word_t * PIndex, P_JE);
263 +extern PPvoid_t JudyLNext( Pcvoid_t PArray, Word_t * PIndex, P_JE);
264 +extern PPvoid_t JudyLLast( Pcvoid_t PArray, Word_t * PIndex, P_JE);
265 +extern PPvoid_t JudyLPrev( Pcvoid_t PArray, Word_t * PIndex, P_JE);
266 +extern int JudyLFirstEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
267 +extern int JudyLNextEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
268 +extern int JudyLLastEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
269 +extern int JudyLPrevEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
270 +
271 +// ****************************************************************************
272 +// JUDYSL FUNCTIONS:
273 +
274 +extern PPvoid_t JudySLGet( Pcvoid_t, const uint8_t * Index, P_JE);
275 +extern PPvoid_t JudySLIns( PPvoid_t, const uint8_t * Index, P_JE);
276 +extern int JudySLDel( PPvoid_t, const uint8_t * Index, P_JE);
277 +extern Word_t JudySLFreeArray( PPvoid_t, P_JE);
278 +extern PPvoid_t JudySLFirst( Pcvoid_t, uint8_t * Index, P_JE);
279 +extern PPvoid_t JudySLNext( Pcvoid_t, uint8_t * Index, P_JE);
280 +extern PPvoid_t JudySLLast( Pcvoid_t, uint8_t * Index, P_JE);
281 +extern PPvoid_t JudySLPrev( Pcvoid_t, uint8_t * Index, P_JE);
282 +
283 +// ****************************************************************************
284 +// JUDYHSL FUNCTIONS:
285 +
286 +extern PPvoid_t JudyHSGet( Pcvoid_t, void *, Word_t);
287 +extern PPvoid_t JudyHSIns( PPvoid_t, void *, Word_t, P_JE);
288 +extern int JudyHSDel( PPvoid_t, void *, Word_t, P_JE);
289 +extern Word_t JudyHSFreeArray( PPvoid_t, P_JE);
290 +
291 +extern const char *Judy1MallocSizes;
292 +extern const char *JudyLMallocSizes;
293 +
294 +// ****************************************************************************
295 +// JUDY memory interface to malloc() FUNCTIONS:
296 +
297 +extern Word_t JudyMalloc(Word_t); // words reqd => words allocd.
298 +extern Word_t JudyMallocVirtual(Word_t); // words reqd => words allocd.
299 +extern void JudyFree(Pvoid_t, Word_t); // free, size in words.
300 +extern void JudyFreeVirtual(Pvoid_t, Word_t); // free, size in words.
301 +
302 +#define JLAP_INVALID 0x1 /* flag to mark pointer "not a Judy array" */
303 +
304 +// ****************************************************************************
305 +// MACRO EQUIVALENTS FOR JUDY FUNCTIONS:
306 +//
307 +// The following macros, such as J1T, are shorthands for calling Judy functions
308 +// with parameter address-of and detailed error checking included. Since they
309 +// are macros, the error checking code is replicated each time the macro is
310 +// used, but it runs fast in the normal case of no error.
311 +//
312 +// If the caller does not like the way the default JUDYERROR macro handles
313 +// errors (such as an exit(1) call when out of memory), they may define their
314 +// own before the "#include <Judy.h>". A routine such as HandleJudyError
315 +// could do checking on specific error numbers and print a different message
316 +// dependent on the error. The following is one example:
317 +//
318 +// Note: the back-slashes are removed because some compilers will not accept
319 +// them in comments.
320 +//
321 +// void HandleJudyError(uint8_t *, int, uint8_t *, int, int);
322 +// #define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID)
323 +// {
324 +// HandleJudyError(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID);
325 +// }
326 +//
327 +// The routine HandleJudyError could do checking on specific error numbers and
328 +// print a different message dependent on the error.
329 +//
330 +// The macro receives five parameters that are:
331 +//
332 +// 1. CallerFile: Source filename where a Judy call returned a serious error.
333 +// 2. CallerLine: Line number in that source file.
334 +// 3. JudyFunc: Name of Judy function reporting the error.
335 +// 4. JudyErrno: One of the JU_ERRNO* values enumerated above.
336 +// 5. JudyErrID: The je_ErrID field described above.
337 +
338 +#ifndef JUDYERROR_NOTEST
339 +#ifndef JUDYERROR /* supply a default error macro */
340 +#include <stdio.h>
341 +
342 +#define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID) \
343 + { \
344 + (void) fprintf(stderr, "File '%s', line %d: %s(), " \
345 + "JU_ERRNO_* == %d, ID == %d\n", \
346 + CallerFile, CallerLine, \
347 + JudyFunc, JudyErrno, JudyErrID); \
348 + exit(1); \
349 + }
350 +
351 +#endif /* JUDYERROR */
352 +#endif /* JUDYERROR_NOTEST */
353 +
354 +// If the JUDYERROR macro is not desired at all, then the following eliminates
355 +// it. However, the return code from each Judy function (that is, the first
356 +// parameter of each macro) must be checked by the caller to assure that an
357 +// error did not occur.
358 +//
359 +// Example:
360 +//
361 +// #define JUDYERROR_NOTEST 1
362 +// #include <Judy.h>
363 +//
364 +// or use this cc option at compile time:
365 +//
366 +// cc -DJUDYERROR_NOTEST ...
367 +//
368 +// Example code:
369 +//
370 +// J1S(Rc, PArray, Index);
371 +// if (Rc == JERR) goto ...error
372 +//
373 +// or:
374 +//
375 +// JLI(PValue, PArray, Index);
376 +// if (PValue == PJERR) goto ...error
377 +
378 +
379 +// Internal shorthand macros for writing the J1S, etc. macros:
380 +
381 +#ifdef JUDYERROR_NOTEST /* ============================================ */
382 +
383 +// "Judy Set Error":
384 +
385 +#define J_SE(FuncName,Errno) ((void) 0)
386 +
387 +// Note: In each J_*() case below, the digit is the number of key parameters
388 +// to the Judy*() call. Just assign the Func result to the callers Rc value
389 +// without a cast because none is required, and this keeps the API simpler.
390 +// However, a family of different J_*() macros is needed to support the
391 +// different numbers of key parameters (0,1,2) and the Func return type.
392 +//
393 +// In the names below, "I" = integer result; "P" = pointer result. Note, the
394 +// Funcs for J_*P() return PPvoid_t, but cast this to a Pvoid_t for flexible,
395 +// error-free assignment, and then compare to PJERR.
396 +
397 +#define J_0I(Rc,PArray,Func,FuncName) \
398 + { (Rc) = Func(PArray, PJE0); }
399 +
400 +#define J_1I(Rc,PArray,Index,Func,FuncName) \
401 + { (Rc) = Func(PArray, Index, PJE0); }
402 +
403 +#define J_1P(PV,PArray,Index,Func,FuncName) \
404 + { (PV) = (Pvoid_t) Func(PArray, Index, PJE0); }
405 +
406 +#define J_2I(Rc,PArray,Index,Arg2,Func,FuncName) \
407 + { (Rc) = Func(PArray, Index, Arg2, PJE0); }
408 +
409 +#define J_2C(Rc,PArray,Index1,Index2,Func,FuncName) \
410 + { (Rc) = Func(PArray, Index1, Index2, PJE0); }
411 +
412 +#define J_2P(PV,PArray,Index,Arg2,Func,FuncName) \
413 + { (PV) = (Pvoid_t) Func(PArray, Index, Arg2, PJE0); }
414 +
415 +// Variations for Judy*Set/InsArray functions:
416 +
417 +#define J_2AI(Rc,PArray,Count,PIndex,Func,FuncName) \
418 + { (Rc) = Func(PArray, Count, PIndex, PJE0); }
419 +#define J_3AI(Rc,PArray,Count,PIndex,PValue,Func,FuncName) \
420 + { (Rc) = Func(PArray, Count, PIndex, PValue, PJE0); }
421 +
422 +#else /* ================ ! JUDYERROR_NOTEST ============================= */
423 +
424 +#define J_E(FuncName,PJE) \
425 + JUDYERROR(__FILE__, __LINE__, FuncName, JU_ERRNO(PJE), JU_ERRID(PJE))
426 +
427 +#define J_SE(FuncName,Errno) \
428 + { \
429 + JError_t J_Error; \
430 + JU_ERRNO(&J_Error) = (Errno); \
431 + JU_ERRID(&J_Error) = __LINE__; \
432 + J_E(FuncName, &J_Error); \
433 + }
434 +
435 +// Note: In each J_*() case below, the digit is the number of key parameters
436 +// to the Judy*() call. Just assign the Func result to the callers Rc value
437 +// without a cast because none is required, and this keeps the API simpler.
438 +// However, a family of different J_*() macros is needed to support the
439 +// different numbers of key parameters (0,1,2) and the Func return type.
440 +//
441 +// In the names below, "I" = integer result; "P" = pointer result. Note, the
442 +// Funcs for J_*P() return PPvoid_t, but cast this to a Pvoid_t for flexible,
443 +// error-free assignment, and then compare to PJERR.
444 +
445 +#define J_0I(Rc,PArray,Func,FuncName) \
446 + { \
447 + JError_t J_Error; \
448 + if (((Rc) = Func(PArray, &J_Error)) == JERR) \
449 + J_E(FuncName, &J_Error); \
450 + }
451 +
452 +#define J_1I(Rc,PArray,Index,Func,FuncName) \
453 + { \
454 + JError_t J_Error; \
455 + if (((Rc) = Func(PArray, Index, &J_Error)) == JERR) \
456 + J_E(FuncName, &J_Error); \
457 + }
458 +
459 +#define J_1P(Rc,PArray,Index,Func,FuncName) \
460 + { \
461 + JError_t J_Error; \
462 + if (((Rc) = (Pvoid_t) Func(PArray, Index, &J_Error)) == PJERR) \
463 + J_E(FuncName, &J_Error); \
464 + }
465 +
466 +#define J_2I(Rc,PArray,Index,Arg2,Func,FuncName) \
467 + { \
468 + JError_t J_Error; \
469 + if (((Rc) = Func(PArray, Index, Arg2, &J_Error)) == JERR) \
470 + J_E(FuncName, &J_Error); \
471 + }
472 +
473 +// Variation for Judy*Count functions, which return 0, not JERR, for error (and
474 +// also for other non-error cases):
475 +//
476 +// Note: JU_ERRNO_NFMAX should only apply to 32-bit Judy1, but this header
477 +// file lacks the necessary ifdefs to make it go away otherwise, so always
478 +// check against it.
479 +
480 +#define J_2C(Rc,PArray,Index1,Index2,Func,FuncName) \
481 + { \
482 + JError_t J_Error; \
483 + if ((((Rc) = Func(PArray, Index1, Index2, &J_Error)) == 0) \
484 + && (JU_ERRNO(&J_Error) > JU_ERRNO_NFMAX)) \
485 + { \
486 + J_E(FuncName, &J_Error); \
487 + } \
488 + }
489 +
490 +#define J_2P(PV,PArray,Index,Arg2,Func,FuncName) \
491 + { \
492 + JError_t J_Error; \
493 + if (((PV) = (Pvoid_t) Func(PArray, Index, Arg2, &J_Error)) \
494 + == PJERR) J_E(FuncName, &J_Error); \
495 + }
496 +
497 +// Variations for Judy*Set/InsArray functions:
498 +
499 +#define J_2AI(Rc,PArray,Count,PIndex,Func,FuncName) \
500 + { \
501 + JError_t J_Error; \
502 + if (((Rc) = Func(PArray, Count, PIndex, &J_Error)) == JERR) \
503 + J_E(FuncName, &J_Error); \
504 + }
505 +
506 +#define J_3AI(Rc,PArray,Count,PIndex,PValue,Func,FuncName) \
507 + { \
508 + JError_t J_Error; \
509 + if (((Rc) = Func(PArray, Count, PIndex, PValue, &J_Error)) \
510 + == JERR) J_E(FuncName, &J_Error); \
511 + }
512 +
513 +#endif /* ================ ! JUDYERROR_NOTEST ============================= */
514 +
515 +// Some of the macros are special cases that use inlined shortcuts for speed
516 +// with root-level leaves:
517 +
518 +// This is a slower version with current processors, but in the future...
519 +
520 +#define J1T(Rc,PArray,Index) \
521 + (Rc) = Judy1Test((Pvoid_t)(PArray), Index, PJE0)
522 +
523 +#define J1S( Rc, PArray, Index) \
524 + J_1I(Rc, (&(PArray)), Index, Judy1Set, "Judy1Set")
525 +#define J1SA(Rc, PArray, Count, PIndex) \
526 + J_2AI(Rc,(&(PArray)), Count, PIndex, Judy1SetArray, "Judy1SetArray")
527 +#define J1U( Rc, PArray, Index) \
528 + J_1I(Rc, (&(PArray)), Index, Judy1Unset, "Judy1Unset")
529 +#define J1F( Rc, PArray, Index) \
530 + J_1I(Rc, PArray, &(Index), Judy1First, "Judy1First")
531 +#define J1N( Rc, PArray, Index) \
532 + J_1I(Rc, PArray, &(Index), Judy1Next, "Judy1Next")
533 +#define J1L( Rc, PArray, Index) \
534 + J_1I(Rc, PArray, &(Index), Judy1Last, "Judy1Last")
535 +#define J1P( Rc, PArray, Index) \
536 + J_1I(Rc, PArray, &(Index), Judy1Prev, "Judy1Prev")
537 +#define J1FE(Rc, PArray, Index) \
538 + J_1I(Rc, PArray, &(Index), Judy1FirstEmpty, "Judy1FirstEmpty")
539 +#define J1NE(Rc, PArray, Index) \
540 + J_1I(Rc, PArray, &(Index), Judy1NextEmpty, "Judy1NextEmpty")
541 +#define J1LE(Rc, PArray, Index) \
542 + J_1I(Rc, PArray, &(Index), Judy1LastEmpty, "Judy1LastEmpty")
543 +#define J1PE(Rc, PArray, Index) \
544 + J_1I(Rc, PArray, &(Index), Judy1PrevEmpty, "Judy1PrevEmpty")
545 +#define J1C( Rc, PArray, Index1, Index2) \
546 + J_2C(Rc, PArray, Index1, Index2, Judy1Count, "Judy1Count")
547 +#define J1BC(Rc, PArray, Count, Index) \
548 + J_2I(Rc, PArray, Count, &(Index), Judy1ByCount, "Judy1ByCount")
549 +#define J1FA(Rc, PArray) \
550 + J_0I(Rc, (&(PArray)), Judy1FreeArray, "Judy1FreeArray")
551 +#define J1MU(Rc, PArray) \
552 + (Rc) = Judy1MemUsed(PArray)
553 +
554 +#define JLG(PV,PArray,Index) \
555 + (PV) = (Pvoid_t)JudyLGet((Pvoid_t)PArray, Index, PJE0)
556 +
557 +#define JLI( PV, PArray, Index) \
558 + J_1P(PV, (&(PArray)), Index, JudyLIns, "JudyLIns")
559 +
560 +#define JLIA(Rc, PArray, Count, PIndex, PValue) \
561 + J_3AI(Rc,(&(PArray)), Count, PIndex, PValue, JudyLInsArray, \
562 + "JudyLInsArray")
563 +#define JLD( Rc, PArray, Index) \
564 + J_1I(Rc, (&(PArray)), Index, JudyLDel, "JudyLDel")
565 +
566 +#define JLF( PV, PArray, Index) \
567 + J_1P(PV, PArray, &(Index), JudyLFirst, "JudyLFirst")
568 +
569 +#define JLN( PV, PArray, Index) \
570 + J_1P(PV, PArray, &(Index), JudyLNext, "JudyLNext")
571 +
572 +#define JLL( PV, PArray, Index) \
573 + J_1P(PV, PArray, &(Index), JudyLLast, "JudyLLast")
574 +#define JLP( PV, PArray, Index) \
575 + J_1P(PV, PArray, &(Index), JudyLPrev, "JudyLPrev")
576 +#define JLFE(Rc, PArray, Index) \
577 + J_1I(Rc, PArray, &(Index), JudyLFirstEmpty, "JudyLFirstEmpty")
578 +#define JLNE(Rc, PArray, Index) \
579 + J_1I(Rc, PArray, &(Index), JudyLNextEmpty, "JudyLNextEmpty")
580 +#define JLLE(Rc, PArray, Index) \
581 + J_1I(Rc, PArray, &(Index), JudyLLastEmpty, "JudyLLastEmpty")
582 +#define JLPE(Rc, PArray, Index) \
583 + J_1I(Rc, PArray, &(Index), JudyLPrevEmpty, "JudyLPrevEmpty")
584 +#define JLC( Rc, PArray, Index1, Index2) \
585 + J_2C(Rc, PArray, Index1, Index2, JudyLCount, "JudyLCount")
586 +#define JLBC(PV, PArray, Count, Index) \
587 + J_2P(PV, PArray, Count, &(Index), JudyLByCount, "JudyLByCount")
588 +#define JLFA(Rc, PArray) \
589 + J_0I(Rc, (&(PArray)), JudyLFreeArray, "JudyLFreeArray")
590 +#define JLMU(Rc, PArray) \
591 + (Rc) = JudyLMemUsed(PArray)
592 +
593 +#define JHSI(PV, PArray, PIndex, Count) \
594 + J_2P(PV, (&(PArray)), PIndex, Count, JudyHSIns, "JudyHSIns")
595 +#define JHSG(PV, PArray, PIndex, Count) \
596 + (PV) = (Pvoid_t) JudyHSGet(PArray, PIndex, Count)
597 +#define JHSD(Rc, PArray, PIndex, Count) \
598 + J_2I(Rc, (&(PArray)), PIndex, Count, JudyHSDel, "JudyHSDel")
599 +#define JHSFA(Rc, PArray) \
600 + J_0I(Rc, (&(PArray)), JudyHSFreeArray, "JudyHSFreeArray")
601 +
602 +#define JSLG( PV, PArray, Index) \
603 + J_1P( PV, PArray, Index, JudySLGet, "JudySLGet")
604 +#define JSLI( PV, PArray, Index) \
605 + J_1P( PV, (&(PArray)), Index, JudySLIns, "JudySLIns")
606 +#define JSLD( Rc, PArray, Index) \
607 + J_1I( Rc, (&(PArray)), Index, JudySLDel, "JudySLDel")
608 +#define JSLF( PV, PArray, Index) \
609 + J_1P( PV, PArray, Index, JudySLFirst, "JudySLFirst")
610 +#define JSLN( PV, PArray, Index) \
611 + J_1P( PV, PArray, Index, JudySLNext, "JudySLNext")
612 +#define JSLL( PV, PArray, Index) \
613 + J_1P( PV, PArray, Index, JudySLLast, "JudySLLast")
614 +#define JSLP( PV, PArray, Index) \
615 + J_1P( PV, PArray, Index, JudySLPrev, "JudySLPrev")
616 +#define JSLFA(Rc, PArray) \
617 + J_0I( Rc, (&(PArray)), JudySLFreeArray, "JudySLFreeArray")
618 +
619 +#ifdef __cplusplus
620 +}
621 +#endif
622 +#endif /* ! _JUDY_INCLUDED */
libnetdata/libjudy/src/JudyCommon/JudyMalloc.c new
+87
@@ -0,0 +1,87 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.33 $ $Source: /judy/src/JudyCommon/JudyMalloc.c $
19 +// ************************************************************************ //
20 +// JUDY - Memory Allocater //
21 +// -by- //
22 +// Douglas L. Baskins //
23 +// Hewlett Packard //
24 +// Fort Collins, Co //
25 +// (970) 229-2027 //
26 +// //
27 +// ************************************************************************ //
28 +
29 +// JUDY INCLUDE FILES
30 +#include "Judy.h"
31 +
32 +// ****************************************************************************
33 +// J U D Y M A L L O C
34 +//
35 +// Allocate RAM. This is the single location in Judy code that calls
36 +// malloc(3C). Note: JPM accounting occurs at a higher level.
37 +
38 +Word_t JudyMalloc(
39 + Word_t Words)
40 +{
41 + Word_t Addr;
42 +
43 + Addr = (Word_t) malloc(Words * sizeof(Word_t));
44 + return(Addr);
45 +
46 +} // JudyMalloc()
47 +
48 +
49 +// ****************************************************************************
50 +// J U D Y F R E E
51 +
52 +void JudyFree(
53 + void * PWord,
54 + Word_t Words)
55 +{
56 + (void) Words;
57 + free(PWord);
58 +
59 +} // JudyFree()
60 +
61 +
62 +// ****************************************************************************
63 +// J U D Y M A L L O C
64 +//
65 +// Higher-level "wrapper" for allocating objects that need not be in RAM,
66 +// although at this time they are in fact only in RAM. Later we hope that some
67 +// entire subtrees (at a JPM or branch) can be "virtual", so their allocations
68 +// and frees should go through this level.
69 +
70 +Word_t JudyMallocVirtual(
71 + Word_t Words)
72 +{
73 + return(JudyMalloc(Words));
74 +
75 +} // JudyMallocVirtual()
76 +
77 +
78 +// ****************************************************************************
79 +// J U D Y F R E E
80 +
81 +void JudyFreeVirtual(
82 + void * PWord,
83 + Word_t Words)
84 +{
85 + JudyFree(PWord, Words);
86 +
87 +} // JudyFreeVirtual()
libnetdata/libjudy/src/JudyCommon/JudyPrivate.h new
+1613
@@ -0,0 +1,1613 @@
1 +#ifndef _JUDYPRIVATE_INCLUDED
2 +#define _JUDYPRIVATE_INCLUDED
3 +// _________________
4 +//
5 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
6 +//
7 +// This program is free software; you can redistribute it and/or modify it
8 +// under the term of the GNU Lesser General Public License as published by the
9 +// Free Software Foundation; either version 2 of the License, or (at your
10 +// option) any later version.
11 +//
12 +// This program is distributed in the hope that it will be useful, but WITHOUT
13 +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 +// for more details.
16 +//
17 +// You should have received a copy of the GNU Lesser General Public License
18 +// along with this program; if not, write to the Free Software Foundation,
19 +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 +// _________________
21 +
22 +// @(#) $Revision: 4.77 $ $Source: /judy/src/JudyCommon/JudyPrivate.h $
23 +//
24 +// Header file for all Judy sources, for global but private (non-exported)
25 +// declarations.
26 +
27 +#include "Judy.h"
28 +
29 +// ****************************************************************************
30 +// A VERY BRIEF EXPLANATION OF A JUDY ARRAY
31 +//
32 +// A Judy array is, effectively, a digital tree (or Trie) with 256 element
33 +// branches (nodes), and with "compression tricks" applied to low-population
34 +// branches or leaves to save a lot of memory at the cost of relatively little
35 +// CPU time or cache fills.
36 +//
37 +// In the actual implementation, a Judy array is level-less, and traversing the
38 +// "tree" actually means following the states in a state machine (SM) as
39 +// directed by the Index. A Judy array is referred to here as an "SM", rather
40 +// than as a "tree"; having "states", rather than "levels".
41 +//
42 +// Each branch or leaf in the SM decodes a portion ("digit") of the original
43 +// Index; with 256-way branches there are 8 bits per digit. There are 3 kinds
44 +// of branches, called: Linear, Bitmap and Uncompressed, of which the first 2
45 +// are compressed to contain no NULL entries.
46 +//
47 +// An Uncompressed branch has a 1.0 cache line fill cost to decode 8 bits of
48 +// (digit, part of an Index), but it might contain many NULL entries, and is
49 +// therefore inefficient with memory if lightly populated.
50 +//
51 +// A Linear branch has a ~1.75 cache line fill cost when at maximum population.
52 +// A Bitmap branch has ~2.0 cache line fills. Linear and Bitmap branches are
53 +// converted to Uncompressed branches when the additional memory can be
54 +// amortized with larger populations. Higher-state branches have higher
55 +// priority to be converted.
56 +//
57 +// Linear branches can hold 28 elements (based on detailed analysis) -- thus 28
58 +// expanses. A Linear branch is converted to a Bitmap branch when the 29th
59 +// expanse is required.
60 +//
61 +// A Bitmap branch could hold 256 expanses, but is forced to convert to an
62 +// Uncompressed branch when 185 expanses are required. Hopefully, it is
63 +// converted before that because of population growth (again, based on detailed
64 +// analysis and heuristics in the code).
65 +//
66 +// A path through the SM terminates to a leaf when the Index (or key)
67 +// population in the expanse below a pointer will fit into 1 or 2 cache lines
68 +// (~31..255 Indexes). A maximum-population Leaf has ~1.5 cache line fill
69 +// cost.
70 +//
71 +// Leaves are sorted arrays of Indexes, where the Index Sizes (IS) are: 0, 1,
72 +// 8, 16, 24, 32, [40, 48, 56, 64] bits. The IS depends on the "density"
73 +// (population/expanse) of the values in the Leaf. Zero bits are possible if
74 +// population == expanse in the SM (that is, a full small expanse).
75 +//
76 +// Elements of a branches are called Judy Pointers (JPs). Each JP object
77 +// points to the next object in the SM, plus, a JP can decode an additional
78 +// 2[6] bytes of an Index, but at the cost of "narrowing" the expanse
79 +// represented by the next object in the SM. A "narrow" JP (one which has
80 +// decode bytes/digits) is a way of skipping states in the SM.
81 +//
82 +// Although counterintuitive, we think a Judy SM is optimal when the Leaves are
83 +// stored at MINIMUM compression (narrowing, or use of Decode bytes). If more
84 +// aggressive compression was used, decompression of a leaf be required to
85 +// insert an index. Additional compression would save a little memory but not
86 +// help performance significantly.
87 +
88 +
89 +#ifdef A_PICTURE_IS_WORTH_1000_WORDS
90 +*******************************************************************************
91 +
92 +JUDY 32-BIT STATE MACHINE (SM) EXAMPLE, FOR INDEX = 0x02040103
93 +
94 +The Index used in this example is purposely chosen to allow small, simple
95 +examples below; each 1-byte "digit" from the Index has a small numeric value
96 +that fits in one column. In the drawing below:
97 +
98 + JRP == Judy Root Pointer;
99 +
100 + C == 1 byte of a 1..3 byte Population (count of Indexes) below this
101 + pointer. Since this is shared with the Decode field, the combined
102 + sizes must be 3[7], that is, 1 word less 1 byte for the JP Type.
103 +
104 + The 1-byte field jp_Type is represented as:
105 +
106 + 1..3 == Number of bytes in the population (Pop0) word of the Branch or Leaf
107 + below the pointer (note: 1..7 on 64-bit); indicates:
108 + - number of bytes in Decode field == 3 - this number;
109 + - number of bytes remaining to decode.
110 + Note: The maximum is 3, not 4, because the 1st byte of the Index is
111 + always decoded digitally in the top branch.
112 + -B- == JP points to a Branch (there are many kinds of Branches).
113 + -L- == JP points to a Leaf (there are many kinds of Leaves).
114 +
115 + (2) == Digit of Index decoded by position offset in branch (really
116 + 0..0xff).
117 +
118 + 4* == Digit of Index necessary for decoding a "narrow" pointer, in a
119 + Decode field; replaces 1 missing branch (really 0..0xff).
120 +
121 + 4+ == Digit of Index NOT necessary for decoding a "narrow" pointer, but
122 + used for fast traversal of the SM by Judy1Test() and JudyLGet()
123 + (see the code) (really 0..0xff).
124 +
125 + 0 == Byte in a JPs Pop0 field that is always ignored, because a leaf
126 + can never contain more than 256 Indexes (Pop0 <= 255).
127 +
128 + +----- == A Branch or Leaf; drawn open-ended to remind you that it could
129 + | have up to 256 columns.
130 + +-----
131 +
132 + |
133 + | == Pointer to next Branch or Leaf.
134 + V
135 +
136 + |
137 + O == A state is skipped by using a "narrow" pointer.
138 + |
139 +
140 + < 1 > == Digit (Index) shown as an example is not necessarily in the
141 + position shown; is sorted in order with neighbor Indexes.
142 + (Really 0..0xff.)
143 +
144 +Note that this example shows every possibly topology to reach a leaf in a
145 +32-bit Judy SM, although this is a very subtle point!
146 +
147 + STATE or`
148 + LEVEL
149 + +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
150 + |RJP| |RJP| |RJP| |RJP| |RJP| |RJP| |RJP| |RJP|
151 + L---+ B---+ B---+ B---+ B---+ B---+ B---+ B---+
152 + | | | | | | | |
153 + | | | | | | | |
154 + V V (2) V (2) V (2) V (2) V (2) V (2) V (2)
155 + +------ +------ +------ +------ +------ +------ +------ +------
156 +Four |< 2 > | 0 | 4* | C | 4* | 4* | C | C
157 +byte |< 4 > | 0 | 0 | C | 1* | C | C | C 4
158 +Index|< 1 > | C | C | C | C | C | C | C
159 +Leaf |< 3 > | 3 | 2 | 3 | 1 | 2 | 3 | 3
160 + +------ +--L--- +--L--- +--B--- +--L--- +--B--- +--B--- +--B---
161 + | | | | | | |
162 + / | / | | / /
163 + / | / | | / /
164 + | | | | | | |
165 + V | V (4) | | V (4) V (4)
166 + +------ | +------ | | +------ +------
167 + Three |< 4 > | | 4+ | | | 4+ | 4+
168 + byte Index|< 1 > O | 0 O O | 1* | C 3
169 + Leaf |< 3 > | | C | | | C | C
170 + +------ | | 2 | | | 1 | 2
171 + / +----L- | | +----L- +----B-
172 + / | | | | |
173 + | / | / / /
174 + | / | / / /
175 + | / | | / /
176 + | / | | / /
177 + | | | | | |
178 + V V | V(1) | V(1)
179 + +------ +------ | +------ | +------
180 + Two byte |< 1 > |< 1 > | | 4+ | | 4+
181 + Index Leaf |< 3 > |< 3 > O | 1+ O | 1+ 2
182 + +------ +------ / | C | | C
183 + / | 1 | | 1
184 + | +-L---- | +-L----
185 + | | | |
186 + | / | /
187 + | | | |
188 + V V V V
189 + +------ +------ +------ +------
190 + One byte Index Leaf |< 3 > |< 3 > |< 3 > |< 3 > 1
191 + +------ +------ +------ +------
192 +
193 +
194 +#endif // A_PICTURE_IS_WORTH_1000_WORDS
195 +
196 +
197 +// ****************************************************************************
198 +// MISCELLANEOUS GLOBALS:
199 +//
200 +// PLATFORM-SPECIFIC CONVENIENCE MACROS:
201 +//
202 +// These are derived from context (set by cc or in system header files) or
203 +// based on JU_<PLATFORM> macros from make_includes/platform.*.mk. We decided
204 +// on 011018 that any macro reliably derivable from context (cc or headers) for
205 +// ALL platforms supported by Judy is based on that derivation, but ANY
206 +// exception means to stop using the external macro completely and derive from
207 +// JU_<PLATFORM> instead.
208 +
209 +// Other miscellaneous stuff:
210 +
211 +#ifndef _BOOL_T
212 +#define _BOOL_T
213 +typedef int bool_t;
214 +#endif
215 +
216 +#define FUNCTION // null; easy to find functions.
217 +
218 +#ifndef TRUE
219 +#define TRUE 1
220 +#endif
221 +
222 +#ifndef FALSE
223 +#define FALSE 0
224 +#endif
225 +
226 +#ifdef TRACE // turn on all other tracing in the code:
227 +#define TRACEJP 1 // JP traversals in JudyIns.c and JudyDel.c.
228 +#define TRACEJPR 1 // JP traversals in retrieval code, JudyGet.c.
229 +#define TRACECF 1 // cache fills in JudyGet.c.
230 +#define TRACEMI 1 // malloc calls in JudyMallocIF.c.
231 +#define TRACEMF 1 // malloc calls at a lower level in JudyMalloc.c.
232 +#endif
233 +
234 +
235 +// SUPPORT FOR DEBUG-ONLY CODE:
236 +//
237 +// By convention, use -DDEBUG to enable both debug-only code AND assertions in
238 +// the Judy sources.
239 +//
240 +// Invert the sense of assertions, so they are off unless explicitly requested,
241 +// in a uniform way.
242 +//
243 +// Note: It is NOT appropriate to put this in Judy.h; it would mess up
244 +// application code.
245 +
246 +#ifndef DEBUG
247 +#define NDEBUG 1 // must be 1 for "#if".
248 +#endif
249 +
250 +// Shorthand notations to avoid #ifdefs for single-line conditional statements:
251 +//
252 +// Warning: These cannot be used around compiler directives, such as
253 +// "#include", nor in the case where Code contains a comma other than nested
254 +// within parentheses or quotes.
255 +
256 +#ifndef DEBUG
257 +#define DBGCODE(Code) // null.
258 +#else
259 +#define DBGCODE(Code) Code
260 +#endif
261 +
262 +#ifdef JUDY1
263 +#define JUDY1CODE(Code) Code
264 +#define JUDYLCODE(Code) // null.
265 +#endif
266 +
267 +#ifdef JUDYL
268 +#define JUDYLCODE(Code) Code
269 +#define JUDY1CODE(Code) // null.
270 +#endif
271 +
272 +#include <assert.h>
273 +
274 +// ****************************************************************************
275 +// FUNDAMENTAL CONSTANTS FOR MACHINE
276 +// ****************************************************************************
277 +
278 +// Machine (CPU) cache line size:
279 +//
280 +// NOTE: A leaf size of 2 cache lines maximum is the target (optimal) for
281 +// Judy. Its hard to obtain a machines cache line size at compile time, but
282 +// if the machine has an unexpected cache line size, its not devastating if
283 +// the following constants end up causing leaves that are 1 cache line in size,
284 +// or even 4 cache lines in size. The assumed 32-bit system has 16-word =
285 +// 64-byte cache lines, and the assumed 64-bit system has 16-word = 128-byte
286 +// cache lines.
287 +
288 +#ifdef JU_64BIT
289 +#define cJU_BYTESPERCL 128 // cache line size in bytes.
290 +#else
291 +#define cJU_BYTESPERCL 64 // cache line size in bytes.
292 +#endif
293 +
294 +// Bits Per Byte:
295 +
296 +#define cJU_BITSPERBYTE 0x8
297 +
298 +// Bytes Per Word and Bits Per Word, latter assuming sizeof(byte) is 8 bits:
299 +//
300 +// Expect 32 [64] bits per word.
301 +
302 +#define cJU_BYTESPERWORD (sizeof(Word_t))
303 +#define cJU_BITSPERWORD (sizeof(Word_t) * cJU_BITSPERBYTE)
304 +
305 +#define JU_BYTESTOWORDS(BYTES) \
306 + (((BYTES) + cJU_BYTESPERWORD - 1) / cJU_BYTESPERWORD)
307 +
308 +// A word that is all-ones, normally equal to -1UL, but safer with ~0:
309 +
310 +#define cJU_ALLONES (~0UL)
311 +
312 +// Note, these are forward references, but thats OK:
313 +
314 +#define cJU_FULLBITMAPB ((BITMAPB_t) cJU_ALLONES)
315 +#define cJU_FULLBITMAPL ((BITMAPL_t) cJU_ALLONES)
316 +
317 +
318 +// ****************************************************************************
319 +// MISCELLANEOUS JUDY-SPECIFIC DECLARATIONS
320 +// ****************************************************************************
321 +
322 +// ROOT STATE:
323 +//
324 +// State at the start of the Judy SM, based on 1 byte decoded per state; equal
325 +// to the number of bytes per Index to decode.
326 +
327 +#define cJU_ROOTSTATE (sizeof(Word_t))
328 +
329 +
330 +// SUBEXPANSES PER STATE:
331 +//
332 +// Number of subexpanses per state traversed, which is the number of JPs in a
333 +// branch (actual or theoretical) and the number of bits in a bitmap.
334 +
335 +#define cJU_SUBEXPPERSTATE 256
336 +
337 +
338 +// LEAF AND VALUE POINTERS:
339 +//
340 +// Some other basic object types are in declared in JudyPrivateBranch.h
341 +// (Pjbl_t, Pjbb_t, Pjbu_t, Pjp_t) or are Judy1/L-specific (Pjlb_t). The
342 +// few remaining types are declared below.
343 +//
344 +// Note: Leaf pointers are cast to different-sized objects depending on the
345 +// leafs level, but are at least addresses (not just numbers), so use void *
346 +// (Pvoid_t), not PWord_t or Word_t for them, except use Pjlw_t for whole-word
347 +// (top-level, root-level) leaves. Value areas, however, are always whole
348 +// words.
349 +//
350 +// Furthermore, use Pjll_t only for generic leaf pointers (for various size
351 +// LeafLs). Use Pjlw_t for LeafWs. Use Pleaf (with type uint8_t *, uint16_t
352 +// *, etc) when the leaf index size is known.
353 +
354 +typedef PWord_t Pjlw_t; // pointer to root-level leaf (whole-word indexes).
355 +typedef Pvoid_t Pjll_t; // pointer to lower-level linear leaf.
356 +
357 +#ifdef JUDYL
358 +typedef PWord_t Pjv_t; // pointer to JudyL value area.
359 +#endif
360 +
361 +
362 +// POINTER PREPARATION MACROS:
363 +//
364 +// These macros are used to strip malloc-namespace-type bits from a pointer +
365 +// malloc-type word (which references any Judy mallocd object that might be
366 +// obtained from other than a direct call of malloc()), prior to dereferencing
367 +// the pointer as an address. The malloc-type bits allow Judy mallocd objects
368 +// to come from different "malloc() namespaces".
369 +//
370 +// (root pointer) (JRP, see above)
371 +// jp.jp_Addr generic pointer to next-level node, except when used
372 +// as a JudyL Immed01 value area
373 +// JU_JBB_PJP macro hides jbbs_Pjp (pointer to JP subarray)
374 +// JL_JLB_PVALUE macro hides jLlbs_PValue (pointer to value subarray)
375 +//
376 +// When setting one of these fields or passing an address to j__udyFree*(), the
377 +// "raw" memory address is used; otherwise the memory address must be passed
378 +// through one of the macros below before its dereferenced.
379 +//
380 +// Note: After much study, the typecasts below appear in the macros rather
381 +// than at the point of use, which is both simpler and allows the compiler to
382 +// do type-checking.
383 +
384 +
385 +#define P_JLW( ADDR) ((Pjlw_t) (ADDR)) // root leaf.
386 +#define P_JPM( ADDR) ((Pjpm_t) (ADDR)) // root JPM.
387 +#define P_JBL( ADDR) ((Pjbl_t) (ADDR)) // BranchL.
388 +#define P_JBB( ADDR) ((Pjbb_t) (ADDR)) // BranchB.
389 +#define P_JBU( ADDR) ((Pjbu_t) (ADDR)) // BranchU.
390 +#define P_JLL( ADDR) ((Pjll_t) (ADDR)) // LeafL.
391 +#define P_JLB( ADDR) ((Pjlb_t) (ADDR)) // LeafB1.
392 +#define P_JP( ADDR) ((Pjp_t) (ADDR)) // JP.
393 +
394 +#ifdef JUDYL
395 +#define P_JV( ADDR) ((Pjv_t) (ADDR)) // &value.
396 +#endif
397 +
398 +
399 +// LEAST BYTES:
400 +//
401 +// Mask for least bytes of a word, and a macro to perform this mask on an
402 +// Index.
403 +//
404 +// Note: This macro has been problematic in the past to get right and to make
405 +// portable. Its not OK on all systems to shift by the full word size. This
406 +// macro should allow shifting by 1..N bytes, where N is the word size, but
407 +// should produce a compiler warning if the macro is called with Bytes == 0.
408 +//
409 +// Warning: JU_LEASTBYTESMASK() is not a constant macro unless Bytes is a
410 +// constant; otherwise it is a variable shift, which is expensive on some
411 +// processors.
412 +
413 +#define JU_LEASTBYTESMASK(BYTES) \
414 + ((0x100UL << (cJU_BITSPERBYTE * ((BYTES) - 1))) - 1)
415 +
416 +#define JU_LEASTBYTES(INDEX,BYTES) ((INDEX) & JU_LEASTBYTESMASK(BYTES))
417 +
418 +
419 +// BITS IN EACH BITMAP SUBEXPANSE FOR BITMAP BRANCH AND LEAF:
420 +//
421 +// The bits per bitmap subexpanse times the number of subexpanses equals a
422 +// constant (cJU_SUBEXPPERSTATE). You can also think of this as a compile-time
423 +// choice of "aspect ratio" for bitmap branches and leaves (which can be set
424 +// independently for each).
425 +//
426 +// A default aspect ratio is hardwired here if not overridden at compile time,
427 +// such as by "EXTCCOPTS=-DBITMAP_BRANCH16x16 make".
428 +
429 +#if (! (defined(BITMAP_BRANCH8x32) || defined(BITMAP_BRANCH16x16) || defined(BITMAP_BRANCH32x8)))
430 +#define BITMAP_BRANCH32x8 1 // 32 bits per subexpanse, 8 subexpanses.
431 +#endif
432 +
433 +#ifdef BITMAP_BRANCH8x32
434 +#define BITMAPB_t uint8_t
435 +#endif
436 +
437 +#ifdef BITMAP_BRANCH16x16
438 +#define BITMAPB_t uint16_t
439 +#endif
440 +
441 +#ifdef BITMAP_BRANCH32x8
442 +#define BITMAPB_t uint32_t
443 +#endif
444 +
445 +// Note: For bitmap leaves, BITMAP_LEAF64x4 is only valid for 64 bit:
446 +//
447 +// Note: Choice of aspect ratio mostly matters for JudyL bitmap leaves. For
448 +// Judy1 the choice doesnt matter much -- the code generated for different
449 +// BITMAP_LEAF* values choices varies, but correctness and performance are the
450 +// same.
451 +
452 +#ifndef JU_64BIT
453 +
454 +#if (! (defined(BITMAP_LEAF8x32) || defined(BITMAP_LEAF16x16) || defined(BITMAP_LEAF32x8)))
455 +#define BITMAP_LEAF32x8 // 32 bits per subexpanse, 8 subexpanses.
456 +#endif
457 +
458 +#else // 32BIT
459 +
460 +#if (! (defined(BITMAP_LEAF8x32) || defined(BITMAP_LEAF16x16) || defined(BITMAP_LEAF32x8) || defined(BITMAP_LEAF64x4)))
461 +#define BITMAP_LEAF64x4 // 64 bits per subexpanse, 4 subexpanses.
462 +
463 +#endif
464 +#endif // JU_64BIT
465 +
466 +#ifdef BITMAP_LEAF8x32
467 +#define BITMAPL_t uint8_t
468 +#endif
469 +
470 +#ifdef BITMAP_LEAF16x16
471 +#define BITMAPL_t uint16_t
472 +#endif
473 +
474 +#ifdef BITMAP_LEAF32x8
475 +#define BITMAPL_t uint32_t
476 +#endif
477 +
478 +#ifdef BITMAP_LEAF64x4
479 +#define BITMAPL_t uint64_t
480 +#endif
481 +
482 +
483 +// EXPORTED DATA AND FUNCTIONS:
484 +
485 +#ifdef JUDY1
486 +extern const uint8_t j__1_BranchBJPPopToWords[];
487 +#endif
488 +
489 +#ifdef JUDYL
490 +extern const uint8_t j__L_BranchBJPPopToWords[];
491 +#endif
492 +
493 +// Fast LeafL search routine used for inlined code:
494 +
495 +#if (! defined(SEARCH_BINARY)) || (! defined(SEARCH_LINEAR))
496 +// default a binary search leaf method
497 +#define SEARCH_BINARY 1
498 +//#define SEARCH_LINEAR 1
499 +#endif
500 +
501 +#ifdef SEARCH_LINEAR
502 +
503 +#define SEARCHLEAFNATIVE(LEAFTYPE,ADDR,POP1,INDEX) \
504 + LEAFTYPE *P_leaf = (LEAFTYPE *)(ADDR); \
505 + LEAFTYPE I_ndex = (INDEX); /* with masking */ \
506 + if (I_ndex > P_leaf[(POP1) - 1]) return(~(POP1)); \
507 + while(I_ndex > *P_leaf) P_leaf++; \
508 + if (I_ndex == *P_leaf) return(P_leaf - (LEAFTYPE *)(ADDR)); \
509 + return(~(P_leaf - (LEAFTYPE *)(ADDR)));
510 +
511 +
512 +#define SEARCHLEAFNONNAT(ADDR,POP1,INDEX,LFBTS,COPYINDEX) \
513 +{ \
514 + uint8_t *P_leaf, *P_leafEnd; \
515 + Word_t i_ndex; \
516 + Word_t I_ndex = JU_LEASTBYTES((INDEX), (LFBTS)); \
517 + Word_t p_op1; \
518 + \
519 + P_leaf = (uint8_t *)(ADDR); \
520 + P_leafEnd = P_leaf + ((POP1) * (LFBTS)); \
521 + \
522 + do { \
523 + JU_COPY3_PINDEX_TO_LONG(i_ndex, P_leaf); \
524 + if (I_ndex <= i_ndex) break; \
525 + P_leaf += (LFBTS); \
526 + } while (P_leaf < P_leafEnd); \
527 + \
528 + p_op1 = (P_leaf - (uint8_t *) (ADDR)) / (LFBTS); \
529 + if (I_ndex == i_ndex) return(p_op1); \
530 + return(~p_op1); \
531 +}
532 +#endif // SEARCH_LINEAR
533 +
534 +#ifdef SEARCH_BINARY
535 +
536 +#define SEARCHLEAFNATIVE(LEAFTYPE,ADDR,POP1,INDEX) \
537 + LEAFTYPE *P_leaf = (LEAFTYPE *)(ADDR); \
538 + LEAFTYPE I_ndex = (LEAFTYPE)INDEX; /* truncate hi bits */ \
539 + Word_t l_ow = cJU_ALLONES; \
540 + Word_t m_id; \
541 + Word_t h_igh = POP1; \
542 + \
543 + while ((h_igh - l_ow) > 1UL) \
544 + { \
545 + m_id = (h_igh + l_ow) / 2; \
546 + if (P_leaf[m_id] > I_ndex) \
547 + h_igh = m_id; \
548 + else \
549 + l_ow = m_id; \
550 + } \
551 + if (l_ow == cJU_ALLONES || P_leaf[l_ow] != I_ndex) \
552 + return(~h_igh); \
553 + return(l_ow)
554 +
555 +
556 +#define SEARCHLEAFNONNAT(ADDR,POP1,INDEX,LFBTS,COPYINDEX) \
557 + uint8_t *P_leaf = (uint8_t *)(ADDR); \
558 + Word_t l_ow = cJU_ALLONES; \
559 + Word_t m_id; \
560 + Word_t h_igh = POP1; \
561 + Word_t I_ndex = JU_LEASTBYTES((INDEX), (LFBTS)); \
562 + Word_t i_ndex; \
563 + \
564 + I_ndex = JU_LEASTBYTES((INDEX), (LFBTS)); \
565 + \
566 + while ((h_igh - l_ow) > 1UL) \
567 + { \
568 + m_id = (h_igh + l_ow) / 2; \
569 + COPYINDEX(i_ndex, &P_leaf[m_id * (LFBTS)]); \
570 + if (i_ndex > I_ndex) \
571 + h_igh = m_id; \
572 + else \
573 + l_ow = m_id; \
574 + } \
575 + if (l_ow == cJU_ALLONES) return(~h_igh); \
576 + \
577 + COPYINDEX(i_ndex, &P_leaf[l_ow * (LFBTS)]); \
578 + if (i_ndex != I_ndex) return(~h_igh); \
579 + return(l_ow)
580 +
581 +#endif // SEARCH_BINARY
582 +
583 +// Fast way to count bits set in 8..32[64]-bit int:
584 +//
585 +// For performance, j__udyCountBits*() are written to take advantage of
586 +// platform-specific features where available.
587 +//
588 +
589 +#ifdef JU_NOINLINE
590 +
591 +extern BITMAPB_t j__udyCountBitsB(BITMAPB_t word);
592 +extern BITMAPL_t j__udyCountBitsL(BITMAPL_t word);
593 +
594 +// Compiler supports inline
595 +
596 +#elif defined(JU_HPUX_IPF)
597 +
598 +#define j__udyCountBitsB(WORD) _Asm_popcnt(WORD)
599 +#define j__udyCountBitsL(WORD) _Asm_popcnt(WORD)
600 +
601 +#elif defined(JU_LINUX_IPF)
602 +
603 +static inline BITMAPB_t j__udyCountBitsB(BITMAPB_t word)
604 +{
605 + BITMAPB_t result;
606 + __asm__ ("popcnt %0=%1" : "=r" (result) : "r" (word));
607 + return(result);
608 +}
609 +
610 +static inline BITMAPL_t j__udyCountBitsL(BITMAPL_t word)
611 +{
612 + BITMAPL_t result;
613 + __asm__ ("popcnt %0=%1" : "=r" (result) : "r" (word));
614 + return(result);
615 +}
616 +
617 +
618 +#else // No instructions available, use inline code
619 +
620 +// ****************************************************************************
621 +// __ J U D Y C O U N T B I T S B
622 +//
623 +// Return the number of bits set in "Word", for a bitmap branch.
624 +//
625 +// Note: Bitmap branches have maximum bitmap size = 32 bits.
626 +
627 +#ifdef JU_WIN
628 +static __inline BITMAPB_t j__udyCountBitsB(BITMAPB_t word)
629 +#else
630 +static inline BITMAPB_t j__udyCountBitsB(BITMAPB_t word)
631 +#endif
632 +{
633 + word = (word & 0x55555555) + ((word & 0xAAAAAAAA) >> 1);
634 + word = (word & 0x33333333) + ((word & 0xCCCCCCCC) >> 2);
635 + word = (word & 0x0F0F0F0F) + ((word & 0xF0F0F0F0) >> 4); // >= 8 bits.
636 +#if defined(BITMAP_BRANCH16x16) || defined(BITMAP_BRANCH32x8)
637 + word = (word & 0x00FF00FF) + ((word & 0xFF00FF00) >> 8); // >= 16 bits.
638 +#endif
639 +
640 +#ifdef BITMAP_BRANCH32x8
641 + word = (word & 0x0000FFFF) + ((word & 0xFFFF0000) >> 16); // >= 32 bits.
642 +#endif
643 + return(word);
644 +
645 +} // j__udyCountBitsB()
646 +
647 +
648 +// ****************************************************************************
649 +// __ J U D Y C O U N T B I T S L
650 +//
651 +// Return the number of bits set in "Word", for a bitmap leaf.
652 +//
653 +// Note: Bitmap branches have maximum bitmap size = 32 bits.
654 +
655 +// Note: Need both 32-bit and 64-bit versions of j__udyCountBitsL() because
656 +// bitmap leaves can have 64-bit bitmaps.
657 +
658 +#ifdef JU_WIN
659 +static __inline BITMAPL_t j__udyCountBitsL(BITMAPL_t word)
660 +#else
661 +static inline BITMAPL_t j__udyCountBitsL(BITMAPL_t word)
662 +#endif
663 +{
664 +#ifndef JU_64BIT
665 +
666 + word = (word & 0x55555555) + ((word & 0xAAAAAAAA) >> 1);
667 + word = (word & 0x33333333) + ((word & 0xCCCCCCCC) >> 2);
668 + word = (word & 0x0F0F0F0F) + ((word & 0xF0F0F0F0) >> 4); // >= 8 bits.
669 +#if defined(BITMAP_LEAF16x16) || defined(BITMAP_LEAF32x8)
670 + word = (word & 0x00FF00FF) + ((word & 0xFF00FF00) >> 8); // >= 16 bits.
671 +#endif
672 +#ifdef BITMAP_LEAF32x8
673 + word = (word & 0x0000FFFF) + ((word & 0xFFFF0000) >> 16); // >= 32 bits.
674 +#endif
675 +
676 +#else // JU_64BIT
677 +
678 + word = (word & 0x5555555555555555) + ((word & 0xAAAAAAAAAAAAAAAA) >> 1);
679 + word = (word & 0x3333333333333333) + ((word & 0xCCCCCCCCCCCCCCCC) >> 2);
680 + word = (word & 0x0F0F0F0F0F0F0F0F) + ((word & 0xF0F0F0F0F0F0F0F0) >> 4);
681 +#if defined(BITMAP_LEAF16x16) || defined(BITMAP_LEAF32x8) || defined(BITMAP_LEAF64x4)
682 + word = (word & 0x00FF00FF00FF00FF) + ((word & 0xFF00FF00FF00FF00) >> 8);
683 +#endif
684 +#if defined(BITMAP_LEAF32x8) || defined(BITMAP_LEAF64x4)
685 + word = (word & 0x0000FFFF0000FFFF) + ((word & 0xFFFF0000FFFF0000) >>16);
686 +#endif
687 +#ifdef BITMAP_LEAF64x4
688 + word = (word & 0x00000000FFFFFFFF) + ((word & 0xFFFFFFFF00000000) >>32);
689 +#endif
690 +#endif // JU_64BIT
691 +
692 + return(word);
693 +
694 +} // j__udyCountBitsL()
695 +
696 +#endif // Compiler supports inline
697 +
698 +// GET POP0:
699 +//
700 +// Get from jp_DcdPopO the Pop0 for various JP Types.
701 +//
702 +// Notes:
703 +//
704 +// - Different macros require different parameters...
705 +//
706 +// - There are no simple macros for cJU_BRANCH* Types because their
707 +// populations must be added up and dont reside in an already-calculated
708 +// place. (TBD: This is no longer true, now its in the JPM.)
709 +//
710 +// - cJU_JPIMM_POP0() is not defined because it would be redundant because the
711 +// Pop1 is already encoded in each enum name.
712 +//
713 +// - A linear or bitmap leaf Pop0 cannot exceed cJU_SUBEXPPERSTATE - 1 (Pop0 =
714 +// 0..255), so use a simpler, faster macro for it than for other JP Types.
715 +//
716 +// - Avoid any complex calculations that would slow down the compiled code.
717 +// Assume these macros are only called for the appropriate JP Types.
718 +// Unfortunately theres no way to trigger an assertion here if the JP type
719 +// is incorrect for the macro, because these are merely expressions, not
720 +// statements.
721 +
722 +#define JU_LEAFW_POP0(JRP) (*P_JLW(JRP))
723 +#define cJU_JPFULLPOPU1_POP0 (cJU_SUBEXPPERSTATE - 1)
724 +
725 +// GET JP Type:
726 +// Since bit fields greater than 32 bits are not supported in some compilers
727 +// the jp_DcdPopO field is expanded to include the jp_Type in the high 8 bits
728 +// of the Word_t.
729 +// First the read macro:
730 +
731 +#define JU_JPTYPE(PJP) ((PJP)->jp_Type)
732 +
733 +#define JU_JPLEAF_POP0(PJP) ((PJP)->jp_DcdP0[sizeof(Word_t) - 2])
734 +
735 +#ifdef JU_64BIT
736 +
737 +#define JU_JPDCDPOP0(PJP) \
738 + ((Word_t)(PJP)->jp_DcdP0[0] << 48 | \
739 + (Word_t)(PJP)->jp_DcdP0[1] << 40 | \
740 + (Word_t)(PJP)->jp_DcdP0[2] << 32 | \
741 + (Word_t)(PJP)->jp_DcdP0[3] << 24 | \
742 + (Word_t)(PJP)->jp_DcdP0[4] << 16 | \
743 + (Word_t)(PJP)->jp_DcdP0[5] << 8 | \
744 + (Word_t)(PJP)->jp_DcdP0[6])
745 +
746 +
747 +#define JU_JPSETADT(PJP,ADDR,DCDPOP0,TYPE) \
748 +{ \
749 + (PJP)->jp_Addr = (ADDR); \
750 + (PJP)->jp_DcdP0[0] = (uint8_t)((Word_t)(DCDPOP0) >> 48); \
751 + (PJP)->jp_DcdP0[1] = (uint8_t)((Word_t)(DCDPOP0) >> 40); \
752 + (PJP)->jp_DcdP0[2] = (uint8_t)((Word_t)(DCDPOP0) >> 32); \
753 + (PJP)->jp_DcdP0[3] = (uint8_t)((Word_t)(DCDPOP0) >> 24); \
754 + (PJP)->jp_DcdP0[4] = (uint8_t)((Word_t)(DCDPOP0) >> 16); \
755 + (PJP)->jp_DcdP0[5] = (uint8_t)((Word_t)(DCDPOP0) >> 8); \
756 + (PJP)->jp_DcdP0[6] = (uint8_t)((Word_t)(DCDPOP0)); \
757 + (PJP)->jp_Type = (TYPE); \
758 +}
759 +
760 +#else // 32 Bit
761 +
762 +#define JU_JPDCDPOP0(PJP) \
763 + ((Word_t)(PJP)->jp_DcdP0[0] << 16 | \
764 + (Word_t)(PJP)->jp_DcdP0[1] << 8 | \
765 + (Word_t)(PJP)->jp_DcdP0[2])
766 +
767 +
768 +#define JU_JPSETADT(PJP,ADDR,DCDPOP0,TYPE) \
769 +{ \
770 + (PJP)->jp_Addr = (ADDR); \
771 + (PJP)->jp_DcdP0[0] = (uint8_t)((Word_t)(DCDPOP0) >> 16); \
772 + (PJP)->jp_DcdP0[1] = (uint8_t)((Word_t)(DCDPOP0) >> 8); \
773 + (PJP)->jp_DcdP0[2] = (uint8_t)((Word_t)(DCDPOP0)); \
774 + (PJP)->jp_Type = (TYPE); \
775 +}
776 +
777 +#endif // 32 Bit
778 +
779 +// NUMBER OF BITS IN A BRANCH OR LEAF BITMAP AND SUBEXPANSE:
780 +//
781 +// Note: cJU_BITSPERBITMAP must be the same as the number of JPs in a branch.
782 +
783 +#define cJU_BITSPERBITMAP cJU_SUBEXPPERSTATE
784 +
785 +// Bitmaps are accessed in units of "subexpanses":
786 +
787 +#define cJU_BITSPERSUBEXPB (sizeof(BITMAPB_t) * cJU_BITSPERBYTE)
788 +#define cJU_NUMSUBEXPB (cJU_BITSPERBITMAP / cJU_BITSPERSUBEXPB)
789 +
790 +#define cJU_BITSPERSUBEXPL (sizeof(BITMAPL_t) * cJU_BITSPERBYTE)
791 +#define cJU_NUMSUBEXPL (cJU_BITSPERBITMAP / cJU_BITSPERSUBEXPL)
792 +
793 +
794 +// MASK FOR A SPECIFIED BIT IN A BITMAP:
795 +//
796 +// Warning: If BitNum is a variable, this results in a variable shift that is
797 +// expensive, at least on some processors. Use with caution.
798 +//
799 +// Warning: BitNum must be less than cJU_BITSPERWORD, that is, 0 ..
800 +// cJU_BITSPERWORD - 1, to avoid a truncated shift on some machines.
801 +//
802 +// TBD: Perhaps use an array[32] of masks instead of calculating them.
803 +
804 +#define JU_BITPOSMASKB(BITNUM) (1L << ((BITNUM) % cJU_BITSPERSUBEXPB))
805 +#define JU_BITPOSMASKL(BITNUM) (1L << ((BITNUM) % cJU_BITSPERSUBEXPL))
806 +
807 +
808 +// TEST/SET/CLEAR A BIT IN A BITMAP LEAF:
809 +//
810 +// Test if a byte-sized Digit (portion of Index) has a corresponding bit set in
811 +// a bitmap, or set a byte-sized Digits bit into a bitmap, by looking up the
812 +// correct subexpanse and then checking/setting the correct bit.
813 +//
814 +// Note: Mask higher bits, if any, for the convenience of the user of this
815 +// macro, in case they pass a full Index, not just a digit. If the caller has
816 +// a true 8-bit digit, make it of type uint8_t and the compiler should skip the
817 +// unnecessary mask step.
818 +
819 +#define JU_SUBEXPL(DIGIT) (((DIGIT) / cJU_BITSPERSUBEXPL) & (cJU_NUMSUBEXPL-1))
820 +
821 +#define JU_BITMAPTESTL(PJLB, INDEX) \
822 + (JU_JLB_BITMAP(PJLB, JU_SUBEXPL(INDEX)) & JU_BITPOSMASKL(INDEX))
823 +
824 +#define JU_BITMAPSETL(PJLB, INDEX) \
825 + (JU_JLB_BITMAP(PJLB, JU_SUBEXPL(INDEX)) |= JU_BITPOSMASKL(INDEX))
826 +
827 +#define JU_BITMAPCLEARL(PJLB, INDEX) \
828 + (JU_JLB_BITMAP(PJLB, JU_SUBEXPL(INDEX)) ^= JU_BITPOSMASKL(INDEX))
829 +
830 +
831 +// MAP BITMAP BIT OFFSET TO DIGIT:
832 +//
833 +// Given a digit variable to set, a bitmap branch or leaf subexpanse (base 0),
834 +// the bitmap (BITMAP*_t) for that subexpanse, and an offset (Nth set bit in
835 +// the bitmap, base 0), compute the digit (also base 0) corresponding to the
836 +// subexpanse and offset by counting all bits in the bitmap until offset+1 set
837 +// bits are seen. Avoid expensive variable shifts. Offset should be less than
838 +// the number of set bits in the bitmap; assert this.
839 +//
840 +// If theres a better way to do this, I dont know what it is.
841 +
842 +#define JU_BITMAPDIGITB(DIGIT,SUBEXP,BITMAP,OFFSET) \
843 + { \
844 + BITMAPB_t bitmap = (BITMAP); int remain = (OFFSET); \
845 + (DIGIT) = (SUBEXP) * cJU_BITSPERSUBEXPB; \
846 + \
847 + while ((remain -= (bitmap & 1)) >= 0) \
848 + { \
849 + bitmap >>= 1; ++(DIGIT); \
850 + assert((DIGIT) < ((SUBEXP) + 1) * cJU_BITSPERSUBEXPB); \
851 + } \
852 + }
853 +
854 +#define JU_BITMAPDIGITL(DIGIT,SUBEXP,BITMAP,OFFSET) \
855 + { \
856 + BITMAPL_t bitmap = (BITMAP); int remain = (OFFSET); \
857 + (DIGIT) = (SUBEXP) * cJU_BITSPERSUBEXPL; \
858 + \
859 + while ((remain -= (bitmap & 1)) >= 0) \
860 + { \
861 + bitmap >>= 1; ++(DIGIT); \
862 + assert((DIGIT) < ((SUBEXP) + 1) * cJU_BITSPERSUBEXPL); \
863 + } \
864 + }
865 +
866 +
867 +// MASKS FOR PORTIONS OF 32-BIT WORDS:
868 +//
869 +// These are useful for bitmap subexpanses.
870 +//
871 +// "LOWER"/"HIGHER" means bits representing lower/higher-valued Indexes. The
872 +// exact order of bits in the word is explicit here but is hidden from the
873 +// caller.
874 +//
875 +// "EXC" means exclusive of the specified bit; "INC" means inclusive.
876 +//
877 +// In each case, BitPos is either "JU_BITPOSMASK*(BitNum)", or a variable saved
878 +// from an earlier call of that macro; either way, it must be a 32-bit word
879 +// with a single bit set. In the first case, assume the compiler is smart
880 +// enough to optimize out common subexpressions.
881 +//
882 +// The expressions depend on unsigned decimal math that should be universal.
883 +
884 +#define JU_MASKLOWEREXC( BITPOS) ((BITPOS) - 1)
885 +#define JU_MASKLOWERINC( BITPOS) (JU_MASKLOWEREXC(BITPOS) | (BITPOS))
886 +#define JU_MASKHIGHERINC(BITPOS) (-(BITPOS))
887 +#define JU_MASKHIGHEREXC(BITPOS) (JU_MASKHIGHERINC(BITPOS) ^ (BITPOS))
888 +
889 +
890 +// ****************************************************************************
891 +// SUPPORT FOR NATIVE INDEX SIZES
892 +// ****************************************************************************
893 +//
894 +// Copy a series of generic objects (uint8_t, uint16_t, uint32_t, Word_t) from
895 +// one place to another.
896 +
897 +#define JU_COPYMEM(PDST,PSRC,POP1) \
898 + { \
899 + Word_t i_ndex = 0; \
900 + assert((POP1) > 0); \
901 + do { (PDST)[i_ndex] = (PSRC)[i_ndex]; } \
902 + while (++i_ndex < (POP1)); \
903 + }
904 +
905 +
906 +// ****************************************************************************
907 +// SUPPORT FOR NON-NATIVE INDEX SIZES
908 +// ****************************************************************************
909 +//
910 +// Copy a 3-byte Index pointed by a uint8_t * to a Word_t:
911 +//
912 +#define JU_COPY3_PINDEX_TO_LONG(DESTLONG,PINDEX) \
913 + DESTLONG = (Word_t)(PINDEX)[0] << 16; \
914 + DESTLONG += (Word_t)(PINDEX)[1] << 8; \
915 + DESTLONG += (Word_t)(PINDEX)[2]
916 +
917 +// Copy a Word_t to a 3-byte Index pointed at by a uint8_t *:
918 +
919 +#define JU_COPY3_LONG_TO_PINDEX(PINDEX,SOURCELONG) \
920 + (PINDEX)[0] = (uint8_t)((SOURCELONG) >> 16); \
921 + (PINDEX)[1] = (uint8_t)((SOURCELONG) >> 8); \
922 + (PINDEX)[2] = (uint8_t)((SOURCELONG))
923 +
924 +#ifdef JU_64BIT
925 +
926 +// Copy a 5-byte Index pointed by a uint8_t * to a Word_t:
927 +//
928 +#define JU_COPY5_PINDEX_TO_LONG(DESTLONG,PINDEX) \
929 + DESTLONG = (Word_t)(PINDEX)[0] << 32; \
930 + DESTLONG += (Word_t)(PINDEX)[1] << 24; \
931 + DESTLONG += (Word_t)(PINDEX)[2] << 16; \
932 + DESTLONG += (Word_t)(PINDEX)[3] << 8; \
933 + DESTLONG += (Word_t)(PINDEX)[4]
934 +
935 +// Copy a Word_t to a 5-byte Index pointed at by a uint8_t *:
936 +
937 +#define JU_COPY5_LONG_TO_PINDEX(PINDEX,SOURCELONG) \
938 + (PINDEX)[0] = (uint8_t)((SOURCELONG) >> 32); \
939 + (PINDEX)[1] = (uint8_t)((SOURCELONG) >> 24); \
940 + (PINDEX)[2] = (uint8_t)((SOURCELONG) >> 16); \
941 + (PINDEX)[3] = (uint8_t)((SOURCELONG) >> 8); \
942 + (PINDEX)[4] = (uint8_t)((SOURCELONG))
943 +
944 +// Copy a 6-byte Index pointed by a uint8_t * to a Word_t:
945 +//
946 +#define JU_COPY6_PINDEX_TO_LONG(DESTLONG,PINDEX) \
947 + DESTLONG = (Word_t)(PINDEX)[0] << 40; \
948 + DESTLONG += (Word_t)(PINDEX)[1] << 32; \
949 + DESTLONG += (Word_t)(PINDEX)[2] << 24; \
950 + DESTLONG += (Word_t)(PINDEX)[3] << 16; \
951 + DESTLONG += (Word_t)(PINDEX)[4] << 8; \
952 + DESTLONG += (Word_t)(PINDEX)[5]
953 +
954 +// Copy a Word_t to a 6-byte Index pointed at by a uint8_t *:
955 +
956 +#define JU_COPY6_LONG_TO_PINDEX(PINDEX,SOURCELONG) \
957 + (PINDEX)[0] = (uint8_t)((SOURCELONG) >> 40); \
958 + (PINDEX)[1] = (uint8_t)((SOURCELONG) >> 32); \
959 + (PINDEX)[2] = (uint8_t)((SOURCELONG) >> 24); \
960 + (PINDEX)[3] = (uint8_t)((SOURCELONG) >> 16); \
961 + (PINDEX)[4] = (uint8_t)((SOURCELONG) >> 8); \
962 + (PINDEX)[5] = (uint8_t)((SOURCELONG))
963 +
964 +// Copy a 7-byte Index pointed by a uint8_t * to a Word_t:
965 +//
966 +#define JU_COPY7_PINDEX_TO_LONG(DESTLONG,PINDEX) \
967 + DESTLONG = (Word_t)(PINDEX)[0] << 48; \
968 + DESTLONG += (Word_t)(PINDEX)[1] << 40; \
969 + DESTLONG += (Word_t)(PINDEX)[2] << 32; \
970 + DESTLONG += (Word_t)(PINDEX)[3] << 24; \
971 + DESTLONG += (Word_t)(PINDEX)[4] << 16; \
972 + DESTLONG += (Word_t)(PINDEX)[5] << 8; \
973 + DESTLONG += (Word_t)(PINDEX)[6]
974 +
975 +// Copy a Word_t to a 7-byte Index pointed at by a uint8_t *:
976 +
977 +#define JU_COPY7_LONG_TO_PINDEX(PINDEX,SOURCELONG) \
978 + (PINDEX)[0] = (uint8_t)((SOURCELONG) >> 48); \
979 + (PINDEX)[1] = (uint8_t)((SOURCELONG) >> 40); \
980 + (PINDEX)[2] = (uint8_t)((SOURCELONG) >> 32); \
981 + (PINDEX)[3] = (uint8_t)((SOURCELONG) >> 24); \
982 + (PINDEX)[4] = (uint8_t)((SOURCELONG) >> 16); \
983 + (PINDEX)[5] = (uint8_t)((SOURCELONG) >> 8); \
984 + (PINDEX)[6] = (uint8_t)((SOURCELONG))
985 +
986 +#endif // JU_64BIT
987 +
988 +// ****************************************************************************
989 +// COMMON CODE FRAGMENTS (MACROS)
990 +// ****************************************************************************
991 +//
992 +// These code chunks are shared between various source files.
993 +
994 +
995 +// SET (REPLACE) ONE DIGIT IN AN INDEX:
996 +//
997 +// To avoid endian issues, use masking and ORing, which operates in a
998 +// big-endian register, rather than treating the Index as an array of bytes,
999 +// though that would be simpler, but would operate in endian-specific memory.
1000 +//
1001 +// TBD: This contains two variable shifts, is that bad?
1002 +
1003 +#define JU_SETDIGIT(INDEX,DIGIT,STATE) \
1004 + (INDEX) = ((INDEX) & (~cJU_MASKATSTATE(STATE))) \
1005 + | (((Word_t) (DIGIT)) \
1006 + << (((STATE) - 1) * cJU_BITSPERBYTE))
1007 +
1008 +// Fast version for single LSB:
1009 +
1010 +#define JU_SETDIGIT1(INDEX,DIGIT) (INDEX) = ((INDEX) & ~0xff) | (DIGIT)
1011 +
1012 +
1013 +// SET (REPLACE) "N" LEAST DIGITS IN AN INDEX:
1014 +
1015 +#define JU_SETDIGITS(INDEX,INDEX2,cSTATE) \
1016 + (INDEX) = ((INDEX ) & (~JU_LEASTBYTESMASK(cSTATE))) \
1017 + | ((INDEX2) & ( JU_LEASTBYTESMASK(cSTATE)))
1018 +
1019 +// COPY DECODE BYTES FROM JP TO INDEX:
1020 +//
1021 +// Modify Index digit(s) to match the bytes in jp_DcdPopO in case one or more
1022 +// branches are skipped and the digits are significant. Its probably faster
1023 +// to just do this unconditionally than to check if its necessary.
1024 +//
1025 +// To avoid endian issues, use masking and ORing, which operates in a
1026 +// big-endian register, rather than treating the Index as an array of bytes,
1027 +// though that would be simpler, but would operate in endian-specific memory.
1028 +//
1029 +// WARNING: Must not call JU_LEASTBYTESMASK (via cJU_DCDMASK) with Bytes =
1030 +// cJU_ROOTSTATE or a bad mask is generated, but there are no Dcd bytes to copy
1031 +// in this case anyway. In fact there are no Dcd bytes unless State <
1032 +// cJU_ROOTSTATE - 1, so dont call this macro except in those cases.
1033 +//
1034 +// TBD: It would be nice to validate jp_DcdPopO against known digits to ensure
1035 +// no corruption, but this is non-trivial.
1036 +
1037 +#define JU_SETDCD(INDEX,PJP,cSTATE) \
1038 + (INDEX) = ((INDEX) & ~cJU_DCDMASK(cSTATE)) \
1039 + | (JU_JPDCDPOP0(PJP) & cJU_DCDMASK(cSTATE))
1040 +
1041 +// INSERT/DELETE AN INDEX IN-PLACE IN MEMORY:
1042 +//
1043 +// Given a pointer to an array of "even" (native), same-sized objects
1044 +// (indexes), the current population of the array, an offset in the array, and
1045 +// a new Index to insert, "shift up" the array elements (Indexes) above the
1046 +// insertion point and insert the new Index. Assume there is sufficient memory
1047 +// to do this.
1048 +//
1049 +// In these macros, "i_offset" is an index offset, and "b_off" is a byte
1050 +// offset for odd Index sizes.
1051 +//
1052 +// Note: Endian issues only arise fro insertion, not deletion, and even for
1053 +// insertion, they are transparent when native (even) objects are used, and
1054 +// handled explicitly for odd (non-native) Index sizes.
1055 +//
1056 +// Note: The following macros are tricky enough that there is some test code
1057 +// for them appended to this file.
1058 +
1059 +#define JU_INSERTINPLACE(PARRAY,POP1,OFFSET,INDEX) \
1060 + assert((long) (POP1) > 0); \
1061 + assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1062 + { \
1063 + Word_t i_offset = (POP1); \
1064 + \
1065 + while (i_offset-- > (OFFSET)) \
1066 + (PARRAY)[i_offset + 1] = (PARRAY)[i_offset]; \
1067 + \
1068 + (PARRAY)[OFFSET] = (INDEX); \
1069 + }
1070 +
1071 +
1072 +// Variation for non-native Indexes, where cIS = Index Size
1073 +// and PByte must point to a uint8_t (byte); shift byte-by-byte:
1074 +//
1075 +
1076 +#define JU_INSERTINPLACE3(PBYTE,POP1,OFFSET,INDEX) \
1077 +{ \
1078 + Word_t i_off = POP1; \
1079 + \
1080 + while (i_off-- > (OFFSET)) \
1081 + { \
1082 + Word_t i_dx = i_off * 3; \
1083 + (PBYTE)[i_dx + 0 + 3] = (PBYTE)[i_dx + 0]; \
1084 + (PBYTE)[i_dx + 1 + 3] = (PBYTE)[i_dx + 1]; \
1085 + (PBYTE)[i_dx + 2 + 3] = (PBYTE)[i_dx + 2]; \
1086 + } \
1087 + JU_COPY3_LONG_TO_PINDEX(&((PBYTE)[(OFFSET) * 3]), INDEX); \
1088 +}
1089 +
1090 +#ifdef JU_64BIT
1091 +
1092 +#define JU_INSERTINPLACE5(PBYTE,POP1,OFFSET,INDEX) \
1093 +{ \
1094 + Word_t i_off = POP1; \
1095 + \
1096 + while (i_off-- > (OFFSET)) \
1097 + { \
1098 + Word_t i_dx = i_off * 5; \
1099 + (PBYTE)[i_dx + 0 + 5] = (PBYTE)[i_dx + 0]; \
1100 + (PBYTE)[i_dx + 1 + 5] = (PBYTE)[i_dx + 1]; \
1101 + (PBYTE)[i_dx + 2 + 5] = (PBYTE)[i_dx + 2]; \
1102 + (PBYTE)[i_dx + 3 + 5] = (PBYTE)[i_dx + 3]; \
1103 + (PBYTE)[i_dx + 4 + 5] = (PBYTE)[i_dx + 4]; \
1104 + } \
1105 + JU_COPY5_LONG_TO_PINDEX(&((PBYTE)[(OFFSET) * 5]), INDEX); \
1106 +}
1107 +
1108 +#define JU_INSERTINPLACE6(PBYTE,POP1,OFFSET,INDEX) \
1109 +{ \
1110 + Word_t i_off = POP1; \
1111 + \
1112 + while (i_off-- > (OFFSET)) \
1113 + { \
1114 + Word_t i_dx = i_off * 6; \
1115 + (PBYTE)[i_dx + 0 + 6] = (PBYTE)[i_dx + 0]; \
1116 + (PBYTE)[i_dx + 1 + 6] = (PBYTE)[i_dx + 1]; \
1117 + (PBYTE)[i_dx + 2 + 6] = (PBYTE)[i_dx + 2]; \
1118 + (PBYTE)[i_dx + 3 + 6] = (PBYTE)[i_dx + 3]; \
1119 + (PBYTE)[i_dx + 4 + 6] = (PBYTE)[i_dx + 4]; \
1120 + (PBYTE)[i_dx + 5 + 6] = (PBYTE)[i_dx + 5]; \
1121 + } \
1122 + JU_COPY6_LONG_TO_PINDEX(&((PBYTE)[(OFFSET) * 6]), INDEX); \
1123 +}
1124 +
1125 +#define JU_INSERTINPLACE7(PBYTE,POP1,OFFSET,INDEX) \
1126 +{ \
1127 + Word_t i_off = POP1; \
1128 + \
1129 + while (i_off-- > (OFFSET)) \
1130 + { \
1131 + Word_t i_dx = i_off * 7; \
1132 + (PBYTE)[i_dx + 0 + 7] = (PBYTE)[i_dx + 0]; \
1133 + (PBYTE)[i_dx + 1 + 7] = (PBYTE)[i_dx + 1]; \
1134 + (PBYTE)[i_dx + 2 + 7] = (PBYTE)[i_dx + 2]; \
1135 + (PBYTE)[i_dx + 3 + 7] = (PBYTE)[i_dx + 3]; \
1136 + (PBYTE)[i_dx + 4 + 7] = (PBYTE)[i_dx + 4]; \
1137 + (PBYTE)[i_dx + 5 + 7] = (PBYTE)[i_dx + 5]; \
1138 + (PBYTE)[i_dx + 6 + 7] = (PBYTE)[i_dx + 6]; \
1139 + } \
1140 + JU_COPY7_LONG_TO_PINDEX(&((PBYTE)[(OFFSET) * 7]), INDEX); \
1141 +}
1142 +#endif // JU_64BIT
1143 +
1144 +// Counterparts to the above for deleting an Index:
1145 +//
1146 +// "Shift down" the array elements starting at the Index to be deleted.
1147 +
1148 +#define JU_DELETEINPLACE(PARRAY,POP1,OFFSET,IGNORE) \
1149 + assert((long) (POP1) > 0); \
1150 + assert((Word_t) (OFFSET) < (Word_t) (POP1)); \
1151 + { \
1152 + Word_t i_offset = (OFFSET); \
1153 + \
1154 + while (++i_offset < (POP1)) \
1155 + (PARRAY)[i_offset - 1] = (PARRAY)[i_offset]; \
1156 + }
1157 +
1158 +// Variation for odd-byte-sized (non-native) Indexes, where cIS = Index Size
1159 +// and PByte must point to a uint8_t (byte); copy byte-by-byte:
1160 +//
1161 +// Note: If cIS == 1, JU_DELETEINPLACE_ODD == JU_DELETEINPLACE.
1162 +//
1163 +// Note: There are no endian issues here because bytes are just shifted as-is,
1164 +// not converted to/from an Index.
1165 +
1166 +#define JU_DELETEINPLACE_ODD(PBYTE,POP1,OFFSET,cIS) \
1167 + assert((long) (POP1) > 0); \
1168 + assert((Word_t) (OFFSET) < (Word_t) (POP1)); \
1169 + { \
1170 + Word_t b_off = (((OFFSET) + 1) * (cIS)) - 1; \
1171 + \
1172 + while (++b_off < ((POP1) * (cIS))) \
1173 + (PBYTE)[b_off - (cIS)] = (PBYTE)[b_off]; \
1174 + }
1175 +
1176 +
1177 +// INSERT/DELETE AN INDEX WHILE COPYING OTHERS:
1178 +//
1179 +// Copy PSource[] to PDest[], where PSource[] has Pop1 elements (Indexes),
1180 +// inserting Index at PDest[Offset]. Unlike JU_*INPLACE*() above, these macros
1181 +// are used when moving Indexes from one memory object to another.
1182 +
1183 +#define JU_INSERTCOPY(PDEST,PSOURCE,POP1,OFFSET,INDEX) \
1184 + assert((long) (POP1) > 0); \
1185 + assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1186 + { \
1187 + Word_t i_offset; \
1188 + \
1189 + for (i_offset = 0; i_offset < (OFFSET); ++i_offset) \
1190 + (PDEST)[i_offset] = (PSOURCE)[i_offset]; \
1191 + \
1192 + (PDEST)[i_offset] = (INDEX); \
1193 + \
1194 + for (/* null */; i_offset < (POP1); ++i_offset) \
1195 + (PDEST)[i_offset + 1] = (PSOURCE)[i_offset]; \
1196 + }
1197 +
1198 +#define JU_INSERTCOPY3(PDEST,PSOURCE,POP1,OFFSET,INDEX) \
1199 +assert((long) (POP1) > 0); \
1200 +assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1201 +{ \
1202 + Word_t o_ff; \
1203 + \
1204 + for (o_ff = 0; o_ff < (OFFSET); o_ff++) \
1205 + { \
1206 + Word_t i_dx = o_ff * 3; \
1207 + (PDEST)[i_dx + 0] = (PSOURCE)[i_dx + 0]; \
1208 + (PDEST)[i_dx + 1] = (PSOURCE)[i_dx + 1]; \
1209 + (PDEST)[i_dx + 2] = (PSOURCE)[i_dx + 2]; \
1210 + } \
1211 + JU_COPY3_LONG_TO_PINDEX(&((PDEST)[(OFFSET) * 3]), INDEX); \
1212 + \
1213 + for (/* null */; o_ff < (POP1); o_ff++) \
1214 + { \
1215 + Word_t i_dx = o_ff * 3; \
1216 + (PDEST)[i_dx + 0 + 3] = (PSOURCE)[i_dx + 0]; \
1217 + (PDEST)[i_dx + 1 + 3] = (PSOURCE)[i_dx + 1]; \
1218 + (PDEST)[i_dx + 2 + 3] = (PSOURCE)[i_dx + 2]; \
1219 + } \
1220 +}
1221 +
1222 +#ifdef JU_64BIT
1223 +
1224 +#define JU_INSERTCOPY5(PDEST,PSOURCE,POP1,OFFSET,INDEX) \
1225 +assert((long) (POP1) > 0); \
1226 +assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1227 +{ \
1228 + Word_t o_ff; \
1229 + \
1230 + for (o_ff = 0; o_ff < (OFFSET); o_ff++) \
1231 + { \
1232 + Word_t i_dx = o_ff * 5; \
1233 + (PDEST)[i_dx + 0] = (PSOURCE)[i_dx + 0]; \
1234 + (PDEST)[i_dx + 1] = (PSOURCE)[i_dx + 1]; \
1235 + (PDEST)[i_dx + 2] = (PSOURCE)[i_dx + 2]; \
1236 + (PDEST)[i_dx + 3] = (PSOURCE)[i_dx + 3]; \
1237 + (PDEST)[i_dx + 4] = (PSOURCE)[i_dx + 4]; \
1238 + } \
1239 + JU_COPY5_LONG_TO_PINDEX(&((PDEST)[(OFFSET) * 5]), INDEX); \
1240 + \
1241 + for (/* null */; o_ff < (POP1); o_ff++) \
1242 + { \
1243 + Word_t i_dx = o_ff * 5; \
1244 + (PDEST)[i_dx + 0 + 5] = (PSOURCE)[i_dx + 0]; \
1245 + (PDEST)[i_dx + 1 + 5] = (PSOURCE)[i_dx + 1]; \
1246 + (PDEST)[i_dx + 2 + 5] = (PSOURCE)[i_dx + 2]; \
1247 + (PDEST)[i_dx + 3 + 5] = (PSOURCE)[i_dx + 3]; \
1248 + (PDEST)[i_dx + 4 + 5] = (PSOURCE)[i_dx + 4]; \
1249 + } \
1250 +}
1251 +
1252 +#define JU_INSERTCOPY6(PDEST,PSOURCE,POP1,OFFSET,INDEX) \
1253 +assert((long) (POP1) > 0); \
1254 +assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1255 +{ \
1256 + Word_t o_ff; \
1257 + \
1258 + for (o_ff = 0; o_ff < (OFFSET); o_ff++) \
1259 + { \
1260 + Word_t i_dx = o_ff * 6; \
1261 + (PDEST)[i_dx + 0] = (PSOURCE)[i_dx + 0]; \
1262 + (PDEST)[i_dx + 1] = (PSOURCE)[i_dx + 1]; \
1263 + (PDEST)[i_dx + 2] = (PSOURCE)[i_dx + 2]; \
1264 + (PDEST)[i_dx + 3] = (PSOURCE)[i_dx + 3]; \
1265 + (PDEST)[i_dx + 4] = (PSOURCE)[i_dx + 4]; \
1266 + (PDEST)[i_dx + 5] = (PSOURCE)[i_dx + 5]; \
1267 + } \
1268 + JU_COPY6_LONG_TO_PINDEX(&((PDEST)[(OFFSET) * 6]), INDEX); \
1269 + \
1270 + for (/* null */; o_ff < (POP1); o_ff++) \
1271 + { \
1272 + Word_t i_dx = o_ff * 6; \
1273 + (PDEST)[i_dx + 0 + 6] = (PSOURCE)[i_dx + 0]; \
1274 + (PDEST)[i_dx + 1 + 6] = (PSOURCE)[i_dx + 1]; \
1275 + (PDEST)[i_dx + 2 + 6] = (PSOURCE)[i_dx + 2]; \
1276 + (PDEST)[i_dx + 3 + 6] = (PSOURCE)[i_dx + 3]; \
1277 + (PDEST)[i_dx + 4 + 6] = (PSOURCE)[i_dx + 4]; \
1278 + (PDEST)[i_dx + 5 + 6] = (PSOURCE)[i_dx + 5]; \
1279 + } \
1280 +}
1281 +
1282 +#define JU_INSERTCOPY7(PDEST,PSOURCE,POP1,OFFSET,INDEX) \
1283 +assert((long) (POP1) > 0); \
1284 +assert((Word_t) (OFFSET) <= (Word_t) (POP1)); \
1285 +{ \
1286 + Word_t o_ff; \
1287 + \
1288 + for (o_ff = 0; o_ff < (OFFSET); o_ff++) \
1289 + { \
1290 + Word_t i_dx = o_ff * 7; \
1291 + (PDEST)[i_dx + 0] = (PSOURCE)[i_dx + 0]; \
1292 + (PDEST)[i_dx + 1] = (PSOURCE)[i_dx + 1]; \
1293 + (PDEST)[i_dx + 2] = (PSOURCE)[i_dx + 2]; \
1294 + (PDEST)[i_dx + 3] = (PSOURCE)[i_dx + 3]; \
1295 + (PDEST)[i_dx + 4] = (PSOURCE)[i_dx + 4]; \
1296 + (PDEST)[i_dx + 5] = (PSOURCE)[i_dx + 5]; \
1297 + (PDEST)[i_dx + 6] = (PSOURCE)[i_dx + 6]; \
1298 + } \
1299 + JU_COPY7_LONG_TO_PINDEX(&((PDEST)[(OFFSET) * 7]), INDEX); \
1300 + \
1301 + for (/* null */; o_ff < (POP1); o_ff++) \
1302 + { \
1303 + Word_t i_dx = o_ff * 7; \
1304 + (PDEST)[i_dx + 0 + 7] = (PSOURCE)[i_dx + 0]; \
1305 + (PDEST)[i_dx + 1 + 7] = (PSOURCE)[i_dx + 1]; \
1306 + (PDEST)[i_dx + 2 + 7] = (PSOURCE)[i_dx + 2]; \
1307 + (PDEST)[i_dx + 3 + 7] = (PSOURCE)[i_dx + 3]; \
1308 + (PDEST)[i_dx + 4 + 7] = (PSOURCE)[i_dx + 4]; \
1309 + (PDEST)[i_dx + 5 + 7] = (PSOURCE)[i_dx + 5]; \
1310 + (PDEST)[i_dx + 6 + 7] = (PSOURCE)[i_dx + 6]; \
1311 + } \
1312 +}
1313 +
1314 +#endif // JU_64BIT
1315 +
1316 +// Counterparts to the above for deleting an Index:
1317 +
1318 +#define JU_DELETECOPY(PDEST,PSOURCE,POP1,OFFSET,IGNORE) \
1319 + assert((long) (POP1) > 0); \
1320 + assert((Word_t) (OFFSET) < (Word_t) (POP1)); \
1321 + { \
1322 + Word_t i_offset; \
1323 + \
1324 + for (i_offset = 0; i_offset < (OFFSET); ++i_offset) \
1325 + (PDEST)[i_offset] = (PSOURCE)[i_offset]; \
1326 + \
1327 + for (++i_offset; i_offset < (POP1); ++i_offset) \
1328 + (PDEST)[i_offset - 1] = (PSOURCE)[i_offset]; \
1329 + }
1330 +
1331 +// Variation for odd-byte-sized (non-native) Indexes, where cIS = Index Size;
1332 +// copy byte-by-byte:
1333 +//
1334 +// Note: There are no endian issues here because bytes are just shifted as-is,
1335 +// not converted to/from an Index.
1336 +//
1337 +// Note: If cIS == 1, JU_DELETECOPY_ODD == JU_DELETECOPY, at least in concept.
1338 +
1339 +#define JU_DELETECOPY_ODD(PDEST,PSOURCE,POP1,OFFSET,cIS) \
1340 + assert((long) (POP1) > 0); \
1341 + assert((Word_t) (OFFSET) < (Word_t) (POP1)); \
1342 + { \
1343 + uint8_t *_Pdest = (uint8_t *) (PDEST); \
1344 + uint8_t *_Psource = (uint8_t *) (PSOURCE); \
1345 + Word_t b_off; \
1346 + \
1347 + for (b_off = 0; b_off < ((OFFSET) * (cIS)); ++b_off) \
1348 + *_Pdest++ = *_Psource++; \
1349 + \
1350 + _Psource += (cIS); \
1351 + \
1352 + for (b_off += (cIS); b_off < ((POP1) * (cIS)); ++b_off) \
1353 + *_Pdest++ = *_Psource++; \
1354 + }
1355 +
1356 +
1357 +// GENERIC RETURN CODE HANDLING FOR JUDY1 (NO VALUE AREAS) AND JUDYL (VALUE
1358 +// AREAS):
1359 +//
1360 +// This common code hides Judy1 versus JudyL details of how to return various
1361 +// conditions, including a pointer to a value area for JudyL.
1362 +//
1363 +// First, define an internal variation of JERR called JERRI (I = int) to make
1364 +// lint happy. We accidentally shipped to 11.11 OEUR with all functions that
1365 +// return int or Word_t using JERR, which is type Word_t, for errors. Lint
1366 +// complains about this for functions that return int. So, internally use
1367 +// JERRI for error returns from the int functions. Experiments show that
1368 +// callers which compare int Foo() to (Word_t) JERR (~0UL) are OK, since JERRI
1369 +// sign-extends to match JERR.
1370 +
1371 +#define JERRI ((int) ~0) // see above.
1372 +
1373 +#ifdef JUDY1
1374 +
1375 +#define JU_RET_FOUND return(1)
1376 +#define JU_RET_NOTFOUND return(0)
1377 +
1378 +// For Judy1, these all "fall through" to simply JU_RET_FOUND, since there is no
1379 +// value area pointer to return:
1380 +
1381 +#define JU_RET_FOUND_LEAFW(PJLW,POP1,OFFSET) JU_RET_FOUND
1382 +
1383 +#define JU_RET_FOUND_JPM(Pjpm) JU_RET_FOUND
1384 +#define JU_RET_FOUND_PVALUE(Pjv,OFFSET) JU_RET_FOUND
1385 +#ifndef JU_64BIT
1386 +#define JU_RET_FOUND_LEAF1(Pjll,POP1,OFFSET) JU_RET_FOUND
1387 +#endif
1388 +#define JU_RET_FOUND_LEAF2(Pjll,POP1,OFFSET) JU_RET_FOUND
1389 +#define JU_RET_FOUND_LEAF3(Pjll,POP1,OFFSET) JU_RET_FOUND
1390 +#ifdef JU_64BIT
1391 +#define JU_RET_FOUND_LEAF4(Pjll,POP1,OFFSET) JU_RET_FOUND
1392 +#define JU_RET_FOUND_LEAF5(Pjll,POP1,OFFSET) JU_RET_FOUND
1393 +#define JU_RET_FOUND_LEAF6(Pjll,POP1,OFFSET) JU_RET_FOUND
1394 +#define JU_RET_FOUND_LEAF7(Pjll,POP1,OFFSET) JU_RET_FOUND
1395 +#endif
1396 +#define JU_RET_FOUND_IMM_01(Pjp) JU_RET_FOUND
1397 +#define JU_RET_FOUND_IMM(Pjp,OFFSET) JU_RET_FOUND
1398 +
1399 +// Note: No JudyL equivalent:
1400 +
1401 +#define JU_RET_FOUND_FULLPOPU1 JU_RET_FOUND
1402 +#define JU_RET_FOUND_LEAF_B1(PJLB,SUBEXP,OFFSET) JU_RET_FOUND
1403 +
1404 +#else // JUDYL
1405 +
1406 +// JU_RET_FOUND // see below; must NOT be defined for JudyL.
1407 +#define JU_RET_NOTFOUND return((PPvoid_t) NULL)
1408 +
1409 +// For JudyL, the location of the value area depends on the JP type and other
1410 +// factors:
1411 +//
1412 +// TBD: The value areas should be accessed via data structures, here and in
1413 +// Dougs code, not by hard-coded address calculations.
1414 +//
1415 +// This is useful in insert/delete code when the value area is returned from
1416 +// lower levels in the JPM:
1417 +
1418 +#define JU_RET_FOUND_JPM(Pjpm) return((PPvoid_t) ((Pjpm)->jpm_PValue))
1419 +
1420 +// This is useful in insert/delete code when the value area location is already
1421 +// computed:
1422 +
1423 +#define JU_RET_FOUND_PVALUE(Pjv,OFFSET) return((PPvoid_t) ((Pjv) + OFFSET))
1424 +
1425 +#define JU_RET_FOUND_LEAFW(PJLW,POP1,OFFSET) \
1426 + return((PPvoid_t) (JL_LEAFWVALUEAREA(PJLW, POP1) + (OFFSET)))
1427 +
1428 +#define JU_RET_FOUND_LEAF1(Pjll,POP1,OFFSET) \
1429 + return((PPvoid_t) (JL_LEAF1VALUEAREA(Pjll, POP1) + (OFFSET)))
1430 +#define JU_RET_FOUND_LEAF2(Pjll,POP1,OFFSET) \
1431 + return((PPvoid_t) (JL_LEAF2VALUEAREA(Pjll, POP1) + (OFFSET)))
1432 +#define JU_RET_FOUND_LEAF3(Pjll,POP1,OFFSET) \
1433 + return((PPvoid_t) (JL_LEAF3VALUEAREA(Pjll, POP1) + (OFFSET)))
1434 +#ifdef JU_64BIT
1435 +#define JU_RET_FOUND_LEAF4(Pjll,POP1,OFFSET) \
1436 + return((PPvoid_t) (JL_LEAF4VALUEAREA(Pjll, POP1) + (OFFSET)))
1437 +#define JU_RET_FOUND_LEAF5(Pjll,POP1,OFFSET) \
1438 + return((PPvoid_t) (JL_LEAF5VALUEAREA(Pjll, POP1) + (OFFSET)))
1439 +#define JU_RET_FOUND_LEAF6(Pjll,POP1,OFFSET) \
1440 + return((PPvoid_t) (JL_LEAF6VALUEAREA(Pjll, POP1) + (OFFSET)))
1441 +#define JU_RET_FOUND_LEAF7(Pjll,POP1,OFFSET) \
1442 + return((PPvoid_t) (JL_LEAF7VALUEAREA(Pjll, POP1) + (OFFSET)))
1443 +#endif
1444 +
1445 +// Note: Here jp_Addr is a value area itself and not an address, so P_JV() is
1446 +// not needed:
1447 +
1448 +#define JU_RET_FOUND_IMM_01(PJP) return((PPvoid_t) (&((PJP)->jp_Addr)))
1449 +
1450 +// Note: Here jp_Addr is a pointer to a separately-mallocd value area, so
1451 +// P_JV() is required; likewise for JL_JLB_PVALUE:
1452 +
1453 +#define JU_RET_FOUND_IMM(PJP,OFFSET) \
1454 + return((PPvoid_t) (P_JV((PJP)->jp_Addr) + (OFFSET)))
1455 +
1456 +#define JU_RET_FOUND_LEAF_B1(PJLB,SUBEXP,OFFSET) \
1457 + return((PPvoid_t) (P_JV(JL_JLB_PVALUE(PJLB, SUBEXP)) + (OFFSET)))
1458 +
1459 +#endif // JUDYL
1460 +
1461 +
1462 +// GENERIC ERROR HANDLING:
1463 +//
1464 +// This is complicated by variations in the needs of the callers of these
1465 +// macros. Only use JU_SET_ERRNO() for PJError, because it can be null; use
1466 +// JU_SET_ERRNO_NONNULL() for Pjpm, which is never null, and also in other
1467 +// cases where the pointer is known not to be null (to save dead branches).
1468 +//
1469 +// Note: Most cases of JU_ERRNO_OVERRUN or JU_ERRNO_CORRUPT should result in
1470 +// an assertion failure in debug code, so they are more likely to be caught, so
1471 +// do that here in each macro.
1472 +
1473 +#define JU_SET_ERRNO(PJError, JErrno) \
1474 + { \
1475 + assert((JErrno) != JU_ERRNO_OVERRUN); \
1476 + assert((JErrno) != JU_ERRNO_CORRUPT); \
1477 + \
1478 + if (PJError != (PJError_t) NULL) \
1479 + { \
1480 + JU_ERRNO(PJError) = (JErrno); \
1481 + JU_ERRID(PJError) = __LINE__; \
1482 + } \
1483 + }
1484 +
1485 +// Variation for callers who know already that PJError is non-null; and, it can
1486 +// also be Pjpm (both PJError_t and Pjpm_t have je_* fields), so only assert it
1487 +// for null, not cast to any specific pointer type:
1488 +
1489 +#define JU_SET_ERRNO_NONNULL(PJError, JErrno) \
1490 + { \
1491 + assert((JErrno) != JU_ERRNO_OVERRUN); \
1492 + assert((JErrno) != JU_ERRNO_CORRUPT); \
1493 + assert(PJError); \
1494 + \
1495 + JU_ERRNO(PJError) = (JErrno); \
1496 + JU_ERRID(PJError) = __LINE__; \
1497 + }
1498 +
1499 +// Variation to copy error info from a (required) JPM to an (optional)
1500 +// PJError_t:
1501 +//
1502 +// Note: The assertions above about JU_ERRNO_OVERRUN and JU_ERRNO_CORRUPT
1503 +// should have already popped, so they are not needed here.
1504 +
1505 +#define JU_COPY_ERRNO(PJError, Pjpm) \
1506 + { \
1507 + if (PJError) \
1508 + { \
1509 + JU_ERRNO(PJError) = (uint8_t)JU_ERRNO(Pjpm); \
1510 + JU_ERRID(PJError) = JU_ERRID(Pjpm); \
1511 + } \
1512 + }
1513 +
1514 +// For JErrno parameter to previous macros upon return from Judy*Alloc*():
1515 +//
1516 +// The memory allocator returns an address of 0 for out of memory,
1517 +// 1..sizeof(Word_t)-1 for corruption (an invalid pointer), otherwise a valid
1518 +// pointer.
1519 +
1520 +#define JU_ALLOC_ERRNO(ADDR) \
1521 + (((void *) (ADDR) != (void *) NULL) ? JU_ERRNO_OVERRUN : JU_ERRNO_NOMEM)
1522 +
1523 +#define JU_CHECKALLOC(Type,Ptr,Retval) \
1524 + if ((Ptr) < (Type) sizeof(Word_t)) \
1525 + { \
1526 + JU_SET_ERRNO(PJError, JU_ALLOC_ERRNO(Ptr)); \
1527 + return(Retval); \
1528 + }
1529 +
1530 +// Leaf search routines
1531 +
1532 +#ifdef JU_NOINLINE
1533 +
1534 +int j__udySearchLeaf1(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1535 +int j__udySearchLeaf2(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1536 +int j__udySearchLeaf3(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1537 +
1538 +#ifdef JU_64BIT
1539 +
1540 +int j__udySearchLeaf4(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1541 +int j__udySearchLeaf5(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1542 +int j__udySearchLeaf6(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1543 +int j__udySearchLeaf7(Pjll_t Pjll, Word_t LeafPop1, Word_t Index);
1544 +
1545 +#endif // JU_64BIT
1546 +
1547 +int j__udySearchLeafW(Pjlw_t Pjlw, Word_t LeafPop1, Word_t Index);
1548 +
1549 +#else // complier support for inline
1550 +
1551 +#ifdef JU_WIN
1552 +static __inline int j__udySearchLeaf1(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1553 +#else
1554 +static inline int j__udySearchLeaf1(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1555 +#endif
1556 +{ SEARCHLEAFNATIVE(uint8_t, Pjll, LeafPop1, Index); }
1557 +
1558 +#ifdef JU_WIN
1559 +static __inline int j__udySearchLeaf2(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1560 +#else
1561 +static inline int j__udySearchLeaf2(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1562 +#endif
1563 +{ SEARCHLEAFNATIVE(uint16_t, Pjll, LeafPop1, Index); }
1564 +
1565 +#ifdef JU_WIN
1566 +static __inline int j__udySearchLeaf3(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1567 +#else
1568 +static inline int j__udySearchLeaf3(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1569 +#endif
1570 +{ SEARCHLEAFNONNAT(Pjll, LeafPop1, Index, 3, JU_COPY3_PINDEX_TO_LONG); }
1571 +
1572 +#ifdef JU_64BIT
1573 +
1574 +#ifdef JU_WIN
1575 +static __inline int j__udySearchLeaf4(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1576 +#else
1577 +static inline int j__udySearchLeaf4(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1578 +#endif
1579 +{ SEARCHLEAFNATIVE(uint32_t, Pjll, LeafPop1, Index); }
1580 +
1581 +#ifdef JU_WIN
1582 +static __inline int j__udySearchLeaf5(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1583 +#else
1584 +static inline int j__udySearchLeaf5(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1585 +#endif
1586 +{ SEARCHLEAFNONNAT(Pjll, LeafPop1, Index, 5, JU_COPY5_PINDEX_TO_LONG); }
1587 +
1588 +#ifdef JU_WIN
1589 +static __inline int j__udySearchLeaf6(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1590 +#else
1591 +static inline int j__udySearchLeaf6(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1592 +#endif
1593 +{ SEARCHLEAFNONNAT(Pjll, LeafPop1, Index, 6, JU_COPY6_PINDEX_TO_LONG); }
1594 +
1595 +#ifdef JU_WIN
1596 +static __inline int j__udySearchLeaf7(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1597 +#else
1598 +static inline int j__udySearchLeaf7(Pjll_t Pjll, Word_t LeafPop1, Word_t Index)
1599 +#endif
1600 +{ SEARCHLEAFNONNAT(Pjll, LeafPop1, Index, 7, JU_COPY7_PINDEX_TO_LONG); }
1601 +
1602 +#endif // JU_64BIT
1603 +
1604 +#ifdef JU_WIN
1605 +static __inline int j__udySearchLeafW(Pjlw_t Pjlw, Word_t LeafPop1, Word_t Index)
1606 +#else
1607 +static inline int j__udySearchLeafW(Pjlw_t Pjlw, Word_t LeafPop1, Word_t Index)
1608 +#endif
1609 +{ SEARCHLEAFNATIVE(Word_t, Pjlw, LeafPop1, Index); }
1610 +
1611 +#endif // compiler support for inline
1612 +
1613 +#endif // ! _JUDYPRIVATE_INCLUDED
libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h new
+485
@@ -0,0 +1,485 @@
1 +#ifndef _JUDYPRIVATE1L_INCLUDED
2 +#define _JUDYPRIVATE1L_INCLUDED
3 +// _________________
4 +//
5 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
6 +//
7 +// This program is free software; you can redistribute it and/or modify it
8 +// under the term of the GNU Lesser General Public License as published by the
9 +// Free Software Foundation; either version 2 of the License, or (at your
10 +// option) any later version.
11 +//
12 +// This program is distributed in the hope that it will be useful, but WITHOUT
13 +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 +// for more details.
16 +//
17 +// You should have received a copy of the GNU Lesser General Public License
18 +// along with this program; if not, write to the Free Software Foundation,
19 +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 +// _________________
21 +
22 +// @(#) $Revision: 4.31 $ $Source: /judy/src/JudyCommon/JudyPrivate1L.h $
23 +
24 +// ****************************************************************************
25 +// Declare common cJU_* names for JP Types that occur in both Judy1 and JudyL,
26 +// for use by code that ifdefs JUDY1 and JUDYL. Only JP Types common to both
27 +// Judy1 and JudyL are #defined here with equivalent cJU_* names. JP Types
28 +// unique to only Judy1 or JudyL are listed in comments, so the type lists
29 +// match the Judy1.h and JudyL.h files.
30 +//
31 +// This file also defines cJU_* for other JP-related constants and functions
32 +// that some shared JUDY1/JUDYL code finds handy.
33 +//
34 +// At least in principle this file should be included AFTER Judy1.h or JudyL.h.
35 +//
36 +// WARNING: This file must be kept consistent with the enums in Judy1.h and
37 +// JudyL.h.
38 +//
39 +// TBD: You might think, why not define common cJU_* enums in, say,
40 +// JudyPrivate.h, and then inherit them into superset enums in Judy1.h and
41 +// JudyL.h? The problem is that the enum lists for each class (cJ1_* and
42 +// cJL_*) must be numerically "packed" into the correct order, for two reasons:
43 +// (1) allow the compiler to generate "tight" switch statements with no wasted
44 +// slots (although this is not very big), and (2) allow calculations using the
45 +// enum values, although this is also not an issue if the calculations are only
46 +// within each cJ*_JPIMMED_*_* class and the members are packed within the
47 +// class.
48 +
49 +#ifdef JUDY1
50 +
51 +#define cJU_JRPNULL cJ1_JRPNULL
52 +#define cJU_JPNULL1 cJ1_JPNULL1
53 +#define cJU_JPNULL2 cJ1_JPNULL2
54 +#define cJU_JPNULL3 cJ1_JPNULL3
55 +#ifdef JU_64BIT
56 +#define cJU_JPNULL4 cJ1_JPNULL4
57 +#define cJU_JPNULL5 cJ1_JPNULL5
58 +#define cJU_JPNULL6 cJ1_JPNULL6
59 +#define cJU_JPNULL7 cJ1_JPNULL7
60 +#endif
61 +#define cJU_JPNULLMAX cJ1_JPNULLMAX
62 +#define cJU_JPBRANCH_L2 cJ1_JPBRANCH_L2
63 +#define cJU_JPBRANCH_L3 cJ1_JPBRANCH_L3
64 +#ifdef JU_64BIT
65 +#define cJU_JPBRANCH_L4 cJ1_JPBRANCH_L4
66 +#define cJU_JPBRANCH_L5 cJ1_JPBRANCH_L5
67 +#define cJU_JPBRANCH_L6 cJ1_JPBRANCH_L6
68 +#define cJU_JPBRANCH_L7 cJ1_JPBRANCH_L7
69 +#endif
70 +#define cJU_JPBRANCH_L cJ1_JPBRANCH_L
71 +#define j__U_BranchBJPPopToWords j__1_BranchBJPPopToWords
72 +#define cJU_JPBRANCH_B2 cJ1_JPBRANCH_B2
73 +#define cJU_JPBRANCH_B3 cJ1_JPBRANCH_B3
74 +#ifdef JU_64BIT
75 +#define cJU_JPBRANCH_B4 cJ1_JPBRANCH_B4
76 +#define cJU_JPBRANCH_B5 cJ1_JPBRANCH_B5
77 +#define cJU_JPBRANCH_B6 cJ1_JPBRANCH_B6
78 +#define cJU_JPBRANCH_B7 cJ1_JPBRANCH_B7
79 +#endif
80 +#define cJU_JPBRANCH_B cJ1_JPBRANCH_B
81 +#define cJU_JPBRANCH_U2 cJ1_JPBRANCH_U2
82 +#define cJU_JPBRANCH_U3 cJ1_JPBRANCH_U3
83 +#ifdef JU_64BIT
84 +#define cJU_JPBRANCH_U4 cJ1_JPBRANCH_U4
85 +#define cJU_JPBRANCH_U5 cJ1_JPBRANCH_U5
86 +#define cJU_JPBRANCH_U6 cJ1_JPBRANCH_U6
87 +#define cJU_JPBRANCH_U7 cJ1_JPBRANCH_U7
88 +#endif
89 +#define cJU_JPBRANCH_U cJ1_JPBRANCH_U
90 +#ifndef JU_64BIT
91 +#define cJU_JPLEAF1 cJ1_JPLEAF1
92 +#endif
93 +#define cJU_JPLEAF2 cJ1_JPLEAF2
94 +#define cJU_JPLEAF3 cJ1_JPLEAF3
95 +#ifdef JU_64BIT
96 +#define cJU_JPLEAF4 cJ1_JPLEAF4
97 +#define cJU_JPLEAF5 cJ1_JPLEAF5
98 +#define cJU_JPLEAF6 cJ1_JPLEAF6
99 +#define cJU_JPLEAF7 cJ1_JPLEAF7
100 +#endif
101 +#define cJU_JPLEAF_B1 cJ1_JPLEAF_B1
102 +// cJ1_JPFULLPOPU1
103 +#define cJU_JPIMMED_1_01 cJ1_JPIMMED_1_01
104 +#define cJU_JPIMMED_2_01 cJ1_JPIMMED_2_01
105 +#define cJU_JPIMMED_3_01 cJ1_JPIMMED_3_01
106 +#ifdef JU_64BIT
107 +#define cJU_JPIMMED_4_01 cJ1_JPIMMED_4_01
108 +#define cJU_JPIMMED_5_01 cJ1_JPIMMED_5_01
109 +#define cJU_JPIMMED_6_01 cJ1_JPIMMED_6_01
110 +#define cJU_JPIMMED_7_01 cJ1_JPIMMED_7_01
111 +#endif
112 +#define cJU_JPIMMED_1_02 cJ1_JPIMMED_1_02
113 +#define cJU_JPIMMED_1_03 cJ1_JPIMMED_1_03
114 +#define cJU_JPIMMED_1_04 cJ1_JPIMMED_1_04
115 +#define cJU_JPIMMED_1_05 cJ1_JPIMMED_1_05
116 +#define cJU_JPIMMED_1_06 cJ1_JPIMMED_1_06
117 +#define cJU_JPIMMED_1_07 cJ1_JPIMMED_1_07
118 +#ifdef JU_64BIT
119 +// cJ1_JPIMMED_1_08
120 +// cJ1_JPIMMED_1_09
121 +// cJ1_JPIMMED_1_10
122 +// cJ1_JPIMMED_1_11
123 +// cJ1_JPIMMED_1_12
124 +// cJ1_JPIMMED_1_13
125 +// cJ1_JPIMMED_1_14
126 +// cJ1_JPIMMED_1_15
127 +#endif
128 +#define cJU_JPIMMED_2_02 cJ1_JPIMMED_2_02
129 +#define cJU_JPIMMED_2_03 cJ1_JPIMMED_2_03
130 +#ifdef JU_64BIT
131 +// cJ1_JPIMMED_2_04
132 +// cJ1_JPIMMED_2_05
133 +// cJ1_JPIMMED_2_06
134 +// cJ1_JPIMMED_2_07
135 +#endif
136 +#define cJU_JPIMMED_3_02 cJ1_JPIMMED_3_02
137 +#ifdef JU_64BIT
138 +// cJ1_JPIMMED_3_03
139 +// cJ1_JPIMMED_3_04
140 +// cJ1_JPIMMED_3_05
141 +// cJ1_JPIMMED_4_02
142 +// cJ1_JPIMMED_4_03
143 +// cJ1_JPIMMED_5_02
144 +// cJ1_JPIMMED_5_03
145 +// cJ1_JPIMMED_6_02
146 +// cJ1_JPIMMED_7_02
147 +#endif
148 +#define cJU_JPIMMED_CAP cJ1_JPIMMED_CAP
149 +
150 +#else // JUDYL ****************************************************************
151 +
152 +#define cJU_JRPNULL cJL_JRPNULL
153 +#define cJU_JPNULL1 cJL_JPNULL1
154 +#define cJU_JPNULL2 cJL_JPNULL2
155 +#define cJU_JPNULL3 cJL_JPNULL3
156 +#ifdef JU_64BIT
157 +#define cJU_JPNULL4 cJL_JPNULL4
158 +#define cJU_JPNULL5 cJL_JPNULL5
159 +#define cJU_JPNULL6 cJL_JPNULL6
160 +#define cJU_JPNULL7 cJL_JPNULL7
161 +#endif
162 +#define cJU_JPNULLMAX cJL_JPNULLMAX
163 +#define cJU_JPBRANCH_L2 cJL_JPBRANCH_L2
164 +#define cJU_JPBRANCH_L3 cJL_JPBRANCH_L3
165 +#ifdef JU_64BIT
166 +#define cJU_JPBRANCH_L4 cJL_JPBRANCH_L4
167 +#define cJU_JPBRANCH_L5 cJL_JPBRANCH_L5
168 +#define cJU_JPBRANCH_L6 cJL_JPBRANCH_L6
169 +#define cJU_JPBRANCH_L7 cJL_JPBRANCH_L7
170 +#endif
171 +#define cJU_JPBRANCH_L cJL_JPBRANCH_L
172 +#define j__U_BranchBJPPopToWords j__L_BranchBJPPopToWords
173 +#define cJU_JPBRANCH_B2 cJL_JPBRANCH_B2
174 +#define cJU_JPBRANCH_B3 cJL_JPBRANCH_B3
175 +#ifdef JU_64BIT
176 +#define cJU_JPBRANCH_B4 cJL_JPBRANCH_B4
177 +#define cJU_JPBRANCH_B5 cJL_JPBRANCH_B5
178 +#define cJU_JPBRANCH_B6 cJL_JPBRANCH_B6
179 +#define cJU_JPBRANCH_B7 cJL_JPBRANCH_B7
180 +#endif
181 +#define cJU_JPBRANCH_B cJL_JPBRANCH_B
182 +#define cJU_JPBRANCH_U2 cJL_JPBRANCH_U2
183 +#define cJU_JPBRANCH_U3 cJL_JPBRANCH_U3
184 +#ifdef JU_64BIT
185 +#define cJU_JPBRANCH_U4 cJL_JPBRANCH_U4
186 +#define cJU_JPBRANCH_U5 cJL_JPBRANCH_U5
187 +#define cJU_JPBRANCH_U6 cJL_JPBRANCH_U6
188 +#define cJU_JPBRANCH_U7 cJL_JPBRANCH_U7
189 +#endif
190 +#define cJU_JPBRANCH_U cJL_JPBRANCH_U
191 +#define cJU_JPLEAF1 cJL_JPLEAF1
192 +#define cJU_JPLEAF2 cJL_JPLEAF2
193 +#define cJU_JPLEAF3 cJL_JPLEAF3
194 +#ifdef JU_64BIT
195 +#define cJU_JPLEAF4 cJL_JPLEAF4
196 +#define cJU_JPLEAF5 cJL_JPLEAF5
197 +#define cJU_JPLEAF6 cJL_JPLEAF6
198 +#define cJU_JPLEAF7 cJL_JPLEAF7
199 +#endif
200 +#define cJU_JPLEAF_B1 cJL_JPLEAF_B1
201 +#define cJU_JPIMMED_1_01 cJL_JPIMMED_1_01
202 +#define cJU_JPIMMED_2_01 cJL_JPIMMED_2_01
203 +#define cJU_JPIMMED_3_01 cJL_JPIMMED_3_01
204 +#ifdef JU_64BIT
205 +#define cJU_JPIMMED_4_01 cJL_JPIMMED_4_01
206 +#define cJU_JPIMMED_5_01 cJL_JPIMMED_5_01
207 +#define cJU_JPIMMED_6_01 cJL_JPIMMED_6_01
208 +#define cJU_JPIMMED_7_01 cJL_JPIMMED_7_01
209 +#endif
210 +#define cJU_JPIMMED_1_02 cJL_JPIMMED_1_02
211 +#define cJU_JPIMMED_1_03 cJL_JPIMMED_1_03
212 +#ifdef JU_64BIT
213 +#define cJU_JPIMMED_1_04 cJL_JPIMMED_1_04
214 +#define cJU_JPIMMED_1_05 cJL_JPIMMED_1_05
215 +#define cJU_JPIMMED_1_06 cJL_JPIMMED_1_06
216 +#define cJU_JPIMMED_1_07 cJL_JPIMMED_1_07
217 +#define cJU_JPIMMED_2_02 cJL_JPIMMED_2_02
218 +#define cJU_JPIMMED_2_03 cJL_JPIMMED_2_03
219 +#define cJU_JPIMMED_3_02 cJL_JPIMMED_3_02
220 +#endif
221 +#define cJU_JPIMMED_CAP cJL_JPIMMED_CAP
222 +
223 +#endif // JUDYL
224 +
225 +
226 +// ****************************************************************************
227 +// cJU*_ other than JP types:
228 +
229 +#ifdef JUDY1
230 +
231 +#define cJU_LEAFW_MAXPOP1 cJ1_LEAFW_MAXPOP1
232 +#ifndef JU_64BIT
233 +#define cJU_LEAF1_MAXPOP1 cJ1_LEAF1_MAXPOP1
234 +#endif
235 +#define cJU_LEAF2_MAXPOP1 cJ1_LEAF2_MAXPOP1
236 +#define cJU_LEAF3_MAXPOP1 cJ1_LEAF3_MAXPOP1
237 +#ifdef JU_64BIT
238 +#define cJU_LEAF4_MAXPOP1 cJ1_LEAF4_MAXPOP1
239 +#define cJU_LEAF5_MAXPOP1 cJ1_LEAF5_MAXPOP1
240 +#define cJU_LEAF6_MAXPOP1 cJ1_LEAF6_MAXPOP1
241 +#define cJU_LEAF7_MAXPOP1 cJ1_LEAF7_MAXPOP1
242 +#endif
243 +#define cJU_IMMED1_MAXPOP1 cJ1_IMMED1_MAXPOP1
244 +#define cJU_IMMED2_MAXPOP1 cJ1_IMMED2_MAXPOP1
245 +#define cJU_IMMED3_MAXPOP1 cJ1_IMMED3_MAXPOP1
246 +#ifdef JU_64BIT
247 +#define cJU_IMMED4_MAXPOP1 cJ1_IMMED4_MAXPOP1
248 +#define cJU_IMMED5_MAXPOP1 cJ1_IMMED5_MAXPOP1
249 +#define cJU_IMMED6_MAXPOP1 cJ1_IMMED6_MAXPOP1
250 +#define cJU_IMMED7_MAXPOP1 cJ1_IMMED7_MAXPOP1
251 +#endif
252 +
253 +#define JU_LEAF1POPTOWORDS(Pop1) J1_LEAF1POPTOWORDS(Pop1)
254 +#define JU_LEAF2POPTOWORDS(Pop1) J1_LEAF2POPTOWORDS(Pop1)
255 +#define JU_LEAF3POPTOWORDS(Pop1) J1_LEAF3POPTOWORDS(Pop1)
256 +#ifdef JU_64BIT
257 +#define JU_LEAF4POPTOWORDS(Pop1) J1_LEAF4POPTOWORDS(Pop1)
258 +#define JU_LEAF5POPTOWORDS(Pop1) J1_LEAF5POPTOWORDS(Pop1)
259 +#define JU_LEAF6POPTOWORDS(Pop1) J1_LEAF6POPTOWORDS(Pop1)
260 +#define JU_LEAF7POPTOWORDS(Pop1) J1_LEAF7POPTOWORDS(Pop1)
261 +#endif
262 +#define JU_LEAFWPOPTOWORDS(Pop1) J1_LEAFWPOPTOWORDS(Pop1)
263 +
264 +#ifndef JU_64BIT
265 +#define JU_LEAF1GROWINPLACE(Pop1) J1_LEAF1GROWINPLACE(Pop1)
266 +#endif
267 +#define JU_LEAF2GROWINPLACE(Pop1) J1_LEAF2GROWINPLACE(Pop1)
268 +#define JU_LEAF3GROWINPLACE(Pop1) J1_LEAF3GROWINPLACE(Pop1)
269 +#ifdef JU_64BIT
270 +#define JU_LEAF4GROWINPLACE(Pop1) J1_LEAF4GROWINPLACE(Pop1)
271 +#define JU_LEAF5GROWINPLACE(Pop1) J1_LEAF5GROWINPLACE(Pop1)
272 +#define JU_LEAF6GROWINPLACE(Pop1) J1_LEAF6GROWINPLACE(Pop1)
273 +#define JU_LEAF7GROWINPLACE(Pop1) J1_LEAF7GROWINPLACE(Pop1)
274 +#endif
275 +#define JU_LEAFWGROWINPLACE(Pop1) J1_LEAFWGROWINPLACE(Pop1)
276 +
277 +#define j__udyCreateBranchL j__udy1CreateBranchL
278 +#define j__udyCreateBranchB j__udy1CreateBranchB
279 +#define j__udyCreateBranchU j__udy1CreateBranchU
280 +#define j__udyCascade1 j__udy1Cascade1
281 +#define j__udyCascade2 j__udy1Cascade2
282 +#define j__udyCascade3 j__udy1Cascade3
283 +#ifdef JU_64BIT
284 +#define j__udyCascade4 j__udy1Cascade4
285 +#define j__udyCascade5 j__udy1Cascade5
286 +#define j__udyCascade6 j__udy1Cascade6
287 +#define j__udyCascade7 j__udy1Cascade7
288 +#endif
289 +#define j__udyCascadeL j__udy1CascadeL
290 +#define j__udyInsertBranch j__udy1InsertBranch
291 +
292 +#define j__udyBranchBToBranchL j__udy1BranchBToBranchL
293 +#ifndef JU_64BIT
294 +#define j__udyLeafB1ToLeaf1 j__udy1LeafB1ToLeaf1
295 +#endif
296 +#define j__udyLeaf1ToLeaf2 j__udy1Leaf1ToLeaf2
297 +#define j__udyLeaf2ToLeaf3 j__udy1Leaf2ToLeaf3
298 +#ifndef JU_64BIT
299 +#define j__udyLeaf3ToLeafW j__udy1Leaf3ToLeafW
300 +#else
301 +#define j__udyLeaf3ToLeaf4 j__udy1Leaf3ToLeaf4
302 +#define j__udyLeaf4ToLeaf5 j__udy1Leaf4ToLeaf5
303 +#define j__udyLeaf5ToLeaf6 j__udy1Leaf5ToLeaf6
304 +#define j__udyLeaf6ToLeaf7 j__udy1Leaf6ToLeaf7
305 +#define j__udyLeaf7ToLeafW j__udy1Leaf7ToLeafW
306 +#endif
307 +
308 +#define jpm_t j1pm_t
309 +#define Pjpm_t Pj1pm_t
310 +
311 +#define jlb_t j1lb_t
312 +#define Pjlb_t Pj1lb_t
313 +
314 +#define JU_JLB_BITMAP J1_JLB_BITMAP
315 +
316 +#define j__udyAllocJPM j__udy1AllocJ1PM
317 +#define j__udyAllocJBL j__udy1AllocJBL
318 +#define j__udyAllocJBB j__udy1AllocJBB
319 +#define j__udyAllocJBBJP j__udy1AllocJBBJP
320 +#define j__udyAllocJBU j__udy1AllocJBU
321 +#ifndef JU_64BIT
322 +#define j__udyAllocJLL1 j__udy1AllocJLL1
323 +#endif
324 +#define j__udyAllocJLL2 j__udy1AllocJLL2
325 +#define j__udyAllocJLL3 j__udy1AllocJLL3
326 +#ifdef JU_64BIT
327 +#define j__udyAllocJLL4 j__udy1AllocJLL4
328 +#define j__udyAllocJLL5 j__udy1AllocJLL5
329 +#define j__udyAllocJLL6 j__udy1AllocJLL6
330 +#define j__udyAllocJLL7 j__udy1AllocJLL7
331 +#endif
332 +#define j__udyAllocJLW j__udy1AllocJLW
333 +#define j__udyAllocJLB1 j__udy1AllocJLB1
334 +#define j__udyFreeJPM j__udy1FreeJ1PM
335 +#define j__udyFreeJBL j__udy1FreeJBL
336 +#define j__udyFreeJBB j__udy1FreeJBB
337 +#define j__udyFreeJBBJP j__udy1FreeJBBJP
338 +#define j__udyFreeJBU j__udy1FreeJBU
339 +#ifndef JU_64BIT
340 +#define j__udyFreeJLL1 j__udy1FreeJLL1
341 +#endif
342 +#define j__udyFreeJLL2 j__udy1FreeJLL2
343 +#define j__udyFreeJLL3 j__udy1FreeJLL3
344 +#ifdef JU_64BIT
345 +#define j__udyFreeJLL4 j__udy1FreeJLL4
346 +#define j__udyFreeJLL5 j__udy1FreeJLL5
347 +#define j__udyFreeJLL6 j__udy1FreeJLL6
348 +#define j__udyFreeJLL7 j__udy1FreeJLL7
349 +#endif
350 +#define j__udyFreeJLW j__udy1FreeJLW
351 +#define j__udyFreeJLB1 j__udy1FreeJLB1
352 +#define j__udyFreeSM j__udy1FreeSM
353 +
354 +#define j__uMaxWords j__u1MaxWords
355 +
356 +#ifdef DEBUG
357 +#define JudyCheckPop Judy1CheckPop
358 +#endif
359 +
360 +#else // JUDYL ****************************************************************
361 +
362 +#define cJU_LEAFW_MAXPOP1 cJL_LEAFW_MAXPOP1
363 +#define cJU_LEAF1_MAXPOP1 cJL_LEAF1_MAXPOP1
364 +#define cJU_LEAF2_MAXPOP1 cJL_LEAF2_MAXPOP1
365 +#define cJU_LEAF3_MAXPOP1 cJL_LEAF3_MAXPOP1
366 +#ifdef JU_64BIT
367 +#define cJU_LEAF4_MAXPOP1 cJL_LEAF4_MAXPOP1
368 +#define cJU_LEAF5_MAXPOP1 cJL_LEAF5_MAXPOP1
369 +#define cJU_LEAF6_MAXPOP1 cJL_LEAF6_MAXPOP1
370 +#define cJU_LEAF7_MAXPOP1 cJL_LEAF7_MAXPOP1
371 +#endif
372 +#define cJU_IMMED1_MAXPOP1 cJL_IMMED1_MAXPOP1
373 +#define cJU_IMMED2_MAXPOP1 cJL_IMMED2_MAXPOP1
374 +#define cJU_IMMED3_MAXPOP1 cJL_IMMED3_MAXPOP1
375 +#ifdef JU_64BIT
376 +#define cJU_IMMED4_MAXPOP1 cJL_IMMED4_MAXPOP1
377 +#define cJU_IMMED5_MAXPOP1 cJL_IMMED5_MAXPOP1
378 +#define cJU_IMMED6_MAXPOP1 cJL_IMMED6_MAXPOP1
379 +#define cJU_IMMED7_MAXPOP1 cJL_IMMED7_MAXPOP1
380 +#endif
381 +
382 +#define JU_LEAF1POPTOWORDS(Pop1) JL_LEAF1POPTOWORDS(Pop1)
383 +#define JU_LEAF2POPTOWORDS(Pop1) JL_LEAF2POPTOWORDS(Pop1)
384 +#define JU_LEAF3POPTOWORDS(Pop1) JL_LEAF3POPTOWORDS(Pop1)
385 +#ifdef JU_64BIT
386 +#define JU_LEAF4POPTOWORDS(Pop1) JL_LEAF4POPTOWORDS(Pop1)
387 +#define JU_LEAF5POPTOWORDS(Pop1) JL_LEAF5POPTOWORDS(Pop1)
388 +#define JU_LEAF6POPTOWORDS(Pop1) JL_LEAF6POPTOWORDS(Pop1)
389 +#define JU_LEAF7POPTOWORDS(Pop1) JL_LEAF7POPTOWORDS(Pop1)
390 +#endif
391 +#define JU_LEAFWPOPTOWORDS(Pop1) JL_LEAFWPOPTOWORDS(Pop1)
392 +
393 +#define JU_LEAF1GROWINPLACE(Pop1) JL_LEAF1GROWINPLACE(Pop1)
394 +#define JU_LEAF2GROWINPLACE(Pop1) JL_LEAF2GROWINPLACE(Pop1)
395 +#define JU_LEAF3GROWINPLACE(Pop1) JL_LEAF3GROWINPLACE(Pop1)
396 +#ifdef JU_64BIT
397 +#define JU_LEAF4GROWINPLACE(Pop1) JL_LEAF4GROWINPLACE(Pop1)
398 +#define JU_LEAF5GROWINPLACE(Pop1) JL_LEAF5GROWINPLACE(Pop1)
399 +#define JU_LEAF6GROWINPLACE(Pop1) JL_LEAF6GROWINPLACE(Pop1)
400 +#define JU_LEAF7GROWINPLACE(Pop1) JL_LEAF7GROWINPLACE(Pop1)
401 +#endif
402 +#define JU_LEAFWGROWINPLACE(Pop1) JL_LEAFWGROWINPLACE(Pop1)
403 +
404 +#define j__udyCreateBranchL j__udyLCreateBranchL
405 +#define j__udyCreateBranchB j__udyLCreateBranchB
406 +#define j__udyCreateBranchU j__udyLCreateBranchU
407 +#define j__udyCascade1 j__udyLCascade1
408 +#define j__udyCascade2 j__udyLCascade2
409 +#define j__udyCascade3 j__udyLCascade3
410 +#ifdef JU_64BIT
411 +#define j__udyCascade4 j__udyLCascade4
412 +#define j__udyCascade5 j__udyLCascade5
413 +#define j__udyCascade6 j__udyLCascade6
414 +#define j__udyCascade7 j__udyLCascade7
415 +#endif
416 +#define j__udyCascadeL j__udyLCascadeL
417 +#define j__udyInsertBranch j__udyLInsertBranch
418 +
419 +#define j__udyBranchBToBranchL j__udyLBranchBToBranchL
420 +#define j__udyLeafB1ToLeaf1 j__udyLLeafB1ToLeaf1
421 +#define j__udyLeaf1ToLeaf2 j__udyLLeaf1ToLeaf2
422 +#define j__udyLeaf2ToLeaf3 j__udyLLeaf2ToLeaf3
423 +#ifndef JU_64BIT
424 +#define j__udyLeaf3ToLeafW j__udyLLeaf3ToLeafW
425 +#else
426 +#define j__udyLeaf3ToLeaf4 j__udyLLeaf3ToLeaf4
427 +#define j__udyLeaf4ToLeaf5 j__udyLLeaf4ToLeaf5
428 +#define j__udyLeaf5ToLeaf6 j__udyLLeaf5ToLeaf6
429 +#define j__udyLeaf6ToLeaf7 j__udyLLeaf6ToLeaf7
430 +#define j__udyLeaf7ToLeafW j__udyLLeaf7ToLeafW
431 +#endif
432 +
433 +#define jpm_t jLpm_t
434 +#define Pjpm_t PjLpm_t
435 +
436 +#define jlb_t jLlb_t
437 +#define Pjlb_t PjLlb_t
438 +
439 +#define JU_JLB_BITMAP JL_JLB_BITMAP
440 +
441 +#define j__udyAllocJPM j__udyLAllocJLPM
442 +#define j__udyAllocJBL j__udyLAllocJBL
443 +#define j__udyAllocJBB j__udyLAllocJBB
444 +#define j__udyAllocJBBJP j__udyLAllocJBBJP
445 +#define j__udyAllocJBU j__udyLAllocJBU
446 +#define j__udyAllocJLL1 j__udyLAllocJLL1
447 +#define j__udyAllocJLL2 j__udyLAllocJLL2
448 +#define j__udyAllocJLL3 j__udyLAllocJLL3
449 +#ifdef JU_64BIT
450 +#define j__udyAllocJLL4 j__udyLAllocJLL4
451 +#define j__udyAllocJLL5 j__udyLAllocJLL5
452 +#define j__udyAllocJLL6 j__udyLAllocJLL6
453 +#define j__udyAllocJLL7 j__udyLAllocJLL7
454 +#endif
455 +#define j__udyAllocJLW j__udyLAllocJLW
456 +#define j__udyAllocJLB1 j__udyLAllocJLB1
457 +// j__udyLAllocJV
458 +#define j__udyFreeJPM j__udyLFreeJLPM
459 +#define j__udyFreeJBL j__udyLFreeJBL
460 +#define j__udyFreeJBB j__udyLFreeJBB
461 +#define j__udyFreeJBBJP j__udyLFreeJBBJP
462 +#define j__udyFreeJBU j__udyLFreeJBU
463 +#define j__udyFreeJLL1 j__udyLFreeJLL1
464 +#define j__udyFreeJLL2 j__udyLFreeJLL2
465 +#define j__udyFreeJLL3 j__udyLFreeJLL3
466 +#ifdef JU_64BIT
467 +#define j__udyFreeJLL4 j__udyLFreeJLL4
468 +#define j__udyFreeJLL5 j__udyLFreeJLL5
469 +#define j__udyFreeJLL6 j__udyLFreeJLL6
470 +#define j__udyFreeJLL7 j__udyLFreeJLL7
471 +#endif
472 +#define j__udyFreeJLW j__udyLFreeJLW
473 +#define j__udyFreeJLB1 j__udyLFreeJLB1
474 +#define j__udyFreeSM j__udyLFreeSM
475 +// j__udyLFreeJV
476 +
477 +#define j__uMaxWords j__uLMaxWords
478 +
479 +#ifdef DEBUG
480 +#define JudyCheckPop JudyLCheckPop
481 +#endif
482 +
483 +#endif // JUDYL
484 +
485 +#endif // _JUDYPRIVATE1L_INCLUDED
libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h new
+788
@@ -0,0 +1,788 @@
1 +#ifndef _JUDY_PRIVATE_BRANCH_INCLUDED
2 +#define _JUDY_PRIVATE_BRANCH_INCLUDED
3 +// _________________
4 +//
5 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
6 +//
7 +// This program is free software; you can redistribute it and/or modify it
8 +// under the term of the GNU Lesser General Public License as published by the
9 +// Free Software Foundation; either version 2 of the License, or (at your
10 +// option) any later version.
11 +//
12 +// This program is distributed in the hope that it will be useful, but WITHOUT
13 +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 +// for more details.
16 +//
17 +// You should have received a copy of the GNU Lesser General Public License
18 +// along with this program; if not, write to the Free Software Foundation,
19 +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 +// _________________
21 +
22 +// @(#) $Revision: 1.2 $ $Source: /home/doug/judy-1.0.5_min/test/../src/JudyCommon/RCS/JudyPrivateBranch.h,v $
23 +//
24 +// Header file for all Judy sources, for global but private (non-exported)
25 +// declarations specific to branch support.
26 +//
27 +// See also the "Judy Shop Manual" (try judy/doc/int/JudyShopManual.*).
28 +
29 +
30 +// ****************************************************************************
31 +// JUDY POINTER (JP) SUPPORT
32 +// ****************************************************************************
33 +//
34 +// This "rich pointer" object is pivotal to Judy execution.
35 +//
36 +// JP CONTAINING OTHER THAN IMMEDIATE INDEXES:
37 +//
38 +// If the JP points to a linear or bitmap leaf, jp_DcdPopO contains the
39 +// Population-1 in LSbs and Decode (Dcd) bytes in the MSBs. (In practice the
40 +// Decode bits are masked off while accessing the Pop0 bits.)
41 +//
42 +// The Decode Size, the number of Dcd bytes available, is encoded in jpo_Type.
43 +// It can also be thought of as the number of states "skipped" in the SM, where
44 +// each state decodes 8 bits = 1 byte.
45 +//
46 +// TBD: Dont need two structures, except possibly to force jp_Type to highest
47 +// address!
48 +//
49 +// Note: The jpo_u union is not required by HP-UX or Linux but Win32 because
50 +// the cl.exe compiler otherwise refuses to pack a bitfield (DcdPopO) with
51 +// anything else, even with the -Zp option. This is pretty ugly, but
52 +// fortunately portable, and its all hide-able by macros (see below).
53 +
54 +typedef struct J_UDY_POINTER_OTHERS // JPO.
55 + {
56 + Word_t j_po_Addr; // first word: Pjp_t, Word_t, etc.
57 + union {
58 + Word_t j_po_Addr1;
59 + uint8_t j_po_DcdP0[sizeof(Word_t) - 1];
60 + uint8_t j_po_Bytes[sizeof(Word_t)]; // last byte = jp_Type.
61 + } jpo_u;
62 + } jpo_t;
63 +
64 +
65 +// JP CONTAINING IMMEDIATE INDEXES:
66 +//
67 +// j_pi_1Index[] plus j_pi_LIndex[] together hold as many N-byte (1..3-byte
68 +// [1..7-byte]) Indexes as will fit in sizeof(jpi_t) less 1 byte for j_pi_Type
69 +// (that is, 7..1 [15..1] Indexes).
70 +//
71 +// For Judy1, j_pi_1Index[] is used and j_pi_LIndex[] is not used.
72 +// For JudyL, j_pi_LIndex[] is used and j_pi_1Index[] is not used.
73 +//
74 +// Note: Actually when Pop1 = 1, jpi_t is not used, and the least bytes of the
75 +// single Index are stored in j_po_DcdPopO, for both Judy1 and JudyL, so for
76 +// JudyL the j_po_Addr field can hold the target value.
77 +//
78 +// TBD: Revise this structure to not overload j_po_DcdPopO this way? The
79 +// current arrangement works, its just confusing.
80 +
81 +typedef struct _JUDY_POINTER_IMMEDL
82 + {
83 + Word_t j_pL_Addr;
84 + uint8_t j_pL_LIndex[sizeof(Word_t) - 1]; // see above.
85 + uint8_t j_pL_Type;
86 + } jpL_t;
87 +
88 +typedef struct _JUDY_POINTER_IMMED1
89 + {
90 + uint8_t j_p1_1Index[(2 * sizeof(Word_t)) - 1];
91 + uint8_t j_p1_Type;
92 + } jp1_t;
93 +
94 +// UNION OF JP TYPES:
95 +//
96 +// A branch is an array of cJU_BRANCHUNUMJPS (256) of this object, or an
97 +// alternate data type such as: A linear branch which is a list of 2..7 JPs,
98 +// or a bitmap branch which contains 8 lists of 0..32 JPs. JPs reside only in
99 +// branches of a Judy SM.
100 +
101 +typedef union J_UDY_POINTER // JP.
102 + {
103 + jpo_t j_po; // other than immediate indexes.
104 + jpL_t j_pL; // immediate indexes.
105 + jp1_t j_p1; // immediate indexes.
106 + } jp_t, *Pjp_t;
107 +
108 +// For coding convenience:
109 +//
110 +// Note, jp_Type has the same bits in jpo_t jpL_t and jp1_t.
111 +
112 +#define jp_1Index j_p1.j_p1_1Index // for storing Indexes in first word.
113 +#define jp_LIndex j_pL.j_pL_LIndex // for storing Indexes in second word.
114 +#define jp_Addr j_po.j_po_Addr
115 +#define jp_Addr1 j_po.jpo_u.j_po_Addr1
116 +//#define jp_DcdPop0 j_po.jpo_u.j_po_DcdPop0
117 +#define jp_Addr1 j_po.jpo_u.j_po_Addr1
118 +//#define jp_Type j_po.jpo_u.j_po_Bytes[sizeof(Word_t) - 1]
119 +#define jp_Type j_p1.j_p1_Type
120 +#define jp_DcdP0 j_po.jpo_u.j_po_DcdP0
121 +
122 +
123 +// ****************************************************************************
124 +// JUDY POINTER (JP) -- RELATED MACROS AND CONSTANTS
125 +// ****************************************************************************
126 +
127 +// EXTRACT VALUES FROM JP:
128 +//
129 +// Masks for the bytes in the Dcd and Pop0 parts of jp_DcdPopO:
130 +//
131 +// cJU_DCDMASK() consists of a mask that excludes the (LSb) Pop0 bytes and
132 +// also, just to be safe, the top byte of the word, since jp_DcdPopO is 1 byte
133 +// less than a full word.
134 +//
135 +// Note: These are constant macros (cJU) because cPopBytes should be a
136 +// constant. Also note cPopBytes == state in the SM.
137 +
138 +#define cJU_POP0MASK(cPopBytes) JU_LEASTBYTESMASK(cPopBytes)
139 +
140 +#define cJU_DCDMASK(cPopBytes) \
141 + ((cJU_ALLONES >> cJU_BITSPERBYTE) & (~cJU_POP0MASK(cPopBytes)))
142 +
143 +// Mask off the high byte from INDEX to it can be compared to DcdPopO:
144 +
145 +#define JU_TRIMTODCDSIZE(INDEX) ((cJU_ALLONES >> cJU_BITSPERBYTE) & (INDEX))
146 +
147 +// Get from jp_DcdPopO the Pop0 for various branch JP Types:
148 +//
149 +// Note: There are no simple macros for cJU_BRANCH* Types because their
150 +// populations must be added up and dont reside in an already-calculated
151 +// place.
152 +
153 +#define JU_JPBRANCH_POP0(PJP,cPopBytes) \
154 + (JU_JPDCDPOP0(PJP) & cJU_POP0MASK(cPopBytes))
155 +
156 +// METHOD FOR DETERMINING IF OBJECTS HAVE ROOM TO GROW:
157 +//
158 +// J__U_GROWCK() is a generic method to determine if an object can grow in
159 +// place, based on whether the next population size (one more) would use the
160 +// same space.
161 +
162 +#define J__U_GROWCK(POP1,MAXPOP1,POPTOWORDS) \
163 + (((POP1) != (MAXPOP1)) && (POPTOWORDS[POP1] == POPTOWORDS[(POP1) + 1]))
164 +
165 +#define JU_BRANCHBJPGROWINPLACE(NumJPs) \
166 + J__U_GROWCK(NumJPs, cJU_BITSPERSUBEXPB, j__U_BranchBJPPopToWords)
167 +
168 +
169 +// DETERMINE IF AN INDEX IS (NOT) IN A JPS EXPANSE:
170 +
171 +#define JU_DCDNOTMATCHINDEX(INDEX,PJP,POP0BYTES) \
172 + (((INDEX) ^ JU_JPDCDPOP0(PJP)) & cJU_DCDMASK(POP0BYTES))
173 +
174 +
175 +// NUMBER OF JPs IN AN UNCOMPRESSED BRANCH:
176 +//
177 +// An uncompressed branch is simply an array of 256 Judy Pointers (JPs). It is
178 +// a minimum cacheline fill object. Define it here before its first needed.
179 +
180 +#define cJU_BRANCHUNUMJPS cJU_SUBEXPPERSTATE
181 +
182 +
183 +// ****************************************************************************
184 +// JUDY BRANCH LINEAR (JBL) SUPPORT
185 +// ****************************************************************************
186 +//
187 +// A linear branch is a way of compressing empty expanses (null JPs) out of an
188 +// uncompressed 256-way branch, when the number of populated expanses is so
189 +// small that even a bitmap branch is excessive.
190 +//
191 +// The maximum number of JPs in a Judy linear branch:
192 +//
193 +// Note: This number results in a 1-cacheline sized structure. Previous
194 +// versions had a larger struct so a linear branch didnt become a bitmap
195 +// branch until the memory consumed was even, but for speed, its better to
196 +// switch "sooner" and keep a linear branch fast.
197 +
198 +#define cJU_BRANCHLMAXJPS 7
199 +
200 +
201 +// LINEAR BRANCH STRUCT:
202 +//
203 +// 1-byte count, followed by array of byte-sized expanses, followed by JPs.
204 +
205 +typedef struct J__UDY_BRANCH_LINEAR
206 + {
207 + uint8_t jbl_NumJPs; // num of JPs (Pjp_t), 1..N.
208 + uint8_t jbl_Expanse[cJU_BRANCHLMAXJPS]; // 1..7 MSbs of pop exps.
209 + jp_t jbl_jp [cJU_BRANCHLMAXJPS]; // JPs for populated exps.
210 + } jbl_t, * Pjbl_t;
211 +
212 +
213 +// ****************************************************************************
214 +// JUDY BRANCH BITMAP (JBB) SUPPORT
215 +// ****************************************************************************
216 +//
217 +// A bitmap branch is a way of compressing empty expanses (null JPs) out of
218 +// uncompressed 256-way branch. This costs 1 additional cache line fill, but
219 +// can save a lot of memory when it matters most, near the leaves, and
220 +// typically there will be only one at most in the path to any Index (leaf).
221 +//
222 +// The bitmap indicates which of the cJU_BRANCHUNUMJPS (256) JPs in the branch
223 +// are NOT null, that is, their expanses are populated. The jbb_t also
224 +// contains N pointers to "mini" Judy branches ("subexpanses") of up to M JPs
225 +// each (see BITMAP_BRANCHMxN, for example, BITMAP_BRANCH32x8), where M x N =
226 +// cJU_BRANCHUNUMJPS. These are dynamically allocated and never contain
227 +// cJ*_JPNULL* jp_Types. An empty subexpanse is represented by no bit sets in
228 +// the corresponding subexpanse bitmap, in which case the corresponding
229 +// jbbs_Pjp pointers value is unused.
230 +//
231 +// Note that the number of valid JPs in each 1-of-N subexpanses is determined
232 +// by POPULATION rather than by EXPANSE -- the desired outcome to save memory
233 +// when near the leaves. Note that the memory required for 185 JPs is about as
234 +// much as an uncompressed 256-way branch, therefore 184 is set as the maximum.
235 +// However, it is expected that a conversion to an uncompressed 256-way branch
236 +// will normally take place before this limit is reached for other reasons,
237 +// such as improving performance when the "wasted" memory is well amortized by
238 +// the population under the branch, preserving an acceptable overall
239 +// bytes/Index in the Judy array.
240 +//
241 +// The number of pointers to arrays of JPs in the Judy bitmap branch:
242 +//
243 +// Note: The numbers below are the same in both 32 and 64 bit systems.
244 +
245 +#define cJU_BRANCHBMAXJPS 184 // maximum JPs for bitmap branches.
246 +
247 +// Convenience wrappers for referencing BranchB bitmaps or JP subarray
248 +// pointers:
249 +//
250 +// Note: JU_JBB_PJP produces a "raw" memory address that must pass through
251 +// P_JP before use, except when freeing memory:
252 +
253 +#define JU_JBB_BITMAP(Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Bitmap)
254 +#define JU_JBB_PJP( Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Pjp)
255 +
256 +#define JU_SUBEXPB(Digit) (((Digit) / cJU_BITSPERSUBEXPB) & (cJU_NUMSUBEXPB-1))
257 +
258 +#define JU_BITMAPTESTB(Pjbb, Index) \
259 + (JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) & JU_BITPOSMASKB(Index))
260 +
261 +#define JU_BITMAPSETB(Pjbb, Index) \
262 + (JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) |= JU_BITPOSMASKB(Index))
263 +
264 +// Note: JU_BITMAPCLEARB is not defined because the code does it a faster way.
265 +
266 +typedef struct J__UDY_BRANCH_BITMAP_SUBEXPANSE
267 + {
268 + BITMAPB_t jbbs_Bitmap;
269 + Pjp_t jbbs_Pjp;
270 +
271 + } jbbs_t;
272 +
273 +typedef struct J__UDY_BRANCH_BITMAP
274 + {
275 + jbbs_t jbb_jbbs [cJU_NUMSUBEXPB];
276 +#ifdef SUBEXPCOUNTS
277 + Word_t jbb_subPop1[cJU_NUMSUBEXPB];
278 +#endif
279 + } jbb_t, * Pjbb_t;
280 +
281 +#define JU_BRANCHJP_NUMJPSTOWORDS(NumJPs) (j__U_BranchBJPPopToWords[NumJPs])
282 +
283 +#ifdef SUBEXPCOUNTS
284 +#define cJU_NUMSUBEXPU 16 // number of subexpanse counts.
285 +#endif
286 +
287 +
288 +// ****************************************************************************
289 +// JUDY BRANCH UNCOMPRESSED (JBU) SUPPORT
290 +// ****************************************************************************
291 +
292 +// Convenience wrapper for referencing BranchU JPs:
293 +//
294 +// Note: This produces a non-"raw" address already passed through P_JBU().
295 +
296 +#define JU_JBU_PJP(Pjp,Index,Level) \
297 + (&((P_JBU((Pjp)->jp_Addr))->jbu_jp[JU_DIGITATSTATE(Index, Level)]))
298 +#define JU_JBU_PJP0(Pjp) \
299 + (&((P_JBU((Pjp)->jp_Addr))->jbu_jp[0]))
300 +
301 +typedef struct J__UDY_BRANCH_UNCOMPRESSED
302 + {
303 + jp_t jbu_jp [cJU_BRANCHUNUMJPS]; // JPs for populated exp.
304 +#ifdef SUBEXPCOUNTS
305 + Word_t jbu_subPop1[cJU_NUMSUBEXPU];
306 +#endif
307 + } jbu_t, * Pjbu_t;
308 +
309 +
310 +// ****************************************************************************
311 +// OTHER SUPPORT FOR JUDY STATE MACHINES (SMs)
312 +// ****************************************************************************
313 +
314 +// OBJECT SIZES IN WORDS:
315 +//
316 +// Word_ts per various JudyL structures that have constant sizes.
317 +// cJU_WORDSPERJP should always be 2; this is fundamental to the Judy
318 +// structures.
319 +
320 +#define cJU_WORDSPERJP (sizeof(jp_t) / cJU_BYTESPERWORD)
321 +#define cJU_WORDSPERCL (cJU_BYTESPERCL / cJU_BYTESPERWORD)
322 +
323 +
324 +// OPPORTUNISTIC UNCOMPRESSION:
325 +//
326 +// Define populations at which a BranchL or BranchB must convert to BranchU.
327 +// Earlier conversion is possible with good memory efficiency -- see below.
328 +
329 +#ifndef NO_BRANCHU
330 +
331 +// Max population below BranchL, then convert to BranchU:
332 +
333 +#define JU_BRANCHL_MAX_POP 1000
334 +
335 +// Minimum global population increment before next conversion of a BranchB to a
336 +// BranchU:
337 +//
338 +// This is was done to allow malloc() to coalesce memory before the next big
339 +// (~512 words) allocation.
340 +
341 +#define JU_BTOU_POP_INCREMENT 300
342 +
343 +// Min/max population below BranchB, then convert to BranchU:
344 +
345 +#define JU_BRANCHB_MIN_POP 135
346 +#define JU_BRANCHB_MAX_POP 750
347 +
348 +#else // NO_BRANCHU
349 +
350 +// These are set up to have conservative conversion schedules to BranchU:
351 +
352 +#define JU_BRANCHL_MAX_POP (-1UL)
353 +#define JU_BTOU_POP_INCREMENT 300
354 +#define JU_BRANCHB_MIN_POP 1000
355 +#define JU_BRANCHB_MAX_POP (-1UL)
356 +
357 +#endif // NO_BRANCHU
358 +
359 +
360 +// MISCELLANEOUS MACROS:
361 +
362 +// Get N most significant bits from the shifted Index word:
363 +//
364 +// As Index words are decoded, they are shifted left so only relevant,
365 +// undecoded Index bits remain.
366 +
367 +#define JU_BITSFROMSFTIDX(SFTIDX, N) ((SFTIDX) >> (cJU_BITSPERWORD - (N)))
368 +
369 +// TBD: I have my doubts about the necessity of these macros (dlb):
370 +
371 +// Produce 1-digit mask at specified state:
372 +
373 +#define cJU_MASKATSTATE(State) (0xffL << (((State) - 1) * cJU_BITSPERBYTE))
374 +
375 +// Get byte (digit) from Index at the specified state, right justified:
376 +//
377 +// Note: State must be 1..cJU_ROOTSTATE, and Digits must be 1..(cJU_ROOTSTATE
378 +// - 1), but theres no way to assert these within an expression.
379 +
380 +#define JU_DIGITATSTATE(Index,cState) \
381 + ((uint8_t)((Index) >> (((cState) - 1) * cJU_BITSPERBYTE)))
382 +
383 +// Similarly, place byte (digit) at correct position for the specified state:
384 +//
385 +// Note: Cast digit to a Word_t first so there are no complaints or problems
386 +// about shifting it more than 32 bits on a 64-bit system, say, when it is a
387 +// uint8_t from jbl_Expanse[]. (Believe it or not, the C standard says to
388 +// promote an unsigned char to a signed int; -Ac does not do this, but -Ae
389 +// does.)
390 +//
391 +// Also, to make lint happy, cast the whole result again because apparently
392 +// shifting a Word_t does not result in a Word_t!
393 +
394 +#define JU_DIGITTOSTATE(Digit,cState) \
395 + ((Word_t) (((Word_t) (Digit)) << (((cState) - 1) * cJU_BITSPERBYTE)))
396 +
397 +#endif // ! _JUDY_PRIVATE_BRANCH_INCLUDED
398 +
399 +
400 +#ifdef TEST_INSDEL
401 +
402 +// ****************************************************************************
403 +// TEST CODE FOR INSERT/DELETE MACROS
404 +// ****************************************************************************
405 +//
406 +// To use this, compile a temporary *.c file containing:
407 +//
408 +// #define DEBUG
409 +// #define JUDY_ASSERT
410 +// #define TEST_INSDEL
411 +// #include "JudyPrivate.h"
412 +// #include "JudyPrivateBranch.h"
413 +//
414 +// Use a command like this: cc -Ae +DD64 -I. -I JudyCommon -o t t.c
415 +// For best results, include +DD64 on a 64-bit system.
416 +//
417 +// This test code exercises some tricky macros, but the output must be studied
418 +// manually to verify it. Assume that for even-index testing, whole words
419 +// (Word_t) suffices.
420 +
421 +#include <stdio.h>
422 +
423 +#define INDEXES 3 // in each array.
424 +
425 +
426 +// ****************************************************************************
427 +// I N I T
428 +//
429 +// Set up variables for next test. See usage.
430 +
431 +FUNCTION void Init (
432 + int base,
433 + PWord_t PeIndex,
434 + PWord_t PoIndex,
435 + PWord_t Peleaf, // always whole words.
436 +#ifndef JU_64BIT
437 + uint8_t * Poleaf3)
438 +#else
439 + uint8_t * Poleaf3,
440 + uint8_t * Poleaf5,
441 + uint8_t * Poleaf6,
442 + uint8_t * Poleaf7)
443 +#endif
444 +{
445 + int offset;
446 +
447 + *PeIndex = 99;
448 +
449 + for (offset = 0; offset <= INDEXES; ++offset)
450 + Peleaf[offset] = base + offset;
451 +
452 + for (offset = 0; offset < (INDEXES + 1) * 3; ++offset)
453 + Poleaf3[offset] = base + offset;
454 +
455 +#ifndef JU_64BIT
456 + *PoIndex = (91 << 24) | (92 << 16) | (93 << 8) | 94;
457 +#else
458 +
459 + *PoIndex = (91L << 56) | (92L << 48) | (93L << 40) | (94L << 32)
460 + | (95L << 24) | (96L << 16) | (97L << 8) | 98L;
461 +
462 + for (offset = 0; offset < (INDEXES + 1) * 5; ++offset)
463 + Poleaf5[offset] = base + offset;
464 +
465 + for (offset = 0; offset < (INDEXES + 1) * 6; ++offset)
466 + Poleaf6[offset] = base + offset;
467 +
468 + for (offset = 0; offset < (INDEXES + 1) * 7; ++offset)
469 + Poleaf7[offset] = base + offset;
470 +#endif
471 +
472 +} // Init()
473 +
474 +
475 +// ****************************************************************************
476 +// P R I N T L E A F
477 +//
478 +// Print the byte values in a leaf.
479 +
480 +FUNCTION void PrintLeaf (
481 + char * Label, // for output.
482 + int IOffset, // insertion offset in array.
483 + int Indsize, // index size in bytes.
484 + uint8_t * PLeaf) // array of Index bytes.
485 +{
486 + int offset; // in PLeaf.
487 + int byte; // in one word.
488 +
489 + (void) printf("%s %u: ", Label, IOffset);
490 +
491 + for (offset = 0; offset <= INDEXES; ++offset)
492 + {
493 + for (byte = 0; byte < Indsize; ++byte)
494 + (void) printf("%2d", PLeaf[(offset * Indsize) + byte]);
495 +
496 + (void) printf(" ");
497 + }
498 +
499 + (void) printf("\n");
500 +
501 +} // PrintLeaf()
502 +
503 +
504 +// ****************************************************************************
505 +// M A I N
506 +//
507 +// Test program.
508 +
509 +FUNCTION main()
510 +{
511 + Word_t eIndex; // even, to insert.
512 + Word_t oIndex; // odd, to insert.
513 + Word_t eleaf [ INDEXES + 1]; // even leaf, index size 4.
514 + uint8_t oleaf3[(INDEXES + 1) * 3]; // odd leaf, index size 3.
515 +#ifdef JU_64BIT
516 + uint8_t oleaf5[(INDEXES + 1) * 5]; // odd leaf, index size 5.
517 + uint8_t oleaf6[(INDEXES + 1) * 6]; // odd leaf, index size 6.
518 + uint8_t oleaf7[(INDEXES + 1) * 7]; // odd leaf, index size 7.
519 +#endif
520 + Word_t eleaf_2 [ INDEXES + 1]; // same, but second arrays:
521 + uint8_t oleaf3_2[(INDEXES + 1) * 3];
522 +#ifdef JU_64BIT
523 + uint8_t oleaf5_2[(INDEXES + 1) * 5];
524 + uint8_t oleaf6_2[(INDEXES + 1) * 6];
525 + uint8_t oleaf7_2[(INDEXES + 1) * 7];
526 +#endif
527 + int ioffset; // index insertion offset.
528 +
529 +#ifndef JU_64BIT
530 +#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3)
531 +#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2)
532 +#else
533 +#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3, \
534 + oleaf5, oleaf6, oleaf7)
535 +#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2, \
536 + oleaf5_2, oleaf6_2, oleaf7_2)
537 +#endif
538 +
539 +#define WSIZE sizeof (Word_t) // shorthand.
540 +
541 +#ifdef PRINTALL // to turn on "noisy" printouts.
542 +#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
543 + PrintLeaf(Label,IOffset,Indsize,PLeaf)
544 +#else
545 +#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
546 + if (ioffset == 0) \
547 + PrintLeaf(Label,IOffset,Indsize,PLeaf)
548 +#endif
549 +
550 + (void) printf(
551 +"In each case, tests operate on an initial array of %d indexes. Even-index\n"
552 +"tests set index values to 0,1,2...; odd-index tests set byte values to\n"
553 +"0,1,2... Inserted indexes have a value of 99 or else byte values 91,92,...\n",
554 + INDEXES);
555 +
556 + (void) puts("\nJU_INSERTINPLACE():");
557 +
558 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
559 + {
560 + INIT;
561 + PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
562 + JU_INSERTINPLACE(eleaf, INDEXES, ioffset, eIndex);
563 + PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
564 + }
565 +
566 + (void) puts("\nJU_INSERTINPLACE3():");
567 +
568 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
569 + {
570 + INIT;
571 + PRINTLEAF("Before", ioffset, 3, oleaf3);
572 + JU_INSERTINPLACE3(oleaf3, INDEXES, ioffset, oIndex);
573 + PrintLeaf("After ", ioffset, 3, oleaf3);
574 + }
575 +
576 +#ifdef JU_64BIT
577 + (void) puts("\nJU_INSERTINPLACE5():");
578 +
579 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
580 + {
581 + INIT;
582 + PRINTLEAF("Before", ioffset, 5, oleaf5);
583 + JU_INSERTINPLACE5(oleaf5, INDEXES, ioffset, oIndex);
584 + PrintLeaf("After ", ioffset, 5, oleaf5);
585 + }
586 +
587 + (void) puts("\nJU_INSERTINPLACE6():");
588 +
589 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
590 + {
591 + INIT;
592 + PRINTLEAF("Before", ioffset, 6, oleaf6);
593 + JU_INSERTINPLACE6(oleaf6, INDEXES, ioffset, oIndex);
594 + PrintLeaf("After ", ioffset, 6, oleaf6);
595 + }
596 +
597 + (void) puts("\nJU_INSERTINPLACE7():");
598 +
599 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
600 + {
601 + INIT;
602 + PRINTLEAF("Before", ioffset, 7, oleaf7);
603 + JU_INSERTINPLACE7(oleaf7, INDEXES, ioffset, oIndex);
604 + PrintLeaf("After ", ioffset, 7, oleaf7);
605 + }
606 +#endif // JU_64BIT
607 +
608 + (void) puts("\nJU_DELETEINPLACE():");
609 +
610 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
611 + {
612 + INIT;
613 + PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
614 + JU_DELETEINPLACE(eleaf, INDEXES, ioffset);
615 + PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
616 + }
617 +
618 + (void) puts("\nJU_DELETEINPLACE_ODD(3):");
619 +
620 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
621 + {
622 + INIT;
623 + PRINTLEAF("Before", ioffset, 3, oleaf3);
624 + JU_DELETEINPLACE_ODD(oleaf3, INDEXES, ioffset, 3);
625 + PrintLeaf("After ", ioffset, 3, oleaf3);
626 + }
627 +
628 +#ifdef JU_64BIT
629 + (void) puts("\nJU_DELETEINPLACE_ODD(5):");
630 +
631 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
632 + {
633 + INIT;
634 + PRINTLEAF("Before", ioffset, 5, oleaf5);
635 + JU_DELETEINPLACE_ODD(oleaf5, INDEXES, ioffset, 5);
636 + PrintLeaf("After ", ioffset, 5, oleaf5);
637 + }
638 +
639 + (void) puts("\nJU_DELETEINPLACE_ODD(6):");
640 +
641 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
642 + {
643 + INIT;
644 + PRINTLEAF("Before", ioffset, 6, oleaf6);
645 + JU_DELETEINPLACE_ODD(oleaf6, INDEXES, ioffset, 6);
646 + PrintLeaf("After ", ioffset, 6, oleaf6);
647 + }
648 +
649 + (void) puts("\nJU_DELETEINPLACE_ODD(7):");
650 +
651 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
652 + {
653 + INIT;
654 + PRINTLEAF("Before", ioffset, 7, oleaf7);
655 + JU_DELETEINPLACE_ODD(oleaf7, INDEXES, ioffset, 7);
656 + PrintLeaf("After ", ioffset, 7, oleaf7);
657 + }
658 +#endif // JU_64BIT
659 +
660 + (void) puts("\nJU_INSERTCOPY():");
661 +
662 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
663 + {
664 + INIT2;
665 + PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
666 + PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
667 + JU_INSERTCOPY(eleaf_2, eleaf, INDEXES, ioffset, eIndex);
668 + PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
669 + PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
670 + }
671 +
672 + (void) puts("\nJU_INSERTCOPY3():");
673 +
674 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
675 + {
676 + INIT2;
677 + PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
678 + PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
679 + JU_INSERTCOPY3(oleaf3_2, oleaf3, INDEXES, ioffset, oIndex);
680 + PRINTLEAF("After, src ", ioffset, 3, oleaf3);
681 + PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
682 + }
683 +
684 +#ifdef JU_64BIT
685 + (void) puts("\nJU_INSERTCOPY5():");
686 +
687 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
688 + {
689 + INIT2;
690 + PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
691 + PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
692 + JU_INSERTCOPY5(oleaf5_2, oleaf5, INDEXES, ioffset, oIndex);
693 + PRINTLEAF("After, src ", ioffset, 5, oleaf5);
694 + PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
695 + }
696 +
697 + (void) puts("\nJU_INSERTCOPY6():");
698 +
699 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
700 + {
701 + INIT2;
702 + PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
703 + PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
704 + JU_INSERTCOPY6(oleaf6_2, oleaf6, INDEXES, ioffset, oIndex);
705 + PRINTLEAF("After, src ", ioffset, 6, oleaf6);
706 + PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
707 + }
708 +
709 + (void) puts("\nJU_INSERTCOPY7():");
710 +
711 + for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
712 + {
713 + INIT2;
714 + PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
715 + PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
716 + JU_INSERTCOPY7(oleaf7_2, oleaf7, INDEXES, ioffset, oIndex);
717 + PRINTLEAF("After, src ", ioffset, 7, oleaf7);
718 + PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
719 + }
720 +#endif // JU_64BIT
721 +
722 + (void) puts("\nJU_DELETECOPY():");
723 +
724 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
725 + {
726 + INIT2;
727 + PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
728 + PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
729 + JU_DELETECOPY(eleaf_2, eleaf, INDEXES, ioffset, ignore);
730 + PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
731 + PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
732 + }
733 +
734 + (void) puts("\nJU_DELETECOPY_ODD(3):");
735 +
736 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
737 + {
738 + INIT2;
739 + PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
740 + PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
741 + JU_DELETECOPY_ODD(oleaf3_2, oleaf3, INDEXES, ioffset, 3);
742 + PRINTLEAF("After, src ", ioffset, 3, oleaf3);
743 + PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
744 + }
745 +
746 +#ifdef JU_64BIT
747 + (void) puts("\nJU_DELETECOPY_ODD(5):");
748 +
749 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
750 + {
751 + INIT2;
752 + PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
753 + PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
754 + JU_DELETECOPY_ODD(oleaf5_2, oleaf5, INDEXES, ioffset, 5);
755 + PRINTLEAF("After, src ", ioffset, 5, oleaf5);
756 + PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
757 + }
758 +
759 + (void) puts("\nJU_DELETECOPY_ODD(6):");
760 +
761 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
762 + {
763 + INIT2;
764 + PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
765 + PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
766 + JU_DELETECOPY_ODD(oleaf6_2, oleaf6, INDEXES, ioffset, 6);
767 + PRINTLEAF("After, src ", ioffset, 6, oleaf6);
768 + PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
769 + }
770 +
771 + (void) puts("\nJU_DELETECOPY_ODD(7):");
772 +
773 + for (ioffset = 0; ioffset < INDEXES; ++ioffset)
774 + {
775 + INIT2;
776 + PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
777 + PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
778 + JU_DELETECOPY_ODD(oleaf7_2, oleaf7, INDEXES, ioffset, 7);
779 + PRINTLEAF("After, src ", ioffset, 7, oleaf7);
780 + PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
781 + }
782 +#endif // JU_64BIT
783 +
784 + return(0);
785 +
786 +} // main()
787 +
788 +#endif // TEST_INSDEL
libnetdata/libjudy/src/JudyHS/JudyHS.c new
+771
@@ -0,0 +1,771 @@
1 +// @(#) $Revision: 4.1 $ $Source: /judy/src/JudyHS/JudyHS.c
2 +//=======================================================================
3 +// Author Douglas L. Baskins, Dec 2003.
4 +// Permission to use this code is freely granted, provided that this
5 +// statement is retained.
6 +// email - doug@sourcejudy.com -or- dougbaskins@yahoo.com
7 +//=======================================================================
8 +
9 +#include <string.h> // for memcmp(), memcpy()
10 +
11 +#include <Judy.h> // for JudyL* routines/macros
12 +
13 +/*
14 + This routine is a very fast "string" version of an ADT that stores
15 + (JudyHSIns()), retrieves (JudyHSGet()), deletes (JudyHSDel()) and
16 + frees the entire ADT (JudyHSFreeArray()) strings. It uses the "Judy
17 + arrays" JudyL() API as the main workhorse. The length of the string
18 + is included in the calling parameters so that strings with embedded
19 + \0s can be used. The string lengths can be from 0 bytes to whatever
20 + malloc() can handle (~2GB).
21 +
22 + Compile:
23 +
24 + cc -O JudyHS.c -c needs to link with -lJudy (libJudy.a)
25 +
26 + Note: in gcc version 3.3.1, -O2 generates faster code than -O
27 + Note: in gcc version 3.3.2, -O3 generates faster code than -O2
28 +
29 + NOTES:
30 +
31 +1) There may be some performance issues with 64 bit machines, because I
32 + have not characterized that it yet.
33 +
34 +2) It appears that a modern CPU (>2Ghz) that the instruction times are
35 + much faster that a RAM access, so building up a word from bytes takes
36 + no longer that a whole word access. I am taking advantage of this to
37 + make this code endian neutral. A side effect of this is strings do
38 + not need to be aligned, nor tested to be on to a word boundry. In
39 + older and in slow (RISC) machines, this may be a performance issue.
40 + I have given up trying to optimize for machines that have very slow
41 + mpy, mod, variable shifts and call returns.
42 +
43 +3) JudyHS is very scalable from 1 string to billions (with enough RAM).
44 + The memory usage is also scales with population. I have attempted to
45 + combine the best characteristics of JudyL arrays with Hashing methods
46 + and well designed modern processors (such as the 1.3Ghz Intel
47 + Centrino this is being written on).
48 +
49 + HOW JudyHS WORKS: ( 4[8] means 4 bytes in 32 bit machine and 8 in 64)
50 +
51 + A) A JudyL array is used to separate strings of equal lengths into
52 + their own structures (a different hash table is used for each length
53 + of string). The additional time overhead is very near zero because
54 + of the CPU cache. The space efficiency is improved because the
55 + length need not be stored with the string (ls_t). The "JLHash" ADT
56 + in the test program "StringCompare" is verification of both these
57 + assumptions.
58 +
59 + B) A 32 bit hash value is produced from the string. Many thanks to
60 + the Internet and the author (Bob Jenkins) for coming up with a very
61 + good and fast universal string hash. Next the 32 bit hash number is
62 + used as an Index to another JudyL array. Notice that one (1) JudyL
63 + array is used as a hash table per each string length. If there are
64 + no hash collisions (normally) then the string is copied to a
65 + structure (ls_t) along with room for storing a Value. A flag is
66 + added to the pointer to note it is pointing to a ls_t structure.
67 + Since the lengths of the strings are the same, there is no need to
68 + stored length of string in the ls_t structure. This saves about a
69 + word per string of memory.
70 +
71 + C) When there is a hashing collision (very rare), a JudyL array is
72 + used to decode the next 4[8] bytes of the string. That is, the next
73 + 4[8] bytes of the string are used as the Index. This process is
74 + repeated until the remaining string is unique. The remaining string
75 + (if any) is stored in a (now smaller) ls_t structure. If the
76 + remaining string is less or equal to 4[8] bytes, then the ls_t
77 + structure is not needed and the Value area in the JudyL array is
78 + used. A compile option -DDONOTUSEHASH is available to test this
79 + structure without using hashing (only the JudyL tree is used). This
80 + is equivalent to having all strings hashed to the same bucket. The
81 + speed is still better than all other tree based ADTs I have tested.
82 + An added benefit of this is a very fast "hash collision" resolving.
83 + It could foil hackers that exploit the slow synonym (linked-list)
84 + collision handling property used with most hashing algorithms. If
85 + this is not a necessary property, then a simpler ADT "JLHash" that is
86 + documented the the test program "StringCompare.c" may be used with a
87 + little loss of memory efficiency (because it includes the string
88 + length with the ls_t structure). JudyHS was written to be the
89 + fastest, very scalable, memory efficient, general purpose string ADT
90 + possible. (However, I would like to eat those words someday). (dlb)
91 +
92 +*/
93 +
94 +#ifdef EXAMPLE_CODE
95 +#include <stdio.h>
96 +#include <unistd.h>
97 +#include <string.h>
98 +
99 +#include <Judy.h>
100 +
101 +//#include "JudyHS.h" // for Judy.h without JudyHS*()
102 +
103 +// By Doug Baskins Apr 2004 - for JudyHS man page
104 +
105 +#define MAXLINE 1000000 /* max length of line */
106 +char Index[MAXLINE]; // string to check
107 +
108 +int // Usage: CheckDupLines < file
109 +main()
110 +{
111 + Pvoid_t PJArray = (PWord_t)NULL; // Judy array.
112 + PWord_t PValue; // ^ Judy array element.
113 + Word_t Bytes; // size of JudyHS array.
114 + Word_t LineNumb = 0; // current line number
115 + Word_t Dups = 0; // number of duplicate lines
116 +
117 + while (fgets(Index, MAXLINE, stdin) != (char *)NULL)
118 + {
119 + LineNumb++; // line number
120 +
121 +// store string into array
122 + JHSI(PValue, PJArray, Index, strlen(Index));
123 + if (*PValue) // check if duplicate
124 + {
125 + Dups++; // count duplicates
126 + printf("Duplicate lines %lu:%lu:%s", *PValue, LineNumb, Index);
127 + }
128 + else
129 + {
130 + *PValue = LineNumb; // store Line number
131 + }
132 + }
133 + printf("%lu Duplicates, free JudyHS array of %lu Lines\n",
134 + Dups, LineNumb - Dups);
135 + JHSFA(Bytes, PJArray); // free array
136 + printf("The JudyHS array allocated %lu bytes of memory\n", Bytes);
137 + return (0);
138 +}
139 +#endif // EXAMPLE_CODE
140 +
141 +// Note: Use JLAP_INVALID, which is non-zero, to mark pointers to a ls_t
142 +// This makes it compatable with previous versions of JudyL()
143 +
144 +#define IS_PLS(PLS) (((Word_t) (PLS)) & JLAP_INVALID)
145 +#define CLEAR_PLS(PLS) (((Word_t) (PLS)) & (~JLAP_INVALID))
146 +#define SET_PLS(PLS) (((Word_t) (PLS)) | JLAP_INVALID)
147 +
148 +#define WORDSIZE (sizeof(Word_t))
149 +
150 +// this is the struct used for "leaf" strings. Note that
151 +// the Value is followed by a "variable" length ls_String array.
152 +//
153 +typedef struct L_EAFSTRING
154 +{
155 + Word_t ls_Value; // Value area (cannot change size)
156 + uint8_t ls_String[WORDSIZE]; // to fill out to a Word_t size
157 +} ls_t , *Pls_t;
158 +
159 +#define LS_STRUCTOVD (sizeof(ls_t) - WORDSIZE)
160 +
161 +// Calculate size of ls_t including the string of length of LEN.
162 +//
163 +#define LS_WORDLEN(LEN) (((LEN) + LS_STRUCTOVD + WORDSIZE - 1) / WORDSIZE)
164 +
165 +// Copy from 0..4[8] bytes from string to a Word_t
166 +// NOTE: the copy in in little-endian order to take advantage of improved
167 +// memory efficiency of JudyLIns() with smaller numbers
168 +//
169 +#define COPYSTRING4toWORD(WORD,STR,LEN) \
170 +{ \
171 + WORD = 0; \
172 + switch(LEN) \
173 + { \
174 + default: /* four and greater */ \
175 + case 4: \
176 + WORD += (Word_t)(((uint8_t *)(STR))[3] << 24); \
177 + case 3: \
178 + WORD += (Word_t)(((uint8_t *)(STR))[2] << 16); \
179 + case 2: \
180 + WORD += (Word_t)(((uint8_t *)(STR))[1] << 8); \
181 + case 1: \
182 + WORD += (Word_t)(((uint8_t *)(STR))[0]); \
183 + case 0: break; \
184 + } \
185 +}
186 +
187 +#ifdef JU_64BIT
188 +
189 +// copy from 0..8 bytes from string to Word_t
190 +//
191 +#define COPYSTRING8toWORD(WORD,STR,LEN) \
192 +{ \
193 + WORD = 0UL; \
194 + switch(LEN) \
195 + { \
196 + default: /* eight and greater */ \
197 + case 8: \
198 + WORD += ((Word_t)((uint8_t *)(STR))[7] << 56); \
199 + case 7: \
200 + WORD += ((Word_t)((uint8_t *)(STR))[6] << 48); \
201 + case 6: \
202 + WORD += ((Word_t)((uint8_t *)(STR))[5] << 40); \
203 + case 5: \
204 + WORD += ((Word_t)((uint8_t *)(STR))[4] << 32); \
205 + case 4: \
206 + WORD += ((Word_t)((uint8_t *)(STR))[3] << 24); \
207 + case 3: \
208 + WORD += ((Word_t)((uint8_t *)(STR))[2] << 16); \
209 + case 2: \
210 + WORD += ((Word_t)((uint8_t *)(STR))[1] << 8); \
211 + case 1: \
212 + WORD += ((Word_t)((uint8_t *)(STR))[0]); \
213 + case 0: break; \
214 + } \
215 +}
216 +
217 +#define COPYSTRINGtoWORD COPYSTRING8toWORD
218 +
219 +#else // JU_32BIT
220 +
221 +#define COPYSTRINGtoWORD COPYSTRING4toWORD
222 +
223 +#endif // JU_32BIT
224 +
225 +// set JError_t locally
226 +
227 +#define JU_SET_ERRNO(PJERROR, JERRNO) \
228 +{ \
229 + if (PJERROR != (PJError_t) NULL) \
230 + { \
231 + if (JERRNO) \
232 + JU_ERRNO(PJError) = (JERRNO); \
233 + JU_ERRID(PJERROR) = __LINE__; \
234 + } \
235 +}
236 +
237 +//=======================================================================
238 +// This routine must hash string to 24..32 bits. The "goodness" of
239 +// the hash is not as important as its speed.
240 +//=======================================================================
241 +
242 +// hash to no more than 32 bits
243 +
244 +// extern Word_t gHmask; for hash bits experiments
245 +
246 +#define JUDYHASHSTR(HVALUE,STRING,LENGTH) \
247 +{ \
248 + uint8_t *p_ = (uint8_t *)(STRING); \
249 + uint8_t *q_ = p_ + (LENGTH); \
250 + uint32_t c_ = 0; \
251 + for (; p_ != q_; ++p_) \
252 + { \
253 + c_ = (c_ * 31) + *p_; \
254 + } \
255 +/* c_ &= gHmask; see above */ \
256 + (HVALUE) = c_; \
257 +}
258 +
259 +// Find String of Len in JudyHS structure, return pointer to associated Value
260 +
261 +PPvoid_t
262 +JudyHSGet(Pcvoid_t PArray, // pointer (^) to structure
263 + void * Str, // pointer to string
264 + Word_t Len // length of string
265 + )
266 +{
267 + uint8_t *String = (uint8_t *)Str;
268 + PPvoid_t PPValue; // pointer to Value
269 + Word_t Index; // 4[8] bytes of String
270 +
271 + JLG(PPValue, PArray, Len); // find hash table for strings of Len
272 + if (PPValue == (PPvoid_t) NULL)
273 + return ((PPvoid_t) NULL); // no strings of this Len
274 +
275 +// check for caller error (null pointer)
276 +//
277 + if ((String == (void *) NULL) && (Len != 0))
278 + return ((PPvoid_t) NULL); // avoid null-pointer dereference
279 +
280 +#ifndef DONOTUSEHASH
281 + if (Len > WORDSIZE) // Hash table not necessary with short
282 + {
283 + uint32_t HValue; // hash of input string
284 + JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
285 + JLG(PPValue, *PPValue, (Word_t)HValue); // get ^ to hash bucket
286 + if (PPValue == (PPvoid_t) NULL)
287 + return ((PPvoid_t) NULL); // no entry in Hash table
288 + }
289 +#endif // DONOTUSEHASH
290 +
291 +/*
292 + Each JudyL array decodes 4[8] bytes of the string. Since the hash
293 + collisions occur very infrequently, the performance is not important.
294 + However, even if the Hash code is not used this method still is
295 + significantly faster than common tree methods (AVL, Red-Black, Splay,
296 + b-tree, etc..). You can compare it yourself with #define DONOTUSEHASH
297 + 1 or putting -DDONOTUSEHASH in the cc line. Use the "StringCompare.c"
298 + code to compare (9Dec2003 dlb).
299 +*/
300 + while (Len > WORDSIZE) // traverse tree of JudyL arrays
301 + {
302 + if (IS_PLS(*PPValue)) // ^ to JudyL array or ls_t struct?
303 + {
304 + Pls_t Pls; // ls_t struct, termination of tree
305 + Pls = (Pls_t) CLEAR_PLS(*PPValue); // remove flag from ^
306 +
307 +// if remaining string matches, return ^ to Value, else NULL
308 +
309 + if (memcmp(String, Pls->ls_String, Len) == 0)
310 + return ((PPvoid_t) (&(Pls->ls_Value)));
311 + else
312 + return ((PPvoid_t) NULL); // string does not match
313 + }
314 + else
315 + {
316 + COPYSTRINGtoWORD(Index, String, WORDSIZE);
317 +
318 + JLG(PPValue, *PPValue, Index); // decode next 4[8] bytes
319 + if (PPValue == (PPvoid_t) NULL) // if NULL array, bail out
320 + return ((PPvoid_t) NULL); // string does not match
321 +
322 + String += WORDSIZE; // advance
323 + Len -= WORDSIZE;
324 + }
325 + }
326 +
327 +// Get remaining 1..4[8] bytes left in string
328 +
329 + COPYSTRINGtoWORD(Index, String, Len);
330 + JLG(PPValue, *PPValue, Index); // decode last 1-4[8] bytes
331 + return (PPValue);
332 +}
333 +
334 +// Add string to a tree of JudyL arrays (all lengths must be same)
335 +
336 +static PPvoid_t
337 +insStrJudyLTree(uint8_t * String, // string to add to tree of JudyL arrays
338 + Word_t Len, // length of string
339 + PPvoid_t PPValue, // pointer to root pointer
340 + PJError_t PJError // for returning error info
341 + )
342 +{
343 + Word_t Index; // next 4[8] bytes of String
344 +
345 + while (Len > WORDSIZE) // add to JudyL tree
346 + {
347 +// CASE 1, pointer is to a NULL, make a new ls_t leaf
348 +
349 + if (*PPValue == (Pvoid_t)NULL)
350 + {
351 + Pls_t Pls; // memory for a ls_t
352 + Pls = (Pls_t) JudyMalloc(LS_WORDLEN(Len));
353 + if (Pls == NULL)
354 + {
355 + JU_SET_ERRNO(PJError, JU_ERRNO_NOMEM);
356 + return (PPJERR);
357 + }
358 + Pls->ls_Value = 0; // clear Value word
359 + memcpy(Pls->ls_String, String, Len); // copy to new struct
360 + *PPValue = (Pvoid_t)SET_PLS(Pls); // mark pointer
361 + return ((PPvoid_t) (&Pls->ls_Value)); // return ^ to Value
362 + } // no exit here
363 +// CASE 2: is a ls_t, free (and shorten), then decode into JudyL tree
364 +
365 + if (IS_PLS(*PPValue)) // pointer to a ls_t? (leaf)
366 + {
367 + Pls_t Pls; // ^ to ls_t
368 + uint8_t *String0; // ^ to string in ls_t
369 + Word_t Index0; // 4[8] bytes in string
370 + Word_t FreeLen; // length of ls_t
371 + PPvoid_t PPsplit;
372 +
373 + FreeLen = LS_WORDLEN(Len); // length of ls_t
374 +
375 + Pls = (Pls_t) CLEAR_PLS(*PPValue); // demangle ^ to ls_t
376 + String0 = Pls->ls_String;
377 + if (memcmp(String, String0, Len) == 0) // check if match?
378 + {
379 + return ((PPvoid_t) (&Pls->ls_Value)); // yes, duplicate
380 + }
381 +
382 + *PPValue = NULL; // clear ^ to ls_t and make JudyL
383 +
384 +// This do loop is technically not required, saves multiple JudyFree()
385 +// when storing already sorted strings into structure
386 +
387 + do // decode next 4[8] bytes of string
388 + { // with a JudyL array
389 +// Note: string0 is always aligned
390 +
391 + COPYSTRINGtoWORD(Index0, String0, WORDSIZE);
392 + String0 += WORDSIZE;
393 + COPYSTRINGtoWORD(Index, String, WORDSIZE);
394 + String += WORDSIZE;
395 + Len -= WORDSIZE;
396 + PPsplit = PPValue; // save for split below
397 + PPValue = JudyLIns(PPValue, Index0, PJError);
398 + if (PPValue == PPJERR)
399 + {
400 + JU_SET_ERRNO(PJError, 0);
401 + return (PPJERR);
402 + }
403 +
404 + } while ((Index0 == Index) && (Len > WORDSIZE));
405 +
406 +// finish storing remainder of string that was in the ls_t
407 +
408 + PPValue = insStrJudyLTree(String0, Len, PPValue, PJError);
409 + if (PPValue == PPJERR)
410 + {
411 + return (PPJERR);
412 + }
413 +// copy old Value to Value in new struct
414 +
415 + *(PWord_t)PPValue = Pls->ls_Value;
416 +
417 +// free the string buffer (ls_t)
418 +
419 + JudyFree((Pvoid_t)Pls, FreeLen);
420 + PPValue = JudyLIns(PPsplit, Index, PJError);
421 + if (PPValue == PPJERR)
422 + {
423 + JU_SET_ERRNO(PJError, 0);
424 + return (PPValue);
425 + }
426 +
427 +// finish remainder of newly inserted string
428 +
429 + PPValue = insStrJudyLTree(String, Len, PPValue, PJError);
430 + return (PPValue);
431 + } // no exit here
432 +// CASE 3, more JudyL arrays, decode to next tree
433 +
434 + COPYSTRINGtoWORD(Index, String, WORDSIZE);
435 + Len -= WORDSIZE;
436 + String += WORDSIZE;
437 +
438 + PPValue = JudyLIns(PPValue, Index, PJError); // next 4[8] bytes
439 + if (PPValue == PPJERR)
440 + {
441 + JU_SET_ERRNO(PJError, 0);
442 + return (PPValue);
443 + }
444 + }
445 +// this is done outside of loop so "Len" can be an unsigned number
446 +
447 + COPYSTRINGtoWORD(Index, String, Len);
448 + PPValue = JudyLIns(PPValue, Index, PJError); // remaining 4[8] bytes
449 +
450 + return (PPValue);
451 +}
452 +
453 +
454 +// Insert string to JudyHS structure, return pointer to associated Value
455 +
456 +PPvoid_t
457 +JudyHSIns(PPvoid_t PPArray, // ^ to JudyHashArray name
458 + void * Str, // pointer to string
459 + Word_t Len, // length of string
460 + PJError_t PJError // optional, for returning error info
461 + )
462 +{
463 + uint8_t * String = (uint8_t *)Str;
464 + PPvoid_t PPValue;
465 +
466 +// string can only be NULL if Len is 0.
467 +
468 + if ((String == (uint8_t *) NULL) && (Len != 0UL))
469 + {
470 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
471 + return (PPJERR);
472 + }
473 + JLG(PPValue, *PPArray, Len); // JudyL hash table for strings of Len
474 + if (PPValue == (PPvoid_t) NULL) // make new if missing, (very rare)
475 + {
476 + PPValue = JudyLIns(PPArray, Len, PJError);
477 + if (PPValue == PPJERR)
478 + {
479 + JU_SET_ERRNO(PJError, 0);
480 + return (PPJERR);
481 + }
482 + }
483 +#ifndef DONOTUSEHASH
484 + if (Len > WORDSIZE)
485 + {
486 + uint32_t HValue; // hash of input string
487 + JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
488 + PPValue = JudyLIns(PPValue, (Word_t)HValue, PJError);
489 + if (PPValue == PPJERR)
490 + {
491 + JU_SET_ERRNO(PJError, 0);
492 + return (PPJERR);
493 + }
494 + }
495 +#endif // DONOTUSEHASH
496 +
497 + PPValue = insStrJudyLTree(String, Len, PPValue, PJError); // add string
498 + return (PPValue); // ^ to Value
499 +}
500 +
501 +// Delete string from tree of JudyL arrays (all Lens must be same)
502 +
503 +static int
504 +delStrJudyLTree(uint8_t * String, // delete from tree of JudyL arrays
505 + Word_t Len, // length of string
506 + PPvoid_t PPValue, // ^ to hash bucket
507 + PJError_t PJError // for returning error info
508 + )
509 +{
510 + PPvoid_t PPValueN; // next pointer
511 + Word_t Index;
512 + int Ret; // -1=failed, 1=success, 2=quit del
513 +
514 + if (IS_PLS(*PPValue)) // is pointer to ls_t?
515 + {
516 + Pls_t Pls;
517 + Pls = (Pls_t) CLEAR_PLS(*PPValue); // demangle pointer
518 + JudyFree((Pvoid_t)Pls, LS_WORDLEN(Len)); // free the ls_t
519 +
520 + *PPValue = (Pvoid_t)NULL; // clean pointer
521 + return (1); // successfully deleted
522 + }
523 +
524 + if (Len > WORDSIZE) // delete from JudyL tree, not leaf
525 + {
526 + COPYSTRINGtoWORD(Index, String, WORDSIZE); // get Index
527 + JLG(PPValueN, *PPValue, Index); // get pointer to next JudyL array
528 +
529 + String += WORDSIZE; // advance to next 4[8] bytes
530 + Len -= WORDSIZE;
531 +
532 + Ret = delStrJudyLTree(String, Len, PPValueN, PJError);
533 + if (Ret != 1) return(Ret);
534 +
535 + if (*PPValueN == (PPvoid_t) NULL)
536 + {
537 +// delete JudyL element from tree
538 +
539 + Ret = JudyLDel(PPValue, Index, PJError);
540 + }
541 + }
542 + else
543 + {
544 + COPYSTRINGtoWORD(Index, String, Len); // get leaf element
545 +
546 +// delete last 1-4[8] bytes from leaf element
547 +
548 + Ret = JudyLDel(PPValue, Index, PJError);
549 + }
550 + return (Ret);
551 +}
552 +
553 +// Delete string from JHS structure
554 +
555 +int
556 +JudyHSDel(PPvoid_t PPArray, // ^ to JudyHashArray struct
557 + void * Str, // pointer to string
558 + Word_t Len, // length of string
559 + PJError_t PJError // optional, for returning error info
560 + )
561 +{
562 + uint8_t * String = (uint8_t *)Str;
563 + PPvoid_t PPBucket, PPHtble;
564 + int Ret; // return bool from Delete routine
565 +#ifndef DONOTUSEHASH
566 + uint32_t HValue = 0; // hash value of input string
567 +#endif // DONOTUSEHASH
568 +
569 + if (PPArray == NULL)
570 + return (0); // no pointer, return not found
571 +
572 +// This is a little slower than optimum method, but not much in new CPU
573 +// Verify that string is in the structure -- simplifies future assumptions
574 +
575 + if (JudyHSGet(*PPArray, String, Len) == (PPvoid_t) NULL)
576 + return (0); // string not found, return
577 +
578 +// string is in structure, so testing for absence is not necessary
579 +
580 + JLG(PPHtble, *PPArray, Len); // JudyL hash table for strings of Len
581 +
582 +#ifdef DONOTUSEHASH
583 + PPBucket = PPHtble; // simulate below code
584 +#else // USEHASH
585 + if (Len > WORDSIZE)
586 + {
587 + JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
588 +
589 +// get pointer to hash bucket
590 +
591 + JLG(PPBucket, *PPHtble, (Word_t)HValue);
592 + }
593 + else
594 + {
595 + PPBucket = PPHtble; // no bucket to JLGet
596 + }
597 +#endif // USEHASH
598 +
599 +// delete from JudyL tree
600 +//
601 + Ret = delStrJudyLTree(String, Len, PPBucket, PJError);
602 + if (Ret != 1)
603 + {
604 + JU_SET_ERRNO(PJError, 0);
605 + return(-1);
606 + }
607 +// handle case of missing JudyL array from hash table and length table
608 +
609 + if (*PPBucket == (Pvoid_t)NULL) // if JudyL tree gone
610 + {
611 +#ifndef DONOTUSEHASH
612 + if (Len > WORDSIZE)
613 + {
614 +// delete entry in Hash table
615 +
616 + Ret = JudyLDel(PPHtble, (Word_t)HValue, PJError);
617 + if (Ret != 1)
618 + {
619 + JU_SET_ERRNO(PJError, 0);
620 + return(-1);
621 + }
622 + }
623 +#endif // USEHASH
624 + if (*PPHtble == (PPvoid_t) NULL) // if Hash table gone
625 + {
626 +// delete entry from the String length table
627 +
628 + Ret = JudyLDel(PPArray, Len, PJError);
629 + if (Ret != 1)
630 + {
631 + JU_SET_ERRNO(PJError, 0);
632 + return(-1);
633 + }
634 + }
635 + }
636 + return (1); // success
637 +}
638 +
639 +static Word_t
640 +delJudyLTree(PPvoid_t PPValue, // ^ to JudyL root pointer
641 + Word_t Len, // length of string
642 + PJError_t PJError) // for returning error info
643 +{
644 + Word_t bytes_freed = 0; // bytes freed at point
645 + Word_t bytes_total = 0; // accumulated bytes freed
646 + PPvoid_t PPValueN;
647 +
648 +// Pointer is to another tree of JudyL arrays or ls_t struct
649 +
650 + if (Len > WORDSIZE) // more depth to tree
651 + {
652 + Word_t NEntry;
653 +
654 +// Pointer is to a ls_t struct
655 +
656 + if (IS_PLS(*PPValue))
657 + {
658 + Pls_t Pls;
659 + Word_t freewords;
660 +
661 + freewords = LS_WORDLEN(Len); // calculate length
662 + Pls = (Pls_t)CLEAR_PLS(*PPValue); // demangle pointer
663 +
664 +// *PPValue = (Pvoid_t)NULL; // clean pointer
665 + JudyFree((Pvoid_t)Pls, freewords); // free the ls_t
666 +
667 + return(freewords * WORDSIZE);
668 + }
669 +// else
670 +// Walk all the entrys in the JudyL array
671 +
672 + NEntry = 0; // start at beginning
673 + for (PPValueN = JudyLFirst(*PPValue, &NEntry, PJError);
674 + (PPValueN != (PPvoid_t) NULL) && (PPValueN != PPJERR);
675 + PPValueN = JudyLNext(*PPValue, &NEntry, PJError))
676 + {
677 +// recurse to the next level in the tree of arrays
678 +
679 + bytes_freed = delJudyLTree(PPValueN, Len - WORDSIZE, PJError);
680 + if (bytes_freed == JERR) return(JERR);
681 + bytes_total += bytes_freed;
682 + }
683 + if (PPValueN == PPJERR) return(JERR);
684 +
685 +// now free this JudyL array
686 +
687 + bytes_freed = JudyLFreeArray(PPValue, PJError);
688 + if (bytes_freed == JERR) return(JERR);
689 + bytes_total += bytes_freed;
690 +
691 + return(bytes_total); // return amount freed
692 + }
693 +// else
694 +
695 +// Pointer to simple JudyL array
696 +
697 + bytes_freed = JudyLFreeArray(PPValue, PJError);
698 +
699 + return(bytes_freed);
700 +}
701 +
702 +
703 +Word_t // bytes freed
704 +JudyHSFreeArray(PPvoid_t PPArray, // ^ to JudyHashArray struct
705 + PJError_t PJError // optional, for returning error info
706 + )
707 +{
708 + Word_t Len; // start at beginning
709 + Word_t bytes_freed; // bytes freed at this level.
710 + Word_t bytes_total; // bytes total at all levels.
711 + PPvoid_t PPHtble;
712 +
713 + if (PPArray == NULL)
714 + return (0); // no pointer, return none
715 +
716 +// Walk the string length table for subsidary hash structs
717 +// NOTE: This is necessary to determine the depth of the tree
718 +
719 + bytes_freed = 0;
720 + bytes_total = 0;
721 + Len = 0; // walk to length table
722 +
723 + for (PPHtble = JudyLFirst(*PPArray, &Len, PJError);
724 + (PPHtble != (PPvoid_t) NULL) && (PPHtble != PPJERR);
725 + PPHtble = JudyLNext(*PPArray, &Len, PJError))
726 + {
727 + PPvoid_t PPValueH;
728 +
729 +#ifndef DONOTUSEHASH
730 + if (Len > WORDSIZE)
731 + {
732 + Word_t HEntry = 0; // walk the hash tables
733 +
734 + for (PPValueH = JudyLFirst(*PPHtble, &HEntry, PJError);
735 + (PPValueH != (PPvoid_t) NULL) && (PPValueH != PPJERR);
736 + PPValueH = JudyLNext(*PPHtble, &HEntry, PJError))
737 + {
738 + bytes_freed = delJudyLTree(PPValueH, Len, PJError);
739 + if (bytes_freed == JERR) return(JERR);
740 + bytes_total += bytes_freed;
741 + }
742 +
743 + if (PPValueH == PPJERR) return(JERR);
744 +
745 +// free the Hash table for this length of string
746 +
747 + bytes_freed = JudyLFreeArray(PPHtble, PJError);
748 + if (bytes_freed == JERR) return(JERR);
749 + bytes_total += bytes_freed;
750 + }
751 + else
752 +#endif // DONOTUSEHASH
753 + {
754 + PPValueH = PPHtble; // simulate hash table
755 +
756 + bytes_freed = delJudyLTree(PPValueH, Len, PJError);
757 + if (bytes_freed == JERR) return(JERR);
758 + bytes_total += bytes_freed;
759 + }
760 + }
761 + if (PPHtble == PPJERR) return(JERR);
762 +
763 +// free the length table
764 +
765 + bytes_freed = JudyLFreeArray(PPArray, PJError);
766 + if (bytes_freed == JERR) return(JERR);
767 +
768 + bytes_total += bytes_freed;
769 +
770 + return(bytes_total); // return bytes freed
771 +}
libnetdata/libjudy/src/JudyL/JudyL.h new
+505
@@ -0,0 +1,505 @@
1 +#ifndef _JUDYL_INCLUDED
2 +#define _JUDYL_INCLUDED
3 +// _________________
4 +//
5 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
6 +//
7 +// This program is free software; you can redistribute it and/or modify it
8 +// under the term of the GNU Lesser General Public License as published by the
9 +// Free Software Foundation; either version 2 of the License, or (at your
10 +// option) any later version.
11 +//
12 +// This program is distributed in the hope that it will be useful, but WITHOUT
13 +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 +// for more details.
16 +//
17 +// You should have received a copy of the GNU Lesser General Public License
18 +// along with this program; if not, write to the Free Software Foundation,
19 +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 +// _________________
21 +
22 +// @(#) $Revision: 4.41 $ $Source: /judy/src/JudyL/JudyL.h $
23 +
24 +// ****************************************************************************
25 +// JUDYL -- SMALL/LARGE AND/OR CLUSTERED/SPARSE ARRAYS
26 +//
27 +// -by-
28 +//
29 +// Douglas L. Baskins
30 +// doug@sourcejudy.com
31 +//
32 +// Judy arrays are designed to be used instead of arrays. The performance
33 +// suggests the reason why Judy arrays are thought of as arrays, instead of
34 +// trees. They are remarkably memory efficient at all populations.
35 +// Implemented as a hybrid digital tree (but really a state machine, see
36 +// below), Judy arrays feature fast insert/retrievals, fast near neighbor
37 +// searching, and contain a population tree for extremely fast ordinal related
38 +// retrievals.
39 +//
40 +// CONVENTIONS:
41 +//
42 +// - The comments here refer to 32-bit [64-bit] systems.
43 +//
44 +// - BranchL, LeafL refer to linear branches and leaves (small populations),
45 +// except LeafL does not actually appear as such; rather, Leaf1..3 [Leaf1..7]
46 +// is used to represent leaf Index sizes, and LeafW refers to a Leaf with
47 +// full (Long) word Indexes, which is also a type of linear leaf. Note that
48 +// root-level LeafW (Leaf4 [Leaf8]) leaves are called LEAFW.
49 +//
50 +// - BranchB, LeafB1 refer to bitmap branches and leaves (intermediate
51 +// populations).
52 +//
53 +// - BranchU refers to uncompressed branches. An uncompressed branch has 256
54 +// JPs, some of which could be null. Note: All leaves are compressed (and
55 +// sorted), or else an expanse is full (FullPopu), so there is no LeafU
56 +// equivalent to BranchU.
57 +//
58 +// - "Popu" is short for "Population".
59 +// - "Pop1" refers to actual population (base 1).
60 +// - "Pop0" refers to Pop1 - 1 (base 0), the way populations are stored in data
61 +// structures.
62 +//
63 +// - Branches and Leaves are both named by the number of bytes in their Pop0
64 +// field. In the case of Leaves, the same number applies to the Index sizes.
65 +//
66 +// - The representation of many numbers as hex is a relatively safe and
67 +// portable way to get desired bitpatterns as unsigned longs.
68 +//
69 +// - Some preprocessors cant handle single apostrophe characters within
70 +// #ifndef code, so here, delete all instead.
71 +
72 +
73 +#include "JudyPrivate.h" // includes Judy.h in turn.
74 +#include "JudyPrivateBranch.h" // support for branches.
75 +
76 +
77 +// ****************************************************************************
78 +// JUDYL ROOT POINTER (JRP) AND JUDYL POINTER (JP) TYPE FIELDS
79 +// ****************************************************************************
80 +
81 +typedef enum // uint8_t -- but C does not support this type of enum.
82 +{
83 +
84 +// JP NULL TYPES:
85 +//
86 +// There is a series of cJL_JPNULL* Types because each one pre-records a
87 +// different Index Size for when the first Index is inserted in the previously
88 +// null JP. They must start >= 8 (three bits).
89 +//
90 +// Note: These Types must be in sequential order for doing relative
91 +// calculations between them.
92 +
93 + cJL_JPNULL1 = 1,
94 + // Index Size 1[1] byte when 1 Index inserted.
95 + cJL_JPNULL2, // Index Size 2[2] bytes when 1 Index inserted.
96 + cJL_JPNULL3, // Index Size 3[3] bytes when 1 Index inserted.
97 +
98 +#ifndef JU_64BIT
99 +#define cJL_JPNULLMAX cJL_JPNULL3
100 +#else
101 + cJL_JPNULL4, // Index Size 4[4] bytes when 1 Index inserted.
102 + cJL_JPNULL5, // Index Size 5[5] bytes when 1 Index inserted.
103 + cJL_JPNULL6, // Index Size 6[6] bytes when 1 Index inserted.
104 + cJL_JPNULL7, // Index Size 7[7] bytes when 1 Index inserted.
105 +#define cJL_JPNULLMAX cJL_JPNULL7
106 +#endif
107 +
108 +
109 +// JP BRANCH TYPES:
110 +//
111 +// Note: There are no state-1 branches; only leaves reside at state 1.
112 +
113 +// Linear branches:
114 +//
115 +// Note: These Types must be in sequential order for doing relative
116 +// calculations between them.
117 +
118 + cJL_JPBRANCH_L2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
119 + cJL_JPBRANCH_L3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
120 +
121 +#ifdef JU_64BIT
122 + cJL_JPBRANCH_L4, // [4] bytes Pop0, [3] bytes Dcd.
123 + cJL_JPBRANCH_L5, // [5] bytes Pop0, [2] bytes Dcd.
124 + cJL_JPBRANCH_L6, // [6] bytes Pop0, [1] byte Dcd.
125 + cJL_JPBRANCH_L7, // [7] bytes Pop0, [0] bytes Dcd.
126 +#endif
127 +
128 + cJL_JPBRANCH_L, // note: DcdPopO field not used.
129 +
130 +// Bitmap branches:
131 +//
132 +// Note: These Types must be in sequential order for doing relative
133 +// calculations between them.
134 +
135 + cJL_JPBRANCH_B2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
136 + cJL_JPBRANCH_B3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
137 +
138 +#ifdef JU_64BIT
139 + cJL_JPBRANCH_B4, // [4] bytes Pop0, [3] bytes Dcd.
140 + cJL_JPBRANCH_B5, // [5] bytes Pop0, [2] bytes Dcd.
141 + cJL_JPBRANCH_B6, // [6] bytes Pop0, [1] byte Dcd.
142 + cJL_JPBRANCH_B7, // [7] bytes Pop0, [0] bytes Dcd.
143 +#endif
144 +
145 + cJL_JPBRANCH_B, // note: DcdPopO field not used.
146 +
147 +// Uncompressed branches:
148 +//
149 +// Note: These Types must be in sequential order for doing relative
150 +// calculations between them.
151 +
152 + cJL_JPBRANCH_U2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
153 + cJL_JPBRANCH_U3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
154 +
155 +#ifdef JU_64BIT
156 + cJL_JPBRANCH_U4, // [4] bytes Pop0, [3] bytes Dcd.
157 + cJL_JPBRANCH_U5, // [5] bytes Pop0, [2] bytes Dcd.
158 + cJL_JPBRANCH_U6, // [6] bytes Pop0, [1] byte Dcd.
159 + cJL_JPBRANCH_U7, // [7] bytes Pop0, [0] bytes Dcd.
160 +#endif
161 +
162 + cJL_JPBRANCH_U, // note: DcdPopO field not used.
163 +
164 +
165 +// JP LEAF TYPES:
166 +
167 +// Linear leaves:
168 +//
169 +// Note: These Types must be in sequential order for doing relative
170 +// calculations between them.
171 +//
172 +// Note: There is no full-word (4-byte [8-byte]) Index leaf under a JP because
173 +// non-root-state leaves only occur under branches that decode at least one
174 +// byte. Full-word, root-state leaves are under a JRP, not a JP. However, in
175 +// the code a "fake" JP can be created temporarily above a root-state leaf.
176 +
177 + cJL_JPLEAF1, // 1[1] byte Pop0, 2 bytes Dcd.
178 + cJL_JPLEAF2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
179 + cJL_JPLEAF3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
180 +
181 +#ifdef JU_64BIT
182 + cJL_JPLEAF4, // [4] bytes Pop0, [3] bytes Dcd.
183 + cJL_JPLEAF5, // [5] bytes Pop0, [2] bytes Dcd.
184 + cJL_JPLEAF6, // [6] bytes Pop0, [1] byte Dcd.
185 + cJL_JPLEAF7, // [7] bytes Pop0, [0] bytes Dcd.
186 +#endif
187 +
188 +// Bitmap leaf; Index Size == 1:
189 +//
190 +// Note: These are currently only supported at state 1. At other states the
191 +// bitmap would grow from 256 to 256^2, 256^3, ... bits, which would not be
192 +// efficient..
193 +
194 + cJL_JPLEAF_B1, // 1[1] byte Pop0, 2[6] bytes Dcd.
195 +
196 +// Full population; Index Size == 1 virtual leaf:
197 +//
198 +// Note: JudyL has no cJL_JPFULLPOPU1 equivalent to cJ1_JPFULLPOPU1, because
199 +// in the JudyL case this could result in a values-only leaf of up to 256 words
200 +// (value areas) that would be slow to insert/delete.
201 +
202 +
203 +// JP IMMEDIATES; leaves (Indexes) stored inside a JP:
204 +//
205 +// The second numeric suffix is the Pop1 for each type. As the Index Size
206 +// increases, the maximum possible population decreases.
207 +//
208 +// Note: These Types must be in sequential order in each group (Index Size),
209 +// and the groups in correct order too, for doing relative calculations between
210 +// them. For example, since these Types enumerate the Pop1 values (unlike
211 +// other JP Types where there is a Pop0 value in the JP), the maximum Pop1 for
212 +// each Index Size is computable.
213 +//
214 +// All enums equal or above this point are cJL_JPIMMEDs.
215 +
216 + cJL_JPIMMED_1_01, // Index Size = 1, Pop1 = 1.
217 + cJL_JPIMMED_2_01, // Index Size = 2, Pop1 = 1.
218 + cJL_JPIMMED_3_01, // Index Size = 3, Pop1 = 1.
219 +
220 +#ifdef JU_64BIT
221 + cJL_JPIMMED_4_01, // Index Size = 4, Pop1 = 1.
222 + cJL_JPIMMED_5_01, // Index Size = 5, Pop1 = 1.
223 + cJL_JPIMMED_6_01, // Index Size = 6, Pop1 = 1.
224 + cJL_JPIMMED_7_01, // Index Size = 7, Pop1 = 1.
225 +#endif
226 +
227 + cJL_JPIMMED_1_02, // Index Size = 1, Pop1 = 2.
228 + cJL_JPIMMED_1_03, // Index Size = 1, Pop1 = 3.
229 +
230 +#ifdef JU_64BIT
231 + cJL_JPIMMED_1_04, // Index Size = 1, Pop1 = 4.
232 + cJL_JPIMMED_1_05, // Index Size = 1, Pop1 = 5.
233 + cJL_JPIMMED_1_06, // Index Size = 1, Pop1 = 6.
234 + cJL_JPIMMED_1_07, // Index Size = 1, Pop1 = 7.
235 +
236 + cJL_JPIMMED_2_02, // Index Size = 2, Pop1 = 2.
237 + cJL_JPIMMED_2_03, // Index Size = 2, Pop1 = 3.
238 +
239 + cJL_JPIMMED_3_02, // Index Size = 3, Pop1 = 2.
240 +#endif
241 +
242 +// This special Type is merely a sentinel for doing relative calculations.
243 +// This value should not be used in switch statements (to avoid allocating code
244 +// for it), which is also why it appears at the end of the enum list.
245 +
246 + cJL_JPIMMED_CAP
247 +
248 +} jpL_Type_t;
249 +
250 +
251 +// RELATED VALUES:
252 +
253 +// Index Size (state) for leaf JP, and JP type based on Index Size (state):
254 +
255 +#define JL_LEAFINDEXSIZE(jpType) ((jpType) - cJL_JPLEAF1 + 1)
256 +#define JL_LEAFTYPE(IndexSize) ((IndexSize) + cJL_JPLEAF1 - 1)
257 +
258 +
259 +// MAXIMUM POPULATIONS OF LINEAR LEAVES:
260 +
261 +#ifndef JU_64BIT // 32-bit
262 +
263 +#define J_L_MAXB (sizeof(Word_t) * 64)
264 +#define ALLOCSIZES { 3, 5, 7, 11, 15, 23, 32, 47, 64, TERMINATOR } // in words.
265 +#define cJL_LEAF1_MAXWORDS (32) // max Leaf1 size in words.
266 +
267 +// Note: cJL_LEAF1_MAXPOP1 is chosen such that the index portion is less than
268 +// 32 bytes -- the number of bytes the index takes in a bitmap leaf.
269 +
270 +#define cJL_LEAF1_MAXPOP1 \
271 + ((cJL_LEAF1_MAXWORDS * cJU_BYTESPERWORD)/(1 + cJU_BYTESPERWORD))
272 +#define cJL_LEAF2_MAXPOP1 (J_L_MAXB / (2 + cJU_BYTESPERWORD))
273 +#define cJL_LEAF3_MAXPOP1 (J_L_MAXB / (3 + cJU_BYTESPERWORD))
274 +#define cJL_LEAFW_MAXPOP1 \
275 + ((J_L_MAXB - cJU_BYTESPERWORD) / (2 * cJU_BYTESPERWORD))
276 +
277 +#else // 64-bit
278 +
279 +#define J_L_MAXB (sizeof(Word_t) * 64)
280 +#define ALLOCSIZES { 3, 5, 7, 11, 15, 23, 32, 47, 64, TERMINATOR } // in words.
281 +#define cJL_LEAF1_MAXWORDS (15) // max Leaf1 size in words.
282 +
283 +#define cJL_LEAF1_MAXPOP1 \
284 + ((cJL_LEAF1_MAXWORDS * cJU_BYTESPERWORD)/(1 + cJU_BYTESPERWORD))
285 +#define cJL_LEAF2_MAXPOP1 (J_L_MAXB / (2 + cJU_BYTESPERWORD))
286 +#define cJL_LEAF3_MAXPOP1 (J_L_MAXB / (3 + cJU_BYTESPERWORD))
287 +#define cJL_LEAF4_MAXPOP1 (J_L_MAXB / (4 + cJU_BYTESPERWORD))
288 +#define cJL_LEAF5_MAXPOP1 (J_L_MAXB / (5 + cJU_BYTESPERWORD))
289 +#define cJL_LEAF6_MAXPOP1 (J_L_MAXB / (6 + cJU_BYTESPERWORD))
290 +#define cJL_LEAF7_MAXPOP1 (J_L_MAXB / (7 + cJU_BYTESPERWORD))
291 +#define cJL_LEAFW_MAXPOP1 \
292 + ((J_L_MAXB - cJU_BYTESPERWORD) / (2 * cJU_BYTESPERWORD))
293 +
294 +#endif // 64-bit
295 +
296 +
297 +// MAXIMUM POPULATIONS OF IMMEDIATE JPs:
298 +//
299 +// These specify the maximum Population of immediate JPs with various Index
300 +// Sizes (== sizes of remaining undecoded Index bits). Since the JP Types enum
301 +// already lists all the immediates in order by state and size, calculate these
302 +// values from it to avoid redundancy.
303 +
304 +#define cJL_IMMED1_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 1) // 3 [7].
305 +#define cJL_IMMED2_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 2) // 1 [3].
306 +#define cJL_IMMED3_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 3) // 1 [2].
307 +
308 +#ifdef JU_64BIT
309 +#define cJL_IMMED4_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 4) // [1].
310 +#define cJL_IMMED5_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 5) // [1].
311 +#define cJL_IMMED6_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 6) // [1].
312 +#define cJL_IMMED7_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 7) // [1].
313 +#endif
314 +
315 +
316 +// ****************************************************************************
317 +// JUDYL LEAF BITMAP (JLLB) SUPPORT
318 +// ****************************************************************************
319 +//
320 +// Assemble bitmap leaves out of smaller units that put bitmap subexpanses
321 +// close to their associated pointers. Why not just use a bitmap followed by a
322 +// series of pointers? (See 4.27.) Turns out this wastes a cache fill on
323 +// systems with smaller cache lines than the assumed value cJU_WORDSPERCL.
324 +
325 +#define JL_JLB_BITMAP(Pjlb, Subexp) ((Pjlb)->jLlb_jLlbs[Subexp].jLlbs_Bitmap)
326 +#define JL_JLB_PVALUE(Pjlb, Subexp) ((Pjlb)->jLlb_jLlbs[Subexp].jLlbs_PValue)
327 +
328 +typedef struct J__UDYL_LEAF_BITMAP_SUBEXPANSE
329 +{
330 + BITMAPL_t jLlbs_Bitmap;
331 + Pjv_t jLlbs_PValue;
332 +
333 +} jLlbs_t;
334 +
335 +typedef struct J__UDYL_LEAF_BITMAP
336 +{
337 + jLlbs_t jLlb_jLlbs[cJU_NUMSUBEXPL];
338 +
339 +} jLlb_t, * PjLlb_t;
340 +
341 +// Words per bitmap leaf:
342 +
343 +#define cJL_WORDSPERLEAFB1 (sizeof(jLlb_t) / cJU_BYTESPERWORD)
344 +
345 +
346 +// ****************************************************************************
347 +// MEMORY ALLOCATION SUPPORT
348 +// ****************************************************************************
349 +
350 +// ARRAY-GLOBAL INFORMATION:
351 +//
352 +// At the cost of an occasional additional cache fill, this object, which is
353 +// pointed at by a JRP and in turn points to a JP_BRANCH*, carries array-global
354 +// information about a JudyL array that has sufficient population to amortize
355 +// the cost. The jpm_Pop0 field prevents having to add up the total population
356 +// for the array in insert, delete, and count code. The jpm_JP field prevents
357 +// having to build a fake JP for entry to a state machine; however, the
358 +// jp_DcdPopO field in jpm_JP, being one byte too small, is not used.
359 +//
360 +// Note: Struct fields are ordered to keep "hot" data in the first 8 words
361 +// (see left-margin comments) for machines with 8-word cache lines, and to keep
362 +// sub-word fields together for efficient packing.
363 +
364 +typedef struct J_UDYL_POPULATION_AND_MEMORY
365 +{
366 +/* 1 */ Word_t jpm_Pop0; // total population-1 in array.
367 +/* 2 */ jp_t jpm_JP; // JP to first branch; see above.
368 +/* 4 */ Word_t jpm_LastUPop0; // last jpm_Pop0 when convert to BranchU
369 +/* 7 */ Pjv_t jpm_PValue; // pointer to value to return.
370 +// Note: Field names match PJError_t for convenience in macros:
371 +/* 8 */ char je_Errno; // one of the enums in Judy.h.
372 +/* 8/9 */ int je_ErrID; // often an internal source line number.
373 +/* 9/10 */ Word_t jpm_TotalMemWords; // words allocated in array.
374 +} jLpm_t, *PjLpm_t;
375 +
376 +
377 +// TABLES FOR DETERMINING IF LEAVES HAVE ROOM TO GROW:
378 +//
379 +// These tables indicate if a given memory chunk can support growth of a given
380 +// object into wasted (rounded-up) memory in the chunk. Note: This violates
381 +// the hiddenness of the JudyMalloc code.
382 +
383 +extern const uint8_t j__L_Leaf1PopToWords[cJL_LEAF1_MAXPOP1 + 1];
384 +extern const uint8_t j__L_Leaf2PopToWords[cJL_LEAF2_MAXPOP1 + 1];
385 +extern const uint8_t j__L_Leaf3PopToWords[cJL_LEAF3_MAXPOP1 + 1];
386 +#ifdef JU_64BIT
387 +extern const uint8_t j__L_Leaf4PopToWords[cJL_LEAF4_MAXPOP1 + 1];
388 +extern const uint8_t j__L_Leaf5PopToWords[cJL_LEAF5_MAXPOP1 + 1];
389 +extern const uint8_t j__L_Leaf6PopToWords[cJL_LEAF6_MAXPOP1 + 1];
390 +extern const uint8_t j__L_Leaf7PopToWords[cJL_LEAF7_MAXPOP1 + 1];
391 +#endif
392 +extern const uint8_t j__L_LeafWPopToWords[cJL_LEAFW_MAXPOP1 + 1];
393 +extern const uint8_t j__L_LeafVPopToWords[];
394 +
395 +// These tables indicate where value areas start:
396 +
397 +extern const uint8_t j__L_Leaf1Offset [cJL_LEAF1_MAXPOP1 + 1];
398 +extern const uint8_t j__L_Leaf2Offset [cJL_LEAF2_MAXPOP1 + 1];
399 +extern const uint8_t j__L_Leaf3Offset [cJL_LEAF3_MAXPOP1 + 1];
400 +#ifdef JU_64BIT
401 +extern const uint8_t j__L_Leaf4Offset [cJL_LEAF4_MAXPOP1 + 1];
402 +extern const uint8_t j__L_Leaf5Offset [cJL_LEAF5_MAXPOP1 + 1];
403 +extern const uint8_t j__L_Leaf6Offset [cJL_LEAF6_MAXPOP1 + 1];
404 +extern const uint8_t j__L_Leaf7Offset [cJL_LEAF7_MAXPOP1 + 1];
405 +#endif
406 +extern const uint8_t j__L_LeafWOffset [cJL_LEAFW_MAXPOP1 + 1];
407 +
408 +// Also define macros to hide the details in the code using these tables.
409 +
410 +#define JL_LEAF1GROWINPLACE(Pop1) \
411 + J__U_GROWCK(Pop1, cJL_LEAF1_MAXPOP1, j__L_Leaf1PopToWords)
412 +#define JL_LEAF2GROWINPLACE(Pop1) \
413 + J__U_GROWCK(Pop1, cJL_LEAF2_MAXPOP1, j__L_Leaf2PopToWords)
414 +#define JL_LEAF3GROWINPLACE(Pop1) \
415 + J__U_GROWCK(Pop1, cJL_LEAF3_MAXPOP1, j__L_Leaf3PopToWords)
416 +#ifdef JU_64BIT
417 +#define JL_LEAF4GROWINPLACE(Pop1) \
418 + J__U_GROWCK(Pop1, cJL_LEAF4_MAXPOP1, j__L_Leaf4PopToWords)
419 +#define JL_LEAF5GROWINPLACE(Pop1) \
420 + J__U_GROWCK(Pop1, cJL_LEAF5_MAXPOP1, j__L_Leaf5PopToWords)
421 +#define JL_LEAF6GROWINPLACE(Pop1) \
422 + J__U_GROWCK(Pop1, cJL_LEAF6_MAXPOP1, j__L_Leaf6PopToWords)
423 +#define JL_LEAF7GROWINPLACE(Pop1) \
424 + J__U_GROWCK(Pop1, cJL_LEAF7_MAXPOP1, j__L_Leaf7PopToWords)
425 +#endif
426 +#define JL_LEAFWGROWINPLACE(Pop1) \
427 + J__U_GROWCK(Pop1, cJL_LEAFW_MAXPOP1, j__L_LeafWPopToWords)
428 +#define JL_LEAFVGROWINPLACE(Pop1) \
429 + J__U_GROWCK(Pop1, cJU_BITSPERSUBEXPL, j__L_LeafVPopToWords)
430 +
431 +#define JL_LEAF1VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf1Offset[Pop1])
432 +#define JL_LEAF2VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf2Offset[Pop1])
433 +#define JL_LEAF3VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf3Offset[Pop1])
434 +#ifdef JU_64BIT
435 +#define JL_LEAF4VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf4Offset[Pop1])
436 +#define JL_LEAF5VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf5Offset[Pop1])
437 +#define JL_LEAF6VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf6Offset[Pop1])
438 +#define JL_LEAF7VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf7Offset[Pop1])
439 +#endif
440 +#define JL_LEAFWVALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_LeafWOffset[Pop1])
441 +
442 +#define JL_LEAF1POPTOWORDS(Pop1) (j__L_Leaf1PopToWords[Pop1])
443 +#define JL_LEAF2POPTOWORDS(Pop1) (j__L_Leaf2PopToWords[Pop1])
444 +#define JL_LEAF3POPTOWORDS(Pop1) (j__L_Leaf3PopToWords[Pop1])
445 +#ifdef JU_64BIT
446 +#define JL_LEAF4POPTOWORDS(Pop1) (j__L_Leaf4PopToWords[Pop1])
447 +#define JL_LEAF5POPTOWORDS(Pop1) (j__L_Leaf5PopToWords[Pop1])
448 +#define JL_LEAF6POPTOWORDS(Pop1) (j__L_Leaf6PopToWords[Pop1])
449 +#define JL_LEAF7POPTOWORDS(Pop1) (j__L_Leaf7PopToWords[Pop1])
450 +#endif
451 +#define JL_LEAFWPOPTOWORDS(Pop1) (j__L_LeafWPopToWords[Pop1])
452 +#define JL_LEAFVPOPTOWORDS(Pop1) (j__L_LeafVPopToWords[Pop1])
453 +
454 +
455 +// FUNCTIONS TO ALLOCATE OBJECTS:
456 +
457 +PjLpm_t j__udyLAllocJLPM(void); // constant size.
458 +
459 +Pjbl_t j__udyLAllocJBL( PjLpm_t); // constant size.
460 +Pjbb_t j__udyLAllocJBB( PjLpm_t); // constant size.
461 +Pjp_t j__udyLAllocJBBJP(Word_t, PjLpm_t);
462 +Pjbu_t j__udyLAllocJBU( PjLpm_t); // constant size.
463 +
464 +Pjll_t j__udyLAllocJLL1( Word_t, PjLpm_t);
465 +Pjll_t j__udyLAllocJLL2( Word_t, PjLpm_t);
466 +Pjll_t j__udyLAllocJLL3( Word_t, PjLpm_t);
467 +
468 +#ifdef JU_64BIT
469 +Pjll_t j__udyLAllocJLL4( Word_t, PjLpm_t);
470 +Pjll_t j__udyLAllocJLL5( Word_t, PjLpm_t);
471 +Pjll_t j__udyLAllocJLL6( Word_t, PjLpm_t);
472 +Pjll_t j__udyLAllocJLL7( Word_t, PjLpm_t);
473 +#endif
474 +
475 +Pjlw_t j__udyLAllocJLW( Word_t ); // no PjLpm_t needed.
476 +PjLlb_t j__udyLAllocJLB1( PjLpm_t); // constant size.
477 +Pjv_t j__udyLAllocJV( Word_t, PjLpm_t);
478 +
479 +
480 +// FUNCTIONS TO FREE OBJECTS:
481 +
482 +void j__udyLFreeJLPM( PjLpm_t, PjLpm_t); // constant size.
483 +
484 +void j__udyLFreeJBL( Pjbl_t, PjLpm_t); // constant size.
485 +void j__udyLFreeJBB( Pjbb_t, PjLpm_t); // constant size.
486 +void j__udyLFreeJBBJP(Pjp_t, Word_t, PjLpm_t);
487 +void j__udyLFreeJBU( Pjbu_t, PjLpm_t); // constant size.
488 +
489 +void j__udyLFreeJLL1( Pjll_t, Word_t, PjLpm_t);
490 +void j__udyLFreeJLL2( Pjll_t, Word_t, PjLpm_t);
491 +void j__udyLFreeJLL3( Pjll_t, Word_t, PjLpm_t);
492 +
493 +#ifdef JU_64BIT
494 +void j__udyLFreeJLL4( Pjll_t, Word_t, PjLpm_t);
495 +void j__udyLFreeJLL5( Pjll_t, Word_t, PjLpm_t);
496 +void j__udyLFreeJLL6( Pjll_t, Word_t, PjLpm_t);
497 +void j__udyLFreeJLL7( Pjll_t, Word_t, PjLpm_t);
498 +#endif
499 +
500 +void j__udyLFreeJLW( Pjlw_t, Word_t, PjLpm_t);
501 +void j__udyLFreeJLB1( PjLlb_t, PjLpm_t); // constant size.
502 +void j__udyLFreeJV( Pjv_t, Word_t, PjLpm_t);
503 +void j__udyLFreeSM( Pjp_t, PjLpm_t); // everything below Pjp.
504 +
505 +#endif // ! _JUDYL_INCLUDED
libnetdata/libjudy/src/JudyL/JudyLByCount.c new
+954
@@ -0,0 +1,954 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.28 $ $Source: /judy/src/JudyCommon/JudyByCount.c $
19 +//
20 +// Judy*ByCount() function for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DNOSMARTJBB, -DNOSMARTJBU, and/or -DNOSMARTJLB to build a
24 +// version with cache line optimizations deleted, for testing.
25 +//
26 +// Judy*ByCount() is a conceptual although not literal inverse of Judy*Count().
27 +// Judy*Count() takes a pair of Indexes, and allows finding the ordinal of a
28 +// given Index (that is, its position in the list of valid indexes from the
29 +// beginning) as a degenerate case, because in general the count between two
30 +// Indexes, inclusive, is not always just the difference in their ordinals.
31 +// However, it suffices for Judy*ByCount() to simply be an ordinal-to-Index
32 +// mapper.
33 +//
34 +// Note: Like Judy*Count(), this code must "count sideways" in branches, which
35 +// can result in a lot of cache line fills. However, unlike Judy*Count(), this
36 +// code does not receive a specific Index, hence digit, where to start in each
37 +// branch, so it cant accurately calculate cache line fills required in each
38 +// direction. The best it can do is an approximation based on the total
39 +// population of the expanse (pop1 from Pjp) and the ordinal of the target
40 +// Index (see SETOFFSET()) within the expanse.
41 +//
42 +// Compile with -DSMARTMETRICS to obtain global variables containing smart
43 +// cache line metrics. Note: Dont turn this on simultaneously for this file
44 +// and JudyCount.c because they export the same globals.
45 +// ****************************************************************************
46 +
47 +#if (! (defined(JUDY1) || defined(JUDYL)))
48 +#error: One of -DJUDY1 or -DJUDYL must be specified.
49 +#endif
50 +
51 +#ifdef JUDY1
52 +#include "Judy1.h"
53 +#else
54 +#include "JudyL.h"
55 +#endif
56 +
57 +#include "JudyPrivate1L.h"
58 +
59 +// These are imported from JudyCount.c:
60 +//
61 +// TBD: Should this be in common code? Exported from a header file?
62 +
63 +#ifdef JUDY1
64 +extern Word_t j__udy1JPPop1(const Pjp_t Pjp);
65 +#define j__udyJPPop1 j__udy1JPPop1
66 +#else
67 +extern Word_t j__udyLJPPop1(const Pjp_t Pjp);
68 +#define j__udyJPPop1 j__udyLJPPop1
69 +#endif
70 +
71 +// Avoid duplicate symbols since this file is multi-compiled:
72 +
73 +#ifdef SMARTMETRICS
74 +#ifdef JUDY1
75 +Word_t jbb_upward = 0; // counts of directions taken:
76 +Word_t jbb_downward = 0;
77 +Word_t jbu_upward = 0;
78 +Word_t jbu_downward = 0;
79 +Word_t jlb_upward = 0;
80 +Word_t jlb_downward = 0;
81 +#else
82 +extern Word_t jbb_upward;
83 +extern Word_t jbb_downward;
84 +extern Word_t jbu_upward;
85 +extern Word_t jbu_downward;
86 +extern Word_t jlb_upward;
87 +extern Word_t jlb_downward;
88 +#endif
89 +#endif
90 +
91 +
92 +// ****************************************************************************
93 +// J U D Y 1 B Y C O U N T
94 +// J U D Y L B Y C O U N T
95 +//
96 +// See the manual entry.
97 +
98 +#ifdef JUDY1
99 +FUNCTION int Judy1ByCount
100 +#else
101 +FUNCTION PPvoid_t JudyLByCount
102 +#endif
103 + (
104 + Pcvoid_t PArray, // root pointer to first branch/leaf in SM.
105 + Word_t Count, // ordinal of Index to find, 1..MAX.
106 + Word_t * PIndex, // to return found Index.
107 + PJError_t PJError // optional, for returning error info.
108 + )
109 +{
110 + Word_t Count0; // Count, base-0, to match pop0.
111 + Word_t state; // current state in SM.
112 + Word_t pop1; // of current branch or leaf, or of expanse.
113 + Word_t pop1lower; // pop1 of expanses (JPs) below that for Count.
114 + Word_t digit; // current word in branch.
115 + Word_t jpcount; // JPs in a BranchB subexpanse.
116 + long jpnum; // JP number in a branch (base 0).
117 + long subexp; // for stepping through layer 1 (subexpanses).
118 + int offset; // index ordinal within a leaf, base 0.
119 +
120 + Pjp_t Pjp; // current JP in branch.
121 + Pjll_t Pjll; // current Judy linear leaf.
122 +
123 +
124 +// CHECK FOR EMPTY ARRAY OR NULL PINDEX:
125 +
126 + if (PArray == (Pvoid_t) NULL) JU_RET_NOTFOUND;
127 +
128 + if (PIndex == (PWord_t) NULL)
129 + {
130 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
131 + JUDY1CODE(return(JERRI );)
132 + JUDYLCODE(return(PPJERR);)
133 + }
134 +
135 +// Convert Count to Count0; assume special case of Count = 0 maps to ~0, as
136 +// desired, to represent the last index in a full array:
137 +//
138 +// Note: Think of Count0 as a reliable "number of Indexes below the target."
139 +
140 + Count0 = Count - 1;
141 + assert((Count || Count0 == ~0)); // ensure CPU is sane about 0 - 1.
142 + pop1lower = 0;
143 +
144 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
145 + {
146 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
147 +
148 + if (Count0 > Pjlw[0]) JU_RET_NOTFOUND; // too high.
149 +
150 + *PIndex = Pjlw[Count]; // Index, base 1.
151 +
152 + JU_RET_FOUND_LEAFW(Pjlw, Pjlw[0] + 1, Count0);
153 + }
154 + else
155 + {
156 + Pjpm_t Pjpm = P_JPM(PArray);
157 +
158 + if (Count0 > (Pjpm->jpm_Pop0)) JU_RET_NOTFOUND; // too high.
159 +
160 + Pjp = &(Pjpm->jpm_JP);
161 + pop1 = (Pjpm->jpm_Pop0) + 1;
162 +
163 +// goto SMByCount;
164 + }
165 +
166 +// COMMON CODE:
167 +//
168 +// Prepare to handle a root-level or lower-level branch: Save the current
169 +// state, obtain the total population for the branch in a state-dependent way,
170 +// and then branch to common code for multiple cases.
171 +//
172 +// For root-level branches, the state is always cJU_ROOTSTATE, and the array
173 +// population must already be set in pop1; it is not available in jp_DcdPopO.
174 +//
175 +// Note: The total population is only needed in cases where the common code
176 +// "counts down" instead of up to minimize cache line fills. However, its
177 +// available cheaply, and its better to do it with a constant shift (constant
178 +// state value) instead of a variable shift later "when needed".
179 +
180 +#define PREPB_ROOT(Next) \
181 + state = cJU_ROOTSTATE; \
182 + goto Next
183 +
184 +// Use PREPB_DCD() to first copy the Dcd bytes to *PIndex if there are any
185 +// (only if state < cJU_ROOTSTATE - 1):
186 +
187 +#define PREPB_DCD(Pjp,cState,Next) \
188 + JU_SETDCD(*PIndex, Pjp, cState); \
189 + PREPB((Pjp), cState, Next)
190 +
191 +#define PREPB(Pjp,cState,Next) \
192 + state = (cState); \
193 + pop1 = JU_JPBRANCH_POP0(Pjp, (cState)) + 1; \
194 + goto Next
195 +
196 +// Calculate whether the ordinal of an Index within a given expanse falls in
197 +// the lower or upper half of the expanses population, taking care with
198 +// unsigned math and boundary conditions:
199 +//
200 +// Note: Assume the ordinal falls within the expanses population, that is,
201 +// 0 < (Count - Pop1lower) <= Pop1exp (assuming infinite math).
202 +//
203 +// Note: If the ordinal is the middle element, it doesnt matter whether
204 +// LOWERHALF() is TRUE or FALSE.
205 +
206 +#define LOWERHALF(Count0,Pop1lower,Pop1exp) \
207 + (((Count0) - (Pop1lower)) < ((Pop1exp) / 2))
208 +
209 +// Calculate the (signed) offset within a leaf to the desired ordinal (Count -
210 +// Pop1lower; offset is one less), and optionally ensure its in range:
211 +
212 +#define SETOFFSET(Offset,Count0,Pop1lower,Pjp) \
213 + (Offset) = (Count0) - (Pop1lower); \
214 + assert((Offset) >= 0); \
215 + assert((Offset) <= JU_JPLEAF_POP0(Pjp))
216 +
217 +// Variations for immediate indexes, with and without pop1-specific assertions:
218 +
219 +#define SETOFFSET_IMM_CK(Offset,Count0,Pop1lower,cPop1) \
220 + (Offset) = (Count0) - (Pop1lower); \
221 + assert((Offset) >= 0); \
222 + assert((Offset) < (cPop1))
223 +
224 +#define SETOFFSET_IMM(Offset,Count0,Pop1lower) \
225 + (Offset) = (Count0) - (Pop1lower)
226 +
227 +
228 +// STATE MACHINE -- TRAVERSE TREE:
229 +//
230 +// In branches, look for the expanse (digit), if any, where the total pop1
231 +// below or at that expanse would meet or exceed Count, meaning the Index must
232 +// be in this expanse.
233 +
234 +SMByCount: // return here for next branch/leaf.
235 +
236 + switch (JU_JPTYPE(Pjp))
237 + {
238 +
239 +
240 +// ----------------------------------------------------------------------------
241 +// LINEAR BRANCH; count populations in JPs in the JBL upwards until finding the
242 +// expanse (digit) containing Count, and "recurse".
243 +//
244 +// Note: There are no null JPs in a JBL; watch out for pop1 == 0.
245 +//
246 +// Note: A JBL should always fit in one cache line => no need to count up
247 +// versus down to save cache line fills.
248 +//
249 +// TBD: The previous is no longer true. Consider enhancing this code to count
250 +// up/down, but it can wait for a later tuning phase. In the meantime, PREPB()
251 +// sets pop1 for the whole array, but that value is not used here. 001215:
252 +// Maybe its true again?
253 +
254 + case cJU_JPBRANCH_L2: PREPB_DCD(Pjp, 2, BranchL);
255 +#ifndef JU_64BIT
256 + case cJU_JPBRANCH_L3: PREPB( Pjp, 3, BranchL);
257 +#else
258 + case cJU_JPBRANCH_L3: PREPB_DCD(Pjp, 3, BranchL);
259 + case cJU_JPBRANCH_L4: PREPB_DCD(Pjp, 4, BranchL);
260 + case cJU_JPBRANCH_L5: PREPB_DCD(Pjp, 5, BranchL);
261 + case cJU_JPBRANCH_L6: PREPB_DCD(Pjp, 6, BranchL);
262 + case cJU_JPBRANCH_L7: PREPB( Pjp, 7, BranchL);
263 +#endif
264 + case cJU_JPBRANCH_L: PREPB_ROOT( BranchL);
265 + {
266 + Pjbl_t Pjbl;
267 +
268 +// Common code (state-independent) for all cases of linear branches:
269 +
270 +BranchL:
271 + Pjbl = P_JBL(Pjp->jp_Addr);
272 +
273 + for (jpnum = 0; jpnum < (Pjbl->jbl_NumJPs); ++jpnum)
274 + {
275 + if ((pop1 = j__udyJPPop1((Pjbl->jbl_jp) + jpnum))
276 + == cJU_ALLONES)
277 + {
278 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
279 + JUDY1CODE(return(JERRI );)
280 + JUDYLCODE(return(PPJERR);)
281 + }
282 + assert(pop1 != 0);
283 +
284 +// Warning: pop1lower and pop1 are unsigned, so do not subtract 1 and compare
285 +// >=, but instead use the following expression:
286 +
287 + if (pop1lower + pop1 > Count0) // Index is in this expanse.
288 + {
289 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[jpnum], state);
290 + Pjp = (Pjbl->jbl_jp) + jpnum;
291 + goto SMByCount; // look under this expanse.
292 + }
293 +
294 + pop1lower += pop1; // add this JPs pop1.
295 + }
296 +
297 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
298 + JUDY1CODE(return(JERRI );)
299 + JUDYLCODE(return(PPJERR);)
300 +
301 + } // case cJU_JPBRANCH_L
302 +
303 +
304 +// ----------------------------------------------------------------------------
305 +// BITMAP BRANCH; count populations in JPs in the JBB upwards or downwards
306 +// until finding the expanse (digit) containing Count, and "recurse".
307 +//
308 +// Note: There are no null JPs in a JBB; watch out for pop1 == 0.
309 +
310 + case cJU_JPBRANCH_B2: PREPB_DCD(Pjp, 2, BranchB);
311 +#ifndef JU_64BIT
312 + case cJU_JPBRANCH_B3: PREPB( Pjp, 3, BranchB);
313 +#else
314 + case cJU_JPBRANCH_B3: PREPB_DCD(Pjp, 3, BranchB);
315 + case cJU_JPBRANCH_B4: PREPB_DCD(Pjp, 4, BranchB);
316 + case cJU_JPBRANCH_B5: PREPB_DCD(Pjp, 5, BranchB);
317 + case cJU_JPBRANCH_B6: PREPB_DCD(Pjp, 6, BranchB);
318 + case cJU_JPBRANCH_B7: PREPB( Pjp, 7, BranchB);
319 +#endif
320 + case cJU_JPBRANCH_B: PREPB_ROOT( BranchB);
321 + {
322 + Pjbb_t Pjbb;
323 +
324 +// Common code (state-independent) for all cases of bitmap branches:
325 +
326 +BranchB:
327 + Pjbb = P_JBB(Pjp->jp_Addr);
328 +
329 +// Shorthand for one subexpanse in a bitmap and for one JP in a bitmap branch:
330 +//
331 +// Note: BMPJP0 exists separately to support assertions.
332 +
333 +#define BMPJP0(Subexp) (P_JP(JU_JBB_PJP(Pjbb, Subexp)))
334 +#define BMPJP(Subexp,JPnum) (BMPJP0(Subexp) + (JPnum))
335 +
336 +
337 +// Common code for descending through a JP:
338 +//
339 +// Determine the digit for the expanse and save it in *PIndex; then "recurse".
340 +
341 +#define JBB_FOUNDEXPANSE \
342 + { \
343 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb,subexp), jpnum); \
344 + JU_SETDIGIT(*PIndex, digit, state); \
345 + Pjp = BMPJP(subexp, jpnum); \
346 + goto SMByCount; \
347 + }
348 +
349 +
350 +#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
351 +
352 +// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
353 +// in JPs upwards, or subtracting the pop1s in JPs downwards:
354 +//
355 +// See header comments about limitations of this for Judy*ByCount().
356 +
357 +#endif
358 +
359 +// COUNT UPWARD, adding each "below" JPs pop1:
360 +
361 +#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
362 +
363 + if (LOWERHALF(Count0, pop1lower, pop1))
364 + {
365 +#endif
366 +#ifdef SMARTMETRICS
367 + ++jbb_upward;
368 +#endif
369 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
370 + {
371 + if ((jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,subexp)))
372 + && (BMPJP0(subexp) == (Pjp_t) NULL))
373 + {
374 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // null ptr.
375 + JUDY1CODE(return(JERRI );)
376 + JUDYLCODE(return(PPJERR);)
377 + }
378 +
379 +// Note: An empty subexpanse (jpcount == 0) is handled "for free":
380 +
381 + for (jpnum = 0; jpnum < jpcount; ++jpnum)
382 + {
383 + if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
384 + == cJU_ALLONES)
385 + {
386 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
387 + JUDY1CODE(return(JERRI );)
388 + JUDYLCODE(return(PPJERR);)
389 + }
390 + assert(pop1 != 0);
391 +
392 +// Warning: pop1lower and pop1 are unsigned, see earlier comment:
393 +
394 + if (pop1lower + pop1 > Count0)
395 + JBB_FOUNDEXPANSE; // Index is in this expanse.
396 +
397 + pop1lower += pop1; // add this JPs pop1.
398 + }
399 + }
400 +#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
401 + }
402 +
403 +
404 +// COUNT DOWNWARD, subtracting each "above" JPs pop1 from the whole expanses
405 +// pop1:
406 +
407 + else
408 + {
409 +#ifdef SMARTMETRICS
410 + ++jbb_downward;
411 +#endif
412 + pop1lower += pop1; // add whole branch to start.
413 +
414 + for (subexp = cJU_NUMSUBEXPB - 1; subexp >= 0; --subexp)
415 + {
416 + if ((jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp)))
417 + && (BMPJP0(subexp) == (Pjp_t) NULL))
418 + {
419 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // null ptr.
420 + JUDY1CODE(return(JERRI );)
421 + JUDYLCODE(return(PPJERR);)
422 + }
423 +
424 +// Note: An empty subexpanse (jpcount == 0) is handled "for free":
425 +
426 + for (jpnum = jpcount - 1; jpnum >= 0; --jpnum)
427 + {
428 + if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
429 + == cJU_ALLONES)
430 + {
431 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
432 + JUDY1CODE(return(JERRI );)
433 + JUDYLCODE(return(PPJERR);)
434 + }
435 + assert(pop1 != 0);
436 +
437 +// Warning: pop1lower and pop1 are unsigned, see earlier comment:
438 +
439 + pop1lower -= pop1;
440 +
441 +// Beware unsigned math problems:
442 +
443 + if ((pop1lower == 0) || (pop1lower - 1 < Count0))
444 + JBB_FOUNDEXPANSE; // Index is in this expanse.
445 + }
446 + }
447 + }
448 +#endif // NOSMARTJBB
449 +
450 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
451 + JUDY1CODE(return(JERRI );)
452 + JUDYLCODE(return(PPJERR);)
453 +
454 + } // case cJU_JPBRANCH_B
455 +
456 +
457 +// ----------------------------------------------------------------------------
458 +// UNCOMPRESSED BRANCH; count populations in JPs in the JBU upwards or
459 +// downwards until finding the expanse (digit) containing Count, and "recurse".
460 +
461 + case cJU_JPBRANCH_U2: PREPB_DCD(Pjp, 2, BranchU);
462 +#ifndef JU_64BIT
463 + case cJU_JPBRANCH_U3: PREPB( Pjp, 3, BranchU);
464 +#else
465 + case cJU_JPBRANCH_U3: PREPB_DCD(Pjp, 3, BranchU);
466 + case cJU_JPBRANCH_U4: PREPB_DCD(Pjp, 4, BranchU);
467 + case cJU_JPBRANCH_U5: PREPB_DCD(Pjp, 5, BranchU);
468 + case cJU_JPBRANCH_U6: PREPB_DCD(Pjp, 6, BranchU);
469 + case cJU_JPBRANCH_U7: PREPB( Pjp, 7, BranchU);
470 +#endif
471 + case cJU_JPBRANCH_U: PREPB_ROOT( BranchU);
472 + {
473 + Pjbu_t Pjbu;
474 +
475 +// Common code (state-independent) for all cases of uncompressed branches:
476 +
477 +BranchU:
478 + Pjbu = P_JBU(Pjp->jp_Addr);
479 +
480 +// Common code for descending through a JP:
481 +//
482 +// Save the digit for the expanse in *PIndex, then "recurse".
483 +
484 +#define JBU_FOUNDEXPANSE \
485 + { \
486 + JU_SETDIGIT(*PIndex, jpnum, state); \
487 + Pjp = (Pjbu->jbu_jp) + jpnum; \
488 + goto SMByCount; \
489 + }
490 +
491 +
492 +#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
493 +
494 +// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
495 +// in JPs upwards, or subtracting the pop1s in JPs downwards:
496 +//
497 +// See header comments about limitations of this for Judy*ByCount().
498 +
499 +#endif
500 +
501 +// COUNT UPWARD, simply adding the pop1 of each JP:
502 +
503 +#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
504 +
505 + if (LOWERHALF(Count0, pop1lower, pop1))
506 + {
507 +#endif
508 +#ifdef SMARTMETRICS
509 + ++jbu_upward;
510 +#endif
511 +
512 + for (jpnum = 0; jpnum < cJU_BRANCHUNUMJPS; ++jpnum)
513 + {
514 + // shortcut, save a function call:
515 +
516 + if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
517 + continue;
518 +
519 + if ((pop1 = j__udyJPPop1((Pjbu->jbu_jp) + jpnum))
520 + == cJU_ALLONES)
521 + {
522 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
523 + JUDY1CODE(return(JERRI );)
524 + JUDYLCODE(return(PPJERR);)
525 + }
526 + assert(pop1 != 0);
527 +
528 +// Warning: pop1lower and pop1 are unsigned, see earlier comment:
529 +
530 + if (pop1lower + pop1 > Count0)
531 + JBU_FOUNDEXPANSE; // Index is in this expanse.
532 +
533 + pop1lower += pop1; // add this JPs pop1.
534 + }
535 +#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
536 + }
537 +
538 +
539 +// COUNT DOWNWARD, subtracting the pop1 of each JP above from the whole
540 +// expanses pop1:
541 +
542 + else
543 + {
544 +#ifdef SMARTMETRICS
545 + ++jbu_downward;
546 +#endif
547 + pop1lower += pop1; // add whole branch to start.
548 +
549 + for (jpnum = cJU_BRANCHUNUMJPS - 1; jpnum >= 0; --jpnum)
550 + {
551 + // shortcut, save a function call:
552 +
553 + if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
554 + continue;
555 +
556 + if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
557 + == cJU_ALLONES)
558 + {
559 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
560 + JUDY1CODE(return(JERRI );)
561 + JUDYLCODE(return(PPJERR);)
562 + }
563 + assert(pop1 != 0);
564 +
565 +// Warning: pop1lower and pop1 are unsigned, see earlier comment:
566 +
567 + pop1lower -= pop1;
568 +
569 +// Beware unsigned math problems:
570 +
571 + if ((pop1lower == 0) || (pop1lower - 1 < Count0))
572 + JBU_FOUNDEXPANSE; // Index is in this expanse.
573 + }
574 + }
575 +#endif // NOSMARTJBU
576 +
577 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
578 + JUDY1CODE(return(JERRI );)
579 + JUDYLCODE(return(PPJERR);)
580 +
581 + } // case cJU_JPBRANCH_U
582 +
583 +// ----------------------------------------------------------------------------
584 +// LINEAR LEAF:
585 +//
586 +// Return the Index at the proper ordinal (see SETOFFSET()) in the leaf. First
587 +// copy Dcd bytes, if there are any (only if state < cJU_ROOTSTATE - 1), to
588 +// *PIndex.
589 +//
590 +// Note: The preceding branch traversal code MIGHT set pop1 for this expanse
591 +// (linear leaf) as a side-effect, but dont depend on that (for JUDYL, which
592 +// is the only cases that need it anyway).
593 +
594 +#define PREPL_DCD(cState) \
595 + JU_SETDCD(*PIndex, Pjp, cState); \
596 + PREPL
597 +
598 +#ifdef JUDY1
599 +#define PREPL_SETPOP1 // not needed in any cases.
600 +#else
601 +#define PREPL_SETPOP1 pop1 = JU_JPLEAF_POP0(Pjp) + 1
602 +#endif
603 +
604 +#define PREPL \
605 + Pjll = P_JLL(Pjp->jp_Addr); \
606 + PREPL_SETPOP1; \
607 + SETOFFSET(offset, Count0, pop1lower, Pjp)
608 +
609 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
610 + case cJU_JPLEAF1:
611 +
612 + PREPL_DCD(1);
613 + JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
614 + JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
615 +#endif
616 +
617 + case cJU_JPLEAF2:
618 +
619 + PREPL_DCD(2);
620 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
621 + | ((uint16_t *) Pjll)[offset];
622 + JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
623 +
624 +#ifndef JU_64BIT
625 + case cJU_JPLEAF3:
626 + {
627 + Word_t lsb;
628 + PREPL;
629 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
630 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
631 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
632 + }
633 +
634 +#else
635 + case cJU_JPLEAF3:
636 + {
637 + Word_t lsb;
638 + PREPL_DCD(3);
639 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
640 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
641 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
642 + }
643 +
644 + case cJU_JPLEAF4:
645 +
646 + PREPL_DCD(4);
647 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
648 + | ((uint32_t *) Pjll)[offset];
649 + JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
650 +
651 + case cJU_JPLEAF5:
652 + {
653 + Word_t lsb;
654 + PREPL_DCD(5);
655 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
656 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
657 + JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
658 + }
659 +
660 + case cJU_JPLEAF6:
661 + {
662 + Word_t lsb;
663 + PREPL_DCD(6);
664 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
665 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
666 + JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
667 + }
668 +
669 + case cJU_JPLEAF7:
670 + {
671 + Word_t lsb;
672 + PREPL;
673 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
674 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
675 + JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
676 + }
677 +#endif
678 +
679 +
680 +// ----------------------------------------------------------------------------
681 +// BITMAP LEAF:
682 +//
683 +// Return the Index at the proper ordinal (see SETOFFSET()) in the leaf by
684 +// counting bits. First copy Dcd bytes (always present since state 1 <
685 +// cJU_ROOTSTATE) to *PIndex.
686 +//
687 +// Note: The preceding branch traversal code MIGHT set pop1 for this expanse
688 +// (bitmap leaf) as a side-effect, but dont depend on that.
689 +
690 + case cJU_JPLEAF_B1:
691 + {
692 + Pjlb_t Pjlb;
693 +
694 + JU_SETDCD(*PIndex, Pjp, 1);
695 + Pjlb = P_JLB(Pjp->jp_Addr);
696 + pop1 = JU_JPLEAF_POP0(Pjp) + 1;
697 +
698 +// COUNT UPWARD, adding the pop1 of each subexpanse:
699 +//
700 +// The entire bitmap should fit in one cache line, but still try to save some
701 +// CPU time by counting the fewest possible number of subexpanses from the
702 +// bitmap.
703 +//
704 +// See header comments about limitations of this for Judy*ByCount().
705 +
706 +#ifndef NOSMARTJLB // enable to turn off smart code for comparison purposes.
707 +
708 + if (LOWERHALF(Count0, pop1lower, pop1))
709 + {
710 +#endif
711 +#ifdef SMARTMETRICS
712 + ++jlb_upward;
713 +#endif
714 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
715 + {
716 + pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
717 +
718 +// Warning: pop1lower and pop1 are unsigned, see earlier comment:
719 +
720 + if (pop1lower + pop1 > Count0)
721 + goto LeafB1; // Index is in this subexpanse.
722 +
723 + pop1lower += pop1; // add this subexpanses pop1.
724 + }
725 +#ifndef NOSMARTJLB // enable to turn off smart code for comparison purposes.
726 + }
727 +
728 +
729 +// COUNT DOWNWARD, subtracting each "above" subexpanses pop1 from the whole
730 +// expanses pop1:
731 +
732 + else
733 + {
734 +#ifdef SMARTMETRICS
735 + ++jlb_downward;
736 +#endif
737 + pop1lower += pop1; // add whole leaf to start.
738 +
739 + for (subexp = cJU_NUMSUBEXPL - 1; subexp >= 0; --subexp)
740 + {
741 + pop1lower -= j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
742 +
743 +// Beware unsigned math problems:
744 +
745 + if ((pop1lower == 0) || (pop1lower - 1 < Count0))
746 + goto LeafB1; // Index is in this subexpanse.
747 + }
748 + }
749 +#endif // NOSMARTJLB
750 +
751 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
752 + JUDY1CODE(return(JERRI );)
753 + JUDYLCODE(return(PPJERR);)
754 +
755 +
756 +// RETURN INDEX FOUND:
757 +//
758 +// Come here with subexp set to the correct subexpanse, and pop1lower set to
759 +// the sum for all lower expanses and subexpanses in the Judy tree. Calculate
760 +// and save in *PIndex the digit corresponding to the ordinal in this
761 +// subexpanse.
762 +
763 +LeafB1:
764 + SETOFFSET(offset, Count0, pop1lower, Pjp);
765 + JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
766 + JU_SETDIGIT1(*PIndex, digit);
767 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
768 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + offset))
769 +
770 + } // case cJU_JPLEAF_B1
771 +
772 +
773 +#ifdef JUDY1
774 +// ----------------------------------------------------------------------------
775 +// FULL POPULATION:
776 +//
777 +// Copy Dcd bytes (always present since state 1 < cJU_ROOTSTATE) to *PIndex,
778 +// then set the appropriate digit for the ordinal (see SETOFFSET()) in the leaf
779 +// as the LSB in *PIndex.
780 +
781 + case cJ1_JPFULLPOPU1:
782 +
783 + JU_SETDCD(*PIndex, Pjp, 1);
784 + SETOFFSET(offset, Count0, pop1lower, Pjp);
785 + assert(offset >= 0);
786 + assert(offset <= cJU_JPFULLPOPU1_POP0);
787 + JU_SETDIGIT1(*PIndex, offset);
788 + JU_RET_FOUND_FULLPOPU1;
789 +#endif
790 +
791 +
792 +// ----------------------------------------------------------------------------
793 +// IMMEDIATE:
794 +//
795 +// Locate the Index with the proper ordinal (see SETOFFSET()) in the Immediate,
796 +// depending on leaf Index Size and pop1. Note: There are no Dcd bytes in an
797 +// Immediate JP, but in a cJU_JPIMMED_*_01 JP, the field holds the least bytes
798 +// of the immediate Index.
799 +
800 +#define SET_01(cState) JU_SETDIGITS(*PIndex, JU_JPDCDPOP0(Pjp), cState)
801 +
802 + case cJU_JPIMMED_1_01: SET_01(1); goto Imm_01;
803 + case cJU_JPIMMED_2_01: SET_01(2); goto Imm_01;
804 + case cJU_JPIMMED_3_01: SET_01(3); goto Imm_01;
805 +#ifdef JU_64BIT
806 + case cJU_JPIMMED_4_01: SET_01(4); goto Imm_01;
807 + case cJU_JPIMMED_5_01: SET_01(5); goto Imm_01;
808 + case cJU_JPIMMED_6_01: SET_01(6); goto Imm_01;
809 + case cJU_JPIMMED_7_01: SET_01(7); goto Imm_01;
810 +#endif
811 +
812 +Imm_01:
813 +
814 + DBGCODE(SETOFFSET_IMM_CK(offset, Count0, pop1lower, 1);)
815 + JU_RET_FOUND_IMM_01(Pjp);
816 +
817 +// Shorthand for where to find start of Index bytes array:
818 +
819 +#ifdef JUDY1
820 +#define PJI (Pjp->jp_1Index)
821 +#else
822 +#define PJI (Pjp->jp_LIndex)
823 +#endif
824 +
825 +// Optional code to check the remaining ordinal (see SETOFFSET_IMM()) against
826 +// the Index Size of the Immediate:
827 +
828 +#ifndef DEBUG // simple placeholder:
829 +#define IMM(cPop1,Next) \
830 + goto Next
831 +#else // extra pop1-specific checking:
832 +#define IMM(cPop1,Next) \
833 + SETOFFSET_IMM_CK(offset, Count0, pop1lower, cPop1); \
834 + goto Next
835 +#endif
836 +
837 + case cJU_JPIMMED_1_02: IMM( 2, Imm1);
838 + case cJU_JPIMMED_1_03: IMM( 3, Imm1);
839 +#if (defined(JUDY1) || defined(JU_64BIT))
840 + case cJU_JPIMMED_1_04: IMM( 4, Imm1);
841 + case cJU_JPIMMED_1_05: IMM( 5, Imm1);
842 + case cJU_JPIMMED_1_06: IMM( 6, Imm1);
843 + case cJU_JPIMMED_1_07: IMM( 7, Imm1);
844 +#endif
845 +#if (defined(JUDY1) && defined(JU_64BIT))
846 + case cJ1_JPIMMED_1_08: IMM( 8, Imm1);
847 + case cJ1_JPIMMED_1_09: IMM( 9, Imm1);
848 + case cJ1_JPIMMED_1_10: IMM(10, Imm1);
849 + case cJ1_JPIMMED_1_11: IMM(11, Imm1);
850 + case cJ1_JPIMMED_1_12: IMM(12, Imm1);
851 + case cJ1_JPIMMED_1_13: IMM(13, Imm1);
852 + case cJ1_JPIMMED_1_14: IMM(14, Imm1);
853 + case cJ1_JPIMMED_1_15: IMM(15, Imm1);
854 +#endif
855 +
856 +Imm1: SETOFFSET_IMM(offset, Count0, pop1lower);
857 + JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
858 + JU_RET_FOUND_IMM(Pjp, offset);
859 +
860 +#if (defined(JUDY1) || defined(JU_64BIT))
861 + case cJU_JPIMMED_2_02: IMM(2, Imm2);
862 + case cJU_JPIMMED_2_03: IMM(3, Imm2);
863 +#endif
864 +#if (defined(JUDY1) && defined(JU_64BIT))
865 + case cJ1_JPIMMED_2_04: IMM(4, Imm2);
866 + case cJ1_JPIMMED_2_05: IMM(5, Imm2);
867 + case cJ1_JPIMMED_2_06: IMM(6, Imm2);
868 + case cJ1_JPIMMED_2_07: IMM(7, Imm2);
869 +#endif
870 +
871 +#if (defined(JUDY1) || defined(JU_64BIT))
872 +Imm2: SETOFFSET_IMM(offset, Count0, pop1lower);
873 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
874 + | ((uint16_t *) PJI)[offset];
875 + JU_RET_FOUND_IMM(Pjp, offset);
876 +#endif
877 +
878 +#if (defined(JUDY1) || defined(JU_64BIT))
879 + case cJU_JPIMMED_3_02: IMM(2, Imm3);
880 +#endif
881 +#if (defined(JUDY1) && defined(JU_64BIT))
882 + case cJ1_JPIMMED_3_03: IMM(3, Imm3);
883 + case cJ1_JPIMMED_3_04: IMM(4, Imm3);
884 + case cJ1_JPIMMED_3_05: IMM(5, Imm3);
885 +#endif
886 +
887 +#if (defined(JUDY1) || defined(JU_64BIT))
888 +Imm3:
889 + {
890 + Word_t lsb;
891 + SETOFFSET_IMM(offset, Count0, pop1lower);
892 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
893 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
894 + JU_RET_FOUND_IMM(Pjp, offset);
895 + }
896 +#endif
897 +
898 +#if (defined(JUDY1) && defined(JU_64BIT))
899 + case cJ1_JPIMMED_4_02: IMM(2, Imm4);
900 + case cJ1_JPIMMED_4_03: IMM(3, Imm4);
901 +
902 +Imm4: SETOFFSET_IMM(offset, Count0, pop1lower);
903 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
904 + | ((uint32_t *) PJI)[offset];
905 + JU_RET_FOUND_IMM(Pjp, offset);
906 +
907 + case cJ1_JPIMMED_5_02: IMM(2, Imm5);
908 + case cJ1_JPIMMED_5_03: IMM(3, Imm5);
909 +
910 +Imm5:
911 + {
912 + Word_t lsb;
913 + SETOFFSET_IMM(offset, Count0, pop1lower);
914 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
915 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
916 + JU_RET_FOUND_IMM(Pjp, offset);
917 + }
918 +
919 + case cJ1_JPIMMED_6_02: IMM(2, Imm6);
920 +
921 +Imm6:
922 + {
923 + Word_t lsb;
924 + SETOFFSET_IMM(offset, Count0, pop1lower);
925 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
926 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
927 + JU_RET_FOUND_IMM(Pjp, offset);
928 + }
929 +
930 + case cJ1_JPIMMED_7_02: IMM(2, Imm7);
931 +
932 +Imm7:
933 + {
934 + Word_t lsb;
935 + SETOFFSET_IMM(offset, Count0, pop1lower);
936 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
937 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
938 + JU_RET_FOUND_IMM(Pjp, offset);
939 + }
940 +#endif // (JUDY1 && JU_64BIT)
941 +
942 +
943 +// ----------------------------------------------------------------------------
944 +// UNEXPECTED JP TYPES:
945 +
946 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
947 + JUDY1CODE(return(JERRI );)
948 + JUDYLCODE(return(PPJERR);)
949 +
950 + } // SMByCount switch.
951 +
952 + /*NOTREACHED*/
953 +
954 +} // Judy1ByCount() / JudyLByCount()
libnetdata/libjudy/src/JudyL/JudyLCascade.c new
+1942
@@ -0,0 +1,1942 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.38 $ $Source: /judy/src/JudyCommon/JudyCascade.c $
19 +
20 +#ifdef JUDY1
21 +#include "Judy1.h"
22 +#else
23 +#include "JudyL.h"
24 +#endif
25 +
26 +#include "JudyPrivate1L.h"
27 +
28 +extern int j__udyCreateBranchL(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
29 +extern int j__udyCreateBranchB(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
30 +
31 +DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)
32 +
33 +static const jbb_t StageJBBZero; // zeroed versions of namesake struct.
34 +
35 +// TBD: There are multiple copies of (some of) these CopyWto3, Copy3toW,
36 +// CopyWto7 and Copy7toW functions in Judy1Cascade.c, JudyLCascade.c, and
37 +// JudyDecascade.c. These static functions should probably be moved to a
38 +// common place, made macros, or something to avoid having four copies.
39 +
40 +
41 +// ****************************************************************************
42 +// __ J U D Y C O P Y X T O W
43 +
44 +
45 +FUNCTION static void j__udyCopy3toW(
46 + PWord_t PDest,
47 + uint8_t * PSrc,
48 + Word_t LeafIndexes)
49 +{
50 + do
51 + {
52 + JU_COPY3_PINDEX_TO_LONG(*PDest, PSrc);
53 + PSrc += 3;
54 + PDest += 1;
55 +
56 + } while(--LeafIndexes);
57 +
58 +} //j__udyCopy3toW()
59 +
60 +
61 +#ifdef JU_64BIT
62 +
63 +FUNCTION static void j__udyCopy4toW(
64 + PWord_t PDest,
65 + uint32_t * PSrc,
66 + Word_t LeafIndexes)
67 +{
68 + do { *PDest++ = *PSrc++;
69 + } while(--LeafIndexes);
70 +
71 +} // j__udyCopy4toW()
72 +
73 +
74 +FUNCTION static void j__udyCopy5toW(
75 + PWord_t PDest,
76 + uint8_t * PSrc,
77 + Word_t LeafIndexes)
78 +{
79 + do
80 + {
81 + JU_COPY5_PINDEX_TO_LONG(*PDest, PSrc);
82 + PSrc += 5;
83 + PDest += 1;
84 +
85 + } while(--LeafIndexes);
86 +
87 +} // j__udyCopy5toW()
88 +
89 +
90 +FUNCTION static void j__udyCopy6toW(
91 + PWord_t PDest,
92 + uint8_t * PSrc,
93 + Word_t LeafIndexes)
94 +{
95 + do
96 + {
97 + JU_COPY6_PINDEX_TO_LONG(*PDest, PSrc);
98 + PSrc += 6;
99 + PDest += 1;
100 +
101 + } while(--LeafIndexes);
102 +
103 +} // j__udyCopy6toW()
104 +
105 +
106 +FUNCTION static void j__udyCopy7toW(
107 + PWord_t PDest,
108 + uint8_t * PSrc,
109 + Word_t LeafIndexes)
110 +{
111 + do
112 + {
113 + JU_COPY7_PINDEX_TO_LONG(*PDest, PSrc);
114 + PSrc += 7;
115 + PDest += 1;
116 +
117 + } while(--LeafIndexes);
118 +
119 +} // j__udyCopy7toW()
120 +
121 +#endif // JU_64BIT
122 +
123 +
124 +// ****************************************************************************
125 +// __ J U D Y C O P Y W T O X
126 +
127 +
128 +FUNCTION static void j__udyCopyWto3(
129 + uint8_t * PDest,
130 + PWord_t PSrc,
131 + Word_t LeafIndexes)
132 +{
133 + do
134 + {
135 + JU_COPY3_LONG_TO_PINDEX(PDest, *PSrc);
136 + PSrc += 1;
137 + PDest += 3;
138 +
139 + } while(--LeafIndexes);
140 +
141 +} // j__udyCopyWto3()
142 +
143 +
144 +#ifdef JU_64BIT
145 +
146 +FUNCTION static void j__udyCopyWto4(
147 + uint8_t * PDest,
148 + PWord_t PSrc,
149 + Word_t LeafIndexes)
150 +{
151 + uint32_t *PDest32 = (uint32_t *)PDest;
152 +
153 + do
154 + {
155 + *PDest32 = *PSrc;
156 + PSrc += 1;
157 + PDest32 += 1;
158 + } while(--LeafIndexes);
159 +
160 +} // j__udyCopyWto4()
161 +
162 +
163 +FUNCTION static void j__udyCopyWto5(
164 + uint8_t * PDest,
165 + PWord_t PSrc,
166 + Word_t LeafIndexes)
167 +{
168 + do
169 + {
170 + JU_COPY5_LONG_TO_PINDEX(PDest, *PSrc);
171 + PSrc += 1;
172 + PDest += 5;
173 +
174 + } while(--LeafIndexes);
175 +
176 +} // j__udyCopyWto5()
177 +
178 +
179 +FUNCTION static void j__udyCopyWto6(
180 + uint8_t * PDest,
181 + PWord_t PSrc,
182 + Word_t LeafIndexes)
183 +{
184 + do
185 + {
186 + JU_COPY6_LONG_TO_PINDEX(PDest, *PSrc);
187 + PSrc += 1;
188 + PDest += 6;
189 +
190 + } while(--LeafIndexes);
191 +
192 +} // j__udyCopyWto6()
193 +
194 +
195 +FUNCTION static void j__udyCopyWto7(
196 + uint8_t * PDest,
197 + PWord_t PSrc,
198 + Word_t LeafIndexes)
199 +{
200 + do
201 + {
202 + JU_COPY7_LONG_TO_PINDEX(PDest, *PSrc);
203 + PSrc += 1;
204 + PDest += 7;
205 +
206 + } while(--LeafIndexes);
207 +
208 +} // j__udyCopyWto7()
209 +
210 +#endif // JU_64BIT
211 +
212 +
213 +// ****************************************************************************
214 +// COMMON CODE (MACROS):
215 +//
216 +// Free objects in an array of valid JPs, StageJP[ExpCnt] == last one may
217 +// include Immeds, which are ignored.
218 +
219 +#define FREEALLEXIT(ExpCnt,StageJP,Pjpm) \
220 + { \
221 + Word_t _expct = (ExpCnt); \
222 + while (_expct--) j__udyFreeSM(&((StageJP)[_expct]), Pjpm); \
223 + return(-1); \
224 + }
225 +
226 +// Clear the array that keeps track of the number of JPs in a subexpanse:
227 +
228 +#define ZEROJP(SubJPCount) \
229 + { \
230 + int ii; \
231 + for (ii = 0; ii < cJU_NUMSUBEXPB; ii++) (SubJPCount[ii]) = 0; \
232 + }
233 +
234 +// ****************************************************************************
235 +// __ J U D Y S T A G E J B B T O J B B
236 +//
237 +// Create a mallocd BranchB (jbb_t) from a staged BranchB while "splaying" a
238 +// single old leaf. Return -1 if out of memory, otherwise 1.
239 +
240 +static int j__udyStageJBBtoJBB(
241 + Pjp_t PjpLeaf, // JP of leaf being splayed.
242 + Pjbb_t PStageJBB, // temp jbb_t on stack.
243 + Pjp_t PjpArray, // array of JPs to splayed new leaves.
244 + uint8_t * PSubCount, // count of JPs for each subexpanse.
245 + Pjpm_t Pjpm) // the jpm_t for JudyAlloc*().
246 +{
247 + Pjbb_t PjbbRaw; // pointer to new bitmap branch.
248 + Pjbb_t Pjbb;
249 + Word_t subexp;
250 +
251 +// Get memory for new BranchB:
252 +
253 + if ((PjbbRaw = j__udyAllocJBB(Pjpm)) == (Pjbb_t) NULL) return(-1);
254 + Pjbb = P_JBB(PjbbRaw);
255 +
256 +// Copy staged BranchB into just-allocated BranchB:
257 +
258 + *Pjbb = *PStageJBB;
259 +
260 +// Allocate the JP subarrays (BJP) for the new BranchB:
261 +
262 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; subexp++)
263 + {
264 + Pjp_t PjpRaw;
265 + Pjp_t Pjp;
266 + Word_t NumJP; // number of JPs in each subexpanse.
267 +
268 + if ((NumJP = PSubCount[subexp]) == 0) continue; // empty.
269 +
270 +// Out of memory, back out previous allocations:
271 +
272 + if ((PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm)) == (Pjp_t) NULL)
273 + {
274 + while(subexp--)
275 + {
276 + if ((NumJP = PSubCount[subexp]) == 0) continue;
277 +
278 + PjpRaw = JU_JBB_PJP(Pjbb, subexp);
279 + j__udyFreeJBBJP(PjpRaw, NumJP, Pjpm);
280 + }
281 + j__udyFreeJBB(PjbbRaw, Pjpm);
282 + return(-1); // out of memory.
283 + }
284 + Pjp = P_JP(PjpRaw);
285 +
286 +// Place the JP subarray pointer in the new BranchB, copy subarray JPs, and
287 +// advance to the next subexpanse:
288 +
289 + JU_JBB_PJP(Pjbb, subexp) = PjpRaw;
290 + JU_COPYMEM(Pjp, PjpArray, NumJP);
291 + PjpArray += NumJP;
292 +
293 + } // for each subexpanse.
294 +
295 +// Change the PjpLeaf from Leaf to BranchB:
296 +
297 + PjpLeaf->jp_Addr = (Word_t) PjbbRaw;
298 + PjpLeaf->jp_Type += cJU_JPBRANCH_B2 - cJU_JPLEAF2; // Leaf to BranchB.
299 +
300 + return(1);
301 +
302 +} // j__udyStageJBBtoJBB()
303 +
304 +
305 +// ****************************************************************************
306 +// __ J U D Y J L L 2 T O J L B 1
307 +//
308 +// Create a LeafB1 (jlb_t = JLB1) from a Leaf2 (2-byte Indexes and for JudyL,
309 +// Word_t Values). Return NULL if out of memory, else a pointer to the new
310 +// LeafB1.
311 +//
312 +// NOTE: Caller must release the Leaf2 that was passed in.
313 +
314 +FUNCTION static Pjlb_t j__udyJLL2toJLB1(
315 + uint16_t * Pjll, // array of 16-bit indexes.
316 +#ifdef JUDYL
317 + Pjv_t Pjv, // array of associated values.
318 +#endif
319 + Word_t LeafPop1, // number of indexes/values.
320 + Pvoid_t Pjpm) // jpm_t for JudyAlloc*()/JudyFree*().
321 +{
322 + Pjlb_t PjlbRaw;
323 + Pjlb_t Pjlb;
324 + int offset;
325 +JUDYLCODE(int subexp;)
326 +
327 +// Allocate the LeafB1:
328 +
329 + if ((PjlbRaw = j__udyAllocJLB1(Pjpm)) == (Pjlb_t) NULL)
330 + return((Pjlb_t) NULL);
331 + Pjlb = P_JLB(PjlbRaw);
332 +
333 +// Copy Leaf2 indexes to LeafB1:
334 +
335 + for (offset = 0; offset < LeafPop1; ++offset)
336 + JU_BITMAPSETL(Pjlb, Pjll[offset]);
337 +
338 +#ifdef JUDYL
339 +
340 +// Build LeafVs from bitmap:
341 +
342 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
343 + {
344 + struct _POINTER_VALUES
345 + {
346 + Word_t pv_Pop1; // size of value area.
347 + Pjv_t pv_Pjv; // raw pointer to value area.
348 + } pv[cJU_NUMSUBEXPL];
349 +
350 +// Get the population of the subexpanse, and if any, allocate a LeafV:
351 +
352 + pv[subexp].pv_Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
353 +
354 + if (pv[subexp].pv_Pop1)
355 + {
356 + Pjv_t Pjvnew;
357 +
358 +// TBD: There is an opportunity to put pop == 1 value in pointer:
359 +
360 + pv[subexp].pv_Pjv = j__udyLAllocJV(pv[subexp].pv_Pop1, Pjpm);
361 +
362 +// Upon out of memory, free all previously allocated:
363 +
364 + if (pv[subexp].pv_Pjv == (Pjv_t) NULL)
365 + {
366 + while(subexp--)
367 + {
368 + if (pv[subexp].pv_Pop1)
369 + {
370 + j__udyLFreeJV(pv[subexp].pv_Pjv, pv[subexp].pv_Pop1,
371 + Pjpm);
372 + }
373 + }
374 + j__udyFreeJLB1(PjlbRaw, Pjpm);
375 + return((Pjlb_t) NULL);
376 + }
377 +
378 + Pjvnew = P_JV(pv[subexp].pv_Pjv);
379 + JU_COPYMEM(Pjvnew, Pjv, pv[subexp].pv_Pop1);
380 + Pjv += pv[subexp].pv_Pop1; // advance value pointer.
381 +
382 +// Place raw pointer to value array in bitmap subexpanse:
383 +
384 + JL_JLB_PVALUE(Pjlb, subexp) = pv[subexp].pv_Pjv;
385 +
386 + } // populated subexpanse.
387 + } // each subexpanse.
388 +
389 +#endif // JUDYL
390 +
391 + return(PjlbRaw); // pointer to LeafB1.
392 +
393 +} // j__udyJLL2toJLB1()
394 +
395 +
396 +// ****************************************************************************
397 +// __ J U D Y C A S C A D E 1
398 +//
399 +// Create bitmap leaf from 1-byte Indexes and Word_t Values.
400 +//
401 +// TBD: There must be a better way.
402 +//
403 +// Only for JudyL 32 bit: (note, unifdef disallows comment on next line)
404 +
405 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
406 +
407 +FUNCTION int j__udyCascade1(
408 + Pjp_t Pjp,
409 + Pvoid_t Pjpm)
410 +{
411 + Word_t DcdP0;
412 + uint8_t * PLeaf;
413 + Pjlb_t PjlbRaw;
414 + Pjlb_t Pjlb;
415 + Word_t Pop1;
416 + Word_t ii; // temp for loop counter
417 +JUDYLCODE(Pjv_t Pjv;)
418 +
419 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF1);
420 + assert((JU_JPDCDPOP0(Pjp) & 0xFF) == (cJU_LEAF1_MAXPOP1-1));
421 +
422 + PjlbRaw = j__udyAllocJLB1(Pjpm);
423 + if (PjlbRaw == (Pjlb_t) NULL) return(-1);
424 +
425 + Pjlb = P_JLB(PjlbRaw);
426 + PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
427 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
428 +
429 + JUDYLCODE(Pjv = JL_LEAF1VALUEAREA(PLeaf, Pop1);)
430 +
431 +// Copy 1 byte index Leaf to bitmap Leaf
432 + for (ii = 0; ii < Pop1; ii++) JU_BITMAPSETL(Pjlb, PLeaf[ii]);
433 +
434 +#ifdef JUDYL
435 +// Build 8 subexpanse Value leaves from bitmap
436 + for (ii = 0; ii < cJU_NUMSUBEXPL; ii++)
437 + {
438 +// Get number of Indexes in subexpanse
439 + if ((Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, ii))))
440 + {
441 + Pjv_t PjvnewRaw; // value area of new leaf.
442 + Pjv_t Pjvnew;
443 +
444 + PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
445 + if (PjvnewRaw == (Pjv_t) NULL) // out of memory.
446 + {
447 +// Free prevously allocated LeafVs:
448 + while(ii--)
449 + {
450 + if ((Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, ii))))
451 + {
452 + PjvnewRaw = JL_JLB_PVALUE(Pjlb, ii);
453 + j__udyLFreeJV(PjvnewRaw, Pop1, Pjpm);
454 + }
455 + }
456 +// Free the bitmap leaf
457 + j__udyLFreeJLB1(PjlbRaw,Pjpm);
458 + return(-1);
459 + }
460 + Pjvnew = P_JV(PjvnewRaw);
461 + JU_COPYMEM(Pjvnew, Pjv, Pop1);
462 +
463 + Pjv += Pop1;
464 + JL_JLB_PVALUE(Pjlb, ii) = PjvnewRaw;
465 + }
466 + }
467 +#endif // JUDYL
468 +
469 + DcdP0 = JU_JPDCDPOP0(Pjp) | (PLeaf[0] & cJU_DCDMASK(1));
470 + JU_JPSETADT(Pjp, (Word_t)PjlbRaw, DcdP0, cJU_JPLEAF_B1);
471 +
472 + return(1); // return success
473 +
474 +} // j__udyCascade1()
475 +
476 +#endif // (!(JUDY1 && JU_64BIT))
477 +
478 +
479 +// ****************************************************************************
480 +// __ J U D Y C A S C A D E 2
481 +//
482 +// Entry PLeaf of size LeafPop1 is either compressed or splayed with pointer
483 +// returned in Pjp. Entry Levels sizeof(Word_t) down to level 2.
484 +//
485 +// Splay or compress the 2-byte Index Leaf that Pjp point to. Return *Pjp as a
486 +// (compressed) cJU_LEAFB1 or a cJU_BRANCH_*2
487 +
488 +FUNCTION int j__udyCascade2(
489 + Pjp_t Pjp,
490 + Pvoid_t Pjpm)
491 +{
492 + uint16_t * PLeaf; // pointer to leaf, explicit type.
493 + Word_t End, Start; // temporaries.
494 + Word_t ExpCnt; // count of expanses of splay.
495 + Word_t CIndex; // current Index word.
496 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
497 +
498 +// Temp staging for parts(Leaves) of newly splayed leaf
499 + jp_t StageJP [cJU_LEAF2_MAXPOP1]; // JPs of new leaves
500 + uint8_t StageExp [cJU_LEAF2_MAXPOP1]; // Expanses of new leaves
501 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
502 + jbb_t StageJBB; // staged bitmap branch
503 +
504 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF2);
505 + assert((JU_JPDCDPOP0(Pjp) & 0xFFFF) == (cJU_LEAF2_MAXPOP1-1));
506 +
507 +// Get the address of the Leaf
508 + PLeaf = (uint16_t *) P_JLL(Pjp->jp_Addr);
509 +
510 +// And its Value area
511 + JUDYLCODE(Pjv = JL_LEAF2VALUEAREA(PLeaf, cJU_LEAF2_MAXPOP1);)
512 +
513 +// If Leaf is in 1 expanse -- just compress it to a Bitmap Leaf
514 +
515 + CIndex = PLeaf[0];
516 + if (!JU_DIGITATSTATE(CIndex ^ PLeaf[cJU_LEAF2_MAXPOP1-1], 2))
517 + {
518 +// cJU_JPLEAF_B1
519 + Word_t DcdP0;
520 + Pjlb_t PjlbRaw;
521 + PjlbRaw = j__udyJLL2toJLB1(PLeaf,
522 +#ifdef JUDYL
523 + Pjv,
524 +#endif
525 + cJU_LEAF2_MAXPOP1, Pjpm);
526 + if (PjlbRaw == (Pjlb_t)NULL) return(-1); // out of memory
527 +
528 +// Merge in another Dcd byte because compressing
529 + DcdP0 = (CIndex & cJU_DCDMASK(1)) | JU_JPDCDPOP0(Pjp);
530 + JU_JPSETADT(Pjp, (Word_t)PjlbRaw, DcdP0, cJU_JPLEAF_B1);
531 +
532 + return(1);
533 + }
534 +
535 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
536 +
537 + StageJBB = StageJBBZero; // zero staged bitmap branch
538 + ZEROJP(SubJPCount);
539 +
540 +// Splay the 2 byte index Leaf to 1 byte Index Leaves
541 + for (ExpCnt = Start = 0, End = 1; ; End++)
542 + {
543 +// Check if new expanse or last one
544 + if ( (End == cJU_LEAF2_MAXPOP1)
545 + ||
546 + (JU_DIGITATSTATE(CIndex ^ PLeaf[End], 2))
547 + )
548 + {
549 +// Build a leaf below the previous expanse
550 +//
551 + Pjp_t PjpJP = StageJP + ExpCnt;
552 + Word_t Pop1 = End - Start;
553 + Word_t expanse = JU_DIGITATSTATE(CIndex, 2);
554 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
555 +//
556 +// set the bit that is the current expanse
557 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
558 +#ifdef SUBEXPCOUNTS
559 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
560 +#endif
561 +// count number of expanses in each subexpanse
562 + SubJPCount[subexp]++;
563 +
564 +// Save byte expanse of leaf
565 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 2);
566 +
567 + if (Pop1 == 1) // cJU_JPIMMED_1_01
568 + {
569 + Word_t DcdP0;
570 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(1)) |
571 + CIndex;
572 +#ifdef JUDY1
573 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_1_01);
574 +#else // JUDYL
575 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
576 + cJL_JPIMMED_1_01);
577 +#endif // JUDYL
578 + }
579 + else if (Pop1 <= cJU_IMMED1_MAXPOP1) // bigger
580 + {
581 +// cJL_JPIMMED_1_02..3: JudyL 32
582 +// cJ1_JPIMMED_1_02..7: Judy1 32
583 +// cJL_JPIMMED_1_02..7: JudyL 64
584 +// cJ1_JPIMMED_1_02..15: Judy1 64
585 +#ifdef JUDYL
586 + Pjv_t PjvnewRaw; // value area of leaf.
587 + Pjv_t Pjvnew;
588 +
589 +// Allocate Value area for Immediate Leaf
590 + PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
591 + if (PjvnewRaw == (Pjv_t) NULL)
592 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
593 +
594 + Pjvnew = P_JV(PjvnewRaw);
595 +
596 +// Copy to Values to Value Leaf
597 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
598 + PjpJP->jp_Addr = (Word_t) PjvnewRaw;
599 +
600 +// Copy to JP as an immediate Leaf
601 + JU_COPYMEM(PjpJP->jp_LIndex, PLeaf + Start,
602 + Pop1);
603 +#else
604 + JU_COPYMEM(PjpJP->jp_1Index, PLeaf + Start,
605 + Pop1);
606 +#endif
607 +// Set Type, Population and Index size
608 + PjpJP->jp_Type = cJU_JPIMMED_1_02 + Pop1 - 2;
609 + }
610 +
611 +// 64Bit Judy1 does not have Leaf1: (note, unifdef disallows comment on next
612 +// line)
613 +
614 +#if (! (defined(JUDY1) && defined(JU_64BIT)))
615 + else if (Pop1 <= cJU_LEAF1_MAXPOP1) // still bigger
616 + {
617 +// cJU_JPLEAF1
618 + Word_t DcdP0;
619 + Pjll_t PjllRaw; // pointer to new leaf.
620 + Pjll_t Pjll;
621 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
622 +
623 +// Get a new Leaf
624 + PjllRaw = j__udyAllocJLL1(Pop1, Pjpm);
625 + if (PjllRaw == (Pjll_t)NULL)
626 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
627 +
628 + Pjll = P_JLL(PjllRaw);
629 +#ifdef JUDYL
630 +// Copy to Values to new Leaf
631 + Pjvnew = JL_LEAF1VALUEAREA(Pjll, Pop1);
632 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
633 +#endif
634 +// Copy Indexes to new Leaf
635 + JU_COPYMEM((uint8_t *)Pjll, PLeaf+Start, Pop1);
636 +
637 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 1);)
638 +
639 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2))
640 + |
641 + (CIndex & cJU_DCDMASK(2-1))
642 + |
643 + (Pop1 - 1);
644 +
645 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
646 + cJU_JPLEAF1);
647 + }
648 +#endif // (!(JUDY1 && JU_64BIT)) // Not 64Bit Judy1
649 +
650 + else // biggest
651 + {
652 +// cJU_JPLEAF_B1
653 + Word_t DcdP0;
654 + Pjlb_t PjlbRaw;
655 + PjlbRaw = j__udyJLL2toJLB1(
656 + PLeaf + Start,
657 +#ifdef JUDYL
658 + Pjv + Start,
659 +#endif
660 + Pop1, Pjpm);
661 + if (PjlbRaw == (Pjlb_t)NULL)
662 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
663 +
664 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2))
665 + |
666 + (CIndex & cJU_DCDMASK(2-1))
667 + |
668 + (Pop1 - 1);
669 +
670 + JU_JPSETADT(PjpJP, (Word_t)PjlbRaw, DcdP0,
671 + cJU_JPLEAF_B1);
672 + }
673 + ExpCnt++;
674 +// Done?
675 + if (End == cJU_LEAF2_MAXPOP1) break;
676 +
677 +// New Expanse, Start and Count
678 + CIndex = PLeaf[End];
679 + Start = End;
680 + }
681 + }
682 +
683 +// Now put all the Leaves below a BranchL or BranchB:
684 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
685 + {
686 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
687 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
688 +
689 + Pjp->jp_Type = cJU_JPBRANCH_L2;
690 + }
691 + else
692 + {
693 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
694 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
695 + }
696 + return(1);
697 +
698 +} // j__udyCascade2()
699 +
700 +
701 +// ****************************************************************************
702 +// __ J U D Y C A S C A D E 3
703 +//
704 +// Return *Pjp as a (compressed) cJU_LEAF2, cJU_BRANCH_L3, cJU_BRANCH_B3.
705 +
706 +FUNCTION int j__udyCascade3(
707 + Pjp_t Pjp,
708 + Pvoid_t Pjpm)
709 +{
710 + uint8_t * PLeaf; // pointer to leaf, explicit type.
711 + Word_t End, Start; // temporaries.
712 + Word_t ExpCnt; // count of expanses of splay.
713 + Word_t CIndex; // current Index word.
714 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
715 +
716 +// Temp staging for parts(Leaves) of newly splayed leaf
717 + jp_t StageJP [cJU_LEAF3_MAXPOP1]; // JPs of new leaves
718 + Word_t StageA [cJU_LEAF3_MAXPOP1];
719 + uint8_t StageExp [cJU_LEAF3_MAXPOP1]; // Expanses of new leaves
720 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
721 + jbb_t StageJBB; // staged bitmap branch
722 +
723 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF3);
724 + assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFF) == (cJU_LEAF3_MAXPOP1-1));
725 +
726 +// Get the address of the Leaf
727 + PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
728 +
729 +// Extract leaf to Word_t and insert-sort Index into it
730 + j__udyCopy3toW(StageA, PLeaf, cJU_LEAF3_MAXPOP1);
731 +
732 +// Get the address of the Leaf and Value area
733 + JUDYLCODE(Pjv = JL_LEAF3VALUEAREA(PLeaf, cJU_LEAF3_MAXPOP1);)
734 +
735 +// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
736 +
737 + CIndex = StageA[0];
738 + if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF3_MAXPOP1-1], 3))
739 + {
740 + Word_t DcdP0;
741 + Pjll_t PjllRaw; // pointer to new leaf.
742 + Pjll_t Pjll;
743 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
744 +
745 +// Alloc a 2 byte Index Leaf
746 + PjllRaw = j__udyAllocJLL2(cJU_LEAF3_MAXPOP1, Pjpm);
747 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
748 +
749 + Pjll = P_JLL(PjllRaw);
750 +
751 +// Copy just 2 bytes Indexes to new Leaf
752 +// j__udyCopyWto2((uint16_t *) Pjll, StageA, cJU_LEAF3_MAXPOP1);
753 + JU_COPYMEM ((uint16_t *) Pjll, StageA, cJU_LEAF3_MAXPOP1);
754 +#ifdef JUDYL
755 +// Copy Value area into new Leaf
756 + Pjvnew = JL_LEAF2VALUEAREA(Pjll, cJU_LEAF3_MAXPOP1);
757 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF3_MAXPOP1);
758 +#endif
759 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF3_MAXPOP1, 2);)
760 +
761 +// Form new JP, Pop0 field is unchanged
762 +// Add in another Dcd byte because compressing
763 + DcdP0 = (CIndex & cJU_DCDMASK(2)) | JU_JPDCDPOP0(Pjp);
764 +
765 + JU_JPSETADT(Pjp, (Word_t) PjllRaw, DcdP0, cJU_JPLEAF2);
766 +
767 + return(1); // Success
768 + }
769 +
770 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
771 +
772 + StageJBB = StageJBBZero; // zero staged bitmap branch
773 + ZEROJP(SubJPCount);
774 +
775 +// Splay the 3 byte index Leaf to 2 byte Index Leaves
776 + for (ExpCnt = Start = 0, End = 1; ; End++)
777 + {
778 +// Check if new expanse or last one
779 + if ( (End == cJU_LEAF3_MAXPOP1)
780 + ||
781 + (JU_DIGITATSTATE(CIndex ^ StageA[End], 3))
782 + )
783 + {
784 +// Build a leaf below the previous expanse
785 +
786 + Pjp_t PjpJP = StageJP + ExpCnt;
787 + Word_t Pop1 = End - Start;
788 + Word_t expanse = JU_DIGITATSTATE(CIndex, 3);
789 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
790 +//
791 +// set the bit that is the current expanse
792 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
793 +#ifdef SUBEXPCOUNTS
794 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
795 +#endif
796 +// count number of expanses in each subexpanse
797 + SubJPCount[subexp]++;
798 +
799 +// Save byte expanse of leaf
800 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 3);
801 +
802 + if (Pop1 == 1) // cJU_JPIMMED_2_01
803 + {
804 + Word_t DcdP0;
805 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(2)) |
806 + CIndex;
807 +#ifdef JUDY1
808 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_2_01);
809 +#else // JUDYL
810 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
811 + cJL_JPIMMED_2_01);
812 +#endif // JUDYL
813 + }
814 +#if (defined(JUDY1) || defined(JU_64BIT))
815 + else if (Pop1 <= cJU_IMMED2_MAXPOP1)
816 + {
817 +// cJ1_JPIMMED_2_02..3: Judy1 32
818 +// cJL_JPIMMED_2_02..3: JudyL 64
819 +// cJ1_JPIMMED_2_02..7: Judy1 64
820 +#ifdef JUDYL
821 +// Alloc is 1st in case of malloc fail
822 + Pjv_t PjvnewRaw; // value area of new leaf.
823 + Pjv_t Pjvnew;
824 +
825 +// Allocate Value area for Immediate Leaf
826 + PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
827 + if (PjvnewRaw == (Pjv_t) NULL)
828 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
829 +
830 + Pjvnew = P_JV(PjvnewRaw);
831 +
832 +// Copy to Values to Value Leaf
833 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
834 +
835 + PjpJP->jp_Addr = (Word_t) PjvnewRaw;
836 +
837 +// Copy to Index to JP as an immediate Leaf
838 + JU_COPYMEM((uint16_t *) (PjpJP->jp_LIndex),
839 + StageA + Start, Pop1);
840 +#else // JUDY1
841 + JU_COPYMEM((uint16_t *) (PjpJP->jp_1Index),
842 + StageA + Start, Pop1);
843 +#endif // JUDY1
844 +// Set Type, Population and Index size
845 + PjpJP->jp_Type = cJU_JPIMMED_2_02 + Pop1 - 2;
846 + }
847 +#endif // (JUDY1 || JU_64BIT)
848 +
849 + else // Make a linear leaf2
850 + {
851 +// cJU_JPLEAF2
852 + Word_t DcdP0;
853 + Pjll_t PjllRaw; // pointer to new leaf.
854 + Pjll_t Pjll;
855 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
856 +
857 + PjllRaw = j__udyAllocJLL2(Pop1, Pjpm);
858 + if (PjllRaw == (Pjll_t) NULL)
859 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
860 +
861 + Pjll = P_JLL(PjllRaw);
862 +#ifdef JUDYL
863 +// Copy to Values to new Leaf
864 + Pjvnew = JL_LEAF2VALUEAREA(Pjll, Pop1);
865 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
866 +#endif
867 +// Copy least 2 bytes per Index of Leaf to new Leaf
868 + JU_COPYMEM((uint16_t *) Pjll, StageA+Start,
869 + Pop1);
870 +
871 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 2);)
872 +
873 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(3))
874 + |
875 + (CIndex & cJU_DCDMASK(3-1))
876 + |
877 + (Pop1 - 1);
878 +
879 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
880 + cJU_JPLEAF2);
881 + }
882 + ExpCnt++;
883 +// Done?
884 + if (End == cJU_LEAF3_MAXPOP1) break;
885 +
886 +// New Expanse, Start and Count
887 + CIndex = StageA[End];
888 + Start = End;
889 + }
890 + }
891 +
892 +// Now put all the Leaves below a BranchL or BranchB:
893 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
894 + {
895 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
896 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
897 +
898 + Pjp->jp_Type = cJU_JPBRANCH_L3;
899 + }
900 + else
901 + {
902 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
903 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
904 + }
905 + return(1);
906 +
907 +} // j__udyCascade3()
908 +
909 +
910 +#ifdef JU_64BIT // JudyCascade[4567]
911 +
912 +// ****************************************************************************
913 +// __ J U D Y C A S C A D E 4
914 +//
915 +// Cascade from a cJU_JPLEAF4 to one of the following:
916 +// 1. if leaf is in 1 expanse:
917 +// compress it into a JPLEAF3
918 +// 2. if leaf contains multiple expanses:
919 +// create linear or bitmap branch containing
920 +// each new expanse is either a:
921 +// JPIMMED_3_01 branch
922 +// JPIMMED_3_02 branch
923 +// JPLEAF3
924 +
925 +FUNCTION int j__udyCascade4(
926 + Pjp_t Pjp,
927 + Pvoid_t Pjpm)
928 +{
929 + uint32_t * PLeaf; // pointer to leaf, explicit type.
930 + Word_t End, Start; // temporaries.
931 + Word_t ExpCnt; // count of expanses of splay.
932 + Word_t CIndex; // current Index word.
933 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
934 +
935 +// Temp staging for parts(Leaves) of newly splayed leaf
936 + jp_t StageJP [cJU_LEAF4_MAXPOP1]; // JPs of new leaves
937 + Word_t StageA [cJU_LEAF4_MAXPOP1];
938 + uint8_t StageExp [cJU_LEAF4_MAXPOP1]; // Expanses of new leaves
939 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
940 + jbb_t StageJBB; // staged bitmap branch
941 +
942 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF4);
943 + assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFF) == (cJU_LEAF4_MAXPOP1-1));
944 +
945 +// Get the address of the Leaf
946 + PLeaf = (uint32_t *) P_JLL(Pjp->jp_Addr);
947 +
948 +// Extract 4 byte index Leaf to Word_t
949 + j__udyCopy4toW(StageA, PLeaf, cJU_LEAF4_MAXPOP1);
950 +
951 +// Get the address of the Leaf and Value area
952 + JUDYLCODE(Pjv = JL_LEAF4VALUEAREA(PLeaf, cJU_LEAF4_MAXPOP1);)
953 +
954 +// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
955 +
956 + CIndex = StageA[0];
957 + if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF4_MAXPOP1-1], 4))
958 + {
959 + Word_t DcdP0;
960 + Pjll_t PjllRaw; // pointer to new leaf.
961 + Pjll_t Pjll;
962 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new Leaf.
963 +
964 +// Alloc a 3 byte Index Leaf
965 + PjllRaw = j__udyAllocJLL3(cJU_LEAF4_MAXPOP1, Pjpm);
966 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
967 +
968 + Pjll = P_JLL(PjllRaw);
969 +
970 +// Copy Index area into new Leaf
971 + j__udyCopyWto3((uint8_t *) Pjll, StageA, cJU_LEAF4_MAXPOP1);
972 +#ifdef JUDYL
973 +// Copy Value area into new Leaf
974 + Pjvnew = JL_LEAF3VALUEAREA(Pjll, cJU_LEAF4_MAXPOP1);
975 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF4_MAXPOP1);
976 +#endif
977 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF4_MAXPOP1, 3);)
978 +
979 + DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(3));
980 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF3);
981 +
982 + return(1);
983 + }
984 +
985 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
986 +
987 + StageJBB = StageJBBZero; // zero staged bitmap branch
988 + ZEROJP(SubJPCount);
989 +
990 +// Splay the 4 byte index Leaf to 3 byte Index Leaves
991 + for (ExpCnt = Start = 0, End = 1; ; End++)
992 + {
993 +// Check if new expanse or last one
994 + if ( (End == cJU_LEAF4_MAXPOP1)
995 + ||
996 + (JU_DIGITATSTATE(CIndex ^ StageA[End], 4))
997 + )
998 + {
999 +// Build a leaf below the previous expanse
1000 +
1001 + Pjp_t PjpJP = StageJP + ExpCnt;
1002 + Word_t Pop1 = End - Start;
1003 + Word_t expanse = JU_DIGITATSTATE(CIndex, 4);
1004 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
1005 +//
1006 +// set the bit that is the current expanse
1007 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
1008 +#ifdef SUBEXPCOUNTS
1009 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
1010 +#endif
1011 +// count number of expanses in each subexpanse
1012 + SubJPCount[subexp]++;
1013 +
1014 +// Save byte expanse of leaf
1015 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 4);
1016 +
1017 + if (Pop1 == 1) // cJU_JPIMMED_3_01
1018 + {
1019 + Word_t DcdP0;
1020 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(3)) |
1021 + CIndex;
1022 +#ifdef JUDY1
1023 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_3_01);
1024 +#else // JUDYL
1025 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
1026 + cJL_JPIMMED_3_01);
1027 +#endif // JUDYL
1028 + }
1029 + else if (Pop1 <= cJU_IMMED3_MAXPOP1)
1030 + {
1031 +// cJ1_JPIMMED_3_02 : Judy1 32
1032 +// cJL_JPIMMED_3_02 : JudyL 64
1033 +// cJ1_JPIMMED_3_02..5: Judy1 64
1034 +
1035 +#ifdef JUDYL
1036 +// Alloc is 1st in case of malloc fail
1037 + Pjv_t PjvnewRaw; // value area of new leaf.
1038 + Pjv_t Pjvnew;
1039 +
1040 +// Allocate Value area for Immediate Leaf
1041 + PjvnewRaw = j__udyLAllocJV(Pop1, Pjpm);
1042 + if (PjvnewRaw == (Pjv_t) NULL)
1043 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1044 +
1045 + Pjvnew = P_JV(PjvnewRaw);
1046 +
1047 +// Copy to Values to Value Leaf
1048 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1049 + PjpJP->jp_Addr = (Word_t) PjvnewRaw;
1050 +
1051 +// Copy to Index to JP as an immediate Leaf
1052 + j__udyCopyWto3(PjpJP->jp_LIndex,
1053 + StageA + Start, Pop1);
1054 +#else
1055 + j__udyCopyWto3(PjpJP->jp_1Index,
1056 + StageA + Start, Pop1);
1057 +#endif
1058 +// Set type, population and Index size
1059 + PjpJP->jp_Type = cJU_JPIMMED_3_02 + Pop1 - 2;
1060 + }
1061 + else
1062 + {
1063 +// cJU_JPLEAF3
1064 + Word_t DcdP0;
1065 + Pjll_t PjllRaw; // pointer to new leaf.
1066 + Pjll_t Pjll;
1067 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1068 +
1069 + PjllRaw = j__udyAllocJLL3(Pop1, Pjpm);
1070 + if (PjllRaw == (Pjll_t)NULL)
1071 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1072 +
1073 + Pjll = P_JLL(PjllRaw);
1074 +
1075 +// Copy Indexes to new Leaf
1076 + j__udyCopyWto3((uint8_t *) Pjll, StageA + Start,
1077 + Pop1);
1078 +#ifdef JUDYL
1079 +// Copy to Values to new Leaf
1080 + Pjvnew = JL_LEAF3VALUEAREA(Pjll, Pop1);
1081 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1082 +#endif
1083 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 3);)
1084 +
1085 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(4))
1086 + |
1087 + (CIndex & cJU_DCDMASK(4-1))
1088 + |
1089 + (Pop1 - 1);
1090 +
1091 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
1092 + cJU_JPLEAF3);
1093 + }
1094 + ExpCnt++;
1095 +// Done?
1096 + if (End == cJU_LEAF4_MAXPOP1) break;
1097 +
1098 +// New Expanse, Start and Count
1099 + CIndex = StageA[End];
1100 + Start = End;
1101 + }
1102 + }
1103 +
1104 +// Now put all the Leaves below a BranchL or BranchB:
1105 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
1106 + {
1107 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
1108 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1109 +
1110 + Pjp->jp_Type = cJU_JPBRANCH_L4;
1111 + }
1112 + else
1113 + {
1114 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
1115 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1116 + }
1117 + return(1);
1118 +
1119 +} // j__udyCascade4()
1120 +
1121 +
1122 +// ****************************************************************************
1123 +// __ J U D Y C A S C A D E 5
1124 +//
1125 +// Cascade from a cJU_JPLEAF5 to one of the following:
1126 +// 1. if leaf is in 1 expanse:
1127 +// compress it into a JPLEAF4
1128 +// 2. if leaf contains multiple expanses:
1129 +// create linear or bitmap branch containing
1130 +// each new expanse is either a:
1131 +// JPIMMED_4_01 branch
1132 +// JPLEAF4
1133 +
1134 +FUNCTION int j__udyCascade5(
1135 + Pjp_t Pjp,
1136 + Pvoid_t Pjpm)
1137 +{
1138 + uint8_t * PLeaf; // pointer to leaf, explicit type.
1139 + Word_t End, Start; // temporaries.
1140 + Word_t ExpCnt; // count of expanses of splay.
1141 + Word_t CIndex; // current Index word.
1142 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
1143 +
1144 +// Temp staging for parts(Leaves) of newly splayed leaf
1145 + jp_t StageJP [cJU_LEAF5_MAXPOP1]; // JPs of new leaves
1146 + Word_t StageA [cJU_LEAF5_MAXPOP1];
1147 + uint8_t StageExp [cJU_LEAF5_MAXPOP1]; // Expanses of new leaves
1148 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
1149 + jbb_t StageJBB; // staged bitmap branch
1150 +
1151 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF5);
1152 + assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFFFF) == (cJU_LEAF5_MAXPOP1-1));
1153 +
1154 +// Get the address of the Leaf
1155 + PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
1156 +
1157 +// Extract 5 byte index Leaf to Word_t
1158 + j__udyCopy5toW(StageA, PLeaf, cJU_LEAF5_MAXPOP1);
1159 +
1160 +// Get the address of the Leaf and Value area
1161 + JUDYLCODE(Pjv = JL_LEAF5VALUEAREA(PLeaf, cJU_LEAF5_MAXPOP1);)
1162 +
1163 +// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
1164 +
1165 + CIndex = StageA[0];
1166 + if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF5_MAXPOP1-1], 5))
1167 + {
1168 + Word_t DcdP0;
1169 + Pjll_t PjllRaw; // pointer to new leaf.
1170 + Pjll_t Pjll;
1171 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1172 +
1173 +// Alloc a 4 byte Index Leaf
1174 + PjllRaw = j__udyAllocJLL4(cJU_LEAF5_MAXPOP1, Pjpm);
1175 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
1176 +
1177 + Pjll = P_JLL(PjllRaw);
1178 +
1179 +// Copy Index area into new Leaf
1180 + j__udyCopyWto4((uint8_t *) Pjll, StageA, cJU_LEAF5_MAXPOP1);
1181 +#ifdef JUDYL
1182 +// Copy Value area into new Leaf
1183 + Pjvnew = JL_LEAF4VALUEAREA(Pjll, cJU_LEAF5_MAXPOP1);
1184 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF5_MAXPOP1);
1185 +#endif
1186 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF5_MAXPOP1, 4);)
1187 +
1188 + DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(4));
1189 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF4);
1190 +
1191 + return(1);
1192 + }
1193 +
1194 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
1195 +
1196 + StageJBB = StageJBBZero; // zero staged bitmap branch
1197 + ZEROJP(SubJPCount);
1198 +
1199 +// Splay the 5 byte index Leaf to 4 byte Index Leaves
1200 + for (ExpCnt = Start = 0, End = 1; ; End++)
1201 + {
1202 +// Check if new expanse or last one
1203 + if ( (End == cJU_LEAF5_MAXPOP1)
1204 + ||
1205 + (JU_DIGITATSTATE(CIndex ^ StageA[End], 5))
1206 + )
1207 + {
1208 +// Build a leaf below the previous expanse
1209 +
1210 + Pjp_t PjpJP = StageJP + ExpCnt;
1211 + Word_t Pop1 = End - Start;
1212 + Word_t expanse = JU_DIGITATSTATE(CIndex, 5);
1213 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
1214 +//
1215 +// set the bit that is the current expanse
1216 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
1217 +#ifdef SUBEXPCOUNTS
1218 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
1219 +#endif
1220 +// count number of expanses in each subexpanse
1221 + SubJPCount[subexp]++;
1222 +
1223 +// Save byte expanse of leaf
1224 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 5);
1225 +
1226 + if (Pop1 == 1) // cJU_JPIMMED_4_01
1227 + {
1228 + Word_t DcdP0;
1229 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(4)) |
1230 + CIndex;
1231 +#ifdef JUDY1
1232 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_4_01);
1233 +#else // JUDYL
1234 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
1235 + cJL_JPIMMED_4_01);
1236 +#endif // JUDYL
1237 + }
1238 +#ifdef JUDY1
1239 + else if (Pop1 <= cJ1_IMMED4_MAXPOP1)
1240 + {
1241 +// cJ1_JPIMMED_4_02..3: Judy1 64
1242 +
1243 +// Copy to Index to JP as an immediate Leaf
1244 + j__udyCopyWto4(PjpJP->jp_1Index,
1245 + StageA + Start, Pop1);
1246 +
1247 +// Set pointer, type, population and Index size
1248 + PjpJP->jp_Type = cJ1_JPIMMED_4_02 + Pop1 - 2;
1249 + }
1250 +#endif
1251 + else
1252 + {
1253 +// cJU_JPLEAF4
1254 + Word_t DcdP0;
1255 + Pjll_t PjllRaw; // pointer to new leaf.
1256 + Pjll_t Pjll;
1257 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1258 +
1259 +// Get a new Leaf
1260 + PjllRaw = j__udyAllocJLL4(Pop1, Pjpm);
1261 + if (PjllRaw == (Pjll_t)NULL)
1262 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1263 +
1264 + Pjll = P_JLL(PjllRaw);
1265 +
1266 +// Copy Indexes to new Leaf
1267 + j__udyCopyWto4((uint8_t *) Pjll, StageA + Start,
1268 + Pop1);
1269 +#ifdef JUDYL
1270 +// Copy to Values to new Leaf
1271 + Pjvnew = JL_LEAF4VALUEAREA(Pjll, Pop1);
1272 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1273 +#endif
1274 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 4);)
1275 +
1276 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(5))
1277 + |
1278 + (CIndex & cJU_DCDMASK(5-1))
1279 + |
1280 + (Pop1 - 1);
1281 +
1282 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
1283 + cJU_JPLEAF4);
1284 + }
1285 + ExpCnt++;
1286 +// Done?
1287 + if (End == cJU_LEAF5_MAXPOP1) break;
1288 +
1289 +// New Expanse, Start and Count
1290 + CIndex = StageA[End];
1291 + Start = End;
1292 + }
1293 + }
1294 +
1295 +// Now put all the Leaves below a BranchL or BranchB:
1296 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
1297 + {
1298 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
1299 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1300 +
1301 + Pjp->jp_Type = cJU_JPBRANCH_L5;
1302 + }
1303 + else
1304 + {
1305 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
1306 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1307 + }
1308 + return(1);
1309 +
1310 +} // j__udyCascade5()
1311 +
1312 +
1313 +// ****************************************************************************
1314 +// __ J U D Y C A S C A D E 6
1315 +//
1316 +// Cascade from a cJU_JPLEAF6 to one of the following:
1317 +// 1. if leaf is in 1 expanse:
1318 +// compress it into a JPLEAF5
1319 +// 2. if leaf contains multiple expanses:
1320 +// create linear or bitmap branch containing
1321 +// each new expanse is either a:
1322 +// JPIMMED_5_01 ... JPIMMED_5_03 branch
1323 +// JPIMMED_5_01 branch
1324 +// JPLEAF5
1325 +
1326 +FUNCTION int j__udyCascade6(
1327 + Pjp_t Pjp,
1328 + Pvoid_t Pjpm)
1329 +{
1330 + uint8_t * PLeaf; // pointer to leaf, explicit type.
1331 + Word_t End, Start; // temporaries.
1332 + Word_t ExpCnt; // count of expanses of splay.
1333 + Word_t CIndex; // current Index word.
1334 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
1335 +
1336 +// Temp staging for parts(Leaves) of newly splayed leaf
1337 + jp_t StageJP [cJU_LEAF6_MAXPOP1]; // JPs of new leaves
1338 + Word_t StageA [cJU_LEAF6_MAXPOP1];
1339 + uint8_t StageExp [cJU_LEAF6_MAXPOP1]; // Expanses of new leaves
1340 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
1341 + jbb_t StageJBB; // staged bitmap branch
1342 +
1343 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF6);
1344 + assert((JU_JPDCDPOP0(Pjp) & 0xFFFFFFFFFFFF) == (cJU_LEAF6_MAXPOP1-1));
1345 +
1346 +// Get the address of the Leaf
1347 + PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
1348 +
1349 +// Extract 6 byte index Leaf to Word_t
1350 + j__udyCopy6toW(StageA, PLeaf, cJU_LEAF6_MAXPOP1);
1351 +
1352 +// Get the address of the Leaf and Value area
1353 + JUDYLCODE(Pjv = JL_LEAF6VALUEAREA(PLeaf, cJU_LEAF6_MAXPOP1);)
1354 +
1355 +// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
1356 +
1357 + CIndex = StageA[0];
1358 + if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF6_MAXPOP1-1], 6))
1359 + {
1360 + Word_t DcdP0;
1361 + Pjll_t PjllRaw; // pointer to new leaf.
1362 + Pjll_t Pjll;
1363 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1364 +
1365 +// Alloc a 5 byte Index Leaf
1366 + PjllRaw = j__udyAllocJLL5(cJU_LEAF6_MAXPOP1, Pjpm);
1367 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
1368 +
1369 + Pjll = P_JLL(PjllRaw);
1370 +
1371 +// Copy Index area into new Leaf
1372 + j__udyCopyWto5((uint8_t *) Pjll, StageA, cJU_LEAF6_MAXPOP1);
1373 +#ifdef JUDYL
1374 +// Copy Value area into new Leaf
1375 + Pjvnew = JL_LEAF5VALUEAREA(Pjll, cJU_LEAF6_MAXPOP1);
1376 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF6_MAXPOP1);
1377 +#endif
1378 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF6_MAXPOP1, 5);)
1379 +
1380 + DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(5));
1381 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF5);
1382 +
1383 + return(1);
1384 + }
1385 +
1386 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
1387 +
1388 + StageJBB = StageJBBZero; // zero staged bitmap branch
1389 + ZEROJP(SubJPCount);
1390 +
1391 +// Splay the 6 byte index Leaf to 5 byte Index Leaves
1392 + for (ExpCnt = Start = 0, End = 1; ; End++)
1393 + {
1394 +// Check if new expanse or last one
1395 + if ( (End == cJU_LEAF6_MAXPOP1)
1396 + ||
1397 + (JU_DIGITATSTATE(CIndex ^ StageA[End], 6))
1398 + )
1399 + {
1400 +// Build a leaf below the previous expanse
1401 +
1402 + Pjp_t PjpJP = StageJP + ExpCnt;
1403 + Word_t Pop1 = End - Start;
1404 + Word_t expanse = JU_DIGITATSTATE(CIndex, 6);
1405 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
1406 +//
1407 +// set the bit that is the current expanse
1408 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
1409 +#ifdef SUBEXPCOUNTS
1410 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
1411 +#endif
1412 +// count number of expanses in each subexpanse
1413 + SubJPCount[subexp]++;
1414 +
1415 +// Save byte expanse of leaf
1416 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 6);
1417 +
1418 + if (Pop1 == 1) // cJU_JPIMMED_5_01
1419 + {
1420 + Word_t DcdP0;
1421 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(5)) |
1422 + CIndex;
1423 +#ifdef JUDY1
1424 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_5_01);
1425 +#else // JUDYL
1426 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
1427 + cJL_JPIMMED_5_01);
1428 +#endif // JUDYL
1429 + }
1430 +#ifdef JUDY1
1431 + else if (Pop1 <= cJ1_IMMED5_MAXPOP1)
1432 + {
1433 +// cJ1_JPIMMED_5_02..3: Judy1 64
1434 +
1435 +// Copy to Index to JP as an immediate Leaf
1436 + j__udyCopyWto5(PjpJP->jp_1Index,
1437 + StageA + Start, Pop1);
1438 +
1439 +// Set pointer, type, population and Index size
1440 + PjpJP->jp_Type = cJ1_JPIMMED_5_02 + Pop1 - 2;
1441 + }
1442 +#endif
1443 + else
1444 + {
1445 +// cJU_JPLEAF5
1446 + Word_t DcdP0;
1447 + Pjll_t PjllRaw; // pointer to new leaf.
1448 + Pjll_t Pjll;
1449 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1450 +
1451 +// Get a new Leaf
1452 + PjllRaw = j__udyAllocJLL5(Pop1, Pjpm);
1453 + if (PjllRaw == (Pjll_t)NULL)
1454 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1455 +
1456 + Pjll = P_JLL(PjllRaw);
1457 +
1458 +// Copy Indexes to new Leaf
1459 + j__udyCopyWto5((uint8_t *) Pjll, StageA + Start,
1460 + Pop1);
1461 +
1462 +// Copy to Values to new Leaf
1463 +#ifdef JUDYL
1464 + Pjvnew = JL_LEAF5VALUEAREA(Pjll, Pop1);
1465 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1466 +#endif
1467 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 5);)
1468 +
1469 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(6))
1470 + |
1471 + (CIndex & cJU_DCDMASK(6-1))
1472 + |
1473 + (Pop1 - 1);
1474 +
1475 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
1476 + cJU_JPLEAF5);
1477 + }
1478 + ExpCnt++;
1479 +// Done?
1480 + if (End == cJU_LEAF6_MAXPOP1) break;
1481 +
1482 +// New Expanse, Start and Count
1483 + CIndex = StageA[End];
1484 + Start = End;
1485 + }
1486 + }
1487 +
1488 +// Now put all the Leaves below a BranchL or BranchB:
1489 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
1490 + {
1491 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
1492 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1493 +
1494 + Pjp->jp_Type = cJU_JPBRANCH_L6;
1495 + }
1496 + else
1497 + {
1498 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
1499 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1500 + }
1501 + return(1);
1502 +
1503 +} // j__udyCascade6()
1504 +
1505 +
1506 +// ****************************************************************************
1507 +// __ J U D Y C A S C A D E 7
1508 +//
1509 +// Cascade from a cJU_JPLEAF7 to one of the following:
1510 +// 1. if leaf is in 1 expanse:
1511 +// compress it into a JPLEAF6
1512 +// 2. if leaf contains multiple expanses:
1513 +// create linear or bitmap branch containing
1514 +// each new expanse is either a:
1515 +// JPIMMED_6_01 ... JPIMMED_6_02 branch
1516 +// JPIMMED_6_01 branch
1517 +// JPLEAF6
1518 +
1519 +FUNCTION int j__udyCascade7(
1520 + Pjp_t Pjp,
1521 + Pvoid_t Pjpm)
1522 +{
1523 + uint8_t * PLeaf; // pointer to leaf, explicit type.
1524 + Word_t End, Start; // temporaries.
1525 + Word_t ExpCnt; // count of expanses of splay.
1526 + Word_t CIndex; // current Index word.
1527 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
1528 +
1529 +// Temp staging for parts(Leaves) of newly splayed leaf
1530 + jp_t StageJP [cJU_LEAF7_MAXPOP1]; // JPs of new leaves
1531 + Word_t StageA [cJU_LEAF7_MAXPOP1];
1532 + uint8_t StageExp [cJU_LEAF7_MAXPOP1]; // Expanses of new leaves
1533 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
1534 + jbb_t StageJBB; // staged bitmap branch
1535 +
1536 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF7);
1537 + assert(JU_JPDCDPOP0(Pjp) == (cJU_LEAF7_MAXPOP1-1));
1538 +
1539 +// Get the address of the Leaf
1540 + PLeaf = (uint8_t *) P_JLL(Pjp->jp_Addr);
1541 +
1542 +// Extract 7 byte index Leaf to Word_t
1543 + j__udyCopy7toW(StageA, PLeaf, cJU_LEAF7_MAXPOP1);
1544 +
1545 +// Get the address of the Leaf and Value area
1546 + JUDYLCODE(Pjv = JL_LEAF7VALUEAREA(PLeaf, cJU_LEAF7_MAXPOP1);)
1547 +
1548 +// If Leaf is in 1 expanse -- just compress it (compare 1st, last & Index)
1549 +
1550 + CIndex = StageA[0];
1551 + if (!JU_DIGITATSTATE(CIndex ^ StageA[cJU_LEAF7_MAXPOP1-1], 7))
1552 + {
1553 + Word_t DcdP0;
1554 + Pjll_t PjllRaw; // pointer to new leaf.
1555 + Pjll_t Pjll;
1556 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1557 +
1558 +// Alloc a 6 byte Index Leaf
1559 + PjllRaw = j__udyAllocJLL6(cJU_LEAF7_MAXPOP1, Pjpm);
1560 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
1561 +
1562 + Pjll = P_JLL(PjllRaw);
1563 +
1564 +// Copy Index area into new Leaf
1565 + j__udyCopyWto6((uint8_t *) Pjll, StageA, cJU_LEAF7_MAXPOP1);
1566 +#ifdef JUDYL
1567 +// Copy Value area into new Leaf
1568 + Pjvnew = JL_LEAF6VALUEAREA(Pjll, cJU_LEAF7_MAXPOP1);
1569 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAF7_MAXPOP1);
1570 +#endif
1571 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAF7_MAXPOP1, 6);)
1572 +
1573 + DcdP0 = JU_JPDCDPOP0(Pjp) | (CIndex & cJU_DCDMASK(6));
1574 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, DcdP0, cJU_JPLEAF6);
1575 +
1576 + return(1);
1577 + }
1578 +
1579 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
1580 +
1581 + StageJBB = StageJBBZero; // zero staged bitmap branch
1582 + ZEROJP(SubJPCount);
1583 +
1584 +// Splay the 7 byte index Leaf to 6 byte Index Leaves
1585 + for (ExpCnt = Start = 0, End = 1; ; End++)
1586 + {
1587 +// Check if new expanse or last one
1588 + if ( (End == cJU_LEAF7_MAXPOP1)
1589 + ||
1590 + (JU_DIGITATSTATE(CIndex ^ StageA[End], 7))
1591 + )
1592 + {
1593 +// Build a leaf below the previous expanse
1594 +
1595 + Pjp_t PjpJP = StageJP + ExpCnt;
1596 + Word_t Pop1 = End - Start;
1597 + Word_t expanse = JU_DIGITATSTATE(CIndex, 7);
1598 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
1599 +//
1600 +// set the bit that is the current expanse
1601 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
1602 +#ifdef SUBEXPCOUNTS
1603 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
1604 +#endif
1605 +// count number of expanses in each subexpanse
1606 + SubJPCount[subexp]++;
1607 +
1608 +// Save byte expanse of leaf
1609 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex, 7);
1610 +
1611 + if (Pop1 == 1) // cJU_JPIMMED_6_01
1612 + {
1613 + Word_t DcdP0;
1614 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(6)) |
1615 + CIndex;
1616 +#ifdef JUDY1
1617 + JU_JPSETADT(PjpJP, 0, DcdP0, cJ1_JPIMMED_6_01);
1618 +#else // JUDYL
1619 + JU_JPSETADT(PjpJP, Pjv[Start], DcdP0,
1620 + cJL_JPIMMED_6_01);
1621 +#endif // JUDYL
1622 + }
1623 +#ifdef JUDY1
1624 + else if (Pop1 == cJ1_IMMED6_MAXPOP1)
1625 + {
1626 +// cJ1_JPIMMED_6_02: Judy1 64
1627 +
1628 +// Copy to Index to JP as an immediate Leaf
1629 + j__udyCopyWto6(PjpJP->jp_1Index,
1630 + StageA + Start, 2);
1631 +
1632 +// Set pointer, type, population and Index size
1633 + PjpJP->jp_Type = cJ1_JPIMMED_6_02;
1634 + }
1635 +#endif
1636 + else
1637 + {
1638 +// cJU_JPLEAF6
1639 + Word_t DcdP0;
1640 + Pjll_t PjllRaw; // pointer to new leaf.
1641 + Pjll_t Pjll;
1642 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1643 +
1644 +// Get a new Leaf
1645 + PjllRaw = j__udyAllocJLL6(Pop1, Pjpm);
1646 + if (PjllRaw == (Pjll_t)NULL)
1647 + FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1648 + Pjll = P_JLL(PjllRaw);
1649 +
1650 +// Copy Indexes to new Leaf
1651 + j__udyCopyWto6((uint8_t *) Pjll, StageA + Start,
1652 + Pop1);
1653 +#ifdef JUDYL
1654 +// Copy to Values to new Leaf
1655 + Pjvnew = JL_LEAF6VALUEAREA(Pjll, Pop1);
1656 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1657 +#endif
1658 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 6);)
1659 +
1660 + DcdP0 = (JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(7))
1661 + |
1662 + (CIndex & cJU_DCDMASK(7-1))
1663 + |
1664 + (Pop1 - 1);
1665 +
1666 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, DcdP0,
1667 + cJU_JPLEAF6);
1668 + }
1669 + ExpCnt++;
1670 +// Done?
1671 + if (End == cJU_LEAF7_MAXPOP1) break;
1672 +
1673 +// New Expanse, Start and Count
1674 + CIndex = StageA[End];
1675 + Start = End;
1676 + }
1677 + }
1678 +
1679 +// Now put all the Leaves below a BranchL or BranchB:
1680 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
1681 + {
1682 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
1683 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1684 +
1685 + Pjp->jp_Type = cJU_JPBRANCH_L7;
1686 + }
1687 + else
1688 + {
1689 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
1690 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1691 + }
1692 + return(1);
1693 +
1694 +} // j__udyCascade7()
1695 +
1696 +#endif // JU_64BIT
1697 +
1698 +
1699 +// ****************************************************************************
1700 +// __ J U D Y C A S C A D E L
1701 +//
1702 +// (Compressed) cJU_LEAF3[7], cJ1_JPBRANCH_L.
1703 +//
1704 +// Cascade from a LEAFW (under Pjp) to one of the following:
1705 +// 1. if LEAFW is in 1 expanse:
1706 +// create linear branch with a JPLEAF3[7] under it
1707 +// 2. LEAFW contains multiple expanses:
1708 +// create linear or bitmap branch containing new expanses
1709 +// each new expanse is either a: 32 64
1710 +// JPIMMED_3_01 branch Y N
1711 +// JPIMMED_7_01 branch N Y
1712 +// JPLEAF3 Y N
1713 +// JPLEAF7 N Y
1714 +
1715 +FUNCTION int j__udyCascadeL(
1716 + Pjp_t Pjp,
1717 + Pvoid_t Pjpm)
1718 +{
1719 + Pjlw_t Pjlw; // leaf to work on.
1720 + Word_t End, Start; // temporaries.
1721 + Word_t ExpCnt; // count of expanses of splay.
1722 + Word_t CIndex; // current Index word.
1723 +JUDYLCODE(Pjv_t Pjv;) // value area of leaf.
1724 +
1725 +// Temp staging for parts(Leaves) of newly splayed leaf
1726 + jp_t StageJP [cJU_LEAFW_MAXPOP1];
1727 + uint8_t StageExp[cJU_LEAFW_MAXPOP1];
1728 + uint8_t SubJPCount[cJU_NUMSUBEXPB]; // JPs in each subexpanse
1729 + jbb_t StageJBB; // staged bitmap branch
1730 +
1731 +// Get the address of the Leaf
1732 + Pjlw = P_JLW(Pjp->jp_Addr);
1733 +
1734 + assert(Pjlw[0] == (cJU_LEAFW_MAXPOP1 - 1));
1735 +
1736 +// Get pointer to Value area of old Leaf
1737 + JUDYLCODE(Pjv = JL_LEAFWVALUEAREA(Pjlw, cJU_LEAFW_MAXPOP1);)
1738 +
1739 + Pjlw++; // Now point to Index area
1740 +
1741 +// If Leaf is in 1 expanse -- first compress it (compare 1st, last & Index):
1742 +
1743 + CIndex = Pjlw[0]; // also used far below
1744 + if (!JU_DIGITATSTATE(CIndex ^ Pjlw[cJU_LEAFW_MAXPOP1 - 1],
1745 + cJU_ROOTSTATE))
1746 + {
1747 + Pjll_t PjllRaw; // pointer to new leaf.
1748 + Pjll_t Pjll;
1749 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1750 +
1751 +// Get the common expanse to all elements in Leaf
1752 + StageExp[0] = JU_DIGITATSTATE(CIndex, cJU_ROOTSTATE);
1753 +
1754 +// Alloc a 3[7] byte Index Leaf
1755 +#ifdef JU_64BIT
1756 + PjllRaw = j__udyAllocJLL7(cJU_LEAFW_MAXPOP1, Pjpm);
1757 + if (PjllRaw == (Pjlb_t)NULL) return(-1); // out of memory
1758 +
1759 + Pjll = P_JLL(PjllRaw);
1760 +
1761 +// Copy LEAFW to a cJU_JPLEAF7
1762 + j__udyCopyWto7((uint8_t *) Pjll, Pjlw, cJU_LEAFW_MAXPOP1);
1763 +#ifdef JUDYL
1764 +// Get the Value area of new Leaf
1765 + Pjvnew = JL_LEAF7VALUEAREA(Pjll, cJU_LEAFW_MAXPOP1);
1766 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAFW_MAXPOP1);
1767 +#endif
1768 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAFW_MAXPOP1, 7);)
1769 +#else // 32 Bit
1770 + PjllRaw = j__udyAllocJLL3(cJU_LEAFW_MAXPOP1, Pjpm);
1771 + if (PjllRaw == (Pjll_t) NULL) return(-1);
1772 +
1773 + Pjll = P_JLL(PjllRaw);
1774 +
1775 +// Copy LEAFW to a cJU_JPLEAF3
1776 + j__udyCopyWto3((uint8_t *) Pjll, Pjlw, cJU_LEAFW_MAXPOP1);
1777 +#ifdef JUDYL
1778 +// Get the Value area of new Leaf
1779 + Pjvnew = JL_LEAF3VALUEAREA(Pjll, cJU_LEAFW_MAXPOP1);
1780 + JU_COPYMEM(Pjvnew, Pjv, cJU_LEAFW_MAXPOP1);
1781 +#endif
1782 + DBGCODE(JudyCheckSorted(Pjll, cJU_LEAFW_MAXPOP1, 3);)
1783 +#endif // 32 Bit
1784 +
1785 +// Following not needed because cJU_DCDMASK(3[7]) is == 0
1786 +////// StageJP[0].jp_DcdPopO |= (CIndex & cJU_DCDMASK(3[7]));
1787 +#ifdef JU_64BIT
1788 + JU_JPSETADT(&(StageJP[0]), (Word_t)PjllRaw, cJU_LEAFW_MAXPOP1-1,
1789 + cJU_JPLEAF7);
1790 +#else // 32BIT
1791 + JU_JPSETADT(&(StageJP[0]), (Word_t)PjllRaw, cJU_LEAFW_MAXPOP1-1,
1792 + cJU_JPLEAF3);
1793 +#endif // 32BIT
1794 +// Create a 1 element Linear branch
1795 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, 1, Pjpm) == -1)
1796 + return(-1);
1797 +
1798 +// Change the type of callers JP
1799 + Pjp->jp_Type = cJU_JPBRANCH_L;
1800 +
1801 + return(1);
1802 + }
1803 +
1804 +// Else in 2+ expanses, splay Leaf into smaller leaves at higher compression
1805 +
1806 + StageJBB = StageJBBZero; // zero staged bitmap branch
1807 + ZEROJP(SubJPCount);
1808 +
1809 +// Splay the 4[8] byte Index Leaf to 3[7] byte Index Leaves
1810 + for (ExpCnt = Start = 0, End = 1; ; End++)
1811 + {
1812 +// Check if new expanse or last one
1813 + if ( (End == cJU_LEAFW_MAXPOP1)
1814 + ||
1815 + (JU_DIGITATSTATE(CIndex ^ Pjlw[End], cJU_ROOTSTATE))
1816 + )
1817 + {
1818 +// Build a leaf below the previous expanse
1819 +
1820 + Pjp_t PjpJP = StageJP + ExpCnt;
1821 + Word_t Pop1 = End - Start;
1822 + Word_t expanse = JU_DIGITATSTATE(CIndex, cJU_ROOTSTATE);
1823 + Word_t subexp = expanse / cJU_BITSPERSUBEXPB;
1824 +//
1825 +// set the bit that is the current expanse
1826 + JU_JBB_BITMAP(&StageJBB, subexp) |= JU_BITPOSMASKB(expanse);
1827 +#ifdef SUBEXPCOUNTS
1828 + StageJBB.jbb_subPop1[subexp] += Pop1; // pop of subexpanse
1829 +#endif
1830 +// count number of expanses in each subexpanse
1831 + SubJPCount[subexp]++;
1832 +
1833 +// Save byte expanse of leaf
1834 + StageExp[ExpCnt] = JU_DIGITATSTATE(CIndex,
1835 + cJU_ROOTSTATE);
1836 +
1837 + if (Pop1 == 1) // cJU_JPIMMED_3[7]_01
1838 + {
1839 +#ifdef JU_64BIT
1840 +#ifdef JUDY1
1841 + JU_JPSETADT(PjpJP, 0, CIndex, cJ1_JPIMMED_7_01);
1842 +#else // JUDYL
1843 + JU_JPSETADT(PjpJP, Pjv[Start], CIndex,
1844 + cJL_JPIMMED_7_01);
1845 +#endif // JUDYL
1846 +
1847 +#else // JU_32BIT
1848 +#ifdef JUDY1
1849 + JU_JPSETADT(PjpJP, 0, CIndex, cJ1_JPIMMED_3_01);
1850 +#else // JUDYL
1851 + JU_JPSETADT(PjpJP, Pjv[Start], CIndex,
1852 + cJL_JPIMMED_3_01);
1853 +#endif // JUDYL
1854 +#endif // JU_32BIT
1855 + }
1856 +#ifdef JUDY1
1857 +#ifdef JU_64BIT
1858 + else if (Pop1 <= cJ1_IMMED7_MAXPOP1)
1859 +#else
1860 + else if (Pop1 <= cJ1_IMMED3_MAXPOP1)
1861 +#endif
1862 + {
1863 +// cJ1_JPIMMED_3_02 : Judy1 32
1864 +// cJ1_JPIMMED_7_02 : Judy1 64
1865 +// Copy to JP as an immediate Leaf
1866 +#ifdef JU_64BIT
1867 + j__udyCopyWto7(PjpJP->jp_1Index, Pjlw+Start, 2);
1868 + PjpJP->jp_Type = cJ1_JPIMMED_7_02;
1869 +#else
1870 + j__udyCopyWto3(PjpJP->jp_1Index, Pjlw+Start, 2);
1871 + PjpJP->jp_Type = cJ1_JPIMMED_3_02;
1872 +#endif // 32 Bit
1873 + }
1874 +#endif // JUDY1
1875 + else // Linear Leaf JPLEAF3[7]
1876 + {
1877 +// cJU_JPLEAF3[7]
1878 + Pjll_t PjllRaw; // pointer to new leaf.
1879 + Pjll_t Pjll;
1880 + JUDYLCODE(Pjv_t Pjvnew;) // value area of new leaf.
1881 +#ifdef JU_64BIT
1882 + PjllRaw = j__udyAllocJLL7(Pop1, Pjpm);
1883 + if (PjllRaw == (Pjll_t) NULL) return(-1);
1884 + Pjll = P_JLL(PjllRaw);
1885 +
1886 + j__udyCopyWto7((uint8_t *) Pjll, Pjlw + Start,
1887 + Pop1);
1888 +#ifdef JUDYL
1889 + Pjvnew = JL_LEAF7VALUEAREA(Pjll, Pop1);
1890 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1891 +#endif // JUDYL
1892 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 7);)
1893 +#else // JU_64BIT - 32 Bit
1894 + PjllRaw = j__udyAllocJLL3(Pop1, Pjpm);
1895 + if (PjllRaw == (Pjll_t) NULL) return(-1);
1896 + Pjll = P_JLL(PjllRaw);
1897 +
1898 + j__udyCopyWto3((uint8_t *) Pjll, Pjlw + Start,
1899 + Pop1);
1900 +#ifdef JUDYL
1901 + Pjvnew = JL_LEAF3VALUEAREA(Pjll, Pop1);
1902 + JU_COPYMEM(Pjvnew, Pjv + Start, Pop1);
1903 +#endif // JUDYL
1904 + DBGCODE(JudyCheckSorted(Pjll, Pop1, 3);)
1905 +#endif // 32 Bit
1906 +
1907 +#ifdef JU_64BIT
1908 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, Pop1 - 1,
1909 + cJU_JPLEAF7);
1910 +#else // JU_64BIT - 32 Bit
1911 + JU_JPSETADT(PjpJP, (Word_t)PjllRaw, Pop1 - 1,
1912 + cJU_JPLEAF3);
1913 +#endif // 32 Bit
1914 + }
1915 + ExpCnt++;
1916 +// Done?
1917 + if (End == cJU_LEAFW_MAXPOP1) break;
1918 +
1919 +// New Expanse, Start and Count
1920 + CIndex = Pjlw[End];
1921 + Start = End;
1922 + }
1923 + }
1924 +
1925 +// Now put all the Leaves below a BranchL or BranchB:
1926 + if (ExpCnt <= cJU_BRANCHLMAXJPS) // put the Leaves below a BranchL
1927 + {
1928 + if (j__udyCreateBranchL(Pjp, StageJP, StageExp, ExpCnt,
1929 + Pjpm) == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1930 +
1931 + Pjp->jp_Type = cJU_JPBRANCH_L;
1932 + }
1933 + else
1934 + {
1935 + if (j__udyStageJBBtoJBB(Pjp, &StageJBB, StageJP, SubJPCount, Pjpm)
1936 + == -1) FREEALLEXIT(ExpCnt, StageJP, Pjpm);
1937 +
1938 + Pjp->jp_Type = cJU_JPBRANCH_B; // cJU_LEAFW is out of sequence
1939 + }
1940 + return(1);
1941 +
1942 +} // j__udyCascadeL()
libnetdata/libjudy/src/JudyL/JudyLCount.c new
+1195
@@ -0,0 +1,1195 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.78 $ $Source: /judy/src/JudyCommon/JudyCount.c $
19 +//
20 +// Judy*Count() function for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DNOSMARTJBB, -DNOSMARTJBU, and/or -DNOSMARTJLB to build a
24 +// version with cache line optimizations deleted, for testing.
25 +//
26 +// Compile with -DSMARTMETRICS to obtain global variables containing smart
27 +// cache line metrics. Note: Dont turn this on simultaneously for this file
28 +// and JudyByCount.c because they export the same globals.
29 +//
30 +// Judy*Count() returns the "count of Indexes" (inclusive) between the two
31 +// specified limits (Indexes). This code is remarkably fast. It traverses the
32 +// "Judy array" data structure.
33 +//
34 +// This count code is the GENERIC untuned version (minimum code size). It
35 +// might be possible to tuned to a specific architecture to be faster.
36 +// However, in real applications, with a modern machine, it is expected that
37 +// the instruction times will be swamped by cache line fills.
38 +// ****************************************************************************
39 +
40 +#if (! (defined(JUDY1) || defined(JUDYL)))
41 +#error: One of -DJUDY1 or -DJUDYL must be specified.
42 +#endif
43 +
44 +#ifdef JUDY1
45 +#include "Judy1.h"
46 +#else
47 +#include "JudyL.h"
48 +#endif
49 +
50 +#include "JudyPrivate1L.h"
51 +
52 +
53 +// define a phoney that is for sure
54 +
55 +#define cJU_LEAFW cJU_JPIMMED_CAP
56 +
57 +// Avoid duplicate symbols since this file is multi-compiled:
58 +
59 +#ifdef SMARTMETRICS
60 +#ifdef JUDY1
61 +Word_t jbb_upward = 0; // counts of directions taken:
62 +Word_t jbb_downward = 0;
63 +Word_t jbu_upward = 0;
64 +Word_t jbu_downward = 0;
65 +Word_t jlb_upward = 0;
66 +Word_t jlb_downward = 0;
67 +#else
68 +extern Word_t jbb_upward;
69 +extern Word_t jbb_downward;
70 +extern Word_t jbu_upward;
71 +extern Word_t jbu_downward;
72 +extern Word_t jlb_upward;
73 +extern Word_t jlb_downward;
74 +#endif
75 +#endif
76 +
77 +
78 +// FORWARD DECLARATIONS (prototypes):
79 +
80 +static Word_t j__udy1LCountSM(const Pjp_t Pjp, const Word_t Index,
81 + const Pjpm_t Pjpm);
82 +
83 +// Each of Judy1 and JudyL get their own private (static) version of this
84 +// function:
85 +
86 +static int j__udyCountLeafB1(const Pjll_t Pjll, const Word_t Pop1,
87 + const Word_t Index);
88 +
89 +// These functions are not static because they are exported to Judy*ByCount():
90 +//
91 +// TBD: Should be made static for performance reasons? And thus duplicated?
92 +//
93 +// Note: There really are two different functions, but for convenience they
94 +// are referred to here with a generic name.
95 +
96 +#ifdef JUDY1
97 +#define j__udyJPPop1 j__udy1JPPop1
98 +#else
99 +#define j__udyJPPop1 j__udyLJPPop1
100 +#endif
101 +
102 +Word_t j__udyJPPop1(const Pjp_t Pjp);
103 +
104 +
105 +// LOCAL ERROR HANDLING:
106 +//
107 +// The Judy*Count() functions are unusual because they return 0 instead of JERR
108 +// for an error. In this source file, define C_JERR for clarity.
109 +
110 +#define C_JERR 0
111 +
112 +
113 +// ****************************************************************************
114 +// J U D Y 1 C O U N T
115 +// J U D Y L C O U N T
116 +//
117 +// See the manual entry for details.
118 +//
119 +// This code is written recursively, at least at first, because thats much
120 +// simpler; hope its fast enough.
121 +
122 +#ifdef JUDY1
123 +FUNCTION Word_t Judy1Count
124 +#else
125 +FUNCTION Word_t JudyLCount
126 +#endif
127 + (
128 + Pcvoid_t PArray, // JRP to first branch/leaf in SM.
129 + Word_t Index1, // starting Index.
130 + Word_t Index2, // ending Index.
131 + PJError_t PJError // optional, for returning error info.
132 + )
133 +{
134 + jpm_t fakejpm; // local temporary for small arrays.
135 + Pjpm_t Pjpm; // top JPM or local temporary for error info.
136 + jp_t fakejp; // constructed for calling j__udy1LCountSM().
137 + Pjp_t Pjp; // JP to pass to j__udy1LCountSM().
138 + Word_t pop1; // total for the array.
139 + Word_t pop1above1; // indexes at or above Index1, inclusive.
140 + Word_t pop1above2; // indexes at or above Index2, exclusive.
141 + int retcode; // from Judy*First() calls.
142 +JUDYLCODE(PPvoid_t PPvalue); // from JudyLFirst() calls.
143 +
144 +
145 +// CHECK FOR SHORTCUTS:
146 +//
147 +// As documented, return C_JERR if the Judy array is empty or Index1 > Index2.
148 +
149 + if ((PArray == (Pvoid_t) NULL) || (Index1 > Index2))
150 + {
151 + JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
152 + return(C_JERR);
153 + }
154 +
155 +// If Index1 == Index2, simply check if the specified Index is set; pass
156 +// through the return value from Judy1Test() or JudyLGet() with appropriate
157 +// translations.
158 +
159 + if (Index1 == Index2)
160 + {
161 +#ifdef JUDY1
162 + retcode = Judy1Test(PArray, Index1, PJError);
163 +
164 + if (retcode == JERRI) return(C_JERR); // pass through error.
165 +
166 + if (retcode == 0)
167 + {
168 + JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
169 + return(C_JERR);
170 + }
171 +#else
172 + PPvalue = JudyLGet(PArray, Index1, PJError);
173 +
174 + if (PPvalue == PPJERR) return(C_JERR); // pass through error.
175 +
176 + if (PPvalue == (PPvoid_t) NULL) // Index is not set.
177 + {
178 + JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
179 + return(C_JERR);
180 + }
181 +#endif
182 + return(1); // single index is set.
183 + }
184 +
185 +
186 +// CHECK JRP TYPE:
187 +//
188 +// Use an if/then for speed rather than a switch, and put the most common cases
189 +// first.
190 +//
191 +// Note: Since even cJU_LEAFW types require counting between two Indexes,
192 +// prepare them here for common code below that calls j__udy1LCountSM(), rather
193 +// than handling them even more specially here.
194 +
195 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
196 + {
197 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
198 + Pjpm = & fakejpm;
199 + Pjp = & fakejp;
200 + Pjp->jp_Addr = (Word_t) Pjlw;
201 + Pjp->jp_Type = cJU_LEAFW;
202 + Pjpm->jpm_Pop0 = Pjlw[0]; // from first word of leaf.
203 + pop1 = Pjpm->jpm_Pop0 + 1;
204 + }
205 + else
206 + {
207 + Pjpm = P_JPM(PArray);
208 + Pjp = &(Pjpm->jpm_JP);
209 + pop1 = (Pjpm->jpm_Pop0) + 1; // note: can roll over to 0.
210 +
211 +#if (defined(JUDY1) && (! defined(JU_64BIT)))
212 + if (pop1 == 0) // rare special case of full array:
213 + {
214 + Word_t count = Index2 - Index1 + 1; // can roll over again.
215 +
216 + if (count == 0)
217 + {
218 + JU_SET_ERRNO(PJError, JU_ERRNO_FULL);
219 + return(C_JERR);
220 + }
221 + return(count);
222 + }
223 +#else
224 + assert(pop1); // JudyL or 64-bit cannot create a full array!
225 +#endif
226 + }
227 +
228 +
229 +// COUNT POP1 ABOVE INDEX1, INCLUSIVE:
230 +
231 + assert(pop1); // just to be safe.
232 +
233 + if (Index1 == 0) // shortcut, pop1above1 is entire population:
234 + {
235 + pop1above1 = pop1;
236 + }
237 + else // find first valid Index above Index1, if any:
238 + {
239 +#ifdef JUDY1
240 + if ((retcode = Judy1First(PArray, & Index1, PJError)) == JERRI)
241 + return(C_JERR); // pass through error.
242 +#else
243 + if ((PPvalue = JudyLFirst(PArray, & Index1, PJError)) == PPJERR)
244 + return(C_JERR); // pass through error.
245 +
246 + retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index.
247 +#endif
248 +
249 +// If theres no Index at or above Index1, just return C_JERR (early exit):
250 +
251 + if (retcode == 0)
252 + {
253 + JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
254 + return(C_JERR);
255 + }
256 +
257 +// If a first/next Index was found, call the counting motor starting with that
258 +// known valid Index, meaning the return should be positive, not C_JERR except
259 +// in case of a real error:
260 +
261 + if ((pop1above1 = j__udy1LCountSM(Pjp, Index1, Pjpm)) == C_JERR)
262 + {
263 + JU_COPY_ERRNO(PJError, Pjpm); // pass through error.
264 + return(C_JERR);
265 + }
266 + }
267 +
268 +
269 +// COUNT POP1 ABOVE INDEX2, EXCLUSIVE, AND RETURN THE DIFFERENCE:
270 +//
271 +// In principle, calculate the ordinal of each Index and take the difference,
272 +// with caution about off-by-one errors due to the specified Indexes being set
273 +// or unset. In practice:
274 +//
275 +// - The ordinals computed here are inverse ordinals, that is, the populations
276 +// ABOVE the specified Indexes (Index1 inclusive, Index2 exclusive), so
277 +// subtract pop1above2 from pop1above1, rather than vice-versa.
278 +//
279 +// - Index1s result already includes a count for Index1 and/or Index2 if
280 +// either is set, so calculate pop1above2 exclusive of Index2.
281 +//
282 +// TBD: If Index1 and Index2 fall in the same expanse in the top-state
283 +// branch(es), would it be faster to walk the SM only once, to their divergence
284 +// point, before calling j__udy1LCountSM() or equivalent? Possibly a non-issue
285 +// if a top-state pop1 becomes stored with each Judy1 array. Also, consider
286 +// whether the first call of j__udy1LCountSM() fills the cache, for common tree
287 +// branches, for the second call.
288 +//
289 +// As for pop1above1, look for shortcuts for special cases when pop1above2 is
290 +// zero. Otherwise call the counting "motor".
291 +
292 + assert(pop1above1); // just to be safe.
293 +
294 + if (Index2++ == cJU_ALLONES) return(pop1above1); // Index2 at limit.
295 +
296 +#ifdef JUDY1
297 + if ((retcode = Judy1First(PArray, & Index2, PJError)) == JERRI)
298 + return(C_JERR);
299 +#else
300 + if ((PPvalue = JudyLFirst(PArray, & Index2, PJError)) == PPJERR)
301 + return(C_JERR);
302 +
303 + retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index.
304 +#endif
305 + if (retcode == 0) return(pop1above1); // no Index above Index2.
306 +
307 +// Just as for Index1, j__udy1LCountSM() cannot return 0 (locally == C_JERR)
308 +// except in case of a real error:
309 +
310 + if ((pop1above2 = j__udy1LCountSM(Pjp, Index2, Pjpm)) == C_JERR)
311 + {
312 + JU_COPY_ERRNO(PJError, Pjpm); // pass through error.
313 + return(C_JERR);
314 + }
315 +
316 + if (pop1above1 == pop1above2)
317 + {
318 + JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
319 + return(C_JERR);
320 + }
321 +
322 + return(pop1above1 - pop1above2);
323 +
324 +} // Judy1Count() / JudyLCount()
325 +
326 +
327 +// ****************************************************************************
328 +// __ J U D Y 1 L C O U N T S M
329 +//
330 +// Given a pointer to a JP (with invalid jp_DcdPopO at cJU_ROOTSTATE), a known
331 +// valid Index, and a Pjpm for returning error info, recursively visit a Judy
332 +// array state machine (SM) and return the count of Indexes, including Index,
333 +// through the end of the Judy array at this state or below. In case of error
334 +// or a count of 0 (should never happen), return C_JERR with appropriate
335 +// JU_ERRNO in the Pjpm.
336 +//
337 +// Note: This function is not told the current state because its encoded in
338 +// the JP Type.
339 +//
340 +// Method: To minimize cache line fills, while studying each branch, if Index
341 +// resides above the midpoint of the branch (which often consists of multiple
342 +// cache lines), ADD the populations at or above Index; otherwise, SUBTRACT
343 +// from the population of the WHOLE branch (available from the JP) the
344 +// populations at or above Index. This is especially tricky for bitmap
345 +// branches.
346 +//
347 +// Note: Unlike, say, the Ins and Del walk routines, this function returns the
348 +// same type of returns as Judy*Count(), so it can use *_SET_ERRNO*() macros
349 +// the same way.
350 +
351 +FUNCTION static Word_t j__udy1LCountSM(
352 +const Pjp_t Pjp, // top of Judy (sub)SM.
353 +const Word_t Index, // count at or above this Index.
354 +const Pjpm_t Pjpm) // for returning error info.
355 +{
356 + Pjbl_t Pjbl; // Pjp->jp_Addr masked and cast to types:
357 + Pjbb_t Pjbb;
358 + Pjbu_t Pjbu;
359 + Pjll_t Pjll; // a Judy lower-level linear leaf.
360 +
361 + Word_t digit; // next digit to decode from Index.
362 + long jpnum; // JP number in a branch (base 0).
363 + int offset; // index ordinal within a leaf, base 0.
364 + Word_t pop1; // total population of an expanse.
365 + Word_t pop1above; // to return.
366 +
367 +// Common code to check Decode bits in a JP against the equivalent portion of
368 +// Index; XOR together, then mask bits of interest; must be all 0:
369 +//
370 +// Note: Why does this code only assert() compliance rather than actively
371 +// checking for outliers? Its because Index is supposed to be valid, hence
372 +// always match any Dcd bits traversed.
373 +//
374 +// Note: This assertion turns out to be always true for cState = 3 on 32-bit
375 +// and 7 on 64-bit, but its harmless, probably removed by the compiler.
376 +
377 +#define CHECKDCD(Pjp,cState) \
378 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cState))
379 +
380 +// Common code to prepare to handle a root-level or lower-level branch:
381 +// Extract a state-dependent digit from Index in a "constant" way, obtain the
382 +// total population for the branch in a state-dependent way, and then branch to
383 +// common code for multiple cases:
384 +//
385 +// For root-level branches, the state is always cJU_ROOTSTATE, and the
386 +// population is received in Pjpm->jpm_Pop0.
387 +//
388 +// Note: The total population is only needed in cases where the common code
389 +// "counts up" instead of down to minimize cache line fills. However, its
390 +// available cheaply, and its better to do it with a constant shift (constant
391 +// state value) instead of a variable shift later "when needed".
392 +
393 +#define PREPB_ROOT(Pjp,Next) \
394 + digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE); \
395 + pop1 = (Pjpm->jpm_Pop0) + 1; \
396 + goto Next
397 +
398 +#define PREPB(Pjp,cState,Next) \
399 + digit = JU_DIGITATSTATE(Index, cState); \
400 + pop1 = JU_JPBRANCH_POP0(Pjp, (cState)) + 1; \
401 + goto Next
402 +
403 +
404 +// SWITCH ON JP TYPE:
405 +//
406 +// WARNING: For run-time efficiency the following cases replicate code with
407 +// varying constants, rather than using common code with variable values!
408 +
409 + switch (JU_JPTYPE(Pjp))
410 + {
411 +
412 +
413 +// ----------------------------------------------------------------------------
414 +// ROOT-STATE LEAF that starts with a Pop0 word; just count within the leaf:
415 +
416 + case cJU_LEAFW:
417 + {
418 + Pjlw_t Pjlw = P_JLW(Pjp->jp_Addr); // first word of leaf.
419 +
420 + assert((Pjpm->jpm_Pop0) + 1 == Pjlw[0] + 1); // sent correctly.
421 + offset = j__udySearchLeafW(Pjlw + 1, Pjpm->jpm_Pop0 + 1, Index);
422 + assert(offset >= 0); // Index must exist.
423 + assert(offset < (Pjpm->jpm_Pop0) + 1); // Index be in range.
424 + return((Pjpm->jpm_Pop0) + 1 - offset); // INCLUSIVE of Index.
425 + }
426 +
427 +// ----------------------------------------------------------------------------
428 +// LINEAR BRANCH; count populations in JPs in the JBL ABOVE the next digit in
429 +// Index, and recurse for the next digit in Index:
430 +//
431 +// Note: There are no null JPs in a JBL; watch out for pop1 == 0.
432 +//
433 +// Note: A JBL should always fit in one cache line => no need to count up
434 +// versus down to save cache line fills. (PREPB() sets pop1 for no reason.)
435 +
436 + case cJU_JPBRANCH_L2: CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchL);
437 + case cJU_JPBRANCH_L3: CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchL);
438 +
439 +#ifdef JU_64BIT
440 + case cJU_JPBRANCH_L4: CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchL);
441 + case cJU_JPBRANCH_L5: CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchL);
442 + case cJU_JPBRANCH_L6: CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchL);
443 + case cJU_JPBRANCH_L7: CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchL);
444 +#endif
445 + case cJU_JPBRANCH_L: PREPB_ROOT(Pjp, BranchL);
446 +
447 +// Common code (state-independent) for all cases of linear branches:
448 +
449 +BranchL:
450 +
451 + Pjbl = P_JBL(Pjp->jp_Addr);
452 + jpnum = Pjbl->jbl_NumJPs; // above last JP.
453 + pop1above = 0;
454 +
455 + while (digit < (Pjbl->jbl_Expanse[--jpnum])) // still ABOVE digit.
456 + {
457 + if ((pop1 = j__udyJPPop1((Pjbl->jbl_jp) + jpnum)) == cJU_ALLONES)
458 + {
459 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
460 + return(C_JERR);
461 + }
462 +
463 + pop1above += pop1;
464 + assert(jpnum > 0); // should find digit.
465 + }
466 +
467 + assert(digit == (Pjbl->jbl_Expanse[jpnum])); // should find digit.
468 +
469 + pop1 = j__udy1LCountSM((Pjbl->jbl_jp) + jpnum, Index, Pjpm);
470 + if (pop1 == C_JERR) return(C_JERR); // pass error up.
471 +
472 + assert(pop1above + pop1);
473 + return(pop1above + pop1);
474 +
475 +
476 +// ----------------------------------------------------------------------------
477 +// BITMAP BRANCH; count populations in JPs in the JBB ABOVE the next digit in
478 +// Index, and recurse for the next digit in Index:
479 +//
480 +// Note: There are no null JPs in a JBB; watch out for pop1 == 0.
481 +
482 + case cJU_JPBRANCH_B2: CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchB);
483 + case cJU_JPBRANCH_B3: CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchB);
484 +#ifdef JU_64BIT
485 + case cJU_JPBRANCH_B4: CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchB);
486 + case cJU_JPBRANCH_B5: CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchB);
487 + case cJU_JPBRANCH_B6: CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchB);
488 + case cJU_JPBRANCH_B7: CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchB);
489 +#endif
490 + case cJU_JPBRANCH_B: PREPB_ROOT(Pjp, BranchB);
491 +
492 +// Common code (state-independent) for all cases of bitmap branches:
493 +
494 +BranchB:
495 + {
496 + long subexp; // for stepping through layer 1 (subexpanses).
497 + long findsub; // subexpanse containing Index (digit).
498 + Word_t findbit; // bit representing Index (digit).
499 + Word_t lowermask; // bits for indexes at or below Index.
500 + Word_t jpcount; // JPs in a subexpanse.
501 + Word_t clbelow; // cache lines below digits cache line.
502 + Word_t clabove; // cache lines above digits cache line.
503 +
504 + Pjbb = P_JBB(Pjp->jp_Addr);
505 + findsub = digit / cJU_BITSPERSUBEXPB;
506 + findbit = digit % cJU_BITSPERSUBEXPB;
507 + lowermask = JU_MASKLOWERINC(JU_BITPOSMASKB(findbit));
508 + clbelow = clabove = 0; // initial/default => always downward.
509 +
510 + assert(JU_BITMAPTESTB(Pjbb, digit)); // digit must have a JP.
511 + assert(findsub < cJU_NUMSUBEXPB); // falls in expected range.
512 +
513 +// Shorthand for one subexpanse in a bitmap and for one JP in a bitmap branch:
514 +//
515 +// Note: BMPJP0 exists separately to support assertions.
516 +
517 +#define BMPJP0(Subexp) (P_JP(JU_JBB_PJP(Pjbb, Subexp)))
518 +#define BMPJP(Subexp,JPnum) (BMPJP0(Subexp) + (JPnum))
519 +
520 +#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
521 +
522 +// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
523 +// in JPs above Indexs JP, or subtracting the pop1s in JPs below Indexs JP.
524 +//
525 +// This is tricky because, while each set bit in the bitmap represents a JP,
526 +// the JPs are scattered over cJU_NUMSUBEXPB subexpanses, each of which can
527 +// contain JPs packed into multiple cache lines, and this code must visit every
528 +// JP either BELOW or ABOVE the JP for Index.
529 +//
530 +// Number of cache lines required to hold a linear list of the given number of
531 +// JPs, assuming the first JP is at the start of a cache line or the JPs in
532 +// jpcount fit wholly within a single cache line, which is ensured by
533 +// JudyMalloc():
534 +
535 +#define CLPERJPS(jpcount) \
536 + ((((jpcount) * cJU_WORDSPERJP) + cJU_WORDSPERCL - 1) / cJU_WORDSPERCL)
537 +
538 +// Count cache lines below/above for each subexpanse:
539 +
540 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
541 + {
542 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
543 +
544 +// When at the subexpanse containing Index (digit), add cache lines
545 +// below/above appropriately, excluding the cache line containing the JP for
546 +// Index itself:
547 +
548 + if (subexp < findsub) clbelow += CLPERJPS(jpcount);
549 + else if (subexp > findsub) clabove += CLPERJPS(jpcount);
550 + else // (subexp == findsub)
551 + {
552 + Word_t clfind; // cache line containing Index (digit).
553 +
554 + clfind = CLPERJPS(j__udyCountBitsB(
555 + JU_JBB_BITMAP(Pjbb, subexp) & lowermask));
556 +
557 + assert(clfind > 0); // digit itself should have 1 CL.
558 + clbelow += clfind - 1;
559 + clabove += CLPERJPS(jpcount) - clfind;
560 + }
561 + }
562 +#endif // ! NOSMARTJBB
563 +
564 +// Note: Its impossible to get through the following "if" without setting
565 +// jpnum -- see some of the assertions below -- but gcc -Wall doesnt know
566 +// this, so preset jpnum to make it happy:
567 +
568 + jpnum = 0;
569 +
570 +
571 +// COUNT POPULATION FOR A BITMAP BRANCH, in whichever direction should result
572 +// in fewer cache line fills:
573 +//
574 +// Note: If the remainder of Index is zero, pop1above is the pop1 of the
575 +// entire expanse and theres no point in recursing to lower levels; but this
576 +// should be so rare that its not worth checking for;
577 +// Judy1Count()/JudyLCount() never even calls the motor for Index == 0 (all
578 +// bytes).
579 +
580 +
581 +// COUNT UPWARD, subtracting each "below or at" JPs pop1 from the whole
582 +// expanses pop1:
583 +//
584 +// Note: If this causes clbelow + 1 cache line fills including JPs cache
585 +// line, thats OK; at worst this is the same as clabove.
586 +
587 + if (clbelow < clabove)
588 + {
589 +#ifdef SMARTMETRICS
590 + ++jbb_upward;
591 +#endif
592 + pop1above = pop1; // subtract JPs at/below Index.
593 +
594 +// Count JPs for which to accrue pop1s in this subexpanse:
595 +//
596 +// TBD: If JU_JBB_BITMAP is cJU_FULLBITMAPB, dont bother counting.
597 +
598 + for (subexp = 0; subexp <= findsub; ++subexp)
599 + {
600 + jpcount = j__udyCountBitsB((subexp < findsub) ?
601 + JU_JBB_BITMAP(Pjbb, subexp) :
602 + JU_JBB_BITMAP(Pjbb, subexp) & lowermask);
603 +
604 + // should always find findbit:
605 + assert((subexp < findsub) || jpcount);
606 +
607 +// Subtract pop1s from JPs BELOW OR AT Index (digit):
608 +//
609 +// Note: The pop1 for Indexs JP itself is partially added back later at a
610 +// lower state.
611 +//
612 +// Note: An empty subexpanse (jpcount == 0) is handled "for free".
613 +//
614 +// Note: Must be null JP subexp pointer in empty subexpanse and non-empty in
615 +// non-empty subexpanse:
616 +
617 + assert( jpcount || (BMPJP0(subexp) == (Pjp_t) NULL));
618 + assert((! jpcount) || (BMPJP0(subexp) != (Pjp_t) NULL));
619 +
620 + for (jpnum = 0; jpnum < jpcount; ++jpnum)
621 + {
622 + if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
623 + == cJU_ALLONES)
624 + {
625 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
626 + return(C_JERR);
627 + }
628 +
629 + pop1above -= pop1;
630 + }
631 +
632 + jpnum = jpcount - 1; // make correct for digit.
633 + }
634 + }
635 +
636 +// COUNT DOWNWARD, adding each "above" JPs pop1:
637 +
638 + else
639 + {
640 + long jpcountbf; // below findbit, inclusive.
641 +#ifdef SMARTMETRICS
642 + ++jbb_downward;
643 +#endif
644 + pop1above = 0; // add JPs above Index.
645 + jpcountbf = 0; // until subexp == findsub.
646 +
647 +// Count JPs for which to accrue pop1s in this subexpanse:
648 +//
649 +// This is more complicated than counting upward because the scan of digits
650 +// subexpanse must count ALL JPs, to know where to START counting down, and
651 +// ALSO note the offset of digits JP to know where to STOP counting down.
652 +
653 + for (subexp = cJU_NUMSUBEXPB - 1; subexp >= findsub; --subexp)
654 + {
655 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
656 +
657 + // should always find findbit:
658 + assert((subexp > findsub) || jpcount);
659 +
660 + if (! jpcount) continue; // empty subexpanse, save time.
661 +
662 +// Count JPs below digit, inclusive:
663 +
664 + if (subexp == findsub)
665 + {
666 + jpcountbf = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp)
667 + & lowermask);
668 + }
669 +
670 + // should always find findbit:
671 + assert((subexp > findsub) || jpcountbf);
672 + assert(jpcount >= jpcountbf); // proper relationship.
673 +
674 +// Add pop1s from JPs ABOVE Index (digit):
675 +
676 + // no null JP subexp pointers:
677 + assert(BMPJP0(subexp) != (Pjp_t) NULL);
678 +
679 + for (jpnum = jpcount - 1; jpnum >= jpcountbf; --jpnum)
680 + {
681 + if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
682 + == cJU_ALLONES)
683 + {
684 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
685 + return(C_JERR);
686 + }
687 +
688 + pop1above += pop1;
689 + }
690 + // jpnum is now correct for digit.
691 + }
692 + } // else.
693 +
694 +// Return the net population ABOVE the digits JP at this state (in this JBB)
695 +// plus the population AT OR ABOVE Index in the SM under the digits JP:
696 +
697 + pop1 = j__udy1LCountSM(BMPJP(findsub, jpnum), Index, Pjpm);
698 + if (pop1 == C_JERR) return(C_JERR); // pass error up.
699 +
700 + assert(pop1above + pop1);
701 + return(pop1above + pop1);
702 +
703 + } // case.
704 +
705 +
706 +// ----------------------------------------------------------------------------
707 +// UNCOMPRESSED BRANCH; count populations in JPs in the JBU ABOVE the next
708 +// digit in Index, and recurse for the next digit in Index:
709 +//
710 +// Note: If the remainder of Index is zero, pop1above is the pop1 of the
711 +// entire expanse and theres no point in recursing to lower levels; but this
712 +// should be so rare that its not worth checking for;
713 +// Judy1Count()/JudyLCount() never even calls the motor for Index == 0 (all
714 +// bytes).
715 +
716 + case cJU_JPBRANCH_U2: CHECKDCD(Pjp, 2); PREPB(Pjp, 2, BranchU);
717 + case cJU_JPBRANCH_U3: CHECKDCD(Pjp, 3); PREPB(Pjp, 3, BranchU);
718 +#ifdef JU_64BIT
719 + case cJU_JPBRANCH_U4: CHECKDCD(Pjp, 4); PREPB(Pjp, 4, BranchU);
720 + case cJU_JPBRANCH_U5: CHECKDCD(Pjp, 5); PREPB(Pjp, 5, BranchU);
721 + case cJU_JPBRANCH_U6: CHECKDCD(Pjp, 6); PREPB(Pjp, 6, BranchU);
722 + case cJU_JPBRANCH_U7: CHECKDCD(Pjp, 7); PREPB(Pjp, 7, BranchU);
723 +#endif
724 + case cJU_JPBRANCH_U: PREPB_ROOT(Pjp, BranchU);
725 +
726 +// Common code (state-independent) for all cases of uncompressed branches:
727 +
728 +BranchU:
729 + Pjbu = P_JBU(Pjp->jp_Addr);
730 +
731 +#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
732 +
733 +// FIGURE OUT WHICH WAY CAUSES FEWER CACHE LINE FILLS; adding the JPs above
734 +// Indexs JP, or subtracting the JPs below Indexs JP.
735 +//
736 +// COUNT UPWARD, subtracting the pop1 of each JP BELOW OR AT Index, from the
737 +// whole expanses pop1:
738 +
739 + if (digit < (cJU_BRANCHUNUMJPS / 2))
740 + {
741 + pop1above = pop1; // subtract JPs below Index.
742 +#ifdef SMARTMETRICS
743 + ++jbu_upward;
744 +#endif
745 + for (jpnum = 0; jpnum <= digit; ++jpnum)
746 + {
747 + if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
748 + continue; // shortcut, save a function call.
749 +
750 + if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
751 + == cJU_ALLONES)
752 + {
753 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
754 + return(C_JERR);
755 + }
756 +
757 + pop1above -= pop1;
758 + }
759 + }
760 +
761 +// COUNT DOWNWARD, simply adding the pop1 of each JP ABOVE Index:
762 +
763 + else
764 +#endif // NOSMARTJBU
765 + {
766 + assert(digit < cJU_BRANCHUNUMJPS);
767 +#ifdef SMARTMETRICS
768 + ++jbu_downward;
769 +#endif
770 + pop1above = 0; // add JPs above Index.
771 +
772 + for (jpnum = cJU_BRANCHUNUMJPS - 1; jpnum > digit; --jpnum)
773 + {
774 + if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
775 + continue; // shortcut, save a function call.
776 +
777 + if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
778 + == cJU_ALLONES)
779 + {
780 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
781 + return(C_JERR);
782 + }
783 +
784 + pop1above += pop1;
785 + }
786 + }
787 +
788 + if ((pop1 = j__udy1LCountSM(Pjbu->jbu_jp + digit, Index, Pjpm))
789 + == C_JERR) return(C_JERR); // pass error up.
790 +
791 + assert(pop1above + pop1);
792 + return(pop1above + pop1);
793 +
794 +
795 +// ----------------------------------------------------------------------------
796 +// LEAF COUNT MACROS:
797 +//
798 +// LEAF*ABOVE() are common code for different JP types (linear leaves, bitmap
799 +// leaves, and immediates) and different leaf Index Sizes, which result in
800 +// calling different leaf search functions. Linear leaves get the leaf address
801 +// from jp_Addr and the Population from jp_DcdPopO, while immediates use Pjp
802 +// itself as the leaf address and get Population from jp_Type.
803 +
804 +#define LEAFLABOVE(Func) \
805 + Pjll = P_JLL(Pjp->jp_Addr); \
806 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
807 + LEAFABOVE(Func, Pjll, pop1)
808 +
809 +#define LEAFB1ABOVE(Func) LEAFLABOVE(Func) // different Func, otherwise same.
810 +
811 +#ifdef JUDY1
812 +#define IMMABOVE(Func,Pop1) \
813 + Pjll = (Pjll_t) Pjp; \
814 + LEAFABOVE(Func, Pjll, Pop1)
815 +#else
816 +// Note: For JudyL immediates with >= 2 Indexes, the index bytes are in a
817 +// different place than for Judy1:
818 +
819 +#define IMMABOVE(Func,Pop1) \
820 + LEAFABOVE(Func, (Pjll_t) (Pjp->jp_LIndex), Pop1)
821 +#endif
822 +
823 +// For all leaf types, the population AT OR ABOVE is the total pop1 less the
824 +// offset of Index; and Index should always be found:
825 +
826 +#define LEAFABOVE(Func,Pjll,Pop1) \
827 + offset = Func(Pjll, Pop1, Index); \
828 + assert(offset >= 0); \
829 + assert(offset < (Pop1)); \
830 + return((Pop1) - offset)
831 +
832 +// IMMABOVE_01 handles the special case of an immediate JP with 1 index, which
833 +// the search functions arent used for anyway:
834 +//
835 +// The target Index should be the one in this Immediate, in which case the
836 +// count above (inclusive) is always 1.
837 +
838 +#define IMMABOVE_01 \
839 + assert((JU_JPDCDPOP0(Pjp)) == JU_TRIMTODCDSIZE(Index)); \
840 + return(1)
841 +
842 +
843 +// ----------------------------------------------------------------------------
844 +// LINEAR LEAF; search the leaf for Index; size is computed from jp_Type:
845 +
846 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
847 + case cJU_JPLEAF1: LEAFLABOVE(j__udySearchLeaf1);
848 +#endif
849 + case cJU_JPLEAF2: LEAFLABOVE(j__udySearchLeaf2);
850 + case cJU_JPLEAF3: LEAFLABOVE(j__udySearchLeaf3);
851 +
852 +#ifdef JU_64BIT
853 + case cJU_JPLEAF4: LEAFLABOVE(j__udySearchLeaf4);
854 + case cJU_JPLEAF5: LEAFLABOVE(j__udySearchLeaf5);
855 + case cJU_JPLEAF6: LEAFLABOVE(j__udySearchLeaf6);
856 + case cJU_JPLEAF7: LEAFLABOVE(j__udySearchLeaf7);
857 +#endif
858 +
859 +
860 +// ----------------------------------------------------------------------------
861 +// BITMAP LEAF; search the leaf for Index:
862 +//
863 +// Since the bitmap describes Indexes digitally rather than linearly, this is
864 +// not really a search, but just a count.
865 +
866 + case cJU_JPLEAF_B1: LEAFB1ABOVE(j__udyCountLeafB1);
867 +
868 +
869 +#ifdef JUDY1
870 +// ----------------------------------------------------------------------------
871 +// FULL POPULATION:
872 +//
873 +// Return the count of Indexes AT OR ABOVE Index, which is the total population
874 +// of the expanse (a constant) less the value of the undecoded digit remaining
875 +// in Index (its base-0 offset in the expanse), which yields an inclusive count
876 +// above.
877 +//
878 +// TBD: This only supports a 1-byte full expanse. Should this extract a
879 +// stored value for pop0 and possibly more LSBs of Index, to handle larger full
880 +// expanses?
881 +
882 + case cJ1_JPFULLPOPU1:
883 + return(cJU_JPFULLPOPU1_POP0 + 1 - JU_DIGITATSTATE(Index, 1));
884 +#endif
885 +
886 +
887 +// ----------------------------------------------------------------------------
888 +// IMMEDIATE:
889 +
890 + case cJU_JPIMMED_1_01: IMMABOVE_01;
891 + case cJU_JPIMMED_2_01: IMMABOVE_01;
892 + case cJU_JPIMMED_3_01: IMMABOVE_01;
893 +#ifdef JU_64BIT
894 + case cJU_JPIMMED_4_01: IMMABOVE_01;
895 + case cJU_JPIMMED_5_01: IMMABOVE_01;
896 + case cJU_JPIMMED_6_01: IMMABOVE_01;
897 + case cJU_JPIMMED_7_01: IMMABOVE_01;
898 +#endif
899 +
900 + case cJU_JPIMMED_1_02: IMMABOVE(j__udySearchLeaf1, 2);
901 + case cJU_JPIMMED_1_03: IMMABOVE(j__udySearchLeaf1, 3);
902 +#if (defined(JUDY1) || defined(JU_64BIT))
903 + case cJU_JPIMMED_1_04: IMMABOVE(j__udySearchLeaf1, 4);
904 + case cJU_JPIMMED_1_05: IMMABOVE(j__udySearchLeaf1, 5);
905 + case cJU_JPIMMED_1_06: IMMABOVE(j__udySearchLeaf1, 6);
906 + case cJU_JPIMMED_1_07: IMMABOVE(j__udySearchLeaf1, 7);
907 +#endif
908 +#if (defined(JUDY1) && defined(JU_64BIT))
909 + case cJ1_JPIMMED_1_08: IMMABOVE(j__udySearchLeaf1, 8);
910 + case cJ1_JPIMMED_1_09: IMMABOVE(j__udySearchLeaf1, 9);
911 + case cJ1_JPIMMED_1_10: IMMABOVE(j__udySearchLeaf1, 10);
912 + case cJ1_JPIMMED_1_11: IMMABOVE(j__udySearchLeaf1, 11);
913 + case cJ1_JPIMMED_1_12: IMMABOVE(j__udySearchLeaf1, 12);
914 + case cJ1_JPIMMED_1_13: IMMABOVE(j__udySearchLeaf1, 13);
915 + case cJ1_JPIMMED_1_14: IMMABOVE(j__udySearchLeaf1, 14);
916 + case cJ1_JPIMMED_1_15: IMMABOVE(j__udySearchLeaf1, 15);
917 +#endif
918 +
919 +#if (defined(JUDY1) || defined(JU_64BIT))
920 + case cJU_JPIMMED_2_02: IMMABOVE(j__udySearchLeaf2, 2);
921 + case cJU_JPIMMED_2_03: IMMABOVE(j__udySearchLeaf2, 3);
922 +#endif
923 +#if (defined(JUDY1) && defined(JU_64BIT))
924 + case cJ1_JPIMMED_2_04: IMMABOVE(j__udySearchLeaf2, 4);
925 + case cJ1_JPIMMED_2_05: IMMABOVE(j__udySearchLeaf2, 5);
926 + case cJ1_JPIMMED_2_06: IMMABOVE(j__udySearchLeaf2, 6);
927 + case cJ1_JPIMMED_2_07: IMMABOVE(j__udySearchLeaf2, 7);
928 +#endif
929 +
930 +#if (defined(JUDY1) || defined(JU_64BIT))
931 + case cJU_JPIMMED_3_02: IMMABOVE(j__udySearchLeaf3, 2);
932 +#endif
933 +#if (defined(JUDY1) && defined(JU_64BIT))
934 + case cJ1_JPIMMED_3_03: IMMABOVE(j__udySearchLeaf3, 3);
935 + case cJ1_JPIMMED_3_04: IMMABOVE(j__udySearchLeaf3, 4);
936 + case cJ1_JPIMMED_3_05: IMMABOVE(j__udySearchLeaf3, 5);
937 +
938 + case cJ1_JPIMMED_4_02: IMMABOVE(j__udySearchLeaf4, 2);
939 + case cJ1_JPIMMED_4_03: IMMABOVE(j__udySearchLeaf4, 3);
940 +
941 + case cJ1_JPIMMED_5_02: IMMABOVE(j__udySearchLeaf5, 2);
942 + case cJ1_JPIMMED_5_03: IMMABOVE(j__udySearchLeaf5, 3);
943 +
944 + case cJ1_JPIMMED_6_02: IMMABOVE(j__udySearchLeaf6, 2);
945 +
946 + case cJ1_JPIMMED_7_02: IMMABOVE(j__udySearchLeaf7, 2);
947 +#endif
948 +
949 +
950 +// ----------------------------------------------------------------------------
951 +// OTHER CASES:
952 +
953 + default: JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT); return(C_JERR);
954 +
955 + } // switch on JP type
956 +
957 + /*NOTREACHED*/
958 +
959 +} // j__udy1LCountSM()
960 +
961 +
962 +// ****************************************************************************
963 +// J U D Y C O U N T L E A F B 1
964 +//
965 +// This is a private analog of the j__udySearchLeaf*() functions for counting
966 +// in bitmap 1-byte leaves. Since a bitmap leaf describes Indexes digitally
967 +// rather than linearly, this is not really a search, but just a count of the
968 +// valid Indexes == set bits below or including Index, which should be valid.
969 +// Return the "offset" (really the ordinal), 0 .. Pop1 - 1, of Index in Pjll;
970 +// if Indexs bit is not set (which should never happen, so this is DEBUG-mode
971 +// only), return the 1s-complement equivalent (== negative offset minus 1).
972 +//
973 +// Note: The source code for this function looks identical for both Judy1 and
974 +// JudyL, but the JU_JLB_BITMAP macro varies.
975 +//
976 +// Note: For simpler calling, the first arg is of type Pjll_t but then cast to
977 +// Pjlb_t.
978 +
979 +FUNCTION static int j__udyCountLeafB1(
980 +const Pjll_t Pjll, // bitmap leaf, as Pjll_t for consistency.
981 +const Word_t Pop1, // Population of whole leaf.
982 +const Word_t Index) // to which to count.
983 +{
984 + Pjlb_t Pjlb = (Pjlb_t) Pjll; // to proper type.
985 + Word_t digit = Index & cJU_MASKATSTATE(1);
986 + Word_t findsub = digit / cJU_BITSPERSUBEXPL;
987 + Word_t findbit = digit % cJU_BITSPERSUBEXPL;
988 + int count; // in leaf through Index.
989 + long subexp; // for stepping through subexpanses.
990 +
991 +
992 +// COUNT UPWARD:
993 +//
994 +// The entire bitmap should fit in one cache line, but still try to save some
995 +// CPU time by counting the fewest possible number of subexpanses from the
996 +// bitmap.
997 +
998 +#ifndef NOSMARTJLB // enable to turn off smart code for comparison purposes.
999 +
1000 + if (findsub < (cJU_NUMSUBEXPL / 2))
1001 + {
1002 +#ifdef SMARTMETRICS
1003 + ++jlb_upward;
1004 +#endif
1005 + count = 0;
1006 +
1007 + for (subexp = 0; subexp < findsub; ++subexp)
1008 + {
1009 + count += ((JU_JLB_BITMAP(Pjlb, subexp) == cJU_FULLBITMAPL) ?
1010 + cJU_BITSPERSUBEXPL :
1011 + j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp)));
1012 + }
1013 +
1014 +// This count includes findbit, which should be set, resulting in a base-1
1015 +// offset:
1016 +
1017 + count += j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, findsub)
1018 + & JU_MASKLOWERINC(JU_BITPOSMASKL(findbit)));
1019 +
1020 + DBGCODE(if (! JU_BITMAPTESTL(Pjlb, digit)) return(~count);)
1021 + assert(count >= 1);
1022 + return(count - 1); // convert to base-0 offset.
1023 + }
1024 +#endif // NOSMARTJLB
1025 +
1026 +
1027 +// COUNT DOWNWARD:
1028 +//
1029 +// Count the valid Indexes above or at Index, and subtract from Pop1.
1030 +
1031 +#ifdef SMARTMETRICS
1032 + ++jlb_downward;
1033 +#endif
1034 + count = Pop1; // base-1 for now.
1035 +
1036 + for (subexp = cJU_NUMSUBEXPL - 1; subexp > findsub; --subexp)
1037 + {
1038 + count -= ((JU_JLB_BITMAP(Pjlb, subexp) == cJU_FULLBITMAPL) ?
1039 + cJU_BITSPERSUBEXPL :
1040 + j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp)));
1041 + }
1042 +
1043 +// This count includes findbit, which should be set, resulting in a base-0
1044 +// offset:
1045 +
1046 + count -= j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, findsub)
1047 + & JU_MASKHIGHERINC(JU_BITPOSMASKL(findbit)));
1048 +
1049 + DBGCODE(if (! JU_BITMAPTESTL(Pjlb, digit)) return(~count);)
1050 + assert(count >= 0); // should find Index itself.
1051 + return(count); // is already a base-0 offset.
1052 +
1053 +} // j__udyCountLeafB1()
1054 +
1055 +
1056 +// ****************************************************************************
1057 +// J U D Y J P P O P 1
1058 +//
1059 +// This function takes any type of JP other than a root-level JP (cJU_LEAFW* or
1060 +// cJU_JPBRANCH* with no number suffix) and extracts the Pop1 from it. In some
1061 +// sense this is a wrapper around the JU_JP*_POP0 macros. Why write it as a
1062 +// function instead of a complex macro containing a trinary? (See version
1063 +// Judy1.h version 4.17.) We think its cheaper to call a function containing
1064 +// a switch statement with "constant" cases than to do the variable
1065 +// calculations in a trinary.
1066 +//
1067 +// For invalid JP Types return cJU_ALLONES. Note that this is an impossibly
1068 +// high Pop1 for any JP below a top level branch.
1069 +
1070 +FUNCTION Word_t j__udyJPPop1(
1071 +const Pjp_t Pjp) // JP to count.
1072 +{
1073 + switch (JU_JPTYPE(Pjp))
1074 + {
1075 +#ifdef notdef // caller should shortcut and not even call with these:
1076 +
1077 + case cJU_JPNULL1:
1078 + case cJU_JPNULL2:
1079 + case cJU_JPNULL3: return(0);
1080 +#ifdef JU_64BIT
1081 + case cJU_JPNULL4:
1082 + case cJU_JPNULL5:
1083 + case cJU_JPNULL6:
1084 + case cJU_JPNULL7: return(0);
1085 +#endif
1086 +#endif // notdef
1087 +
1088 + case cJU_JPBRANCH_L2:
1089 + case cJU_JPBRANCH_B2:
1090 + case cJU_JPBRANCH_U2: return(JU_JPBRANCH_POP0(Pjp,2) + 1);
1091 +
1092 + case cJU_JPBRANCH_L3:
1093 + case cJU_JPBRANCH_B3:
1094 + case cJU_JPBRANCH_U3: return(JU_JPBRANCH_POP0(Pjp,3) + 1);
1095 +
1096 +#ifdef JU_64BIT
1097 + case cJU_JPBRANCH_L4:
1098 + case cJU_JPBRANCH_B4:
1099 + case cJU_JPBRANCH_U4: return(JU_JPBRANCH_POP0(Pjp,4) + 1);
1100 +
1101 + case cJU_JPBRANCH_L5:
1102 + case cJU_JPBRANCH_B5:
1103 + case cJU_JPBRANCH_U5: return(JU_JPBRANCH_POP0(Pjp,5) + 1);
1104 +
1105 + case cJU_JPBRANCH_L6:
1106 + case cJU_JPBRANCH_B6:
1107 + case cJU_JPBRANCH_U6: return(JU_JPBRANCH_POP0(Pjp,6) + 1);
1108 +
1109 + case cJU_JPBRANCH_L7:
1110 + case cJU_JPBRANCH_B7:
1111 + case cJU_JPBRANCH_U7: return(JU_JPBRANCH_POP0(Pjp,7) + 1);
1112 +#endif
1113 +
1114 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1115 + case cJU_JPLEAF1:
1116 +#endif
1117 + case cJU_JPLEAF2:
1118 + case cJU_JPLEAF3:
1119 +#ifdef JU_64BIT
1120 + case cJU_JPLEAF4:
1121 + case cJU_JPLEAF5:
1122 + case cJU_JPLEAF6:
1123 + case cJU_JPLEAF7:
1124 +#endif
1125 + case cJU_JPLEAF_B1: return(JU_JPLEAF_POP0(Pjp) + 1);
1126 +
1127 +#ifdef JUDY1
1128 + case cJ1_JPFULLPOPU1: return(cJU_JPFULLPOPU1_POP0 + 1);
1129 +#endif
1130 +
1131 + case cJU_JPIMMED_1_01:
1132 + case cJU_JPIMMED_2_01:
1133 + case cJU_JPIMMED_3_01: return(1);
1134 +#ifdef JU_64BIT
1135 + case cJU_JPIMMED_4_01:
1136 + case cJU_JPIMMED_5_01:
1137 + case cJU_JPIMMED_6_01:
1138 + case cJU_JPIMMED_7_01: return(1);
1139 +#endif
1140 +
1141 + case cJU_JPIMMED_1_02: return(2);
1142 + case cJU_JPIMMED_1_03: return(3);
1143 +#if (defined(JUDY1) || defined(JU_64BIT))
1144 + case cJU_JPIMMED_1_04: return(4);
1145 + case cJU_JPIMMED_1_05: return(5);
1146 + case cJU_JPIMMED_1_06: return(6);
1147 + case cJU_JPIMMED_1_07: return(7);
1148 +#endif
1149 +#if (defined(JUDY1) && defined(JU_64BIT))
1150 + case cJ1_JPIMMED_1_08: return(8);
1151 + case cJ1_JPIMMED_1_09: return(9);
1152 + case cJ1_JPIMMED_1_10: return(10);
1153 + case cJ1_JPIMMED_1_11: return(11);
1154 + case cJ1_JPIMMED_1_12: return(12);
1155 + case cJ1_JPIMMED_1_13: return(13);
1156 + case cJ1_JPIMMED_1_14: return(14);
1157 + case cJ1_JPIMMED_1_15: return(15);
1158 +#endif
1159 +
1160 +#if (defined(JUDY1) || defined(JU_64BIT))
1161 + case cJU_JPIMMED_2_02: return(2);
1162 + case cJU_JPIMMED_2_03: return(3);
1163 +#endif
1164 +#if (defined(JUDY1) && defined(JU_64BIT))
1165 + case cJ1_JPIMMED_2_04: return(4);
1166 + case cJ1_JPIMMED_2_05: return(5);
1167 + case cJ1_JPIMMED_2_06: return(6);
1168 + case cJ1_JPIMMED_2_07: return(7);
1169 +#endif
1170 +
1171 +#if (defined(JUDY1) || defined(JU_64BIT))
1172 + case cJU_JPIMMED_3_02: return(2);
1173 +#endif
1174 +#if (defined(JUDY1) && defined(JU_64BIT))
1175 + case cJ1_JPIMMED_3_03: return(3);
1176 + case cJ1_JPIMMED_3_04: return(4);
1177 + case cJ1_JPIMMED_3_05: return(5);
1178 +
1179 + case cJ1_JPIMMED_4_02: return(2);
1180 + case cJ1_JPIMMED_4_03: return(3);
1181 +
1182 + case cJ1_JPIMMED_5_02: return(2);
1183 + case cJ1_JPIMMED_5_03: return(3);
1184 +
1185 + case cJ1_JPIMMED_6_02: return(2);
1186 +
1187 + case cJ1_JPIMMED_7_02: return(2);
1188 +#endif
1189 +
1190 + default: return(cJU_ALLONES);
1191 + }
1192 +
1193 + /*NOTREACHED*/
1194 +
1195 +} // j__udyJPPop1()
libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c new
+314
@@ -0,0 +1,314 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.26 $ $Source: /judy/src/JudyCommon/JudyCreateBranch.c $
19 +
20 +// Branch creation functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +
36 +// ****************************************************************************
37 +// J U D Y C R E A T E B R A N C H L
38 +//
39 +// Build a BranchL from an array of JPs and associated 1 byte digits
40 +// (expanses). Return with Pjp pointing to the BranchL. Caller must
41 +// deallocate passed arrays, if necessary.
42 +//
43 +// We have no idea what kind of BranchL it is, so caller must set the jp_Type.
44 +//
45 +// Return -1 if error (details in Pjpm), otherwise return 1.
46 +
47 +FUNCTION int j__udyCreateBranchL(
48 + Pjp_t Pjp, // Build JPs from this place
49 + Pjp_t PJPs, // Array of JPs to put into Bitmap branch
50 + uint8_t Exp[], // Array of expanses to put into bitmap
51 + Word_t ExpCnt, // Number of above JPs and Expanses
52 + Pvoid_t Pjpm)
53 +{
54 + Pjbl_t PjblRaw; // pointer to linear branch.
55 + Pjbl_t Pjbl;
56 +
57 + assert(ExpCnt <= cJU_BRANCHLMAXJPS);
58 +
59 + PjblRaw = j__udyAllocJBL(Pjpm);
60 + if (PjblRaw == (Pjbl_t) NULL) return(-1);
61 + Pjbl = P_JBL(PjblRaw);
62 +
63 +// Build a Linear Branch
64 + Pjbl->jbl_NumJPs = ExpCnt;
65 +
66 +// Copy from the Linear branch from splayed leaves
67 + JU_COPYMEM(Pjbl->jbl_Expanse, Exp, ExpCnt);
68 + JU_COPYMEM(Pjbl->jbl_jp, PJPs, ExpCnt);
69 +
70 +// Pass back new pointer to the Linear branch in JP
71 + Pjp->jp_Addr = (Word_t) PjblRaw;
72 +
73 + return(1);
74 +
75 +} // j__udyCreateBranchL()
76 +
77 +
78 +// ****************************************************************************
79 +// J U D Y C R E A T E B R A N C H B
80 +//
81 +// Build a BranchB from an array of JPs and associated 1 byte digits
82 +// (expanses). Return with Pjp pointing to the BranchB. Caller must
83 +// deallocate passed arrays, if necessary.
84 +//
85 +// We have no idea what kind of BranchB it is, so caller must set the jp_Type.
86 +//
87 +// Return -1 if error (details in Pjpm), otherwise return 1.
88 +
89 +FUNCTION int j__udyCreateBranchB(
90 + Pjp_t Pjp, // Build JPs from this place
91 + Pjp_t PJPs, // Array of JPs to put into Bitmap branch
92 + uint8_t Exp[], // Array of expanses to put into bitmap
93 + Word_t ExpCnt, // Number of above JPs and Expanses
94 + Pvoid_t Pjpm)
95 +{
96 + Pjbb_t PjbbRaw; // pointer to bitmap branch.
97 + Pjbb_t Pjbb;
98 + Word_t ii, jj; // Temps
99 + uint8_t CurrSubExp; // Current sub expanse for BM
100 +
101 +// This assertion says the number of populated subexpanses is not too large.
102 +// This function is only called when a BranchL overflows to a BranchB or when a
103 +// cascade occurs, meaning a leaf overflows. Either way ExpCnt cant be very
104 +// large, in fact a lot smaller than cJU_BRANCHBMAXJPS. (Otherwise a BranchU
105 +// would be used.) Popping this assertion means something (unspecified) has
106 +// gone very wrong, or else Judys design criteria have changed, although in
107 +// fact there should be no HARM in creating a BranchB with higher actual
108 +// fanout.
109 +
110 + assert(ExpCnt <= cJU_BRANCHBMAXJPS);
111 +
112 +// Get memory for a Bitmap branch
113 + PjbbRaw = j__udyAllocJBB(Pjpm);
114 + if (PjbbRaw == (Pjbb_t) NULL) return(-1);
115 + Pjbb = P_JBB(PjbbRaw);
116 +
117 +// Get 1st "sub" expanse (0..7) of bitmap branch
118 + CurrSubExp = Exp[0] / cJU_BITSPERSUBEXPB;
119 +
120 +// Index thru all 1 byte sized expanses:
121 +
122 + for (jj = ii = 0; ii <= ExpCnt; ii++)
123 + {
124 + Word_t SubExp; // Cannot be a uint8_t
125 +
126 +// Make sure we cover the last one
127 + if (ii == ExpCnt)
128 + {
129 + SubExp = cJU_ALLONES; // Force last one
130 + }
131 + else
132 + {
133 +// Calculate the "sub" expanse of the byte expanse
134 + SubExp = Exp[ii] / cJU_BITSPERSUBEXPB; // Bits 5..7.
135 +
136 +// Set the bit that represents the expanse in Exp[]
137 + JU_JBB_BITMAP(Pjbb, SubExp) |= JU_BITPOSMASKB(Exp[ii]);
138 + }
139 +// Check if a new "sub" expanse range needed
140 + if (SubExp != CurrSubExp)
141 + {
142 +// Get number of JPs in this sub expanse
143 + Word_t NumJP = ii - jj;
144 + Pjp_t PjpRaw;
145 + Pjp_t Pjp;
146 +
147 + PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm);
148 + Pjp = P_JP(PjpRaw);
149 +
150 + if (PjpRaw == (Pjp_t) NULL) // out of memory.
151 + {
152 +
153 +// Free any previous allocations:
154 +
155 + while(CurrSubExp--)
156 + {
157 + NumJP = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,
158 + CurrSubExp));
159 + if (NumJP)
160 + {
161 + j__udyFreeJBBJP(JU_JBB_PJP(Pjbb,
162 + CurrSubExp), NumJP, Pjpm);
163 + }
164 + }
165 + j__udyFreeJBB(PjbbRaw, Pjpm);
166 + return(-1);
167 + }
168 +
169 +// Place the array of JPs in bitmap branch:
170 +
171 + JU_JBB_PJP(Pjbb, CurrSubExp) = PjpRaw;
172 +
173 +// Copy the JPs to new leaf:
174 +
175 + JU_COPYMEM(Pjp, PJPs + jj, NumJP);
176 +
177 +// On to the next bitmap branch "sub" expanse:
178 +
179 + jj = ii;
180 + CurrSubExp = SubExp;
181 + }
182 + } // for each 1-byte expanse
183 +
184 +// Pass back some of the JP to the new Bitmap branch:
185 +
186 + Pjp->jp_Addr = (Word_t) PjbbRaw;
187 +
188 + return(1);
189 +
190 +} // j__udyCreateBranchB()
191 +
192 +
193 +// ****************************************************************************
194 +// J U D Y C R E A T E B R A N C H U
195 +//
196 +// Build a BranchU from a BranchB. Return with Pjp pointing to the BranchU.
197 +// Free the BranchB and its JP subarrays.
198 +//
199 +// Return -1 if error (details in Pjpm), otherwise return 1.
200 +
201 +FUNCTION int j__udyCreateBranchU(
202 + Pjp_t Pjp,
203 + Pvoid_t Pjpm)
204 +{
205 + jp_t JPNull;
206 + Pjbu_t PjbuRaw;
207 + Pjbu_t Pjbu;
208 + Pjbb_t PjbbRaw;
209 + Pjbb_t Pjbb;
210 + Word_t ii, jj;
211 + BITMAPB_t BitMap;
212 + Pjp_t PDstJP;
213 +#ifdef JU_STAGED_EXP
214 + jbu_t BranchU; // Staged uncompressed branch
215 +#else
216 +
217 +// Allocate memory for a BranchU:
218 +
219 + PjbuRaw = j__udyAllocJBU(Pjpm);
220 + if (PjbuRaw == (Pjbu_t) NULL) return(-1);
221 + Pjbu = P_JBU(PjbuRaw);
222 +#endif
223 + JU_JPSETADT(&JPNull, 0, 0, JU_JPTYPE(Pjp) - cJU_JPBRANCH_B2 + cJU_JPNULL1);
224 +
225 +// Get the pointer to the BranchB:
226 +
227 + PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
228 + Pjbb = P_JBB(PjbbRaw);
229 +
230 +// Set the pointer to the Uncompressed branch
231 +#ifdef JU_STAGED_EXP
232 + PDstJP = BranchU.jbu_jp;
233 +#else
234 + PDstJP = Pjbu->jbu_jp;
235 +#endif
236 + for (ii = 0; ii < cJU_NUMSUBEXPB; ii++)
237 + {
238 + Pjp_t PjpA;
239 + Pjp_t PjpB;
240 +
241 + PjpB = PjpA = P_JP(JU_JBB_PJP(Pjbb, ii));
242 +
243 +// Get the bitmap for this subexpanse
244 + BitMap = JU_JBB_BITMAP(Pjbb, ii);
245 +
246 +// NULL empty subexpanses
247 + if (BitMap == 0)
248 + {
249 +// But, fill with NULLs
250 + for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
251 + {
252 + PDstJP[jj] = JPNull;
253 + }
254 + PDstJP += cJU_BITSPERSUBEXPB;
255 + continue;
256 + }
257 +// Check if Uncompressed subexpanse
258 + if (BitMap == cJU_FULLBITMAPB)
259 + {
260 +// Copy subexpanse to the Uncompressed branch intact
261 + JU_COPYMEM(PDstJP, PjpA, cJU_BITSPERSUBEXPB);
262 +
263 +// Bump to next subexpanse
264 + PDstJP += cJU_BITSPERSUBEXPB;
265 +
266 +// Set length of subexpanse
267 + jj = cJU_BITSPERSUBEXPB;
268 + }
269 + else
270 + {
271 + for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
272 + {
273 +// Copy JP or NULLJP depending on bit
274 + if (BitMap & 1) { *PDstJP = *PjpA++; }
275 + else { *PDstJP = JPNull; }
276 +
277 + PDstJP++; // advance to next JP
278 + BitMap >>= 1;
279 + }
280 + jj = PjpA - PjpB;
281 + }
282 +
283 +// Free the subexpanse:
284 +
285 + j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, ii), jj, Pjpm);
286 +
287 + } // for each JP in BranchU
288 +
289 +#ifdef JU_STAGED_EXP
290 +
291 +// Allocate memory for a BranchU:
292 +
293 + PjbuRaw = j__udyAllocJBU(Pjpm);
294 + if (PjbuRaw == (Pjbu_t) NULL) return(-1);
295 + Pjbu = P_JBU(PjbuRaw);
296 +
297 +// Copy staged branch to newly allocated branch:
298 +//
299 +// TBD: I think this code is broken.
300 +
301 + *Pjbu = BranchU;
302 +
303 +#endif // JU_STAGED_EXP
304 +
305 +// Finally free the BranchB and put the BranchU in its place:
306 +
307 + j__udyFreeJBB(PjbbRaw, Pjpm);
308 +
309 + Pjp->jp_Addr = (Word_t) PjbuRaw;
310 + Pjp->jp_Type += cJU_JPBRANCH_U - cJU_JPBRANCH_B;
311 +
312 + return(1);
313 +
314 +} // j__udyCreateBranchU()
libnetdata/libjudy/src/JudyL/JudyLDecascade.c new
+1206
@@ -0,0 +1,1206 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.25 $ $Source: /judy/src/JudyCommon/JudyDecascade.c $
19 +//
20 +// "Decascade" support functions for JudyDel.c: These functions convert
21 +// smaller-index-size leaves to larger-index-size leaves, and also, bitmap
22 +// leaves (LeafB1s) to Leaf1s, and some types of branches to smaller branches
23 +// at the same index size. Some "decascading" occurs explicitly in JudyDel.c,
24 +// but rare or large subroutines appear as functions here, and the overhead to
25 +// call them is negligible.
26 +//
27 +// Compile with one of -DJUDY1 or -DJUDYL. Note: Function names are converted
28 +// to Judy1 or JudyL specific values by external #defines.
29 +
30 +#if (! (defined(JUDY1) || defined(JUDYL)))
31 +#error: One of -DJUDY1 or -DJUDYL must be specified.
32 +#endif
33 +
34 +#ifdef JUDY1
35 +#include "Judy1.h"
36 +#endif
37 +#ifdef JUDYL
38 +#include "JudyL.h"
39 +#endif
40 +
41 +#include "JudyPrivate1L.h"
42 +
43 +DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)
44 +
45 +
46 +// ****************************************************************************
47 +// __ J U D Y C O P Y 2 T O 3
48 +//
49 +// Copy one or more 2-byte Indexes to a series of 3-byte Indexes.
50 +
51 +FUNCTION static void j__udyCopy2to3(
52 + uint8_t * PDest, // to where to copy 3-byte Indexes.
53 + uint16_t * PSrc, // from where to copy 2-byte indexes.
54 + Word_t Pop1, // number of Indexes to copy.
55 + Word_t MSByte) // most-significant byte, prefix to each Index.
56 +{
57 + Word_t Temp; // for building 3-byte Index.
58 +
59 + assert(Pop1);
60 +
61 + do {
62 + Temp = MSByte | *PSrc++;
63 + JU_COPY3_LONG_TO_PINDEX(PDest, Temp);
64 + PDest += 3;
65 + } while (--Pop1);
66 +
67 +} // j__udyCopy2to3()
68 +
69 +
70 +#ifdef JU_64BIT
71 +
72 +// ****************************************************************************
73 +// __ J U D Y C O P Y 3 T O 4
74 +//
75 +// Copy one or more 3-byte Indexes to a series of 4-byte Indexes.
76 +
77 +FUNCTION static void j__udyCopy3to4(
78 + uint32_t * PDest, // to where to copy 4-byte Indexes.
79 + uint8_t * PSrc, // from where to copy 3-byte indexes.
80 + Word_t Pop1, // number of Indexes to copy.
81 + Word_t MSByte) // most-significant byte, prefix to each Index.
82 +{
83 + Word_t Temp; // for building 4-byte Index.
84 +
85 + assert(Pop1);
86 +
87 + do {
88 + JU_COPY3_PINDEX_TO_LONG(Temp, PSrc);
89 + Temp |= MSByte;
90 + PSrc += 3;
91 + *PDest++ = Temp; // truncates to uint32_t.
92 + } while (--Pop1);
93 +
94 +} // j__udyCopy3to4()
95 +
96 +
97 +// ****************************************************************************
98 +// __ J U D Y C O P Y 4 T O 5
99 +//
100 +// Copy one or more 4-byte Indexes to a series of 5-byte Indexes.
101 +
102 +FUNCTION static void j__udyCopy4to5(
103 + uint8_t * PDest, // to where to copy 4-byte Indexes.
104 + uint32_t * PSrc, // from where to copy 4-byte indexes.
105 + Word_t Pop1, // number of Indexes to copy.
106 + Word_t MSByte) // most-significant byte, prefix to each Index.
107 +{
108 + Word_t Temp; // for building 5-byte Index.
109 +
110 + assert(Pop1);
111 +
112 + do {
113 + Temp = MSByte | *PSrc++;
114 + JU_COPY5_LONG_TO_PINDEX(PDest, Temp);
115 + PDest += 5;
116 + } while (--Pop1);
117 +
118 +} // j__udyCopy4to5()
119 +
120 +
121 +// ****************************************************************************
122 +// __ J U D Y C O P Y 5 T O 6
123 +//
124 +// Copy one or more 5-byte Indexes to a series of 6-byte Indexes.
125 +
126 +FUNCTION static void j__udyCopy5to6(
127 + uint8_t * PDest, // to where to copy 6-byte Indexes.
128 + uint8_t * PSrc, // from where to copy 5-byte indexes.
129 + Word_t Pop1, // number of Indexes to copy.
130 + Word_t MSByte) // most-significant byte, prefix to each Index.
131 +{
132 + Word_t Temp; // for building 6-byte Index.
133 +
134 + assert(Pop1);
135 +
136 + do {
137 + JU_COPY5_PINDEX_TO_LONG(Temp, PSrc);
138 + Temp |= MSByte;
139 + JU_COPY6_LONG_TO_PINDEX(PDest, Temp);
140 + PSrc += 5;
141 + PDest += 6;
142 + } while (--Pop1);
143 +
144 +} // j__udyCopy5to6()
145 +
146 +
147 +// ****************************************************************************
148 +// __ J U D Y C O P Y 6 T O 7
149 +//
150 +// Copy one or more 6-byte Indexes to a series of 7-byte Indexes.
151 +
152 +FUNCTION static void j__udyCopy6to7(
153 + uint8_t * PDest, // to where to copy 6-byte Indexes.
154 + uint8_t * PSrc, // from where to copy 5-byte indexes.
155 + Word_t Pop1, // number of Indexes to copy.
156 + Word_t MSByte) // most-significant byte, prefix to each Index.
157 +{
158 + Word_t Temp; // for building 6-byte Index.
159 +
160 + assert(Pop1);
161 +
162 + do {
163 + JU_COPY6_PINDEX_TO_LONG(Temp, PSrc);
164 + Temp |= MSByte;
165 + JU_COPY7_LONG_TO_PINDEX(PDest, Temp);
166 + PSrc += 6;
167 + PDest += 7;
168 + } while (--Pop1);
169 +
170 +} // j__udyCopy6to7()
171 +
172 +#endif // JU_64BIT
173 +
174 +
175 +#ifndef JU_64BIT // 32-bit
176 +
177 +// ****************************************************************************
178 +// __ J U D Y C O P Y 3 T O W
179 +//
180 +// Copy one or more 3-byte Indexes to a series of longs (words, always 4-byte).
181 +
182 +FUNCTION static void j__udyCopy3toW(
183 + PWord_t PDest, // to where to copy full-word Indexes.
184 + uint8_t * PSrc, // from where to copy 3-byte indexes.
185 + Word_t Pop1, // number of Indexes to copy.
186 + Word_t MSByte) // most-significant byte, prefix to each Index.
187 +{
188 + assert(Pop1);
189 +
190 + do {
191 + JU_COPY3_PINDEX_TO_LONG(*PDest, PSrc);
192 + *PDest++ |= MSByte;
193 + PSrc += 3;
194 + } while (--Pop1);
195 +
196 +} // j__udyCopy3toW()
197 +
198 +
199 +#else // JU_64BIT
200 +
201 +// ****************************************************************************
202 +// __ J U D Y C O P Y 7 T O W
203 +//
204 +// Copy one or more 7-byte Indexes to a series of longs (words, always 8-byte).
205 +
206 +FUNCTION static void j__udyCopy7toW(
207 + PWord_t PDest, // to where to copy full-word Indexes.
208 + uint8_t * PSrc, // from where to copy 7-byte indexes.
209 + Word_t Pop1, // number of Indexes to copy.
210 + Word_t MSByte) // most-significant byte, prefix to each Index.
211 +{
212 + assert(Pop1);
213 +
214 + do {
215 + JU_COPY7_PINDEX_TO_LONG(*PDest, PSrc);
216 + *PDest++ |= MSByte;
217 + PSrc += 7;
218 + } while (--Pop1);
219 +
220 +} // j__udyCopy7toW()
221 +
222 +#endif // JU_64BIT
223 +
224 +
225 +// ****************************************************************************
226 +// __ J U D Y B R A N C H B T O B R A N C H L
227 +//
228 +// When a BranchB shrinks to have few enough JPs, call this function to convert
229 +// it to a BranchL. Return 1 for success, or -1 for failure (with details in
230 +// Pjpm).
231 +
232 +FUNCTION int j__udyBranchBToBranchL(
233 + Pjp_t Pjp, // points to BranchB to shrink.
234 + Pvoid_t Pjpm) // for global accounting.
235 +{
236 + Pjbb_t PjbbRaw; // old BranchB to shrink.
237 + Pjbb_t Pjbb;
238 + Pjbl_t PjblRaw; // new BranchL to create.
239 + Pjbl_t Pjbl;
240 + Word_t Digit; // in BranchB.
241 + Word_t NumJPs; // non-null JPs in BranchB.
242 + uint8_t Expanse[cJU_BRANCHLMAXJPS]; // for building jbl_Expanse[].
243 + Pjp_t Pjpjbl; // current JP in BranchL.
244 + Word_t SubExp; // in BranchB.
245 +
246 + assert(JU_JPTYPE(Pjp) >= cJU_JPBRANCH_B2);
247 + assert(JU_JPTYPE(Pjp) <= cJU_JPBRANCH_B);
248 +
249 + PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
250 + Pjbb = P_JBB(PjbbRaw);
251 +
252 +// Copy 1-byte subexpanse digits from BranchB to temporary buffer for BranchL,
253 +// for each bit set in the BranchB:
254 +//
255 +// TBD: The following supports variable-sized linear branches, but they are no
256 +// longer variable; this could be simplified to save the copying.
257 +//
258 +// TBD: Since cJU_BRANCHLMAXJP == 7 now, and cJU_BRANCHUNUMJPS == 256, the
259 +// following might be inefficient; is there a faster way to do it? At least
260 +// skip wholly empty subexpanses?
261 +
262 + for (NumJPs = Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
263 + {
264 + if (JU_BITMAPTESTB(Pjbb, Digit))
265 + {
266 + Expanse[NumJPs++] = Digit;
267 + assert(NumJPs <= cJU_BRANCHLMAXJPS); // required of caller.
268 + }
269 + }
270 +
271 +// Allocate and populate the BranchL:
272 +
273 + if ((PjblRaw = j__udyAllocJBL(Pjpm)) == (Pjbl_t) NULL) return(-1);
274 + Pjbl = P_JBL(PjblRaw);
275 +
276 + JU_COPYMEM(Pjbl->jbl_Expanse, Expanse, NumJPs);
277 +
278 + Pjbl->jbl_NumJPs = NumJPs;
279 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjbl->jbl_Expanse), NumJPs, 1);)
280 +
281 +// Copy JPs from each BranchB subexpanse subarray:
282 +
283 + Pjpjbl = P_JP(Pjbl->jbl_jp); // start at first JP in array.
284 +
285 + for (SubExp = 0; SubExp < cJU_NUMSUBEXPB; ++SubExp)
286 + {
287 + Pjp_t PjpRaw = JU_JBB_PJP(Pjbb, SubExp); // current Pjp.
288 + Pjp_t Pjp;
289 +
290 + if (PjpRaw == (Pjp_t) NULL) continue; // skip empty subexpanse.
291 + Pjp = P_JP(PjpRaw);
292 +
293 + NumJPs = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, SubExp));
294 + assert(NumJPs);
295 + JU_COPYMEM(Pjpjbl, Pjp, NumJPs); // one subarray at a time.
296 +
297 + Pjpjbl += NumJPs;
298 + j__udyFreeJBBJP(PjpRaw, NumJPs, Pjpm); // subarray.
299 + }
300 + j__udyFreeJBB(PjbbRaw, Pjpm); // BranchB itself.
301 +
302 +// Finish up: Calculate new JP type (same index size = level in new class),
303 +// and tie new BranchB into parent JP:
304 +
305 + Pjp->jp_Type += cJU_JPBRANCH_L - cJU_JPBRANCH_B;
306 + Pjp->jp_Addr = (Word_t) PjblRaw;
307 +
308 + return(1);
309 +
310 +} // j__udyBranchBToBranchL()
311 +
312 +
313 +#ifdef notdef
314 +
315 +// ****************************************************************************
316 +// __ J U D Y B R A N C H U T O B R A N C H B
317 +//
318 +// When a BranchU shrinks to need little enough memory, call this function to
319 +// convert it to a BranchB to save memory (at the cost of some speed). Return
320 +// 1 for success, or -1 for failure (with details in Pjpm).
321 +//
322 +// TBD: Fill out if/when needed. Not currently used in JudyDel.c for reasons
323 +// explained there.
324 +
325 +FUNCTION int j__udyBranchUToBranchB(
326 + Pjp_t Pjp, // points to BranchU to shrink.
327 + Pvoid_t Pjpm) // for global accounting.
328 +{
329 + assert(FALSE);
330 + return(1);
331 +}
332 +#endif // notdef
333 +
334 +
335 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
336 +
337 +// ****************************************************************************
338 +// __ J U D Y L E A F B 1 T O L E A F 1
339 +//
340 +// Shrink a bitmap leaf (cJU_LEAFB1) to linear leaf (cJU_JPLEAF1).
341 +// Return 1 for success, or -1 for failure (with details in Pjpm).
342 +//
343 +// Note: This function is different than the other JudyLeaf*ToLeaf*()
344 +// functions because it receives a Pjp, not just a leaf, and handles its own
345 +// allocation and free, in order to allow the caller to continue with a LeafB1
346 +// if allocation fails.
347 +
348 +FUNCTION int j__udyLeafB1ToLeaf1(
349 + Pjp_t Pjp, // points to LeafB1 to shrink.
350 + Pvoid_t Pjpm) // for global accounting.
351 +{
352 + Pjlb_t PjlbRaw; // bitmap in old leaf.
353 + Pjlb_t Pjlb;
354 + Pjll_t PjllRaw; // new Leaf1.
355 + uint8_t * Pleaf1; // Leaf1 pointer type.
356 + Word_t Digit; // in LeafB1 bitmap.
357 +#ifdef JUDYL
358 + Pjv_t PjvNew; // value area in new Leaf1.
359 + Word_t Pop1;
360 + Word_t SubExp;
361 +#endif
362 +
363 + assert(JU_JPTYPE(Pjp) == cJU_JPLEAF_B1);
364 + assert(((JU_JPDCDPOP0(Pjp) & 0xFF) + 1) == cJU_LEAF1_MAXPOP1);
365 +
366 +// Allocate JPLEAF1 and prepare pointers:
367 +
368 + if ((PjllRaw = j__udyAllocJLL1(cJU_LEAF1_MAXPOP1, Pjpm)) == 0)
369 + return(-1);
370 +
371 + Pleaf1 = (uint8_t *) P_JLL(PjllRaw);
372 + PjlbRaw = (Pjlb_t) (Pjp->jp_Addr);
373 + Pjlb = P_JLB(PjlbRaw);
374 + JUDYLCODE(PjvNew = JL_LEAF1VALUEAREA(Pleaf1, cJL_LEAF1_MAXPOP1);)
375 +
376 +// Copy 1-byte indexes from old LeafB1 to new Leaf1:
377 +
378 + for (Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
379 + if (JU_BITMAPTESTL(Pjlb, Digit))
380 + *Pleaf1++ = Digit;
381 +
382 +#ifdef JUDYL
383 +
384 +// Copy all old-LeafB1 value areas from value subarrays to new Leaf1:
385 +
386 + for (SubExp = 0; SubExp < cJU_NUMSUBEXPL; ++SubExp)
387 + {
388 + Pjv_t PjvRaw = JL_JLB_PVALUE(Pjlb, SubExp);
389 + Pjv_t Pjv = P_JV(PjvRaw);
390 +
391 + if (Pjv == (Pjv_t) NULL) continue; // skip empty subarray.
392 +
393 + Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, SubExp)); // subarray.
394 + assert(Pop1);
395 +
396 + JU_COPYMEM(PjvNew, Pjv, Pop1); // copy value areas.
397 + j__udyLFreeJV(PjvRaw, Pop1, Pjpm);
398 + PjvNew += Pop1; // advance through new.
399 + }
400 +
401 + assert((((Word_t) Pleaf1) - (Word_t) P_JLL(PjllRaw))
402 + == (PjvNew - JL_LEAF1VALUEAREA(P_JLL(PjllRaw), cJL_LEAF1_MAXPOP1)));
403 +#endif // JUDYL
404 +
405 + DBGCODE(JudyCheckSorted((Pjll_t) P_JLL(PjllRaw),
406 + (((Word_t) Pleaf1) - (Word_t) P_JLL(PjllRaw)), 1);)
407 +
408 +// Finish up: Free the old LeafB1 and plug the new Leaf1 into the JP:
409 +//
410 +// Note: jp_DcdPopO does not change here.
411 +
412 + j__udyFreeJLB1(PjlbRaw, Pjpm);
413 +
414 + Pjp->jp_Addr = (Word_t) PjllRaw;
415 + Pjp->jp_Type = cJU_JPLEAF1;
416 +
417 + return(1);
418 +
419 +} // j__udyLeafB1ToLeaf1()
420 +
421 +#endif // (JUDYL || (! JU_64BIT))
422 +
423 +
424 +// ****************************************************************************
425 +// __ J U D Y L E A F 1 T O L E A F 2
426 +//
427 +// Copy 1-byte Indexes from a LeafB1 or Leaf1 to 2-byte Indexes in a Leaf2.
428 +// Pjp MUST be one of: cJU_JPLEAF_B1, cJU_JPLEAF1, or cJU_JPIMMED_1_*.
429 +// Return number of Indexes copied.
430 +//
431 +// TBD: In this and all following functions, the caller should already be able
432 +// to compute the Pop1 return value, so why return it?
433 +
434 +FUNCTION Word_t j__udyLeaf1ToLeaf2(
435 + uint16_t * PLeaf2, // destination uint16_t * Index portion of leaf.
436 +#ifdef JUDYL
437 + Pjv_t Pjv2, // destination value part of leaf.
438 +#endif
439 + Pjp_t Pjp, // 1-byte-index object from which to copy.
440 + Word_t MSByte, // most-significant byte, prefix to each Index.
441 + Pvoid_t Pjpm) // for global accounting.
442 +{
443 + Word_t Pop1; // Indexes in leaf.
444 + Word_t Offset; // in linear leaf list.
445 +JUDYLCODE(Pjv_t Pjv1Raw;) // source object value area.
446 +JUDYLCODE(Pjv_t Pjv1;)
447 +
448 + switch (JU_JPTYPE(Pjp))
449 + {
450 +
451 +
452 +// JPLEAF_B1:
453 +
454 + case cJU_JPLEAF_B1:
455 + {
456 + Pjlb_t Pjlb = P_JLB(Pjp->jp_Addr);
457 + Word_t Digit; // in LeafB1 bitmap.
458 + JUDYLCODE(Word_t SubExp;) // in LeafB1.
459 +
460 + Pop1 = JU_JPBRANCH_POP0(Pjp, 1) + 1; assert(Pop1);
461 +
462 +// Copy 1-byte indexes from old LeafB1 to new Leaf2, including splicing in
463 +// the missing MSByte needed in the Leaf2:
464 +
465 + for (Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
466 + if (JU_BITMAPTESTL(Pjlb, Digit))
467 + *PLeaf2++ = MSByte | Digit;
468 +
469 +#ifdef JUDYL
470 +
471 +// Copy all old-LeafB1 value areas from value subarrays to new Leaf2:
472 +
473 + for (SubExp = 0; SubExp < cJU_NUMSUBEXPL; ++SubExp)
474 + {
475 + Word_t SubExpPop1;
476 +
477 + Pjv1Raw = JL_JLB_PVALUE(Pjlb, SubExp);
478 + if (Pjv1Raw == (Pjv_t) NULL) continue; // skip empty.
479 + Pjv1 = P_JV(Pjv1Raw);
480 +
481 + SubExpPop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, SubExp));
482 + assert(SubExpPop1);
483 +
484 + JU_COPYMEM(Pjv2, Pjv1, SubExpPop1); // copy value areas.
485 + j__udyLFreeJV(Pjv1Raw, SubExpPop1, Pjpm);
486 + Pjv2 += SubExpPop1; // advance through new.
487 + }
488 +#endif // JUDYL
489 +
490 + j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm); // LeafB1 itself.
491 + return(Pop1);
492 +
493 + } // case cJU_JPLEAF_B1
494 +
495 +
496 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
497 +
498 +// JPLEAF1:
499 +
500 + case cJU_JPLEAF1:
501 + {
502 + uint8_t * PLeaf1 = (uint8_t *) P_JLL(Pjp->jp_Addr);
503 +
504 + Pop1 = JU_JPBRANCH_POP0(Pjp, 1) + 1; assert(Pop1);
505 + JUDYLCODE(Pjv1 = JL_LEAF1VALUEAREA(PLeaf1, Pop1);)
506 +
507 +// Copy all Index bytes including splicing in missing MSByte needed in Leaf2
508 +// (plus, for JudyL, value areas):
509 +
510 + for (Offset = 0; Offset < Pop1; ++Offset)
511 + {
512 + PLeaf2[Offset] = MSByte | PLeaf1[Offset];
513 + JUDYLCODE(Pjv2[Offset] = Pjv1[Offset];)
514 + }
515 + j__udyFreeJLL1((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
516 + return(Pop1);
517 + }
518 +#endif // (JUDYL || (! JU_64BIT))
519 +
520 +
521 +// JPIMMED_1_01:
522 +//
523 +// Note: jp_DcdPopO has 3 [7] bytes of Index (all but most significant byte),
524 +// so the assignment to PLeaf2[] truncates and MSByte is not needed.
525 +
526 + case cJU_JPIMMED_1_01:
527 + {
528 + PLeaf2[0] = JU_JPDCDPOP0(Pjp); // see above.
529 + JUDYLCODE(Pjv2[0] = Pjp->jp_Addr;)
530 + return(1);
531 + }
532 +
533 +
534 +// JPIMMED_1_0[2+]:
535 +
536 + case cJU_JPIMMED_1_02:
537 + case cJU_JPIMMED_1_03:
538 +#if (defined(JUDY1) || defined(JU_64BIT))
539 + case cJU_JPIMMED_1_04:
540 + case cJU_JPIMMED_1_05:
541 + case cJU_JPIMMED_1_06:
542 + case cJU_JPIMMED_1_07:
543 +#endif
544 +#if (defined(JUDY1) && defined(JU_64BIT))
545 + case cJ1_JPIMMED_1_08:
546 + case cJ1_JPIMMED_1_09:
547 + case cJ1_JPIMMED_1_10:
548 + case cJ1_JPIMMED_1_11:
549 + case cJ1_JPIMMED_1_12:
550 + case cJ1_JPIMMED_1_13:
551 + case cJ1_JPIMMED_1_14:
552 + case cJ1_JPIMMED_1_15:
553 +#endif
554 + {
555 + Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_02 + 2; assert(Pop1);
556 + JUDYLCODE(Pjv1Raw = (Pjv_t) (Pjp->jp_Addr);)
557 + JUDYLCODE(Pjv1 = P_JV(Pjv1Raw);)
558 +
559 + for (Offset = 0; Offset < Pop1; ++Offset)
560 + {
561 +#ifdef JUDY1
562 + PLeaf2[Offset] = MSByte | Pjp->jp_1Index[Offset];
563 +#else
564 + PLeaf2[Offset] = MSByte | Pjp->jp_LIndex[Offset];
565 + Pjv2 [Offset] = Pjv1[Offset];
566 +#endif
567 + }
568 + JUDYLCODE(j__udyLFreeJV(Pjv1Raw, Pop1, Pjpm);)
569 + return(Pop1);
570 + }
571 +
572 +
573 +// UNEXPECTED CASES, including JPNULL1, should be handled by caller:
574 +
575 + default: assert(FALSE); break;
576 +
577 + } // switch
578 +
579 + return(0);
580 +
581 +} // j__udyLeaf1ToLeaf2()
582 +
583 +
584 +// *****************************************************************************
585 +// __ J U D Y L E A F 2 T O L E A F 3
586 +//
587 +// Copy 2-byte Indexes from a Leaf2 to 3-byte Indexes in a Leaf3.
588 +// Pjp MUST be one of: cJU_JPLEAF2 or cJU_JPIMMED_2_*.
589 +// Return number of Indexes copied.
590 +//
591 +// Note: By the time this function is called to compress a level-3 branch to a
592 +// Leaf3, the branch has no narrow pointers under it, meaning only level-2
593 +// objects are below it and must be handled here.
594 +
595 +FUNCTION Word_t j__udyLeaf2ToLeaf3(
596 + uint8_t * PLeaf3, // destination "uint24_t *" Index part of leaf.
597 +#ifdef JUDYL
598 + Pjv_t Pjv3, // destination value part of leaf.
599 +#endif
600 + Pjp_t Pjp, // 2-byte-index object from which to copy.
601 + Word_t MSByte, // most-significant byte, prefix to each Index.
602 + Pvoid_t Pjpm) // for global accounting.
603 +{
604 + Word_t Pop1; // Indexes in leaf.
605 +#if (defined(JUDYL) && defined(JU_64BIT))
606 + Pjv_t Pjv2Raw; // source object value area.
607 +#endif
608 +JUDYLCODE(Pjv_t Pjv2;)
609 +
610 + switch (JU_JPTYPE(Pjp))
611 + {
612 +
613 +
614 +// JPLEAF2:
615 +
616 + case cJU_JPLEAF2:
617 + {
618 + uint16_t * PLeaf2 = (uint16_t *) P_JLL(Pjp->jp_Addr);
619 +
620 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
621 + j__udyCopy2to3(PLeaf3, PLeaf2, Pop1, MSByte);
622 +#ifdef JUDYL
623 + Pjv2 = JL_LEAF2VALUEAREA(PLeaf2, Pop1);
624 + JU_COPYMEM(Pjv3, Pjv2, Pop1);
625 +#endif
626 + j__udyFreeJLL2((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
627 + return(Pop1);
628 + }
629 +
630 +
631 +// JPIMMED_2_01:
632 +//
633 +// Note: jp_DcdPopO has 3 [7] bytes of Index (all but most significant byte),
634 +// so the "assignment" to PLeaf3[] is exact [truncates] and MSByte is not
635 +// needed.
636 +
637 + case cJU_JPIMMED_2_01:
638 + {
639 + JU_COPY3_LONG_TO_PINDEX(PLeaf3, JU_JPDCDPOP0(Pjp)); // see above.
640 + JUDYLCODE(Pjv3[0] = Pjp->jp_Addr;)
641 + return(1);
642 + }
643 +
644 +
645 +// JPIMMED_2_0[2+]:
646 +
647 +#if (defined(JUDY1) || defined(JU_64BIT))
648 + case cJU_JPIMMED_2_02:
649 + case cJU_JPIMMED_2_03:
650 +#endif
651 +#if (defined(JUDY1) && defined(JU_64BIT))
652 + case cJ1_JPIMMED_2_04:
653 + case cJ1_JPIMMED_2_05:
654 + case cJ1_JPIMMED_2_06:
655 + case cJ1_JPIMMED_2_07:
656 +#endif
657 +#if (defined(JUDY1) || defined(JU_64BIT))
658 + {
659 + JUDY1CODE(uint16_t * PLeaf2 = (uint16_t *) (Pjp->jp_1Index);)
660 + JUDYLCODE(uint16_t * PLeaf2 = (uint16_t *) (Pjp->jp_LIndex);)
661 +
662 + Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_2_02 + 2; assert(Pop1);
663 + j__udyCopy2to3(PLeaf3, PLeaf2, Pop1, MSByte);
664 +#ifdef JUDYL
665 + Pjv2Raw = (Pjv_t) (Pjp->jp_Addr);
666 + Pjv2 = P_JV(Pjv2Raw);
667 + JU_COPYMEM(Pjv3, Pjv2, Pop1);
668 + j__udyLFreeJV(Pjv2Raw, Pop1, Pjpm);
669 +#endif
670 + return(Pop1);
671 + }
672 +#endif // (JUDY1 || JU_64BIT)
673 +
674 +
675 +// UNEXPECTED CASES, including JPNULL2, should be handled by caller:
676 +
677 + default: assert(FALSE); break;
678 +
679 + } // switch
680 +
681 + return(0);
682 +
683 +} // j__udyLeaf2ToLeaf3()
684 +
685 +
686 +#ifdef JU_64BIT
687 +
688 +// ****************************************************************************
689 +// __ J U D Y L E A F 3 T O L E A F 4
690 +//
691 +// Copy 3-byte Indexes from a Leaf3 to 4-byte Indexes in a Leaf4.
692 +// Pjp MUST be one of: cJU_JPLEAF3 or cJU_JPIMMED_3_*.
693 +// Return number of Indexes copied.
694 +//
695 +// Note: By the time this function is called to compress a level-4 branch to a
696 +// Leaf4, the branch has no narrow pointers under it, meaning only level-3
697 +// objects are below it and must be handled here.
698 +
699 +FUNCTION Word_t j__udyLeaf3ToLeaf4(
700 + uint32_t * PLeaf4, // destination uint32_t * Index part of leaf.
701 +#ifdef JUDYL
702 + Pjv_t Pjv4, // destination value part of leaf.
703 +#endif
704 + Pjp_t Pjp, // 3-byte-index object from which to copy.
705 + Word_t MSByte, // most-significant byte, prefix to each Index.
706 + Pvoid_t Pjpm) // for global accounting.
707 +{
708 + Word_t Pop1; // Indexes in leaf.
709 +JUDYLCODE(Pjv_t Pjv3Raw;) // source object value area.
710 +JUDYLCODE(Pjv_t Pjv3;)
711 +
712 + switch (JU_JPTYPE(Pjp))
713 + {
714 +
715 +
716 +// JPLEAF3:
717 +
718 + case cJU_JPLEAF3:
719 + {
720 + uint8_t * PLeaf3 = (uint8_t *) P_JLL(Pjp->jp_Addr);
721 +
722 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
723 + j__udyCopy3to4(PLeaf4, (uint8_t *) PLeaf3, Pop1, MSByte);
724 +#ifdef JUDYL
725 + Pjv3 = JL_LEAF3VALUEAREA(PLeaf3, Pop1);
726 + JU_COPYMEM(Pjv4, Pjv3, Pop1);
727 +#endif
728 + j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
729 + return(Pop1);
730 + }
731 +
732 +
733 +// JPIMMED_3_01:
734 +//
735 +// Note: jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
736 +// the assignment to PLeaf4[] truncates and MSByte is not needed.
737 +
738 + case cJU_JPIMMED_3_01:
739 + {
740 + PLeaf4[0] = JU_JPDCDPOP0(Pjp); // see above.
741 + JUDYLCODE(Pjv4[0] = Pjp->jp_Addr;)
742 + return(1);
743 + }
744 +
745 +
746 +// JPIMMED_3_0[2+]:
747 +
748 + case cJU_JPIMMED_3_02:
749 +#ifdef JUDY1
750 + case cJ1_JPIMMED_3_03:
751 + case cJ1_JPIMMED_3_04:
752 + case cJ1_JPIMMED_3_05:
753 +#endif
754 + {
755 + JUDY1CODE(uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_1Index);)
756 + JUDYLCODE(uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_LIndex);)
757 +
758 + JUDY1CODE(Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_3_02 + 2;)
759 + JUDYLCODE(Pop1 = 2;)
760 +
761 + j__udyCopy3to4(PLeaf4, PLeaf3, Pop1, MSByte);
762 +#ifdef JUDYL
763 + Pjv3Raw = (Pjv_t) (Pjp->jp_Addr);
764 + Pjv3 = P_JV(Pjv3Raw);
765 + JU_COPYMEM(Pjv4, Pjv3, Pop1);
766 + j__udyLFreeJV(Pjv3Raw, Pop1, Pjpm);
767 +#endif
768 + return(Pop1);
769 + }
770 +
771 +
772 +// UNEXPECTED CASES, including JPNULL3, should be handled by caller:
773 +
774 + default: assert(FALSE); break;
775 +
776 + } // switch
777 +
778 + return(0);
779 +
780 +} // j__udyLeaf3ToLeaf4()
781 +
782 +
783 +// Note: In all following j__udyLeaf*ToLeaf*() functions, JPIMMED_*_0[2+]
784 +// cases exist for Judy1 (&& 64-bit) only. JudyL has no equivalent Immeds.
785 +
786 +
787 +// *****************************************************************************
788 +// __ J U D Y L E A F 4 T O L E A F 5
789 +//
790 +// Copy 4-byte Indexes from a Leaf4 to 5-byte Indexes in a Leaf5.
791 +// Pjp MUST be one of: cJU_JPLEAF4 or cJU_JPIMMED_4_*.
792 +// Return number of Indexes copied.
793 +//
794 +// Note: By the time this function is called to compress a level-5 branch to a
795 +// Leaf5, the branch has no narrow pointers under it, meaning only level-4
796 +// objects are below it and must be handled here.
797 +
798 +FUNCTION Word_t j__udyLeaf4ToLeaf5(
799 + uint8_t * PLeaf5, // destination "uint40_t *" Index part of leaf.
800 +#ifdef JUDYL
801 + Pjv_t Pjv5, // destination value part of leaf.
802 +#endif
803 + Pjp_t Pjp, // 4-byte-index object from which to copy.
804 + Word_t MSByte, // most-significant byte, prefix to each Index.
805 + Pvoid_t Pjpm) // for global accounting.
806 +{
807 + Word_t Pop1; // Indexes in leaf.
808 +JUDYLCODE(Pjv_t Pjv4;) // source object value area.
809 +
810 + switch (JU_JPTYPE(Pjp))
811 + {
812 +
813 +
814 +// JPLEAF4:
815 +
816 + case cJU_JPLEAF4:
817 + {
818 + uint32_t * PLeaf4 = (uint32_t *) P_JLL(Pjp->jp_Addr);
819 +
820 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
821 + j__udyCopy4to5(PLeaf5, PLeaf4, Pop1, MSByte);
822 +#ifdef JUDYL
823 + Pjv4 = JL_LEAF4VALUEAREA(PLeaf4, Pop1);
824 + JU_COPYMEM(Pjv5, Pjv4, Pop1);
825 +#endif
826 + j__udyFreeJLL4((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
827 + return(Pop1);
828 + }
829 +
830 +
831 +// JPIMMED_4_01:
832 +//
833 +// Note: jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
834 +// the assignment to PLeaf5[] truncates and MSByte is not needed.
835 +
836 + case cJU_JPIMMED_4_01:
837 + {
838 + JU_COPY5_LONG_TO_PINDEX(PLeaf5, JU_JPDCDPOP0(Pjp)); // see above.
839 + JUDYLCODE(Pjv5[0] = Pjp->jp_Addr;)
840 + return(1);
841 + }
842 +
843 +
844 +#ifdef JUDY1
845 +
846 +// JPIMMED_4_0[4+]:
847 +
848 + case cJ1_JPIMMED_4_02:
849 + case cJ1_JPIMMED_4_03:
850 + {
851 + uint32_t * PLeaf4 = (uint32_t *) (Pjp->jp_1Index);
852 +
853 + Pop1 = JU_JPTYPE(Pjp) - cJ1_JPIMMED_4_02 + 2;
854 + j__udyCopy4to5(PLeaf5, PLeaf4, Pop1, MSByte);
855 + return(Pop1);
856 + }
857 +#endif // JUDY1
858 +
859 +
860 +// UNEXPECTED CASES, including JPNULL4, should be handled by caller:
861 +
862 + default: assert(FALSE); break;
863 +
864 + } // switch
865 +
866 + return(0);
867 +
868 +} // j__udyLeaf4ToLeaf5()
869 +
870 +
871 +// ****************************************************************************
872 +// __ J U D Y L E A F 5 T O L E A F 6
873 +//
874 +// Copy 5-byte Indexes from a Leaf5 to 6-byte Indexes in a Leaf6.
875 +// Pjp MUST be one of: cJU_JPLEAF5 or cJU_JPIMMED_5_*.
876 +// Return number of Indexes copied.
877 +//
878 +// Note: By the time this function is called to compress a level-6 branch to a
879 +// Leaf6, the branch has no narrow pointers under it, meaning only level-5
880 +// objects are below it and must be handled here.
881 +
882 +FUNCTION Word_t j__udyLeaf5ToLeaf6(
883 + uint8_t * PLeaf6, // destination uint8_t * Index part of leaf.
884 +#ifdef JUDYL
885 + Pjv_t Pjv6, // destination value part of leaf.
886 +#endif
887 + Pjp_t Pjp, // 5-byte-index object from which to copy.
888 + Word_t MSByte, // most-significant byte, prefix to each Index.
889 + Pvoid_t Pjpm) // for global accounting.
890 +{
891 + Word_t Pop1; // Indexes in leaf.
892 +JUDYLCODE(Pjv_t Pjv5;) // source object value area.
893 +
894 + switch (JU_JPTYPE(Pjp))
895 + {
896 +
897 +
898 +// JPLEAF5:
899 +
900 + case cJU_JPLEAF5:
901 + {
902 + uint8_t * PLeaf5 = (uint8_t *) P_JLL(Pjp->jp_Addr);
903 +
904 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
905 + j__udyCopy5to6(PLeaf6, PLeaf5, Pop1, MSByte);
906 +#ifdef JUDYL
907 + Pjv5 = JL_LEAF5VALUEAREA(PLeaf5, Pop1);
908 + JU_COPYMEM(Pjv6, Pjv5, Pop1);
909 +#endif
910 + j__udyFreeJLL5((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
911 + return(Pop1);
912 + }
913 +
914 +
915 +// JPIMMED_5_01:
916 +//
917 +// Note: jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
918 +// the assignment to PLeaf6[] truncates and MSByte is not needed.
919 +
920 + case cJU_JPIMMED_5_01:
921 + {
922 + JU_COPY6_LONG_TO_PINDEX(PLeaf6, JU_JPDCDPOP0(Pjp)); // see above.
923 + JUDYLCODE(Pjv6[0] = Pjp->jp_Addr;)
924 + return(1);
925 + }
926 +
927 +
928 +#ifdef JUDY1
929 +
930 +// JPIMMED_5_0[2+]:
931 +
932 + case cJ1_JPIMMED_5_02:
933 + case cJ1_JPIMMED_5_03:
934 + {
935 + uint8_t * PLeaf5 = (uint8_t *) (Pjp->jp_1Index);
936 +
937 + Pop1 = JU_JPTYPE(Pjp) - cJ1_JPIMMED_5_02 + 2;
938 + j__udyCopy5to6(PLeaf6, PLeaf5, Pop1, MSByte);
939 + return(Pop1);
940 + }
941 +#endif // JUDY1
942 +
943 +
944 +// UNEXPECTED CASES, including JPNULL5, should be handled by caller:
945 +
946 + default: assert(FALSE); break;
947 +
948 + } // switch
949 +
950 + return(0);
951 +
952 +} // j__udyLeaf5ToLeaf6()
953 +
954 +
955 +// *****************************************************************************
956 +// __ J U D Y L E A F 6 T O L E A F 7
957 +//
958 +// Copy 6-byte Indexes from a Leaf2 to 7-byte Indexes in a Leaf7.
959 +// Pjp MUST be one of: cJU_JPLEAF6 or cJU_JPIMMED_6_*.
960 +// Return number of Indexes copied.
961 +//
962 +// Note: By the time this function is called to compress a level-7 branch to a
963 +// Leaf7, the branch has no narrow pointers under it, meaning only level-6
964 +// objects are below it and must be handled here.
965 +
966 +FUNCTION Word_t j__udyLeaf6ToLeaf7(
967 + uint8_t * PLeaf7, // destination "uint24_t *" Index part of leaf.
968 +#ifdef JUDYL
969 + Pjv_t Pjv7, // destination value part of leaf.
970 +#endif
971 + Pjp_t Pjp, // 6-byte-index object from which to copy.
972 + Word_t MSByte, // most-significant byte, prefix to each Index.
973 + Pvoid_t Pjpm) // for global accounting.
974 +{
975 + Word_t Pop1; // Indexes in leaf.
976 +JUDYLCODE(Pjv_t Pjv6;) // source object value area.
977 +
978 + switch (JU_JPTYPE(Pjp))
979 + {
980 +
981 +
982 +// JPLEAF6:
983 +
984 + case cJU_JPLEAF6:
985 + {
986 + uint8_t * PLeaf6 = (uint8_t *) P_JLL(Pjp->jp_Addr);
987 +
988 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
989 + j__udyCopy6to7(PLeaf7, PLeaf6, Pop1, MSByte);
990 +#ifdef JUDYL
991 + Pjv6 = JL_LEAF6VALUEAREA(PLeaf6, Pop1);
992 + JU_COPYMEM(Pjv7, Pjv6, Pop1);
993 +#endif
994 + j__udyFreeJLL6((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
995 + return(Pop1);
996 + }
997 +
998 +
999 +// JPIMMED_6_01:
1000 +//
1001 +// Note: jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
1002 +// the "assignment" to PLeaf7[] is exact and MSByte is not needed.
1003 +
1004 + case cJU_JPIMMED_6_01:
1005 + {
1006 + JU_COPY7_LONG_TO_PINDEX(PLeaf7, JU_JPDCDPOP0(Pjp)); // see above.
1007 + JUDYLCODE(Pjv7[0] = Pjp->jp_Addr;)
1008 + return(1);
1009 + }
1010 +
1011 +
1012 +#ifdef JUDY1
1013 +
1014 +// JPIMMED_6_02:
1015 +
1016 + case cJ1_JPIMMED_6_02:
1017 + {
1018 + uint8_t * PLeaf6 = (uint8_t *) (Pjp->jp_1Index);
1019 +
1020 + j__udyCopy6to7(PLeaf7, PLeaf6, /* Pop1 = */ 2, MSByte);
1021 + return(2);
1022 + }
1023 +#endif // JUDY1
1024 +
1025 +
1026 +// UNEXPECTED CASES, including JPNULL6, should be handled by caller:
1027 +
1028 + default: assert(FALSE); break;
1029 +
1030 + } // switch
1031 +
1032 + return(0);
1033 +
1034 +} // j__udyLeaf6ToLeaf7()
1035 +
1036 +#endif // JU_64BIT
1037 +
1038 +
1039 +#ifndef JU_64BIT // 32-bit version first
1040 +
1041 +// ****************************************************************************
1042 +// __ J U D Y L E A F 3 T O L E A F W
1043 +//
1044 +// Copy 3-byte Indexes from a Leaf3 to 4-byte Indexes in a LeafW. Pjp MUST be
1045 +// one of: cJU_JPLEAF3 or cJU_JPIMMED_3_*. Return number of Indexes copied.
1046 +//
1047 +// Note: By the time this function is called to compress a level-L branch to a
1048 +// LeafW, the branch has no narrow pointers under it, meaning only level-3
1049 +// objects are below it and must be handled here.
1050 +
1051 +FUNCTION Word_t j__udyLeaf3ToLeafW(
1052 + Pjlw_t Pjlw, // destination Index part of leaf.
1053 +#ifdef JUDYL
1054 + Pjv_t PjvW, // destination value part of leaf.
1055 +#endif
1056 + Pjp_t Pjp, // 3-byte-index object from which to copy.
1057 + Word_t MSByte, // most-significant byte, prefix to each Index.
1058 + Pvoid_t Pjpm) // for global accounting.
1059 +{
1060 + Word_t Pop1; // Indexes in leaf.
1061 +JUDYLCODE(Pjv_t Pjv3;) // source object value area.
1062 +
1063 + switch (JU_JPTYPE(Pjp))
1064 + {
1065 +
1066 +
1067 +// JPLEAF3:
1068 +
1069 + case cJU_JPLEAF3:
1070 + {
1071 + uint8_t * PLeaf3 = (uint8_t *) P_JLL(Pjp->jp_Addr);
1072 +
1073 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
1074 + j__udyCopy3toW((PWord_t) Pjlw, PLeaf3, Pop1, MSByte);
1075 +#ifdef JUDYL
1076 + Pjv3 = JL_LEAF3VALUEAREA(PLeaf3, Pop1);
1077 + JU_COPYMEM(PjvW, Pjv3, Pop1);
1078 +#endif
1079 + j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
1080 + return(Pop1);
1081 + }
1082 +
1083 +
1084 +// JPIMMED_3_01:
1085 +//
1086 +// Note: jp_DcdPopO has 3 bytes of Index (all but most significant byte), and
1087 +// MSByte must be ord in.
1088 +
1089 + case cJU_JPIMMED_3_01:
1090 + {
1091 + Pjlw[0] = MSByte | JU_JPDCDPOP0(Pjp); // see above.
1092 + JUDYLCODE(PjvW[0] = Pjp->jp_Addr;)
1093 + return(1);
1094 + }
1095 +
1096 +
1097 +#ifdef JUDY1
1098 +
1099 +// JPIMMED_3_02:
1100 +
1101 + case cJU_JPIMMED_3_02:
1102 + {
1103 + uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_1Index);
1104 +
1105 + j__udyCopy3toW((PWord_t) Pjlw, PLeaf3, /* Pop1 = */ 2, MSByte);
1106 + return(2);
1107 + }
1108 +#endif // JUDY1
1109 +
1110 +
1111 +// UNEXPECTED CASES, including JPNULL3, should be handled by caller:
1112 +
1113 + default: assert(FALSE); break;
1114 +
1115 + } // switch
1116 +
1117 + return(0);
1118 +
1119 +} // j__udyLeaf3ToLeafW()
1120 +
1121 +
1122 +#else // JU_64BIT
1123 +
1124 +
1125 +// ****************************************************************************
1126 +// __ J U D Y L E A F 7 T O L E A F W
1127 +//
1128 +// Copy 7-byte Indexes from a Leaf7 to 8-byte Indexes in a LeafW.
1129 +// Pjp MUST be one of: cJU_JPLEAF7 or cJU_JPIMMED_7_*.
1130 +// Return number of Indexes copied.
1131 +//
1132 +// Note: By the time this function is called to compress a level-L branch to a
1133 +// LeafW, the branch has no narrow pointers under it, meaning only level-7
1134 +// objects are below it and must be handled here.
1135 +
1136 +FUNCTION Word_t j__udyLeaf7ToLeafW(
1137 + Pjlw_t Pjlw, // destination Index part of leaf.
1138 +#ifdef JUDYL
1139 + Pjv_t PjvW, // destination value part of leaf.
1140 +#endif
1141 + Pjp_t Pjp, // 7-byte-index object from which to copy.
1142 + Word_t MSByte, // most-significant byte, prefix to each Index.
1143 + Pvoid_t Pjpm) // for global accounting.
1144 +{
1145 + Word_t Pop1; // Indexes in leaf.
1146 +JUDYLCODE(Pjv_t Pjv7;) // source object value area.
1147 +
1148 + switch (JU_JPTYPE(Pjp))
1149 + {
1150 +
1151 +
1152 +// JPLEAF7:
1153 +
1154 + case cJU_JPLEAF7:
1155 + {
1156 + uint8_t * PLeaf7 = (uint8_t *) P_JLL(Pjp->jp_Addr);
1157 +
1158 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
1159 + j__udyCopy7toW((PWord_t) Pjlw, PLeaf7, Pop1, MSByte);
1160 +#ifdef JUDYL
1161 + Pjv7 = JL_LEAF7VALUEAREA(PLeaf7, Pop1);
1162 + JU_COPYMEM(PjvW, Pjv7, Pop1);
1163 +#endif
1164 + j__udyFreeJLL7((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
1165 + return(Pop1);
1166 + }
1167 +
1168 +
1169 +// JPIMMED_7_01:
1170 +//
1171 +// Note: jp_DcdPopO has 7 bytes of Index (all but most significant byte), and
1172 +// MSByte must be ord in.
1173 +
1174 + case cJU_JPIMMED_7_01:
1175 + {
1176 + Pjlw[0] = MSByte | JU_JPDCDPOP0(Pjp); // see above.
1177 + JUDYLCODE(PjvW[0] = Pjp->jp_Addr;)
1178 + return(1);
1179 + }
1180 +
1181 +
1182 +#ifdef JUDY1
1183 +
1184 +// JPIMMED_7_02:
1185 +
1186 + case cJ1_JPIMMED_7_02:
1187 + {
1188 + uint8_t * PLeaf7 = (uint8_t *) (Pjp->jp_1Index);
1189 +
1190 + j__udyCopy7toW((PWord_t) Pjlw, PLeaf7, /* Pop1 = */ 2, MSByte);
1191 + return(2);
1192 + }
1193 +#endif
1194 +
1195 +
1196 +// UNEXPECTED CASES, including JPNULL7, should be handled by caller:
1197 +
1198 + default: assert(FALSE); break;
1199 +
1200 + } // switch
1201 +
1202 + return(0);
1203 +
1204 +} // j__udyLeaf7ToLeafW()
1205 +
1206 +#endif // JU_64BIT
libnetdata/libjudy/src/JudyL/JudyLDel.c new
+2146
@@ -0,0 +1,2146 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.68 $ $Source: /judy/src/JudyCommon/JudyDel.c $
19 +//
20 +// Judy1Unset() and JudyLDel() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// About HYSTERESIS: In the Judy code, hysteresis means leaving around a
24 +// nominally suboptimal (not maximally compressed) data structure after a
25 +// deletion. As a result, the shape of the tree for two identical index sets
26 +// can differ depending on the insert/delete path taken to arrive at the index
27 +// sets. The purpose is to minimize worst-case behavior (thrashing) that could
28 +// result from a series of intermixed insertions and deletions. It also makes
29 +// for MUCH simpler code, because instead of performing, "delete and then
30 +// compress," it can say, "compress and then delete," where due to hysteresis,
31 +// compression is not even attempted until the object IS compressible.
32 +//
33 +// In some cases the code has no choice and it must "ungrow" a data structure
34 +// across a "phase transition" boundary without hysteresis. In other cases the
35 +// amount (such as "hysteresis = 1") is indicated by the number of JP deletions
36 +// (in branches) or index deletions (in leaves) that can occur in succession
37 +// before compressing the data structure. (It appears that hysteresis <= 1 in
38 +// all cases.)
39 +//
40 +// In general no hysteresis occurs when the data structure type remains the
41 +// same but the allocated memory chunk for the node must shrink, because the
42 +// relationship is hardwired and theres no way to know how much memory is
43 +// allocated to a given data structure. Hysteresis = 0 in all these cases.
44 +//
45 +// TBD: Could this code be faster if memory chunk hysteresis were supported
46 +// somehow along with data structure type hysteresis?
47 +//
48 +// TBD: Should some of the assertions here be converted to product code that
49 +// returns JU_ERRNO_CORRUPT?
50 +//
51 +// TBD: Dougs code had an odd mix of function-wide and limited-scope
52 +// variables. Should some of the function-wide variables appear only in
53 +// limited scopes, or more likely, vice-versa?
54 +
55 +#if (! (defined(JUDY1) || defined(JUDYL)))
56 +#error: One of -DJUDY1 or -DJUDYL must be specified.
57 +#endif
58 +
59 +#ifdef JUDY1
60 +#include "Judy1.h"
61 +#else
62 +#include "JudyL.h"
63 +#endif
64 +
65 +#include "JudyPrivate1L.h"
66 +
67 +DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);)
68 +DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)
69 +
70 +#ifdef TRACEJP
71 +#include "JudyPrintJP.c"
72 +#endif
73 +
74 +// These are defined to generic values in JudyCommon/JudyPrivateTypes.h:
75 +//
76 +// TBD: These should be exported from a header file, but perhaps not, as they
77 +// are only used here, and exported from JudyDecascade.c, which is a separate
78 +// file for profiling reasons (to prevent inlining), but which potentially
79 +// could be merged with this file, either in SoftCM or at compile-time:
80 +
81 +#ifdef JUDY1
82 +
83 +extern int j__udy1BranchBToBranchL(Pjp_t Pjp, Pvoid_t Pjpm);
84 +#ifndef JU_64BIT
85 +extern int j__udy1LeafB1ToLeaf1(Pjp_t, Pvoid_t);
86 +#endif
87 +extern Word_t j__udy1Leaf1ToLeaf2(uint16_t *, Pjp_t, Word_t, Pvoid_t);
88 +extern Word_t j__udy1Leaf2ToLeaf3(uint8_t *, Pjp_t, Word_t, Pvoid_t);
89 +#ifndef JU_64BIT
90 +extern Word_t j__udy1Leaf3ToLeafW(Pjlw_t, Pjp_t, Word_t, Pvoid_t);
91 +#else
92 +extern Word_t j__udy1Leaf3ToLeaf4(uint32_t *, Pjp_t, Word_t, Pvoid_t);
93 +extern Word_t j__udy1Leaf4ToLeaf5(uint8_t *, Pjp_t, Word_t, Pvoid_t);
94 +extern Word_t j__udy1Leaf5ToLeaf6(uint8_t *, Pjp_t, Word_t, Pvoid_t);
95 +extern Word_t j__udy1Leaf6ToLeaf7(uint8_t *, Pjp_t, Word_t, Pvoid_t);
96 +extern Word_t j__udy1Leaf7ToLeafW(Pjlw_t, Pjp_t, Word_t, Pvoid_t);
97 +#endif
98 +
99 +#else // JUDYL
100 +
101 +extern int j__udyLBranchBToBranchL(Pjp_t Pjp, Pvoid_t Pjpm);
102 +extern int j__udyLLeafB1ToLeaf1(Pjp_t, Pvoid_t);
103 +extern Word_t j__udyLLeaf1ToLeaf2(uint16_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
104 +extern Word_t j__udyLLeaf2ToLeaf3(uint8_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
105 +#ifndef JU_64BIT
106 +extern Word_t j__udyLLeaf3ToLeafW(Pjlw_t, Pjv_t, Pjp_t, Word_t, Pvoid_t);
107 +#else
108 +extern Word_t j__udyLLeaf3ToLeaf4(uint32_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
109 +extern Word_t j__udyLLeaf4ToLeaf5(uint8_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
110 +extern Word_t j__udyLLeaf5ToLeaf6(uint8_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
111 +extern Word_t j__udyLLeaf6ToLeaf7(uint8_t *, Pjv_t, Pjp_t, Word_t, Pvoid_t);
112 +extern Word_t j__udyLLeaf7ToLeafW(Pjlw_t, Pjv_t, Pjp_t, Word_t, Pvoid_t);
113 +#endif
114 +
115 +#endif // JUDYL
116 +
117 +// For convenience in the calling code; "M1" means "minus one":
118 +
119 +#ifndef JU_64BIT
120 +#define j__udyLeafM1ToLeafW j__udyLeaf3ToLeafW
121 +#else
122 +#define j__udyLeafM1ToLeafW j__udyLeaf7ToLeafW
123 +#endif
124 +
125 +
126 +// ****************************************************************************
127 +// __ J U D Y D E L W A L K
128 +//
129 +// Given a pointer to a JP, an Index known to be valid, the number of bytes
130 +// left to decode (== level in the tree), and a pointer to a global JPM, walk a
131 +// Judy (sub)tree to do an unset/delete of that index, and possibly modify the
132 +// JPM. This function is only called internally, and recursively. Unlike
133 +// Judy1Test() and JudyLGet(), the extra time required for recursion should be
134 +// negligible compared with the total.
135 +//
136 +// Return values:
137 +//
138 +// -1 error; details in JPM
139 +//
140 +// 0 Index already deleted (should never happen, Index is known to be valid)
141 +//
142 +// 1 previously valid Index deleted
143 +//
144 +// 2 same as 1, but in addition the JP now points to a BranchL containing a
145 +// single JP, which should be compressed into the parent branch (if there
146 +// is one, which is not the case for a top-level branch under a JPM)
147 +
148 +DBGCODE(uint8_t parentJPtype;) // parent branch JP type.
149 +
150 +FUNCTION static int j__udyDelWalk(
151 + Pjp_t Pjp, // current JP under which to delete.
152 + Word_t Index, // to delete.
153 + Word_t ParentLevel, // of parent branch.
154 + Pjpm_t Pjpm) // for returning info to top level.
155 +{
156 + Word_t pop1; // of a leaf.
157 + Word_t level; // of a leaf.
158 + uint8_t digit; // from Index, in current branch.
159 + Pjll_t PjllnewRaw; // address of newly allocated leaf.
160 + Pjll_t Pjllnew;
161 + int offset; // within a branch.
162 + int retcode; // return code: -1, 0, 1, 2.
163 +JUDYLCODE(Pjv_t PjvRaw;) // value area.
164 +JUDYLCODE(Pjv_t Pjv;)
165 +
166 + DBGCODE(level = 0;)
167 +
168 +ContinueDelWalk: // for modifying state without recursing.
169 +
170 +#ifdef TRACEJP
171 + JudyPrintJP(Pjp, "d", __LINE__);
172 +#endif
173 +
174 + switch (JU_JPTYPE(Pjp)) // entry: Pjp, Index.
175 + {
176 +
177 +
178 +// ****************************************************************************
179 +// LINEAR BRANCH:
180 +//
181 +// MACROS FOR COMMON CODE:
182 +//
183 +// Check for population too high to compress a branch to a leaf, meaning just
184 +// descend through the branch, with a purposeful off-by-one error that
185 +// constitutes hysteresis = 1. In other words, do not compress until the
186 +// branchs CURRENT population fits in the leaf, even BEFORE deleting one
187 +// index.
188 +//
189 +// Next is a label for branch-type-specific common code. Variables pop1,
190 +// level, digit, and Index are in the context.
191 +
192 +#define JU_BRANCH_KEEP(cLevel,MaxPop1,Next) \
193 + if (pop1 > (MaxPop1)) /* hysteresis = 1 */ \
194 + { \
195 + assert((cLevel) >= 2); \
196 + level = (cLevel); \
197 + digit = JU_DIGITATSTATE(Index, cLevel); \
198 + goto Next; \
199 + }
200 +
201 +// Support for generic calling of JudyLeaf*ToLeaf*() functions:
202 +//
203 +// Note: Cannot use JUDYLCODE() because this contains a comma.
204 +
205 +#ifdef JUDY1
206 +#define JU_PVALUEPASS // null.
207 +#else
208 +#define JU_PVALUEPASS Pjv,
209 +#endif
210 +
211 +// During compression to a leaf, check if a JP contains nothing but a
212 +// cJU_JPIMMED_*_01, in which case shortcut calling j__udyLeaf*ToLeaf*():
213 +//
214 +// Copy the index bytes from the jp_DcdPopO field (with possible truncation),
215 +// and continue the branch-JP-walk loop. Variables Pjp and Pleaf are in the
216 +// context.
217 +
218 +#define JU_BRANCH_COPY_IMMED_EVEN(cLevel,Pjp,ignore) \
219 + if (JU_JPTYPE(Pjp) == cJU_JPIMMED_1_01 + (cLevel) - 2) \
220 + { \
221 + *Pleaf++ = JU_JPDCDPOP0(Pjp); \
222 + JUDYLCODE(*Pjv++ = (Pjp)->jp_Addr;) \
223 + continue; /* for-loop */ \
224 + }
225 +
226 +#define JU_BRANCH_COPY_IMMED_ODD(cLevel,Pjp,CopyIndex) \
227 + if (JU_JPTYPE(Pjp) == cJU_JPIMMED_1_01 + (cLevel) - 2) \
228 + { \
229 + CopyIndex(Pleaf, (Word_t) (JU_JPDCDPOP0(Pjp))); \
230 + Pleaf += (cLevel); /* index size = level */ \
231 + JUDYLCODE(*Pjv++ = (Pjp)->jp_Addr;) \
232 + continue; /* for-loop */ \
233 + }
234 +
235 +// Compress a BranchL into a leaf one index size larger:
236 +//
237 +// Allocate a new leaf, walk the JPs in the old BranchL and pack their contents
238 +// into the new leaf (of type NewJPType), free the old BranchL, and finally
239 +// restart the switch to delete Index from the new leaf. (Note that all
240 +// BranchLs are the same size.) Variables Pjp, Pjpm, Pleaf, digit, and pop1
241 +// are in the context.
242 +
243 +#define JU_BRANCHL_COMPRESS(cLevel,LeafType,MaxPop1,NewJPType, \
244 + LeafToLeaf,Alloc,ValueArea, \
245 + CopyImmed,CopyIndex) \
246 + { \
247 + LeafType Pleaf; \
248 + Pjbl_t PjblRaw; \
249 + Pjbl_t Pjbl; \
250 + Word_t numJPs; \
251 + \
252 + if ((PjllnewRaw = Alloc(MaxPop1, Pjpm)) == 0) return(-1); \
253 + Pjllnew = P_JLL(PjllnewRaw); \
254 + Pleaf = (LeafType) Pjllnew; \
255 + JUDYLCODE(Pjv = ValueArea(Pleaf, MaxPop1);) \
256 + \
257 + PjblRaw = (Pjbl_t) (Pjp->jp_Addr); \
258 + Pjbl = P_JBL(PjblRaw); \
259 + numJPs = Pjbl->jbl_NumJPs; \
260 + \
261 + for (offset = 0; offset < numJPs; ++offset) \
262 + { \
263 + CopyImmed(cLevel, (Pjbl->jbl_jp) + offset, CopyIndex); \
264 + \
265 + pop1 = LeafToLeaf(Pleaf, JU_PVALUEPASS \
266 + (Pjbl->jbl_jp) + offset, \
267 + JU_DIGITTOSTATE(Pjbl->jbl_Expanse[offset], \
268 + cLevel), (Pvoid_t) Pjpm); \
269 + Pleaf = (LeafType) (((Word_t) Pleaf) + ((cLevel) * pop1)); \
270 + JUDYLCODE(Pjv += pop1;) \
271 + } \
272 + assert(((((Word_t) Pleaf) - ((Word_t) Pjllnew)) / (cLevel)) == (MaxPop1)); \
273 + JUDYLCODE(assert((Pjv - ValueArea(Pjllnew, MaxPop1)) == (MaxPop1));) \
274 + DBGCODE(JudyCheckSorted(Pjllnew, MaxPop1, cLevel);) \
275 + \
276 + j__udyFreeJBL(PjblRaw, Pjpm); \
277 + \
278 + Pjp->jp_Type = (NewJPType); \
279 + Pjp->jp_Addr = (Word_t) PjllnewRaw; \
280 + goto ContinueDelWalk; /* delete from new leaf */ \
281 + }
282 +
283 +// Overall common code for initial BranchL deletion handling:
284 +//
285 +// Assert that Index is in the branch, then see if the BranchL should be kept
286 +// or else compressed to a leaf. Variables Index, Pjp, and pop1 are in the
287 +// context.
288 +
289 +#define JU_BRANCHL(cLevel,MaxPop1,LeafType,NewJPType, \
290 + LeafToLeaf,Alloc,ValueArea,CopyImmed,CopyIndex) \
291 + \
292 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cLevel)); \
293 + assert(ParentLevel > (cLevel)); \
294 + \
295 + pop1 = JU_JPBRANCH_POP0(Pjp, cLevel) + 1; \
296 + JU_BRANCH_KEEP(cLevel, MaxPop1, BranchLKeep); \
297 + assert(pop1 == (MaxPop1)); \
298 + \
299 + JU_BRANCHL_COMPRESS(cLevel, LeafType, MaxPop1, NewJPType, \
300 + LeafToLeaf, Alloc, ValueArea, CopyImmed, CopyIndex)
301 +
302 +
303 +// END OF MACROS, START OF CASES:
304 +
305 + case cJU_JPBRANCH_L2:
306 +
307 + JU_BRANCHL(2, cJU_LEAF2_MAXPOP1, uint16_t *, cJU_JPLEAF2,
308 + j__udyLeaf1ToLeaf2, j__udyAllocJLL2, JL_LEAF2VALUEAREA,
309 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
310 +
311 + case cJU_JPBRANCH_L3:
312 +
313 + JU_BRANCHL(3, cJU_LEAF3_MAXPOP1, uint8_t *, cJU_JPLEAF3,
314 + j__udyLeaf2ToLeaf3, j__udyAllocJLL3, JL_LEAF3VALUEAREA,
315 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY3_LONG_TO_PINDEX);
316 +
317 +#ifdef JU_64BIT
318 + case cJU_JPBRANCH_L4:
319 +
320 + JU_BRANCHL(4, cJU_LEAF4_MAXPOP1, uint32_t *, cJU_JPLEAF4,
321 + j__udyLeaf3ToLeaf4, j__udyAllocJLL4, JL_LEAF4VALUEAREA,
322 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
323 +
324 + case cJU_JPBRANCH_L5:
325 +
326 + JU_BRANCHL(5, cJU_LEAF5_MAXPOP1, uint8_t *, cJU_JPLEAF5,
327 + j__udyLeaf4ToLeaf5, j__udyAllocJLL5, JL_LEAF5VALUEAREA,
328 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY5_LONG_TO_PINDEX);
329 +
330 + case cJU_JPBRANCH_L6:
331 +
332 + JU_BRANCHL(6, cJU_LEAF6_MAXPOP1, uint8_t *, cJU_JPLEAF6,
333 + j__udyLeaf5ToLeaf6, j__udyAllocJLL6, JL_LEAF6VALUEAREA,
334 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY6_LONG_TO_PINDEX);
335 +
336 + case cJU_JPBRANCH_L7:
337 +
338 + JU_BRANCHL(7, cJU_LEAF7_MAXPOP1, uint8_t *, cJU_JPLEAF7,
339 + j__udyLeaf6ToLeaf7, j__udyAllocJLL7, JL_LEAF7VALUEAREA,
340 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY7_LONG_TO_PINDEX);
341 +#endif // JU_64BIT
342 +
343 +// A top-level BranchL is different and cannot use JU_BRANCHL(): Dont try to
344 +// compress to a (LEAFW) leaf yet, but leave this for a later deletion
345 +// (hysteresis > 0); and the next JP type depends on the system word size; so
346 +// dont use JU_BRANCH_KEEP():
347 +
348 + case cJU_JPBRANCH_L:
349 + {
350 + Pjbl_t Pjbl;
351 + Word_t numJPs;
352 +
353 + level = cJU_ROOTSTATE;
354 + digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
355 +
356 + // fall through:
357 +
358 +
359 +// COMMON CODE FOR KEEPING AND DESCENDING THROUGH A BRANCHL:
360 +//
361 +// Come here with level and digit set.
362 +
363 +BranchLKeep:
364 + Pjbl = P_JBL(Pjp->jp_Addr);
365 + numJPs = Pjbl->jbl_NumJPs;
366 + assert(numJPs > 0);
367 + DBGCODE(parentJPtype = JU_JPTYPE(Pjp);)
368 +
369 +// Search for a match to the digit (valid Index => must find digit):
370 +
371 + for (offset = 0; (Pjbl->jbl_Expanse[offset]) != digit; ++offset)
372 + assert(offset < numJPs - 1);
373 +
374 + Pjp = (Pjbl->jbl_jp) + offset;
375 +
376 +// If not at a (deletable) JPIMMED_*_01, continue the walk (to descend through
377 +// the BranchL):
378 +
379 + assert(level >= 2);
380 + if ((JU_JPTYPE(Pjp)) != cJU_JPIMMED_1_01 + level - 2) break;
381 +
382 +// At JPIMMED_*_01: Ensure the index is in the right expanse, then delete the
383 +// Immed from the BranchL:
384 +//
385 +// Note: A BranchL has a fixed size and format regardless of numJPs.
386 +
387 + assert(JU_JPDCDPOP0(Pjp) == JU_TRIMTODCDSIZE(Index));
388 +
389 + JU_DELETEINPLACE(Pjbl->jbl_Expanse, numJPs, offset, ignore);
390 + JU_DELETEINPLACE(Pjbl->jbl_jp, numJPs, offset, ignore);
391 +
392 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjbl->jbl_Expanse),
393 + numJPs - 1, 1);)
394 +
395 +// If only one index left in the BranchL, indicate this to the caller:
396 +
397 + return ((--(Pjbl->jbl_NumJPs) <= 1) ? 2 : 1);
398 +
399 + } // case cJU_JPBRANCH_L.
400 +
401 +
402 +// ****************************************************************************
403 +// BITMAP BRANCH:
404 +//
405 +// MACROS FOR COMMON CODE:
406 +//
407 +// Note the reuse of common macros here, defined earlier: JU_BRANCH_KEEP(),
408 +// JU_PVALUE*.
409 +//
410 +// Compress a BranchB into a leaf one index size larger:
411 +//
412 +// Allocate a new leaf, walk the JPs in the old BranchB (one bitmap subexpanse
413 +// at a time) and pack their contents into the new leaf (of type NewJPType),
414 +// free the old BranchB, and finally restart the switch to delete Index from
415 +// the new leaf. Variables Pjp, Pjpm, Pleaf, digit, and pop1 are in the
416 +// context.
417 +//
418 +// Note: Its no accident that the interface to JU_BRANCHB_COMPRESS() is
419 +// identical to JU_BRANCHL_COMPRESS(). Only the details differ in how to
420 +// traverse the branchs JPs.
421 +
422 +#define JU_BRANCHB_COMPRESS(cLevel,LeafType,MaxPop1,NewJPType, \
423 + LeafToLeaf,Alloc,ValueArea, \
424 + CopyImmed,CopyIndex) \
425 + { \
426 + LeafType Pleaf; \
427 + Pjbb_t PjbbRaw; /* BranchB to compress */ \
428 + Pjbb_t Pjbb; \
429 + Word_t subexp; /* current subexpanse number */ \
430 + BITMAPB_t bitmap; /* portion for this subexpanse */ \
431 + Pjp_t Pjp2Raw; /* one subexpanses subarray */ \
432 + Pjp_t Pjp2; \
433 + \
434 + if ((PjllnewRaw = Alloc(MaxPop1, Pjpm)) == 0) return(-1); \
435 + Pjllnew = P_JLL(PjllnewRaw); \
436 + Pleaf = (LeafType) Pjllnew; \
437 + JUDYLCODE(Pjv = ValueArea(Pleaf, MaxPop1);) \
438 + \
439 + PjbbRaw = (Pjbb_t) (Pjp->jp_Addr); \
440 + Pjbb = P_JBB(PjbbRaw); \
441 + \
442 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp) \
443 + { \
444 + if ((bitmap = JU_JBB_BITMAP(Pjbb, subexp)) == 0) \
445 + continue; /* empty subexpanse */ \
446 + \
447 + digit = subexp * cJU_BITSPERSUBEXPB; \
448 + Pjp2Raw = JU_JBB_PJP(Pjbb, subexp); \
449 + Pjp2 = P_JP(Pjp2Raw); \
450 + assert(Pjp2 != (Pjp_t) NULL); \
451 + \
452 + for (offset = 0; bitmap != 0; bitmap >>= 1, ++digit) \
453 + { \
454 + if (! (bitmap & 1)) \
455 + continue; /* empty sub-subexpanse */ \
456 + \
457 + ++offset; /* before any continue */ \
458 + \
459 + CopyImmed(cLevel, Pjp2 + offset - 1, CopyIndex); \
460 + \
461 + pop1 = LeafToLeaf(Pleaf, JU_PVALUEPASS \
462 + Pjp2 + offset - 1, \
463 + JU_DIGITTOSTATE(digit, cLevel), \
464 + (Pvoid_t) Pjpm); \
465 + Pleaf = (LeafType) (((Word_t) Pleaf) + ((cLevel) * pop1)); \
466 + JUDYLCODE(Pjv += pop1;) \
467 + } \
468 + j__udyFreeJBBJP(Pjp2Raw, /* pop1 = */ offset, Pjpm); \
469 + } \
470 + assert(((((Word_t) Pleaf) - ((Word_t) Pjllnew)) / (cLevel)) == (MaxPop1)); \
471 + JUDYLCODE(assert((Pjv - ValueArea(Pjllnew, MaxPop1)) == (MaxPop1));) \
472 + DBGCODE(JudyCheckSorted(Pjllnew, MaxPop1, cLevel);) \
473 + \
474 + j__udyFreeJBB(PjbbRaw, Pjpm); \
475 + \
476 + Pjp->jp_Type = (NewJPType); \
477 + Pjp->jp_Addr = (Word_t) PjllnewRaw; \
478 + goto ContinueDelWalk; /* delete from new leaf */ \
479 + }
480 +
481 +// Overall common code for initial BranchB deletion handling:
482 +//
483 +// Assert that Index is in the branch, then see if the BranchB should be kept
484 +// or else compressed to a leaf. Variables Index, Pjp, and pop1 are in the
485 +// context.
486 +
487 +#define JU_BRANCHB(cLevel,MaxPop1,LeafType,NewJPType, \
488 + LeafToLeaf,Alloc,ValueArea,CopyImmed,CopyIndex) \
489 + \
490 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cLevel)); \
491 + assert(ParentLevel > (cLevel)); \
492 + \
493 + pop1 = JU_JPBRANCH_POP0(Pjp, cLevel) + 1; \
494 + JU_BRANCH_KEEP(cLevel, MaxPop1, BranchBKeep); \
495 + assert(pop1 == (MaxPop1)); \
496 + \
497 + JU_BRANCHB_COMPRESS(cLevel, LeafType, MaxPop1, NewJPType, \
498 + LeafToLeaf, Alloc, ValueArea, CopyImmed, CopyIndex)
499 +
500 +
501 +// END OF MACROS, START OF CASES:
502 +//
503 +// Note: Its no accident that the macro calls for these cases is nearly
504 +// identical to the code for BranchLs.
505 +
506 + case cJU_JPBRANCH_B2:
507 +
508 + JU_BRANCHB(2, cJU_LEAF2_MAXPOP1, uint16_t *, cJU_JPLEAF2,
509 + j__udyLeaf1ToLeaf2, j__udyAllocJLL2, JL_LEAF2VALUEAREA,
510 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
511 +
512 + case cJU_JPBRANCH_B3:
513 +
514 + JU_BRANCHB(3, cJU_LEAF3_MAXPOP1, uint8_t *, cJU_JPLEAF3,
515 + j__udyLeaf2ToLeaf3, j__udyAllocJLL3, JL_LEAF3VALUEAREA,
516 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY3_LONG_TO_PINDEX);
517 +
518 +#ifdef JU_64BIT
519 + case cJU_JPBRANCH_B4:
520 +
521 + JU_BRANCHB(4, cJU_LEAF4_MAXPOP1, uint32_t *, cJU_JPLEAF4,
522 + j__udyLeaf3ToLeaf4, j__udyAllocJLL4, JL_LEAF4VALUEAREA,
523 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
524 +
525 + case cJU_JPBRANCH_B5:
526 +
527 + JU_BRANCHB(5, cJU_LEAF5_MAXPOP1, uint8_t *, cJU_JPLEAF5,
528 + j__udyLeaf4ToLeaf5, j__udyAllocJLL5, JL_LEAF5VALUEAREA,
529 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY5_LONG_TO_PINDEX);
530 +
531 + case cJU_JPBRANCH_B6:
532 +
533 + JU_BRANCHB(6, cJU_LEAF6_MAXPOP1, uint8_t *, cJU_JPLEAF6,
534 + j__udyLeaf5ToLeaf6, j__udyAllocJLL6, JL_LEAF6VALUEAREA,
535 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY6_LONG_TO_PINDEX);
536 +
537 + case cJU_JPBRANCH_B7:
538 +
539 + JU_BRANCHB(7, cJU_LEAF7_MAXPOP1, uint8_t *, cJU_JPLEAF7,
540 + j__udyLeaf6ToLeaf7, j__udyAllocJLL7, JL_LEAF7VALUEAREA,
541 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY7_LONG_TO_PINDEX);
542 +#endif // JU_64BIT
543 +
544 +// A top-level BranchB is different and cannot use JU_BRANCHB(): Dont try to
545 +// compress to a (LEAFW) leaf yet, but leave this for a later deletion
546 +// (hysteresis > 0); and the next JP type depends on the system word size; so
547 +// dont use JU_BRANCH_KEEP():
548 +
549 + case cJU_JPBRANCH_B:
550 + {
551 + Pjbb_t Pjbb; // BranchB to modify.
552 + Word_t subexp; // current subexpanse number.
553 + Word_t subexp2; // in second-level loop.
554 + BITMAPB_t bitmap; // portion for this subexpanse.
555 + BITMAPB_t bitmask; // with digits bit set.
556 + Pjp_t Pjp2Raw; // one subexpanses subarray.
557 + Pjp_t Pjp2;
558 + Word_t numJPs; // in one subexpanse.
559 +
560 + level = cJU_ROOTSTATE;
561 + digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
562 +
563 + // fall through:
564 +
565 +
566 +// COMMON CODE FOR KEEPING AND DESCENDING THROUGH A BRANCHB:
567 +//
568 +// Come here with level and digit set.
569 +
570 +BranchBKeep:
571 + Pjbb = P_JBB(Pjp->jp_Addr);
572 + subexp = digit / cJU_BITSPERSUBEXPB;
573 + bitmap = JU_JBB_BITMAP(Pjbb, subexp);
574 + bitmask = JU_BITPOSMASKB(digit);
575 + assert(bitmap & bitmask); // Index valid => digits bit is set.
576 + DBGCODE(parentJPtype = JU_JPTYPE(Pjp);)
577 +
578 +// Compute digits offset into the bitmap, with a fast method if all bits are
579 +// set:
580 +
581 + offset = ((bitmap == (cJU_FULLBITMAPB)) ?
582 + digit % cJU_BITSPERSUBEXPB :
583 + j__udyCountBitsB(bitmap & JU_MASKLOWEREXC(bitmask)));
584 +
585 + Pjp2Raw = JU_JBB_PJP(Pjbb, subexp);
586 + Pjp2 = P_JP(Pjp2Raw);
587 + assert(Pjp2 != (Pjp_t) NULL); // valid subexpanse pointer.
588 +
589 +// If not at a (deletable) JPIMMED_*_01, continue the walk (to descend through
590 +// the BranchB):
591 +
592 + if (JU_JPTYPE(Pjp2 + offset) != cJU_JPIMMED_1_01 + level - 2)
593 + {
594 + Pjp = Pjp2 + offset;
595 + break;
596 + }
597 +
598 +// At JPIMMED_*_01: Ensure the index is in the right expanse, then delete the
599 +// Immed from the BranchB:
600 +
601 + assert(JU_JPDCDPOP0(Pjp2 + offset)
602 + == JU_TRIMTODCDSIZE(Index));
603 +
604 +// If only one index is left in the subexpanse, free the JP array:
605 +
606 + if ((numJPs = j__udyCountBitsB(bitmap)) == 1)
607 + {
608 + j__udyFreeJBBJP(Pjp2Raw, /* pop1 = */ 1, Pjpm);
609 + JU_JBB_PJP(Pjbb, subexp) = (Pjp_t) NULL;
610 + }
611 +
612 +// Shrink JP array in-place:
613 +
614 + else if (JU_BRANCHBJPGROWINPLACE(numJPs - 1))
615 + {
616 + assert(numJPs > 0);
617 + JU_DELETEINPLACE(Pjp2, numJPs, offset, ignore);
618 + }
619 +
620 +// JP array would end up too large; compress it to a smaller one:
621 +
622 + else
623 + {
624 + Pjp_t PjpnewRaw;
625 + Pjp_t Pjpnew;
626 +
627 + if ((PjpnewRaw = j__udyAllocJBBJP(numJPs - 1, Pjpm))
628 + == (Pjp_t) NULL) return(-1);
629 + Pjpnew = P_JP(PjpnewRaw);
630 +
631 + JU_DELETECOPY(Pjpnew, Pjp2, numJPs, offset, ignore);
632 + j__udyFreeJBBJP(Pjp2Raw, numJPs, Pjpm); // old.
633 +
634 + JU_JBB_PJP(Pjbb, subexp) = PjpnewRaw;
635 + }
636 +
637 +// Clear digits bit in the bitmap:
638 +
639 + JU_JBB_BITMAP(Pjbb, subexp) ^= bitmask;
640 +
641 +// If the current subexpanse alone is still too large for a BranchL (with
642 +// hysteresis = 1), the delete is all done:
643 +
644 + if (numJPs > cJU_BRANCHLMAXJPS) return(1);
645 +
646 +// Consider shrinking the current BranchB to a BranchL:
647 +//
648 +// Check the numbers of JPs in other subexpanses in the BranchL. Upon reaching
649 +// the critical number of numJPs (which could be right at the start; again,
650 +// with hysteresis = 1), its faster to just watch for any non-empty subexpanse
651 +// than to count bits in each subexpanse. Upon finding too many JPs, give up
652 +// on shrinking the BranchB.
653 +
654 + for (subexp2 = 0; subexp2 < cJU_NUMSUBEXPB; ++subexp2)
655 + {
656 + if (subexp2 == subexp) continue; // skip current subexpanse.
657 +
658 + if ((numJPs == cJU_BRANCHLMAXJPS) ?
659 + JU_JBB_BITMAP(Pjbb, subexp2) :
660 + ((numJPs += j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp2)))
661 + > cJU_BRANCHLMAXJPS))
662 + {
663 + return(1); // too many JPs, cannot shrink.
664 + }
665 + }
666 +
667 +// Shrink current BranchB to a BranchL:
668 +//
669 +// Note: In this rare case, ignore the return value, do not pass it to the
670 +// caller, because the deletion is already successfully completed and the
671 +// caller(s) must decrement population counts. The only errors expected from
672 +// this call are JU_ERRNO_NOMEM and JU_ERRNO_OVERRUN, neither of which is worth
673 +// forwarding from this point. See also 4.1, 4.8, and 4.15 of this file.
674 +
675 + (void) j__udyBranchBToBranchL(Pjp, Pjpm);
676 + return(1);
677 +
678 + } // case.
679 +
680 +
681 +// ****************************************************************************
682 +// UNCOMPRESSED BRANCH:
683 +//
684 +// MACROS FOR COMMON CODE:
685 +//
686 +// Note the reuse of common macros here, defined earlier: JU_PVALUE*.
687 +//
688 +// Compress a BranchU into a leaf one index size larger:
689 +//
690 +// Allocate a new leaf, walk the JPs in the old BranchU and pack their contents
691 +// into the new leaf (of type NewJPType), free the old BranchU, and finally
692 +// restart the switch to delete Index from the new leaf. Variables Pjp, Pjpm,
693 +// digit, and pop1 are in the context.
694 +//
695 +// Note: Its no accident that the interface to JU_BRANCHU_COMPRESS() is
696 +// nearly identical to JU_BRANCHL_COMPRESS(); just NullJPType is added. The
697 +// details differ in how to traverse the branchs JPs --
698 +//
699 +// -- and also, what to do upon encountering a cJU_JPIMMED_*_01 JP. In
700 +// BranchLs and BranchBs the JP must be deleted, but in a BranchU its merely
701 +// converted to a null JP, and this is done by other switch cases, so the "keep
702 +// branch" situation is simpler here and JU_BRANCH_KEEP() is not used. Also,
703 +// theres no code to convert a BranchU to a BranchB since counting the JPs in
704 +// a BranchU is (at least presently) expensive, and besides, keeping around a
705 +// BranchU is form of hysteresis.
706 +
707 +#define JU_BRANCHU_COMPRESS(cLevel,LeafType,MaxPop1,NullJPType,NewJPType, \
708 + LeafToLeaf,Alloc,ValueArea,CopyImmed,CopyIndex) \
709 + { \
710 + LeafType Pleaf; \
711 + Pjbu_t PjbuRaw = (Pjbu_t) (Pjp->jp_Addr); \
712 + Pjp_t Pjp2 = JU_JBU_PJP0(Pjp); \
713 + Word_t ldigit; /* larger than uint8_t */ \
714 + \
715 + if ((PjllnewRaw = Alloc(MaxPop1, Pjpm)) == 0) return(-1); \
716 + Pjllnew = P_JLL(PjllnewRaw); \
717 + Pleaf = (LeafType) Pjllnew; \
718 + JUDYLCODE(Pjv = ValueArea(Pleaf, MaxPop1);) \
719 + \
720 + for (ldigit = 0; ldigit < cJU_BRANCHUNUMJPS; ++ldigit, ++Pjp2) \
721 + { \
722 + /* fast-process common types: */ \
723 + if (JU_JPTYPE(Pjp2) == (NullJPType)) continue; \
724 + CopyImmed(cLevel, Pjp2, CopyIndex); \
725 + \
726 + pop1 = LeafToLeaf(Pleaf, JU_PVALUEPASS Pjp2, \
727 + JU_DIGITTOSTATE(ldigit, cLevel), \
728 + (Pvoid_t) Pjpm); \
729 + Pleaf = (LeafType) (((Word_t) Pleaf) + ((cLevel) * pop1)); \
730 + JUDYLCODE(Pjv += pop1;) \
731 + } \
732 + assert(((((Word_t) Pleaf) - ((Word_t) Pjllnew)) / (cLevel)) == (MaxPop1)); \
733 + JUDYLCODE(assert((Pjv - ValueArea(Pjllnew, MaxPop1)) == (MaxPop1));) \
734 + DBGCODE(JudyCheckSorted(Pjllnew, MaxPop1, cLevel);) \
735 + \
736 + j__udyFreeJBU(PjbuRaw, Pjpm); \
737 + \
738 + Pjp->jp_Type = (NewJPType); \
739 + Pjp->jp_Addr = (Word_t) PjllnewRaw; \
740 + goto ContinueDelWalk; /* delete from new leaf */ \
741 + }
742 +
743 +// Overall common code for initial BranchU deletion handling:
744 +//
745 +// Assert that Index is in the branch, then see if a BranchU should be kept or
746 +// else compressed to a leaf. Variables level, Index, Pjp, and pop1 are in the
747 +// context.
748 +//
749 +// Note: BranchU handling differs from BranchL and BranchB as described above.
750 +
751 +#define JU_BRANCHU(cLevel,MaxPop1,LeafType,NullJPType,NewJPType, \
752 + LeafToLeaf,Alloc,ValueArea,CopyImmed,CopyIndex) \
753 + \
754 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cLevel)); \
755 + assert(ParentLevel > (cLevel)); \
756 + DBGCODE(parentJPtype = JU_JPTYPE(Pjp);) \
757 + \
758 + pop1 = JU_JPBRANCH_POP0(Pjp, cLevel) + 1; \
759 + \
760 + if (pop1 > (MaxPop1)) /* hysteresis = 1 */ \
761 + { \
762 + level = (cLevel); \
763 + Pjp = P_JP(Pjp->jp_Addr) + JU_DIGITATSTATE(Index, cLevel);\
764 + break; /* descend to next level */ \
765 + } \
766 + assert(pop1 == (MaxPop1)); \
767 + \
768 + JU_BRANCHU_COMPRESS(cLevel, LeafType, MaxPop1, NullJPType, NewJPType, \
769 + LeafToLeaf, Alloc, ValueArea, CopyImmed, CopyIndex)
770 +
771 +
772 +// END OF MACROS, START OF CASES:
773 +//
774 +// Note: Its no accident that the macro calls for these cases is nearly
775 +// identical to the code for BranchLs, with the addition of cJU_JPNULL*
776 +// parameters only needed for BranchUs.
777 +
778 + case cJU_JPBRANCH_U2:
779 +
780 + JU_BRANCHU(2, cJU_LEAF2_MAXPOP1, uint16_t *,
781 + cJU_JPNULL1, cJU_JPLEAF2,
782 + j__udyLeaf1ToLeaf2, j__udyAllocJLL2, JL_LEAF2VALUEAREA,
783 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
784 +
785 + case cJU_JPBRANCH_U3:
786 +
787 + JU_BRANCHU(3, cJU_LEAF3_MAXPOP1, uint8_t *,
788 + cJU_JPNULL2, cJU_JPLEAF3,
789 + j__udyLeaf2ToLeaf3, j__udyAllocJLL3, JL_LEAF3VALUEAREA,
790 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY3_LONG_TO_PINDEX);
791 +
792 +#ifdef JU_64BIT
793 + case cJU_JPBRANCH_U4:
794 +
795 + JU_BRANCHU(4, cJU_LEAF4_MAXPOP1, uint32_t *,
796 + cJU_JPNULL3, cJU_JPLEAF4,
797 + j__udyLeaf3ToLeaf4, j__udyAllocJLL4, JL_LEAF4VALUEAREA,
798 + JU_BRANCH_COPY_IMMED_EVEN, ignore);
799 +
800 + case cJU_JPBRANCH_U5:
801 +
802 + JU_BRANCHU(5, cJU_LEAF5_MAXPOP1, uint8_t *,
803 + cJU_JPNULL4, cJU_JPLEAF5,
804 + j__udyLeaf4ToLeaf5, j__udyAllocJLL5, JL_LEAF5VALUEAREA,
805 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY5_LONG_TO_PINDEX);
806 +
807 + case cJU_JPBRANCH_U6:
808 +
809 + JU_BRANCHU(6, cJU_LEAF6_MAXPOP1, uint8_t *,
810 + cJU_JPNULL5, cJU_JPLEAF6,
811 + j__udyLeaf5ToLeaf6, j__udyAllocJLL6, JL_LEAF6VALUEAREA,
812 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY6_LONG_TO_PINDEX);
813 +
814 + case cJU_JPBRANCH_U7:
815 +
816 + JU_BRANCHU(7, cJU_LEAF7_MAXPOP1, uint8_t *,
817 + cJU_JPNULL6, cJU_JPLEAF7,
818 + j__udyLeaf6ToLeaf7, j__udyAllocJLL7, JL_LEAF7VALUEAREA,
819 + JU_BRANCH_COPY_IMMED_ODD, JU_COPY7_LONG_TO_PINDEX);
820 +#endif // JU_64BIT
821 +
822 +// A top-level BranchU is different and cannot use JU_BRANCHU(): Dont try to
823 +// compress to a (LEAFW) leaf yet, but leave this for a later deletion
824 +// (hysteresis > 0); just descend through the BranchU:
825 +
826 + case cJU_JPBRANCH_U:
827 +
828 + DBGCODE(parentJPtype = JU_JPTYPE(Pjp);)
829 +
830 + level = cJU_ROOTSTATE;
831 + Pjp = P_JP(Pjp->jp_Addr) + JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
832 + break;
833 +
834 +
835 +// ****************************************************************************
836 +// LINEAR LEAF:
837 +//
838 +// State transitions while deleting an Index, the inverse of the similar table
839 +// that appears in JudyIns.c:
840 +//
841 +// Note: In JudyIns.c this table is not needed and does not appear until the
842 +// Immed handling code; because once a Leaf is reached upon growing the tree,
843 +// the situation remains simpler, but for deleting indexes, the complexity
844 +// arises when leaves must compress to Immeds.
845 +//
846 +// Note: There are other transitions possible too, not shown here, such as to
847 +// a leaf one level higher.
848 +//
849 +// (Yes, this is very terse... Study it and it will make sense.)
850 +// (Note, parts of this diagram are repeated below for quick reference.)
851 +//
852 +// reformat JP here for Judy1 only, from word-1 to word-2
853 +// |
854 +// JUDY1 && JU_64BIT JUDY1 || JU_64BIT |
855 +// V
856 +// (*) Leaf1 [[ => 1_15..08 ] => 1_07 => ... => 1_04 ] => 1_03 => 1_02 => 1_01
857 +// Leaf2 [[ => 2_07..04 ] => 2_03 => 2_02 ] => 2_01
858 +// Leaf3 [[ => 3_05..03 ] => 3_02 ] => 3_01
859 +// JU_64BIT only:
860 +// Leaf4 [[ => 4_03..02 ]] => 4_01
861 +// Leaf5 [[ => 5_03..02 ]] => 5_01
862 +// Leaf6 [[ => 6_02 ]] => 6_01
863 +// Leaf7 [[ => 7_02 ]] => 7_01
864 +//
865 +// (*) For Judy1 & 64-bit, go directly from a LeafB1 to cJU_JPIMMED_1_15; skip
866 +// Leaf1, as described in Judy1.h regarding cJ1_JPLEAF1.
867 +//
868 +// MACROS FOR COMMON CODE:
869 +//
870 +// (De)compress a LeafX into a LeafY one index size (cIS) larger (X+1 = Y):
871 +//
872 +// This is only possible when the current leaf is under a narrow pointer
873 +// ((ParentLevel - 1) > cIS) and its population fits in a higher-level leaf.
874 +// Variables ParentLevel, pop1, PjllnewRaw, Pjllnew, Pjpm, and Index are in the
875 +// context.
876 +//
877 +// Note: Doing an "uplevel" doesnt occur until the old leaf can be compressed
878 +// up one level BEFORE deleting an index; that is, hysteresis = 1.
879 +//
880 +// Note: LeafType, MaxPop1, NewJPType, and Alloc refer to the up-level leaf,
881 +// not the current leaf.
882 +//
883 +// Note: 010327: Fixed bug where the jp_DcdPopO next-uplevel digit (byte)
884 +// above the current Pop0 value was not being cleared. When upleveling, one
885 +// digit in jp_DcdPopO "moves" from being part of the Dcd subfield to the Pop0
886 +// subfield, but since a leaf maxpop1 is known to be <= 1 byte in size, the new
887 +// Pop0 byte should always be zero. This is easy to overlook because
888 +// JU_JPLEAF_POP0() "knows" to only use the LSB of Pop0 (for efficiency) and
889 +// ignore the other bytes... Until someone uses cJU_POP0MASK() instead of
890 +// JU_JPLEAF_POP0(), such as in JudyInsertBranch.c.
891 +//
892 +// TBD: Should JudyInsertBranch.c use JU_JPLEAF_POP0() rather than
893 +// cJU_POP0MASK(), for efficiency? Does it know for sure its a narrow pointer
894 +// under the leaf? Not necessarily.
895 +
896 +#define JU_LEAF_UPLEVEL(cIS,LeafType,MaxPop1,NewJPType,LeafToLeaf, \
897 + Alloc,ValueArea) \
898 + \
899 + assert(((ParentLevel - 1) == (cIS)) || (pop1 >= (MaxPop1))); \
900 + \
901 + if (((ParentLevel - 1) > (cIS)) /* under narrow pointer */ \
902 + && (pop1 == (MaxPop1))) /* hysteresis = 1 */ \
903 + { \
904 + Word_t D_cdP0; \
905 + if ((PjllnewRaw = Alloc(MaxPop1, Pjpm)) == 0) return(-1); \
906 + Pjllnew = P_JLL(PjllnewRaw); \
907 + JUDYLCODE(Pjv = ValueArea((LeafType) Pjllnew, MaxPop1);) \
908 + \
909 + (void) LeafToLeaf((LeafType) Pjllnew, JU_PVALUEPASS Pjp, \
910 + Index & cJU_DCDMASK(cIS), /* TBD, Doug says */ \
911 + (Pvoid_t) Pjpm); \
912 + DBGCODE(JudyCheckSorted(Pjllnew, MaxPop1, cIS + 1);) \
913 + \
914 + D_cdP0 = (~cJU_MASKATSTATE((cIS) + 1)) & JU_JPDCDPOP0(Pjp); \
915 + JU_JPSETADT(Pjp, (Word_t)PjllnewRaw, D_cdP0, NewJPType); \
916 + goto ContinueDelWalk; /* delete from new leaf */ \
917 + }
918 +
919 +
920 +// For Leaf3, only support JU_LEAF_UPLEVEL on a 64-bit system, and for Leaf7,
921 +// there is no JU_LEAF_UPLEVEL:
922 +//
923 +// Note: Theres no way here to go from Leaf3 [Leaf7] to LEAFW on a 32-bit
924 +// [64-bit] system. Thats handled in the main code, because its different in
925 +// that a JPM is involved.
926 +
927 +#ifndef JU_64BIT // 32-bit.
928 +#define JU_LEAF_UPLEVEL64(cIS,LeafType,MaxPop1,NewJPType,LeafToLeaf, \
929 + Alloc,ValueArea) // null.
930 +#else
931 +#define JU_LEAF_UPLEVEL64(cIS,LeafType,MaxPop1,NewJPType,LeafToLeaf, \
932 + Alloc,ValueArea) \
933 + JU_LEAF_UPLEVEL (cIS,LeafType,MaxPop1,NewJPType,LeafToLeaf, \
934 + Alloc,ValueArea)
935 +#define JU_LEAF_UPLEVEL_NONE(cIS,LeafType,MaxPop1,NewJPType,LeafToLeaf, \
936 + Alloc,ValueArea) // null.
937 +#endif
938 +
939 +// Compress a Leaf* with pop1 = 2, or a JPIMMED_*_02, into a JPIMMED_*_01:
940 +//
941 +// Copy whichever Index is NOT being deleted (and assert that the other one is
942 +// found; Index must be valid). This requires special handling of the Index
943 +// bytes (and value area). Variables Pjp, Index, offset, and Pleaf are in the
944 +// context, offset is modified to the undeleted Index, and Pjp is modified
945 +// including jp_Addr.
946 +
947 +
948 +#define JU_TOIMMED_01_EVEN(cIS,ignore1,ignore2) \
949 +{ \
950 + Word_t D_cdP0; \
951 + Word_t A_ddr = 0; \
952 + uint8_t T_ype = JU_JPTYPE(Pjp); \
953 + offset = (Pleaf[0] == JU_LEASTBYTES(Index, cIS)); /* undeleted Ind */ \
954 + assert(Pleaf[offset ? 0 : 1] == JU_LEASTBYTES(Index, cIS)); \
955 + D_cdP0 = (Index & cJU_DCDMASK(cIS)) | Pleaf[offset]; \
956 +JUDYLCODE(A_ddr = Pjv[offset];) \
957 + JU_JPSETADT(Pjp, A_ddr, D_cdP0, T_ype); \
958 +}
959 +
960 +#define JU_TOIMMED_01_ODD(cIS,SearchLeaf,CopyPIndex) \
961 + { \
962 + Word_t D_cdP0; \
963 + Word_t A_ddr = 0; \
964 + uint8_t T_ype = JU_JPTYPE(Pjp); \
965 + \
966 + offset = SearchLeaf(Pleaf, 2, Index); \
967 + assert(offset >= 0); /* Index must be valid */ \
968 + CopyPIndex(D_cdP0, & (Pleaf[offset ? 0 : cIS])); \
969 + D_cdP0 |= Index & cJU_DCDMASK(cIS); \
970 + JUDYLCODE(A_ddr = Pjv[offset ? 0 : 1];) \
971 + JU_JPSETADT(Pjp, A_ddr, D_cdP0, T_ype); \
972 + }
973 +
974 +
975 +// Compress a Leaf* into a JPIMMED_*_0[2+]:
976 +//
977 +// This occurs as soon as its possible, with hysteresis = 0. Variables pop1,
978 +// Pleaf, offset, and Pjpm are in the context.
979 +//
980 +// TBD: Explain why hysteresis = 0 here, rather than > 0. Probably because
981 +// the insert code assumes if the population is small enough, an Immed is used,
982 +// not a leaf.
983 +//
984 +// The differences between Judy1 and JudyL with respect to value area handling
985 +// are just too large for completely common code between them... Oh well, some
986 +// big ifdefs follow.
987 +
988 +#ifdef JUDY1
989 +
990 +#define JU_LEAF_TOIMMED(cIS,LeafType,MaxPop1,BaseJPType,ignore1,\
991 + ignore2,ignore3,ignore4, \
992 + DeleteCopy,FreeLeaf) \
993 + \
994 + assert(pop1 > (MaxPop1)); \
995 + \
996 + if ((pop1 - 1) == (MaxPop1)) /* hysteresis = 0 */ \
997 + { \
998 + Pjll_t PjllRaw = (Pjll_t) (Pjp->jp_Addr); \
999 + DeleteCopy((LeafType) (Pjp->jp_1Index), Pleaf, pop1, offset, cIS); \
1000 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjp->jp_1Index), pop1-1, cIS);) \
1001 + Pjp->jp_Type = (BaseJPType) - 1 + (MaxPop1) - 1; \
1002 + FreeLeaf(PjllRaw, pop1, Pjpm); \
1003 + return(1); \
1004 + }
1005 +
1006 +#else // JUDYL
1007 +
1008 +// Pjv is also in the context.
1009 +
1010 +#define JU_LEAF_TOIMMED(cIS,LeafType,MaxPop1,BaseJPType,ignore1,\
1011 + ignore2,ignore3,ignore4, \
1012 + DeleteCopy,FreeLeaf) \
1013 + \
1014 + assert(pop1 > (MaxPop1)); \
1015 + \
1016 + if ((pop1 - 1) == (MaxPop1)) /* hysteresis = 0 */ \
1017 + { \
1018 + Pjll_t PjllRaw = (Pjll_t) (Pjp->jp_Addr); \
1019 + Pjv_t PjvnewRaw; \
1020 + Pjv_t Pjvnew; \
1021 + \
1022 + if ((PjvnewRaw = j__udyLAllocJV(pop1 - 1, Pjpm)) \
1023 + == (Pjv_t) NULL) return(-1); \
1024 + JUDYLCODE(Pjvnew = P_JV(PjvnewRaw);) \
1025 + \
1026 + DeleteCopy((LeafType) (Pjp->jp_LIndex), Pleaf, pop1, offset, cIS); \
1027 + JU_DELETECOPY(Pjvnew, Pjv, pop1, offset, cIS); \
1028 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjp->jp_LIndex), pop1-1, cIS);) \
1029 + FreeLeaf(PjllRaw, pop1, Pjpm); \
1030 + Pjp->jp_Addr = (Word_t) PjvnewRaw; \
1031 + Pjp->jp_Type = (BaseJPType) - 2 + (MaxPop1); \
1032 + return(1); \
1033 + }
1034 +
1035 +// A complicating factor for JudyL & 32-bit is that Leaf2..3, and for JudyL &
1036 +// 64-bit Leaf 4..7, go directly to an Immed*_01, where the value is stored in
1037 +// jp_Addr and not in a separate LeafV. For efficiency, use the following
1038 +// macro in cases where it can apply; it is rigged to do the right thing.
1039 +// Unfortunately, this requires the calling code to "know" the transition table
1040 +// and call the right macro.
1041 +//
1042 +// This variant compresses a Leaf* with pop1 = 2 into a JPIMMED_*_01:
1043 +
1044 +#define JU_LEAF_TOIMMED_01(cIS,LeafType,MaxPop1,ignore,Immed01JPType, \
1045 + ToImmed,SearchLeaf,CopyPIndex, \
1046 + DeleteCopy,FreeLeaf) \
1047 + \
1048 + assert(pop1 > (MaxPop1)); \
1049 + \
1050 + if ((pop1 - 1) == (MaxPop1)) /* hysteresis = 0 */ \
1051 + { \
1052 + Pjll_t PjllRaw = (Pjll_t) (Pjp->jp_Addr); \
1053 + ToImmed(cIS, SearchLeaf, CopyPIndex); \
1054 + FreeLeaf(PjllRaw, pop1, Pjpm); \
1055 + Pjp->jp_Type = (Immed01JPType); \
1056 + return(1); \
1057 + }
1058 +#endif // JUDYL
1059 +
1060 +// See comments above about these:
1061 +//
1062 +// Note: Here "23" means index size 2 or 3, and "47" means 4..7.
1063 +
1064 +#if (defined(JUDY1) || defined(JU_64BIT))
1065 +#define JU_LEAF_TOIMMED_23(cIS,LeafType,MaxPop1,BaseJPType,Immed01JPType, \
1066 + ToImmed,SearchLeaf,CopyPIndex, \
1067 + DeleteCopy,FreeLeaf) \
1068 + JU_LEAF_TOIMMED( cIS,LeafType,MaxPop1,BaseJPType,ignore1, \
1069 + ignore2,ignore3,ignore4, \
1070 + DeleteCopy,FreeLeaf)
1071 +#else // JUDYL && 32-bit
1072 +#define JU_LEAF_TOIMMED_23(cIS,LeafType,MaxPop1,BaseJPType,Immed01JPType, \
1073 + ToImmed,SearchLeaf,CopyPIndex, \
1074 + DeleteCopy,FreeLeaf) \
1075 + JU_LEAF_TOIMMED_01(cIS,LeafType,MaxPop1,ignore,Immed01JPType, \
1076 + ToImmed,SearchLeaf,CopyPIndex, \
1077 + DeleteCopy,FreeLeaf)
1078 +#endif
1079 +
1080 +#ifdef JU_64BIT
1081 +#ifdef JUDY1
1082 +#define JU_LEAF_TOIMMED_47(cIS,LeafType,MaxPop1,BaseJPType,Immed01JPType, \
1083 + ToImmed,SearchLeaf,CopyPIndex, \
1084 + DeleteCopy,FreeLeaf) \
1085 + JU_LEAF_TOIMMED( cIS,LeafType,MaxPop1,BaseJPType,ignore1, \
1086 + ignore2,ignore3,ignore4, \
1087 + DeleteCopy,FreeLeaf)
1088 +#else // JUDYL && 64-bit
1089 +#define JU_LEAF_TOIMMED_47(cIS,LeafType,MaxPop1,BaseJPType,Immed01JPType, \
1090 + ToImmed,SearchLeaf,CopyPIndex, \
1091 + DeleteCopy,FreeLeaf) \
1092 + JU_LEAF_TOIMMED_01(cIS,LeafType,MaxPop1,ignore,Immed01JPType, \
1093 + ToImmed,SearchLeaf,CopyPIndex, \
1094 + DeleteCopy,FreeLeaf)
1095 +#endif // JUDYL
1096 +#endif // JU_64BIT
1097 +
1098 +// Compress a Leaf* in place:
1099 +//
1100 +// Here hysteresis = 0 (no memory is wasted). Variables pop1, Pleaf, and
1101 +// offset, and for JudyL, Pjv, are in the context.
1102 +
1103 +#ifdef JUDY1
1104 +#define JU_LEAF_INPLACE(cIS,GrowInPlace,DeleteInPlace) \
1105 + if (GrowInPlace(pop1 - 1)) /* hysteresis = 0 */ \
1106 + { \
1107 + DeleteInPlace(Pleaf, pop1, offset, cIS); \
1108 + DBGCODE(JudyCheckSorted(Pleaf, pop1 - 1, cIS);) \
1109 + return(1); \
1110 + }
1111 +#else
1112 +#define JU_LEAF_INPLACE(cIS,GrowInPlace,DeleteInPlace) \
1113 + if (GrowInPlace(pop1 - 1)) /* hysteresis = 0 */ \
1114 + { \
1115 + DeleteInPlace(Pleaf, pop1, offset, cIS); \
1116 +/**/ JU_DELETEINPLACE(Pjv, pop1, offset, ignore); \
1117 + DBGCODE(JudyCheckSorted(Pleaf, pop1 - 1, cIS);) \
1118 + return(1); \
1119 + }
1120 +#endif
1121 +
1122 +// Compress a Leaf* into a smaller memory object of the same JP type:
1123 +//
1124 +// Variables PjllnewRaw, Pjllnew, Pleafpop1, Pjpm, PleafRaw, Pleaf, and offset
1125 +// are in the context.
1126 +
1127 +#ifdef JUDY1
1128 +
1129 +#define JU_LEAF_SHRINK(cIS,LeafType,DeleteCopy,Alloc,FreeLeaf,ValueArea) \
1130 + if ((PjllnewRaw = Alloc(pop1 - 1, Pjpm)) == 0) return(-1); \
1131 + Pjllnew = P_JLL(PjllnewRaw); \
1132 + DeleteCopy((LeafType) Pjllnew, Pleaf, pop1, offset, cIS); \
1133 + DBGCODE(JudyCheckSorted(Pjllnew, pop1 - 1, cIS);) \
1134 + FreeLeaf(PleafRaw, pop1, Pjpm); \
1135 + Pjp->jp_Addr = (Word_t) PjllnewRaw; \
1136 + return(1)
1137 +
1138 +#else // JUDYL
1139 +
1140 +#define JU_LEAF_SHRINK(cIS,LeafType,DeleteCopy,Alloc,FreeLeaf,ValueArea) \
1141 + { \
1142 +/**/ Pjv_t Pjvnew; \
1143 + \
1144 + if ((PjllnewRaw = Alloc(pop1 - 1, Pjpm)) == 0) return(-1); \
1145 + Pjllnew = P_JLL(PjllnewRaw); \
1146 +/**/ Pjvnew = ValueArea(Pjllnew, pop1 - 1); \
1147 + DeleteCopy((LeafType) Pjllnew, Pleaf, pop1, offset, cIS); \
1148 +/**/ JU_DELETECOPY(Pjvnew, Pjv, pop1, offset, cIS); \
1149 + DBGCODE(JudyCheckSorted(Pjllnew, pop1 - 1, cIS);) \
1150 + FreeLeaf(PleafRaw, pop1, Pjpm); \
1151 + Pjp->jp_Addr = (Word_t) PjllnewRaw; \
1152 + return(1); \
1153 + }
1154 +#endif // JUDYL
1155 +
1156 +// Overall common code for Leaf* deletion handling:
1157 +//
1158 +// See if the leaf can be:
1159 +// - (de)compressed to one a level higher (JU_LEAF_UPLEVEL()), or if not,
1160 +// - compressed to an Immediate JP (JU_LEAF_TOIMMED()), or if not,
1161 +// - shrunk in place (JU_LEAF_INPLACE()), or if none of those, then
1162 +// - shrink the leaf to a smaller chunk of memory (JU_LEAF_SHRINK()).
1163 +//
1164 +// Variables Pjp, pop1, Index, and offset are in the context.
1165 +// The *Up parameters refer to a leaf one level up, if there is any.
1166 +
1167 +#define JU_LEAF(cIS, \
1168 + UpLevel, \
1169 + LeafTypeUp,MaxPop1Up,LeafJPTypeUp,LeafToLeaf, \
1170 + AllocUp,ValueAreaUp, \
1171 + LeafToImmed,ToImmed,CopyPIndex, \
1172 + LeafType,ImmedMaxPop1,ImmedBaseJPType,Immed01JPType, \
1173 + SearchLeaf,GrowInPlace,DeleteInPlace,DeleteCopy, \
1174 + Alloc,FreeLeaf,ValueArea) \
1175 + { \
1176 + Pjll_t PleafRaw; \
1177 + LeafType Pleaf; \
1178 + \
1179 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, cIS)); \
1180 + assert(ParentLevel > (cIS)); \
1181 + \
1182 + PleafRaw = (Pjll_t) (Pjp->jp_Addr); \
1183 + Pleaf = (LeafType) P_JLL(PleafRaw); \
1184 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
1185 + \
1186 + UpLevel(cIS, LeafTypeUp, MaxPop1Up, LeafJPTypeUp, \
1187 + LeafToLeaf, AllocUp, ValueAreaUp); \
1188 + \
1189 + offset = SearchLeaf(Pleaf, pop1, Index); \
1190 + assert(offset >= 0); /* Index must be valid */ \
1191 + JUDYLCODE(Pjv = ValueArea(Pleaf, pop1);) \
1192 + \
1193 + LeafToImmed(cIS, LeafType, ImmedMaxPop1, \
1194 + ImmedBaseJPType, Immed01JPType, \
1195 + ToImmed, SearchLeaf, CopyPIndex, \
1196 + DeleteCopy, FreeLeaf); \
1197 + \
1198 + JU_LEAF_INPLACE(cIS, GrowInPlace, DeleteInPlace); \
1199 + \
1200 + JU_LEAF_SHRINK(cIS, LeafType, DeleteCopy, Alloc, FreeLeaf, \
1201 + ValueArea); \
1202 + }
1203 +
1204 +// END OF MACROS, START OF CASES:
1205 +//
1206 +// (*) Leaf1 [[ => 1_15..08 ] => 1_07 => ... => 1_04 ] => 1_03 => 1_02 => 1_01
1207 +
1208 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1209 + case cJU_JPLEAF1:
1210 +
1211 + JU_LEAF(1,
1212 + JU_LEAF_UPLEVEL, uint16_t *, cJU_LEAF2_MAXPOP1, cJU_JPLEAF2,
1213 + j__udyLeaf1ToLeaf2, j__udyAllocJLL2, JL_LEAF2VALUEAREA,
1214 + JU_LEAF_TOIMMED, ignore, ignore,
1215 + uint8_t *, cJU_IMMED1_MAXPOP1,
1216 + cJU_JPIMMED_1_02, cJU_JPIMMED_1_01, j__udySearchLeaf1,
1217 + JU_LEAF1GROWINPLACE, JU_DELETEINPLACE, JU_DELETECOPY,
1218 + j__udyAllocJLL1, j__udyFreeJLL1, JL_LEAF1VALUEAREA);
1219 +#endif
1220 +
1221 +// A complicating factor is that for JudyL & 32-bit, a Leaf2 must go directly
1222 +// to an Immed 2_01 and a Leaf3 must go directly to an Immed 3_01:
1223 +//
1224 +// Leaf2 [[ => 2_07..04 ] => 2_03 => 2_02 ] => 2_01
1225 +// Leaf3 [[ => 3_05..03 ] => 3_02 ] => 3_01
1226 +//
1227 +// Hence use JU_LEAF_TOIMMED_23 instead of JU_LEAF_TOIMMED in the cases below,
1228 +// and also the parameters ToImmed and, for odd index sizes, CopyPIndex, are
1229 +// required.
1230 +
1231 + case cJU_JPLEAF2:
1232 +
1233 + JU_LEAF(2,
1234 + JU_LEAF_UPLEVEL, uint8_t *, cJU_LEAF3_MAXPOP1, cJU_JPLEAF3,
1235 + j__udyLeaf2ToLeaf3, j__udyAllocJLL3, JL_LEAF3VALUEAREA,
1236 + JU_LEAF_TOIMMED_23, JU_TOIMMED_01_EVEN, ignore,
1237 + uint16_t *, cJU_IMMED2_MAXPOP1,
1238 + cJU_JPIMMED_2_02, cJU_JPIMMED_2_01, j__udySearchLeaf2,
1239 + JU_LEAF2GROWINPLACE, JU_DELETEINPLACE, JU_DELETECOPY,
1240 + j__udyAllocJLL2, j__udyFreeJLL2, JL_LEAF2VALUEAREA);
1241 +
1242 +// On 32-bit there is no transition to "uplevel" for a Leaf3, so use
1243 +// JU_LEAF_UPLEVEL64 instead of JU_LEAF_UPLEVEL:
1244 +
1245 + case cJU_JPLEAF3:
1246 +
1247 + JU_LEAF(3,
1248 + JU_LEAF_UPLEVEL64, uint32_t *, cJU_LEAF4_MAXPOP1,
1249 + cJU_JPLEAF4,
1250 + j__udyLeaf3ToLeaf4, j__udyAllocJLL4, JL_LEAF4VALUEAREA,
1251 + JU_LEAF_TOIMMED_23,
1252 + JU_TOIMMED_01_ODD, JU_COPY3_PINDEX_TO_LONG,
1253 + uint8_t *, cJU_IMMED3_MAXPOP1,
1254 + cJU_JPIMMED_3_02, cJU_JPIMMED_3_01, j__udySearchLeaf3,
1255 + JU_LEAF3GROWINPLACE, JU_DELETEINPLACE_ODD,
1256 + JU_DELETECOPY_ODD,
1257 + j__udyAllocJLL3, j__udyFreeJLL3, JL_LEAF3VALUEAREA);
1258 +
1259 +#ifdef JU_64BIT
1260 +
1261 +// A complicating factor is that for JudyL & 64-bit, a Leaf[4-7] must go
1262 +// directly to an Immed [4-7]_01:
1263 +//
1264 +// Leaf4 [[ => 4_03..02 ]] => 4_01
1265 +// Leaf5 [[ => 5_03..02 ]] => 5_01
1266 +// Leaf6 [[ => 6_02 ]] => 6_01
1267 +// Leaf7 [[ => 7_02 ]] => 7_01
1268 +//
1269 +// Hence use JU_LEAF_TOIMMED_47 instead of JU_LEAF_TOIMMED in the cases below.
1270 +
1271 + case cJU_JPLEAF4:
1272 +
1273 + JU_LEAF(4,
1274 + JU_LEAF_UPLEVEL, uint8_t *, cJU_LEAF5_MAXPOP1, cJU_JPLEAF5,
1275 + j__udyLeaf4ToLeaf5, j__udyAllocJLL5, JL_LEAF5VALUEAREA,
1276 + JU_LEAF_TOIMMED_47, JU_TOIMMED_01_EVEN, ignore,
1277 + uint32_t *, cJU_IMMED4_MAXPOP1,
1278 + cJ1_JPIMMED_4_02, cJU_JPIMMED_4_01, j__udySearchLeaf4,
1279 + JU_LEAF4GROWINPLACE, JU_DELETEINPLACE, JU_DELETECOPY,
1280 + j__udyAllocJLL4, j__udyFreeJLL4, JL_LEAF4VALUEAREA);
1281 +
1282 + case cJU_JPLEAF5:
1283 +
1284 + JU_LEAF(5,
1285 + JU_LEAF_UPLEVEL, uint8_t *, cJU_LEAF6_MAXPOP1, cJU_JPLEAF6,
1286 + j__udyLeaf5ToLeaf6, j__udyAllocJLL6, JL_LEAF6VALUEAREA,
1287 + JU_LEAF_TOIMMED_47,
1288 + JU_TOIMMED_01_ODD, JU_COPY5_PINDEX_TO_LONG,
1289 + uint8_t *, cJU_IMMED5_MAXPOP1,
1290 + cJ1_JPIMMED_5_02, cJU_JPIMMED_5_01, j__udySearchLeaf5,
1291 + JU_LEAF5GROWINPLACE, JU_DELETEINPLACE_ODD,
1292 + JU_DELETECOPY_ODD,
1293 + j__udyAllocJLL5, j__udyFreeJLL5, JL_LEAF5VALUEAREA);
1294 +
1295 + case cJU_JPLEAF6:
1296 +
1297 + JU_LEAF(6,
1298 + JU_LEAF_UPLEVEL, uint8_t *, cJU_LEAF7_MAXPOP1, cJU_JPLEAF7,
1299 + j__udyLeaf6ToLeaf7, j__udyAllocJLL7, JL_LEAF7VALUEAREA,
1300 + JU_LEAF_TOIMMED_47,
1301 + JU_TOIMMED_01_ODD, JU_COPY6_PINDEX_TO_LONG,
1302 + uint8_t *, cJU_IMMED6_MAXPOP1,
1303 + cJ1_JPIMMED_6_02, cJU_JPIMMED_6_01, j__udySearchLeaf6,
1304 + JU_LEAF6GROWINPLACE, JU_DELETEINPLACE_ODD,
1305 + JU_DELETECOPY_ODD,
1306 + j__udyAllocJLL6, j__udyFreeJLL6, JL_LEAF6VALUEAREA);
1307 +
1308 +// There is no transition to "uplevel" for a Leaf7, so use JU_LEAF_UPLEVEL_NONE
1309 +// instead of JU_LEAF_UPLEVEL, and ignore all of the parameters to that macro:
1310 +
1311 + case cJU_JPLEAF7:
1312 +
1313 + JU_LEAF(7,
1314 + JU_LEAF_UPLEVEL_NONE, ignore1, ignore2, ignore3, ignore4,
1315 + ignore5, ignore6,
1316 + JU_LEAF_TOIMMED_47,
1317 + JU_TOIMMED_01_ODD, JU_COPY7_PINDEX_TO_LONG,
1318 + uint8_t *, cJU_IMMED7_MAXPOP1,
1319 + cJ1_JPIMMED_7_02, cJU_JPIMMED_7_01, j__udySearchLeaf7,
1320 + JU_LEAF7GROWINPLACE, JU_DELETEINPLACE_ODD,
1321 + JU_DELETECOPY_ODD,
1322 + j__udyAllocJLL7, j__udyFreeJLL7, JL_LEAF7VALUEAREA);
1323 +#endif // JU_64BIT
1324 +
1325 +
1326 +// ****************************************************************************
1327 +// BITMAP LEAF:
1328 +
1329 + case cJU_JPLEAF_B1:
1330 + {
1331 +#ifdef JUDYL
1332 + Pjv_t PjvnewRaw; // new value area.
1333 + Pjv_t Pjvnew;
1334 + Word_t subexp; // 1 of 8 subexpanses in bitmap.
1335 + Pjlb_t Pjlb; // pointer to bitmap part of the leaf.
1336 + BITMAPL_t bitmap; // for one subexpanse.
1337 + BITMAPL_t bitmask; // bit set for Indexs digit.
1338 +#endif
1339 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, 1));
1340 + assert(ParentLevel > 1);
1341 + // valid Index:
1342 + assert(JU_BITMAPTESTL(P_JLB(Pjp->jp_Addr), Index));
1343 +
1344 + pop1 = JU_JPLEAF_POP0(Pjp) + 1;
1345 +
1346 +// Like a Leaf1, see if its under a narrow pointer and can become a Leaf2
1347 +// (hysteresis = 1):
1348 +
1349 + JU_LEAF_UPLEVEL(1, uint16_t *, cJU_LEAF2_MAXPOP1, cJU_JPLEAF2,
1350 + j__udyLeaf1ToLeaf2, j__udyAllocJLL2,
1351 + JL_LEAF2VALUEAREA);
1352 +
1353 +#if (defined(JUDY1) && defined(JU_64BIT))
1354 +
1355 +// Handle the unusual special case, on Judy1 64-bit only, where a LeafB1 goes
1356 +// directly to a JPIMMED_1_15; as described in comments in Judy1.h and
1357 +// JudyIns.c. Copy 1-byte indexes from old LeafB1 to the Immed:
1358 +
1359 + if ((pop1 - 1) == cJU_IMMED1_MAXPOP1) // hysteresis = 0.
1360 + {
1361 + Pjlb_t PjlbRaw; // bitmap in old leaf.
1362 + Pjlb_t Pjlb;
1363 + uint8_t * Pleafnew; // JPIMMED as a pointer.
1364 + Word_t ldigit; // larger than uint8_t.
1365 +
1366 + PjlbRaw = (Pjlb_t) (Pjp->jp_Addr);
1367 + Pjlb = P_JLB(PjlbRaw);
1368 + Pleafnew = Pjp->jp_1Index;
1369 +
1370 + JU_BITMAPCLEARL(Pjlb, Index); // unset Indexs bit.
1371 +
1372 +// TBD: This is very slow, there must be a better way:
1373 +
1374 + for (ldigit = 0; ldigit < cJU_BRANCHUNUMJPS; ++ldigit)
1375 + {
1376 + if (JU_BITMAPTESTL(Pjlb, ldigit))
1377 + {
1378 + *Pleafnew++ = ldigit;
1379 + assert(Pleafnew - (Pjp->jp_1Index)
1380 + <= cJU_IMMED1_MAXPOP1);
1381 + }
1382 + }
1383 +
1384 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjp->jp_1Index),
1385 + cJU_IMMED1_MAXPOP1, 1);)
1386 + j__udyFreeJLB1(PjlbRaw, Pjpm);
1387 +
1388 + Pjp->jp_Type = cJ1_JPIMMED_1_15;
1389 + return(1);
1390 + }
1391 +
1392 +#else // (JUDYL || (! JU_64BIT))
1393 +
1394 +// Compress LeafB1 to a Leaf1:
1395 +//
1396 +// Note: 4.37 of this file contained alternate code for Judy1 only that simply
1397 +// cleared the bit and allowed the LeafB1 to go below cJU_LEAF1_MAXPOP1. This
1398 +// was the ONLY case where a malloc failure was not fatal; however, it violated
1399 +// the critical assumption that the tree is always kept in least-compressed
1400 +// form.
1401 +
1402 + if (pop1 == cJU_LEAF1_MAXPOP1) // hysteresis = 1.
1403 + {
1404 + if (j__udyLeafB1ToLeaf1(Pjp, Pjpm) == -1) return(-1);
1405 + goto ContinueDelWalk; // delete Index in new Leaf1.
1406 + }
1407 +#endif // (JUDYL || (! JU_64BIT))
1408 +
1409 +#ifdef JUDY1
1410 + // unset Indexs bit:
1411 +
1412 + JU_BITMAPCLEARL(P_JLB(Pjp->jp_Addr), Index);
1413 +#else // JUDYL
1414 +
1415 +// This is very different from Judy1 because of the need to manage the value
1416 +// area:
1417 +//
1418 +// Get last byte to decode from Index, and pointer to bitmap leaf:
1419 +
1420 + digit = JU_DIGITATSTATE(Index, 1);
1421 + Pjlb = P_JLB(Pjp->jp_Addr);
1422 +
1423 +// Prepare additional values:
1424 +
1425 + subexp = digit / cJU_BITSPERSUBEXPL; // which subexpanse.
1426 + bitmap = JU_JLB_BITMAP(Pjlb, subexp); // subexps 32-bit map.
1427 + PjvRaw = JL_JLB_PVALUE(Pjlb, subexp); // corresponding values.
1428 + Pjv = P_JV(PjvRaw);
1429 + bitmask = JU_BITPOSMASKL(digit); // mask for Index.
1430 +
1431 + assert(bitmap & bitmask); // Index must be valid.
1432 +
1433 + if (bitmap == cJU_FULLBITMAPL) // full bitmap, take shortcut:
1434 + {
1435 + pop1 = cJU_BITSPERSUBEXPL;
1436 + offset = digit % cJU_BITSPERSUBEXPL;
1437 + }
1438 + else // compute subexpanse pop1 and value area offset:
1439 + {
1440 + pop1 = j__udyCountBitsL(bitmap);
1441 + offset = j__udyCountBitsL(bitmap & (bitmask - 1));
1442 + }
1443 +
1444 +// Handle solitary Index remaining in subexpanse:
1445 +
1446 + if (pop1 == 1)
1447 + {
1448 + j__udyLFreeJV(PjvRaw, 1, Pjpm);
1449 +
1450 + JL_JLB_PVALUE(Pjlb, subexp) = (Pjv_t) NULL;
1451 + JU_JLB_BITMAP(Pjlb, subexp) = 0;
1452 +
1453 + return(1);
1454 + }
1455 +
1456 +// Shrink value area in place or move to a smaller value area:
1457 +
1458 + if (JL_LEAFVGROWINPLACE(pop1 - 1)) // hysteresis = 0.
1459 + {
1460 + JU_DELETEINPLACE(Pjv, pop1, offset, ignore);
1461 + }
1462 + else
1463 + {
1464 + if ((PjvnewRaw = j__udyLAllocJV(pop1 - 1, Pjpm))
1465 + == (Pjv_t) NULL) return(-1);
1466 + Pjvnew = P_JV(PjvnewRaw);
1467 +
1468 + JU_DELETECOPY(Pjvnew, Pjv, pop1, offset, ignore);
1469 + j__udyLFreeJV(PjvRaw, pop1, Pjpm);
1470 + JL_JLB_PVALUE(Pjlb, subexp) = (Pjv_t) PjvnewRaw;
1471 + }
1472 +
1473 + JU_JLB_BITMAP(Pjlb, subexp) ^= bitmask; // clear Indexs bit.
1474 +
1475 +#endif // JUDYL
1476 +
1477 + return(1);
1478 +
1479 + } // case.
1480 +
1481 +
1482 +#ifdef JUDY1
1483 +
1484 +// ****************************************************************************
1485 +// FULL POPULATION LEAF:
1486 +//
1487 +// Convert to a LeafB1 and delete the index. Hysteresis = 0; none is possible.
1488 +//
1489 +// Note: Earlier the second assertion below said, "== 2", but in fact the
1490 +// parent could be at a higher level if a fullpop is under a narrow pointer.
1491 +
1492 + case cJ1_JPFULLPOPU1:
1493 + {
1494 + Pjlb_t PjlbRaw;
1495 + Pjlb_t Pjlb;
1496 + Word_t subexp;
1497 +
1498 + assert(! JU_DCDNOTMATCHINDEX(Index, Pjp, 2));
1499 + assert(ParentLevel > 1); // see above.
1500 +
1501 + if ((PjlbRaw = j__udyAllocJLB1(Pjpm)) == (Pjlb_t) NULL)
1502 + return(-1);
1503 + Pjlb = P_JLB(PjlbRaw);
1504 +
1505 +// Fully populate the leaf, then unset Indexs bit:
1506 +
1507 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
1508 + JU_JLB_BITMAP(Pjlb, subexp) = cJU_FULLBITMAPL;
1509 +
1510 + JU_BITMAPCLEARL(Pjlb, Index);
1511 +
1512 + Pjp->jp_Addr = (Word_t) PjlbRaw;
1513 + Pjp->jp_Type = cJU_JPLEAF_B1;
1514 +
1515 + return(1);
1516 + }
1517 +#endif // JUDY1
1518 +
1519 +
1520 +// ****************************************************************************
1521 +// IMMEDIATE JP:
1522 +//
1523 +// If theres just the one Index in the Immed, convert the JP to a JPNULL*
1524 +// (should only happen in a BranchU); otherwise delete the Index from the
1525 +// Immed. See the state transitions table elsewhere in this file for a summary
1526 +// of which Immed types must be handled. Hysteresis = 0; none is possible with
1527 +// Immeds.
1528 +//
1529 +// MACROS FOR COMMON CODE:
1530 +//
1531 +// Single Index remains in cJU_JPIMMED_*_01; convert JP to null:
1532 +//
1533 +// Variables Pjp and parentJPtype are in the context.
1534 +//
1535 +// Note: cJU_JPIMMED_*_01 should only be encountered in BranchUs, not in
1536 +// BranchLs or BranchBs (where its improper to merely modify the JP to be a
1537 +// null JP); that is, BranchL and BranchB code should have already handled
1538 +// any cJU_JPIMMED_*_01 by different means.
1539 +
1540 +#define JU_IMMED_01(NewJPType,ParentJPType) \
1541 + \
1542 + assert(parentJPtype == (ParentJPType)); \
1543 + assert(JU_JPDCDPOP0(Pjp) == JU_TRIMTODCDSIZE(Index)); \
1544 + JU_JPSETADT(Pjp, 0, 0, NewJPType); \
1545 + return(1)
1546 +
1547 +// Convert cJ*_JPIMMED_*_02 to cJU_JPIMMED_*_01:
1548 +//
1549 +// Move the undeleted Index, whichever does not match the least bytes of Index,
1550 +// from undecoded-bytes-only (in jp_1Index or jp_LIndex as appropriate) to
1551 +// jp_DcdPopO (full-field). Pjp, Index, and offset are in the context.
1552 +
1553 +#define JU_IMMED_02(cIS,LeafType,NewJPType) \
1554 + { \
1555 + LeafType Pleaf; \
1556 + \
1557 + assert((ParentLevel - 1) == (cIS)); \
1558 + JUDY1CODE(Pleaf = (LeafType) (Pjp->jp_1Index);) \
1559 + JUDYLCODE(Pleaf = (LeafType) (Pjp->jp_LIndex);) \
1560 + JUDYLCODE(PjvRaw = (Pjv_t) (Pjp->jp_Addr);) \
1561 + JUDYLCODE(Pjv = P_JV(PjvRaw);) \
1562 + JU_TOIMMED_01_EVEN(cIS, ignore, ignore); \
1563 + JUDYLCODE(j__udyLFreeJV(PjvRaw, 2, Pjpm);) \
1564 + Pjp->jp_Type = (NewJPType); \
1565 + return(1); \
1566 + }
1567 +
1568 +#if (defined(JUDY1) || defined(JU_64BIT))
1569 +
1570 +// Variation for "odd" cJ*_JPIMMED_*_02 JP types, which are very different from
1571 +// "even" types because they use leaf search code and odd-copy macros:
1572 +//
1573 +// Note: JudyL 32-bit has no "odd" JPIMMED_*_02 types.
1574 +
1575 +#define JU_IMMED_02_ODD(cIS,NewJPType,SearchLeaf,CopyPIndex) \
1576 + { \
1577 + uint8_t * Pleaf; \
1578 + \
1579 + assert((ParentLevel - 1) == (cIS)); \
1580 + JUDY1CODE(Pleaf = (uint8_t *) (Pjp->jp_1Index);) \
1581 + JUDYLCODE(Pleaf = (uint8_t *) (Pjp->jp_LIndex);) \
1582 + JUDYLCODE(PjvRaw = (Pjv_t) (Pjp->jp_Addr);) \
1583 + JUDYLCODE(Pjv = P_JV(PjvRaw);) \
1584 + JU_TOIMMED_01_ODD(cIS, SearchLeaf, CopyPIndex); \
1585 + JUDYLCODE(j__udyLFreeJV(PjvRaw, 2, Pjpm);) \
1586 + Pjp->jp_Type = (NewJPType); \
1587 + return(1); \
1588 + }
1589 +#endif // (JUDY1 || JU_64BIT)
1590 +
1591 +// Core code for deleting one Index (and for JudyL, its value area) from a
1592 +// larger Immed:
1593 +//
1594 +// Variables Pleaf, pop1, and offset are in the context.
1595 +
1596 +#ifdef JUDY1
1597 +#define JU_IMMED_DEL(cIS,DeleteInPlace) \
1598 + DeleteInPlace(Pleaf, pop1, offset, cIS); \
1599 + DBGCODE(JudyCheckSorted(Pleaf, pop1 - 1, cIS);)
1600 +
1601 +#else // JUDYL
1602 +
1603 +// For JudyL the value area might need to be shrunk:
1604 +
1605 +#define JU_IMMED_DEL(cIS,DeleteInPlace) \
1606 + \
1607 + if (JL_LEAFVGROWINPLACE(pop1 - 1)) /* hysteresis = 0 */ \
1608 + { \
1609 + DeleteInPlace( Pleaf, pop1, offset, cIS); \
1610 + JU_DELETEINPLACE(Pjv, pop1, offset, ignore); \
1611 + DBGCODE(JudyCheckSorted(Pleaf, pop1 - 1, cIS);) \
1612 + } \
1613 + else \
1614 + { \
1615 + Pjv_t PjvnewRaw; \
1616 + Pjv_t Pjvnew; \
1617 + \
1618 + if ((PjvnewRaw = j__udyLAllocJV(pop1 - 1, Pjpm)) \
1619 + == (Pjv_t) NULL) return(-1); \
1620 + Pjvnew = P_JV(PjvnewRaw); \
1621 + \
1622 + DeleteInPlace(Pleaf, pop1, offset, cIS); \
1623 + JU_DELETECOPY(Pjvnew, Pjv, pop1, offset, ignore); \
1624 + DBGCODE(JudyCheckSorted(Pleaf, pop1 - 1, cIS);) \
1625 + j__udyLFreeJV(PjvRaw, pop1, Pjpm); \
1626 + \
1627 + (Pjp->jp_Addr) = (Word_t) PjvnewRaw; \
1628 + }
1629 +#endif // JUDYL
1630 +
1631 +// Delete one Index from a larger Immed where no restructuring is required:
1632 +//
1633 +// Variables pop1, Pjp, offset, and Index are in the context.
1634 +
1635 +#define JU_IMMED(cIS,LeafType,BaseJPType,SearchLeaf,DeleteInPlace) \
1636 + { \
1637 + LeafType Pleaf; \
1638 + \
1639 + assert((ParentLevel - 1) == (cIS)); \
1640 + JUDY1CODE(Pleaf = (LeafType) (Pjp->jp_1Index);) \
1641 + JUDYLCODE(Pleaf = (LeafType) (Pjp->jp_LIndex);) \
1642 + JUDYLCODE(PjvRaw = (Pjv_t) (Pjp->jp_Addr);) \
1643 + JUDYLCODE(Pjv = P_JV(PjvRaw);) \
1644 + pop1 = (JU_JPTYPE(Pjp)) - (BaseJPType) + 2; \
1645 + offset = SearchLeaf(Pleaf, pop1, Index); \
1646 + assert(offset >= 0); /* Index must be valid */ \
1647 + \
1648 + JU_IMMED_DEL(cIS, DeleteInPlace); \
1649 + --(Pjp->jp_Type); \
1650 + return(1); \
1651 + }
1652 +
1653 +
1654 +// END OF MACROS, START OF CASES:
1655 +
1656 +// Single Index remains in Immed; convert JP to null:
1657 +
1658 + case cJU_JPIMMED_1_01: JU_IMMED_01(cJU_JPNULL1, cJU_JPBRANCH_U2);
1659 + case cJU_JPIMMED_2_01: JU_IMMED_01(cJU_JPNULL2, cJU_JPBRANCH_U3);
1660 +#ifndef JU_64BIT
1661 + case cJU_JPIMMED_3_01: JU_IMMED_01(cJU_JPNULL3, cJU_JPBRANCH_U);
1662 +#else
1663 + case cJU_JPIMMED_3_01: JU_IMMED_01(cJU_JPNULL3, cJU_JPBRANCH_U4);
1664 + case cJU_JPIMMED_4_01: JU_IMMED_01(cJU_JPNULL4, cJU_JPBRANCH_U5);
1665 + case cJU_JPIMMED_5_01: JU_IMMED_01(cJU_JPNULL5, cJU_JPBRANCH_U6);
1666 + case cJU_JPIMMED_6_01: JU_IMMED_01(cJU_JPNULL6, cJU_JPBRANCH_U7);
1667 + case cJU_JPIMMED_7_01: JU_IMMED_01(cJU_JPNULL7, cJU_JPBRANCH_U);
1668 +#endif
1669 +
1670 +// Multiple Indexes remain in the Immed JP; delete the specified Index:
1671 +
1672 + case cJU_JPIMMED_1_02:
1673 +
1674 + JU_IMMED_02(1, uint8_t *, cJU_JPIMMED_1_01);
1675 +
1676 + case cJU_JPIMMED_1_03:
1677 +#if (defined(JUDY1) || defined(JU_64BIT))
1678 + case cJU_JPIMMED_1_04:
1679 + case cJU_JPIMMED_1_05:
1680 + case cJU_JPIMMED_1_06:
1681 + case cJU_JPIMMED_1_07:
1682 +#endif
1683 +#if (defined(JUDY1) && defined(JU_64BIT))
1684 + case cJ1_JPIMMED_1_08:
1685 + case cJ1_JPIMMED_1_09:
1686 + case cJ1_JPIMMED_1_10:
1687 + case cJ1_JPIMMED_1_11:
1688 + case cJ1_JPIMMED_1_12:
1689 + case cJ1_JPIMMED_1_13:
1690 + case cJ1_JPIMMED_1_14:
1691 + case cJ1_JPIMMED_1_15:
1692 +#endif
1693 + JU_IMMED(1, uint8_t *, cJU_JPIMMED_1_02,
1694 + j__udySearchLeaf1, JU_DELETEINPLACE);
1695 +
1696 +#if (defined(JUDY1) || defined(JU_64BIT))
1697 + case cJU_JPIMMED_2_02:
1698 +
1699 + JU_IMMED_02(2, uint16_t *, cJU_JPIMMED_2_01);
1700 +
1701 + case cJU_JPIMMED_2_03:
1702 +#endif
1703 +#if (defined(JUDY1) && defined(JU_64BIT))
1704 + case cJ1_JPIMMED_2_04:
1705 + case cJ1_JPIMMED_2_05:
1706 + case cJ1_JPIMMED_2_06:
1707 + case cJ1_JPIMMED_2_07:
1708 +#endif
1709 +#if (defined(JUDY1) || defined(JU_64BIT))
1710 + JU_IMMED(2, uint16_t *, cJU_JPIMMED_2_02,
1711 + j__udySearchLeaf2, JU_DELETEINPLACE);
1712 +
1713 + case cJU_JPIMMED_3_02:
1714 +
1715 + JU_IMMED_02_ODD(3, cJU_JPIMMED_3_01,
1716 + j__udySearchLeaf3, JU_COPY3_PINDEX_TO_LONG);
1717 +
1718 +#endif
1719 +
1720 +#if (defined(JUDY1) && defined(JU_64BIT))
1721 + case cJ1_JPIMMED_3_03:
1722 + case cJ1_JPIMMED_3_04:
1723 + case cJ1_JPIMMED_3_05:
1724 +
1725 + JU_IMMED(3, uint8_t *, cJU_JPIMMED_3_02,
1726 + j__udySearchLeaf3, JU_DELETEINPLACE_ODD);
1727 +
1728 + case cJ1_JPIMMED_4_02:
1729 +
1730 + JU_IMMED_02(4, uint32_t *, cJU_JPIMMED_4_01);
1731 +
1732 + case cJ1_JPIMMED_4_03:
1733 +
1734 + JU_IMMED(4, uint32_t *, cJ1_JPIMMED_4_02,
1735 + j__udySearchLeaf4, JU_DELETEINPLACE);
1736 +
1737 + case cJ1_JPIMMED_5_02:
1738 +
1739 + JU_IMMED_02_ODD(5, cJU_JPIMMED_5_01,
1740 + j__udySearchLeaf5, JU_COPY5_PINDEX_TO_LONG);
1741 +
1742 + case cJ1_JPIMMED_5_03:
1743 +
1744 + JU_IMMED(5, uint8_t *, cJ1_JPIMMED_5_02,
1745 + j__udySearchLeaf5, JU_DELETEINPLACE_ODD);
1746 +
1747 + case cJ1_JPIMMED_6_02:
1748 +
1749 + JU_IMMED_02_ODD(6, cJU_JPIMMED_6_01,
1750 + j__udySearchLeaf6, JU_COPY6_PINDEX_TO_LONG);
1751 +
1752 + case cJ1_JPIMMED_7_02:
1753 +
1754 + JU_IMMED_02_ODD(7, cJU_JPIMMED_7_01,
1755 + j__udySearchLeaf7, JU_COPY7_PINDEX_TO_LONG);
1756 +
1757 +#endif // (JUDY1 && JU_64BIT)
1758 +
1759 +
1760 +// ****************************************************************************
1761 +// INVALID JP TYPE:
1762 +
1763 + default: JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT); return(-1);
1764 +
1765 + } // switch
1766 +
1767 +
1768 +// PROCESS JP -- RECURSIVELY:
1769 +//
1770 +// For non-Immed JP types, if successful, post-decrement the population count
1771 +// at this level, or collapse a BranchL if necessary by copying the remaining
1772 +// JP in the BranchL to the parent (hysteresis = 0), which implicitly creates a
1773 +// narrow pointer if there was not already one in the hierarchy.
1774 +
1775 + assert(level);
1776 + retcode = j__udyDelWalk(Pjp, Index, level, Pjpm);
1777 + assert(retcode != 0); // should never happen.
1778 +
1779 + if ((JU_JPTYPE(Pjp)) < cJU_JPIMMED_1_01) // not an Immed.
1780 + {
1781 + switch (retcode)
1782 + {
1783 + case 1:
1784 + {
1785 + jp_t JP = *Pjp;
1786 + Word_t DcdP0;
1787 +
1788 + DcdP0 = JU_JPDCDPOP0(Pjp) - 1; // decrement count.
1789 + JU_JPSETADT(Pjp, JP.jp_Addr, DcdP0, JU_JPTYPE(&JP));
1790 + break;
1791 + }
1792 + case 2: // collapse BranchL to single JP; see above:
1793 + {
1794 + Pjbl_t PjblRaw = (Pjbl_t) (Pjp->jp_Addr);
1795 + Pjbl_t Pjbl = P_JBL(PjblRaw);
1796 +
1797 + *Pjp = Pjbl->jbl_jp[0];
1798 + j__udyFreeJBL(PjblRaw, Pjpm);
1799 + retcode = 1;
1800 + }
1801 + }
1802 + }
1803 +
1804 + return(retcode);
1805 +
1806 +} // j__udyDelWalk()
1807 +
1808 +
1809 +// ****************************************************************************
1810 +// J U D Y 1 U N S E T
1811 +// J U D Y L D E L
1812 +//
1813 +// Main entry point. See the manual entry for details.
1814 +
1815 +#ifdef JUDY1
1816 +FUNCTION int Judy1Unset
1817 +#else
1818 +FUNCTION int JudyLDel
1819 +#endif
1820 + (
1821 + PPvoid_t PPArray, // in which to delete.
1822 + Word_t Index, // to delete.
1823 + PJError_t PJError // optional, for returning error info.
1824 + )
1825 +{
1826 + Word_t pop1; // population of leaf.
1827 + int offset; // at which to delete Index.
1828 + JUDY1CODE(int retcode;) // return code from Judy1Test().
1829 +JUDYLCODE(PPvoid_t PPvalue;) // pointer from JudyLGet().
1830 +
1831 +
1832 +// CHECK FOR NULL ARRAY POINTER (error by caller):
1833 +
1834 + if (PPArray == (PPvoid_t) NULL)
1835 + {
1836 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY);
1837 + return(JERRI);
1838 + }
1839 +
1840 +
1841 +// CHECK IF INDEX IS INVALID:
1842 +//
1843 +// If so, theres nothing to do. This saves a lot of time. Pass through
1844 +// PJError, if any, from the "get" function.
1845 +
1846 +#ifdef JUDY1
1847 + if ((retcode = Judy1Test(*PPArray, Index, PJError)) == JERRI)
1848 + return (JERRI);
1849 +
1850 + if (retcode == 0) return(0);
1851 +#else
1852 + if ((PPvalue = JudyLGet(*PPArray, Index, PJError)) == PPJERR)
1853 + return (JERRI);
1854 +
1855 + if (PPvalue == (PPvoid_t) NULL) return(0);
1856 +#endif
1857 +
1858 +
1859 +// ****************************************************************************
1860 +// PROCESS TOP LEVEL (LEAFW) BRANCHES AND LEAVES:
1861 +
1862 +// ****************************************************************************
1863 +// LEAFW LEAF, OTHER SIZE:
1864 +//
1865 +// Shrink or convert the leaf as necessary. Hysteresis = 0; none is possible.
1866 +
1867 + if (JU_LEAFW_POP0(*PPArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
1868 + {
1869 + JUDYLCODE(Pjv_t Pjv;) // current value area.
1870 + JUDYLCODE(Pjv_t Pjvnew;) // value area in new leaf.
1871 + Pjlw_t Pjlw = P_JLW(*PPArray); // first word of leaf.
1872 + Pjlw_t Pjlwnew; // replacement leaf.
1873 + pop1 = Pjlw[0] + 1; // first word of leaf is pop0.
1874 +
1875 +// Delete single (last) Index from array:
1876 +
1877 + if (pop1 == 1)
1878 + {
1879 + j__udyFreeJLW(Pjlw, /* pop1 = */ 1, (Pjpm_t) NULL);
1880 + *PPArray = (Pvoid_t) NULL;
1881 + return(1);
1882 + }
1883 +
1884 +// Locate Index in compressible leaf:
1885 +
1886 + offset = j__udySearchLeafW(Pjlw + 1, pop1, Index);
1887 + assert(offset >= 0); // Index must be valid.
1888 +
1889 + JUDYLCODE(Pjv = JL_LEAFWVALUEAREA(Pjlw, pop1);)
1890 +
1891 +// Delete Index in-place:
1892 +//
1893 +// Note: "Grow in place from pop1 - 1" is the logical inverse of, "shrink in
1894 +// place from pop1." Also, Pjlw points to the count word, so skip that for
1895 +// doing the deletion.
1896 +
1897 + if (JU_LEAFWGROWINPLACE(pop1 - 1))
1898 + {
1899 + JU_DELETEINPLACE(Pjlw + 1, pop1, offset, ignore);
1900 +#ifdef JUDYL // also delete from value area:
1901 + JU_DELETEINPLACE(Pjv, pop1, offset, ignore);
1902 +#endif
1903 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjlw + 1), pop1 - 1,
1904 + cJU_ROOTSTATE);)
1905 + --(Pjlw[0]); // decrement population.
1906 + DBGCODE(JudyCheckPop(*PPArray);)
1907 + return(1);
1908 + }
1909 +
1910 +// Allocate new leaf for use in either case below:
1911 +
1912 + Pjlwnew = j__udyAllocJLW(pop1 - 1);
1913 + JU_CHECKALLOC(Pjlw_t, Pjlwnew, JERRI);
1914 +
1915 +// Shrink to smaller LEAFW:
1916 +//
1917 +// Note: Skip the first word = pop0 in each leaf.
1918 +
1919 + Pjlwnew[0] = (pop1 - 1) - 1;
1920 + JU_DELETECOPY(Pjlwnew + 1, Pjlw + 1, pop1, offset, ignore);
1921 +
1922 +#ifdef JUDYL // also delete from value area:
1923 + Pjvnew = JL_LEAFWVALUEAREA(Pjlwnew, pop1 - 1);
1924 + JU_DELETECOPY(Pjvnew, Pjv, pop1, offset, ignore);
1925 +#endif
1926 + DBGCODE(JudyCheckSorted(Pjlwnew + 1, pop1 - 1, cJU_ROOTSTATE);)
1927 +
1928 + j__udyFreeJLW(Pjlw, pop1, (Pjpm_t) NULL);
1929 +
1930 +//// *PPArray = (Pvoid_t) Pjlwnew | cJU_LEAFW);
1931 + *PPArray = (Pvoid_t) Pjlwnew;
1932 + DBGCODE(JudyCheckPop(*PPArray);)
1933 + return(1);
1934 +
1935 + }
1936 + else
1937 +
1938 +
1939 +// ****************************************************************************
1940 +// JRP BRANCH:
1941 +//
1942 +// Traverse through the JPM to do the deletion unless the population is small
1943 +// enough to convert immediately to a LEAFW.
1944 +
1945 + {
1946 + Pjpm_t Pjpm;
1947 + Pjp_t Pjp; // top-level JP to process.
1948 + Word_t digit; // in a branch.
1949 + JUDYLCODE(Pjv_t Pjv;) // to value area.
1950 + Pjlw_t Pjlwnew; // replacement leaf.
1951 + DBGCODE(Pjlw_t Pjlwnew_orig;)
1952 +
1953 + Pjpm = P_JPM(*PPArray); // top object in array (tree).
1954 + Pjp = &(Pjpm->jpm_JP); // next object (first branch or leaf).
1955 +
1956 + assert(((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_L)
1957 + || ((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_B)
1958 + || ((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_U));
1959 +
1960 +// WALK THE TREE
1961 +//
1962 +// Note: Recursive code in j__udyDelWalk() knows how to collapse a lower-level
1963 +// BranchL containing a single JP into the parent JP as a narrow pointer, but
1964 +// the code here cant do that for a top-level BranchL. The result can be
1965 +// PArray -> JPM -> BranchL containing a single JP. This situation is
1966 +// unavoidable because a JPM cannot contain a narrow pointer; the BranchL is
1967 +// required in order to hold the top digit decoded, and it does not collapse to
1968 +// a LEAFW until the population is low enough.
1969 +//
1970 +// TBD: Should we add a topdigit field to JPMs so they can hold narrow
1971 +// pointers?
1972 +
1973 + if (j__udyDelWalk(Pjp, Index, cJU_ROOTSTATE, Pjpm) == -1)
1974 + {
1975 + JU_COPY_ERRNO(PJError, Pjpm);
1976 + return(JERRI);
1977 + }
1978 +
1979 + --(Pjpm->jpm_Pop0); // success; decrement total population.
1980 +
1981 + if ((Pjpm->jpm_Pop0 + 1) != cJU_LEAFW_MAXPOP1)
1982 + {
1983 + DBGCODE(JudyCheckPop(*PPArray);)
1984 + return(1);
1985 + }
1986 +
1987 +// COMPRESS A BRANCH[LBU] TO A LEAFW:
1988 +//
1989 + Pjlwnew = j__udyAllocJLW(cJU_LEAFW_MAXPOP1);
1990 + JU_CHECKALLOC(Pjlw_t, Pjlwnew, JERRI);
1991 +
1992 +// Plug leaf into root pointer and set population count:
1993 +
1994 +//// *PPArray = (Pvoid_t) ((Word_t) Pjlwnew | cJU_LEAFW);
1995 + *PPArray = (Pvoid_t) Pjlwnew;
1996 +#ifdef JUDYL // prepare value area:
1997 + Pjv = JL_LEAFWVALUEAREA(Pjlwnew, cJU_LEAFW_MAXPOP1);
1998 +#endif
1999 + *Pjlwnew++ = cJU_LEAFW_MAXPOP1 - 1; // set pop0.
2000 + DBGCODE(Pjlwnew_orig = Pjlwnew;)
2001 +
2002 + switch (JU_JPTYPE(Pjp))
2003 + {
2004 +
2005 +// JPBRANCH_L: Copy each JPs indexes to the new LEAFW and free the old
2006 +// branch:
2007 +
2008 + case cJU_JPBRANCH_L:
2009 + {
2010 + Pjbl_t PjblRaw = (Pjbl_t) (Pjp->jp_Addr);
2011 + Pjbl_t Pjbl = P_JBL(PjblRaw);
2012 +
2013 + for (offset = 0; offset < Pjbl->jbl_NumJPs; ++offset)
2014 + {
2015 + pop1 = j__udyLeafM1ToLeafW(Pjlwnew, JU_PVALUEPASS
2016 + (Pjbl->jbl_jp) + offset,
2017 + JU_DIGITTOSTATE(Pjbl->jbl_Expanse[offset],
2018 + cJU_BYTESPERWORD),
2019 + (Pvoid_t) Pjpm);
2020 + Pjlwnew += pop1; // advance through indexes.
2021 + JUDYLCODE(Pjv += pop1;) // advance through values.
2022 + }
2023 + j__udyFreeJBL(PjblRaw, Pjpm);
2024 +
2025 + assert(Pjlwnew == Pjlwnew_orig + cJU_LEAFW_MAXPOP1);
2026 + break; // delete Index from new LEAFW.
2027 + }
2028 +
2029 +// JPBRANCH_B: Copy each JPs indexes to the new LEAFW and free the old
2030 +// branch, including each JP subarray:
2031 +
2032 + case cJU_JPBRANCH_B:
2033 + {
2034 + Pjbb_t PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
2035 + Pjbb_t Pjbb = P_JBB(PjbbRaw);
2036 + Word_t subexp; // current subexpanse number.
2037 + BITMAPB_t bitmap; // portion for this subexpanse.
2038 + Pjp_t Pjp2Raw; // one subexpanses subarray.
2039 + Pjp_t Pjp2;
2040 +
2041 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
2042 + {
2043 + if ((bitmap = JU_JBB_BITMAP(Pjbb, subexp)) == 0)
2044 + continue; // skip empty subexpanse.
2045 +
2046 + digit = subexp * cJU_BITSPERSUBEXPB;
2047 + Pjp2Raw = JU_JBB_PJP(Pjbb, subexp);
2048 + Pjp2 = P_JP(Pjp2Raw);
2049 + assert(Pjp2 != (Pjp_t) NULL);
2050 +
2051 +// Walk through bits for all possible sub-subexpanses (digits); increment
2052 +// offset for each populated subexpanse; until no more set bits:
2053 +
2054 + for (offset = 0; bitmap != 0; bitmap >>= 1, ++digit)
2055 + {
2056 + if (! (bitmap & 1)) // skip empty sub-subexpanse.
2057 + continue;
2058 +
2059 + pop1 = j__udyLeafM1ToLeafW(Pjlwnew, JU_PVALUEPASS
2060 + Pjp2 + offset,
2061 + JU_DIGITTOSTATE(digit, cJU_BYTESPERWORD),
2062 + (Pvoid_t) Pjpm);
2063 + Pjlwnew += pop1; // advance through indexes.
2064 + JUDYLCODE(Pjv += pop1;) // advance through values.
2065 + ++offset;
2066 + }
2067 + j__udyFreeJBBJP(Pjp2Raw, /* pop1 = */ offset, Pjpm);
2068 + }
2069 + j__udyFreeJBB(PjbbRaw, Pjpm);
2070 +
2071 + assert(Pjlwnew == Pjlwnew_orig + cJU_LEAFW_MAXPOP1);
2072 + break; // delete Index from new LEAFW.
2073 +
2074 + } // case cJU_JPBRANCH_B.
2075 +
2076 +
2077 +// JPBRANCH_U: Copy each JPs indexes to the new LEAFW and free the old
2078 +// branch:
2079 +
2080 + case cJU_JPBRANCH_U:
2081 + {
2082 + Pjbu_t PjbuRaw = (Pjbu_t) (Pjp->jp_Addr);
2083 + Pjbu_t Pjbu = P_JBU(PjbuRaw);
2084 + Word_t ldigit; // larger than uint8_t.
2085 +
2086 + for (Pjp = Pjbu->jbu_jp, ldigit = 0;
2087 + ldigit < cJU_BRANCHUNUMJPS;
2088 + ++Pjp, ++ldigit)
2089 + {
2090 +
2091 +// Shortcuts, to save a little time for possibly big branches:
2092 +
2093 + if ((JU_JPTYPE(Pjp)) == cJU_JPNULLMAX) // skip null JP.
2094 + continue;
2095 +
2096 +// TBD: Should the following shortcut also be used in BranchL and BranchB
2097 +// code?
2098 +
2099 +#ifndef JU_64BIT
2100 + if ((JU_JPTYPE(Pjp)) == cJU_JPIMMED_3_01)
2101 +#else
2102 + if ((JU_JPTYPE(Pjp)) == cJU_JPIMMED_7_01)
2103 +#endif
2104 + { // single Immed:
2105 + *Pjlwnew++ = JU_DIGITTOSTATE(ldigit, cJU_BYTESPERWORD)
2106 + | JU_JPDCDPOP0(Pjp); // rebuild Index.
2107 +#ifdef JUDYL
2108 + *Pjv++ = Pjp->jp_Addr; // copy value area.
2109 +#endif
2110 + continue;
2111 + }
2112 +
2113 + pop1 = j__udyLeafM1ToLeafW(Pjlwnew, JU_PVALUEPASS
2114 + Pjp, JU_DIGITTOSTATE(ldigit, cJU_BYTESPERWORD),
2115 + (Pvoid_t) Pjpm);
2116 + Pjlwnew += pop1; // advance through indexes.
2117 + JUDYLCODE(Pjv += pop1;) // advance through values.
2118 + }
2119 + j__udyFreeJBU(PjbuRaw, Pjpm);
2120 +
2121 + assert(Pjlwnew == Pjlwnew_orig + cJU_LEAFW_MAXPOP1);
2122 + break; // delete Index from new LEAFW.
2123 +
2124 + } // case cJU_JPBRANCH_U.
2125 +
2126 +
2127 +// INVALID JP TYPE in jpm_t struct
2128 +
2129 + default: JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
2130 + return(JERRI);
2131 +
2132 + } // end switch on sub-JP type.
2133 +
2134 + DBGCODE(JudyCheckSorted((Pjll_t) Pjlwnew_orig, cJU_LEAFW_MAXPOP1,
2135 + cJU_ROOTSTATE);)
2136 +
2137 +// FREE JPM (no longer needed):
2138 +
2139 + j__udyFreeJPM(Pjpm, (Pjpm_t) NULL);
2140 + DBGCODE(JudyCheckPop(*PPArray);)
2141 + return(1);
2142 +
2143 + }
2144 + /*NOTREACHED*/
2145 +
2146 +} // Judy1Unset() / JudyLDel()
libnetdata/libjudy/src/JudyL/JudyLFirst.c new
+213
@@ -0,0 +1,213 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.12 $ $Source: /judy/src/JudyCommon/JudyFirst.c $
19 +//
20 +// Judy*First[Empty]() and Judy*Last[Empty]() routines for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// These are inclusive versions of Judy*Next[Empty]() and Judy*Prev[Empty]().
24 +
25 +#if (! (defined(JUDY1) || defined(JUDYL)))
26 +#error: One of -DJUDY1 or -DJUDYL must be specified.
27 +#endif
28 +
29 +#ifdef JUDY1
30 +#include "Judy1.h"
31 +#else
32 +#include "JudyL.h"
33 +#endif
34 +
35 +
36 +// ****************************************************************************
37 +// J U D Y 1 F I R S T
38 +// J U D Y L F I R S T
39 +//
40 +// See the manual entry for details.
41 +
42 +#ifdef JUDY1
43 +FUNCTION int Judy1First
44 +#else
45 +FUNCTION PPvoid_t JudyLFirst
46 +#endif
47 + (
48 + Pcvoid_t PArray, // Judy array to search.
49 + Word_t * PIndex, // starting point and result.
50 + PJError_t PJError // optional, for returning error info.
51 + )
52 +{
53 + if (PIndex == (PWord_t) NULL) // caller error:
54 + {
55 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
56 + JUDY1CODE(return(JERRI );)
57 + JUDYLCODE(return(PPJERR);)
58 + }
59 +
60 +#ifdef JUDY1
61 + switch (Judy1Test(PArray, *PIndex, PJError))
62 + {
63 + case 1: return(1); // found *PIndex itself.
64 + case 0: return(Judy1Next(PArray, PIndex, PJError));
65 + default: return(JERRI);
66 + }
67 +#else
68 + {
69 + PPvoid_t PValue;
70 +
71 + if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
72 + return(PPJERR);
73 +
74 + if (PValue != (PPvoid_t) NULL) return(PValue); // found *PIndex.
75 +
76 + return(JudyLNext(PArray, PIndex, PJError));
77 + }
78 +#endif
79 +
80 +} // Judy1First() / JudyLFirst()
81 +
82 +
83 +// ****************************************************************************
84 +// J U D Y 1 L A S T
85 +// J U D Y L L A S T
86 +//
87 +// See the manual entry for details.
88 +
89 +#ifdef JUDY1
90 +FUNCTION int Judy1Last(
91 +#else
92 +FUNCTION PPvoid_t JudyLLast(
93 +#endif
94 + Pcvoid_t PArray, // Judy array to search.
95 + Word_t * PIndex, // starting point and result.
96 + PJError_t PJError) // optional, for returning error info.
97 +{
98 + if (PIndex == (PWord_t) NULL)
99 + {
100 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX); // caller error.
101 + JUDY1CODE(return(JERRI );)
102 + JUDYLCODE(return(PPJERR);)
103 + }
104 +
105 +#ifdef JUDY1
106 + switch (Judy1Test(PArray, *PIndex, PJError))
107 + {
108 + case 1: return(1); // found *PIndex itself.
109 + case 0: return(Judy1Prev(PArray, PIndex, PJError));
110 + default: return(JERRI);
111 + }
112 +#else
113 + {
114 + PPvoid_t PValue;
115 +
116 + if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
117 + return(PPJERR);
118 +
119 + if (PValue != (PPvoid_t) NULL) return(PValue); // found *PIndex.
120 +
121 + return(JudyLPrev(PArray, PIndex, PJError));
122 + }
123 +#endif
124 +
125 +} // Judy1Last() / JudyLLast()
126 +
127 +
128 +// ****************************************************************************
129 +// J U D Y 1 F I R S T E M P T Y
130 +// J U D Y L F I R S T E M P T Y
131 +//
132 +// See the manual entry for details.
133 +
134 +#ifdef JUDY1
135 +FUNCTION int Judy1FirstEmpty(
136 +#else
137 +FUNCTION int JudyLFirstEmpty(
138 +#endif
139 + Pcvoid_t PArray, // Judy array to search.
140 + Word_t * PIndex, // starting point and result.
141 + PJError_t PJError) // optional, for returning error info.
142 +{
143 + if (PIndex == (PWord_t) NULL) // caller error:
144 + {
145 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
146 + return(JERRI);
147 + }
148 +
149 +#ifdef JUDY1
150 + switch (Judy1Test(PArray, *PIndex, PJError))
151 + {
152 + case 0: return(1); // found *PIndex itself.
153 + case 1: return(Judy1NextEmpty(PArray, PIndex, PJError));
154 + default: return(JERRI);
155 + }
156 +#else
157 + {
158 + PPvoid_t PValue;
159 +
160 + if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
161 + return(JERRI);
162 +
163 + if (PValue == (PPvoid_t) NULL) return(1); // found *PIndex.
164 +
165 + return(JudyLNextEmpty(PArray, PIndex, PJError));
166 + }
167 +#endif
168 +
169 +} // Judy1FirstEmpty() / JudyLFirstEmpty()
170 +
171 +
172 +// ****************************************************************************
173 +// J U D Y 1 L A S T E M P T Y
174 +// J U D Y L L A S T E M P T Y
175 +//
176 +// See the manual entry for details.
177 +
178 +#ifdef JUDY1
179 +FUNCTION int Judy1LastEmpty(
180 +#else
181 +FUNCTION int JudyLLastEmpty(
182 +#endif
183 + Pcvoid_t PArray, // Judy array to search.
184 + Word_t * PIndex, // starting point and result.
185 + PJError_t PJError) // optional, for returning error info.
186 +{
187 + if (PIndex == (PWord_t) NULL)
188 + {
189 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX); // caller error.
190 + return(JERRI);
191 + }
192 +
193 +#ifdef JUDY1
194 + switch (Judy1Test(PArray, *PIndex, PJError))
195 + {
196 + case 0: return(1); // found *PIndex itself.
197 + case 1: return(Judy1PrevEmpty(PArray, PIndex, PJError));
198 + default: return(JERRI);
199 + }
200 +#else
201 + {
202 + PPvoid_t PValue;
203 +
204 + if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
205 + return(JERRI);
206 +
207 + if (PValue == (PPvoid_t) NULL) return(1); // found *PIndex.
208 +
209 + return(JudyLPrevEmpty(PArray, PIndex, PJError));
210 + }
211 +#endif
212 +
213 +} // Judy1LastEmpty() / JudyLLastEmpty()
libnetdata/libjudy/src/JudyL/JudyLFreeArray.c new
+363
@@ -0,0 +1,363 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.51 $ $Source: /judy/src/JudyCommon/JudyFreeArray.c $
19 +//
20 +// Judy1FreeArray() and JudyLFreeArray() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +// Return the number of bytes freed from the array.
23 +
24 +#if (! (defined(JUDY1) || defined(JUDYL)))
25 +#error: One of -DJUDY1 or -DJUDYL must be specified.
26 +#endif
27 +
28 +#ifdef JUDY1
29 +#include "Judy1.h"
30 +#else
31 +#include "JudyL.h"
32 +#endif
33 +
34 +#include "JudyPrivate1L.h"
35 +
36 +DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);)
37 +
38 +
39 +// ****************************************************************************
40 +// J U D Y 1 F R E E A R R A Y
41 +// J U D Y L F R E E A R R A Y
42 +//
43 +// See the Judy*(3C) manual entry for details.
44 +//
45 +// This code is written recursively, at least at first, because thats much
46 +// simpler. Hope its fast enough.
47 +
48 +#ifdef JUDY1
49 +FUNCTION Word_t Judy1FreeArray
50 +#else
51 +FUNCTION Word_t JudyLFreeArray
52 +#endif
53 + (
54 + PPvoid_t PPArray, // array to free.
55 + PJError_t PJError // optional, for returning error info.
56 + )
57 +{
58 + jpm_t jpm; // local to accumulate free statistics.
59 +
60 +// CHECK FOR NULL POINTER (error by caller):
61 +
62 + if (PPArray == (PPvoid_t) NULL)
63 + {
64 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY);
65 + return(JERR);
66 + }
67 +
68 + DBGCODE(JudyCheckPop(*PPArray);)
69 +
70 +// Zero jpm.jpm_Pop0 (meaning the array will be empty in a moment) for accurate
71 +// logging in TRACEMI2.
72 +
73 + jpm.jpm_Pop0 = 0; // see above.
74 + jpm.jpm_TotalMemWords = 0; // initialize memory freed.
75 +
76 +// Empty array:
77 +
78 + if (P_JLW(*PPArray) == (Pjlw_t) NULL) return(0);
79 +
80 +// PROCESS TOP LEVEL "JRP" BRANCHES AND LEAF:
81 +
82 + if (JU_LEAFW_POP0(*PPArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
83 + {
84 + Pjlw_t Pjlw = P_JLW(*PPArray); // first word of leaf.
85 +
86 + j__udyFreeJLW(Pjlw, Pjlw[0] + 1, &jpm);
87 + *PPArray = (Pvoid_t) NULL; // make an empty array.
88 + return (-(jpm.jpm_TotalMemWords * cJU_BYTESPERWORD)); // see above.
89 + }
90 + else
91 +
92 +// Rootstate leaves: just free the leaf:
93 +
94 +// Common code for returning the amount of memory freed.
95 +//
96 +// Note: In a an ordinary LEAFW, pop0 = *PPArray[0].
97 +//
98 +// Accumulate (negative) words freed, while freeing objects.
99 +// Return the positive bytes freed.
100 +
101 + {
102 + Pjpm_t Pjpm = P_JPM(*PPArray);
103 + Word_t TotalMem = Pjpm->jpm_TotalMemWords;
104 +
105 + j__udyFreeSM(&(Pjpm->jpm_JP), &jpm); // recurse through tree.
106 + j__udyFreeJPM(Pjpm, &jpm);
107 +
108 +// Verify the array was not corrupt. This means that amount of memory freed
109 +// (which is negative) is equal to the initial amount:
110 +
111 + if (TotalMem + jpm.jpm_TotalMemWords)
112 + {
113 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
114 + return(JERR);
115 + }
116 +
117 + *PPArray = (Pvoid_t) NULL; // make an empty array.
118 + return (TotalMem * cJU_BYTESPERWORD);
119 + }
120 +
121 +} // Judy1FreeArray() / JudyLFreeArray()
122 +
123 +
124 +// ****************************************************************************
125 +// __ J U D Y F R E E S M
126 +//
127 +// Given a pointer to a JP, recursively visit and free (depth first) all nodes
128 +// in a Judy array BELOW the JP, but not the JP itself. Accumulate in *Pjpm
129 +// the total words freed (as a negative value). "SM" = State Machine.
130 +//
131 +// Note: Corruption is not detected at this level because during a FreeArray,
132 +// if the code hasnt already core dumped, its better to remain silent, even
133 +// if some memory has not been freed, than to bother the caller about the
134 +// corruption. TBD: Is this true? If not, must list all legitimate JPNULL
135 +// and JPIMMED above first, and revert to returning bool_t (see 4.34).
136 +
137 +FUNCTION void j__udyFreeSM(
138 + Pjp_t Pjp, // top of Judy (top-state).
139 + Pjpm_t Pjpm) // to return words freed.
140 +{
141 + Word_t Pop1;
142 +
143 + switch (JU_JPTYPE(Pjp))
144 + {
145 +
146 +#ifdef JUDY1
147 +
148 +// FULL EXPANSE -- nothing to free for this jp_Type.
149 +
150 + case cJ1_JPFULLPOPU1:
151 + break;
152 +#endif
153 +
154 +// JUDY BRANCH -- free the sub-tree depth first:
155 +
156 +// LINEAR BRANCH -- visit each JP in the JBLs list, then free the JBL:
157 +//
158 +// Note: There are no null JPs in a JBL.
159 +
160 + case cJU_JPBRANCH_L:
161 + case cJU_JPBRANCH_L2:
162 + case cJU_JPBRANCH_L3:
163 +#ifdef JU_64BIT
164 + case cJU_JPBRANCH_L4:
165 + case cJU_JPBRANCH_L5:
166 + case cJU_JPBRANCH_L6:
167 + case cJU_JPBRANCH_L7:
168 +#endif // JU_64BIT
169 + {
170 + Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr);
171 + Word_t offset;
172 +
173 + for (offset = 0; offset < Pjbl->jbl_NumJPs; ++offset)
174 + j__udyFreeSM((Pjbl->jbl_jp) + offset, Pjpm);
175 +
176 + j__udyFreeJBL((Pjbl_t) (Pjp->jp_Addr), Pjpm);
177 + break;
178 + }
179 +
180 +
181 +// BITMAP BRANCH -- visit each JP in the JBBs list based on the bitmap, also
182 +//
183 +// Note: There are no null JPs in a JBB.
184 +
185 + case cJU_JPBRANCH_B:
186 + case cJU_JPBRANCH_B2:
187 + case cJU_JPBRANCH_B3:
188 +#ifdef JU_64BIT
189 + case cJU_JPBRANCH_B4:
190 + case cJU_JPBRANCH_B5:
191 + case cJU_JPBRANCH_B6:
192 + case cJU_JPBRANCH_B7:
193 +#endif // JU_64BIT
194 + {
195 + Word_t subexp;
196 + Word_t offset;
197 + Word_t jpcount;
198 +
199 + Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr);
200 +
201 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
202 + {
203 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
204 +
205 + if (jpcount)
206 + {
207 + for (offset = 0; offset < jpcount; ++offset)
208 + {
209 + j__udyFreeSM(P_JP(JU_JBB_PJP(Pjbb, subexp)) + offset,
210 + Pjpm);
211 + }
212 + j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, subexp), jpcount, Pjpm);
213 + }
214 + }
215 + j__udyFreeJBB((Pjbb_t) (Pjp->jp_Addr), Pjpm);
216 +
217 + break;
218 + }
219 +
220 +
221 +// UNCOMPRESSED BRANCH -- visit each JP in the JBU array, then free the JBU
222 +// itself:
223 +//
224 +// Note: Null JPs are handled during recursion at a lower state.
225 +
226 + case cJU_JPBRANCH_U:
227 + case cJU_JPBRANCH_U2:
228 + case cJU_JPBRANCH_U3:
229 +#ifdef JU_64BIT
230 + case cJU_JPBRANCH_U4:
231 + case cJU_JPBRANCH_U5:
232 + case cJU_JPBRANCH_U6:
233 + case cJU_JPBRANCH_U7:
234 +#endif // JU_64BIT
235 + {
236 + Word_t offset;
237 + Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr);
238 +
239 + for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
240 + j__udyFreeSM((Pjbu->jbu_jp) + offset, Pjpm);
241 +
242 + j__udyFreeJBU((Pjbu_t) (Pjp->jp_Addr), Pjpm);
243 + break;
244 + }
245 +
246 +
247 +// -- Cases below here terminate and do not recurse. --
248 +
249 +
250 +// LINEAR LEAF -- just free the leaf; size is computed from jp_Type:
251 +//
252 +// Note: cJU_JPLEAF1 is a special case, see discussion in ../Judy1/Judy1.h
253 +
254 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
255 + case cJU_JPLEAF1:
256 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
257 + j__udyFreeJLL1((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
258 + break;
259 +#endif
260 +
261 + case cJU_JPLEAF2:
262 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
263 + j__udyFreeJLL2((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
264 + break;
265 +
266 + case cJU_JPLEAF3:
267 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
268 + j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
269 + break;
270 +
271 +#ifdef JU_64BIT
272 + case cJU_JPLEAF4:
273 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
274 + j__udyFreeJLL4((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
275 + break;
276 +
277 + case cJU_JPLEAF5:
278 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
279 + j__udyFreeJLL5((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
280 + break;
281 +
282 + case cJU_JPLEAF6:
283 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
284 + j__udyFreeJLL6((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
285 + break;
286 +
287 + case cJU_JPLEAF7:
288 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
289 + j__udyFreeJLL7((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
290 + break;
291 +#endif // JU_64BIT
292 +
293 +
294 +// BITMAP LEAF -- free sub-expanse arrays of JPs, then free the JBB.
295 +
296 + case cJU_JPLEAF_B1:
297 + {
298 +#ifdef JUDYL
299 + Word_t subexp;
300 + Word_t jpcount;
301 + Pjlb_t Pjlb = P_JLB(Pjp->jp_Addr);
302 +
303 +// Free the value areas in the bitmap leaf:
304 +
305 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
306 + {
307 + jpcount = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
308 +
309 + if (jpcount)
310 + j__udyLFreeJV(JL_JLB_PVALUE(Pjlb, subexp), jpcount, Pjpm);
311 + }
312 +#endif // JUDYL
313 +
314 + j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm);
315 + break;
316 +
317 + } // case cJU_JPLEAF_B1
318 +
319 +#ifdef JUDYL
320 +
321 +
322 +// IMMED*:
323 +//
324 +// For JUDYL, all non JPIMMED_*_01s have a LeafV which must be freed:
325 +
326 + case cJU_JPIMMED_1_02:
327 + case cJU_JPIMMED_1_03:
328 +#ifdef JU_64BIT
329 + case cJU_JPIMMED_1_04:
330 + case cJU_JPIMMED_1_05:
331 + case cJU_JPIMMED_1_06:
332 + case cJU_JPIMMED_1_07:
333 +#endif
334 + Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_02 + 2;
335 + j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm);
336 + break;
337 +
338 +#ifdef JU_64BIT
339 + case cJU_JPIMMED_2_02:
340 + case cJU_JPIMMED_2_03:
341 +
342 + Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_2_02 + 2;
343 + j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm);
344 + break;
345 +
346 + case cJU_JPIMMED_3_02:
347 + j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), 2, Pjpm);
348 + break;
349 +
350 +#endif // JU_64BIT
351 +#endif // JUDYL
352 +
353 +
354 +// OTHER JPNULL, JPIMMED, OR UNEXPECTED TYPE -- nothing to free for this type:
355 +//
356 +// Note: Lump together no-op and invalid JP types; see function header
357 +// comments.
358 +
359 + default: break;
360 +
361 + } // switch (JU_JPTYPE(Pjp))
362 +
363 +} // j__udyFreeSM()
libnetdata/libjudy/src/JudyL/JudyLGet.c new
+1094
@@ -0,0 +1,1094 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.43 $ $Source: /judy/src/JudyCommon/JudyGet.c $
19 +//
20 +// Judy1Test() and JudyLGet() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +#ifdef TRACEJPR // different macro name, for "retrieval" only.
36 +#include "JudyPrintJP.c"
37 +#endif
38 +
39 +
40 +// ****************************************************************************
41 +// J U D Y 1 T E S T
42 +// J U D Y L G E T
43 +//
44 +// See the manual entry for details. Note support for "shortcut" entries to
45 +// trees known to start with a JPM.
46 +
47 +#ifdef JUDY1
48 +
49 +#ifdef JUDYGETINLINE
50 +FUNCTION int j__udy1Test
51 +#else
52 +FUNCTION int Judy1Test
53 +#endif
54 +
55 +#else // JUDYL
56 +
57 +#ifdef JUDYGETINLINE
58 +FUNCTION PPvoid_t j__udyLGet
59 +#else
60 +FUNCTION PPvoid_t JudyLGet
61 +#endif
62 +
63 +#endif // JUDYL
64 + (
65 +#ifdef JUDYGETINLINE
66 + Pvoid_t PArray, // from which to retrieve.
67 + Word_t Index // to retrieve.
68 +#else
69 + Pcvoid_t PArray, // from which to retrieve.
70 + Word_t Index, // to retrieve.
71 + PJError_t PJError // optional, for returning error info.
72 +#endif
73 + )
74 +{
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;)
81 +
82 +#ifndef JUDYGETINLINE
83 +
84 + if (PArray == (Pcvoid_t) NULL) // empty array.
85 + {
86 + JUDY1CODE(return(0);)
87 + JUDYLCODE(return((PPvoid_t) NULL);)
88 + }
89 +
90 +// ****************************************************************************
91 +// PROCESS TOP LEVEL BRANCHES AND LEAF:
92 +
93 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
94 + {
95 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
96 + int posidx; // signed offset in leaf.
97 +
98 + Pop1 = Pjlw[0] + 1;
99 + posidx = j__udySearchLeafW(Pjlw + 1, Pop1, Index);
100 +
101 + if (posidx >= 0)
102 + {
103 + JUDY1CODE(return(1);)
104 + JUDYLCODE(return((PPvoid_t) (JL_LEAFWVALUEAREA(Pjlw, Pop1) + posidx));)
105 + }
106 + JUDY1CODE(return(0);)
107 + JUDYLCODE(return((PPvoid_t) NULL);)
108 + }
109 +
110 +#endif // ! JUDYGETINLINE
111 +
112 + Pjpm = P_JPM(PArray);
113 + Pjp = &(Pjpm->jpm_JP); // top branch is below JPM.
114 +
115 +// ****************************************************************************
116 +// WALK THE JUDY TREE USING A STATE MACHINE:
117 +
118 +ContinueWalk: // for going down one level; come here with Pjp set.
119 +
120 +#ifdef TRACEJPR
121 + JudyPrintJP(Pjp, "g", __LINE__);
122 +#endif
123 + switch (JU_JPTYPE(Pjp))
124 + {
125 +
126 +// Ensure the switch table starts at 0 for speed; otherwise more code is
127 +// executed:
128 +
129 + case 0: goto ReturnCorrupt; // save a little code.
130 +
131 +
132 +// ****************************************************************************
133 +// JPNULL*:
134 +//
135 +// Note: These are legitimate in a BranchU (only) and do not constitute a
136 +// fault.
137 +
138 + case cJU_JPNULL1:
139 + case cJU_JPNULL2:
140 + case cJU_JPNULL3:
141 +#ifdef JU_64BIT
142 + case cJU_JPNULL4:
143 + case cJU_JPNULL5:
144 + case cJU_JPNULL6:
145 + case cJU_JPNULL7:
146 +#endif
147 + assert(ParentJPType >= cJU_JPBRANCH_U2);
148 + assert(ParentJPType <= cJU_JPBRANCH_U);
149 + JUDY1CODE(return(0);)
150 + JUDYLCODE(return((PPvoid_t) NULL);)
151 +
152 +
153 +// ****************************************************************************
154 +// JPBRANCH_L*:
155 +//
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.
159 +
160 + case cJU_JPBRANCH_L2:
161 +
162 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
163 + Digit = JU_DIGITATSTATE(Index, 2);
164 + goto JudyBranchL;
165 +
166 + case cJU_JPBRANCH_L3:
167 +
168 +#ifdef JU_64BIT // otherwise its a no-op:
169 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
170 +#endif
171 + Digit = JU_DIGITATSTATE(Index, 3);
172 + goto JudyBranchL;
173 +
174 +#ifdef JU_64BIT
175 + case cJU_JPBRANCH_L4:
176 +
177 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
178 + Digit = JU_DIGITATSTATE(Index, 4);
179 + goto JudyBranchL;
180 +
181 + case cJU_JPBRANCH_L5:
182 +
183 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
184 + Digit = JU_DIGITATSTATE(Index, 5);
185 + goto JudyBranchL;
186 +
187 + case cJU_JPBRANCH_L6:
188 +
189 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
190 + Digit = JU_DIGITATSTATE(Index, 6);
191 + goto JudyBranchL;
192 +
193 + case cJU_JPBRANCH_L7:
194 +
195 + // JU_DCDNOTMATCHINDEX() would be a no-op.
196 + Digit = JU_DIGITATSTATE(Index, 7);
197 + goto JudyBranchL;
198 +
199 +#endif // JU_64BIT
200 +
201 + case cJU_JPBRANCH_L:
202 + {
203 + Pjbl_t Pjbl;
204 + int posidx;
205 +
206 + Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
207 +
208 +// Common code for all BranchLs; come here with Digit set:
209 +
210 +JudyBranchL:
211 + Pjbl = P_JBL(Pjp->jp_Addr);
212 +
213 + posidx = 0;
214 +
215 + do {
216 + if (Pjbl->jbl_Expanse[posidx] == Digit)
217 + { // found Digit; continue traversal:
218 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
219 + Pjp = Pjbl->jbl_jp + posidx;
220 + goto ContinueWalk;
221 + }
222 + } while (++posidx != Pjbl->jbl_NumJPs);
223 +
224 + break;
225 + }
226 +
227 +
228 +// ****************************************************************************
229 +// JPBRANCH_B*:
230 +
231 + case cJU_JPBRANCH_B2:
232 +
233 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
234 + Digit = JU_DIGITATSTATE(Index, 2);
235 + goto JudyBranchB;
236 +
237 + case cJU_JPBRANCH_B3:
238 +
239 +#ifdef JU_64BIT // otherwise its a no-op:
240 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
241 +#endif
242 + Digit = JU_DIGITATSTATE(Index, 3);
243 + goto JudyBranchB;
244 +
245 +
246 +#ifdef JU_64BIT
247 + case cJU_JPBRANCH_B4:
248 +
249 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
250 + Digit = JU_DIGITATSTATE(Index, 4);
251 + goto JudyBranchB;
252 +
253 + case cJU_JPBRANCH_B5:
254 +
255 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
256 + Digit = JU_DIGITATSTATE(Index, 5);
257 + goto JudyBranchB;
258 +
259 + case cJU_JPBRANCH_B6:
260 +
261 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
262 + Digit = JU_DIGITATSTATE(Index, 6);
263 + goto JudyBranchB;
264 +
265 + case cJU_JPBRANCH_B7:
266 +
267 + // JU_DCDNOTMATCHINDEX() would be a no-op.
268 + Digit = JU_DIGITATSTATE(Index, 7);
269 + goto JudyBranchB;
270 +
271 +#endif // JU_64BIT
272 +
273 + case cJU_JPBRANCH_B:
274 + {
275 + Pjbb_t Pjbb;
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.
279 +
280 + Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
281 +
282 +// Common code for all BranchBs; come here with Digit set:
283 +
284 +JudyBranchB:
285 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
286 + Pjbb = P_JBB(Pjp->jp_Addr);
287 + subexp = Digit / cJU_BITSPERSUBEXPB;
288 +
289 + BitMap = JU_JBB_BITMAP(Pjbb, subexp);
290 + Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp));
291 +
292 + BitMask = JU_BITPOSMASKB(Digit);
293 +
294 +// No JP in subexpanse for Index => Index not found:
295 +
296 + if (! (BitMap & BitMask)) break;
297 +
298 +// Count JPs in the subexpanse below the one for Index:
299 +
300 + Pjp += j__udyCountBitsB(BitMap & (BitMask - 1));
301 +
302 + goto ContinueWalk;
303 +
304 + } // case cJU_JPBRANCH_B*
305 +
306 +
307 +// ****************************************************************************
308 +// JPBRANCH_U*:
309 +//
310 +// Notice the reverse order of the cases, and falling through to the next case,
311 +// for performance.
312 +
313 + case cJU_JPBRANCH_U:
314 +
315 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
316 + Pjp = JU_JBU_PJP(Pjp, Index, cJU_ROOTSTATE);
317 +
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:
321 +
322 +#ifndef JU_64BIT
323 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
324 +#else
325 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U7) goto ContinueWalk;
326 +#endif
327 +
328 +#ifdef JU_64BIT
329 + case cJU_JPBRANCH_U7:
330 +
331 + // JU_DCDNOTMATCHINDEX() would be a no-op.
332 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
333 + Pjp = JU_JBU_PJP(Pjp, Index, 7);
334 +
335 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U6) goto ContinueWalk;
336 + // and fall through.
337 +
338 + case cJU_JPBRANCH_U6:
339 +
340 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
341 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
342 + Pjp = JU_JBU_PJP(Pjp, Index, 6);
343 +
344 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U5) goto ContinueWalk;
345 + // and fall through.
346 +
347 + case cJU_JPBRANCH_U5:
348 +
349 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
350 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
351 + Pjp = JU_JBU_PJP(Pjp, Index, 5);
352 +
353 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U4) goto ContinueWalk;
354 + // and fall through.
355 +
356 + case cJU_JPBRANCH_U4:
357 +
358 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
359 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
360 + Pjp = JU_JBU_PJP(Pjp, Index, 4);
361 +
362 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
363 + // and fall through.
364 +
365 +#endif // JU_64BIT
366 +
367 + case cJU_JPBRANCH_U3:
368 +
369 +#ifdef JU_64BIT // otherwise its a no-op:
370 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
371 +#endif
372 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
373 + Pjp = JU_JBU_PJP(Pjp, Index, 3);
374 +
375 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U2) goto ContinueWalk;
376 + // and fall through.
377 +
378 + case cJU_JPBRANCH_U2:
379 +
380 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
381 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
382 + Pjp = JU_JBU_PJP(Pjp, Index, 2);
383 +
384 +// Note: BranchU2 is a special case that must continue traversal to a leaf,
385 +// immed, full, or null type:
386 +
387 + goto ContinueWalk;
388 +
389 +
390 +// ****************************************************************************
391 +// JPLEAF*:
392 +//
393 +// Note: Here the calls of JU_DCDNOTMATCHINDEX() are necessary and check
394 +// whether Index is out of the expanse of a narrow pointer.
395 +
396 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
397 +
398 + case cJU_JPLEAF1:
399 + {
400 + int posidx; // signed offset in leaf.
401 +
402 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
403 +
404 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
405 + Pjll = P_JLL(Pjp->jp_Addr);
406 +
407 + if ((posidx = j__udySearchLeaf1(Pjll, Pop1, Index)) < 0) break;
408 +
409 + JUDY1CODE(return(1);)
410 + JUDYLCODE(return((PPvoid_t) (JL_LEAF1VALUEAREA(Pjll, Pop1) + posidx));)
411 + }
412 +
413 +#endif // (JUDYL || (! JU_64BIT))
414 +
415 + case cJU_JPLEAF2:
416 + {
417 + int posidx; // signed offset in leaf.
418 +
419 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
420 +
421 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
422 + Pjll = P_JLL(Pjp->jp_Addr);
423 +
424 + if ((posidx = j__udySearchLeaf2(Pjll, Pop1, Index)) < 0) break;
425 +
426 + JUDY1CODE(return(1);)
427 + JUDYLCODE(return((PPvoid_t) (JL_LEAF2VALUEAREA(Pjll, Pop1) + posidx));)
428 + }
429 + case cJU_JPLEAF3:
430 + {
431 + int posidx; // signed offset in leaf.
432 +
433 +#ifdef JU_64BIT // otherwise its a no-op:
434 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
435 +#endif
436 +
437 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
438 + Pjll = P_JLL(Pjp->jp_Addr);
439 +
440 + if ((posidx = j__udySearchLeaf3(Pjll, Pop1, Index)) < 0) break;
441 +
442 + JUDY1CODE(return(1);)
443 + JUDYLCODE(return((PPvoid_t) (JL_LEAF3VALUEAREA(Pjll, Pop1) + posidx));)
444 + }
445 +#ifdef JU_64BIT
446 + case cJU_JPLEAF4:
447 + {
448 + int posidx; // signed offset in leaf.
449 +
450 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
451 +
452 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
453 + Pjll = P_JLL(Pjp->jp_Addr);
454 +
455 + if ((posidx = j__udySearchLeaf4(Pjll, Pop1, Index)) < 0) break;
456 +
457 + JUDY1CODE(return(1);)
458 + JUDYLCODE(return((PPvoid_t) (JL_LEAF4VALUEAREA(Pjll, Pop1) + posidx));)
459 + }
460 + case cJU_JPLEAF5:
461 + {
462 + int posidx; // signed offset in leaf.
463 +
464 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
465 +
466 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
467 + Pjll = P_JLL(Pjp->jp_Addr);
468 +
469 + if ((posidx = j__udySearchLeaf5(Pjll, Pop1, Index)) < 0) break;
470 +
471 + JUDY1CODE(return(1);)
472 + JUDYLCODE(return((PPvoid_t) (JL_LEAF5VALUEAREA(Pjll, Pop1) + posidx));)
473 + }
474 +
475 + case cJU_JPLEAF6:
476 + {
477 + int posidx; // signed offset in leaf.
478 +
479 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
480 +
481 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
482 + Pjll = P_JLL(Pjp->jp_Addr);
483 +
484 + if ((posidx = j__udySearchLeaf6(Pjll, Pop1, Index)) < 0) break;
485 +
486 + JUDY1CODE(return(1);)
487 + JUDYLCODE(return((PPvoid_t) (JL_LEAF6VALUEAREA(Pjll, Pop1) + posidx));)
488 + }
489 + case cJU_JPLEAF7:
490 + {
491 + int posidx; // signed offset in leaf.
492 +
493 + // JU_DCDNOTMATCHINDEX() would be a no-op.
494 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
495 + Pjll = P_JLL(Pjp->jp_Addr);
496 +
497 + if ((posidx = j__udySearchLeaf7(Pjll, Pop1, Index)) < 0) break;
498 +
499 + JUDY1CODE(return(1);)
500 + JUDYLCODE(return((PPvoid_t) (JL_LEAF7VALUEAREA(Pjll, Pop1) + posidx));)
501 + }
502 +#endif // JU_64BIT
503 +
504 +
505 +// ****************************************************************************
506 +// JPLEAF_B1:
507 +
508 + case cJU_JPLEAF_B1:
509 + {
510 + Pjlb_t Pjlb;
511 +#ifdef JUDYL
512 + int posidx;
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.
516 + Pjv_t Pjv;
517 +#endif
518 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
519 +
520 + Pjlb = P_JLB(Pjp->jp_Addr);
521 +
522 +#ifdef JUDY1
523 +
524 +// Simply check if Indexs bit is set in the bitmap:
525 +
526 + if (JU_BITMAPTESTL(Pjlb, Index)) return(1);
527 + break;
528 +
529 +#else // JUDYL
530 +
531 +// JudyL is much more complicated because of value area subarrays:
532 +
533 + Digit = JU_DIGITATSTATE(Index, 1);
534 + subexp = Digit / cJU_BITSPERSUBEXPL;
535 + BitMap = JU_JLB_BITMAP(Pjlb, subexp);
536 + BitMask = JU_BITPOSMASKL(Digit);
537 +
538 +// No value in subexpanse for Index => Index not found:
539 +
540 + if (! (BitMap & BitMask)) break;
541 +
542 +// Count value areas in the subexpanse below the one for Index:
543 +
544 + Pjv = P_JV(JL_JLB_PVALUE(Pjlb, subexp));
545 + assert(Pjv != (Pjv_t) NULL);
546 + posidx = j__udyCountBitsL(BitMap & (BitMask - 1));
547 +
548 + return((PPvoid_t) (Pjv + posidx));
549 +
550 +#endif // JUDYL
551 +
552 + } // case cJU_JPLEAF_B1
553 +
554 +#ifdef JUDY1
555 +
556 +// ****************************************************************************
557 +// JPFULLPOPU1:
558 +//
559 +// If the Index is in the expanse, it is necessarily valid (found).
560 +
561 + case cJ1_JPFULLPOPU1:
562 +
563 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
564 + return(1);
565 +
566 +#ifdef notdef // for future enhancements
567 +#ifdef JU_64BIT
568 +
569 +// Note: Need ? if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
570 +
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;
587 +#endif
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;
602 +
603 + return(1); // found, not in exclusion list
604 +
605 +#endif // JUDY1
606 +#endif // notdef
607 +
608 +// ****************************************************************************
609 +// JPIMMED*:
610 +//
611 +// Note that the contents of jp_DcdPopO are different for cJU_JPIMMED_*_01:
612 +
613 + case cJU_JPIMMED_1_01:
614 + case cJU_JPIMMED_2_01:
615 + case cJU_JPIMMED_3_01:
616 +#ifdef JU_64BIT
617 + case cJU_JPIMMED_4_01:
618 + case cJU_JPIMMED_5_01:
619 + case cJU_JPIMMED_6_01:
620 + case cJU_JPIMMED_7_01:
621 +#endif
622 + if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) break;
623 +
624 + JUDY1CODE(return(1);)
625 + JUDYLCODE(return((PPvoid_t) &(Pjp->jp_Addr));) // immediate value area.
626 +
627 +
628 +// Macros to make code more readable and avoid dup errors
629 +
630 +#ifdef JUDY1
631 +
632 +#define CHECKINDEXNATIVE(LEAF_T, PJP, IDX, INDEX) \
633 +if (((LEAF_T *)((PJP)->jp_1Index))[(IDX) - 1] == (LEAF_T)(INDEX)) \
634 + return(1)
635 +
636 +#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
637 +{ \
638 + Word_t i_ndex; \
639 + uint8_t *a_ddr; \
640 + a_ddr = (PJP)->jp_1Index + (((IDX) - 1) * (LFBTS)); \
641 + COPY(i_ndex, a_ddr); \
642 + if (i_ndex == JU_LEASTBYTES((INDEX), (LFBTS))) \
643 + return(1); \
644 +}
645 +#endif
646 +
647 +#ifdef JUDYL
648 +
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))
652 +
653 +#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
654 +{ \
655 + Word_t i_ndex; \
656 + uint8_t *a_ddr; \
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)); \
661 +}
662 +#endif
663 +
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);
673 +#endif
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);
679 +#endif
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);
683 + break;
684 +
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);
690 +#endif
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);
695 + break;
696 +#endif
697 +
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);
705 +#endif
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);
710 + break;
711 +#endif
712 +
713 +#if (defined(JUDY1) && defined(JU_64BIT))
714 +
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);
718 + break;
719 +
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);
725 + break;
726 +
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);
730 + break;
731 +
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);
735 + break;
736 +
737 +#endif // (JUDY1 && JU_64BIT)
738 +
739 +
740 +// ****************************************************************************
741 +// INVALID JP TYPE:
742 +
743 + default:
744 +
745 +ReturnCorrupt:
746 +
747 +#ifdef JUDYGETINLINE // Pjpm is known to be non-null:
748 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
749 +#else
750 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
751 +#endif
752 + JUDY1CODE(return(JERRI );)
753 + JUDYLCODE(return(PPJERR);)
754 +
755 + } // switch on JP type
756 +
757 +JUDY1CODE(return(0);)
758 +JUDYLCODE(return((PPvoid_t) NULL);)
759 +
760 +} // Judy1Test() / JudyLGet()
761 +
762 +
763 +#ifndef JUDYGETINLINE // only compile the following function once:
764 +#ifdef DEBUG
765 +
766 +// ****************************************************************************
767 +// J U D Y C H E C K P O P
768 +//
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.
771 +//
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.
775 +//
776 +// Note: Even though this function does nothing useful for LEAFW leaves, its
777 +// good practice to call it anyway, and cheap too.
778 +//
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.
782 +//
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?
787 +//
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:
792 +//
793 +// - Zero LS bits in jp_Addr field.
794 +//
795 +// - Correct Dcd bits.
796 +//
797 +// - Consistent JP types (always descending down the tree).
798 +//
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).
802 +//
803 +// - Any others possible?
804 +
805 +#include <stdlib.h> // for getenv() and atol().
806 +
807 +static Word_t JudyCheckPopSM(Pjp_t Pjp, Word_t RootPop1);
808 +
809 +FUNCTION void JudyCheckPop(
810 + Pvoid_t PArray)
811 +{
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.
817 +
818 +
819 +// CHECK FOR EXTERNAL ENABLING:
820 +
821 + if (! checked) // only check once.
822 + {
823 + char * value; // for getenv().
824 +
825 + checked = TRUE;
826 +
827 + if ((value = getenv("CHECKPOP")) == (char *) NULL)
828 + {
829 +#ifdef notdef
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:
832 +
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");
836 +#endif
837 + return;
838 + }
839 +
840 + callsmin = atol(value); // note: non-number evaluates to 0.
841 + enabled = TRUE;
842 +
843 + (void) printf("JudyCheckPop() present and enabled; callsmin = "
844 + "%lu\n", callsmin);
845 + }
846 + else if (! enabled) return;
847 +
848 +// Previously or just now enabled; check if non-active or newly active:
849 +
850 + if (! active)
851 + {
852 + if (++calls < callsmin) return;
853 +
854 + (void) printf("JudyCheckPop() activated at call %lu\n", calls);
855 + active = TRUE;
856 + }
857 +
858 +// IGNORE LEAFW AT TOP OF TREE:
859 +
860 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
861 + return;
862 +
863 +// Check JPM pop0 against tree, recursively:
864 +//
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.
870 +
871 + {
872 + Pjpm_t Pjpm = P_JPM(PArray);
873 + (void) JudyCheckPopSM(&(Pjpm->jpm_JP), Pjpm->jpm_Pop0 + 1);
874 + return;
875 + }
876 +
877 +} // JudyCheckPop()
878 +
879 +
880 +// ****************************************************************************
881 +// J U D Y C H E C K P O P S M
882 +//
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.
887 +//
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.
890 +
891 +FUNCTION static Word_t JudyCheckPopSM(
892 + Pjp_t Pjp, // top of subtree.
893 + Word_t RootPop1) // whole array, for top-level branches only.
894 +{
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.
898 +
899 +#define PREPBRANCH(cPopBytes,Next) \
900 + pop1_jp = JU_JPBRANCH_POP0(Pjp, cPopBytes) + 1; goto Next
901 +
902 +assert((((Word_t) (Pjp->jp_Addr)) & 7) == 3);
903 + switch (JU_JPTYPE(Pjp))
904 + {
905 +
906 + case cJU_JPBRANCH_L2: PREPBRANCH(2, BranchL);
907 + case cJU_JPBRANCH_L3: PREPBRANCH(3, BranchL);
908 +#ifdef JU_64BIT
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);
913 +#endif
914 + case cJU_JPBRANCH_L: pop1_jp = RootPop1;
915 + {
916 + Pjbl_t Pjbl;
917 +BranchL:
918 + Pjbl = P_JBL(Pjp->jp_Addr);
919 +
920 + for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
921 + pop1 += JudyCheckPopSM((Pjbl->jbl_jp) + offset, 0);
922 +
923 + assert(pop1_jp == pop1);
924 + return(pop1);
925 + }
926 +
927 + case cJU_JPBRANCH_B2: PREPBRANCH(2, BranchB);
928 + case cJU_JPBRANCH_B3: PREPBRANCH(3, BranchB);
929 +#ifdef JU_64BIT
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);
934 +#endif
935 + case cJU_JPBRANCH_B: pop1_jp = RootPop1;
936 + {
937 + Word_t subexp;
938 + Word_t jpcount;
939 + Pjbb_t Pjbb;
940 +BranchB:
941 + Pjbb = P_JBB(Pjp->jp_Addr);
942 +
943 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
944 + {
945 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
946 +
947 + for (offset = 0; offset < jpcount; ++offset)
948 + {
949 + pop1 += JudyCheckPopSM(P_JP(JU_JBB_PJP(Pjbb, subexp))
950 + + offset, 0);
951 + }
952 + }
953 +
954 + assert(pop1_jp == pop1);
955 + return(pop1);
956 + }
957 +
958 + case cJU_JPBRANCH_U2: PREPBRANCH(2, BranchU);
959 + case cJU_JPBRANCH_U3: PREPBRANCH(3, BranchU);
960 +#ifdef JU_64BIT
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);
965 +#endif
966 + case cJU_JPBRANCH_U: pop1_jp = RootPop1;
967 + {
968 + Pjbu_t Pjbu;
969 +BranchU:
970 + Pjbu = P_JBU(Pjp->jp_Addr);
971 +
972 + for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
973 + {
974 + if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
975 + && ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
976 + {
977 + continue; // skip null JP to save time.
978 + }
979 +
980 + pop1 += JudyCheckPopSM((Pjbu->jbu_jp) + offset, 0);
981 + }
982 +
983 + assert(pop1_jp == pop1);
984 + return(pop1);
985 + }
986 +
987 +
988 +// -- Cases below here terminate and do not recurse. --
989 +//
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.
993 +
994 +#define CHECKLEAF(MaxPop1) \
995 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
996 + assert(pop1 >= 1); \
997 + assert(pop1 <= (MaxPop1)); \
998 + return(pop1)
999 +
1000 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1001 + case cJU_JPLEAF1: CHECKLEAF(cJU_LEAF1_MAXPOP1);
1002 +#endif
1003 + case cJU_JPLEAF2: CHECKLEAF(cJU_LEAF2_MAXPOP1);
1004 + case cJU_JPLEAF3: CHECKLEAF(cJU_LEAF3_MAXPOP1);
1005 +#ifdef JU_64BIT
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);
1010 +#endif
1011 +
1012 + case cJU_JPLEAF_B1:
1013 + {
1014 + Word_t subexp;
1015 + Pjlb_t Pjlb;
1016 +
1017 + pop1_jp = JU_JPLEAF_POP0(Pjp) + 1;
1018 +
1019 + Pjlb = P_JLB(Pjp->jp_Addr);
1020 +
1021 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
1022 + pop1 += j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
1023 +
1024 + assert(pop1_jp == pop1);
1025 + return(pop1);
1026 + }
1027 +
1028 + JUDY1CODE(case cJ1_JPFULLPOPU1: return(cJU_JPFULLPOPU1_POP0);)
1029 +
1030 + case cJU_JPIMMED_1_01: return(1);
1031 + case cJU_JPIMMED_2_01: return(1);
1032 + case cJU_JPIMMED_3_01: return(1);
1033 +#ifdef JU_64BIT
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);
1038 +#endif
1039 +
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);
1047 +#endif
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);
1057 +#endif
1058 +
1059 +#if (defined(JUDY1) || defined(JU_64BIT))
1060 + case cJU_JPIMMED_2_02: return(2);
1061 + case cJU_JPIMMED_2_03: return(3);
1062 +#endif
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);
1068 +#endif
1069 +
1070 +#if (defined(JUDY1) || defined(JU_64BIT))
1071 + case cJU_JPIMMED_3_02: return(2);
1072 +#endif
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);
1077 +
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);
1084 +#endif
1085 +
1086 + } // switch (JU_JPTYPE(Pjp))
1087 +
1088 + assert(FALSE); // unrecognized JP type => corruption.
1089 + return(0); // to make some compilers happy.
1090 +
1091 +} // JudyCheckPopSM()
1092 +
1093 +#endif // DEBUG
1094 +#endif // ! JUDYGETINLINE
libnetdata/libjudy/src/JudyL/JudyLIns.c new
+1873
@@ -0,0 +1,1873 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.116 $ $Source: /judy/src/JudyCommon/JudyIns.c $
19 +//
20 +// Judy1Set() and JudyLIns() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// TBD: Should some of the assertions here be converted to product code that
24 +// returns JU_ERRNO_CORRUPT?
25 +
26 +#if (! (defined(JUDY1) || defined(JUDYL)))
27 +#error: One of -DJUDY1 or -DJUDYL must be specified.
28 +#endif
29 +
30 +#ifdef JUDY1
31 +#include "Judy1.h"
32 +#else
33 +#include "JudyL.h"
34 +#endif
35 +
36 +#include "JudyPrivate1L.h"
37 +
38 +// Note: Call JudyCheckPop() even before "already inserted" returns, to catch
39 +// population errors; see fix in 4.84:
40 +
41 +DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);)
42 +DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)
43 +
44 +#ifdef TRACEJP
45 +#include "JudyPrintJP.c"
46 +#endif
47 +
48 +
49 +// These are defined to generic values in JudyCommon/JudyPrivateTypes.h:
50 +//
51 +// TBD: These should be exported from a header file, but perhaps not, as they
52 +// are only used here, and exported from Judy*Decascade, which is a separate
53 +// file for profiling reasons (to prevent inlining), but which potentially
54 +// could be merged with this file, either in SoftCM or at compile-time.
55 +
56 +#ifdef JUDY1
57 +extern int j__udy1CreateBranchB(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
58 +extern int j__udy1CreateBranchU(Pjp_t, Pvoid_t);
59 +
60 +#ifndef JU_64BIT
61 +extern int j__udy1Cascade1(Pjp_t, Pvoid_t);
62 +#endif
63 +extern int j__udy1Cascade2(Pjp_t, Pvoid_t);
64 +extern int j__udy1Cascade3(Pjp_t, Pvoid_t);
65 +#ifdef JU_64BIT
66 +extern int j__udy1Cascade4(Pjp_t, Pvoid_t);
67 +extern int j__udy1Cascade5(Pjp_t, Pvoid_t);
68 +extern int j__udy1Cascade6(Pjp_t, Pvoid_t);
69 +extern int j__udy1Cascade7(Pjp_t, Pvoid_t);
70 +#endif
71 +extern int j__udy1CascadeL(Pjp_t, Pvoid_t);
72 +
73 +extern int j__udy1InsertBranch(Pjp_t Pjp, Word_t Index, Word_t Btype, Pjpm_t);
74 +
75 +#else // JUDYL
76 +
77 +extern int j__udyLCreateBranchB(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
78 +extern int j__udyLCreateBranchU(Pjp_t, Pvoid_t);
79 +
80 +extern int j__udyLCascade1(Pjp_t, Pvoid_t);
81 +extern int j__udyLCascade2(Pjp_t, Pvoid_t);
82 +extern int j__udyLCascade3(Pjp_t, Pvoid_t);
83 +#ifdef JU_64BIT
84 +extern int j__udyLCascade4(Pjp_t, Pvoid_t);
85 +extern int j__udyLCascade5(Pjp_t, Pvoid_t);
86 +extern int j__udyLCascade6(Pjp_t, Pvoid_t);
87 +extern int j__udyLCascade7(Pjp_t, Pvoid_t);
88 +#endif
89 +extern int j__udyLCascadeL(Pjp_t, Pvoid_t);
90 +
91 +extern int j__udyLInsertBranch(Pjp_t Pjp, Word_t Index, Word_t Btype, Pjpm_t);
92 +#endif
93 +
94 +
95 +// ****************************************************************************
96 +// MACROS FOR COMMON CODE:
97 +//
98 +// Check if Index is an outlier to (that is, not a member of) this expanse:
99 +//
100 +// An outlier is an Index in-the-expanse of the slot containing the pointer,
101 +// but not-in-the-expanse of the "narrow" pointer in that slot. (This means
102 +// the Dcd part of the Index differs from the equivalent part of jp_DcdPopO.)
103 +// Therefore, the remedy is to put a cJU_JPBRANCH_L* between the narrow pointer
104 +// and the object to which it points, and add the outlier Index as an Immediate
105 +// in the cJU_JPBRANCH_L*. The "trick" is placing the cJU_JPBRANCH_L* at a
106 +// Level that is as low as possible. This is determined by counting the digits
107 +// in the existing narrow pointer that are the same as the digits in the new
108 +// Index (see j__udyInsertBranch()).
109 +//
110 +// Note: At some high Levels, cJU_DCDMASK() is all zeros => dead code; assume
111 +// the compiler optimizes this out.
112 +
113 +#define JU_CHECK_IF_OUTLIER(Pjp, Index, cLevel, Pjpm) \
114 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, cLevel)) \
115 + return(j__udyInsertBranch(Pjp, Index, cLevel, Pjpm))
116 +
117 +// Check if an Index is already in a leaf or immediate, after calling
118 +// j__udySearchLeaf*() to set Offset:
119 +//
120 +// A non-negative Offset means the Index already exists, so return 0; otherwise
121 +// complement Offset to proceed.
122 +
123 +#ifdef JUDY1
124 +#define Pjv ignore // placeholder.
125 +#define JU_CHECK_IF_EXISTS(Offset,ignore,Pjpm) \
126 + { \
127 + if ((Offset) >= 0) return(0); \
128 + (Offset) = ~(Offset); \
129 + }
130 +#else
131 +// For JudyL, also set the value area pointer in the Pjpm:
132 +
133 +#define JU_CHECK_IF_EXISTS(Offset,Pjv,Pjpm) \
134 + { \
135 + if ((Offset) >= 0) \
136 + { \
137 + (Pjpm)->jpm_PValue = (Pjv) + (Offset); \
138 + return(0); \
139 + } \
140 + (Offset) = ~(Offset); \
141 + }
142 +#endif
143 +
144 +
145 +// ****************************************************************************
146 +// __ J U D Y I N S W A L K
147 +//
148 +// Walk the Judy tree to do a set/insert. This is only called internally, and
149 +// recursively. Unlike Judy1Test() and JudyLGet(), the extra time required for
150 +// recursion should be negligible compared with the total.
151 +//
152 +// Return -1 for error (details in JPM), 0 for Index already inserted, 1 for
153 +// new Index inserted.
154 +
155 +FUNCTION static int j__udyInsWalk(
156 + Pjp_t Pjp, // current JP to descend.
157 + Word_t Index, // to insert.
158 + Pjpm_t Pjpm) // for returning info to top Level.
159 +{
160 + uint8_t digit; // from Index, current offset into a branch.
161 + jp_t newJP; // for creating a new Immed JP.
162 + Word_t exppop1; // expanse (leaf) population.
163 + int retcode; // return codes: -1, 0, 1.
164 +
165 +#ifdef SUBEXPCOUNTS
166 +// Pointer to BranchB/U subexpanse counter:
167 +//
168 +// Note: Very important for performance reasons (avoids cache fills).
169 +
170 + PWord_t PSubExp = (PWord_t) NULL;
171 +#endif
172 +
173 +ContinueInsWalk: // for modifying state without recursing.
174 +
175 +#ifdef TRACEJP
176 + JudyPrintJP(Pjp, "i", __LINE__);
177 +#endif
178 +
179 + switch (JU_JPTYPE(Pjp)) // entry: Pjp, Index.
180 + {
181 +
182 +
183 +// ****************************************************************************
184 +// JPNULL*:
185 +//
186 +// Convert JP in place from current null type to cJU_JPIMMED_*_01 by
187 +// calculating new JP type.
188 +
189 + case cJU_JPNULL1:
190 + case cJU_JPNULL2:
191 + case cJU_JPNULL3:
192 +#ifdef JU_64BIT
193 + case cJU_JPNULL4:
194 + case cJU_JPNULL5:
195 + case cJU_JPNULL6:
196 + case cJU_JPNULL7:
197 +#endif
198 + assert((Pjp->jp_Addr) == 0);
199 + JU_JPSETADT(Pjp, 0, Index, JU_JPTYPE(Pjp) + cJU_JPIMMED_1_01 - cJU_JPNULL1);
200 +#ifdef JUDYL
201 + // value area is first word of new Immed_01 JP:
202 + Pjpm->jpm_PValue = (Pjv_t) (&(Pjp->jp_Addr));
203 +#endif
204 + return(1);
205 +
206 +
207 +// ****************************************************************************
208 +// JPBRANCH_L*:
209 +//
210 +// If the new Index is not an outlier to the branchs expanse, and the branch
211 +// should not be converted to uncompressed, extract the digit and record the
212 +// Immediate type to create for a new Immed JP, before going to common code.
213 +//
214 +// Note: JU_CHECK_IF_OUTLIER() is a no-op for BranchB3[7] on 32[64]-bit.
215 +
216 +#define JU_BRANCH_OUTLIER(DIGIT,POP1,cLEVEL,PJP,INDEX,PJPM) \
217 + JU_CHECK_IF_OUTLIER(PJP, INDEX, cLEVEL, PJPM); \
218 + (DIGIT) = JU_DIGITATSTATE(INDEX, cLEVEL); \
219 + (POP1) = JU_JPBRANCH_POP0(PJP, cLEVEL)
220 +
221 + case cJU_JPBRANCH_L2:
222 + JU_BRANCH_OUTLIER(digit, exppop1, 2, Pjp, Index, Pjpm);
223 + goto JudyBranchL;
224 +
225 + case cJU_JPBRANCH_L3:
226 + JU_BRANCH_OUTLIER(digit, exppop1, 3, Pjp, Index, Pjpm);
227 + goto JudyBranchL;
228 +
229 +#ifdef JU_64BIT
230 + case cJU_JPBRANCH_L4:
231 + JU_BRANCH_OUTLIER(digit, exppop1, 4, Pjp, Index, Pjpm);
232 + goto JudyBranchL;
233 +
234 + case cJU_JPBRANCH_L5:
235 + JU_BRANCH_OUTLIER(digit, exppop1, 5, Pjp, Index, Pjpm);
236 + goto JudyBranchL;
237 +
238 + case cJU_JPBRANCH_L6:
239 + JU_BRANCH_OUTLIER(digit, exppop1, 6, Pjp, Index, Pjpm);
240 + goto JudyBranchL;
241 +
242 + case cJU_JPBRANCH_L7:
243 + JU_BRANCH_OUTLIER(digit, exppop1, 7, Pjp, Index, Pjpm);
244 + goto JudyBranchL;
245 +#endif
246 +
247 +// Similar to common code above, but no outlier check is needed, and the Immed
248 +// type depends on the word size:
249 +
250 + case cJU_JPBRANCH_L:
251 + {
252 + Pjbl_t PjblRaw; // pointer to old linear branch.
253 + Pjbl_t Pjbl;
254 + Pjbu_t PjbuRaw; // pointer to new uncompressed branch.
255 + Pjbu_t Pjbu;
256 + Word_t numJPs; // number of JPs = populated expanses.
257 + int offset; // in branch.
258 +
259 + digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
260 + exppop1 = Pjpm->jpm_Pop0;
261 +
262 + // fall through:
263 +
264 +// COMMON CODE FOR LINEAR BRANCHES:
265 +//
266 +// Come here with digit and exppop1 already set.
267 +
268 +JudyBranchL:
269 + PjblRaw = (Pjbl_t) (Pjp->jp_Addr);
270 + Pjbl = P_JBL(PjblRaw);
271 +
272 +// If population under this branch greater than:
273 +
274 + if (exppop1 > JU_BRANCHL_MAX_POP)
275 + goto ConvertBranchLtoU;
276 +
277 + numJPs = Pjbl->jbl_NumJPs;
278 +
279 + if ((numJPs == 0) || (numJPs > cJU_BRANCHLMAXJPS))
280 + {
281 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
282 + return(-1);
283 + }
284 +
285 +// Search for a match to the digit:
286 +
287 + offset = j__udySearchLeaf1((Pjll_t) (Pjbl->jbl_Expanse), numJPs,
288 + digit);
289 +
290 +// If Index is found, offset is into an array of 1..cJU_BRANCHLMAXJPS JPs:
291 +
292 + if (offset >= 0)
293 + {
294 + Pjp = (Pjbl->jbl_jp) + offset; // address of next JP.
295 + break; // continue walk.
296 + }
297 +
298 +// Expanse is missing (not populated) for the passed Index, so insert an Immed
299 +// -- if theres room:
300 +
301 + if (numJPs < cJU_BRANCHLMAXJPS)
302 + {
303 + offset = ~offset; // insertion offset.
304 +
305 + JU_JPSETADT(&newJP, 0, Index,
306 + JU_JPTYPE(Pjp) + cJU_JPIMMED_1_01-cJU_JPBRANCH_L2);
307 +
308 + JU_INSERTINPLACE(Pjbl->jbl_Expanse, numJPs, offset, digit);
309 + JU_INSERTINPLACE(Pjbl->jbl_jp, numJPs, offset, newJP);
310 +
311 + DBGCODE(JudyCheckSorted((Pjll_t) (Pjbl->jbl_Expanse),
312 + numJPs + 1, /* IndexSize = */ 1);)
313 + ++(Pjbl->jbl_NumJPs);
314 +#ifdef JUDYL
315 + // value area is first word of new Immed 01 JP:
316 + Pjpm->jpm_PValue = (Pjv_t) ((Pjbl->jbl_jp) + offset);
317 +#endif
318 + return(1);
319 + }
320 +
321 +
322 +// MAXED OUT LINEAR BRANCH, CONVERT TO A BITMAP BRANCH, THEN INSERT:
323 +//
324 +// Copy the linear branch to a bitmap branch.
325 +//
326 +// TBD: Consider renaming j__udyCreateBranchB() to j__udyConvertBranchLtoB().
327 +
328 + assert((numJPs) <= cJU_BRANCHLMAXJPS);
329 +
330 + if (j__udyCreateBranchB(Pjp, Pjbl->jbl_jp, Pjbl->jbl_Expanse,
331 + numJPs, Pjpm) == -1)
332 + {
333 + return(-1);
334 + }
335 +
336 +// Convert jp_Type from linear branch to equivalent bitmap branch:
337 +
338 + Pjp->jp_Type += cJU_JPBRANCH_B - cJU_JPBRANCH_L;
339 +
340 + j__udyFreeJBL(PjblRaw, Pjpm); // free old BranchL.
341 +
342 +// Having changed branch types, now do the insert in the new branch type:
343 +
344 + goto ContinueInsWalk;
345 +
346 +
347 +// OPPORTUNISTICALLY CONVERT FROM BRANCHL TO BRANCHU:
348 +//
349 +// Memory efficiency is no object because the branchs pop1 is large enough, so
350 +// speed up array access. Come here with PjblRaw set. Note: This is goto
351 +// code because the previous block used to fall through into it as well, but no
352 +// longer.
353 +
354 +ConvertBranchLtoU:
355 +
356 +// Allocate memory for an uncompressed branch:
357 +
358 + if ((PjbuRaw = j__udyAllocJBU(Pjpm)) == (Pjbu_t) NULL)
359 + return(-1);
360 + Pjbu = P_JBU(PjbuRaw);
361 +
362 +// Set the proper NULL type for most of the uncompressed branchs JPs:
363 +
364 + JU_JPSETADT(&newJP, 0, 0,
365 + JU_JPTYPE(Pjp) - cJU_JPBRANCH_L2 + cJU_JPNULL1);
366 +
367 +// Initialize: Pre-set uncompressed branch to mostly JPNULL*s:
368 +
369 + for (numJPs = 0; numJPs < cJU_BRANCHUNUMJPS; ++numJPs)
370 + Pjbu->jbu_jp[numJPs] = newJP;
371 +
372 +// Copy JPs from linear branch to uncompressed branch:
373 +
374 + {
375 +#ifdef SUBEXPCOUNTS
376 + Word_t popmask = cJU_POP0MASK(JU_JPTYPE(Pjp))
377 + - cJU_JPBRANCH_L2 - 2;
378 +
379 + for (numJPs = 0; numJPs < cJU_NUMSUBEXPU; ++numJPs)
380 + Pjbu->jbu_subPop1[numJPs] = 0;
381 +#endif
382 + for (numJPs = 0; numJPs < Pjbl->jbl_NumJPs; ++numJPs)
383 + {
384 + Pjp_t Pjp1 = &(Pjbl->jbl_jp[numJPs]);
385 + offset = Pjbl->jbl_Expanse[numJPs];
386 + Pjbu->jbu_jp[offset] = *Pjp1;
387 +#ifdef SUBEXPCOUNTS
388 + Pjbu->jbu_subPop1[offset/cJU_NUMSUBEXPU] +=
389 + JU_JPDCDPOP0(Pjp1) & popmask + 1;
390 +#endif
391 + }
392 + }
393 + j__udyFreeJBL(PjblRaw, Pjpm); // free old BranchL.
394 +
395 +// Plug new values into parent JP:
396 +
397 + Pjp->jp_Addr = (Word_t) PjbuRaw;
398 + Pjp->jp_Type += cJU_JPBRANCH_U - cJU_JPBRANCH_L; // to BranchU.
399 +
400 +// Save global population of last BranchU conversion:
401 +
402 + Pjpm->jpm_LastUPop0 = Pjpm->jpm_Pop0;
403 + goto ContinueInsWalk;
404 +
405 + } // case cJU_JPBRANCH_L.
406 +
407 +
408 +// ****************************************************************************
409 +// JPBRANCH_B*:
410 +//
411 +// If the new Index is not an outlier to the branchs expanse, extract the
412 +// digit and record the Immediate type to create for a new Immed JP, before
413 +// going to common code.
414 +//
415 +// Note: JU_CHECK_IF_OUTLIER() is a no-op for BranchB3[7] on 32[64]-bit.
416 +
417 + case cJU_JPBRANCH_B2:
418 + JU_BRANCH_OUTLIER(digit, exppop1, 2, Pjp, Index, Pjpm);
419 + goto JudyBranchB;
420 +
421 + case cJU_JPBRANCH_B3:
422 + JU_BRANCH_OUTLIER(digit, exppop1, 3, Pjp, Index, Pjpm);
423 + goto JudyBranchB;
424 +
425 +#ifdef JU_64BIT
426 + case cJU_JPBRANCH_B4:
427 + JU_BRANCH_OUTLIER(digit, exppop1, 4, Pjp, Index, Pjpm);
428 + goto JudyBranchB;
429 +
430 + case cJU_JPBRANCH_B5:
431 + JU_BRANCH_OUTLIER(digit, exppop1, 5, Pjp, Index, Pjpm);
432 + goto JudyBranchB;
433 +
434 + case cJU_JPBRANCH_B6:
435 + JU_BRANCH_OUTLIER(digit, exppop1, 6, Pjp, Index, Pjpm);
436 + goto JudyBranchB;
437 +
438 + case cJU_JPBRANCH_B7:
439 + JU_BRANCH_OUTLIER(digit, exppop1, 7, Pjp, Index, Pjpm);
440 + goto JudyBranchB;
441 +#endif
442 +
443 + case cJU_JPBRANCH_B:
444 + {
445 + Pjbb_t Pjbb; // pointer to bitmap branch.
446 + Pjbb_t PjbbRaw; // pointer to bitmap branch.
447 + Pjp_t Pjp2Raw; // 1 of N arrays of JPs.
448 + Pjp_t Pjp2; // 1 of N arrays of JPs.
449 + Word_t subexp; // 1 of N subexpanses in bitmap.
450 + BITMAPB_t bitmap; // for one subexpanse.
451 + BITMAPB_t bitmask; // bit set for Indexs digit.
452 + Word_t numJPs; // number of JPs = populated expanses.
453 + int offset; // in bitmap branch.
454 +
455 +// Similar to common code above, but no outlier check is needed, and the Immed
456 +// type depends on the word size:
457 +
458 + digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
459 + exppop1 = Pjpm->jpm_Pop0;
460 +
461 + // fall through:
462 +
463 +
464 +// COMMON CODE FOR BITMAP BRANCHES:
465 +//
466 +// Come here with digit and exppop1 already set.
467 +
468 +JudyBranchB:
469 +
470 +// If population increment is greater than.. (300):
471 +
472 + if ((Pjpm->jpm_Pop0 - Pjpm->jpm_LastUPop0) > JU_BTOU_POP_INCREMENT)
473 + {
474 +
475 +// If total population of array is greater than.. (750):
476 +
477 + if (Pjpm->jpm_Pop0 > JU_BRANCHB_MAX_POP)
478 + {
479 +
480 +// If population under the branch is greater than.. (135):
481 +
482 + if (exppop1 > JU_BRANCHB_MIN_POP)
483 + {
484 + if (j__udyCreateBranchU(Pjp, Pjpm) == -1) return(-1);
485 +
486 +// Save global population of last BranchU conversion:
487 +
488 + Pjpm->jpm_LastUPop0 = Pjpm->jpm_Pop0;
489 +
490 + goto ContinueInsWalk;
491 + }
492 + }
493 + }
494 +
495 +// CONTINUE TO USE BRANCHB:
496 +//
497 +// Get pointer to bitmap branch (JBB):
498 +
499 + PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
500 + Pjbb = P_JBB(PjbbRaw);
501 +
502 +// Form the Int32 offset, and Bit offset values:
503 +//
504 +// 8 bit Decode | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
505 +// |SubExpanse | Bit offset |
506 +//
507 +// Get the 1 of 8 expanses from digit, Bits 5..7 = 1 of 8, and get the 32-bit
508 +// word that may have a bit set:
509 +
510 + subexp = digit / cJU_BITSPERSUBEXPB;
511 + bitmap = JU_JBB_BITMAP(Pjbb, subexp);
512 +
513 + Pjp2Raw = JU_JBB_PJP(Pjbb, subexp);
514 + Pjp2 = P_JP(Pjp2Raw);
515 +
516 +// Get the bit position that represents the desired expanse, and get the offset
517 +// into the array of JPs for the JP that matches the bit.
518 +
519 + bitmask = JU_BITPOSMASKB(digit);
520 + offset = j__udyCountBitsB(bitmap & (bitmask - 1));
521 +
522 +// If JP is already in this expanse, get Pjp and continue the walk:
523 +
524 + if (bitmap & bitmask)
525 + {
526 +#ifdef SUBEXPCOUNTS
527 + PSubExp = &(Pjbb->jbb_Counts[subexp]); // ptr to subexp counts.
528 +#endif
529 + Pjp = Pjp2 + offset;
530 + break; // continue walk.
531 + }
532 +
533 +
534 +// ADD NEW EXPANSE FOR NEW INDEX:
535 +//
536 +// The new expanse always an cJU_JPIMMED_*_01 containing just the new Index, so
537 +// finish setting up an Immed JP.
538 +
539 + JU_JPSETADT(&newJP, 0, Index,
540 + JU_JPTYPE(Pjp) + cJU_JPIMMED_1_01-cJU_JPBRANCH_B2);
541 +
542 +// Get 1 of the 8 JP arrays and calculate number of JPs in subexpanse array:
543 +
544 + Pjp2Raw = JU_JBB_PJP(Pjbb, subexp);
545 + Pjp2 = P_JP(Pjp2Raw);
546 + numJPs = j__udyCountBitsB(bitmap);
547 +
548 +// Expand branch JP subarray in-place:
549 +
550 + if (JU_BRANCHBJPGROWINPLACE(numJPs))
551 + {
552 + assert(numJPs > 0);
553 + JU_INSERTINPLACE(Pjp2, numJPs, offset, newJP);
554 +#ifdef JUDYL
555 + // value area is first word of new Immed 01 JP:
556 + Pjpm->jpm_PValue = (Pjv_t) (Pjp2 + offset);
557 +#endif
558 + }
559 +
560 +// No room, allocate a bigger bitmap branch JP subarray:
561 +
562 + else
563 + {
564 + Pjp_t PjpnewRaw;
565 + Pjp_t Pjpnew;
566 +
567 + if ((PjpnewRaw = j__udyAllocJBBJP(numJPs + 1, Pjpm)) == 0)
568 + return(-1);
569 + Pjpnew = P_JP(PjpnewRaw);
570 +
571 +// If there was an old JP array, then copy it, insert the new Immed JP, and
572 +// free the old array:
573 +
574 + if (numJPs)
575 + {
576 + JU_INSERTCOPY(Pjpnew, Pjp2, numJPs, offset, newJP);
577 + j__udyFreeJBBJP(Pjp2Raw, numJPs, Pjpm);
578 +#ifdef JUDYL
579 + // value area is first word of new Immed 01 JP:
580 + Pjpm->jpm_PValue = (Pjv_t) (Pjpnew + offset);
581 +#endif
582 + }
583 +
584 +// New JP subarray; point to cJU_JPIMMED_*_01 and place it:
585 +
586 + else
587 + {
588 + assert(JU_JBB_PJP(Pjbb, subexp) == (Pjp_t) NULL);
589 + Pjp = Pjpnew;
590 + *Pjp = newJP; // copy to new memory.
591 +#ifdef JUDYL
592 + // value area is first word of new Immed 01 JP:
593 + Pjpm->jpm_PValue = (Pjv_t) (&(Pjp->jp_Addr));
594 +#endif
595 + }
596 +
597 +// Place new JP subarray in BranchB:
598 +
599 + JU_JBB_PJP(Pjbb, subexp) = PjpnewRaw;
600 +
601 + } // else
602 +
603 +// Set the new Indexs bit:
604 +
605 + JU_JBB_BITMAP(Pjbb, subexp) |= bitmask;
606 +
607 + return(1);
608 +
609 + } // case
610 +
611 +
612 +// ****************************************************************************
613 +// JPBRANCH_U*:
614 +//
615 +// Just drop through the JP for the correct digit. If the JP turns out to be a
616 +// JPNULL*, thats OK, the memory is already allocated, and the next walk
617 +// simply places an Immed in it.
618 +//
619 +#ifdef SUBEXPCOUNTS
620 +#define JU_GETSUBEXP(PSubExp,Pjbu,Digit) \
621 + (PSubExp) = &((Pjbu)->jbu_subPop1[(Digit) / cJU_NUMSUBEXPU])
622 +#else
623 +#define JU_GETSUBEXP(PSubExp,Pjbu,Digit) // null.
624 +#endif
625 +
626 +#define JU_JBU_PJP_SUBEXP(Pjp,PSubExp,Index,Level) \
627 + { \
628 + uint8_t digit = JU_DIGITATSTATE(Index, Level); \
629 + Pjbu_t P_jbu = P_JBU((Pjp)->jp_Addr); \
630 + (Pjp) = &(P_jbu->jbu_jp[digit]); \
631 + JU_GETSUBEXP(PSubExp, P_jbu, digit); \
632 + }
633 +
634 + case cJU_JPBRANCH_U2:
635 + JU_CHECK_IF_OUTLIER(Pjp, Index, 2, Pjpm);
636 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 2);
637 + break;
638 +
639 +#ifdef JU_64BIT
640 + case cJU_JPBRANCH_U3:
641 + JU_CHECK_IF_OUTLIER(Pjp, Index, 3, Pjpm);
642 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 3);
643 + break;
644 +
645 + case cJU_JPBRANCH_U4:
646 + JU_CHECK_IF_OUTLIER(Pjp, Index, 4, Pjpm);
647 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 4);
648 + break;
649 +
650 + case cJU_JPBRANCH_U5:
651 + JU_CHECK_IF_OUTLIER(Pjp, Index, 5, Pjpm);
652 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 5);
653 + break;
654 +
655 + case cJU_JPBRANCH_U6:
656 + JU_CHECK_IF_OUTLIER(Pjp, Index, 6, Pjpm);
657 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 6);
658 + break;
659 +
660 + case cJU_JPBRANCH_U7:
661 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 7);
662 +#else
663 + case cJU_JPBRANCH_U3:
664 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, 3);
665 +#endif
666 + break;
667 +
668 + case cJU_JPBRANCH_U:
669 + JU_JBU_PJP_SUBEXP(Pjp, PSubExp, Index, cJU_ROOTSTATE);
670 + break;
671 +
672 +
673 +// ****************************************************************************
674 +// JPLEAF*:
675 +//
676 +// COMMON CODE FRAGMENTS TO MINIMIZE REDUNDANCY BELOW:
677 +//
678 +// These are necessary to support performance by function and loop unrolling
679 +// while avoiding huge amounts of nearly identical code.
680 +//
681 +// Prepare to handle a linear leaf: Check for an outlier; set pop1 and pointer
682 +// to leaf:
683 +
684 +#ifdef JUDY1
685 +#define JU_LEAFVALUE(Pjv) // null.
686 +#define JU_LEAFPREPVALUE(Pjv, ValueArea) // null.
687 +#else
688 +#define JU_LEAFVALUE(Pjv) Pjv_t Pjv
689 +#define JU_LEAFPREPVALUE(Pjv, ValueArea) (Pjv) = ValueArea(Pleaf, exppop1)
690 +#endif
691 +
692 +#define JU_LEAFPREP(cIS,Type,MaxPop1,ValueArea) \
693 + Pjll_t PjllRaw; \
694 + Type Pleaf; /* specific type */ \
695 + int offset; \
696 + JU_LEAFVALUE(Pjv); \
697 + \
698 + JU_CHECK_IF_OUTLIER(Pjp, Index, cIS, Pjpm); \
699 + \
700 + exppop1 = JU_JPLEAF_POP0(Pjp) + 1; \
701 + assert(exppop1 <= (MaxPop1)); \
702 + PjllRaw = (Pjll_t) (Pjp->jp_Addr); \
703 + Pleaf = (Type) P_JLL(PjllRaw); \
704 + JU_LEAFPREPVALUE(Pjv, ValueArea)
705 +
706 +// Add to, or grow, a linear leaf: Find Index position; if the Index is
707 +// absent, if theres room in the leaf, insert the Index [and value of 0] in
708 +// place, otherwise grow the leaf:
709 +//
710 +// Note: These insertions always take place with whole words, using
711 +// JU_INSERTINPLACE() or JU_INSERTCOPY().
712 +
713 +#ifdef JUDY1
714 +#define JU_LEAFGROWVALUEADD(Pjv,ExpPop1,Offset) // null.
715 +#else
716 +#define JU_LEAFGROWVALUEADD(Pjv,ExpPop1,Offset) \
717 + JU_INSERTINPLACE(Pjv, ExpPop1, Offset, 0); \
718 + Pjpm->jpm_PValue = (Pjv) + (Offset)
719 +#endif
720 +
721 +#ifdef JUDY1
722 +#define JU_LEAFGROWVALUENEW(ValueArea,Pjv,ExpPop1,Offset) // null.
723 +#else
724 +#define JU_LEAFGROWVALUENEW(ValueArea,Pjv,ExpPop1,Offset) \
725 + { \
726 + Pjv_t Pjvnew = ValueArea(Pleafnew, (ExpPop1) + 1); \
727 + JU_INSERTCOPY(Pjvnew, Pjv, ExpPop1, Offset, 0); \
728 + Pjpm->jpm_PValue = (Pjvnew) + (Offset); \
729 + }
730 +#endif
731 +
732 +#define JU_LEAFGROW(cIS,Type,MaxPop1,Search,ValueArea,GrowInPlace, \
733 + InsertInPlace,InsertCopy,Alloc,Free) \
734 + \
735 + offset = Search(Pleaf, exppop1, Index); \
736 + JU_CHECK_IF_EXISTS(offset, Pjv, Pjpm); \
737 + \
738 + if (GrowInPlace(exppop1)) /* add to current leaf */ \
739 + { \
740 + InsertInPlace(Pleaf, exppop1, offset, Index); \
741 + JU_LEAFGROWVALUEADD(Pjv, exppop1, offset); \
742 + DBGCODE(JudyCheckSorted((Pjll_t) Pleaf, exppop1 + 1, cIS);) \
743 + return(1); \
744 + } \
745 + \
746 + if (exppop1 < (MaxPop1)) /* grow to new leaf */ \
747 + { \
748 + Pjll_t PjllnewRaw; \
749 + Type Pleafnew; \
750 + if ((PjllnewRaw = Alloc(exppop1 + 1, Pjpm)) == 0) return(-1); \
751 + Pleafnew = (Type) P_JLL(PjllnewRaw); \
752 + InsertCopy(Pleafnew, Pleaf, exppop1, offset, Index); \
753 + JU_LEAFGROWVALUENEW(ValueArea, Pjv, exppop1, offset); \
754 + DBGCODE(JudyCheckSorted((Pjll_t) Pleafnew, exppop1 + 1, cIS);) \
755 + Free(PjllRaw, exppop1, Pjpm); \
756 + (Pjp->jp_Addr) = (Word_t) PjllnewRaw; \
757 + return(1); \
758 + } \
759 + assert(exppop1 == (MaxPop1))
760 +
761 +// Handle linear leaf overflow (cascade): Splay or compress into smaller
762 +// leaves:
763 +
764 +#define JU_LEAFCASCADE(MaxPop1,Cascade,Free) \
765 + if (Cascade(Pjp, Pjpm) == -1) return(-1); \
766 + Free(PjllRaw, MaxPop1, Pjpm); \
767 + goto ContinueInsWalk
768 +
769 +// Wrapper around all of the above:
770 +
771 +#define JU_LEAFSET(cIS,Type,MaxPop1,Search,GrowInPlace,InsertInPlace, \
772 + InsertCopy,Cascade,Alloc,Free,ValueArea) \
773 + { \
774 + JU_LEAFPREP(cIS,Type,MaxPop1,ValueArea); \
775 + JU_LEAFGROW(cIS,Type,MaxPop1,Search,ValueArea,GrowInPlace, \
776 + InsertInPlace,InsertCopy,Alloc,Free); \
777 + JU_LEAFCASCADE(MaxPop1,Cascade,Free); \
778 + }
779 +
780 +// END OF MACROS; LEAFL CASES START HERE:
781 +//
782 +// 64-bit Judy1 does not have 1-byte leaves:
783 +
784 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
785 +
786 + case cJU_JPLEAF1:
787 +
788 + JU_LEAFSET(1, uint8_t *, cJU_LEAF1_MAXPOP1, j__udySearchLeaf1,
789 + JU_LEAF1GROWINPLACE, JU_INSERTINPLACE, JU_INSERTCOPY,
790 + j__udyCascade1, j__udyAllocJLL1, j__udyFreeJLL1,
791 + JL_LEAF1VALUEAREA);
792 +
793 +#endif // (JUDYL || ! JU_64BIT)
794 +
795 + case cJU_JPLEAF2:
796 +
797 + JU_LEAFSET(2, uint16_t *, cJU_LEAF2_MAXPOP1, j__udySearchLeaf2,
798 + JU_LEAF2GROWINPLACE, JU_INSERTINPLACE, JU_INSERTCOPY,
799 + j__udyCascade2, j__udyAllocJLL2, j__udyFreeJLL2,
800 + JL_LEAF2VALUEAREA);
801 +
802 + case cJU_JPLEAF3:
803 +
804 + JU_LEAFSET(3, uint8_t *, cJU_LEAF3_MAXPOP1, j__udySearchLeaf3,
805 + JU_LEAF3GROWINPLACE, JU_INSERTINPLACE3, JU_INSERTCOPY3,
806 + j__udyCascade3, j__udyAllocJLL3, j__udyFreeJLL3,
807 + JL_LEAF3VALUEAREA);
808 +
809 +#ifdef JU_64BIT
810 + case cJU_JPLEAF4:
811 +
812 + JU_LEAFSET(4, uint32_t *, cJU_LEAF4_MAXPOP1, j__udySearchLeaf4,
813 + JU_LEAF4GROWINPLACE, JU_INSERTINPLACE, JU_INSERTCOPY,
814 + j__udyCascade4, j__udyAllocJLL4, j__udyFreeJLL4,
815 + JL_LEAF4VALUEAREA);
816 +
817 + case cJU_JPLEAF5:
818 +
819 + JU_LEAFSET(5, uint8_t *, cJU_LEAF5_MAXPOP1, j__udySearchLeaf5,
820 + JU_LEAF5GROWINPLACE, JU_INSERTINPLACE5, JU_INSERTCOPY5,
821 + j__udyCascade5, j__udyAllocJLL5, j__udyFreeJLL5,
822 + JL_LEAF5VALUEAREA);
823 +
824 + case cJU_JPLEAF6:
825 +
826 + JU_LEAFSET(6, uint8_t *, cJU_LEAF6_MAXPOP1, j__udySearchLeaf6,
827 + JU_LEAF6GROWINPLACE, JU_INSERTINPLACE6, JU_INSERTCOPY6,
828 + j__udyCascade6, j__udyAllocJLL6, j__udyFreeJLL6,
829 + JL_LEAF6VALUEAREA);
830 +
831 + case cJU_JPLEAF7:
832 +
833 + JU_LEAFSET(7, uint8_t *, cJU_LEAF7_MAXPOP1, j__udySearchLeaf7,
834 + JU_LEAF7GROWINPLACE, JU_INSERTINPLACE7, JU_INSERTCOPY7,
835 + j__udyCascade7, j__udyAllocJLL7, j__udyFreeJLL7,
836 + JL_LEAF7VALUEAREA);
837 +#endif // JU_64BIT
838 +
839 +
840 +// ****************************************************************************
841 +// JPLEAF_B1:
842 +//
843 +// 8 bit Decode | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
844 +// |SubExpanse | Bit offset |
845 +//
846 +// Note: For JudyL, values are stored in 8 subexpanses, each a linear word
847 +// array of up to 32 values each.
848 +
849 + case cJU_JPLEAF_B1:
850 + {
851 +#ifdef JUDYL
852 + Pjv_t PjvRaw; // pointer to value part of the leaf.
853 + Pjv_t Pjv; // pointer to value part of the leaf.
854 + Pjv_t PjvnewRaw; // new value area.
855 + Pjv_t Pjvnew; // new value area.
856 + Word_t subexp; // 1 of 8 subexpanses in bitmap.
857 + Pjlb_t Pjlb; // pointer to bitmap part of the leaf.
858 + BITMAPL_t bitmap; // for one subexpanse.
859 + BITMAPL_t bitmask; // bit set for Indexs digit.
860 + int offset; // of index in value area.
861 +#endif
862 +
863 + JU_CHECK_IF_OUTLIER(Pjp, Index, 1, Pjpm);
864 +
865 +#ifdef JUDY1
866 +
867 +// If Index (bit) is already set, return now:
868 +
869 + if (JU_BITMAPTESTL(P_JLB(Pjp->jp_Addr), Index)) return(0);
870 +
871 +// If bitmap is not full, set the new Indexs bit; otherwise convert to a Full:
872 +
873 + if ((exppop1 = JU_JPLEAF_POP0(Pjp) + 1)
874 + < cJU_JPFULLPOPU1_POP0)
875 + {
876 + JU_BITMAPSETL(P_JLB(Pjp->jp_Addr), Index);
877 + }
878 + else
879 + {
880 + j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm); // free LeafB1.
881 + Pjp->jp_Type = cJ1_JPFULLPOPU1;
882 + Pjp->jp_Addr = 0;
883 + }
884 +
885 +#else // JUDYL
886 +
887 +// This is very different from Judy1 because of the need to return a value area
888 +// even for an existing Index, or manage the value area for a new Index, and
889 +// because JudyL has no Full type:
890 +
891 +// Get last byte to decode from Index, and pointer to bitmap leaf:
892 +
893 + digit = JU_DIGITATSTATE(Index, 1);
894 + Pjlb = P_JLB(Pjp->jp_Addr);
895 +
896 +// Prepare additional values:
897 +
898 + subexp = digit / cJU_BITSPERSUBEXPL; // which subexpanse.
899 + bitmap = JU_JLB_BITMAP(Pjlb, subexp); // subexps 32-bit map.
900 + PjvRaw = JL_JLB_PVALUE(Pjlb, subexp); // corresponding values.
901 + Pjv = P_JV(PjvRaw); // corresponding values.
902 + bitmask = JU_BITPOSMASKL(digit); // mask for Index.
903 + offset = j__udyCountBitsL(bitmap & (bitmask - 1)); // of Index.
904 +
905 +// If Index already exists, get value pointer and exit:
906 +
907 + if (bitmap & bitmask)
908 + {
909 + assert(Pjv);
910 + Pjpm->jpm_PValue = Pjv + offset; // existing value.
911 + return(0);
912 + }
913 +
914 +// Get the total bits set = expanse population of Value area:
915 +
916 + exppop1 = j__udyCountBitsL(bitmap);
917 +
918 +// If the value area can grow in place, do it:
919 +
920 + if (JL_LEAFVGROWINPLACE(exppop1))
921 + {
922 + JU_INSERTINPLACE(Pjv, exppop1, offset, 0);
923 + JU_JLB_BITMAP(Pjlb, subexp) |= bitmask; // set Indexs bit.
924 + Pjpm->jpm_PValue = Pjv + offset; // new value area.
925 + return(1);
926 + }
927 +
928 +// Increase size of value area:
929 +
930 + if ((PjvnewRaw = j__udyLAllocJV(exppop1 + 1, Pjpm))
931 + == (Pjv_t) NULL) return(-1);
932 + Pjvnew = P_JV(PjvnewRaw);
933 +
934 + if (exppop1) // have existing value area.
935 + {
936 + assert(Pjv);
937 + JU_INSERTCOPY(Pjvnew, Pjv, exppop1, offset, 0);
938 + Pjpm->jpm_PValue = Pjvnew + offset;
939 + j__udyLFreeJV(PjvRaw, exppop1, Pjpm); // free old values.
940 + }
941 + else // first index, new value area:
942 + {
943 + Pjpm->jpm_PValue = Pjvnew;
944 + *(Pjpm->jpm_PValue) = 0;
945 + }
946 +
947 +// Set bit for new Index and place new leaf value area in bitmap:
948 +
949 + JU_JLB_BITMAP(Pjlb, subexp) |= bitmask;
950 + JL_JLB_PVALUE(Pjlb, subexp) = PjvnewRaw;
951 +
952 +#endif // JUDYL
953 +
954 + return(1);
955 +
956 + } // case
957 +
958 +
959 +#ifdef JUDY1
960 +// ****************************************************************************
961 +// JPFULLPOPU1:
962 +//
963 +// If Index is not an outlier, then by definition its already set.
964 +
965 + case cJ1_JPFULLPOPU1:
966 +
967 + JU_CHECK_IF_OUTLIER(Pjp, Index, 1, Pjpm);
968 + return(0);
969 +#endif
970 +
971 +
972 +// ****************************************************************************
973 +// JPIMMED*:
974 +//
975 +// This is some of the most complex code in Judy considering Judy1 versus JudyL
976 +// and 32-bit versus 64-bit variations. The following comments attempt to make
977 +// this clearer.
978 +//
979 +// Of the 2 words in a JP, for immediate indexes Judy1 can use 2 words - 1 byte
980 +// = 7 [15] bytes, but JudyL can only use 1 word - 1 byte = 3 [7] bytes because
981 +// the other word is needed for a value area or a pointer to a value area.
982 +//
983 +// For both Judy1 and JudyL, cJU_JPIMMED_*_01 indexes are in word 2; otherwise
984 +// for Judy1 only, a list of 2 or more indexes starts in word 1. JudyL keeps
985 +// the list in word 2 because word 1 is a pointer (to a LeafV, that is, a leaf
986 +// containing only values). Furthermore, cJU_JPIMMED_*_01 indexes are stored
987 +// all-but-first-byte in jp_DcdPopO, not just the Index Sizes bytes.
988 +//
989 +// TBD: This can be confusing because Doug didnt use data structures for it.
990 +// Instead he often directly accesses Pjp for the first word and jp_DcdPopO for
991 +// the second word. It would be nice to use data structs, starting with
992 +// jp_1Index and jp_LIndex where possible.
993 +//
994 +// Maximum Immed JP types for Judy1/JudyL, depending on Index Size (cIS):
995 +//
996 +// 32-bit 64-bit
997 +//
998 +// bytes: 7/ 3 15/ 7 (Judy1/JudyL)
999 +//
1000 +// cIS
1001 +// 1_ 07/03 15/07 (as in: cJ1_JPIMMED_1_07)
1002 +// 2_ 03/01 07/03
1003 +// 3_ 02/01 05/02
1004 +// 4_ 03/01
1005 +// 5_ 03/01
1006 +// 6_ 02/01
1007 +// 7_ 02/01
1008 +//
1009 +// State transitions while inserting an Index, matching the above table:
1010 +// (Yes, this is very terse... Study it and it will make sense.)
1011 +// (Note, parts of this diagram are repeated below for quick reference.)
1012 +//
1013 +// +-- reformat JP here for Judy1 only, from word-2 to word-1
1014 +// |
1015 +// | JUDY1 || JU_64BIT JUDY1 && JU_64BIT
1016 +// V
1017 +// 1_01 => 1_02 => 1_03 => [ 1_04 => ... => 1_07 => [ 1_08..15 => ]] Leaf1 (*)
1018 +// 2_01 => [ 2_02 => 2_03 => [ 2_04..07 => ]] Leaf2
1019 +// 3_01 => [ 3_02 => [ 3_03..05 => ]] Leaf3
1020 +// JU_64BIT only:
1021 +// 4_01 => [[ 4_02..03 => ]] Leaf4
1022 +// 5_01 => [[ 5_02..03 => ]] Leaf5
1023 +// 6_01 => [[ 6_02 => ]] Leaf6
1024 +// 7_01 => [[ 7_02 => ]] Leaf7
1025 +//
1026 +// (*) For Judy1 & 64-bit, go directly from cJU_JPIMMED_1_15 to a LeafB1; skip
1027 +// Leaf1, as described in Judy1.h regarding cJ1_JPLEAF1.
1028 +
1029 +
1030 +// COMMON CODE FRAGMENTS TO MINIMIZE REDUNDANCY BELOW:
1031 +//
1032 +// These are necessary to support performance by function and loop unrolling
1033 +// while avoiding huge amounts of nearly identical code.
1034 +//
1035 +// The differences between Judy1 and JudyL with respect to value area handling
1036 +// are just too large for completely common code between them... Oh well, some
1037 +// big ifdefs follow. However, even in the following ifdefd code, use cJU_*,
1038 +// JU_*, and Judy*() instead of cJ1_* / cJL_*, J1_* / JL_*, and
1039 +// Judy1*()/JudyL*(), for minimum diffs.
1040 +//
1041 +// Handle growth of cJU_JPIMMED_*_01 to cJU_JPIMMED_*_02, for an even or odd
1042 +// Index Size (cIS), given oldIndex, Index, and Pjll in the context:
1043 +//
1044 +// Put oldIndex and Index in their proper order. For odd indexes, must copy
1045 +// bytes.
1046 +
1047 +#ifdef JUDY1
1048 +
1049 +#define JU_IMMSET_01_COPY_EVEN(ignore1,ignore2) \
1050 + if (oldIndex < Index) { Pjll[0] = oldIndex; Pjll[1] = Index; } \
1051 + else { Pjll[0] = Index; Pjll[1] = oldIndex; }
1052 +
1053 +#define JU_IMMSET_01_COPY_ODD(cIS,CopyWord) \
1054 + if (oldIndex < Index) \
1055 + { \
1056 + CopyWord(Pjll + 0, oldIndex); \
1057 + CopyWord(Pjll + (cIS), Index); \
1058 + } \
1059 + else \
1060 + { \
1061 + CopyWord(Pjll + 0, Index); \
1062 + CopyWord(Pjll + (cIS), oldIndex); \
1063 + }
1064 +
1065 +// The "real" *_01 Copy macro:
1066 +//
1067 +// Trim the high byte off Index, look for a match with the old Index, and if
1068 +// none, insert the new Index in the leaf in the correct place, given Pjp and
1069 +// Index in the context.
1070 +//
1071 +// Note: A single immediate index lives in the jp_DcdPopO field, but two or
1072 +// more reside starting at Pjp->jp_1Index.
1073 +
1074 +#define JU_IMMSET_01_COPY(cIS,LeafType,NewJPType,Copy,CopyWord) \
1075 + { \
1076 + LeafType Pjll; \
1077 + Word_t oldIndex = JU_JPDCDPOP0(Pjp); \
1078 + \
1079 + Index = JU_TRIMTODCDSIZE(Index); \
1080 + if (oldIndex == Index) return(0); \
1081 + \
1082 + Pjll = (LeafType) (Pjp->jp_1Index); \
1083 + Copy(cIS,CopyWord); \
1084 + DBGCODE(JudyCheckSorted(Pjll, 2, cIS);) \
1085 + \
1086 + Pjp->jp_Type = (NewJPType); \
1087 + return(1); \
1088 + }
1089 +
1090 +#else // JUDYL
1091 +
1092 +// Variations to also handle value areas; see comments above:
1093 +//
1094 +// For JudyL, Pjv (start of value area) and oldValue are also in the context;
1095 +// leave Pjv set to the value area for Index.
1096 +
1097 +#define JU_IMMSET_01_COPY_EVEN(cIS,CopyWord) \
1098 + if (oldIndex < Index) \
1099 + { \
1100 + Pjll[0] = oldIndex; \
1101 + Pjv [0] = oldValue; \
1102 + Pjll[1] = Index; \
1103 + ++Pjv; \
1104 + } \
1105 + else \
1106 + { \
1107 + Pjll[0] = Index; \
1108 + Pjll[1] = oldIndex; \
1109 + Pjv [1] = oldValue; \
1110 + }
1111 +
1112 +#define JU_IMMSET_01_COPY_ODD(cIS,CopyWord) \
1113 + if (oldIndex < Index) \
1114 + { \
1115 + CopyWord(Pjll + 0, oldIndex); \
1116 + CopyWord(Pjll + (cIS), Index); \
1117 + Pjv[0] = oldValue; \
1118 + ++Pjv; \
1119 + } \
1120 + else \
1121 + { \
1122 + CopyWord(Pjll + 0, Index); \
1123 + CopyWord(Pjll + (cIS), oldIndex); \
1124 + Pjv[1] = oldValue; \
1125 + }
1126 +
1127 +// The old value area is in the first word (*Pjp), and Pjv and Pjpm are also in
1128 +// the context. Also, unlike Judy1, indexes remain in word 2 (jp_LIndex),
1129 +// meaning insert-in-place rather than copy.
1130 +//
1131 +// Return jpm_PValue pointing to Indexs value area. If Index is new, allocate
1132 +// a 2-value-leaf and attach it to the JP.
1133 +
1134 +#define JU_IMMSET_01_COPY(cIS,LeafType,NewJPType,Copy,CopyWord) \
1135 + { \
1136 + LeafType Pjll; \
1137 + Word_t oldIndex = JU_JPDCDPOP0(Pjp); \
1138 + Word_t oldValue; \
1139 + Pjv_t PjvRaw; \
1140 + Pjv_t Pjv; \
1141 + \
1142 + Index = JU_TRIMTODCDSIZE(Index); \
1143 + \
1144 + if (oldIndex == Index) \
1145 + { \
1146 + Pjpm->jpm_PValue = (Pjv_t) Pjp; \
1147 + return(0); \
1148 + } \
1149 + \
1150 + if ((PjvRaw = j__udyLAllocJV(2, Pjpm)) == (Pjv_t) NULL) \
1151 + return(-1); \
1152 + Pjv = P_JV(PjvRaw); \
1153 + \
1154 + oldValue = Pjp->jp_Addr; \
1155 + (Pjp->jp_Addr) = (Word_t) PjvRaw; \
1156 + Pjll = (LeafType) (Pjp->jp_LIndex); \
1157 + \
1158 + Copy(cIS,CopyWord); \
1159 + DBGCODE(JudyCheckSorted(Pjll, 2, cIS);) \
1160 + \
1161 + Pjp->jp_Type = (NewJPType); \
1162 + *Pjv = 0; \
1163 + Pjpm->jpm_PValue = Pjv; \
1164 + return(1); \
1165 + }
1166 +
1167 +// The following is a unique mix of JU_IMMSET_01() and JU_IMMSETCASCADE() for
1168 +// going from cJU_JPIMMED_*_01 directly to a cJU_JPLEAF* for JudyL:
1169 +//
1170 +// If Index is not already set, allocate a leaf, copy the old and new indexes
1171 +// into it, clear and return the new value area, and modify the current JP.
1172 +// Note that jp_DcdPop is set to a pop0 of 0 for now, and incremented later.
1173 +
1174 +
1175 +#define JU_IMMSET_01_CASCADE(cIS,LeafType,NewJPType,ValueArea, \
1176 + Copy,CopyWord,Alloc) \
1177 + { \
1178 + Word_t D_P0; \
1179 + LeafType PjllRaw; \
1180 + LeafType Pjll; \
1181 + Word_t oldIndex = JU_JPDCDPOP0(Pjp); \
1182 + Word_t oldValue; \
1183 + Pjv_t Pjv; \
1184 + \
1185 + Index = JU_TRIMTODCDSIZE(Index); \
1186 + \
1187 + if (oldIndex == Index) \
1188 + { \
1189 + Pjpm->jpm_PValue = (Pjv_t) (&(Pjp->jp_Addr)); \
1190 + return(0); \
1191 + } \
1192 + \
1193 + if ((PjllRaw = (LeafType) Alloc(2, Pjpm)) == (LeafType) NULL) \
1194 + return(-1); \
1195 + Pjll = (LeafType) P_JLL(PjllRaw); \
1196 + Pjv = ValueArea(Pjll, 2); \
1197 + \
1198 + oldValue = Pjp->jp_Addr; \
1199 + \
1200 + Copy(cIS,CopyWord); \
1201 + DBGCODE(JudyCheckSorted(Pjll, 2, cIS);) \
1202 + \
1203 + *Pjv = 0; \
1204 + Pjpm->jpm_PValue = Pjv; \
1205 + D_P0 = Index & cJU_DCDMASK(cIS); /* pop0 = 0 */ \
1206 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, D_P0, NewJPType); \
1207 + \
1208 + return(1); \
1209 + }
1210 +
1211 +#endif // JUDYL
1212 +
1213 +// Handle growth of cJU_JPIMMED_*_[02..15]:
1214 +
1215 +#ifdef JUDY1
1216 +
1217 +// Insert an Index into an immediate JP that has room for more, if the Index is
1218 +// not already present; given Pjp, Index, exppop1, Pjv, and Pjpm in the
1219 +// context:
1220 +//
1221 +// Note: Use this only when the JP format doesnt change, that is, going from
1222 +// cJU_JPIMMED_X_0Y to cJU_JPIMMED_X_0Z, where X >= 2 and Y+1 = Z.
1223 +//
1224 +// Note: Incrementing jp_Type is how to increase the Index population.
1225 +
1226 +#define JU_IMMSETINPLACE(cIS,LeafType,BaseJPType_02,Search,InsertInPlace) \
1227 + { \
1228 + LeafType Pjll; \
1229 + int offset; \
1230 + \
1231 + exppop1 = JU_JPTYPE(Pjp) - (BaseJPType_02) + 2; \
1232 + offset = Search((Pjll_t) (Pjp->jp_1Index), exppop1, Index); \
1233 + \
1234 + JU_CHECK_IF_EXISTS(offset, ignore, Pjpm); \
1235 + \
1236 + Pjll = (LeafType) (Pjp->jp_1Index); \
1237 + InsertInPlace(Pjll, exppop1, offset, Index); \
1238 + DBGCODE(JudyCheckSorted(Pjll, exppop1 + 1, cIS);) \
1239 + ++(Pjp->jp_Type); \
1240 + return(1); \
1241 + }
1242 +
1243 +// Insert an Index into an immediate JP that has no room for more:
1244 +//
1245 +// If the Index is not already present, do a cascade (to a leaf); given Pjp,
1246 +// Index, Pjv, and Pjpm in the context.
1247 +
1248 +
1249 +#define JU_IMMSETCASCADE(cIS,OldPop1,LeafType,NewJPType, \
1250 + ignore,Search,InsertCopy,Alloc) \
1251 + { \
1252 + Word_t D_P0; \
1253 + Pjll_t PjllRaw; \
1254 + Pjll_t Pjll; \
1255 + int offset; \
1256 + \
1257 + offset = Search((Pjll_t) (Pjp->jp_1Index), (OldPop1), Index); \
1258 + JU_CHECK_IF_EXISTS(offset, ignore, Pjpm); \
1259 + \
1260 + if ((PjllRaw = Alloc((OldPop1) + 1, Pjpm)) == 0) return(-1); \
1261 + Pjll = P_JLL(PjllRaw); \
1262 + \
1263 + InsertCopy((LeafType) Pjll, (LeafType) (Pjp->jp_1Index), \
1264 + OldPop1, offset, Index); \
1265 + DBGCODE(JudyCheckSorted(Pjll, (OldPop1) + 1, cIS);) \
1266 + \
1267 + D_P0 = (Index & cJU_DCDMASK(cIS)) + (OldPop1) - 1; \
1268 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, D_P0, NewJPType); \
1269 + return(1); \
1270 + }
1271 +
1272 +#else // JUDYL
1273 +
1274 +// Variations to also handle value areas; see comments above:
1275 +//
1276 +// For JudyL, Pjv (start of value area) is also in the context.
1277 +//
1278 +// TBD: This code makes a true but weak assumption that a JudyL 32-bit 2-index
1279 +// value area must be copied to a new 3-index value area. AND it doesnt know
1280 +// anything about JudyL 64-bit cases (cJU_JPIMMED_1_0[3-7] only) where the
1281 +// value area can grow in place! However, this should not break it, just slow
1282 +// it down.
1283 +
1284 +#define JU_IMMSETINPLACE(cIS,LeafType,BaseJPType_02,Search,InsertInPlace) \
1285 + { \
1286 + LeafType Pleaf; \
1287 + int offset; \
1288 + Pjv_t PjvRaw; \
1289 + Pjv_t Pjv; \
1290 + Pjv_t PjvnewRaw; \
1291 + Pjv_t Pjvnew; \
1292 + \
1293 + exppop1 = JU_JPTYPE(Pjp) - (BaseJPType_02) + 2; \
1294 + offset = Search((Pjll_t) (Pjp->jp_LIndex), exppop1, Index); \
1295 + PjvRaw = (Pjv_t) (Pjp->jp_Addr); \
1296 + Pjv = P_JV(PjvRaw); \
1297 + \
1298 + JU_CHECK_IF_EXISTS(offset, Pjv, Pjpm); \
1299 + \
1300 + if ((PjvnewRaw = j__udyLAllocJV(exppop1 + 1, Pjpm)) \
1301 + == (Pjv_t) NULL) return(-1); \
1302 + Pjvnew = P_JV(PjvnewRaw); \
1303 + \
1304 + Pleaf = (LeafType) (Pjp->jp_LIndex); \
1305 + \
1306 + InsertInPlace(Pleaf, exppop1, offset, Index); \
1307 + /* see TBD above about this: */ \
1308 + JU_INSERTCOPY(Pjvnew, Pjv, exppop1, offset, 0); \
1309 + DBGCODE(JudyCheckSorted(Pleaf, exppop1 + 1, cIS);) \
1310 + j__udyLFreeJV(PjvRaw, exppop1, Pjpm); \
1311 + Pjp->jp_Addr = (Word_t) PjvnewRaw; \
1312 + Pjpm->jpm_PValue = Pjvnew + offset; \
1313 + \
1314 + ++(Pjp->jp_Type); \
1315 + return(1); \
1316 + }
1317 +
1318 +#define JU_IMMSETCASCADE(cIS,OldPop1,LeafType,NewJPType, \
1319 + ValueArea,Search,InsertCopy,Alloc) \
1320 + { \
1321 + Word_t D_P0; \
1322 + Pjll_t PjllRaw; \
1323 + Pjll_t Pjll; \
1324 + int offset; \
1325 + Pjv_t PjvRaw; \
1326 + Pjv_t Pjv; \
1327 + Pjv_t Pjvnew; \
1328 + \
1329 + PjvRaw = (Pjv_t) (Pjp->jp_Addr); \
1330 + Pjv = P_JV(PjvRaw); \
1331 + offset = Search((Pjll_t) (Pjp->jp_LIndex), (OldPop1), Index); \
1332 + JU_CHECK_IF_EXISTS(offset, Pjv, Pjpm); \
1333 + \
1334 + if ((PjllRaw = Alloc((OldPop1) + 1, Pjpm)) == 0) \
1335 + return(-1); \
1336 + Pjll = P_JLL(PjllRaw); \
1337 + InsertCopy((LeafType) Pjll, (LeafType) (Pjp->jp_LIndex), \
1338 + OldPop1, offset, Index); \
1339 + DBGCODE(JudyCheckSorted(Pjll, (OldPop1) + 1, cIS);) \
1340 + \
1341 + Pjvnew = ValueArea(Pjll, (OldPop1) + 1); \
1342 + JU_INSERTCOPY(Pjvnew, Pjv, OldPop1, offset, 0); \
1343 + j__udyLFreeJV(PjvRaw, (OldPop1), Pjpm); \
1344 + Pjpm->jpm_PValue = Pjvnew + offset; \
1345 + \
1346 + D_P0 = (Index & cJU_DCDMASK(cIS)) + (OldPop1) - 1; \
1347 + JU_JPSETADT(Pjp, (Word_t)PjllRaw, D_P0, NewJPType); \
1348 + return(1); \
1349 + }
1350 +
1351 +#endif // JUDYL
1352 +
1353 +// Common convenience/shorthand wrappers around JU_IMMSET_01_COPY() for
1354 +// even/odd index sizes:
1355 +
1356 +#define JU_IMMSET_01( cIS, LeafType, NewJPType) \
1357 + JU_IMMSET_01_COPY(cIS, LeafType, NewJPType, JU_IMMSET_01_COPY_EVEN, \
1358 + ignore)
1359 +
1360 +#define JU_IMMSET_01_ODD( cIS, NewJPType, CopyWord) \
1361 + JU_IMMSET_01_COPY(cIS, uint8_t *, NewJPType, JU_IMMSET_01_COPY_ODD, \
1362 + CopyWord)
1363 +
1364 +
1365 +// END OF MACROS; IMMED CASES START HERE:
1366 +
1367 +// cJU_JPIMMED_*_01 cases:
1368 +//
1369 +// 1_01 always leads to 1_02:
1370 +//
1371 +// (1_01 => 1_02 => 1_03 => [ 1_04 => ... => 1_07 => [ 1_08..15 => ]] LeafL)
1372 +
1373 + case cJU_JPIMMED_1_01: JU_IMMSET_01(1, uint8_t *, cJU_JPIMMED_1_02);
1374 +
1375 +// 2_01 leads to 2_02, and 3_01 leads to 3_02, except for JudyL 32-bit, where
1376 +// they lead to a leaf:
1377 +//
1378 +// (2_01 => [ 2_02 => 2_03 => [ 2_04..07 => ]] LeafL)
1379 +// (3_01 => [ 3_02 => [ 3_03..05 => ]] LeafL)
1380 +
1381 +#if (defined(JUDY1) || defined(JU_64BIT))
1382 + case cJU_JPIMMED_2_01: JU_IMMSET_01(2, uint16_t *, cJU_JPIMMED_2_02);
1383 + case cJU_JPIMMED_3_01: JU_IMMSET_01_ODD (3, cJU_JPIMMED_3_02,
1384 + JU_COPY3_LONG_TO_PINDEX);
1385 +#else
1386 + case cJU_JPIMMED_2_01:
1387 + JU_IMMSET_01_CASCADE(2, uint16_t *, cJU_JPLEAF2, JL_LEAF2VALUEAREA,
1388 + JU_IMMSET_01_COPY_EVEN, ignore,
1389 + j__udyAllocJLL2);
1390 + case cJU_JPIMMED_3_01:
1391 + JU_IMMSET_01_CASCADE(3, uint8_t *, cJU_JPLEAF3, JL_LEAF3VALUEAREA,
1392 + JU_IMMSET_01_COPY_ODD,
1393 + JU_COPY3_LONG_TO_PINDEX, j__udyAllocJLL3);
1394 +#endif
1395 +
1396 +#ifdef JU_64BIT
1397 +
1398 +// [4-7]_01 lead to [4-7]_02 for Judy1, and to leaves for JudyL:
1399 +//
1400 +// (4_01 => [[ 4_02..03 => ]] LeafL)
1401 +// (5_01 => [[ 5_02..03 => ]] LeafL)
1402 +// (6_01 => [[ 6_02 => ]] LeafL)
1403 +// (7_01 => [[ 7_02 => ]] LeafL)
1404 +
1405 +#ifdef JUDY1
1406 + case cJU_JPIMMED_4_01: JU_IMMSET_01(4, uint32_t *, cJ1_JPIMMED_4_02);
1407 + case cJU_JPIMMED_5_01: JU_IMMSET_01_ODD(5, cJ1_JPIMMED_5_02,
1408 + JU_COPY5_LONG_TO_PINDEX);
1409 + case cJU_JPIMMED_6_01: JU_IMMSET_01_ODD(6, cJ1_JPIMMED_6_02,
1410 + JU_COPY6_LONG_TO_PINDEX);
1411 + case cJU_JPIMMED_7_01: JU_IMMSET_01_ODD(7, cJ1_JPIMMED_7_02,
1412 + JU_COPY7_LONG_TO_PINDEX);
1413 +#else // JUDYL
1414 + case cJU_JPIMMED_4_01:
1415 + JU_IMMSET_01_CASCADE(4, uint32_t *, cJU_JPLEAF4, JL_LEAF4VALUEAREA,
1416 + JU_IMMSET_01_COPY_EVEN, ignore,
1417 + j__udyAllocJLL4);
1418 + case cJU_JPIMMED_5_01:
1419 + JU_IMMSET_01_CASCADE(5, uint8_t *, cJU_JPLEAF5, JL_LEAF5VALUEAREA,
1420 + JU_IMMSET_01_COPY_ODD,
1421 + JU_COPY5_LONG_TO_PINDEX, j__udyAllocJLL5);
1422 + case cJU_JPIMMED_6_01:
1423 + JU_IMMSET_01_CASCADE(6, uint8_t *, cJU_JPLEAF6, JL_LEAF6VALUEAREA,
1424 + JU_IMMSET_01_COPY_ODD,
1425 + JU_COPY6_LONG_TO_PINDEX, j__udyAllocJLL6);
1426 + case cJU_JPIMMED_7_01:
1427 + JU_IMMSET_01_CASCADE(7, uint8_t *, cJU_JPLEAF7, JL_LEAF7VALUEAREA,
1428 + JU_IMMSET_01_COPY_ODD,
1429 + JU_COPY7_LONG_TO_PINDEX, j__udyAllocJLL7);
1430 +#endif // JUDYL
1431 +#endif // JU_64BIT
1432 +
1433 +// cJU_JPIMMED_1_* cases that can grow in place:
1434 +//
1435 +// (1_01 => 1_02 => 1_03 => [ 1_04 => ... => 1_07 => [ 1_08..15 => ]] LeafL)
1436 +
1437 + case cJU_JPIMMED_1_02:
1438 +#if (defined(JUDY1) || defined(JU_64BIT))
1439 + case cJU_JPIMMED_1_03:
1440 + case cJU_JPIMMED_1_04:
1441 + case cJU_JPIMMED_1_05:
1442 + case cJU_JPIMMED_1_06:
1443 +#endif
1444 +#if (defined(JUDY1) && defined(JU_64BIT))
1445 + case cJU_JPIMMED_1_07:
1446 + case cJ1_JPIMMED_1_08:
1447 + case cJ1_JPIMMED_1_09:
1448 + case cJ1_JPIMMED_1_10:
1449 + case cJ1_JPIMMED_1_11:
1450 + case cJ1_JPIMMED_1_12:
1451 + case cJ1_JPIMMED_1_13:
1452 + case cJ1_JPIMMED_1_14:
1453 +#endif
1454 + JU_IMMSETINPLACE(1, uint8_t *, cJU_JPIMMED_1_02, j__udySearchLeaf1,
1455 + JU_INSERTINPLACE);
1456 +
1457 +// cJU_JPIMMED_1_* cases that must cascade:
1458 +//
1459 +// (1_01 => 1_02 => 1_03 => [ 1_04 => ... => 1_07 => [ 1_08..15 => ]] LeafL)
1460 +
1461 +#if (defined(JUDYL) && (! defined(JU_64BIT)))
1462 + case cJU_JPIMMED_1_03:
1463 + JU_IMMSETCASCADE(1, 3, uint8_t *, cJU_JPLEAF1, JL_LEAF1VALUEAREA,
1464 + j__udySearchLeaf1, JU_INSERTCOPY,
1465 + j__udyAllocJLL1);
1466 +#endif
1467 +#if (defined(JUDY1) && (! defined(JU_64BIT)))
1468 + case cJU_JPIMMED_1_07:
1469 + JU_IMMSETCASCADE(1, 7, uint8_t *, cJU_JPLEAF1, ignore,
1470 + j__udySearchLeaf1, JU_INSERTCOPY,
1471 + j__udyAllocJLL1);
1472 +
1473 +#endif
1474 +#if (defined(JUDYL) && defined(JU_64BIT))
1475 + case cJU_JPIMMED_1_07:
1476 + JU_IMMSETCASCADE(1, 7, uint8_t *, cJU_JPLEAF1, JL_LEAF1VALUEAREA,
1477 + j__udySearchLeaf1, JU_INSERTCOPY,
1478 + j__udyAllocJLL1);
1479 +
1480 +#endif
1481 +#if (defined(JUDY1) && defined(JU_64BIT))
1482 +// Special case, as described above, go directly from Immed to LeafB1:
1483 +
1484 + case cJ1_JPIMMED_1_15:
1485 + {
1486 + Word_t DcdP0;
1487 + int offset;
1488 + Pjlb_t PjlbRaw;
1489 + Pjlb_t Pjlb;
1490 +
1491 + offset = j__udySearchLeaf1((Pjll_t) Pjp->jp_1Index, 15, Index);
1492 +
1493 + JU_CHECK_IF_EXISTS(offset, ignore, Pjpm);
1494 +
1495 +// Create a bitmap leaf (special case for Judy1 64-bit only, see usage): Set
1496 +// new Index in bitmap, copy an Immed1_15 to the bitmap, and set the parent JP
1497 +// EXCEPT jp_DcdPopO, leaving any followup to the caller:
1498 +
1499 + if ((PjlbRaw = j__udyAllocJLB1(Pjpm)) == (Pjlb_t) NULL)
1500 + return(-1);
1501 + Pjlb = P_JLB(PjlbRaw);
1502 +
1503 + JU_BITMAPSETL(Pjlb, Index);
1504 +
1505 + for (offset = 0; offset < 15; ++offset)
1506 + JU_BITMAPSETL(Pjlb, Pjp->jp_1Index[offset]);
1507 +
1508 +// Set jp_DcdPopO including the current pop0; incremented later:
1509 + DcdP0 = (Index & cJU_DCDMASK(1)) + 15 - 1;
1510 + JU_JPSETADT(Pjp, (Word_t)PjlbRaw, DcdP0, cJU_JPLEAF_B1);
1511 +
1512 + return(1);
1513 + }
1514 +#endif
1515 +
1516 +// cJU_JPIMMED_[2..7]_[02..15] cases that grow in place or cascade:
1517 +//
1518 +// (2_01 => [ 2_02 => 2_03 => [ 2_04..07 => ]] LeafL)
1519 +
1520 +#if (defined(JUDY1) || defined(JU_64BIT))
1521 + case cJU_JPIMMED_2_02:
1522 +#endif
1523 +#if (defined(JUDY1) && defined(JU_64BIT))
1524 + case cJU_JPIMMED_2_03:
1525 + case cJ1_JPIMMED_2_04:
1526 + case cJ1_JPIMMED_2_05:
1527 + case cJ1_JPIMMED_2_06:
1528 +#endif
1529 +#if (defined(JUDY1) || defined(JU_64BIT))
1530 + JU_IMMSETINPLACE(2, uint16_t *, cJU_JPIMMED_2_02, j__udySearchLeaf2,
1531 + JU_INSERTINPLACE);
1532 +#endif
1533 +
1534 +#undef OLDPOP1
1535 +#if ((defined(JUDY1) && (! defined(JU_64BIT))) || (defined(JUDYL) && defined(JU_64BIT)))
1536 + case cJU_JPIMMED_2_03:
1537 +#define OLDPOP1 3
1538 +#endif
1539 +#if (defined(JUDY1) && defined(JU_64BIT))
1540 + case cJ1_JPIMMED_2_07:
1541 +#define OLDPOP1 7
1542 +#endif
1543 +#if (defined(JUDY1) || defined(JU_64BIT))
1544 + JU_IMMSETCASCADE(2, OLDPOP1, uint16_t *, cJU_JPLEAF2,
1545 + JL_LEAF2VALUEAREA, j__udySearchLeaf2,
1546 + JU_INSERTCOPY, j__udyAllocJLL2);
1547 +#endif
1548 +
1549 +// (3_01 => [ 3_02 => [ 3_03..05 => ]] LeafL)
1550 +
1551 +#if (defined(JUDY1) && defined(JU_64BIT))
1552 + case cJU_JPIMMED_3_02:
1553 + case cJ1_JPIMMED_3_03:
1554 + case cJ1_JPIMMED_3_04:
1555 +
1556 + JU_IMMSETINPLACE(3, uint8_t *, cJU_JPIMMED_3_02, j__udySearchLeaf3,
1557 + JU_INSERTINPLACE3);
1558 +#endif
1559 +
1560 +#undef OLDPOP1
1561 +#if ((defined(JUDY1) && (! defined(JU_64BIT))) || (defined(JUDYL) && defined(JU_64BIT)))
1562 + case cJU_JPIMMED_3_02:
1563 +#define OLDPOP1 2
1564 +#endif
1565 +#if (defined(JUDY1) && defined(JU_64BIT))
1566 + case cJ1_JPIMMED_3_05:
1567 +#define OLDPOP1 5
1568 +#endif
1569 +#if (defined(JUDY1) || defined(JU_64BIT))
1570 + JU_IMMSETCASCADE(3, OLDPOP1, uint8_t *, cJU_JPLEAF3,
1571 + JL_LEAF3VALUEAREA, j__udySearchLeaf3,
1572 + JU_INSERTCOPY3, j__udyAllocJLL3);
1573 +#endif
1574 +
1575 +#if (defined(JUDY1) && defined(JU_64BIT))
1576 +
1577 +// (4_01 => [[ 4_02..03 => ]] LeafL)
1578 +
1579 + case cJ1_JPIMMED_4_02:
1580 +
1581 + JU_IMMSETINPLACE(4, uint32_t *, cJ1_JPIMMED_4_02, j__udySearchLeaf4,
1582 + JU_INSERTINPLACE);
1583 +
1584 + case cJ1_JPIMMED_4_03:
1585 +
1586 + JU_IMMSETCASCADE(4, 3, uint32_t *, cJU_JPLEAF4, ignore,
1587 + j__udySearchLeaf4, JU_INSERTCOPY,
1588 + j__udyAllocJLL4);
1589 +
1590 +// (5_01 => [[ 5_02..03 => ]] LeafL)
1591 +
1592 + case cJ1_JPIMMED_5_02:
1593 +
1594 + JU_IMMSETINPLACE(5, uint8_t *, cJ1_JPIMMED_5_02, j__udySearchLeaf5,
1595 + JU_INSERTINPLACE5);
1596 +
1597 + case cJ1_JPIMMED_5_03:
1598 +
1599 + JU_IMMSETCASCADE(5, 3, uint8_t *, cJU_JPLEAF5, ignore,
1600 + j__udySearchLeaf5, JU_INSERTCOPY5,
1601 + j__udyAllocJLL5);
1602 +
1603 +// (6_01 => [[ 6_02 => ]] LeafL)
1604 +
1605 + case cJ1_JPIMMED_6_02:
1606 +
1607 + JU_IMMSETCASCADE(6, 2, uint8_t *, cJU_JPLEAF6, ignore,
1608 + j__udySearchLeaf6, JU_INSERTCOPY6,
1609 + j__udyAllocJLL6);
1610 +
1611 +// (7_01 => [[ 7_02 => ]] LeafL)
1612 +
1613 + case cJ1_JPIMMED_7_02:
1614 +
1615 + JU_IMMSETCASCADE(7, 2, uint8_t *, cJU_JPLEAF7, ignore,
1616 + j__udySearchLeaf7, JU_INSERTCOPY7,
1617 + j__udyAllocJLL7);
1618 +
1619 +#endif // (JUDY1 && JU_64BIT)
1620 +
1621 +
1622 +// ****************************************************************************
1623 +// INVALID JP TYPE:
1624 +
1625 + default: JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT); return(-1);
1626 +
1627 + } // switch on JP type
1628 +
1629 + {
1630 +
1631 +#ifdef SUBEXPCOUNTS
1632 +
1633 +// This code might seem strange here. However it saves some memory read time
1634 +// during insert (~70nS) because a pipelined processor does not need to "stall"
1635 +// waiting for the memory read to complete. Hope the compiler is not too smart
1636 +// or dumb and moves the code down to where it looks like it belongs (below a
1637 +// few lines).
1638 +
1639 + Word_t SubExpCount = 0; // current subexpanse counter.
1640 +
1641 + if (PSubExp != (PWord_t) NULL) // only if BranchB/U.
1642 + SubExpCount = PSubExp[0];
1643 +#endif
1644 +
1645 +// PROCESS JP -- RECURSIVELY:
1646 +//
1647 +// For non-Immed JP types, if successful, post-increment the population count
1648 +// at this Level.
1649 +
1650 + retcode = j__udyInsWalk(Pjp, Index, Pjpm);
1651 +
1652 +// Successful insert, increment JP and subexpanse count:
1653 +
1654 + if ((JU_JPTYPE(Pjp) < cJU_JPIMMED_1_01) && (retcode == 1))
1655 + {
1656 + jp_t JP;
1657 + Word_t DcdP0;
1658 +#ifdef SUBEXPCOUNTS
1659 +
1660 +// Note: Pjp must be a pointer to a BranchB/U:
1661 +
1662 + if (PSubExp != (PWord_t) NULL) PSubExp[0] = SubExpCount + 1;
1663 +#endif
1664 +
1665 + JP = *Pjp;
1666 + DcdP0 = JU_JPDCDPOP0(Pjp) + 1;
1667 + JU_JPSETADT(Pjp, JP.jp_Addr, DcdP0, JU_JPTYPE(&JP));
1668 + }
1669 + }
1670 + return(retcode);
1671 +
1672 +} // j__udyInsWalk()
1673 +
1674 +
1675 +// ****************************************************************************
1676 +// J U D Y 1 S E T
1677 +// J U D Y L I N S
1678 +//
1679 +// Main entry point. See the manual entry for details.
1680 +
1681 +#ifdef JUDY1
1682 +FUNCTION int Judy1Set
1683 +#else
1684 +FUNCTION PPvoid_t JudyLIns
1685 +#endif
1686 + (
1687 + PPvoid_t PPArray, // in which to insert.
1688 + Word_t Index, // to insert.
1689 + PJError_t PJError // optional, for returning error info.
1690 + )
1691 +{
1692 +#ifdef JUDY1
1693 +#define Pjv ignore // placeholders for macros.
1694 +#define Pjvnew ignore
1695 +#else
1696 + Pjv_t Pjv; // value area in old leaf.
1697 + Pjv_t Pjvnew; // value area in new leaf.
1698 +#endif
1699 + Pjpm_t Pjpm; // array-global info.
1700 + int offset; // position in which to store new Index.
1701 + Pjlw_t Pjlw;
1702 +
1703 +
1704 +// CHECK FOR NULL POINTER (error by caller):
1705 +
1706 + if (PPArray == (PPvoid_t) NULL)
1707 + {
1708 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY);
1709 + JUDY1CODE(return(JERRI );)
1710 + JUDYLCODE(return(PPJERR);)
1711 + }
1712 +
1713 + Pjlw = P_JLW(*PPArray); // first word of leaf.
1714 +
1715 +// ****************************************************************************
1716 +// PROCESS TOP LEVEL "JRP" BRANCHES AND LEAVES:
1717 +
1718 +// ****************************************************************************
1719 +// JRPNULL (EMPTY ARRAY): BUILD A LEAFW WITH ONE INDEX:
1720 +
1721 +// if a valid empty array (null pointer), so create an array of population == 1:
1722 +
1723 + if (Pjlw == (Pjlw_t)NULL)
1724 + {
1725 + Pjlw_t Pjlwnew;
1726 +
1727 + Pjlwnew = j__udyAllocJLW(1);
1728 + JUDY1CODE(JU_CHECKALLOC(Pjlw_t, Pjlwnew, JERRI );)
1729 + JUDYLCODE(JU_CHECKALLOC(Pjlw_t, Pjlwnew, PPJERR);)
1730 +
1731 + Pjlwnew[0] = 1 - 1; // pop0 = 0.
1732 + Pjlwnew[1] = Index;
1733 +
1734 + *PPArray = (Pvoid_t) Pjlwnew;
1735 + DBGCODE(JudyCheckPop(*PPArray);)
1736 +
1737 + JUDY1CODE(return(1); )
1738 + JUDYLCODE(Pjlwnew[2] = 0; ) // value area.
1739 + JUDYLCODE(return((PPvoid_t) (Pjlwnew + 2)); )
1740 +
1741 + } // NULL JRP
1742 +
1743 +// ****************************************************************************
1744 +// LEAFW, OTHER SIZE:
1745 +
1746 + if (JU_LEAFW_POP0(*PPArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
1747 + {
1748 + Pjlw_t Pjlwnew;
1749 + Word_t pop1;
1750 +
1751 + Pjlw = P_JLW(*PPArray); // first word of leaf.
1752 + pop1 = Pjlw[0] + 1;
1753 +
1754 +#ifdef JUDYL
1755 + Pjv = JL_LEAFWVALUEAREA(Pjlw, pop1);
1756 +#endif
1757 + offset = j__udySearchLeafW(Pjlw + 1, pop1, Index);
1758 +
1759 + if (offset >= 0) // index is already valid:
1760 + {
1761 + DBGCODE(JudyCheckPop(*PPArray);)
1762 + JUDY1CODE(return(0); )
1763 + JUDYLCODE(return((PPvoid_t) (Pjv + offset)); )
1764 + }
1765 +
1766 + offset = ~offset;
1767 +
1768 +// Insert index in cases where no new memory is needed:
1769 +
1770 + if (JU_LEAFWGROWINPLACE(pop1))
1771 + {
1772 + ++Pjlw[0]; // increase population.
1773 +
1774 + JU_INSERTINPLACE(Pjlw + 1, pop1, offset, Index);
1775 +#ifdef JUDYL
1776 + JU_INSERTINPLACE(Pjv, pop1, offset, 0);
1777 +#endif
1778 + DBGCODE(JudyCheckPop(*PPArray);)
1779 + DBGCODE(JudyCheckSorted(Pjlw + 1, pop1 + 1, cJU_ROOTSTATE);)
1780 +
1781 + JUDY1CODE(return(1); )
1782 + JUDYLCODE(return((PPvoid_t) (Pjv + offset)); )
1783 + }
1784 +
1785 +// Insert index into a new, larger leaf:
1786 +
1787 + if (pop1 < cJU_LEAFW_MAXPOP1) // can grow to a larger leaf.
1788 + {
1789 + Pjlwnew = j__udyAllocJLW(pop1 + 1);
1790 + JUDY1CODE(JU_CHECKALLOC(Pjlw_t, Pjlwnew, JERRI );)
1791 + JUDYLCODE(JU_CHECKALLOC(Pjlw_t, Pjlwnew, PPJERR);)
1792 +
1793 + Pjlwnew[0] = pop1; // set pop0 in new leaf.
1794 +
1795 + JU_INSERTCOPY(Pjlwnew + 1, Pjlw + 1, pop1, offset, Index);
1796 +#ifdef JUDYL
1797 + Pjvnew = JL_LEAFWVALUEAREA(Pjlwnew, pop1 + 1);
1798 + JU_INSERTCOPY(Pjvnew, Pjv, pop1, offset, 0);
1799 +#endif
1800 + DBGCODE(JudyCheckSorted(Pjlwnew + 1, pop1 + 1, cJU_ROOTSTATE);)
1801 +
1802 + j__udyFreeJLW(Pjlw, pop1, NULL);
1803 +
1804 + *PPArray = (Pvoid_t) Pjlwnew;
1805 + DBGCODE(JudyCheckPop(*PPArray);)
1806 +
1807 + JUDY1CODE(return(1); )
1808 + JUDYLCODE(return((PPvoid_t) (Pjvnew + offset)); )
1809 + }
1810 +
1811 + assert(pop1 == cJU_LEAFW_MAXPOP1);
1812 +
1813 +// Leaf at max size => cannot insert new index, so cascade instead:
1814 +//
1815 +// Upon cascading from a LEAFW leaf to the first branch, must allocate and
1816 +// initialize a JPM.
1817 +
1818 + Pjpm = j__udyAllocJPM();
1819 + JUDY1CODE(JU_CHECKALLOC(Pjpm_t, Pjpm, JERRI );)
1820 + JUDYLCODE(JU_CHECKALLOC(Pjpm_t, Pjpm, PPJERR);)
1821 +
1822 + (Pjpm->jpm_Pop0) = cJU_LEAFW_MAXPOP1 - 1;
1823 + (Pjpm->jpm_JP.jp_Addr) = (Word_t) Pjlw;
1824 +
1825 + if (j__udyCascadeL(&(Pjpm->jpm_JP), Pjpm) == -1)
1826 + {
1827 + JU_COPY_ERRNO(PJError, Pjpm);
1828 + JUDY1CODE(return(JERRI );)
1829 + JUDYLCODE(return(PPJERR);)
1830 + }
1831 +
1832 +// Note: No need to pass Pjpm for memory decrement; LEAFW memory is never
1833 +// counted in a JPM at all:
1834 +
1835 + j__udyFreeJLW(Pjlw, cJU_LEAFW_MAXPOP1, NULL);
1836 + *PPArray = (Pvoid_t) Pjpm;
1837 +
1838 + } // JU_LEAFW
1839 +
1840 +// ****************************************************************************
1841 +// BRANCH:
1842 +
1843 + {
1844 + int retcode; // really only needed for Judy1, but free for JudyL.
1845 +
1846 + Pjpm = P_JPM(*PPArray);
1847 + retcode = j__udyInsWalk(&(Pjpm->jpm_JP), Index, Pjpm);
1848 +
1849 + if (retcode == -1)
1850 + {
1851 + JU_COPY_ERRNO(PJError, Pjpm);
1852 + JUDY1CODE(return(JERRI );)
1853 + JUDYLCODE(return(PPJERR);)
1854 + }
1855 +
1856 + if (retcode == 1) ++(Pjpm->jpm_Pop0); // incr total array popu.
1857 +
1858 + assert(((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_L)
1859 + || ((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_B)
1860 + || ((Pjpm->jpm_JP.jp_Type) == cJU_JPBRANCH_U));
1861 + DBGCODE(JudyCheckPop(*PPArray);)
1862 +
1863 +#ifdef JUDY1
1864 + assert((retcode == 0) || (retcode == 1));
1865 + return(retcode); // == JU_RET_*_JPM().
1866 +#else
1867 + assert(Pjpm->jpm_PValue != (Pjv_t) NULL);
1868 + return((PPvoid_t) Pjpm->jpm_PValue);
1869 +#endif
1870 + }
1871 + /*NOTREACHED*/
1872 +
1873 +} // Judy1Set() / JudyLIns()
libnetdata/libjudy/src/JudyL/JudyLInsArray.c new
+1178
@@ -0,0 +1,1178 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// TBD: It would probably be faster for the caller if the JudyL version took
19 +// PIndex as an interleaved array of indexes and values rather than just
20 +// indexes with a separate values array (PValue), especially considering
21 +// indexes and values are copied here with for-loops anyway and not the
22 +// equivalent of memcpy(). All code could be revised to simply count by two
23 +// words for JudyL? Supports "streaming" the data to/from disk better later?
24 +// In which case get rid of JU_ERRNO_NULLPVALUE, no longer needed, and simplify
25 +// the API to this code.
26 +// _________________
27 +
28 +// @(#) $Revision: 4.21 $ $Source: /judy/src/JudyCommon/JudyInsArray.c $
29 +//
30 +// Judy1SetArray() and JudyLInsArray() functions for Judy1 and JudyL.
31 +// Compile with one of -DJUDY1 or -DJUDYL.
32 +
33 +#if (! (defined(JUDY1) || defined(JUDYL)))
34 +#error: One of -DJUDY1 or -DJUDYL must be specified.
35 +#endif
36 +
37 +#ifdef JUDY1
38 +#include "Judy1.h"
39 +#else
40 +#include "JudyL.h"
41 +#endif
42 +
43 +#include "JudyPrivate1L.h"
44 +
45 +DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);)
46 +
47 +
48 +// IMMED AND LEAF SIZE AND BRANCH TYPE ARRAYS:
49 +//
50 +// These support fast and easy lookup by level.
51 +
52 +static uint8_t immed_maxpop1[] = {
53 + 0,
54 + cJU_IMMED1_MAXPOP1,
55 + cJU_IMMED2_MAXPOP1,
56 + cJU_IMMED3_MAXPOP1,
57 +#ifdef JU_64BIT
58 + cJU_IMMED4_MAXPOP1,
59 + cJU_IMMED5_MAXPOP1,
60 + cJU_IMMED6_MAXPOP1,
61 + cJU_IMMED7_MAXPOP1,
62 +#endif
63 + // note: There are no IMMEDs for whole words.
64 +};
65 +
66 +static uint8_t leaf_maxpop1[] = {
67 + 0,
68 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
69 + cJU_LEAF1_MAXPOP1,
70 +#else
71 + 0, // 64-bit Judy1 has no Leaf1.
72 +#endif
73 + cJU_LEAF2_MAXPOP1,
74 + cJU_LEAF3_MAXPOP1,
75 +#ifdef JU_64BIT
76 + cJU_LEAF4_MAXPOP1,
77 + cJU_LEAF5_MAXPOP1,
78 + cJU_LEAF6_MAXPOP1,
79 + cJU_LEAF7_MAXPOP1,
80 +#endif
81 + // note: Root-level leaves are handled differently.
82 +};
83 +
84 +static uint8_t branchL_JPtype[] = {
85 + 0,
86 + 0,
87 + cJU_JPBRANCH_L2,
88 + cJU_JPBRANCH_L3,
89 +#ifdef JU_64BIT
90 + cJU_JPBRANCH_L4,
91 + cJU_JPBRANCH_L5,
92 + cJU_JPBRANCH_L6,
93 + cJU_JPBRANCH_L7,
94 +#endif
95 + cJU_JPBRANCH_L,
96 +};
97 +
98 +static uint8_t branchB_JPtype[] = {
99 + 0,
100 + 0,
101 + cJU_JPBRANCH_B2,
102 + cJU_JPBRANCH_B3,
103 +#ifdef JU_64BIT
104 + cJU_JPBRANCH_B4,
105 + cJU_JPBRANCH_B5,
106 + cJU_JPBRANCH_B6,
107 + cJU_JPBRANCH_B7,
108 +#endif
109 + cJU_JPBRANCH_B,
110 +};
111 +
112 +static uint8_t branchU_JPtype[] = {
113 + 0,
114 + 0,
115 + cJU_JPBRANCH_U2,
116 + cJU_JPBRANCH_U3,
117 +#ifdef JU_64BIT
118 + cJU_JPBRANCH_U4,
119 + cJU_JPBRANCH_U5,
120 + cJU_JPBRANCH_U6,
121 + cJU_JPBRANCH_U7,
122 +#endif
123 + cJU_JPBRANCH_U,
124 +};
125 +
126 +// Subexpanse masks are similer to JU_DCDMASK() but without the need to clear
127 +// the first digits bits. Avoid doing variable shifts by precomputing a
128 +// lookup array.
129 +
130 +static Word_t subexp_mask[] = {
131 + 0,
132 + ~cJU_POP0MASK(1),
133 + ~cJU_POP0MASK(2),
134 + ~cJU_POP0MASK(3),
135 +#ifdef JU_64BIT
136 + ~cJU_POP0MASK(4),
137 + ~cJU_POP0MASK(5),
138 + ~cJU_POP0MASK(6),
139 + ~cJU_POP0MASK(7),
140 +#endif
141 +};
142 +
143 +
144 +// FUNCTION PROTOTYPES:
145 +
146 +static bool_t j__udyInsArray(Pjp_t PjpParent, int Level, PWord_t PPop1,
147 + PWord_t PIndex,
148 +#ifdef JUDYL
149 + Pjv_t PValue,
150 +#endif
151 + Pjpm_t Pjpm);
152 +
153 +
154 +// ****************************************************************************
155 +// J U D Y 1 S E T A R R A Y
156 +// J U D Y L I N S A R R A Y
157 +//
158 +// Main entry point. See the manual entry for external overview.
159 +//
160 +// TBD: Until thats written, note that the function returns 1 for success or
161 +// JERRI for serious error, including insufficient memory to build whole array;
162 +// use Judy*Count() to see how many were stored, the first N of the total
163 +// Count. Also, since it takes Count == Pop1, it cannot handle a full array.
164 +// Also, "sorted" means ascending without duplicates, otherwise you get the
165 +// "unsorted" error.
166 +//
167 +// The purpose of these functions is to allow rapid construction of a large
168 +// Judy array given a sorted list of indexes (and for JudyL, corresponding
169 +// values). At least one customer saw this as useful, and probably it would
170 +// also be useful as a sufficient workaround for fast(er) unload/reload to/from
171 +// disk.
172 +//
173 +// This code is written recursively for simplicity, until/unless someone
174 +// decides to make it faster and more complex. Hopefully recursion is fast
175 +// enough simply because the function is so much faster than a series of
176 +// Set/Ins calls.
177 +
178 +#ifdef JUDY1
179 +FUNCTION int Judy1SetArray
180 +#else
181 +FUNCTION int JudyLInsArray
182 +#endif
183 + (
184 + PPvoid_t PPArray, // in which to insert, initially empty.
185 + Word_t Count, // number of indexes (and values) to insert.
186 +const Word_t * const PIndex, // list of indexes to insert.
187 +#ifdef JUDYL
188 +const Word_t * const PValue, // list of corresponding values.
189 +#endif
190 + PJError_t PJError // optional, for returning error info.
191 + )
192 +{
193 + Pjlw_t Pjlw; // new root-level leaf.
194 + Pjlw_t Pjlwindex; // first index in root-level leaf.
195 + int offset; // in PIndex.
196 +
197 +
198 +// CHECK FOR NULL OR NON-NULL POINTER (error by caller):
199 +
200 + if (PPArray == (PPvoid_t) NULL)
201 + { JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY); return(JERRI); }
202 +
203 + if (*PPArray != (Pvoid_t) NULL)
204 + { JU_SET_ERRNO(PJError, JU_ERRNO_NONNULLPARRAY); return(JERRI); }
205 +
206 + if (PIndex == (PWord_t) NULL)
207 + { JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX); return(JERRI); }
208 +
209 +#ifdef JUDYL
210 + if (PValue == (PWord_t) NULL)
211 + { JU_SET_ERRNO(PJError, JU_ERRNO_NULLPVALUE); return(JERRI); }
212 +#endif
213 +
214 +
215 +// HANDLE LARGE COUNT (= POP1) (typical case):
216 +//
217 +// Allocate and initialize a JPM, set the root pointer to point to it, and then
218 +// build the tree underneath it.
219 +
220 +// Common code for unusual error handling when no JPM available:
221 +
222 + if (Count > cJU_LEAFW_MAXPOP1) // too big for root-level leaf.
223 + {
224 + Pjpm_t Pjpm; // new, to allocate.
225 +
226 +// Allocate JPM:
227 +
228 + Pjpm = j__udyAllocJPM();
229 + JU_CHECKALLOC(Pjpm_t, Pjpm, JERRI);
230 + *PPArray = (Pvoid_t) Pjpm;
231 +
232 +// Set some JPM fields:
233 +
234 + (Pjpm->jpm_Pop0) = Count - 1;
235 + // note: (Pjpm->jpm_TotalMemWords) is now initialized.
236 +
237 +// Build Judy tree:
238 +//
239 +// In case of error save the final Count, possibly modified, unless modified to
240 +// 0, in which case free the JPM itself:
241 +
242 + if (! j__udyInsArray(&(Pjpm->jpm_JP), cJU_ROOTSTATE, &Count,
243 + (PWord_t) PIndex,
244 +#ifdef JUDYL
245 + (Pjv_t) PValue,
246 +#endif
247 + Pjpm))
248 + {
249 + JU_COPY_ERRNO(PJError, Pjpm);
250 +
251 + if (Count) // partial success, adjust pop0:
252 + {
253 + (Pjpm->jpm_Pop0) = Count - 1;
254 + }
255 + else // total failure, free JPM:
256 + {
257 + j__udyFreeJPM(Pjpm, (Pjpm_t) NULL);
258 + *PPArray = (Pvoid_t) NULL;
259 + }
260 +
261 + DBGCODE(JudyCheckPop(*PPArray);)
262 + return(JERRI);
263 + }
264 +
265 + DBGCODE(JudyCheckPop(*PPArray);)
266 + return(1);
267 +
268 + } // large count
269 +
270 +
271 +// HANDLE SMALL COUNT (= POP1):
272 +//
273 +// First ensure indexes are in sorted order:
274 +
275 + for (offset = 1; offset < Count; ++offset)
276 + {
277 + if (PIndex[offset - 1] >= PIndex[offset])
278 + { JU_SET_ERRNO(PJError, JU_ERRNO_UNSORTED); return(JERRI); }
279 + }
280 +
281 + if (Count == 0) return(1); // *PPArray remains null.
282 +
283 + {
284 + Pjlw = j__udyAllocJLW(Count + 1);
285 + JU_CHECKALLOC(Pjlw_t, Pjlw, JERRI);
286 + *PPArray = (Pvoid_t) Pjlw;
287 + Pjlw[0] = Count - 1; // set pop0.
288 + Pjlwindex = Pjlw + 1;
289 + }
290 +
291 +// Copy whole-word indexes (and values) to the root-level leaf:
292 +
293 + JU_COPYMEM(Pjlwindex, PIndex, Count);
294 +JUDYLCODE(JU_COPYMEM(JL_LEAFWVALUEAREA(Pjlw, Count), PValue, Count));
295 +
296 + DBGCODE(JudyCheckPop(*PPArray);)
297 + return(1);
298 +
299 +} // Judy1SetArray() / JudyLInsArray()
300 +
301 +
302 +// ****************************************************************************
303 +// __ J U D Y I N S A R R A Y
304 +//
305 +// Given:
306 +//
307 +// - a pointer to a JP
308 +//
309 +// - the JPs level in the tree, that is, the number of digits left to decode
310 +// in the indexes under the JP (one less than the level of the JPM or branch
311 +// in which the JP resides); cJU_ROOTSTATE on first entry (when JP is the one
312 +// in the JPM), down to 1 for a Leaf1, LeafB1, or FullPop
313 +//
314 +// - a pointer to the number of indexes (and corresponding values) to store in
315 +// this subtree, to modify in case of partial success
316 +//
317 +// - a list of indexes (and for JudyL, corresponding values) to store in this
318 +// subtree
319 +//
320 +// - a JPM for tracking memory usage and returning errors
321 +//
322 +// Recursively build a subtree (immediate indexes, leaf, or branch with
323 +// subtrees) and modify the JP accordingly. On the way down, build a BranchU
324 +// (only) for any expanse with *PPop1 too high for a leaf; on the way out,
325 +// convert the BranchU to a BranchL or BranchB if appropriate. Keep memory
326 +// statistics in the JPM.
327 +//
328 +// Return TRUE for success, or FALSE with error information set in the JPM in
329 +// case of error, in which case leave a partially constructed but healthy tree,
330 +// and modify parent population counts on the way out.
331 +//
332 +// Note: Each call of this function makes all modifications to the PjpParent
333 +// it receives; neither the parent nor child calls do this.
334 +
335 +FUNCTION static bool_t j__udyInsArray(
336 + Pjp_t PjpParent, // parent JP in/under which to store.
337 + int Level, // initial digits remaining to decode.
338 + PWord_t PPop1, // number of indexes to store.
339 + PWord_t PIndex, // list of indexes to store.
340 +#ifdef JUDYL
341 + Pjv_t PValue, // list of corresponding values.
342 +#endif
343 + Pjpm_t Pjpm) // for memory and errors.
344 +{
345 + Pjp_t Pjp; // lower-level JP.
346 + Word_t Pjbany; // any type of branch.
347 + int levelsub; // actual, of Pjps node, <= Level.
348 + Word_t pop1 = *PPop1; // fast local value.
349 + Word_t pop1sub; // population of one subexpanse.
350 + uint8_t JPtype; // current JP type.
351 + uint8_t JPtype_null; // precomputed value for new branch.
352 + jp_t JPnull; // precomputed for speed.
353 + Pjbu_t PjbuRaw; // constructed BranchU.
354 + Pjbu_t Pjbu;
355 + int digit; // in BranchU.
356 + Word_t digitmask; // for a digit in a BranchU.
357 + Word_t digitshifted; // shifted to correct offset.
358 + Word_t digitshincr; // increment for digitshifted.
359 + int offset; // in PIndex, or a bitmap subexpanse.
360 + int numJPs; // number non-null in a BranchU.
361 + bool_t retval; // to return from this func.
362 +JUDYLCODE(Pjv_t PjvRaw); // destination value area.
363 +JUDYLCODE(Pjv_t Pjv);
364 +
365 +
366 +// MACROS FOR COMMON CODE:
367 +//
368 +// Note: These use function and local parameters from the context.
369 +// Note: Assume newly allocated memory is zeroed.
370 +
371 +// Indicate whether a sorted list of indexes in PIndex, based on the first and
372 +// last indexes in the list using pop1, are in the same subexpanse between
373 +// Level and L_evel:
374 +//
375 +// This can be confusing! Note that SAMESUBEXP(L) == TRUE means the indexes
376 +// are the same through level L + 1, and it says nothing about level L and
377 +// lower; they might be the same or they might differ.
378 +//
379 +// Note: In principle SAMESUBEXP needs a mask for the digits from Level,
380 +// inclusive, to L_evel, exclusive. But in practice, since the indexes are all
381 +// known to be identical above Level, it just uses a mask for the digits
382 +// through L_evel + 1; see subexp_mask[].
383 +
384 +#define SAMESUBEXP(L_evel) \
385 + (! ((PIndex[0] ^ PIndex[pop1 - 1]) & subexp_mask[L_evel]))
386 +
387 +// Set PjpParent to a null JP appropriate for the level of the node to which it
388 +// points, which is 1 less than the level of the node in which the JP resides,
389 +// which is by definition Level:
390 +//
391 +// Note: This can set the JPMs JP to an invalid jp_Type, but it doesnt
392 +// matter because the JPM is deleted by the caller.
393 +
394 +#define SETJPNULL_PARENT \
395 + JU_JPSETADT(PjpParent, 0, 0, cJU_JPNULL1 + Level - 1);
396 +
397 +// Variation to set a specified JP (in a branch being built) to a precomputed
398 +// null JP:
399 +
400 +#define SETJPNULL(Pjp) *(Pjp) = JPnull
401 +
402 +// Handle complete (as opposed to partial) memory allocation failure: Set the
403 +// parent JP to an appropriate null type (to leave a consistent tree), zero the
404 +// callers population count, and return FALSE:
405 +//
406 +// Note: At Level == cJU_ROOTSTATE this sets the JPMs JPs jp_Type to a bogus
407 +// value, but it doesnt matter because the JPM should be deleted by the
408 +// caller.
409 +
410 +#define NOMEM { SETJPNULL_PARENT; *PPop1 = 0; return(FALSE); }
411 +
412 +// Allocate a Leaf1-N and save the address in Pjll; in case of failure, NOMEM:
413 +
414 +#define ALLOCLEAF(AllocLeaf) \
415 + if ((PjllRaw = AllocLeaf(pop1, Pjpm)) == (Pjll_t) NULL) NOMEM; \
416 + Pjll = P_JLL(PjllRaw);
417 +
418 +// Copy indexes smaller than words (and values which are whole words) from
419 +// given arrays to immediate indexes or a leaf:
420 +//
421 +// TBD: These macros overlap with some of the code in JudyCascade.c; do some
422 +// merging? That file has functions while these are macros.
423 +
424 +#define COPYTOLEAF_EVEN_SUB(Pjll,LeafType) \
425 + { \
426 + LeafType * P_leaf = (LeafType *) (Pjll); \
427 + Word_t p_op1 = pop1; \
428 + PWord_t P_Index = PIndex; \
429 + \
430 + assert(pop1 > 0); \
431 + \
432 + do { *P_leaf++ = *P_Index++; /* truncates */\
433 + } while (--(p_op1)); \
434 + }
435 +
436 +#define COPYTOLEAF_ODD_SUB(cLevel,Pjll,Copy) \
437 + { \
438 + uint8_t * P_leaf = (uint8_t *) (Pjll); \
439 + Word_t p_op1 = pop1; \
440 + PWord_t P_Index = PIndex; \
441 + \
442 + assert(pop1 > 0); \
443 + \
444 + do { \
445 + Copy(P_leaf, *P_Index); \
446 + P_leaf += (cLevel); ++P_Index; \
447 + } while (--(p_op1)); \
448 + }
449 +
450 +#ifdef JUDY1
451 +
452 +#define COPYTOLEAF_EVEN(Pjll,LeafType) COPYTOLEAF_EVEN_SUB(Pjll,LeafType)
453 +#define COPYTOLEAF_ODD(cLevel,Pjll,Copy) COPYTOLEAF_ODD_SUB(cLevel,Pjll,Copy)
454 +
455 +#else // JUDYL adds copying of values:
456 +
457 +#define COPYTOLEAF_EVEN(Pjll,LeafType) \
458 + { \
459 + COPYTOLEAF_EVEN_SUB(Pjll,LeafType) \
460 + JU_COPYMEM(Pjv, PValue, pop1); \
461 + }
462 +
463 +#define COPYTOLEAF_ODD(cLevel,Pjll,Copy) \
464 + { \
465 + COPYTOLEAF_ODD_SUB( cLevel,Pjll,Copy) \
466 + JU_COPYMEM(Pjv, PValue, pop1); \
467 + }
468 +
469 +#endif
470 +
471 +// Set the JP type for an immediate index, where BaseJPType is JPIMMED_*_02:
472 +
473 +#define SETIMMTYPE(BaseJPType) (PjpParent->jp_Type) = (BaseJPType) + pop1 - 2
474 +
475 +// Allocate and populate a Leaf1-N:
476 +//
477 +// Build MAKELEAF_EVEN() and MAKELEAF_ODD() using macros for common code.
478 +
479 +#define MAKELEAF_SUB1(AllocLeaf,ValueArea,LeafType) \
480 + ALLOCLEAF(AllocLeaf); \
481 + JUDYLCODE(Pjv = ValueArea(Pjll, pop1))
482 +
483 +
484 +#define MAKELEAF_SUB2(cLevel,JPType) \
485 +{ \
486 + Word_t D_cdP0; \
487 + assert(pop1 - 1 <= cJU_POP0MASK(cLevel)); \
488 + D_cdP0 = (*PIndex & cJU_DCDMASK(cLevel)) | (pop1 - 1); \
489 + JU_JPSETADT(PjpParent, (Word_t)PjllRaw, D_cdP0, JPType); \
490 +}
491 +
492 +
493 +#define MAKELEAF_EVEN(cLevel,JPType,AllocLeaf,ValueArea,LeafType) \
494 + MAKELEAF_SUB1(AllocLeaf,ValueArea,LeafType); \
495 + COPYTOLEAF_EVEN(Pjll, LeafType); \
496 + MAKELEAF_SUB2(cLevel, JPType)
497 +
498 +#define MAKELEAF_ODD(cLevel,JPType,AllocLeaf,ValueArea,Copy) \
499 + MAKELEAF_SUB1(AllocLeaf,ValueArea,LeafType); \
500 + COPYTOLEAF_ODD(cLevel, Pjll, Copy); \
501 + MAKELEAF_SUB2(cLevel, JPType)
502 +
503 +// Ensure that the indexes to be stored in immediate indexes or a leaf are
504 +// sorted:
505 +//
506 +// This check is pure overhead, but required in order to protect the Judy array
507 +// against caller error, to avoid a later corruption or core dump from a
508 +// seemingly valid Judy array. Do this check piecemeal at the leaf level while
509 +// the indexes are already in the cache. Higher-level order-checking occurs
510 +// while building branches.
511 +//
512 +// Note: Any sorting error in the expanse of a single immediate indexes JP or
513 +// a leaf => save no indexes in that expanse.
514 +
515 +#define CHECKLEAFORDER \
516 + { \
517 + for (offset = 1; offset < pop1; ++offset) \
518 + { \
519 + if (PIndex[offset - 1] >= PIndex[offset]) \
520 + { \
521 + SETJPNULL_PARENT; \
522 + *PPop1 = 0; \
523 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_UNSORTED); \
524 + return(FALSE); \
525 + } \
526 + } \
527 + }
528 +
529 +
530 +// ------ START OF CODE ------
531 +
532 + assert( Level >= 1);
533 + assert( Level <= cJU_ROOTSTATE);
534 + assert((Level < cJU_ROOTSTATE) || (pop1 > cJU_LEAFW_MAXPOP1));
535 +
536 +
537 +// CHECK FOR TOP LEVEL:
538 +//
539 +// Special case: If at the top level (PjpParent is in the JPM), a top-level
540 +// branch must be created, even if its a BranchL with just one JP. (The JPM
541 +// cannot point to a leaf because the leaf would have to be a lower-level,
542 +// higher-capacity leaf under a narrow pointer (otherwise a root-level leaf
543 +// would suffice), and the JPMs JP cant handle a narrow pointer because the
544 +// jp_DcdPopO field isnt big enough.) Otherwise continue to check for a pop1
545 +// small enough to support immediate indexes or a leaf before giving up and
546 +// making a lower-level branch.
547 +
548 + if (Level == cJU_ROOTSTATE)
549 + {
550 + levelsub = cJU_ROOTSTATE;
551 + goto BuildBranch2;
552 + }
553 + assert(Level < cJU_ROOTSTATE);
554 +
555 +
556 +// SKIP JPIMMED_*_01:
557 +//
558 +// Immeds with pop1 == 1 should be handled in-line during branch construction.
559 +
560 + assert(pop1 > 1);
561 +
562 +
563 +// BUILD JPIMMED_*_02+:
564 +//
565 +// The starting address of the indexes depends on Judy1 or JudyL; also, JudyL
566 +// includes a pointer to a values-only leaf.
567 +
568 + if (pop1 <= immed_maxpop1[Level]) // note: always < root level.
569 + {
570 + JUDY1CODE(uint8_t * Pjll = (uint8_t *) (PjpParent->jp_1Index);)
571 + JUDYLCODE(uint8_t * Pjll = (uint8_t *) (PjpParent->jp_LIndex);)
572 +
573 + CHECKLEAFORDER; // indexes to be stored are sorted.
574 +
575 +#ifdef JUDYL
576 + if ((PjvRaw = j__udyLAllocJV(pop1, Pjpm)) == (Pjv_t) NULL)
577 + NOMEM;
578 + (PjpParent->jp_Addr) = (Word_t) PjvRaw;
579 + Pjv = P_JV(PjvRaw);
580 +#endif
581 +
582 + switch (Level)
583 + {
584 + case 1: COPYTOLEAF_EVEN(Pjll, uint8_t);
585 + SETIMMTYPE(cJU_JPIMMED_1_02);
586 + break;
587 +#if (defined(JUDY1) || defined(JU_64BIT))
588 + case 2: COPYTOLEAF_EVEN(Pjll, uint16_t);
589 + SETIMMTYPE(cJU_JPIMMED_2_02);
590 + break;
591 + case 3: COPYTOLEAF_ODD(3, Pjll, JU_COPY3_LONG_TO_PINDEX);
592 + SETIMMTYPE(cJU_JPIMMED_3_02);
593 + break;
594 +#endif
595 +#if (defined(JUDY1) && defined(JU_64BIT))
596 + case 4: COPYTOLEAF_EVEN(Pjll, uint32_t);
597 + SETIMMTYPE(cJ1_JPIMMED_4_02);
598 + break;
599 + case 5: COPYTOLEAF_ODD(5, Pjll, JU_COPY5_LONG_TO_PINDEX);
600 + SETIMMTYPE(cJ1_JPIMMED_5_02);
601 + break;
602 + case 6: COPYTOLEAF_ODD(6, Pjll, JU_COPY6_LONG_TO_PINDEX);
603 + SETIMMTYPE(cJ1_JPIMMED_6_02);
604 + break;
605 + case 7: COPYTOLEAF_ODD(7, Pjll, JU_COPY7_LONG_TO_PINDEX);
606 + SETIMMTYPE(cJ1_JPIMMED_7_02);
607 + break;
608 +#endif
609 + default: assert(FALSE); // should be impossible.
610 + }
611 +
612 + return(TRUE); // note: no children => no *PPop1 mods.
613 +
614 + } // JPIMMED_*_02+
615 +
616 +
617 +// BUILD JPLEAF*:
618 +//
619 +// This code is a little tricky. The method is: For each level starting at
620 +// the present Level down through levelsub = 1, and then as a special case for
621 +// LeafB1 and FullPop (which are also at levelsub = 1 but have different
622 +// capacity, see later), check if pop1 fits in a leaf (using leaf_maxpop1[])
623 +// at that level. If so, except for Level == levelsub, check if all of the
624 +// current indexes to be stored are in the same (narrow) subexpanse, that is,
625 +// the digits from Level to levelsub + 1, inclusive, are identical between the
626 +// first and last index in the (sorted) list (in PIndex). If this condition is
627 +// satisfied at any level, build a leaf at that level (under a narrow pointer
628 +// if Level > levelsub).
629 +//
630 +// Note: Doing the search in this order results in storing the indexes in
631 +// "least compressed form."
632 +
633 + for (levelsub = Level; levelsub >= 1; --levelsub)
634 + {
635 + Pjll_t PjllRaw;
636 + Pjll_t Pjll;
637 +
638 +// Check if pop1 is too large to fit in a leaf at levelsub; if so, try the next
639 +// lower level:
640 +
641 + if (pop1 > leaf_maxpop1[levelsub]) continue;
642 +
643 +// If pop1 fits in a leaf at levelsub, but levelsub is lower than Level, must
644 +// also check whether all the indexes in the expanse to store can in fact be
645 +// placed under a narrow pointer; if not, a leaf cannot be used, at this or any
646 +// lower level (levelsub):
647 +
648 + if ((levelsub < Level) && (! SAMESUBEXP(levelsub)))
649 + goto BuildBranch; // cant use a narrow, need a branch.
650 +
651 +// Ensure valid pop1 and all indexes are in fact common through Level:
652 +
653 + assert(pop1 <= cJU_POP0MASK(Level) + 1);
654 + assert(! ((PIndex[0] ^ PIndex[pop1 - 1]) & cJU_DCDMASK(Level)));
655 +
656 + CHECKLEAFORDER; // indexes to be stored are sorted.
657 +
658 +// Build correct type of leaf:
659 +//
660 +// Note: The jp_DcdPopO and jp_Type assignments in MAKELEAF_* happen correctly
661 +// for the levelsub (not Level) of the new leaf, even if its under a narrow
662 +// pointer.
663 +
664 + switch (levelsub)
665 + {
666 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
667 + case 1: MAKELEAF_EVEN(1, cJU_JPLEAF1, j__udyAllocJLL1,
668 + JL_LEAF1VALUEAREA, uint8_t);
669 + break;
670 +#endif
671 + case 2: MAKELEAF_EVEN(2, cJU_JPLEAF2, j__udyAllocJLL2,
672 + JL_LEAF2VALUEAREA, uint16_t);
673 + break;
674 + case 3: MAKELEAF_ODD( 3, cJU_JPLEAF3, j__udyAllocJLL3,
675 + JL_LEAF3VALUEAREA, JU_COPY3_LONG_TO_PINDEX);
676 + break;
677 +#ifdef JU_64BIT
678 + case 4: MAKELEAF_EVEN(4, cJU_JPLEAF4, j__udyAllocJLL4,
679 + JL_LEAF4VALUEAREA, uint32_t);
680 + break;
681 + case 5: MAKELEAF_ODD( 5, cJU_JPLEAF5, j__udyAllocJLL5,
682 + JL_LEAF5VALUEAREA, JU_COPY5_LONG_TO_PINDEX);
683 + break;
684 + case 6: MAKELEAF_ODD( 6, cJU_JPLEAF6, j__udyAllocJLL6,
685 + JL_LEAF6VALUEAREA, JU_COPY6_LONG_TO_PINDEX);
686 + break;
687 + case 7: MAKELEAF_ODD( 7, cJU_JPLEAF7, j__udyAllocJLL7,
688 + JL_LEAF7VALUEAREA, JU_COPY7_LONG_TO_PINDEX);
689 + break;
690 +#endif
691 + default: assert(FALSE); // should be impossible.
692 + }
693 +
694 + return(TRUE); // note: no children => no *PPop1 mods.
695 +
696 + } // JPLEAF*
697 +
698 +
699 +// BUILD JPLEAF_B1 OR JPFULLPOPU1:
700 +//
701 +// See above about JPLEAF*. If pop1 doesnt fit in any level of linear leaf,
702 +// it might still fit in a LeafB1 or FullPop, perhaps under a narrow pointer.
703 +
704 + if ((Level == 1) || SAMESUBEXP(1)) // same until last digit.
705 + {
706 + Pjlb_t PjlbRaw; // for bitmap leaf.
707 + Pjlb_t Pjlb;
708 +
709 + assert(pop1 <= cJU_JPFULLPOPU1_POP0 + 1);
710 + CHECKLEAFORDER; // indexes to be stored are sorted.
711 +
712 +#ifdef JUDY1
713 +
714 +// JPFULLPOPU1:
715 +
716 + if (pop1 == cJU_JPFULLPOPU1_POP0 + 1)
717 + {
718 + Word_t Addr = PjpParent->jp_Addr;
719 + Word_t DcdP0 = (*PIndex & cJU_DCDMASK(1))
720 + | cJU_JPFULLPOPU1_POP0;
721 + JU_JPSETADT(PjpParent, Addr, DcdP0, cJ1_JPFULLPOPU1);
722 +
723 + return(TRUE);
724 + }
725 +#endif
726 +
727 +// JPLEAF_B1:
728 +
729 + if ((PjlbRaw = j__udyAllocJLB1(Pjpm)) == (Pjlb_t) NULL)
730 + NOMEM;
731 + Pjlb = P_JLB(PjlbRaw);
732 +
733 + for (offset = 0; offset < pop1; ++offset)
734 + JU_BITMAPSETL(Pjlb, PIndex[offset]);
735 +
736 + retval = TRUE; // default.
737 +
738 +#ifdef JUDYL
739 +
740 +// Build subexpanse values-only leaves (LeafVs) under LeafB1:
741 +
742 + for (offset = 0; offset < cJU_NUMSUBEXPL; ++offset)
743 + {
744 + if (! (pop1sub = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, offset))))
745 + continue; // skip empty subexpanse.
746 +
747 +// Allocate one LeafV = JP subarray; if out of memory, clear bitmaps for higher
748 +// subexpanses and adjust *PPop1:
749 +
750 + if ((PjvRaw = j__udyLAllocJV(pop1sub, Pjpm))
751 + == (Pjv_t) NULL)
752 + {
753 + for (/* null */; offset < cJU_NUMSUBEXPL; ++offset)
754 + {
755 + *PPop1 -= j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, offset));
756 + JU_JLB_BITMAP(Pjlb, offset) = 0;
757 + }
758 +
759 + retval = FALSE;
760 + break;
761 + }
762 +
763 +// Populate values-only leaf and save the pointer to it:
764 +
765 + Pjv = P_JV(PjvRaw);
766 + JU_COPYMEM(Pjv, PValue, pop1sub);
767 + JL_JLB_PVALUE(Pjlb, offset) = PjvRaw; // first-tier pointer.
768 + PValue += pop1sub;
769 +
770 + } // for each subexpanse
771 +
772 +#endif // JUDYL
773 +
774 +// Attach new LeafB1 to parent JP; note use of *PPop1 possibly < pop1:
775 +
776 + JU_JPSETADT(PjpParent, (Word_t) PjlbRaw,
777 + (*PIndex & cJU_DCDMASK(1)) | (*PPop1 - 1), cJU_JPLEAF_B1);
778 +
779 + return(retval);
780 +
781 + } // JPLEAF_B1 or JPFULLPOPU1
782 +
783 +
784 +// BUILD JPBRANCH_U*:
785 +//
786 +// Arriving at BuildBranch means Level < top level but the pop1 is too large
787 +// for immediate indexes or a leaf, even under a narrow pointer, including a
788 +// LeafB1 or FullPop at level 1. This implies SAMESUBEXP(1) == FALSE, that is,
789 +// the indexes to be stored "branch" at level 2 or higher.
790 +
791 +BuildBranch: // come here directly if a leaf wont work.
792 +
793 + assert(Level >= 2);
794 + assert(Level < cJU_ROOTSTATE);
795 + assert(! SAMESUBEXP(1)); // sanity check, see above.
796 +
797 +// Determine the appropriate level for a new branch node; see if a narrow
798 +// pointer can be used:
799 +//
800 +// This can be confusing. The branch is required at the lowest level L where
801 +// the indexes to store are not in the same subexpanse at level L-1. Work down
802 +// from Level to tree level 3, which is 1 above the lowest tree level = 2 at
803 +// which a branch can be used. Theres no need to check SAMESUBEXP at level 2
804 +// because its known to be false at level 2-1 = 1.
805 +//
806 +// Note: Unlike for a leaf node, a narrow pointer is always used for a branch
807 +// if possible, that is, maximum compression is always used, except at the top
808 +// level of the tree, where a JPM cannot support a narrow pointer, meaning a
809 +// top BranchL can have a single JP (fanout = 1); but that case jumps directly
810 +// to BuildBranch2.
811 +//
812 +// Note: For 32-bit systems the only usable values for a narrow pointer are
813 +// Level = 3 and levelsub = 2; 64-bit systems have many more choices; but
814 +// hopefully this for-loop is fast enough even on a 32-bit system.
815 +//
816 +// TBD: If not fast enough, #ifdef JU_64BIT and handle the 32-bit case faster.
817 +
818 + for (levelsub = Level; levelsub >= 3; --levelsub) // see above.
819 + if (! SAMESUBEXP(levelsub - 1)) // at limit of narrow pointer.
820 + break; // put branch at levelsub.
821 +
822 +BuildBranch2: // come here directly for Level = levelsub = cJU_ROOTSTATE.
823 +
824 + assert(levelsub >= 2);
825 + assert(levelsub <= Level);
826 +
827 +// Initially build a BranchU:
828 +//
829 +// Always start with a BranchU because the number of populated subexpanses is
830 +// not yet known. Use digitmask, digitshifted, and digitshincr to avoid
831 +// expensive variable shifts within JU_DIGITATSTATE within the loop.
832 +//
833 +// TBD: The use of digitmask, etc. results in more increment operations per
834 +// loop, is there an even faster way?
835 +//
836 +// TBD: Would it pay to pre-count the populated JPs (subexpanses) and
837 +// pre-compress the branch, that is, build a BranchL or BranchB immediately,
838 +// also taking account of opportunistic uncompression rules? Probably not
839 +// because at high levels of the tree there might be huge numbers of indexes
840 +// (hence cache lines) to scan in the PIndex array to determine the fanout
841 +// (number of JPs) needed.
842 +
843 + if ((PjbuRaw = j__udyAllocJBU(Pjpm)) == (Pjbu_t) NULL) NOMEM;
844 + Pjbu = P_JBU(PjbuRaw);
845 +
846 + JPtype_null = cJU_JPNULL1 + levelsub - 2; // in new BranchU.
847 + JU_JPSETADT(&JPnull, 0, 0, JPtype_null);
848 +
849 + Pjp = Pjbu->jbu_jp; // for convenience in loop.
850 + numJPs = 0; // non-null in the BranchU.
851 + digitmask = cJU_MASKATSTATE(levelsub); // see above.
852 + digitshincr = 1UL << (cJU_BITSPERBYTE * (levelsub - 1));
853 + retval = TRUE;
854 +
855 +// Scan and populate JPs (subexpanses):
856 +//
857 +// Look for all indexes matching each digit in the BranchU (at the correct
858 +// levelsub), and meanwhile notice any sorting error. Increment PIndex (and
859 +// PValue) and reduce pop1 for each subexpanse handled successfully.
860 +
861 + for (digit = digitshifted = 0;
862 + digit < cJU_BRANCHUNUMJPS;
863 + ++digit, digitshifted += digitshincr, ++Pjp)
864 + {
865 + DBGCODE(Word_t pop1subprev;)
866 + assert(pop1 != 0); // end of indexes is handled elsewhere.
867 +
868 +// Count indexes in digits subexpanse:
869 +
870 + for (pop1sub = 0; pop1sub < pop1; ++pop1sub)
871 + if (digitshifted != (PIndex[pop1sub] & digitmask)) break;
872 +
873 +// Empty subexpanse (typical, performance path) or sorting error (rare):
874 +
875 + if (pop1sub == 0)
876 + {
877 + if (digitshifted < (PIndex[0] & digitmask))
878 + { SETJPNULL(Pjp); continue; } // empty subexpanse.
879 +
880 + assert(pop1 < *PPop1); // did save >= 1 index and decr pop1.
881 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_UNSORTED);
882 + goto AbandonBranch;
883 + }
884 +
885 +// Non-empty subexpanse:
886 +//
887 +// First shortcut by handling pop1sub == 1 (JPIMMED_*_01) inline locally.
888 +
889 + if (pop1sub == 1) // note: can be at root level.
890 + {
891 + Word_t Addr = 0;
892 + JUDYLCODE(Addr = (Word_t) (*PValue++);)
893 + JU_JPSETADT(Pjp, Addr, *PIndex, cJU_JPIMMED_1_01 + levelsub -2);
894 +
895 + ++numJPs;
896 +
897 + if (--pop1) { ++PIndex; continue; } // more indexes to store.
898 +
899 + ++digit; ++Pjp; // skip JP just saved.
900 + goto ClearBranch; // save time.
901 + }
902 +
903 +// Recurse to populate one digits (subexpanses) JP; if successful, skip
904 +// indexes (and values) just stored (performance path), except when expanse is
905 +// completely stored:
906 +
907 + DBGCODE(pop1subprev = pop1sub;)
908 +
909 + if (j__udyInsArray(Pjp, levelsub - 1, &pop1sub, (PWord_t) PIndex,
910 +#ifdef JUDYL
911 + (Pjv_t) PValue,
912 +#endif
913 + Pjpm))
914 + { // complete success.
915 + ++numJPs;
916 + assert(pop1subprev == pop1sub);
917 + assert(pop1 >= pop1sub);
918 +
919 + if ((pop1 -= pop1sub) != 0) // more indexes to store:
920 + {
921 + PIndex += pop1sub; // skip indexes just stored.
922 + JUDYLCODE(PValue += pop1sub;)
923 + continue;
924 + }
925 + // else leave PIndex in BranchUs expanse.
926 +
927 +// No more indexes to store in BranchUs expanse:
928 +
929 + ++digit; ++Pjp; // skip JP just saved.
930 + goto ClearBranch; // save time.
931 + }
932 +
933 +// Handle any error at a lower level of recursion:
934 +//
935 +// In case of partial success, pop1sub != 0, but it was reduced from the value
936 +// passed to j__udyInsArray(); skip this JP later during ClearBranch.
937 +
938 + assert(pop1subprev > pop1sub); // check j__udyInsArray().
939 + assert(pop1 > pop1sub); // check j__udyInsArray().
940 +
941 + if (pop1sub) // partial success.
942 + { ++digit; ++Pjp; ++numJPs; } // skip JP just saved.
943 +
944 + pop1 -= pop1sub; // deduct saved indexes if any.
945 +
946 +// Same-level sorting error, or any lower-level error; abandon the rest of the
947 +// branch:
948 +//
949 +// Arrive here with pop1 = remaining unsaved indexes (always non-zero). Adjust
950 +// the *PPop1 value to record and return, modify retval, and use ClearBranch to
951 +// finish up.
952 +
953 +AbandonBranch:
954 + assert(pop1 != 0); // more to store, see above.
955 + assert(pop1 <= *PPop1); // sanity check.
956 +
957 + *PPop1 -= pop1; // deduct unsaved indexes.
958 + pop1 = 0; // to avoid error later.
959 + retval = FALSE;
960 +
961 +// Error (rare), or end of indexes while traversing new BranchU (performance
962 +// path); either way, mark the remaining JPs, if any, in the BranchU as nulls
963 +// and exit the loop:
964 +//
965 +// Arrive here with digit and Pjp set to the first JP to set to null.
966 +
967 +ClearBranch:
968 + for (/* null */; digit < cJU_BRANCHUNUMJPS; ++digit, ++Pjp)
969 + SETJPNULL(Pjp);
970 + break; // saves one more compare.
971 +
972 + } // for each digit
973 +
974 +
975 +// FINISH JPBRANCH_U*:
976 +//
977 +// Arrive here with a BranchU built under Pjbu, numJPs set, and either: retval
978 +// == TRUE and *PPop1 unmodified, or else retval == FALSE, *PPop1 set to the
979 +// actual number of indexes saved (possibly 0 for complete failure at a lower
980 +// level upon the first call of j__udyInsArray()), and the Judy error set in
981 +// Pjpm. Either way, PIndex points to an index within the expanse just
982 +// handled.
983 +
984 + Pjbany = (Word_t) PjbuRaw; // default = use this BranchU.
985 + JPtype = branchU_JPtype[levelsub];
986 +
987 +// Check for complete failure above:
988 +
989 + assert((! retval) || *PPop1); // sanity check.
990 +
991 + if ((! retval) && (*PPop1 == 0)) // nothing stored, full failure.
992 + {
993 + j__udyFreeJBU(PjbuRaw, Pjpm);
994 + SETJPNULL_PARENT;
995 + return(FALSE);
996 + }
997 +
998 +// Complete or partial success so far; watch for sorting error after the
999 +// maximum digit (255) in the BranchU, which is indicated by having more
1000 +// indexes to store in the BranchUs expanse:
1001 +//
1002 +// For example, if an index to store has a digit of 255 at levelsub, followed
1003 +// by an index with a digit of 254, the for-loop above runs out of digits
1004 +// without reducing pop1 to 0.
1005 +
1006 + if (pop1 != 0)
1007 + {
1008 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_UNSORTED);
1009 + *PPop1 -= pop1; // deduct unsaved indexes.
1010 + retval = FALSE;
1011 + }
1012 + assert(*PPop1 != 0); // branch (still) cannot be empty.
1013 +
1014 +
1015 +// OPTIONALLY COMPRESS JPBRANCH_U*:
1016 +//
1017 +// See if the BranchU should be compressed to a BranchL or BranchB; if so, do
1018 +// that and free the BranchU; otherwise just use the existing BranchU. Follow
1019 +// the same rules as in JudyIns.c (version 4.95): Only check local population
1020 +// (cJU_OPP_UNCOMP_POP0) for BranchL, and only check global memory efficiency
1021 +// (JU_OPP_UNCOMPRESS) for BranchB. TBD: Have the rules changed?
1022 +//
1023 +// Note: Because of differing order of operations, the latter compression
1024 +// might not result in the same set of branch nodes as a series of sequential
1025 +// insertions.
1026 +//
1027 +// Note: Allocating a BranchU only to sometimes convert it to a BranchL or
1028 +// BranchB is unfortunate, but attempting to work with a temporary BranchU on
1029 +// the stack and then allocate and keep it as a BranchU in many cases is worse
1030 +// in terms of error handling.
1031 +
1032 +
1033 +// COMPRESS JPBRANCH_U* TO JPBRANCH_L*:
1034 +
1035 + if (numJPs <= cJU_BRANCHLMAXJPS) // JPs fit in a BranchL.
1036 + {
1037 + Pjbl_t PjblRaw = (Pjbl_t) NULL; // new BranchL; init for cc.
1038 + Pjbl_t Pjbl;
1039 +
1040 + if ((*PPop1 > JU_BRANCHL_MAX_POP) // pop too high.
1041 + || ((PjblRaw = j__udyAllocJBL(Pjpm)) == (Pjbl_t) NULL))
1042 + { // cant alloc BranchL.
1043 + goto SetParent; // just keep BranchU.
1044 + }
1045 +
1046 + Pjbl = P_JBL(PjblRaw);
1047 +
1048 +// Copy BranchU JPs to BranchL:
1049 +
1050 + (Pjbl->jbl_NumJPs) = numJPs;
1051 + offset = 0;
1052 +
1053 + for (digit = 0; digit < cJU_BRANCHUNUMJPS; ++digit)
1054 + {
1055 + if ((((Pjbu->jbu_jp) + digit)->jp_Type) == JPtype_null)
1056 + continue;
1057 +
1058 + (Pjbl->jbl_Expanse[offset ]) = digit;
1059 + (Pjbl->jbl_jp [offset++]) = Pjbu->jbu_jp[digit];
1060 + }
1061 + assert(offset == numJPs); // found same number.
1062 +
1063 +// Free the BranchU and prepare to use the new BranchL instead:
1064 +
1065 + j__udyFreeJBU(PjbuRaw, Pjpm);
1066 +
1067 + Pjbany = (Word_t) PjblRaw;
1068 + JPtype = branchL_JPtype[levelsub];
1069 +
1070 + } // compress to BranchL
1071 +
1072 +
1073 +// COMPRESS JPBRANCH_U* TO JPBRANCH_B*:
1074 +//
1075 +// If unable to allocate the BranchB or any JP subarray, free all related
1076 +// memory and just keep the BranchU.
1077 +//
1078 +// Note: This use of JU_OPP_UNCOMPRESS is a bit conservative because the
1079 +// BranchU is already allocated while the (presumably smaller) BranchB is not,
1080 +// the opposite of how its used in single-insert code.
1081 +
1082 + else
1083 + {
1084 + Pjbb_t PjbbRaw = (Pjbb_t) NULL; // new BranchB; init for cc.
1085 + Pjbb_t Pjbb;
1086 + Pjp_t Pjp2; // in BranchU.
1087 +
1088 + if ((*PPop1 > JU_BRANCHB_MAX_POP) // pop too high.
1089 + || ((PjbbRaw = j__udyAllocJBB(Pjpm)) == (Pjbb_t) NULL))
1090 + { // cant alloc BranchB.
1091 + goto SetParent; // just keep BranchU.
1092 + }
1093 +
1094 + Pjbb = P_JBB(PjbbRaw);
1095 +
1096 +// Set bits in bitmap for populated subexpanses:
1097 +
1098 + Pjp2 = Pjbu->jbu_jp;
1099 +
1100 + for (digit = 0; digit < cJU_BRANCHUNUMJPS; ++digit)
1101 + if ((((Pjbu->jbu_jp) + digit)->jp_Type) != JPtype_null)
1102 + JU_BITMAPSETB(Pjbb, digit);
1103 +
1104 +// Copy non-null JPs to BranchB JP subarrays:
1105 +
1106 + for (offset = 0; offset < cJU_NUMSUBEXPB; ++offset)
1107 + {
1108 + Pjp_t PjparrayRaw;
1109 + Pjp_t Pjparray;
1110 +
1111 + if (! (numJPs = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, offset))))
1112 + continue; // skip empty subexpanse.
1113 +
1114 +// If unable to allocate a JP subarray, free all BranchB memory so far and
1115 +// continue to use the BranchU:
1116 +
1117 + if ((PjparrayRaw = j__udyAllocJBBJP(numJPs, Pjpm))
1118 + == (Pjp_t) NULL)
1119 + {
1120 + while (offset-- > 0)
1121 + {
1122 + if (JU_JBB_PJP(Pjbb, offset) == (Pjp_t) NULL) continue;
1123 +
1124 + j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, offset),
1125 + j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, offset)),
1126 + Pjpm);
1127 + }
1128 + j__udyFreeJBB(PjbbRaw, Pjpm);
1129 + goto SetParent; // keep BranchU.
1130 + }
1131 +
1132 +// Set one JP subarray pointer and copy the subexpanses JPs to the subarray:
1133 +//
1134 +// Scan the BranchU for non-null JPs until numJPs JPs are copied.
1135 +
1136 + JU_JBB_PJP(Pjbb, offset) = PjparrayRaw;
1137 + Pjparray = P_JP(PjparrayRaw);
1138 +
1139 + while (numJPs-- > 0)
1140 + {
1141 + while ((Pjp2->jp_Type) == JPtype_null)
1142 + {
1143 + ++Pjp2;
1144 + assert(Pjp2 < (Pjbu->jbu_jp) + cJU_BRANCHUNUMJPS);
1145 + }
1146 + *Pjparray++ = *Pjp2++;
1147 + }
1148 + } // for each subexpanse
1149 +
1150 +// Free the BranchU and prepare to use the new BranchB instead:
1151 +
1152 + j__udyFreeJBU(PjbuRaw, Pjpm);
1153 +
1154 + Pjbany = (Word_t) PjbbRaw;
1155 + JPtype = branchB_JPtype[levelsub];
1156 +
1157 + } // compress to BranchB
1158 +
1159 +
1160 +// COMPLETE OR PARTIAL SUCCESS:
1161 +//
1162 +// Attach new branch (under Pjp, with JPtype) to parent JP; note use of *PPop1,
1163 +// possibly reduced due to partial failure.
1164 +
1165 +SetParent:
1166 + (PjpParent->jp_Addr) = Pjbany;
1167 + (PjpParent->jp_Type) = JPtype;
1168 +
1169 + if (Level < cJU_ROOTSTATE) // PjpParent not in JPM:
1170 + {
1171 + Word_t DcdP0 = (*PIndex & cJU_DCDMASK(levelsub)) | (*PPop1 - 1);
1172 +
1173 + JU_JPSETADT(PjpParent ,Pjbany, DcdP0, JPtype);
1174 + }
1175 +
1176 + return(retval);
1177 +
1178 +} // j__udyInsArray()
libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c new
+135
@@ -0,0 +1,135 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.17 $ $Source: /judy/src/JudyCommon/JudyInsertBranch.c $
19 +
20 +// BranchL insertion functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +extern int j__udyCreateBranchL(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
36 +
37 +
38 +// ****************************************************************************
39 +// __ J U D Y I N S E R T B R A N C H
40 +//
41 +// Insert 2-element BranchL in between Pjp and Pjp->jp_Addr.
42 +//
43 +// Return -1 if out of memory, otherwise return 1.
44 +
45 +FUNCTION int j__udyInsertBranch(
46 + Pjp_t Pjp, // JP containing narrow pointer.
47 + Word_t Index, // outlier to Pjp.
48 + Word_t BranchLevel, // of what JP points to, mapped from JP type.
49 + Pjpm_t Pjpm) // for global accounting.
50 +{
51 + jp_t JP2 [2];
52 + jp_t JP;
53 + Pjp_t PjpNull;
54 + Word_t XorExp;
55 + Word_t Inew, Iold;
56 + Word_t DCDMask; // initially for original BranchLevel.
57 + int Ret;
58 + uint8_t Exp2[2];
59 + uint8_t DecodeByteN, DecodeByteO;
60 +
61 +// Get the current mask for the DCD digits:
62 +
63 + DCDMask = cJU_DCDMASK(BranchLevel);
64 +
65 +// Obtain Dcd bits that differ between Index and JP, shifted so the
66 +// digit for BranchLevel is the LSB:
67 +
68 + XorExp = ((Index ^ JU_JPDCDPOP0(Pjp)) & (cJU_ALLONES >> cJU_BITSPERBYTE))
69 + >> (BranchLevel * cJU_BITSPERBYTE);
70 + assert(XorExp); // Index must be an outlier.
71 +
72 +// Count levels between object under narrow pointer and the level at which
73 +// the outlier diverges from it, which is always at least initial
74 +// BranchLevel + 1, to end up with the level (JP type) at which to insert
75 +// the new intervening BranchL:
76 +
77 + do { ++BranchLevel; } while ((XorExp >>= cJU_BITSPERBYTE));
78 + assert((BranchLevel > 1) && (BranchLevel < cJU_ROOTSTATE));
79 +
80 +// Get the MSB (highest digit) that differs between the old expanse and
81 +// the new Index to insert:
82 +
83 + DecodeByteO = JU_DIGITATSTATE(JU_JPDCDPOP0(Pjp), BranchLevel);
84 + DecodeByteN = JU_DIGITATSTATE(Index, BranchLevel);
85 +
86 + assert(DecodeByteO != DecodeByteN);
87 +
88 +// Determine sorted order for old expanse and new Index digits:
89 +
90 + if (DecodeByteN > DecodeByteO) { Iold = 0; Inew = 1; }
91 + else { Iold = 1; Inew = 0; }
92 +
93 +// Copy old JP into staging area for new Branch
94 + JP2 [Iold] = *Pjp;
95 + Exp2[Iold] = DecodeByteO;
96 + Exp2[Inew] = DecodeByteN;
97 +
98 +// Create a 2 Expanse Linear branch
99 +//
100 +// Note: Pjp->jp_Addr is set by j__udyCreateBranchL()
101 +
102 + Ret = j__udyCreateBranchL(Pjp, JP2, Exp2, 2, Pjpm);
103 + if (Ret == -1) return(-1);
104 +
105 +// Get Pjp to the NULL of where to do insert
106 + PjpNull = ((P_JBL(Pjp->jp_Addr))->jbl_jp) + Inew;
107 +
108 +// Convert to a cJU_JPIMMED_*_01 at the correct level:
109 +// Build JP and set type below to: cJU_JPIMMED_X_01
110 + JU_JPSETADT(PjpNull, 0, Index, cJU_JPIMMED_1_01 - 2 + BranchLevel);
111 +
112 +// Return pointer to Value area in cJU_JPIMMED_X_01
113 + JUDYLCODE(Pjpm->jpm_PValue = (Pjv_t) PjpNull;)
114 +
115 +// The old JP now points to a BranchL that is at higher level. Therefore
116 +// it contains excess DCD bits (in the least significant position) that
117 +// must be removed (zeroed); that is, they become part of the Pop0
118 +// subfield. Note that the remaining (lower) bytes in the Pop0 field do
119 +// not change.
120 +//
121 +// Take from the old DCDMask, which went "down" to a lower BranchLevel,
122 +// and zero any high bits that are still in the mask at the new, higher
123 +// BranchLevel; then use this mask to zero the bits in jp_DcdPopO:
124 +
125 +// Set old JP to a BranchL at correct level
126 +
127 + Pjp->jp_Type = cJU_JPBRANCH_L2 - 2 + BranchLevel;
128 + DCDMask ^= cJU_DCDMASK(BranchLevel);
129 + DCDMask = ~DCDMask & JU_JPDCDPOP0(Pjp);
130 + JP = *Pjp;
131 + JU_JPSETADT(Pjp, JP.jp_Addr, DCDMask, JP.jp_Type);
132 +
133 + return(1);
134 +
135 +} // j__udyInsertBranch()
libnetdata/libjudy/src/JudyL/JudyLMallocIF.c new
+782
@@ -0,0 +1,782 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.45 $ $Source: /judy/src/JudyCommon/JudyMallocIF.c $
19 +//
20 +// Judy malloc/free interface functions for Judy1 and JudyL.
21 +//
22 +// Compile with one of -DJUDY1 or -DJUDYL.
23 +//
24 +// Compile with -DTRACEMI (Malloc Interface) to turn on tracing of malloc/free
25 +// calls at the interface level. (See also TRACEMF in lower-level code.)
26 +// Use -DTRACEMI2 for a terser format suitable for trace analysis.
27 +//
28 +// There can be malloc namespace bits in the LSBs of "raw" addresses from most,
29 +// but not all, of the j__udy*Alloc*() functions; see also JudyPrivate.h. To
30 +// test the Judy code, compile this file with -DMALLOCBITS and use debug flavor
31 +// only (for assertions). This test ensures that (a) all callers properly mask
32 +// the namespace bits out before dereferencing a pointer (or else a core dump
33 +// occurs), and (b) all callers send "raw" (unmasked) addresses to
34 +// j__udy*Free*() calls.
35 +//
36 +// Note: Currently -DDEBUG turns on MALLOCBITS automatically.
37 +
38 +#if (! (defined(JUDY1) || defined(JUDYL)))
39 +#error: One of -DJUDY1 or -DJUDYL must be specified.
40 +#endif
41 +
42 +#ifdef JUDY1
43 +#include "Judy1.h"
44 +#else
45 +#include "JudyL.h"
46 +#endif
47 +
48 +#include "JudyPrivate1L.h"
49 +
50 +// Set "hidden" global j__uMaxWords to the maximum number of words to allocate
51 +// to any one array (large enough to have a JPM, otherwise j__uMaxWords is
52 +// ignored), to trigger a fake malloc error when the number is exceeded. Note,
53 +// this code is always executed, not #ifdefd, because its virtually free.
54 +//
55 +// Note: To keep the MALLOC macro faster and simpler, set j__uMaxWords to
56 +// MAXINT, not zero, by default.
57 +
58 +Word_t j__uMaxWords = ~0UL;
59 +
60 +// This macro hides the faking of a malloc failure:
61 +//
62 +// Note: To keep this fast, just compare WordsPrev to j__uMaxWords without the
63 +// complexity of first adding WordsNow, meaning the trigger point is not
64 +// exactly where you might assume, but it shouldnt matter.
65 +
66 +#define MALLOC(MallocFunc,WordsPrev,WordsNow) \
67 + (((WordsPrev) > j__uMaxWords) ? 0UL : MallocFunc(WordsNow))
68 +
69 +// Clear words starting at address:
70 +//
71 +// Note: Only use this for objects that care; in other cases, it doesnt
72 +// matter if the objects memory is pre-zeroed.
73 +
74 +#define ZEROWORDS(Addr,Words) \
75 + { \
76 + Word_t Words__ = (Words); \
77 + PWord_t Addr__ = (PWord_t) (Addr); \
78 + while (Words__--) *Addr__++ = 0UL; \
79 + }
80 +
81 +#ifdef TRACEMI
82 +
83 +// TRACING SUPPORT:
84 +//
85 +// Note: For TRACEMI, use a format for address printing compatible with other
86 +// tracing facilities; in particular, %x not %lx, to truncate the "noisy" high
87 +// part on 64-bit systems.
88 +//
89 +// TBD: The trace macros need fixing for alternate address types.
90 +//
91 +// Note: TRACEMI2 supports trace analysis no matter the underlying malloc/free
92 +// engine used.
93 +
94 +#include <stdio.h>
95 +
96 +static Word_t j__udyMemSequence = 0L; // event sequence number.
97 +
98 +#define TRACE_ALLOC5(a,b,c,d,e) (void) printf(a, (b), c, d)
99 +#define TRACE_FREE5( a,b,c,d,e) (void) printf(a, (b), c, d)
100 +#define TRACE_ALLOC6(a,b,c,d,e,f) (void) printf(a, (b), c, d, e)
101 +#define TRACE_FREE6( a,b,c,d,e,f) (void) printf(a, (b), c, d, e)
102 +
103 +#else
104 +
105 +#ifdef TRACEMI2
106 +
107 +#include <stdio.h>
108 +
109 +#define b_pw cJU_BYTESPERWORD
110 +
111 +#define TRACE_ALLOC5(a,b,c,d,e) \
112 + (void) printf("a %lx %lx %lx\n", (b), (d) * b_pw, e)
113 +#define TRACE_FREE5( a,b,c,d,e) \
114 + (void) printf("f %lx %lx %lx\n", (b), (d) * b_pw, e)
115 +#define TRACE_ALLOC6(a,b,c,d,e,f) \
116 + (void) printf("a %lx %lx %lx\n", (b), (e) * b_pw, f)
117 +#define TRACE_FREE6( a,b,c,d,e,f) \
118 + (void) printf("f %lx %lx %lx\n", (b), (e) * b_pw, f)
119 +
120 +static Word_t j__udyMemSequence = 0L; // event sequence number.
121 +
122 +#else
123 +
124 +#define TRACE_ALLOC5(a,b,c,d,e) // null.
125 +#define TRACE_FREE5( a,b,c,d,e) // null.
126 +#define TRACE_ALLOC6(a,b,c,d,e,f) // null.
127 +#define TRACE_FREE6( a,b,c,d,e,f) // null.
128 +
129 +#endif // ! TRACEMI2
130 +#endif // ! TRACEMI
131 +
132 +
133 +// MALLOC NAMESPACE SUPPORT:
134 +
135 +#if (defined(DEBUG) && (! defined(MALLOCBITS))) // for now, DEBUG => MALLOCBITS:
136 +#define MALLOCBITS 1
137 +#endif
138 +
139 +#ifdef MALLOCBITS
140 +#define MALLOCBITS_VALUE 0x3 // bit pattern to use.
141 +#define MALLOCBITS_MASK 0x7 // note: matches mask__ in JudyPrivate.h.
142 +
143 +#define MALLOCBITS_SET( Type,Addr) \
144 + ((Addr) = (Type) ((Word_t) (Addr) | MALLOCBITS_VALUE))
145 +#define MALLOCBITS_TEST(Type,Addr) \
146 + assert((((Word_t) (Addr)) & MALLOCBITS_MASK) == MALLOCBITS_VALUE); \
147 + ((Addr) = (Type) ((Word_t) (Addr) & ~MALLOCBITS_VALUE))
148 +#else
149 +#define MALLOCBITS_SET( Type,Addr) // null.
150 +#define MALLOCBITS_TEST(Type,Addr) // null.
151 +#endif
152 +
153 +
154 +// SAVE ERROR INFORMATION IN A Pjpm:
155 +//
156 +// "Small" (invalid) Addr values are used to distinguish overrun and no-mem
157 +// errors. (TBD, non-zero invalid values are no longer returned from
158 +// lower-level functions, that is, JU_ERRNO_OVERRUN is no longer detected.)
159 +
160 +#define J__UDYSETALLOCERROR(Addr) \
161 + { \
162 + JU_ERRID(Pjpm) = __LINE__; \
163 + if ((Word_t) (Addr) > 0) JU_ERRNO(Pjpm) = JU_ERRNO_OVERRUN; \
164 + else JU_ERRNO(Pjpm) = JU_ERRNO_NOMEM; \
165 + return(0); \
166 + }
167 +
168 +
169 +// ****************************************************************************
170 +// ALLOCATION FUNCTIONS:
171 +//
172 +// To help the compiler catch coding errors, each function returns a specific
173 +// object type.
174 +//
175 +// Note: Only j__udyAllocJPM() and j__udyAllocJLW() return multiple values <=
176 +// sizeof(Word_t) to indicate the type of memory allocation failure. Other
177 +// allocation functions convert this failure to a JU_ERRNO.
178 +
179 +
180 +// Note: Unlike other j__udyAlloc*() functions, Pjpms are returned non-raw,
181 +// that is, without malloc namespace or root pointer type bits:
182 +
183 +FUNCTION Pjpm_t j__udyAllocJPM(void)
184 +{
185 + Word_t Words = (sizeof(jpm_t) + cJU_BYTESPERWORD - 1) / cJU_BYTESPERWORD;
186 + Pjpm_t Pjpm = (Pjpm_t) MALLOC(JudyMalloc, Words, Words);
187 +
188 + assert((Words * cJU_BYTESPERWORD) == sizeof(jpm_t));
189 +
190 + if ((Word_t) Pjpm > sizeof(Word_t))
191 + {
192 + ZEROWORDS(Pjpm, Words);
193 + Pjpm->jpm_TotalMemWords = Words;
194 + }
195 +
196 + TRACE_ALLOC5("0x%x %8lu = j__udyAllocJPM(), Words = %lu\n",
197 + Pjpm, j__udyMemSequence++, Words, cJU_LEAFW_MAXPOP1 + 1);
198 + // MALLOCBITS_SET(Pjpm_t, Pjpm); // see above.
199 + return(Pjpm);
200 +
201 +} // j__udyAllocJPM()
202 +
203 +
204 +FUNCTION Pjbl_t j__udyAllocJBL(Pjpm_t Pjpm)
205 +{
206 + Word_t Words = sizeof(jbl_t) / cJU_BYTESPERWORD;
207 + Pjbl_t PjblRaw = (Pjbl_t) MALLOC(JudyMallocVirtual,
208 + Pjpm->jpm_TotalMemWords, Words);
209 +
210 + assert((Words * cJU_BYTESPERWORD) == sizeof(jbl_t));
211 +
212 + if ((Word_t) PjblRaw > sizeof(Word_t))
213 + {
214 + ZEROWORDS(P_JBL(PjblRaw), Words);
215 + Pjpm->jpm_TotalMemWords += Words;
216 + }
217 + else { J__UDYSETALLOCERROR(PjblRaw); }
218 +
219 + TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBL(), Words = %lu\n", PjblRaw,
220 + j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
221 + MALLOCBITS_SET(Pjbl_t, PjblRaw);
222 + return(PjblRaw);
223 +
224 +} // j__udyAllocJBL()
225 +
226 +
227 +FUNCTION Pjbb_t j__udyAllocJBB(Pjpm_t Pjpm)
228 +{
229 + Word_t Words = sizeof(jbb_t) / cJU_BYTESPERWORD;
230 + Pjbb_t PjbbRaw = (Pjbb_t) MALLOC(JudyMallocVirtual,
231 + Pjpm->jpm_TotalMemWords, Words);
232 +
233 + assert((Words * cJU_BYTESPERWORD) == sizeof(jbb_t));
234 +
235 + if ((Word_t) PjbbRaw > sizeof(Word_t))
236 + {
237 + ZEROWORDS(P_JBB(PjbbRaw), Words);
238 + Pjpm->jpm_TotalMemWords += Words;
239 + }
240 + else { J__UDYSETALLOCERROR(PjbbRaw); }
241 +
242 + TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBB(), Words = %lu\n", PjbbRaw,
243 + j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
244 + MALLOCBITS_SET(Pjbb_t, PjbbRaw);
245 + return(PjbbRaw);
246 +
247 +} // j__udyAllocJBB()
248 +
249 +
250 +FUNCTION Pjp_t j__udyAllocJBBJP(Word_t NumJPs, Pjpm_t Pjpm)
251 +{
252 + Word_t Words = JU_BRANCHJP_NUMJPSTOWORDS(NumJPs);
253 + Pjp_t PjpRaw;
254 +
255 + PjpRaw = (Pjp_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
256 +
257 + if ((Word_t) PjpRaw > sizeof(Word_t))
258 + {
259 + Pjpm->jpm_TotalMemWords += Words;
260 + }
261 + else { J__UDYSETALLOCERROR(PjpRaw); }
262 +
263 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJBBJP(%lu), Words = %lu\n", PjpRaw,
264 + j__udyMemSequence++, NumJPs, Words, (Pjpm->jpm_Pop0) + 2);
265 + MALLOCBITS_SET(Pjp_t, PjpRaw);
266 + return(PjpRaw);
267 +
268 +} // j__udyAllocJBBJP()
269 +
270 +
271 +FUNCTION Pjbu_t j__udyAllocJBU(Pjpm_t Pjpm)
272 +{
273 + Word_t Words = sizeof(jbu_t) / cJU_BYTESPERWORD;
274 + Pjbu_t PjbuRaw = (Pjbu_t) MALLOC(JudyMallocVirtual,
275 + Pjpm->jpm_TotalMemWords, Words);
276 +
277 + assert((Words * cJU_BYTESPERWORD) == sizeof(jbu_t));
278 +
279 + if ((Word_t) PjbuRaw > sizeof(Word_t))
280 + {
281 + Pjpm->jpm_TotalMemWords += Words;
282 + }
283 + else { J__UDYSETALLOCERROR(PjbuRaw); }
284 +
285 + TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBU(), Words = %lu\n", PjbuRaw,
286 + j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
287 + MALLOCBITS_SET(Pjbu_t, PjbuRaw);
288 + return(PjbuRaw);
289 +
290 +} // j__udyAllocJBU()
291 +
292 +
293 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
294 +
295 +FUNCTION Pjll_t j__udyAllocJLL1(Word_t Pop1, Pjpm_t Pjpm)
296 +{
297 + Word_t Words = JU_LEAF1POPTOWORDS(Pop1);
298 + Pjll_t PjllRaw;
299 +
300 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
301 +
302 + if ((Word_t) PjllRaw > sizeof(Word_t))
303 + {
304 + Pjpm->jpm_TotalMemWords += Words;
305 + }
306 + else { J__UDYSETALLOCERROR(PjllRaw); }
307 +
308 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL1(%lu), Words = %lu\n", PjllRaw,
309 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
310 + MALLOCBITS_SET(Pjll_t, PjllRaw);
311 + return(PjllRaw);
312 +
313 +} // j__udyAllocJLL1()
314 +
315 +#endif // (JUDYL || (! JU_64BIT))
316 +
317 +
318 +FUNCTION Pjll_t j__udyAllocJLL2(Word_t Pop1, Pjpm_t Pjpm)
319 +{
320 + Word_t Words = JU_LEAF2POPTOWORDS(Pop1);
321 + Pjll_t PjllRaw;
322 +
323 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
324 +
325 + if ((Word_t) PjllRaw > sizeof(Word_t))
326 + {
327 + Pjpm->jpm_TotalMemWords += Words;
328 + }
329 + else { J__UDYSETALLOCERROR(PjllRaw); }
330 +
331 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL2(%lu), Words = %lu\n", PjllRaw,
332 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
333 + MALLOCBITS_SET(Pjll_t, PjllRaw);
334 + return(PjllRaw);
335 +
336 +} // j__udyAllocJLL2()
337 +
338 +
339 +FUNCTION Pjll_t j__udyAllocJLL3(Word_t Pop1, Pjpm_t Pjpm)
340 +{
341 + Word_t Words = JU_LEAF3POPTOWORDS(Pop1);
342 + Pjll_t PjllRaw;
343 +
344 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
345 +
346 + if ((Word_t) PjllRaw > sizeof(Word_t))
347 + {
348 + Pjpm->jpm_TotalMemWords += Words;
349 + }
350 + else { J__UDYSETALLOCERROR(PjllRaw); }
351 +
352 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL3(%lu), Words = %lu\n", PjllRaw,
353 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
354 + MALLOCBITS_SET(Pjll_t, PjllRaw);
355 + return(PjllRaw);
356 +
357 +} // j__udyAllocJLL3()
358 +
359 +
360 +#ifdef JU_64BIT
361 +
362 +FUNCTION Pjll_t j__udyAllocJLL4(Word_t Pop1, Pjpm_t Pjpm)
363 +{
364 + Word_t Words = JU_LEAF4POPTOWORDS(Pop1);
365 + Pjll_t PjllRaw;
366 +
367 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
368 +
369 + if ((Word_t) PjllRaw > sizeof(Word_t))
370 + {
371 + Pjpm->jpm_TotalMemWords += Words;
372 + }
373 + else { J__UDYSETALLOCERROR(PjllRaw); }
374 +
375 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL4(%lu), Words = %lu\n", PjllRaw,
376 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
377 + MALLOCBITS_SET(Pjll_t, PjllRaw);
378 + return(PjllRaw);
379 +
380 +} // j__udyAllocJLL4()
381 +
382 +
383 +FUNCTION Pjll_t j__udyAllocJLL5(Word_t Pop1, Pjpm_t Pjpm)
384 +{
385 + Word_t Words = JU_LEAF5POPTOWORDS(Pop1);
386 + Pjll_t PjllRaw;
387 +
388 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
389 +
390 + if ((Word_t) PjllRaw > sizeof(Word_t))
391 + {
392 + Pjpm->jpm_TotalMemWords += Words;
393 + }
394 + else { J__UDYSETALLOCERROR(PjllRaw); }
395 +
396 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL5(%lu), Words = %lu\n", PjllRaw,
397 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
398 + MALLOCBITS_SET(Pjll_t, PjllRaw);
399 + return(PjllRaw);
400 +
401 +} // j__udyAllocJLL5()
402 +
403 +
404 +FUNCTION Pjll_t j__udyAllocJLL6(Word_t Pop1, Pjpm_t Pjpm)
405 +{
406 + Word_t Words = JU_LEAF6POPTOWORDS(Pop1);
407 + Pjll_t PjllRaw;
408 +
409 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
410 +
411 + if ((Word_t) PjllRaw > sizeof(Word_t))
412 + {
413 + Pjpm->jpm_TotalMemWords += Words;
414 + }
415 + else { J__UDYSETALLOCERROR(PjllRaw); }
416 +
417 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL6(%lu), Words = %lu\n", PjllRaw,
418 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
419 + MALLOCBITS_SET(Pjll_t, PjllRaw);
420 + return(PjllRaw);
421 +
422 +} // j__udyAllocJLL6()
423 +
424 +
425 +FUNCTION Pjll_t j__udyAllocJLL7(Word_t Pop1, Pjpm_t Pjpm)
426 +{
427 + Word_t Words = JU_LEAF7POPTOWORDS(Pop1);
428 + Pjll_t PjllRaw;
429 +
430 + PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
431 +
432 + if ((Word_t) PjllRaw > sizeof(Word_t))
433 + {
434 + Pjpm->jpm_TotalMemWords += Words;
435 + }
436 + else { J__UDYSETALLOCERROR(PjllRaw); }
437 +
438 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL7(%lu), Words = %lu\n", PjllRaw,
439 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
440 + MALLOCBITS_SET(Pjll_t, PjllRaw);
441 + return(PjllRaw);
442 +
443 +} // j__udyAllocJLL7()
444 +
445 +#endif // JU_64BIT
446 +
447 +
448 +// Note: Root-level leaf addresses are always whole words (Pjlw_t), and unlike
449 +// other j__udyAlloc*() functions, they are returned non-raw, that is, without
450 +// malloc namespace or root pointer type bits (the latter are added later by
451 +// the caller):
452 +
453 +FUNCTION Pjlw_t j__udyAllocJLW(Word_t Pop1)
454 +{
455 + Word_t Words = JU_LEAFWPOPTOWORDS(Pop1);
456 + Pjlw_t Pjlw = (Pjlw_t) MALLOC(JudyMalloc, Words, Words);
457 +
458 + TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLW(%lu), Words = %lu\n", Pjlw,
459 + j__udyMemSequence++, Pop1, Words, Pop1);
460 + // MALLOCBITS_SET(Pjlw_t, Pjlw); // see above.
461 + return(Pjlw);
462 +
463 +} // j__udyAllocJLW()
464 +
465 +
466 +FUNCTION Pjlb_t j__udyAllocJLB1(Pjpm_t Pjpm)
467 +{
468 + Word_t Words = sizeof(jlb_t) / cJU_BYTESPERWORD;
469 + Pjlb_t PjlbRaw;
470 +
471 + PjlbRaw = (Pjlb_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
472 +
473 + assert((Words * cJU_BYTESPERWORD) == sizeof(jlb_t));
474 +
475 + if ((Word_t) PjlbRaw > sizeof(Word_t))
476 + {
477 + ZEROWORDS(P_JLB(PjlbRaw), Words);
478 + Pjpm->jpm_TotalMemWords += Words;
479 + }
480 + else { J__UDYSETALLOCERROR(PjlbRaw); }
481 +
482 + TRACE_ALLOC5("0x%x %8lu = j__udyAllocJLB1(), Words = %lu\n", PjlbRaw,
483 + j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
484 + MALLOCBITS_SET(Pjlb_t, PjlbRaw);
485 + return(PjlbRaw);
486 +
487 +} // j__udyAllocJLB1()
488 +
489 +
490 +#ifdef JUDYL
491 +
492 +FUNCTION Pjv_t j__udyLAllocJV(Word_t Pop1, Pjpm_t Pjpm)
493 +{
494 + Word_t Words = JL_LEAFVPOPTOWORDS(Pop1);
495 + Pjv_t PjvRaw;
496 +
497 + PjvRaw = (Pjv_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
498 +
499 + if ((Word_t) PjvRaw > sizeof(Word_t))
500 + {
501 + Pjpm->jpm_TotalMemWords += Words;
502 + }
503 + else { J__UDYSETALLOCERROR(PjvRaw); }
504 +
505 + TRACE_ALLOC6("0x%x %8lu = j__udyLAllocJV(%lu), Words = %lu\n", PjvRaw,
506 + j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
507 + MALLOCBITS_SET(Pjv_t, PjvRaw);
508 + return(PjvRaw);
509 +
510 +} // j__udyLAllocJV()
511 +
512 +#endif // JUDYL
513 +
514 +
515 +// ****************************************************************************
516 +// FREE FUNCTIONS:
517 +//
518 +// To help the compiler catch coding errors, each function takes a specific
519 +// object type to free.
520 +
521 +
522 +// Note: j__udyFreeJPM() receives a root pointer with NO root pointer type
523 +// bits present, that is, they must be stripped by the caller using P_JPM():
524 +
525 +FUNCTION void j__udyFreeJPM(Pjpm_t PjpmFree, Pjpm_t PjpmStats)
526 +{
527 + Word_t Words = (sizeof(jpm_t) + cJU_BYTESPERWORD - 1) / cJU_BYTESPERWORD;
528 +
529 + // MALLOCBITS_TEST(Pjpm_t, PjpmFree); // see above.
530 + JudyFree((Pvoid_t) PjpmFree, Words);
531 +
532 + if (PjpmStats != (Pjpm_t) NULL) PjpmStats->jpm_TotalMemWords -= Words;
533 +
534 +// Note: Log PjpmFree->jpm_Pop0, similar to other j__udyFree*() functions, not
535 +// an assumed value of cJU_LEAFW_MAXPOP1, for when the caller is
536 +// Judy*FreeArray(), jpm_Pop0 is set to 0, and the population after the free
537 +// really will be 0, not cJU_LEAFW_MAXPOP1.
538 +
539 + TRACE_FREE6("0x%x %8lu = j__udyFreeJPM(%lu), Words = %lu\n", PjpmFree,
540 + j__udyMemSequence++, Words, Words, PjpmFree->jpm_Pop0);
541 +
542 +
543 +} // j__udyFreeJPM()
544 +
545 +
546 +FUNCTION void j__udyFreeJBL(Pjbl_t Pjbl, Pjpm_t Pjpm)
547 +{
548 + Word_t Words = sizeof(jbl_t) / cJU_BYTESPERWORD;
549 +
550 + MALLOCBITS_TEST(Pjbl_t, Pjbl);
551 + JudyFreeVirtual((Pvoid_t) Pjbl, Words);
552 +
553 + Pjpm->jpm_TotalMemWords -= Words;
554 +
555 + TRACE_FREE5("0x%x %8lu = j__udyFreeJBL(), Words = %lu\n", Pjbl,
556 + j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
557 +
558 +
559 +} // j__udyFreeJBL()
560 +
561 +
562 +FUNCTION void j__udyFreeJBB(Pjbb_t Pjbb, Pjpm_t Pjpm)
563 +{
564 + Word_t Words = sizeof(jbb_t) / cJU_BYTESPERWORD;
565 +
566 + MALLOCBITS_TEST(Pjbb_t, Pjbb);
567 + JudyFreeVirtual((Pvoid_t) Pjbb, Words);
568 +
569 + Pjpm->jpm_TotalMemWords -= Words;
570 +
571 + TRACE_FREE5("0x%x %8lu = j__udyFreeJBB(), Words = %lu\n", Pjbb,
572 + j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
573 +
574 +
575 +} // j__udyFreeJBB()
576 +
577 +
578 +FUNCTION void j__udyFreeJBBJP(Pjp_t Pjp, Word_t NumJPs, Pjpm_t Pjpm)
579 +{
580 + Word_t Words = JU_BRANCHJP_NUMJPSTOWORDS(NumJPs);
581 +
582 + MALLOCBITS_TEST(Pjp_t, Pjp);
583 + JudyFree((Pvoid_t) Pjp, Words);
584 +
585 + Pjpm->jpm_TotalMemWords -= Words;
586 +
587 + TRACE_FREE6("0x%x %8lu = j__udyFreeJBBJP(%lu), Words = %lu\n", Pjp,
588 + j__udyMemSequence++, NumJPs, Words, Pjpm->jpm_Pop0);
589 +
590 +
591 +} // j__udyFreeJBBJP()
592 +
593 +
594 +FUNCTION void j__udyFreeJBU(Pjbu_t Pjbu, Pjpm_t Pjpm)
595 +{
596 + Word_t Words = sizeof(jbu_t) / cJU_BYTESPERWORD;
597 +
598 + MALLOCBITS_TEST(Pjbu_t, Pjbu);
599 + JudyFreeVirtual((Pvoid_t) Pjbu, Words);
600 +
601 + Pjpm->jpm_TotalMemWords -= Words;
602 +
603 + TRACE_FREE5("0x%x %8lu = j__udyFreeJBU(), Words = %lu\n", Pjbu,
604 + j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
605 +
606 +
607 +} // j__udyFreeJBU()
608 +
609 +
610 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
611 +
612 +FUNCTION void j__udyFreeJLL1(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
613 +{
614 + Word_t Words = JU_LEAF1POPTOWORDS(Pop1);
615 +
616 + MALLOCBITS_TEST(Pjll_t, Pjll);
617 + JudyFree((Pvoid_t) Pjll, Words);
618 +
619 + Pjpm->jpm_TotalMemWords -= Words;
620 +
621 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL1(%lu), Words = %lu\n", Pjll,
622 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
623 +
624 +
625 +} // j__udyFreeJLL1()
626 +
627 +#endif // (JUDYL || (! JU_64BIT))
628 +
629 +
630 +FUNCTION void j__udyFreeJLL2(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
631 +{
632 + Word_t Words = JU_LEAF2POPTOWORDS(Pop1);
633 +
634 + MALLOCBITS_TEST(Pjll_t, Pjll);
635 + JudyFree((Pvoid_t) Pjll, Words);
636 +
637 + Pjpm->jpm_TotalMemWords -= Words;
638 +
639 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL2(%lu), Words = %lu\n", Pjll,
640 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
641 +
642 +
643 +} // j__udyFreeJLL2()
644 +
645 +
646 +FUNCTION void j__udyFreeJLL3(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
647 +{
648 + Word_t Words = JU_LEAF3POPTOWORDS(Pop1);
649 +
650 + MALLOCBITS_TEST(Pjll_t, Pjll);
651 + JudyFree((Pvoid_t) Pjll, Words);
652 +
653 + Pjpm->jpm_TotalMemWords -= Words;
654 +
655 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL3(%lu), Words = %lu\n", Pjll,
656 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
657 +
658 +
659 +} // j__udyFreeJLL3()
660 +
661 +
662 +#ifdef JU_64BIT
663 +
664 +FUNCTION void j__udyFreeJLL4(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
665 +{
666 + Word_t Words = JU_LEAF4POPTOWORDS(Pop1);
667 +
668 + MALLOCBITS_TEST(Pjll_t, Pjll);
669 + JudyFree((Pvoid_t) Pjll, Words);
670 +
671 + Pjpm->jpm_TotalMemWords -= Words;
672 +
673 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL4(%lu), Words = %lu\n", Pjll,
674 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
675 +
676 +
677 +} // j__udyFreeJLL4()
678 +
679 +
680 +FUNCTION void j__udyFreeJLL5(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
681 +{
682 + Word_t Words = JU_LEAF5POPTOWORDS(Pop1);
683 +
684 + MALLOCBITS_TEST(Pjll_t, Pjll);
685 + JudyFree((Pvoid_t) Pjll, Words);
686 +
687 + Pjpm->jpm_TotalMemWords -= Words;
688 +
689 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL5(%lu), Words = %lu\n", Pjll,
690 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
691 +
692 +
693 +} // j__udyFreeJLL5()
694 +
695 +
696 +FUNCTION void j__udyFreeJLL6(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
697 +{
698 + Word_t Words = JU_LEAF6POPTOWORDS(Pop1);
699 +
700 + MALLOCBITS_TEST(Pjll_t, Pjll);
701 + JudyFree((Pvoid_t) Pjll, Words);
702 +
703 + Pjpm->jpm_TotalMemWords -= Words;
704 +
705 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL6(%lu), Words = %lu\n", Pjll,
706 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
707 +
708 +
709 +} // j__udyFreeJLL6()
710 +
711 +
712 +FUNCTION void j__udyFreeJLL7(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
713 +{
714 + Word_t Words = JU_LEAF7POPTOWORDS(Pop1);
715 +
716 + MALLOCBITS_TEST(Pjll_t, Pjll);
717 + JudyFree((Pvoid_t) Pjll, Words);
718 +
719 + Pjpm->jpm_TotalMemWords -= Words;
720 +
721 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLL7(%lu), Words = %lu\n", Pjll,
722 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
723 +
724 +
725 +} // j__udyFreeJLL7()
726 +
727 +#endif // JU_64BIT
728 +
729 +
730 +// Note: j__udyFreeJLW() receives a root pointer with NO root pointer type
731 +// bits present, that is, they are stripped by P_JLW():
732 +
733 +FUNCTION void j__udyFreeJLW(Pjlw_t Pjlw, Word_t Pop1, Pjpm_t Pjpm)
734 +{
735 + Word_t Words = JU_LEAFWPOPTOWORDS(Pop1);
736 +
737 + // MALLOCBITS_TEST(Pjlw_t, Pjlw); // see above.
738 + JudyFree((Pvoid_t) Pjlw, Words);
739 +
740 + if (Pjpm) Pjpm->jpm_TotalMemWords -= Words;
741 +
742 + TRACE_FREE6("0x%x %8lu = j__udyFreeJLW(%lu), Words = %lu\n", Pjlw,
743 + j__udyMemSequence++, Pop1, Words, Pop1 - 1);
744 +
745 +
746 +} // j__udyFreeJLW()
747 +
748 +
749 +FUNCTION void j__udyFreeJLB1(Pjlb_t Pjlb, Pjpm_t Pjpm)
750 +{
751 + Word_t Words = sizeof(jlb_t) / cJU_BYTESPERWORD;
752 +
753 + MALLOCBITS_TEST(Pjlb_t, Pjlb);
754 + JudyFree((Pvoid_t) Pjlb, Words);
755 +
756 + Pjpm->jpm_TotalMemWords -= Words;
757 +
758 + TRACE_FREE5("0x%x %8lu = j__udyFreeJLB1(), Words = %lu\n", Pjlb,
759 + j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
760 +
761 +
762 +} // j__udyFreeJLB1()
763 +
764 +
765 +#ifdef JUDYL
766 +
767 +FUNCTION void j__udyLFreeJV(Pjv_t Pjv, Word_t Pop1, Pjpm_t Pjpm)
768 +{
769 + Word_t Words = JL_LEAFVPOPTOWORDS(Pop1);
770 +
771 + MALLOCBITS_TEST(Pjv_t, Pjv);
772 + JudyFree((Pvoid_t) Pjv, Words);
773 +
774 + Pjpm->jpm_TotalMemWords -= Words;
775 +
776 + TRACE_FREE6("0x%x %8lu = j__udyLFreeJV(%lu), Words = %lu\n", Pjv,
777 + j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
778 +
779 +
780 +} // j__udyLFreeJV()
781 +
782 +#endif // JUDYL
libnetdata/libjudy/src/JudyL/JudyLMemActive.c new
+259
@@ -0,0 +1,259 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.7 $ $Source: /judy/src/JudyCommon/JudyMemActive.c $
19 +//
20 +// Return number of bytes of memory used to support a Judy1/L array.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +FUNCTION static Word_t j__udyGetMemActive(Pjp_t);
36 +
37 +
38 +// ****************************************************************************
39 +// J U D Y 1 M E M A C T I V E
40 +// J U D Y L M E M A C T I V E
41 +
42 +#ifdef JUDY1
43 +FUNCTION Word_t Judy1MemActive
44 +#else
45 +FUNCTION Word_t JudyLMemActive
46 +#endif
47 + (
48 + Pcvoid_t PArray // from which to retrieve.
49 + )
50 +{
51 + if (PArray == (Pcvoid_t)NULL) return(0);
52 +
53 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
54 + {
55 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
56 + Word_t Words = Pjlw[0] + 1; // population.
57 +#ifdef JUDY1
58 + return((Words + 1) * sizeof(Word_t));
59 +#else
60 + return(((Words * 2) + 1) * sizeof(Word_t));
61 +#endif
62 + }
63 + else
64 + {
65 + Pjpm_t Pjpm = P_JPM(PArray);
66 + return(j__udyGetMemActive(&Pjpm->jpm_JP) + sizeof(jpm_t));
67 + }
68 +
69 +} // JudyMemActive()
70 +
71 +
72 +// ****************************************************************************
73 +// __ J U D Y G E T M E M A C T I V E
74 +
75 +FUNCTION static Word_t j__udyGetMemActive(
76 + Pjp_t Pjp) // top of subtree.
77 +{
78 + Word_t offset; // in a branch.
79 + Word_t Bytes = 0; // actual bytes used at this level.
80 + Word_t IdxSz; // bytes per index in leaves
81 +
82 + switch (JU_JPTYPE(Pjp))
83 + {
84 +
85 + case cJU_JPBRANCH_L2:
86 + case cJU_JPBRANCH_L3:
87 +#ifdef JU_64BIT
88 + case cJU_JPBRANCH_L4:
89 + case cJU_JPBRANCH_L5:
90 + case cJU_JPBRANCH_L6:
91 + case cJU_JPBRANCH_L7:
92 +#endif
93 + case cJU_JPBRANCH_L:
94 + {
95 + Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr);
96 +
97 + for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
98 + Bytes += j__udyGetMemActive((Pjbl->jbl_jp) + offset);
99 +
100 + return(Bytes + sizeof(jbl_t));
101 + }
102 +
103 + case cJU_JPBRANCH_B2:
104 + case cJU_JPBRANCH_B3:
105 +#ifdef JU_64BIT
106 + case cJU_JPBRANCH_B4:
107 + case cJU_JPBRANCH_B5:
108 + case cJU_JPBRANCH_B6:
109 + case cJU_JPBRANCH_B7:
110 +#endif
111 + case cJU_JPBRANCH_B:
112 + {
113 + Word_t subexp;
114 + Word_t jpcount;
115 + Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr);
116 +
117 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
118 + {
119 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
120 + Bytes += jpcount * sizeof(jp_t);
121 +
122 + for (offset = 0; offset < jpcount; ++offset)
123 + {
124 + Bytes += j__udyGetMemActive(P_JP(JU_JBB_PJP(Pjbb, subexp))
125 + + offset);
126 + }
127 + }
128 +
129 + return(Bytes + sizeof(jbb_t));
130 + }
131 +
132 + case cJU_JPBRANCH_U2:
133 + case cJU_JPBRANCH_U3:
134 +#ifdef JU_64BIT
135 + case cJU_JPBRANCH_U4:
136 + case cJU_JPBRANCH_U5:
137 + case cJU_JPBRANCH_U6:
138 + case cJU_JPBRANCH_U7:
139 +#endif
140 + case cJU_JPBRANCH_U:
141 + {
142 + Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr);
143 +
144 + for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
145 + {
146 + if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
147 + && ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
148 + {
149 + continue; // skip null JP to save time.
150 + }
151 +
152 + Bytes += j__udyGetMemActive(Pjbu->jbu_jp + offset);
153 + }
154 +
155 + return(Bytes + sizeof(jbu_t));
156 + }
157 +
158 +
159 +// -- Cases below here terminate and do not recurse. --
160 +
161 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
162 + case cJU_JPLEAF1: IdxSz = 1; goto LeafWords;
163 +#endif
164 + case cJU_JPLEAF2: IdxSz = 2; goto LeafWords;
165 + case cJU_JPLEAF3: IdxSz = 3; goto LeafWords;
166 +#ifdef JU_64BIT
167 + case cJU_JPLEAF4: IdxSz = 4; goto LeafWords;
168 + case cJU_JPLEAF5: IdxSz = 5; goto LeafWords;
169 + case cJU_JPLEAF6: IdxSz = 6; goto LeafWords;
170 + case cJU_JPLEAF7: IdxSz = 7; goto LeafWords;
171 +#endif
172 +LeafWords:
173 +
174 +#ifdef JUDY1
175 + return(IdxSz * (JU_JPLEAF_POP0(Pjp) + 1));
176 +#else
177 + return((IdxSz + sizeof(Word_t))
178 + * (JU_JPLEAF_POP0(Pjp) + 1));
179 +#endif
180 + case cJU_JPLEAF_B1:
181 + {
182 +#ifdef JUDY1
183 + return(sizeof(jlb_t));
184 +#else
185 + Bytes = (JU_JPLEAF_POP0(Pjp) + 1) * sizeof(Word_t);
186 +
187 + return(Bytes + sizeof(jlb_t));
188 +#endif
189 + }
190 +
191 + JUDY1CODE(case cJ1_JPFULLPOPU1: return(0);)
192 +
193 +#ifdef JUDY1
194 +#define J__Mpy 0
195 +#else
196 +#define J__Mpy sizeof(Word_t)
197 +#endif
198 +
199 + case cJU_JPIMMED_1_01: return(0);
200 + case cJU_JPIMMED_2_01: return(0);
201 + case cJU_JPIMMED_3_01: return(0);
202 +#ifdef JU_64BIT
203 + case cJU_JPIMMED_4_01: return(0);
204 + case cJU_JPIMMED_5_01: return(0);
205 + case cJU_JPIMMED_6_01: return(0);
206 + case cJU_JPIMMED_7_01: return(0);
207 +#endif
208 +
209 + case cJU_JPIMMED_1_02: return(J__Mpy * 2);
210 + case cJU_JPIMMED_1_03: return(J__Mpy * 3);
211 +#if (defined(JUDY1) || defined(JU_64BIT))
212 + case cJU_JPIMMED_1_04: return(J__Mpy * 4);
213 + case cJU_JPIMMED_1_05: return(J__Mpy * 5);
214 + case cJU_JPIMMED_1_06: return(J__Mpy * 6);
215 + case cJU_JPIMMED_1_07: return(J__Mpy * 7);
216 +#endif
217 +#if (defined(JUDY1) && defined(JU_64BIT))
218 + case cJ1_JPIMMED_1_08: return(0);
219 + case cJ1_JPIMMED_1_09: return(0);
220 + case cJ1_JPIMMED_1_10: return(0);
221 + case cJ1_JPIMMED_1_11: return(0);
222 + case cJ1_JPIMMED_1_12: return(0);
223 + case cJ1_JPIMMED_1_13: return(0);
224 + case cJ1_JPIMMED_1_14: return(0);
225 + case cJ1_JPIMMED_1_15: return(0);
226 +#endif
227 +
228 +#if (defined(JUDY1) || defined(JU_64BIT))
229 + case cJU_JPIMMED_2_02: return(J__Mpy * 2);
230 + case cJU_JPIMMED_2_03: return(J__Mpy * 3);
231 +#endif
232 +#if (defined(JUDY1) && defined(JU_64BIT))
233 + case cJ1_JPIMMED_2_04: return(0);
234 + case cJ1_JPIMMED_2_05: return(0);
235 + case cJ1_JPIMMED_2_06: return(0);
236 + case cJ1_JPIMMED_2_07: return(0);
237 +#endif
238 +
239 +#if (defined(JUDY1) || defined(JU_64BIT))
240 + case cJU_JPIMMED_3_02: return(J__Mpy * 2);
241 +#endif
242 +#if (defined(JUDY1) && defined(JU_64BIT))
243 + case cJ1_JPIMMED_3_03: return(0);
244 + case cJ1_JPIMMED_3_04: return(0);
245 + case cJ1_JPIMMED_3_05: return(0);
246 +
247 + case cJ1_JPIMMED_4_02: return(0);
248 + case cJ1_JPIMMED_4_03: return(0);
249 + case cJ1_JPIMMED_5_02: return(0);
250 + case cJ1_JPIMMED_5_03: return(0);
251 + case cJ1_JPIMMED_6_02: return(0);
252 + case cJ1_JPIMMED_7_02: return(0);
253 +#endif
254 +
255 + } // switch (JU_JPTYPE(Pjp))
256 +
257 + return(0); // to make some compilers happy.
258 +
259 +} // j__udyGetMemActive()
libnetdata/libjudy/src/JudyL/JudyLMemUsed.c new
+61
@@ -0,0 +1,61 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.5 $ $Source: /judy/src/JudyCommon/JudyMemUsed.c $
19 +//
20 +// Return number of bytes of memory used to support a Judy1/L array.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +#ifdef JUDY1
36 +FUNCTION Word_t Judy1MemUsed
37 +#else // JUDYL
38 +FUNCTION Word_t JudyLMemUsed
39 +#endif
40 + (
41 + Pcvoid_t PArray // from which to retrieve.
42 + )
43 +{
44 + Word_t Words = 0;
45 +
46 + if (PArray == (Pcvoid_t) NULL) return(0);
47 +
48 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
49 + {
50 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
51 + Words = JU_LEAFWPOPTOWORDS(Pjlw[0] + 1); // based on pop1.
52 + }
53 + else
54 + {
55 + Pjpm_t Pjpm = P_JPM(PArray);
56 + Words = Pjpm->jpm_TotalMemWords;
57 + }
58 +
59 + return(Words * sizeof(Word_t)); // convert to bytes.
60 +
61 +} // Judy1MemUsed() / JudyLMemUsed()
libnetdata/libjudy/src/JudyL/JudyLNext.c new
+1890
@@ -0,0 +1,1890 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.54 $ $Source: /judy/src/JudyCommon/JudyPrevNext.c $
19 +//
20 +// Judy*Prev() and Judy*Next() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DJUDYNEXT for the Judy*Next() function; otherwise defaults to
24 +// Judy*Prev().
25 +
26 +#if (! (defined(JUDY1) || defined(JUDYL)))
27 +#error: One of -DJUDY1 or -DJUDYL must be specified.
28 +#endif
29 +
30 +#ifndef JUDYNEXT
31 +#ifndef JUDYPREV
32 +#define JUDYPREV 1 // neither set => use default.
33 +#endif
34 +#endif
35 +
36 +#ifdef JUDY1
37 +#include "Judy1.h"
38 +#else
39 +#include "JudyL.h"
40 +#endif
41 +
42 +#include "JudyPrivate1L.h"
43 +
44 +
45 +// ****************************************************************************
46 +// J U D Y 1 P R E V
47 +// J U D Y 1 N E X T
48 +// J U D Y L P R E V
49 +// J U D Y L N E X T
50 +//
51 +// See the manual entry for the API.
52 +//
53 +// OVERVIEW OF Judy*Prev():
54 +//
55 +// Use a reentrant switch statement (state machine, SM1 = "get") to decode the
56 +// callers *PIndex-1, starting with the (PArray), through branches, if
57 +// any, down to an immediate or a leaf. Look for *PIndex-1 in that leaf, and
58 +// if found, return it.
59 +//
60 +// A dead end is either a branch that does not contain a JP for the appropriate
61 +// digit in *PIndex-1, or a leaf that does not contain the undecoded digits of
62 +// *PIndex-1. Upon reaching a dead end, backtrack through the leaf/branches
63 +// that were just traversed, using a list (history) of parent JPs that is built
64 +// while going forward in SM1Get. Start with the current leaf or branch. In a
65 +// backtracked leaf, look for an Index less than *PIndex-1. In each
66 +// backtracked branch, look "sideways" for the next JP, if any, lower than the
67 +// one for the digit (from *PIndex-1) that was previously decoded. While
68 +// backtracking, if a leaf has no previous Index or a branch has no lower JP,
69 +// go to its parent branch in turn. Upon reaching the JRP, return failure, "no
70 +// previous Index". The backtrack process is sufficiently different from
71 +// SM1Get to merit its own separate reentrant switch statement (SM2 =
72 +// "backtrack").
73 +//
74 +// While backtracking, upon finding a lower JP in a branch, there is certain to
75 +// be a "prev" Index under that JP (unless the Judy array is corrupt).
76 +// Traverse forward again, this time taking the last (highest, right-most) JP
77 +// in each branch, and the last (highest) Index upon reaching an immediate or a
78 +// leaf. This traversal is sufficiently different from SM1Get and SM2Backtrack
79 +// to merit its own separate reentrant switch statement (SM3 = "findlimit").
80 +//
81 +// "Decode" bytes in JPs complicate this process a little. In SM1Get, when a
82 +// JP is a narrow pointer, that is, when states are skipped (so the skipped
83 +// digits are stored in jp_DcdPopO), compare the relevant digits to the same
84 +// digits in *PIndex-1. If they are EQUAL, proceed in SM1Get as before. If
85 +// jp_DcdPopOs digits are GREATER, treat the JP as a dead end and proceed in
86 +// SM2Backtrack. If jp_DcdPopOs digits are LESS, treat the JP as if it had
87 +// just been found during a backtrack and proceed directly in SM3Findlimit.
88 +//
89 +// Note that Decode bytes can be ignored in SM3Findlimit; they dont matter.
90 +// Also note that in practice the Decode bytes are routinely compared with
91 +// *PIndex-1 because thats simpler and no slower than first testing for
92 +// narrowness.
93 +//
94 +// Decode bytes also make it unnecessary to construct the Index to return (the
95 +// revised *PIndex) during the search. This step is deferred until finding an
96 +// Index during backtrack or findlimit, before returning it. The first digit
97 +// of *PIndex is derived (saved) based on which JP is used in a JRP branch.
98 +// The remaining digits are obtained from the jp_DcdPopO field in the JP (if
99 +// any) above the immediate or leaf containing the found (prev) Index, plus the
100 +// remaining digit(s) in the immediate or leaf itself. In the case of a LEAFW,
101 +// the Index to return is found directly in the leaf.
102 +//
103 +// Note: Theoretically, as described above, upon reaching a dead end, SM1Get
104 +// passes control to SM2Backtrack to look sideways, even in a leaf. Actually
105 +// its a little more efficient for the SM1Get leaf cases to shortcut this and
106 +// take care of the sideways searches themselves. Hence the history list only
107 +// contains branch JPs, and SM2Backtrack only handles branches. In fact, even
108 +// the branch handling cases in SM1Get do some shortcutting (sideways
109 +// searching) to avoid pushing history and calling SM2Backtrack unnecessarily.
110 +//
111 +// Upon reaching an Index to return after backtracking, *PIndex must be
112 +// modified to the found Index. In principle this could be done by building
113 +// the Index from a saved rootdigit (in the top branch) plus the Dcd bytes from
114 +// the parent JP plus the appropriate Index bytes from the leaf. However,
115 +// Immediates are difficult because their parent JPs lack one (last) digit. So
116 +// instead just build the *PIndex to return "top down" while backtracking and
117 +// findlimiting.
118 +//
119 +// This function is written iteratively for speed, rather than recursively.
120 +//
121 +// CAVEATS:
122 +//
123 +// Why use a backtrack list (history stack), since it has finite size? The
124 +// size is small for Judy on both 32-bit and 64-bit systems, and a list (really
125 +// just an array) is fast to maintain and use. Other alternatives include
126 +// doing a lookahead (lookaside) in each branch while traversing forward
127 +// (decoding), and restarting from the top upon a dead end.
128 +//
129 +// A lookahead means noting the last branch traversed which contained a
130 +// non-null JP lower than the one specified by a digit in *PIndex-1, and
131 +// returning to that point for SM3Findlimit. This seems like a good idea, and
132 +// should be pretty cheap for linear and bitmap branches, but it could result
133 +// in up to 31 unnecessary additional cache line fills (in extreme cases) for
134 +// every uncompressed branch traversed. We have considered means of attaching
135 +// to or hiding within an uncompressed branch (in null JPs) a "cache line map"
136 +// or other structure, such as an offset to the next non-null JP, that would
137 +// speed this up, but it seems unnecessary merely to avoid having a
138 +// finite-length list (array). (If JudySL is ever made "native", the finite
139 +// list length will be an issue.)
140 +//
141 +// Restarting at the top of the Judy array after a dead end requires a careful
142 +// modification of *PIndex-1 to decrement the digit for the parent branch and
143 +// set the remaining lower digits to all 1s. This must be repeated each time a
144 +// parent branch contains another dead end, so even though it should all happen
145 +// in cache, the CPU time can be excessive. (For JudySL or an equivalent
146 +// "infinitely deep" Judy array, consider a hybrid of a large, finite,
147 +// "circular" list and a restart-at-top when the list is backtracked to
148 +// exhaustion.)
149 +//
150 +// Why search for *PIndex-1 instead of *PIndex during SM1Get? In rare
151 +// instances this prevents an unnecessary decode down the wrong path followed
152 +// by a backtrack; its pretty cheap to set up initially; and it means the
153 +// SM1Get machine can simply return if/when it finds that Index.
154 +//
155 +// TBD: Wed like to enhance this function to make successive searches faster.
156 +// This would require saving some previous state, including the previous Index
157 +// returned, and in which leaf it was found. If the next call is for the same
158 +// Index and the array has not been modified, start at the same leaf. This
159 +// should be much easier to implement since this is iterative rather than
160 +// recursive code.
161 +//
162 +// VARIATIONS FOR Judy*Next():
163 +//
164 +// The Judy*Next() code is nearly a perfect mirror of the Judy*Prev() code.
165 +// See the Judy*Prev() overview comments, and mentally switch the following:
166 +//
167 +// - "*PIndex-1" => "*PIndex+1"
168 +// - "less than" => "greater than"
169 +// - "lower" => "higher"
170 +// - "lowest" => "highest"
171 +// - "next-left" => "next-right"
172 +// - "right-most" => "left-most"
173 +//
174 +// Note: SM3Findlimit could be called SM3Findmax/SM3Findmin, but a common name
175 +// for both Prev and Next means many fewer ifdefs in this code.
176 +//
177 +// TBD: Currently this code traverses a JP whether its expanse is partially or
178 +// completely full (populated). For Judy1 (only), since there is no value area
179 +// needed, consider shortcutting to a "success" return upon encountering a full
180 +// JP in SM1Get (or even SM3Findlimit?) A full JP looks like this:
181 +//
182 +// (((JU_JPDCDPOP0(Pjp) ^ cJU_ALLONES) & cJU_POP0MASK(cLevel)) == 0)
183 +
184 +#ifdef JUDY1
185 +#ifdef JUDYPREV
186 +FUNCTION int Judy1Prev
187 +#else
188 +FUNCTION int Judy1Next
189 +#endif
190 +#else
191 +#ifdef JUDYPREV
192 +FUNCTION PPvoid_t JudyLPrev
193 +#else
194 +FUNCTION PPvoid_t JudyLNext
195 +#endif
196 +#endif
197 + (
198 + Pcvoid_t PArray, // Judy array to search.
199 + Word_t * PIndex, // starting point and result.
200 + PJError_t PJError // optional, for returning error info.
201 + )
202 +{
203 + Pjp_t Pjp, Pjp2; // current JPs.
204 + Pjbl_t Pjbl; // Pjp->jp_Addr masked and cast to types:
205 + Pjbb_t Pjbb;
206 + Pjbu_t Pjbu;
207 +
208 +// Note: The following initialization is not strictly required but it makes
209 +// gcc -Wall happy because there is an "impossible" path from Immed handling to
210 +// SM1LeafLImm code that looks like Pjll might be used before set:
211 +
212 + Pjll_t Pjll = (Pjll_t) NULL;
213 + Word_t state; // current state in SM.
214 + Word_t digit; // next digit to decode from Index.
215 +
216 +// Note: The following initialization is not strictly required but it makes
217 +// gcc -Wall happy because there is an "impossible" path from Immed handling to
218 +// SM1LeafLImm code (for JudyL & JudyPrev only) that looks like pop1 might be
219 +// used before set:
220 +
221 +#if (defined(JUDYL) && defined(JUDYPREV))
222 + Word_t pop1 = 0; // in a leaf.
223 +#else
224 + Word_t pop1; // in a leaf.
225 +#endif
226 + int offset; // linear branch/leaf, from j__udySearchLeaf*().
227 + int subexp; // subexpanse in a bitmap branch.
228 + Word_t bitposmask; // bit in bitmap for Index.
229 +
230 +// History for SM2Backtrack:
231 +//
232 +// For a given histnum, APjphist[histnum] is a parent JP that points to a
233 +// branch, and Aoffhist[histnum] is the offset of the NEXT JP in the branch to
234 +// which the parent JP points. The meaning of Aoffhist[histnum] depends on the
235 +// type of branch to which the parent JP points:
236 +//
237 +// Linear: Offset of the next JP in the JP list.
238 +//
239 +// Bitmap: Which subexpanse, plus the offset of the next JP in the
240 +// subexpanses JP list (to avoid bit-counting again), plus for Judy*Next(),
241 +// hidden one byte to the left, which digit, because Judy*Next() also needs
242 +// this.
243 +//
244 +// Uncompressed: Digit, which is actually the offset of the JP in the branch.
245 +//
246 +// Note: Only branch JPs are stored in APjphist[] because, as explained
247 +// earlier, SM1Get shortcuts sideways searches in leaves (and even in branches
248 +// in some cases), so SM2Backtrack only handles branches.
249 +
250 +#define HISTNUMMAX cJU_ROOTSTATE // maximum branches traversable.
251 + Pjp_t APjphist[HISTNUMMAX]; // list of branch JPs traversed.
252 + int Aoffhist[HISTNUMMAX]; // list of next JP offsets; see above.
253 + int histnum = 0; // number of JPs now in list.
254 +
255 +
256 +// ----------------------------------------------------------------------------
257 +// M A C R O S
258 +//
259 +// These are intended to make the code a bit more readable and less redundant.
260 +
261 +
262 +// "PUSH" AND "POP" Pjp AND offset ON HISTORY STACKS:
263 +//
264 +// Note: Ensure a corrupt Judy array does not overflow *hist[]. Meanwhile,
265 +// underflowing *hist[] simply means theres no more room to backtrack =>
266 +// "no previous/next Index".
267 +
268 +#define HISTPUSH(Pjp,Offset) \
269 + APjphist[histnum] = (Pjp); \
270 + Aoffhist[histnum] = (Offset); \
271 + \
272 + if (++histnum >= HISTNUMMAX) \
273 + { \
274 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT) \
275 + JUDY1CODE(return(JERRI );) \
276 + JUDYLCODE(return(PPJERR);) \
277 + }
278 +
279 +#define HISTPOP(Pjp,Offset) \
280 + if ((histnum--) < 1) JU_RET_NOTFOUND; \
281 + (Pjp) = APjphist[histnum]; \
282 + (Offset) = Aoffhist[histnum]
283 +
284 +// How to pack/unpack Aoffhist[] values for bitmap branches:
285 +
286 +#ifdef JUDYPREV
287 +
288 +#define HISTPUSHBOFF(Subexp,Offset,Digit) \
289 + (((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))
290 +
291 +#define HISTPOPBOFF(Subexp,Offset,Digit) \
292 + (Subexp) = (Offset) / cJU_BITSPERSUBEXPB; \
293 + (Offset) %= cJU_BITSPERSUBEXPB
294 +#else
295 +
296 +#define HISTPUSHBOFF(Subexp,Offset,Digit) \
297 + (((Digit) << cJU_BITSPERBYTE) \
298 + | ((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))
299 +
300 +#define HISTPOPBOFF(Subexp,Offset,Digit) \
301 + (Digit) = (Offset) >> cJU_BITSPERBYTE; \
302 + (Subexp) = ((Offset) & JU_LEASTBYTESMASK(1)) / cJU_BITSPERSUBEXPB; \
303 + (Offset) %= cJU_BITSPERSUBEXPB
304 +#endif
305 +
306 +
307 +// CHECK FOR NULL JP:
308 +
309 +#define JPNULL(Type) (((Type) >= cJU_JPNULL1) && ((Type) <= cJU_JPNULLMAX))
310 +
311 +
312 +// SEARCH A BITMAP:
313 +//
314 +// This is a weak analog of j__udySearchLeaf*() for bitmaps. Return the actual
315 +// or next-left position, base 0, of Digit in the single uint32_t bitmap, also
316 +// given a Bitposmask for Digit.
317 +//
318 +// Unlike j__udySearchLeaf*(), the offset is not returned bit-complemented if
319 +// Digits bit is unset, because the caller can check the bitmap themselves to
320 +// determine that. Also, if Digits bit is unset, the returned offset is to
321 +// the next-left JP (including -1), not to the "ideal" position for the Index =
322 +// next-right JP.
323 +//
324 +// Shortcut and skip calling j__udyCountBits*() if the bitmap is full, in which
325 +// case (Digit % cJU_BITSPERSUBEXP*) itself is the base-0 offset.
326 +//
327 +// TBD for Judy*Next(): Should this return next-right instead of next-left?
328 +// That is, +1 from current value? Maybe not, if Digits bit IS set, +1 would
329 +// be wrong.
330 +
331 +#define SEARCHBITMAPB(Bitmap,Digit,Bitposmask) \
332 + (((Bitmap) == cJU_FULLBITMAPB) ? (Digit % cJU_BITSPERSUBEXPB) : \
333 + j__udyCountBitsB((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
334 +
335 +#define SEARCHBITMAPL(Bitmap,Digit,Bitposmask) \
336 + (((Bitmap) == cJU_FULLBITMAPL) ? (Digit % cJU_BITSPERSUBEXPL) : \
337 + j__udyCountBitsL((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
338 +
339 +#ifdef JUDYPREV
340 +// Equivalent to search for the highest offset in Bitmap:
341 +
342 +#define SEARCHBITMAPMAXB(Bitmap) \
343 + (((Bitmap) == cJU_FULLBITMAPB) ? cJU_BITSPERSUBEXPB - 1 : \
344 + j__udyCountBitsB(Bitmap) - 1)
345 +
346 +#define SEARCHBITMAPMAXL(Bitmap) \
347 + (((Bitmap) == cJU_FULLBITMAPL) ? cJU_BITSPERSUBEXPL - 1 : \
348 + j__udyCountBitsL(Bitmap) - 1)
349 +#endif
350 +
351 +
352 +// CHECK DECODE BYTES:
353 +//
354 +// Check Decode bytes in a JP against the equivalent portion of *PIndex. If
355 +// *PIndex is lower (for Judy*Prev()) or higher (for Judy*Next()), this JP is a
356 +// dead end (the same as if it had been absent in a linear or bitmap branch or
357 +// null in an uncompressed branch), enter SM2Backtrack; otherwise enter
358 +// SM3Findlimit to find the highest/lowest Index under this JP, as if the code
359 +// had already backtracked to this JP.
360 +
361 +#ifdef JUDYPREV
362 +#define CDcmp__ <
363 +#else
364 +#define CDcmp__ >
365 +#endif
366 +
367 +#define CHECKDCD(cState) \
368 + if (JU_DCDNOTMATCHINDEX(*PIndex, Pjp, cState)) \
369 + { \
370 + if ((*PIndex & cJU_DCDMASK(cState)) \
371 + CDcmp__(JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(cState))) \
372 + { \
373 + goto SM2Backtrack; \
374 + } \
375 + goto SM3Findlimit; \
376 + }
377 +
378 +
379 +// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM1:
380 +//
381 +// Extract a state-dependent digit from Index in a "constant" way, then jump to
382 +// common code for multiple cases.
383 +
384 +#define SM1PREPB(cState,Next) \
385 + state = (cState); \
386 + digit = JU_DIGITATSTATE(*PIndex, cState); \
387 + goto Next
388 +
389 +
390 +// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM3:
391 +//
392 +// Optionally save Dcd bytes into *PIndex, then save state and jump to common
393 +// code for multiple cases.
394 +
395 +#define SM3PREPB_DCD(cState,Next) \
396 + JU_SETDCD(*PIndex, Pjp, cState); \
397 + SM3PREPB(cState,Next)
398 +
399 +#define SM3PREPB(cState,Next) state = (cState); goto Next
400 +
401 +
402 +// ----------------------------------------------------------------------------
403 +// CHECK FOR SHORTCUTS:
404 +//
405 +// Error out if PIndex is null. Execute JU_RET_NOTFOUND if the Judy array is
406 +// empty or *PIndex is already the minimum/maximum Index possible.
407 +//
408 +// Note: As documented, in case of failure *PIndex may be modified.
409 +
410 + if (PIndex == (PWord_t) NULL)
411 + {
412 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
413 + JUDY1CODE(return(JERRI );)
414 + JUDYLCODE(return(PPJERR);)
415 + }
416 +
417 +#ifdef JUDYPREV
418 + if ((PArray == (Pvoid_t) NULL) || ((*PIndex)-- == 0))
419 +#else
420 + if ((PArray == (Pvoid_t) NULL) || ((*PIndex)++ == cJU_ALLONES))
421 +#endif
422 + JU_RET_NOTFOUND;
423 +
424 +
425 +// HANDLE JRP:
426 +//
427 +// Before even entering SM1Get, check the JRP type. For JRP branches, traverse
428 +// the JPM; handle LEAFW leaves directly; but look for the most common cases
429 +// first.
430 +
431 +// ROOT-STATE LEAF that starts with a Pop0 word; just look within the leaf:
432 +//
433 +// If *PIndex is in the leaf, return it; otherwise return the Index, if any,
434 +// below where it would belong.
435 +
436 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
437 + {
438 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
439 + pop1 = Pjlw[0] + 1;
440 +
441 + if ((offset = j__udySearchLeafW(Pjlw + 1, pop1, *PIndex))
442 + >= 0) // Index is present.
443 + {
444 + assert(offset < pop1); // in expected range.
445 + JU_RET_FOUND_LEAFW(Pjlw, pop1, offset); // *PIndex is set.
446 + }
447 +
448 +#ifdef JUDYPREV
449 + if ((offset = ~offset) == 0) // no next-left Index.
450 +#else
451 + if ((offset = ~offset) >= pop1) // no next-right Index.
452 +#endif
453 + JU_RET_NOTFOUND;
454 +
455 + assert(offset <= pop1); // valid result.
456 +
457 +#ifdef JUDYPREV
458 + *PIndex = Pjlw[offset--]; // next-left Index, base 1.
459 +#else
460 + *PIndex = Pjlw[offset + 1]; // next-right Index, base 1.
461 +#endif
462 + JU_RET_FOUND_LEAFW(Pjlw, pop1, offset); // base 0.
463 +
464 + }
465 + else // JRP BRANCH
466 + {
467 + Pjpm_t Pjpm = P_JPM(PArray);
468 + Pjp = &(Pjpm->jpm_JP);
469 +
470 +// goto SM1Get;
471 + }
472 +
473 +// ============================================================================
474 +// STATE MACHINE 1 -- GET INDEX:
475 +//
476 +// Search for *PIndex (already decremented/incremented so as to be inclusive).
477 +// If found, return it. Otherwise in theory hand off to SM2Backtrack or
478 +// SM3Findlimit, but in practice "shortcut" by first sideways searching the
479 +// current branch or leaf upon hitting a dead end. During sideways search,
480 +// modify *PIndex to a new path taken.
481 +//
482 +// ENTRY: Pjp points to next JP to interpret, whose Decode bytes have not yet
483 +// been checked. This JP is not yet listed in history.
484 +//
485 +// Note: Check Decode bytes at the start of each loop, not after looking up a
486 +// new JP, so its easy to do constant shifts/masks, although this requires
487 +// cautious handling of Pjp, offset, and *hist[] for correct entry to
488 +// SM2Backtrack.
489 +//
490 +// EXIT: Return, or branch to SM2Backtrack or SM3Findlimit with correct
491 +// interface, as described elsewhere.
492 +//
493 +// WARNING: For run-time efficiency the following cases replicate code with
494 +// varying constants, rather than using common code with variable values!
495 +
496 +SM1Get: // return here for next branch/leaf.
497 +
498 + switch (JU_JPTYPE(Pjp))
499 + {
500 +
501 +
502 +// ----------------------------------------------------------------------------
503 +// LINEAR BRANCH:
504 +//
505 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
506 +// next digit in *PIndex.
507 +
508 + case cJU_JPBRANCH_L2: CHECKDCD(2); SM1PREPB(2, SM1BranchL);
509 + case cJU_JPBRANCH_L3: CHECKDCD(3); SM1PREPB(3, SM1BranchL);
510 +#ifdef JU_64BIT
511 + case cJU_JPBRANCH_L4: CHECKDCD(4); SM1PREPB(4, SM1BranchL);
512 + case cJU_JPBRANCH_L5: CHECKDCD(5); SM1PREPB(5, SM1BranchL);
513 + case cJU_JPBRANCH_L6: CHECKDCD(6); SM1PREPB(6, SM1BranchL);
514 + case cJU_JPBRANCH_L7: CHECKDCD(7); SM1PREPB(7, SM1BranchL);
515 +#endif
516 + case cJU_JPBRANCH_L: SM1PREPB(cJU_ROOTSTATE, SM1BranchL);
517 +
518 +// Common code (state-independent) for all cases of linear branches:
519 +
520 +SM1BranchL:
521 + Pjbl = P_JBL(Pjp->jp_Addr);
522 +
523 +// Found JP matching current digit in *PIndex; record parent JP and the next
524 +// JPs offset, and iterate to the next JP:
525 +
526 + if ((offset = j__udySearchLeaf1((Pjll_t) (Pjbl->jbl_Expanse),
527 + Pjbl->jbl_NumJPs, digit)) >= 0)
528 + {
529 + HISTPUSH(Pjp, offset);
530 + Pjp = (Pjbl->jbl_jp) + offset;
531 + goto SM1Get;
532 + }
533 +
534 +// Dead end, no JP in BranchL for next digit in *PIndex:
535 +//
536 +// Get the ideal location of digits JP, and if theres no next-left/right JP
537 +// in the BranchL, shortcut and start backtracking one level up; ignore the
538 +// current Pjp because it points to a BranchL with no next-left/right JP.
539 +
540 +#ifdef JUDYPREV
541 + if ((offset = (~offset) - 1) < 0) // no next-left JP in BranchL.
542 +#else
543 + if ((offset = (~offset)) >= Pjbl->jbl_NumJPs) // no next-right.
544 +#endif
545 + goto SM2Backtrack;
546 +
547 +// Theres a next-left/right JP in the current BranchL; save its digit in
548 +// *PIndex and shortcut to SM3Findlimit:
549 +
550 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
551 + Pjp = (Pjbl->jbl_jp) + offset;
552 + goto SM3Findlimit;
553 +
554 +
555 +// ----------------------------------------------------------------------------
556 +// BITMAP BRANCH:
557 +//
558 +// Check Decode bytes, if any, in the current JP, then look for a JP for the
559 +// next digit in *PIndex.
560 +
561 + case cJU_JPBRANCH_B2: CHECKDCD(2); SM1PREPB(2, SM1BranchB);
562 + case cJU_JPBRANCH_B3: CHECKDCD(3); SM1PREPB(3, SM1BranchB);
563 +#ifdef JU_64BIT
564 + case cJU_JPBRANCH_B4: CHECKDCD(4); SM1PREPB(4, SM1BranchB);
565 + case cJU_JPBRANCH_B5: CHECKDCD(5); SM1PREPB(5, SM1BranchB);
566 + case cJU_JPBRANCH_B6: CHECKDCD(6); SM1PREPB(6, SM1BranchB);
567 + case cJU_JPBRANCH_B7: CHECKDCD(7); SM1PREPB(7, SM1BranchB);
568 +#endif
569 + case cJU_JPBRANCH_B: SM1PREPB(cJU_ROOTSTATE, SM1BranchB);
570 +
571 +// Common code (state-independent) for all cases of bitmap branches:
572 +
573 +SM1BranchB:
574 + Pjbb = P_JBB(Pjp->jp_Addr);
575 +
576 +// Locate the digits JP in the subexpanse list, if present, otherwise the
577 +// offset of the next-left JP, if any:
578 +
579 + subexp = digit / cJU_BITSPERSUBEXPB;
580 + assert(subexp < cJU_NUMSUBEXPB); // falls in expected range.
581 + bitposmask = JU_BITPOSMASKB(digit);
582 + offset = SEARCHBITMAPB(JU_JBB_BITMAP(Pjbb, subexp), digit,
583 + bitposmask);
584 + // right range:
585 + assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPB));
586 +
587 +// Found JP matching current digit in *PIndex:
588 +//
589 +// Record the parent JP and the next JPs offset; and iterate to the next JP.
590 +
591 +// if (JU_BITMAPTESTB(Pjbb, digit)) // slower.
592 + if (JU_JBB_BITMAP(Pjbb, subexp) & bitposmask) // faster.
593 + {
594 + // not negative since at least one bit is set:
595 + assert(offset >= 0);
596 +
597 + HISTPUSH(Pjp, HISTPUSHBOFF(subexp, offset, digit));
598 +
599 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
600 + {
601 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
602 + JUDY1CODE(return(JERRI );)
603 + JUDYLCODE(return(PPJERR);)
604 + }
605 +
606 + Pjp += offset;
607 + goto SM1Get; // iterate to next JP.
608 + }
609 +
610 +// Dead end, no JP in BranchB for next digit in *PIndex:
611 +//
612 +// If theres a next-left/right JP in the current BranchB, shortcut to
613 +// SM3Findlimit. Note: offset is already set to the correct value for the
614 +// next-left/right JP.
615 +
616 +#ifdef JUDYPREV
617 + if (offset >= 0) // next-left JP is in this subexpanse.
618 + goto SM1BranchBFindlimit;
619 +
620 + while (--subexp >= 0) // search next-left subexpanses.
621 +#else
622 + if (JU_JBB_BITMAP(Pjbb, subexp) & JU_MASKHIGHEREXC(bitposmask))
623 + {
624 + ++offset; // next-left => next-right.
625 + goto SM1BranchBFindlimit;
626 + }
627 +
628 + while (++subexp < cJU_NUMSUBEXPB) // search next-right subexps.
629 +#endif
630 + {
631 + if (! JU_JBB_PJP(Pjbb, subexp)) continue; // empty subexpanse.
632 +
633 +#ifdef JUDYPREV
634 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
635 + // expected range:
636 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
637 +#else
638 + offset = 0;
639 +#endif
640 +
641 +// Save the next-left/right JPs digit in *PIndex:
642 +
643 +SM1BranchBFindlimit:
644 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
645 + offset);
646 + JU_SETDIGIT(*PIndex, digit, state);
647 +
648 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
649 + {
650 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
651 + JUDY1CODE(return(JERRI );)
652 + JUDYLCODE(return(PPJERR);)
653 + }
654 +
655 + Pjp += offset;
656 + goto SM3Findlimit;
657 + }
658 +
659 +// Theres no next-left/right JP in the BranchB:
660 +//
661 +// Shortcut and start backtracking one level up; ignore the current Pjp because
662 +// it points to a BranchB with no next-left/right JP.
663 +
664 + goto SM2Backtrack;
665 +
666 +
667 +// ----------------------------------------------------------------------------
668 +// UNCOMPRESSED BRANCH:
669 +//
670 +// Check Decode bytes, if any, in the current JP, then look for a JP for the
671 +// next digit in *PIndex.
672 +
673 + case cJU_JPBRANCH_U2: CHECKDCD(2); SM1PREPB(2, SM1BranchU);
674 + case cJU_JPBRANCH_U3: CHECKDCD(3); SM1PREPB(3, SM1BranchU);
675 +#ifdef JU_64BIT
676 + case cJU_JPBRANCH_U4: CHECKDCD(4); SM1PREPB(4, SM1BranchU);
677 + case cJU_JPBRANCH_U5: CHECKDCD(5); SM1PREPB(5, SM1BranchU);
678 + case cJU_JPBRANCH_U6: CHECKDCD(6); SM1PREPB(6, SM1BranchU);
679 + case cJU_JPBRANCH_U7: CHECKDCD(7); SM1PREPB(7, SM1BranchU);
680 +#endif
681 + case cJU_JPBRANCH_U: SM1PREPB(cJU_ROOTSTATE, SM1BranchU);
682 +
683 +// Common code (state-independent) for all cases of uncompressed branches:
684 +
685 +SM1BranchU:
686 + Pjbu = P_JBU(Pjp->jp_Addr);
687 + Pjp2 = (Pjbu->jbu_jp) + digit;
688 +
689 +// Found JP matching current digit in *PIndex:
690 +//
691 +// Record the parent JP and the next JPs digit, and iterate to the next JP.
692 +//
693 +// TBD: Instead of this, just goto SM1Get, and add cJU_JPNULL* cases to the
694 +// SM1Get state machine? Then backtrack? However, it means you cant detect
695 +// an inappropriate cJU_JPNULL*, when it occurs in other than a BranchU, and
696 +// return JU_RET_CORRUPT.
697 +
698 + if (! JPNULL(JU_JPTYPE(Pjp2))) // digit has a JP.
699 + {
700 + HISTPUSH(Pjp, digit);
701 + Pjp = Pjp2;
702 + goto SM1Get;
703 + }
704 +
705 +// Dead end, no JP in BranchU for next digit in *PIndex:
706 +//
707 +// Search for a next-left/right JP in the current BranchU, and if one is found,
708 +// save its digit in *PIndex and shortcut to SM3Findlimit:
709 +
710 +#ifdef JUDYPREV
711 + while (digit >= 1)
712 + {
713 + Pjp = (Pjbu->jbu_jp) + (--digit);
714 +#else
715 + while (digit < cJU_BRANCHUNUMJPS - 1)
716 + {
717 + Pjp = (Pjbu->jbu_jp) + (++digit);
718 +#endif
719 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
720 +
721 + JU_SETDIGIT(*PIndex, digit, state);
722 + goto SM3Findlimit;
723 + }
724 +
725 +// Theres no next-left/right JP in the BranchU:
726 +//
727 +// Shortcut and start backtracking one level up; ignore the current Pjp because
728 +// it points to a BranchU with no next-left/right JP.
729 +
730 + goto SM2Backtrack;
731 +
732 +
733 +// ----------------------------------------------------------------------------
734 +// LINEAR LEAF:
735 +//
736 +// Check Decode bytes, if any, in the current JP, then search the leaf for
737 +// *PIndex.
738 +
739 +#define SM1LEAFL(Func) \
740 + Pjll = P_JLL(Pjp->jp_Addr); \
741 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
742 + offset = Func(Pjll, pop1, *PIndex); \
743 + goto SM1LeafLImm
744 +
745 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
746 + case cJU_JPLEAF1: CHECKDCD(1); SM1LEAFL(j__udySearchLeaf1);
747 +#endif
748 + case cJU_JPLEAF2: CHECKDCD(2); SM1LEAFL(j__udySearchLeaf2);
749 + case cJU_JPLEAF3: CHECKDCD(3); SM1LEAFL(j__udySearchLeaf3);
750 +
751 +#ifdef JU_64BIT
752 + case cJU_JPLEAF4: CHECKDCD(4); SM1LEAFL(j__udySearchLeaf4);
753 + case cJU_JPLEAF5: CHECKDCD(5); SM1LEAFL(j__udySearchLeaf5);
754 + case cJU_JPLEAF6: CHECKDCD(6); SM1LEAFL(j__udySearchLeaf6);
755 + case cJU_JPLEAF7: CHECKDCD(7); SM1LEAFL(j__udySearchLeaf7);
756 +#endif
757 +
758 +// Common code (state-independent) for all cases of linear leaves and
759 +// immediates:
760 +
761 +SM1LeafLImm:
762 + if (offset >= 0) // *PIndex is in LeafL / Immed.
763 +#ifdef JUDY1
764 + JU_RET_FOUND;
765 +#else
766 + { // JudyL is trickier...
767 + switch (JU_JPTYPE(Pjp))
768 + {
769 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
770 + case cJU_JPLEAF1: JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
771 +#endif
772 + case cJU_JPLEAF2: JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
773 + case cJU_JPLEAF3: JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
774 +#ifdef JU_64BIT
775 + case cJU_JPLEAF4: JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
776 + case cJU_JPLEAF5: JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
777 + case cJU_JPLEAF6: JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
778 + case cJU_JPLEAF7: JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
779 +#endif
780 +
781 + case cJU_JPIMMED_1_01:
782 + case cJU_JPIMMED_2_01:
783 + case cJU_JPIMMED_3_01:
784 +#ifdef JU_64BIT
785 + case cJU_JPIMMED_4_01:
786 + case cJU_JPIMMED_5_01:
787 + case cJU_JPIMMED_6_01:
788 + case cJU_JPIMMED_7_01:
789 +#endif
790 + JU_RET_FOUND_IMM_01(Pjp);
791 +
792 + case cJU_JPIMMED_1_02:
793 + case cJU_JPIMMED_1_03:
794 +#ifdef JU_64BIT
795 + case cJU_JPIMMED_1_04:
796 + case cJU_JPIMMED_1_05:
797 + case cJU_JPIMMED_1_06:
798 + case cJU_JPIMMED_1_07:
799 + case cJU_JPIMMED_2_02:
800 + case cJU_JPIMMED_2_03:
801 + case cJU_JPIMMED_3_02:
802 +#endif
803 + JU_RET_FOUND_IMM(Pjp, offset);
804 + }
805 +
806 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // impossible?
807 + JUDY1CODE(return(JERRI );)
808 + JUDYLCODE(return(PPJERR);)
809 +
810 + } // found *PIndex
811 +
812 +#endif // JUDYL
813 +
814 +// Dead end, no Index in LeafL / Immed for remaining digit(s) in *PIndex:
815 +//
816 +// Get the ideal location of Index, and if theres no next-left/right Index in
817 +// the LeafL / Immed, shortcut and start backtracking one level up; ignore the
818 +// current Pjp because it points to a LeafL / Immed with no next-left/right
819 +// Index.
820 +
821 +#ifdef JUDYPREV
822 + if ((offset = (~offset) - 1) < 0) // no next-left Index.
823 +#else
824 + if ((offset = (~offset)) >= pop1) // no next-right Index.
825 +#endif
826 + goto SM2Backtrack;
827 +
828 +// Theres a next-left/right Index in the current LeafL / Immed; shortcut by
829 +// copying its digit(s) to *PIndex and returning it.
830 +//
831 +// Unfortunately this is pretty hairy, especially avoiding endian issues.
832 +//
833 +// The cJU_JPLEAF* cases are very similar to same-index-size cJU_JPIMMED* cases
834 +// for *_02 and above, but must return differently, at least for JudyL, so
835 +// spell them out separately here at the cost of a little redundant code for
836 +// Judy1.
837 +
838 + switch (JU_JPTYPE(Pjp))
839 + {
840 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
841 + case cJU_JPLEAF1:
842 +
843 + JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
844 + JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
845 +#endif
846 +
847 + case cJU_JPLEAF2:
848 +
849 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
850 + | ((uint16_t *) Pjll)[offset];
851 + JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
852 +
853 + case cJU_JPLEAF3:
854 + {
855 + Word_t lsb;
856 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
857 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
858 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
859 + }
860 +
861 +#ifdef JU_64BIT
862 + case cJU_JPLEAF4:
863 +
864 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
865 + | ((uint32_t *) Pjll)[offset];
866 + JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
867 +
868 + case cJU_JPLEAF5:
869 + {
870 + Word_t lsb;
871 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
872 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
873 + JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
874 + }
875 +
876 + case cJU_JPLEAF6:
877 + {
878 + Word_t lsb;
879 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
880 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
881 + JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
882 + }
883 +
884 + case cJU_JPLEAF7:
885 + {
886 + Word_t lsb;
887 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
888 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
889 + JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
890 + }
891 +
892 +#endif // JU_64BIT
893 +
894 +#define SET_01(cState) JU_SETDIGITS(*PIndex, JU_JPDCDPOP0(Pjp), cState)
895 +
896 + case cJU_JPIMMED_1_01: SET_01(1); goto SM1Imm_01;
897 + case cJU_JPIMMED_2_01: SET_01(2); goto SM1Imm_01;
898 + case cJU_JPIMMED_3_01: SET_01(3); goto SM1Imm_01;
899 +#ifdef JU_64BIT
900 + case cJU_JPIMMED_4_01: SET_01(4); goto SM1Imm_01;
901 + case cJU_JPIMMED_5_01: SET_01(5); goto SM1Imm_01;
902 + case cJU_JPIMMED_6_01: SET_01(6); goto SM1Imm_01;
903 + case cJU_JPIMMED_7_01: SET_01(7); goto SM1Imm_01;
904 +#endif
905 +SM1Imm_01: JU_RET_FOUND_IMM_01(Pjp);
906 +
907 +// Shorthand for where to find start of Index bytes array:
908 +
909 +#ifdef JUDY1
910 +#define PJI (Pjp->jp_1Index)
911 +#else
912 +#define PJI (Pjp->jp_LIndex)
913 +#endif
914 +
915 + case cJU_JPIMMED_1_02:
916 + case cJU_JPIMMED_1_03:
917 +#if (defined(JUDY1) || defined(JU_64BIT))
918 + case cJU_JPIMMED_1_04:
919 + case cJU_JPIMMED_1_05:
920 + case cJU_JPIMMED_1_06:
921 + case cJU_JPIMMED_1_07:
922 +#endif
923 +#if (defined(JUDY1) && defined(JU_64BIT))
924 + case cJ1_JPIMMED_1_08:
925 + case cJ1_JPIMMED_1_09:
926 + case cJ1_JPIMMED_1_10:
927 + case cJ1_JPIMMED_1_11:
928 + case cJ1_JPIMMED_1_12:
929 + case cJ1_JPIMMED_1_13:
930 + case cJ1_JPIMMED_1_14:
931 + case cJ1_JPIMMED_1_15:
932 +#endif
933 + JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
934 + JU_RET_FOUND_IMM(Pjp, offset);
935 +
936 +#if (defined(JUDY1) || defined(JU_64BIT))
937 + case cJU_JPIMMED_2_02:
938 + case cJU_JPIMMED_2_03:
939 +#endif
940 +#if (defined(JUDY1) && defined(JU_64BIT))
941 + case cJ1_JPIMMED_2_04:
942 + case cJ1_JPIMMED_2_05:
943 + case cJ1_JPIMMED_2_06:
944 + case cJ1_JPIMMED_2_07:
945 +#endif
946 +#if (defined(JUDY1) || defined(JU_64BIT))
947 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
948 + | ((uint16_t *) PJI)[offset];
949 + JU_RET_FOUND_IMM(Pjp, offset);
950 +#endif
951 +
952 +#if (defined(JUDY1) || defined(JU_64BIT))
953 + case cJU_JPIMMED_3_02:
954 +#endif
955 +#if (defined(JUDY1) && defined(JU_64BIT))
956 + case cJ1_JPIMMED_3_03:
957 + case cJ1_JPIMMED_3_04:
958 + case cJ1_JPIMMED_3_05:
959 +#endif
960 +#if (defined(JUDY1) || defined(JU_64BIT))
961 + {
962 + Word_t lsb;
963 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
964 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
965 + JU_RET_FOUND_IMM(Pjp, offset);
966 + }
967 +#endif
968 +
969 +#if (defined(JUDY1) && defined(JU_64BIT))
970 + case cJ1_JPIMMED_4_02:
971 + case cJ1_JPIMMED_4_03:
972 +
973 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
974 + | ((uint32_t *) PJI)[offset];
975 + JU_RET_FOUND_IMM(Pjp, offset);
976 +
977 + case cJ1_JPIMMED_5_02:
978 + case cJ1_JPIMMED_5_03:
979 + {
980 + Word_t lsb;
981 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
982 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
983 + JU_RET_FOUND_IMM(Pjp, offset);
984 + }
985 +
986 + case cJ1_JPIMMED_6_02:
987 + {
988 + Word_t lsb;
989 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
990 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
991 + JU_RET_FOUND_IMM(Pjp, offset);
992 + }
993 +
994 + case cJ1_JPIMMED_7_02:
995 + {
996 + Word_t lsb;
997 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
998 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
999 + JU_RET_FOUND_IMM(Pjp, offset);
1000 + }
1001 +
1002 +#endif // (JUDY1 && JU_64BIT)
1003 +
1004 + } // switch for not-found *PIndex
1005 +
1006 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // impossible?
1007 + JUDY1CODE(return(JERRI );)
1008 + JUDYLCODE(return(PPJERR);)
1009 +
1010 +
1011 +// ----------------------------------------------------------------------------
1012 +// BITMAP LEAF:
1013 +//
1014 +// Check Decode bytes, if any, in the current JP, then look in the leaf for
1015 +// *PIndex.
1016 +
1017 + case cJU_JPLEAF_B1:
1018 + {
1019 + Pjlb_t Pjlb;
1020 + CHECKDCD(1);
1021 +
1022 + Pjlb = P_JLB(Pjp->jp_Addr);
1023 + digit = JU_DIGITATSTATE(*PIndex, 1);
1024 + subexp = JU_SUBEXPL(digit);
1025 + bitposmask = JU_BITPOSMASKL(digit);
1026 + assert(subexp < cJU_NUMSUBEXPL); // falls in expected range.
1027 +
1028 +// *PIndex exists in LeafB1:
1029 +
1030 +// if (JU_BITMAPTESTL(Pjlb, digit)) // slower.
1031 + if (JU_JLB_BITMAP(Pjlb, subexp) & bitposmask) // faster.
1032 + {
1033 +#ifdef JUDYL // needs offset at this point:
1034 + offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit, bitposmask);
1035 +#endif
1036 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1037 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1038 + }
1039 +
1040 +// Dead end, no Index in LeafB1 for remaining digit in *PIndex:
1041 +//
1042 +// If theres a next-left/right Index in the current LeafB1, which for
1043 +// Judy*Next() is true if any bits are set for higher Indexes, shortcut by
1044 +// returning it. Note: For Judy*Prev(), offset is set here to the correct
1045 +// value for the next-left JP.
1046 +
1047 + offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit,
1048 + bitposmask);
1049 + // right range:
1050 + assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPL));
1051 +
1052 +#ifdef JUDYPREV
1053 + if (offset >= 0) // next-left JP is in this subexpanse.
1054 + goto SM1LeafB1Findlimit;
1055 +
1056 + while (--subexp >= 0) // search next-left subexpanses.
1057 +#else
1058 + if (JU_JLB_BITMAP(Pjlb, subexp) & JU_MASKHIGHEREXC(bitposmask))
1059 + {
1060 + ++offset; // next-left => next-right.
1061 + goto SM1LeafB1Findlimit;
1062 + }
1063 +
1064 + while (++subexp < cJU_NUMSUBEXPL) // search next-right subexps.
1065 +#endif
1066 + {
1067 + if (! JU_JLB_BITMAP(Pjlb, subexp)) continue; // empty subexp.
1068 +
1069 +#ifdef JUDYPREV
1070 + offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
1071 + // expected range:
1072 + assert((offset >= 0) && (offset < (int) cJU_BITSPERSUBEXPL));
1073 +#else
1074 + offset = 0;
1075 +#endif
1076 +
1077 +// Save the next-left/right Indexess digit in *PIndex:
1078 +
1079 +SM1LeafB1Findlimit:
1080 + JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
1081 + JU_SETDIGIT1(*PIndex, digit);
1082 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1083 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1084 + }
1085 +
1086 +// Theres no next-left/right Index in the LeafB1:
1087 +//
1088 +// Shortcut and start backtracking one level up; ignore the current Pjp because
1089 +// it points to a LeafB1 with no next-left/right Index.
1090 +
1091 + goto SM2Backtrack;
1092 +
1093 + } // case cJU_JPLEAF_B1
1094 +
1095 +#ifdef JUDY1
1096 +// ----------------------------------------------------------------------------
1097 +// FULL POPULATION:
1098 +//
1099 +// If the Decode bytes match, *PIndex is found (without modification).
1100 +
1101 + case cJ1_JPFULLPOPU1:
1102 +
1103 + CHECKDCD(1);
1104 + JU_RET_FOUND_FULLPOPU1;
1105 +#endif
1106 +
1107 +
1108 +// ----------------------------------------------------------------------------
1109 +// IMMEDIATE:
1110 +
1111 +#ifdef JUDYPREV
1112 +#define SM1IMM_SETPOP1(cPop1)
1113 +#else
1114 +#define SM1IMM_SETPOP1(cPop1) pop1 = (cPop1)
1115 +#endif
1116 +
1117 +#define SM1IMM(Func,cPop1) \
1118 + SM1IMM_SETPOP1(cPop1); \
1119 + offset = Func((Pjll_t) (PJI), cPop1, *PIndex); \
1120 + goto SM1LeafLImm
1121 +
1122 +// Special case for Pop1 = 1 Immediate JPs:
1123 +//
1124 +// If *PIndex is in the immediate, offset is 0, otherwise the binary NOT of the
1125 +// offset where it belongs, 0 or 1, same as from the search functions.
1126 +
1127 +#ifdef JUDYPREV
1128 +#define SM1IMM_01_SETPOP1
1129 +#else
1130 +#define SM1IMM_01_SETPOP1 pop1 = 1
1131 +#endif
1132 +
1133 +#define SM1IMM_01 \
1134 + SM1IMM_01_SETPOP1; \
1135 + offset = ((JU_JPDCDPOP0(Pjp) < JU_TRIMTODCDSIZE(*PIndex)) ? ~1 : \
1136 + (JU_JPDCDPOP0(Pjp) == JU_TRIMTODCDSIZE(*PIndex)) ? 0 : \
1137 + ~0); \
1138 + goto SM1LeafLImm
1139 +
1140 + case cJU_JPIMMED_1_01:
1141 + case cJU_JPIMMED_2_01:
1142 + case cJU_JPIMMED_3_01:
1143 +#ifdef JU_64BIT
1144 + case cJU_JPIMMED_4_01:
1145 + case cJU_JPIMMED_5_01:
1146 + case cJU_JPIMMED_6_01:
1147 + case cJU_JPIMMED_7_01:
1148 +#endif
1149 + SM1IMM_01;
1150 +
1151 +// TBD: Doug says it would be OK to have fewer calls and calculate arg 2, here
1152 +// and in Judy*Count() also.
1153 +
1154 + case cJU_JPIMMED_1_02: SM1IMM(j__udySearchLeaf1, 2);
1155 + case cJU_JPIMMED_1_03: SM1IMM(j__udySearchLeaf1, 3);
1156 +#if (defined(JUDY1) || defined(JU_64BIT))
1157 + case cJU_JPIMMED_1_04: SM1IMM(j__udySearchLeaf1, 4);
1158 + case cJU_JPIMMED_1_05: SM1IMM(j__udySearchLeaf1, 5);
1159 + case cJU_JPIMMED_1_06: SM1IMM(j__udySearchLeaf1, 6);
1160 + case cJU_JPIMMED_1_07: SM1IMM(j__udySearchLeaf1, 7);
1161 +#endif
1162 +#if (defined(JUDY1) && defined(JU_64BIT))
1163 + case cJ1_JPIMMED_1_08: SM1IMM(j__udySearchLeaf1, 8);
1164 + case cJ1_JPIMMED_1_09: SM1IMM(j__udySearchLeaf1, 9);
1165 + case cJ1_JPIMMED_1_10: SM1IMM(j__udySearchLeaf1, 10);
1166 + case cJ1_JPIMMED_1_11: SM1IMM(j__udySearchLeaf1, 11);
1167 + case cJ1_JPIMMED_1_12: SM1IMM(j__udySearchLeaf1, 12);
1168 + case cJ1_JPIMMED_1_13: SM1IMM(j__udySearchLeaf1, 13);
1169 + case cJ1_JPIMMED_1_14: SM1IMM(j__udySearchLeaf1, 14);
1170 + case cJ1_JPIMMED_1_15: SM1IMM(j__udySearchLeaf1, 15);
1171 +#endif
1172 +
1173 +#if (defined(JUDY1) || defined(JU_64BIT))
1174 + case cJU_JPIMMED_2_02: SM1IMM(j__udySearchLeaf2, 2);
1175 + case cJU_JPIMMED_2_03: SM1IMM(j__udySearchLeaf2, 3);
1176 +#endif
1177 +#if (defined(JUDY1) && defined(JU_64BIT))
1178 + case cJ1_JPIMMED_2_04: SM1IMM(j__udySearchLeaf2, 4);
1179 + case cJ1_JPIMMED_2_05: SM1IMM(j__udySearchLeaf2, 5);
1180 + case cJ1_JPIMMED_2_06: SM1IMM(j__udySearchLeaf2, 6);
1181 + case cJ1_JPIMMED_2_07: SM1IMM(j__udySearchLeaf2, 7);
1182 +#endif
1183 +
1184 +#if (defined(JUDY1) || defined(JU_64BIT))
1185 + case cJU_JPIMMED_3_02: SM1IMM(j__udySearchLeaf3, 2);
1186 +#endif
1187 +#if (defined(JUDY1) && defined(JU_64BIT))
1188 + case cJ1_JPIMMED_3_03: SM1IMM(j__udySearchLeaf3, 3);
1189 + case cJ1_JPIMMED_3_04: SM1IMM(j__udySearchLeaf3, 4);
1190 + case cJ1_JPIMMED_3_05: SM1IMM(j__udySearchLeaf3, 5);
1191 +
1192 + case cJ1_JPIMMED_4_02: SM1IMM(j__udySearchLeaf4, 2);
1193 + case cJ1_JPIMMED_4_03: SM1IMM(j__udySearchLeaf4, 3);
1194 +
1195 + case cJ1_JPIMMED_5_02: SM1IMM(j__udySearchLeaf5, 2);
1196 + case cJ1_JPIMMED_5_03: SM1IMM(j__udySearchLeaf5, 3);
1197 +
1198 + case cJ1_JPIMMED_6_02: SM1IMM(j__udySearchLeaf6, 2);
1199 +
1200 + case cJ1_JPIMMED_7_02: SM1IMM(j__udySearchLeaf7, 2);
1201 +#endif
1202 +
1203 +
1204 +// ----------------------------------------------------------------------------
1205 +// INVALID JP TYPE:
1206 +
1207 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1208 + JUDY1CODE(return(JERRI );)
1209 + JUDYLCODE(return(PPJERR);)
1210 +
1211 + } // SM1Get switch.
1212 +
1213 + /*NOTREACHED*/
1214 +
1215 +
1216 +// ============================================================================
1217 +// STATE MACHINE 2 -- BACKTRACK BRANCH TO PREVIOUS JP:
1218 +//
1219 +// Look for the next-left/right JP in a branch, backing up the history list as
1220 +// necessary. Upon finding a next-left/right JP, modify the corresponding
1221 +// digit in *PIndex before passing control to SM3Findlimit.
1222 +//
1223 +// Note: As described earlier, only branch JPs are expected here; other types
1224 +// fall into the default case.
1225 +//
1226 +// Note: If a found JP contains needed Dcd bytes, thats OK, theyre copied to
1227 +// *PIndex in SM3Findlimit.
1228 +//
1229 +// TBD: This code has a lot in common with similar code in the shortcut cases
1230 +// in SM1Get. Can combine this code somehow?
1231 +//
1232 +// ENTRY: List, possibly empty, of JPs and offsets in APjphist[] and
1233 +// Aoffhist[]; see earlier comments.
1234 +//
1235 +// EXIT: Execute JU_RET_NOTFOUND if no previous/next JP; otherwise jump to
1236 +// SM3Findlimit to resume a new but different downward search.
1237 +
1238 +SM2Backtrack: // come or return here for first/next sideways search.
1239 +
1240 + HISTPOP(Pjp, offset);
1241 +
1242 + switch (JU_JPTYPE(Pjp))
1243 + {
1244 +
1245 +
1246 +// ----------------------------------------------------------------------------
1247 +// LINEAR BRANCH:
1248 +
1249 + case cJU_JPBRANCH_L2: state = 2; goto SM2BranchL;
1250 + case cJU_JPBRANCH_L3: state = 3; goto SM2BranchL;
1251 +#ifdef JU_64BIT
1252 + case cJU_JPBRANCH_L4: state = 4; goto SM2BranchL;
1253 + case cJU_JPBRANCH_L5: state = 5; goto SM2BranchL;
1254 + case cJU_JPBRANCH_L6: state = 6; goto SM2BranchL;
1255 + case cJU_JPBRANCH_L7: state = 7; goto SM2BranchL;
1256 +#endif
1257 + case cJU_JPBRANCH_L: state = cJU_ROOTSTATE; goto SM2BranchL;
1258 +
1259 +SM2BranchL:
1260 +#ifdef JUDYPREV
1261 + if (--offset < 0) goto SM2Backtrack; // no next-left JP in BranchL.
1262 +#endif
1263 + Pjbl = P_JBL(Pjp->jp_Addr);
1264 +#ifdef JUDYNEXT
1265 + if (++offset >= (Pjbl->jbl_NumJPs)) goto SM2Backtrack;
1266 + // no next-right JP in BranchL.
1267 +#endif
1268 +
1269 +// Theres a next-left/right JP in the current BranchL; save its digit in
1270 +// *PIndex and continue with SM3Findlimit:
1271 +
1272 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
1273 + Pjp = (Pjbl->jbl_jp) + offset;
1274 + goto SM3Findlimit;
1275 +
1276 +
1277 +// ----------------------------------------------------------------------------
1278 +// BITMAP BRANCH:
1279 +
1280 + case cJU_JPBRANCH_B2: state = 2; goto SM2BranchB;
1281 + case cJU_JPBRANCH_B3: state = 3; goto SM2BranchB;
1282 +#ifdef JU_64BIT
1283 + case cJU_JPBRANCH_B4: state = 4; goto SM2BranchB;
1284 + case cJU_JPBRANCH_B5: state = 5; goto SM2BranchB;
1285 + case cJU_JPBRANCH_B6: state = 6; goto SM2BranchB;
1286 + case cJU_JPBRANCH_B7: state = 7; goto SM2BranchB;
1287 +#endif
1288 + case cJU_JPBRANCH_B: state = cJU_ROOTSTATE; goto SM2BranchB;
1289 +
1290 +SM2BranchB:
1291 + Pjbb = P_JBB(Pjp->jp_Addr);
1292 + HISTPOPBOFF(subexp, offset, digit); // unpack values.
1293 +
1294 +// If theres a next-left/right JP in the current BranchB, which for
1295 +// Judy*Next() is true if any bits are set for higher Indexes, continue to
1296 +// SM3Findlimit:
1297 +//
1298 +// Note: offset is set to the JP previously traversed; go one to the
1299 +// left/right.
1300 +
1301 +#ifdef JUDYPREV
1302 + if (offset > 0) // next-left JP is in this subexpanse.
1303 + {
1304 + --offset;
1305 + goto SM2BranchBFindlimit;
1306 + }
1307 +
1308 + while (--subexp >= 0) // search next-left subexpanses.
1309 +#else
1310 + if (JU_JBB_BITMAP(Pjbb, subexp)
1311 + & JU_MASKHIGHEREXC(JU_BITPOSMASKB(digit)))
1312 + {
1313 + ++offset; // next-left => next-right.
1314 + goto SM2BranchBFindlimit;
1315 + }
1316 +
1317 + while (++subexp < cJU_NUMSUBEXPB) // search next-right subexps.
1318 +#endif
1319 + {
1320 + if (! JU_JBB_PJP(Pjbb, subexp)) continue; // empty subexpanse.
1321 +
1322 +#ifdef JUDYPREV
1323 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
1324 + // expected range:
1325 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
1326 +#else
1327 + offset = 0;
1328 +#endif
1329 +
1330 +// Save the next-left/right JPs digit in *PIndex:
1331 +
1332 +SM2BranchBFindlimit:
1333 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
1334 + offset);
1335 + JU_SETDIGIT(*PIndex, digit, state);
1336 +
1337 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
1338 + {
1339 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1340 + JUDY1CODE(return(JERRI );)
1341 + JUDYLCODE(return(PPJERR);)
1342 + }
1343 +
1344 + Pjp += offset;
1345 + goto SM3Findlimit;
1346 + }
1347 +
1348 +// Theres no next-left/right JP in the BranchB:
1349 +
1350 + goto SM2Backtrack;
1351 +
1352 +
1353 +// ----------------------------------------------------------------------------
1354 +// UNCOMPRESSED BRANCH:
1355 +
1356 + case cJU_JPBRANCH_U2: state = 2; goto SM2BranchU;
1357 + case cJU_JPBRANCH_U3: state = 3; goto SM2BranchU;
1358 +#ifdef JU_64BIT
1359 + case cJU_JPBRANCH_U4: state = 4; goto SM2BranchU;
1360 + case cJU_JPBRANCH_U5: state = 5; goto SM2BranchU;
1361 + case cJU_JPBRANCH_U6: state = 6; goto SM2BranchU;
1362 + case cJU_JPBRANCH_U7: state = 7; goto SM2BranchU;
1363 +#endif
1364 + case cJU_JPBRANCH_U: state = cJU_ROOTSTATE; goto SM2BranchU;
1365 +
1366 +SM2BranchU:
1367 +
1368 +// Search for a next-left/right JP in the current BranchU, and if one is found,
1369 +// save its digit in *PIndex and continue to SM3Findlimit:
1370 +
1371 + Pjbu = P_JBU(Pjp->jp_Addr);
1372 + digit = offset;
1373 +
1374 +#ifdef JUDYPREV
1375 + while (digit >= 1)
1376 + {
1377 + Pjp = (Pjbu->jbu_jp) + (--digit);
1378 +#else
1379 + while (digit < cJU_BRANCHUNUMJPS - 1)
1380 + {
1381 + Pjp = (Pjbu->jbu_jp) + (++digit);
1382 +#endif
1383 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
1384 +
1385 + JU_SETDIGIT(*PIndex, digit, state);
1386 + goto SM3Findlimit;
1387 + }
1388 +
1389 +// Theres no next-left/right JP in the BranchU:
1390 +
1391 + goto SM2Backtrack;
1392 +
1393 +
1394 +// ----------------------------------------------------------------------------
1395 +// INVALID JP TYPE:
1396 +
1397 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1398 + JUDY1CODE(return(JERRI );)
1399 + JUDYLCODE(return(PPJERR);)
1400 +
1401 + } // SM2Backtrack switch.
1402 +
1403 + /*NOTREACHED*/
1404 +
1405 +
1406 +// ============================================================================
1407 +// STATE MACHINE 3 -- FIND LIMIT JP/INDEX:
1408 +//
1409 +// Look for the highest/lowest (right/left-most) JP in each branch and the
1410 +// highest/lowest Index in a leaf or immediate, and return it. While
1411 +// traversing, modify appropriate digit(s) in *PIndex to reflect the path
1412 +// taken, including Dcd bytes in each JP (which could hold critical missing
1413 +// digits for skipped branches).
1414 +//
1415 +// ENTRY: Pjp set to a JP under which to find max/min JPs (if a branch JP) or
1416 +// a max/min Index and return (if a leaf or immediate JP).
1417 +//
1418 +// EXIT: Execute JU_RET_FOUND* upon reaching a leaf or immediate. Should be
1419 +// impossible to fail, unless the Judy array is corrupt.
1420 +
1421 +SM3Findlimit: // come or return here for first/next branch/leaf.
1422 +
1423 + switch (JU_JPTYPE(Pjp))
1424 + {
1425 +// ----------------------------------------------------------------------------
1426 +// LINEAR BRANCH:
1427 +//
1428 +// Simply use the highest/lowest (right/left-most) JP in the BranchL, but first
1429 +// copy the Dcd bytes to *PIndex if there are any (only if state <
1430 +// cJU_ROOTSTATE - 1).
1431 +
1432 + case cJU_JPBRANCH_L2: SM3PREPB_DCD(2, SM3BranchL);
1433 +#ifndef JU_64BIT
1434 + case cJU_JPBRANCH_L3: SM3PREPB( 3, SM3BranchL);
1435 +#else
1436 + case cJU_JPBRANCH_L3: SM3PREPB_DCD(3, SM3BranchL);
1437 + case cJU_JPBRANCH_L4: SM3PREPB_DCD(4, SM3BranchL);
1438 + case cJU_JPBRANCH_L5: SM3PREPB_DCD(5, SM3BranchL);
1439 + case cJU_JPBRANCH_L6: SM3PREPB_DCD(6, SM3BranchL);
1440 + case cJU_JPBRANCH_L7: SM3PREPB( 7, SM3BranchL);
1441 +#endif
1442 + case cJU_JPBRANCH_L: SM3PREPB( cJU_ROOTSTATE, SM3BranchL);
1443 +
1444 +SM3BranchL:
1445 + Pjbl = P_JBL(Pjp->jp_Addr);
1446 +
1447 +#ifdef JUDYPREV
1448 + if ((offset = (Pjbl->jbl_NumJPs) - 1) < 0)
1449 +#else
1450 + offset = 0; if ((Pjbl->jbl_NumJPs) == 0)
1451 +#endif
1452 + {
1453 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1454 + JUDY1CODE(return(JERRI );)
1455 + JUDYLCODE(return(PPJERR);)
1456 + }
1457 +
1458 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
1459 + Pjp = (Pjbl->jbl_jp) + offset;
1460 + goto SM3Findlimit;
1461 +
1462 +
1463 +// ----------------------------------------------------------------------------
1464 +// BITMAP BRANCH:
1465 +//
1466 +// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
1467 +// the highest/lowest JP in that subexpanse, but first copy Dcd bytes, if there
1468 +// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.
1469 +
1470 + case cJU_JPBRANCH_B2: SM3PREPB_DCD(2, SM3BranchB);
1471 +#ifndef JU_64BIT
1472 + case cJU_JPBRANCH_B3: SM3PREPB( 3, SM3BranchB);
1473 +#else
1474 + case cJU_JPBRANCH_B3: SM3PREPB_DCD(3, SM3BranchB);
1475 + case cJU_JPBRANCH_B4: SM3PREPB_DCD(4, SM3BranchB);
1476 + case cJU_JPBRANCH_B5: SM3PREPB_DCD(5, SM3BranchB);
1477 + case cJU_JPBRANCH_B6: SM3PREPB_DCD(6, SM3BranchB);
1478 + case cJU_JPBRANCH_B7: SM3PREPB( 7, SM3BranchB);
1479 +#endif
1480 + case cJU_JPBRANCH_B: SM3PREPB( cJU_ROOTSTATE, SM3BranchB);
1481 +
1482 +SM3BranchB:
1483 + Pjbb = P_JBB(Pjp->jp_Addr);
1484 +#ifdef JUDYPREV
1485 + subexp = cJU_NUMSUBEXPB;
1486 +
1487 + while (! (JU_JBB_BITMAP(Pjbb, --subexp))) // find non-empty subexp.
1488 + {
1489 + if (subexp <= 0) // wholly empty bitmap.
1490 + {
1491 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1492 + JUDY1CODE(return(JERRI );)
1493 + JUDYLCODE(return(PPJERR);)
1494 + }
1495 + }
1496 +
1497 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
1498 + // expected range:
1499 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
1500 +#else
1501 + subexp = -1;
1502 +
1503 + while (! (JU_JBB_BITMAP(Pjbb, ++subexp))) // find non-empty subexp.
1504 + {
1505 + if (subexp >= cJU_NUMSUBEXPB - 1) // didnt find one.
1506 + {
1507 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1508 + JUDY1CODE(return(JERRI );)
1509 + JUDYLCODE(return(PPJERR);)
1510 + }
1511 + }
1512 +
1513 + offset = 0;
1514 +#endif
1515 +
1516 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp), offset);
1517 + JU_SETDIGIT(*PIndex, digit, state);
1518 +
1519 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
1520 + {
1521 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1522 + JUDY1CODE(return(JERRI );)
1523 + JUDYLCODE(return(PPJERR);)
1524 + }
1525 +
1526 + Pjp += offset;
1527 + goto SM3Findlimit;
1528 +
1529 +
1530 +// ----------------------------------------------------------------------------
1531 +// UNCOMPRESSED BRANCH:
1532 +//
1533 +// Look for the highest/lowest (right/left-most) non-null JP, and use it, but
1534 +// first copy Dcd bytes to *PIndex if there are any (only if state <
1535 +// cJU_ROOTSTATE - 1).
1536 +
1537 + case cJU_JPBRANCH_U2: SM3PREPB_DCD(2, SM3BranchU);
1538 +#ifndef JU_64BIT
1539 + case cJU_JPBRANCH_U3: SM3PREPB( 3, SM3BranchU);
1540 +#else
1541 + case cJU_JPBRANCH_U3: SM3PREPB_DCD(3, SM3BranchU);
1542 + case cJU_JPBRANCH_U4: SM3PREPB_DCD(4, SM3BranchU);
1543 + case cJU_JPBRANCH_U5: SM3PREPB_DCD(5, SM3BranchU);
1544 + case cJU_JPBRANCH_U6: SM3PREPB_DCD(6, SM3BranchU);
1545 + case cJU_JPBRANCH_U7: SM3PREPB( 7, SM3BranchU);
1546 +#endif
1547 + case cJU_JPBRANCH_U: SM3PREPB( cJU_ROOTSTATE, SM3BranchU);
1548 +
1549 +SM3BranchU:
1550 + Pjbu = P_JBU(Pjp->jp_Addr);
1551 +#ifdef JUDYPREV
1552 + digit = cJU_BRANCHUNUMJPS;
1553 +
1554 + while (digit >= 1)
1555 + {
1556 + Pjp = (Pjbu->jbu_jp) + (--digit);
1557 +#else
1558 +
1559 + for (digit = 0; digit < cJU_BRANCHUNUMJPS; ++digit)
1560 + {
1561 + Pjp = (Pjbu->jbu_jp) + digit;
1562 +#endif
1563 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
1564 +
1565 + JU_SETDIGIT(*PIndex, digit, state);
1566 + goto SM3Findlimit;
1567 + }
1568 +
1569 +// No non-null JPs in BranchU:
1570 +
1571 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1572 + JUDY1CODE(return(JERRI );)
1573 + JUDYLCODE(return(PPJERR);)
1574 +
1575 +
1576 +// ----------------------------------------------------------------------------
1577 +// LINEAR LEAF:
1578 +//
1579 +// Simply use the highest/lowest (right/left-most) Index in the LeafL, but the
1580 +// details vary depending on leaf Index Size. First copy Dcd bytes, if there
1581 +// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.
1582 +
1583 +#define SM3LEAFLDCD(cState) \
1584 + JU_SETDCD(*PIndex, Pjp, cState); \
1585 + SM3LEAFLNODCD
1586 +
1587 +#ifdef JUDY1
1588 +#define SM3LEAFL_SETPOP1 // not needed in any cases.
1589 +#else
1590 +#define SM3LEAFL_SETPOP1 pop1 = JU_JPLEAF_POP0(Pjp) + 1
1591 +#endif
1592 +
1593 +#ifdef JUDYPREV
1594 +#define SM3LEAFLNODCD \
1595 + Pjll = P_JLL(Pjp->jp_Addr); \
1596 + SM3LEAFL_SETPOP1; \
1597 + offset = JU_JPLEAF_POP0(Pjp); assert(offset >= 0)
1598 +#else
1599 +#define SM3LEAFLNODCD \
1600 + Pjll = P_JLL(Pjp->jp_Addr); \
1601 + SM3LEAFL_SETPOP1; \
1602 + offset = 0; assert(JU_JPLEAF_POP0(Pjp) >= 0);
1603 +#endif
1604 +
1605 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1606 + case cJU_JPLEAF1:
1607 +
1608 + SM3LEAFLDCD(1);
1609 + JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
1610 + JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
1611 +#endif
1612 +
1613 + case cJU_JPLEAF2:
1614 +
1615 + SM3LEAFLDCD(2);
1616 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
1617 + | ((uint16_t *) Pjll)[offset];
1618 + JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
1619 +
1620 +#ifndef JU_64BIT
1621 + case cJU_JPLEAF3:
1622 + {
1623 + Word_t lsb;
1624 + SM3LEAFLNODCD;
1625 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
1626 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1627 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
1628 + }
1629 +
1630 +#else
1631 + case cJU_JPLEAF3:
1632 + {
1633 + Word_t lsb;
1634 + SM3LEAFLDCD(3);
1635 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
1636 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1637 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
1638 + }
1639 +
1640 + case cJU_JPLEAF4:
1641 +
1642 + SM3LEAFLDCD(4);
1643 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
1644 + | ((uint32_t *) Pjll)[offset];
1645 + JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
1646 +
1647 + case cJU_JPLEAF5:
1648 + {
1649 + Word_t lsb;
1650 + SM3LEAFLDCD(5);
1651 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
1652 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
1653 + JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
1654 + }
1655 +
1656 + case cJU_JPLEAF6:
1657 + {
1658 + Word_t lsb;
1659 + SM3LEAFLDCD(6);
1660 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
1661 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
1662 + JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
1663 + }
1664 +
1665 + case cJU_JPLEAF7:
1666 + {
1667 + Word_t lsb;
1668 + SM3LEAFLNODCD;
1669 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
1670 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
1671 + JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
1672 + }
1673 +#endif
1674 +
1675 +
1676 +// ----------------------------------------------------------------------------
1677 +// BITMAP LEAF:
1678 +//
1679 +// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
1680 +// the highest/lowest Index in that subexpanse, but first copy Dcd bytes
1681 +// (always present since state 1 < cJU_ROOTSTATE) to *PIndex.
1682 +
1683 + case cJU_JPLEAF_B1:
1684 + {
1685 + Pjlb_t Pjlb;
1686 +
1687 + JU_SETDCD(*PIndex, Pjp, 1);
1688 +
1689 + Pjlb = P_JLB(Pjp->jp_Addr);
1690 +#ifdef JUDYPREV
1691 + subexp = cJU_NUMSUBEXPL;
1692 +
1693 + while (! JU_JLB_BITMAP(Pjlb, --subexp)) // find non-empty subexp.
1694 + {
1695 + if (subexp <= 0) // wholly empty bitmap.
1696 + {
1697 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1698 + JUDY1CODE(return(JERRI );)
1699 + JUDYLCODE(return(PPJERR);)
1700 + }
1701 + }
1702 +
1703 +// TBD: Might it be faster to just use a variant of BITMAPDIGIT*() that yields
1704 +// the digit for the right-most Index with a bit set?
1705 +
1706 + offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
1707 + // expected range:
1708 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPL));
1709 +#else
1710 + subexp = -1;
1711 +
1712 + while (! JU_JLB_BITMAP(Pjlb, ++subexp)) // find non-empty subexp.
1713 + {
1714 + if (subexp >= cJU_NUMSUBEXPL - 1) // didnt find one.
1715 + {
1716 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1717 + JUDY1CODE(return(JERRI );)
1718 + JUDYLCODE(return(PPJERR);)
1719 + }
1720 + }
1721 +
1722 + offset = 0;
1723 +#endif
1724 +
1725 + JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
1726 + JU_SETDIGIT1(*PIndex, digit);
1727 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1728 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1729 +
1730 + } // case cJU_JPLEAF_B1
1731 +
1732 +#ifdef JUDY1
1733 +// ----------------------------------------------------------------------------
1734 +// FULL POPULATION:
1735 +//
1736 +// Copy Dcd bytes to *PIndex (always present since state 1 < cJU_ROOTSTATE),
1737 +// then set the highest/lowest possible digit as the LSB in *PIndex.
1738 +
1739 + case cJ1_JPFULLPOPU1:
1740 +
1741 + JU_SETDCD( *PIndex, Pjp, 1);
1742 +#ifdef JUDYPREV
1743 + JU_SETDIGIT1(*PIndex, cJU_BITSPERBITMAP - 1);
1744 +#else
1745 + JU_SETDIGIT1(*PIndex, 0);
1746 +#endif
1747 + JU_RET_FOUND_FULLPOPU1;
1748 +#endif // JUDY1
1749 +
1750 +
1751 +// ----------------------------------------------------------------------------
1752 +// IMMEDIATE:
1753 +//
1754 +// Simply use the highest/lowest (right/left-most) Index in the Imm, but the
1755 +// details vary depending on leaf Index Size and pop1. Note: There are no Dcd
1756 +// bytes in an Immediate JP, but in a cJU_JPIMMED_*_01 JP, the field holds the
1757 +// least bytes of the immediate Index.
1758 +
1759 + case cJU_JPIMMED_1_01: SET_01(1); goto SM3Imm_01;
1760 + case cJU_JPIMMED_2_01: SET_01(2); goto SM3Imm_01;
1761 + case cJU_JPIMMED_3_01: SET_01(3); goto SM3Imm_01;
1762 +#ifdef JU_64BIT
1763 + case cJU_JPIMMED_4_01: SET_01(4); goto SM3Imm_01;
1764 + case cJU_JPIMMED_5_01: SET_01(5); goto SM3Imm_01;
1765 + case cJU_JPIMMED_6_01: SET_01(6); goto SM3Imm_01;
1766 + case cJU_JPIMMED_7_01: SET_01(7); goto SM3Imm_01;
1767 +#endif
1768 +SM3Imm_01: JU_RET_FOUND_IMM_01(Pjp);
1769 +
1770 +#ifdef JUDYPREV
1771 +#define SM3IMM_OFFSET(cPop1) (cPop1) - 1 // highest.
1772 +#else
1773 +#define SM3IMM_OFFSET(cPop1) 0 // lowest.
1774 +#endif
1775 +
1776 +#define SM3IMM(cPop1,Next) \
1777 + offset = SM3IMM_OFFSET(cPop1); \
1778 + goto Next
1779 +
1780 + case cJU_JPIMMED_1_02: SM3IMM( 2, SM3Imm1);
1781 + case cJU_JPIMMED_1_03: SM3IMM( 3, SM3Imm1);
1782 +#if (defined(JUDY1) || defined(JU_64BIT))
1783 + case cJU_JPIMMED_1_04: SM3IMM( 4, SM3Imm1);
1784 + case cJU_JPIMMED_1_05: SM3IMM( 5, SM3Imm1);
1785 + case cJU_JPIMMED_1_06: SM3IMM( 6, SM3Imm1);
1786 + case cJU_JPIMMED_1_07: SM3IMM( 7, SM3Imm1);
1787 +#endif
1788 +#if (defined(JUDY1) && defined(JU_64BIT))
1789 + case cJ1_JPIMMED_1_08: SM3IMM( 8, SM3Imm1);
1790 + case cJ1_JPIMMED_1_09: SM3IMM( 9, SM3Imm1);
1791 + case cJ1_JPIMMED_1_10: SM3IMM(10, SM3Imm1);
1792 + case cJ1_JPIMMED_1_11: SM3IMM(11, SM3Imm1);
1793 + case cJ1_JPIMMED_1_12: SM3IMM(12, SM3Imm1);
1794 + case cJ1_JPIMMED_1_13: SM3IMM(13, SM3Imm1);
1795 + case cJ1_JPIMMED_1_14: SM3IMM(14, SM3Imm1);
1796 + case cJ1_JPIMMED_1_15: SM3IMM(15, SM3Imm1);
1797 +#endif
1798 +
1799 +SM3Imm1: JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
1800 + JU_RET_FOUND_IMM(Pjp, offset);
1801 +
1802 +#if (defined(JUDY1) || defined(JU_64BIT))
1803 + case cJU_JPIMMED_2_02: SM3IMM(2, SM3Imm2);
1804 + case cJU_JPIMMED_2_03: SM3IMM(3, SM3Imm2);
1805 +#endif
1806 +#if (defined(JUDY1) && defined(JU_64BIT))
1807 + case cJ1_JPIMMED_2_04: SM3IMM(4, SM3Imm2);
1808 + case cJ1_JPIMMED_2_05: SM3IMM(5, SM3Imm2);
1809 + case cJ1_JPIMMED_2_06: SM3IMM(6, SM3Imm2);
1810 + case cJ1_JPIMMED_2_07: SM3IMM(7, SM3Imm2);
1811 +#endif
1812 +
1813 +#if (defined(JUDY1) || defined(JU_64BIT))
1814 +SM3Imm2: *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
1815 + | ((uint16_t *) PJI)[offset];
1816 + JU_RET_FOUND_IMM(Pjp, offset);
1817 +#endif
1818 +
1819 +#if (defined(JUDY1) || defined(JU_64BIT))
1820 + case cJU_JPIMMED_3_02: SM3IMM(2, SM3Imm3);
1821 +#endif
1822 +#if (defined(JUDY1) && defined(JU_64BIT))
1823 + case cJ1_JPIMMED_3_03: SM3IMM(3, SM3Imm3);
1824 + case cJ1_JPIMMED_3_04: SM3IMM(4, SM3Imm3);
1825 + case cJ1_JPIMMED_3_05: SM3IMM(5, SM3Imm3);
1826 +#endif
1827 +
1828 +#if (defined(JUDY1) || defined(JU_64BIT))
1829 +SM3Imm3:
1830 + {
1831 + Word_t lsb;
1832 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
1833 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1834 + JU_RET_FOUND_IMM(Pjp, offset);
1835 + }
1836 +#endif
1837 +
1838 +#if (defined(JUDY1) && defined(JU_64BIT))
1839 + case cJ1_JPIMMED_4_02: SM3IMM(2, SM3Imm4);
1840 + case cJ1_JPIMMED_4_03: SM3IMM(3, SM3Imm4);
1841 +
1842 +SM3Imm4: *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
1843 + | ((uint32_t *) PJI)[offset];
1844 + JU_RET_FOUND_IMM(Pjp, offset);
1845 +
1846 + case cJ1_JPIMMED_5_02: SM3IMM(2, SM3Imm5);
1847 + case cJ1_JPIMMED_5_03: SM3IMM(3, SM3Imm5);
1848 +
1849 +SM3Imm5:
1850 + {
1851 + Word_t lsb;
1852 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
1853 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
1854 + JU_RET_FOUND_IMM(Pjp, offset);
1855 + }
1856 +
1857 + case cJ1_JPIMMED_6_02: SM3IMM(2, SM3Imm6);
1858 +
1859 +SM3Imm6:
1860 + {
1861 + Word_t lsb;
1862 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
1863 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
1864 + JU_RET_FOUND_IMM(Pjp, offset);
1865 + }
1866 +
1867 + case cJ1_JPIMMED_7_02: SM3IMM(2, SM3Imm7);
1868 +
1869 +SM3Imm7:
1870 + {
1871 + Word_t lsb;
1872 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
1873 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
1874 + JU_RET_FOUND_IMM(Pjp, offset);
1875 + }
1876 +#endif // (JUDY1 && JU_64BIT)
1877 +
1878 +
1879 +// ----------------------------------------------------------------------------
1880 +// OTHER CASES:
1881 +
1882 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1883 + JUDY1CODE(return(JERRI );)
1884 + JUDYLCODE(return(PPJERR);)
1885 +
1886 + } // SM3Findlimit switch.
1887 +
1888 + /*NOTREACHED*/
1889 +
1890 +} // Judy1Prev() / Judy1Next() / JudyLPrev() / JudyLNext()
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c new
+1390
@@ -0,0 +1,1390 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.32 $ $Source: /judy/src/JudyCommon/JudyPrevNextEmpty.c $
19 +//
20 +// Judy*PrevEmpty() and Judy*NextEmpty() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DJUDYNEXT for the Judy*NextEmpty() function; otherwise
24 +// defaults to Judy*PrevEmpty().
25 +//
26 +// Compile with -DTRACEJPSE to trace JP traversals.
27 +//
28 +// This file is separate from JudyPrevNext.c because it differs too greatly for
29 +// ifdefs. This might be a bit surprising, but there are two reasons:
30 +//
31 +// - First, down in the details, searching for an empty index (SearchEmpty) is
32 +// remarkably asymmetric with searching for a valid index (SearchValid),
33 +// mainly with respect to: No return of a value area for JudyL; partially-
34 +// full versus totally-full JPs; and handling of narrow pointers.
35 +//
36 +// - Second, we chose to implement SearchEmpty without a backtrack stack or
37 +// backtrack engine, partly as an experiment, and partly because we think
38 +// restarting from the top of the tree is less likely for SearchEmpty than
39 +// for SearchValid, because empty indexes are more likely than valid indexes.
40 +//
41 +// A word about naming: A prior version of this feature (see 4.13) was named
42 +// Judy*Free(), but there were concerns about that being read as a verb rather
43 +// than an adjective. After prolonged debate and based on user input, we
44 +// changed "Free" to "Empty".
45 +
46 +#if (! (defined(JUDY1) || defined(JUDYL)))
47 +#error: One of -DJUDY1 or -DJUDYL must be specified.
48 +#endif
49 +
50 +#ifndef JUDYNEXT
51 +#ifndef JUDYPREV
52 +#define JUDYPREV 1 // neither set => use default.
53 +#endif
54 +#endif
55 +
56 +#ifdef JUDY1
57 +#include "Judy1.h"
58 +#else
59 +#include "JudyL.h"
60 +#endif
61 +
62 +#include "JudyPrivate1L.h"
63 +
64 +#ifdef TRACEJPSE
65 +#include "JudyPrintJP.c"
66 +#endif
67 +
68 +
69 +// ****************************************************************************
70 +// J U D Y 1 P R E V E M P T Y
71 +// J U D Y 1 N E X T E M P T Y
72 +// J U D Y L P R E V E M P T Y
73 +// J U D Y L N E X T E M P T Y
74 +//
75 +// See the manual entry for the API.
76 +//
77 +// OVERVIEW OF Judy*PrevEmpty() / Judy*NextEmpty():
78 +//
79 +// See also for comparison the equivalent comments in JudyPrevNext.c.
80 +//
81 +// Take the callers *PIndex and subtract/add 1, but watch out for
82 +// underflow/overflow, which means "no previous/next empty index found." Use a
83 +// reentrant switch statement (state machine, see SMGetRestart and
84 +// SMGetContinue) to decode Index, starting with the JRP (PArray), through a
85 +// JPM and branches, if any, down to an immediate or a leaf. Look for Index in
86 +// that immediate or leaf, and if not found (invalid index), return success
87 +// (Index is empty).
88 +//
89 +// This search can result in a dead end where taking a different path is
90 +// required. There are four kinds of dead ends:
91 +//
92 +// BRANCH PRIMARY dead end: Encountering a fully-populated JP for the
93 +// appropriate digit in Index. Search sideways in the branch for the
94 +// previous/next absent/null/non-full JP, and if one is found, set Index to the
95 +// highest/lowest index possible in that JPs expanse. Then if the JP is an
96 +// absent or null JP, return success; otherwise for a non-full JP, traverse
97 +// through the partially populated JP.
98 +//
99 +// BRANCH SECONDARY dead end: Reaching the end of a branch during a sideways
100 +// search after a branch primary dead end. Set Index to the lowest/highest
101 +// index possible in the whole branchs expanse (one higher/lower than the
102 +// previous/next branchs expanse), then restart at the top of the tree, which
103 +// includes pre-decrementing/incrementing Index (again) and watching for
104 +// underflow/overflow (again).
105 +//
106 +// LEAF PRIMARY dead end: Finding a valid (non-empty) index in an immediate or
107 +// leaf matching Index. Search sideways in the immediate/leaf for the
108 +// previous/next empty index; if found, set *PIndex to match and return success.
109 +//
110 +// LEAF SECONDARY dead end: Reaching the end of an immediate or leaf during a
111 +// sideways search after a leaf primary dead end. Just as for a branch
112 +// secondary dead end, restart at the top of the tree with Index set to the
113 +// lowest/highest index possible in the whole immediate/leafs expanse.
114 +// TBD: If leaf secondary dead end occurs, could shortcut and treat it as a
115 +// branch primary dead end; but this would require remembering the parent
116 +// branchs type and offset (a "one-deep stack"), and also wrestling with
117 +// narrow pointers, at least for leaves (but not for immediates).
118 +//
119 +// Note some ASYMMETRIES between SearchValid and SearchEmpty:
120 +//
121 +// - The SearchValid code, upon descending through a narrow pointer, if Index
122 +// is outside the expanse of the subsidiary node (effectively a secondary
123 +// dead end), must decide whether to backtrack or findlimit. But the
124 +// SearchEmpty code simply returns success (Index is empty).
125 +//
126 +// - Similarly, the SearchValid code, upon finding no previous/next index in
127 +// the expanse of a narrow pointer (again, a secondary dead end), can simply
128 +// start to backtrack at the parent JP. But the SearchEmpty code would have
129 +// to first determine whether or not the parent JPs narrow expanse contains
130 +// a previous/next empty index outside the subexpanse. Rather than keeping a
131 +// parent state stack and backtracking this way, upon a secondary dead end,
132 +// the SearchEmpty code simply restarts at the top of the tree, whether or
133 +// not a narrow pointer is involved. Again, see the equivalent comments in
134 +// JudyPrevNext.c for comparison.
135 +//
136 +// This function is written iteratively for speed, rather than recursively.
137 +//
138 +// TBD: Wed like to enhance this function to make successive searches faster.
139 +// This would require saving some previous state, including the previous Index
140 +// returned, and in which leaf it was found. If the next call is for the same
141 +// Index and the array has not been modified, start at the same leaf. This
142 +// should be much easier to implement since this is iterative rather than
143 +// recursive code.
144 +
145 +#ifdef JUDY1
146 +#ifdef JUDYPREV
147 +FUNCTION int Judy1PrevEmpty
148 +#else
149 +FUNCTION int Judy1NextEmpty
150 +#endif
151 +#else
152 +#ifdef JUDYPREV
153 +FUNCTION int JudyLPrevEmpty
154 +#else
155 +FUNCTION int JudyLNextEmpty
156 +#endif
157 +#endif
158 + (
159 + Pcvoid_t PArray, // Judy array to search.
160 + Word_t * PIndex, // starting point and result.
161 + PJError_t PJError // optional, for returning error info.
162 + )
163 +{
164 + Word_t Index; // fast copy, in a register.
165 + Pjp_t Pjp; // current JP.
166 + Pjbl_t Pjbl; // Pjp->jp_Addr masked and cast to types:
167 + Pjbb_t Pjbb;
168 + Pjbu_t Pjbu;
169 + Pjlb_t Pjlb;
170 + PWord_t Pword; // alternate name for use by GET* macros.
171 +
172 + Word_t digit; // next digit to decode from Index.
173 + Word_t digits; // current state in SM = digits left to decode.
174 + Word_t pop0; // in a leaf.
175 + Word_t pop0mask; // precalculated to avoid variable shifts.
176 + long offset; // within a branch or leaf (can be large).
177 + int subexp; // subexpanse in a bitmap branch.
178 + BITMAPB_t bitposmaskB; // bit in bitmap for bitmap branch.
179 + BITMAPL_t bitposmaskL; // bit in bitmap for bitmap leaf.
180 + Word_t possfullJP1; // JP types for possibly full subexpanses:
181 + Word_t possfullJP2;
182 + Word_t possfullJP3;
183 +
184 +
185 +// ----------------------------------------------------------------------------
186 +// M A C R O S
187 +//
188 +// These are intended to make the code a bit more readable and less redundant.
189 +
190 +
191 +// CHECK FOR NULL JP:
192 +//
193 +// TBD: In principle this can be reduced (here and in other *.c files) to just
194 +// the latter clause since no Type should ever be below cJU_JPNULL1, but in
195 +// fact some root pointer types can be lower, so for safety do both checks.
196 +
197 +#define JPNULL(Type) (((Type) >= cJU_JPNULL1) && ((Type) <= cJU_JPNULLMAX))
198 +
199 +
200 +// CHECK FOR A FULL JP:
201 +//
202 +// Given a JP, indicate if it is fully populated. Use digits, pop0mask, and
203 +// possfullJP1..3 in the context.
204 +//
205 +// This is a difficult problem because it requires checking the Pop0 bits for
206 +// all-ones, but the number of bytes depends on the JP type, which is not
207 +// directly related to the parent branchs type or level -- the JPs child
208 +// could be under a narrow pointer (hence not full). The simple answer
209 +// requires switching on or otherwise calculating the JP type, which could be
210 +// slow. Instead, in SMPREPB* precalculate pop0mask and also record in
211 +// possfullJP1..3 the child JP (branch) types that could possibly be full (one
212 +// level down), and use them here. For level-2 branches (with digits == 2),
213 +// the test for a full child depends on Judy1/JudyL.
214 +//
215 +// Note: This cannot be applied to the JP in a JPM because it doesnt have
216 +// enough pop0 digits.
217 +//
218 +// TBD: JPFULL_BRANCH diligently checks for BranchL or BranchB, where neither
219 +// of those can ever be full as it turns out. Could just check for a BranchU
220 +// at the right level. Also, pop0mask might be overkill, its not used much,
221 +// so perhaps just call cJU_POP0MASK(digits - 1) here?
222 +//
223 +// First, JPFULL_BRANCH checks for a full expanse for a JP whose child can be a
224 +// branch, that is, a JP in a branch at level 3 or higher:
225 +
226 +#define JPFULL_BRANCH(Pjp) \
227 + ((((JU_JPDCDPOP0(Pjp) ^ cJU_ALLONES) & pop0mask) == 0) \
228 + && ((JU_JPTYPE(Pjp) == possfullJP1) \
229 + || (JU_JPTYPE(Pjp) == possfullJP2) \
230 + || (JU_JPTYPE(Pjp) == possfullJP3)))
231 +
232 +#ifdef JUDY1
233 +#define JPFULL(Pjp) \
234 + ((digits == 2) ? \
235 + (JU_JPTYPE(Pjp) == cJ1_JPFULLPOPU1) : JPFULL_BRANCH(Pjp))
236 +#else
237 +#define JPFULL(Pjp) \
238 + ((digits == 2) ? \
239 + (JU_JPTYPE(Pjp) == cJU_JPLEAF_B1) \
240 + && (((JU_JPDCDPOP0(Pjp) & cJU_POP0MASK(1)) == cJU_POP0MASK(1))) : \
241 + JPFULL_BRANCH(Pjp))
242 +#endif
243 +
244 +
245 +// RETURN SUCCESS:
246 +//
247 +// This hides the need to set *PIndex back to the local value of Index -- use a
248 +// local value for faster operation. Note that the callers *PIndex is ALWAYS
249 +// modified upon success, at least decremented/incremented.
250 +
251 +#define RET_SUCCESS { *PIndex = Index; return(1); }
252 +
253 +
254 +// RETURN A CORRUPTION:
255 +
256 +#define RET_CORRUPT { JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); return(JERRI); }
257 +
258 +
259 +// SEARCH A BITMAP BRANCH:
260 +//
261 +// This is a weak analog of j__udySearchLeaf*() for bitmap branches. Return
262 +// the actual or next-left position, base 0, of Digit in a BITMAPB_t bitmap
263 +// (subexpanse of a full bitmap), also given a Bitposmask for Digit. The
264 +// position is the offset within the set bits.
265 +//
266 +// Unlike j__udySearchLeaf*(), the offset is not returned bit-complemented if
267 +// Digits bit is unset, because the caller can check the bitmap themselves to
268 +// determine that. Also, if Digits bit is unset, the returned offset is to
269 +// the next-left JP or index (including -1), not to the "ideal" position for
270 +// the index = next-right JP or index.
271 +//
272 +// Shortcut and skip calling j__udyCountBitsB() if the bitmap is full, in which
273 +// case (Digit % cJU_BITSPERSUBEXPB) itself is the base-0 offset.
274 +
275 +#define SEARCHBITMAPB(Bitmap,Digit,Bitposmask) \
276 + (((Bitmap) == cJU_FULLBITMAPB) ? (Digit % cJU_BITSPERSUBEXPB) : \
277 + j__udyCountBitsB((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
278 +
279 +#ifdef JUDYPREV
280 +// Equivalent to search for the highest offset in Bitmap, that is, one less
281 +// than the number of bits set:
282 +
283 +#define SEARCHBITMAPMAXB(Bitmap) \
284 + (((Bitmap) == cJU_FULLBITMAPB) ? cJU_BITSPERSUBEXPB - 1 : \
285 + j__udyCountBitsB(Bitmap) - 1)
286 +#endif
287 +
288 +
289 +// CHECK DECODE BYTES:
290 +//
291 +// Check Decode bytes in a JP against the equivalent portion of Index. If they
292 +// dont match, Index is outside the subexpanse of a narrow pointer, hence is
293 +// empty.
294 +
295 +#define CHECKDCD(cDigits) \
296 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, cDigits)) RET_SUCCESS
297 +
298 +
299 +// REVISE REMAINDER OF INDEX:
300 +//
301 +// Put one digit in place in Index and clear/set the lower digits, if any, so
302 +// the resulting Index is at the start/end of an expanse, or just clear/set the
303 +// least digits.
304 +//
305 +// Actually, to make simple use of JU_LEASTBYTESMASK, first clear/set all least
306 +// digits of Index including the digit to be overridden, then set the value of
307 +// that one digit. If Digits == 1 the first operation is redundant, but either
308 +// very fast or even removed by the optimizer.
309 +
310 +#define CLEARLEASTDIGITS(Digits) Index &= ~JU_LEASTBYTESMASK(Digits)
311 +#define SETLEASTDIGITS( Digits) Index |= JU_LEASTBYTESMASK(Digits)
312 +
313 +#define CLEARLEASTDIGITS_D(Digit,Digits) \
314 + { \
315 + CLEARLEASTDIGITS(Digits); \
316 + JU_SETDIGIT(Index, Digit, Digits); \
317 + }
318 +
319 +#define SETLEASTDIGITS_D(Digit,Digits) \
320 + { \
321 + SETLEASTDIGITS(Digits); \
322 + JU_SETDIGIT(Index, Digit, Digits); \
323 + }
324 +
325 +
326 +// SET REMAINDER OF INDEX AND THEN RETURN OR CONTINUE:
327 +
328 +#define SET_AND_RETURN(OpLeastDigits,Digit,Digits) \
329 + { \
330 + OpLeastDigits(Digit, Digits); \
331 + RET_SUCCESS; \
332 + }
333 +
334 +#define SET_AND_CONTINUE(OpLeastDigits,Digit,Digits) \
335 + { \
336 + OpLeastDigits(Digit, Digits); \
337 + goto SMGetContinue; \
338 + }
339 +
340 +
341 +// PREPARE TO HANDLE A LEAFW OR JP BRANCH IN THE STATE MACHINE:
342 +//
343 +// Extract a state-dependent digit from Index in a "constant" way, then jump to
344 +// common code for multiple cases.
345 +//
346 +// TBD: Should this macro do more, such as preparing variable-shift masks for
347 +// use in CLEARLEASTDIGITS and SETLEASTDIGITS?
348 +
349 +#define SMPREPB(cDigits,Next,PossFullJP1,PossFullJP2,PossFullJP3) \
350 + digits = (cDigits); \
351 + digit = JU_DIGITATSTATE(Index, cDigits); \
352 + pop0mask = cJU_POP0MASK((cDigits) - 1); /* for branchs JPs */ \
353 + possfullJP1 = (PossFullJP1); \
354 + possfullJP2 = (PossFullJP2); \
355 + possfullJP3 = (PossFullJP3); \
356 + goto Next
357 +
358 +// Variations for specific-level branches and for shorthands:
359 +//
360 +// Note: SMPREPB2 need not initialize possfullJP* because JPFULL does not use
361 +// them for digits == 2, but gcc -Wall isnt quite smart enough to see this, so
362 +// waste a bit of time and space to get rid of the warning:
363 +
364 +#define SMPREPB2(Next) \
365 + digits = 2; \
366 + digit = JU_DIGITATSTATE(Index, 2); \
367 + pop0mask = cJU_POP0MASK(1); /* for branchs JPs */ \
368 + possfullJP1 = possfullJP2 = possfullJP3 = 0; \
369 + goto Next
370 +
371 +#define SMPREPB3(Next) SMPREPB(3, Next, cJU_JPBRANCH_L2, \
372 + cJU_JPBRANCH_B2, \
373 + cJU_JPBRANCH_U2)
374 +#ifndef JU_64BIT
375 +#define SMPREPBL(Next) SMPREPB(cJU_ROOTSTATE, Next, cJU_JPBRANCH_L3, \
376 + cJU_JPBRANCH_B3, \
377 + cJU_JPBRANCH_U3)
378 +#else
379 +#define SMPREPB4(Next) SMPREPB(4, Next, cJU_JPBRANCH_L3, \
380 + cJU_JPBRANCH_B3, \
381 + cJU_JPBRANCH_U3)
382 +#define SMPREPB5(Next) SMPREPB(5, Next, cJU_JPBRANCH_L4, \
383 + cJU_JPBRANCH_B4, \
384 + cJU_JPBRANCH_U4)
385 +#define SMPREPB6(Next) SMPREPB(6, Next, cJU_JPBRANCH_L5, \
386 + cJU_JPBRANCH_B5, \
387 + cJU_JPBRANCH_U5)
388 +#define SMPREPB7(Next) SMPREPB(7, Next, cJU_JPBRANCH_L6, \
389 + cJU_JPBRANCH_B6, \
390 + cJU_JPBRANCH_U6)
391 +#define SMPREPBL(Next) SMPREPB(cJU_ROOTSTATE, Next, cJU_JPBRANCH_L7, \
392 + cJU_JPBRANCH_B7, \
393 + cJU_JPBRANCH_U7)
394 +#endif
395 +
396 +
397 +// RESTART AFTER SECONDARY DEAD END:
398 +//
399 +// Set Index to the first/last index in the branch or leaf subexpanse and start
400 +// over at the top of the tree.
401 +
402 +#ifdef JUDYPREV
403 +#define SMRESTART(Digits) { CLEARLEASTDIGITS(Digits); goto SMGetRestart; }
404 +#else
405 +#define SMRESTART(Digits) { SETLEASTDIGITS( Digits); goto SMGetRestart; }
406 +#endif
407 +
408 +
409 +// CHECK EDGE OF LEAFS EXPANSE:
410 +//
411 +// Given the LSBs of the lowest/highest valid index in a leaf (or equivalently
412 +// in an immediate JP), the level (index size) of the leaf, and the full index
413 +// to return (as Index in the context) already set to the full index matching
414 +// the lowest/highest one, determine if there is an empty index in the leafs
415 +// expanse below/above the lowest/highest index, which is true if the
416 +// lowest/highest index is not at the "edge" of the leafs expanse based on its
417 +// LSBs. If so, return Index decremented/incremented; otherwise restart at the
418 +// top of the tree.
419 +//
420 +// Note: In many cases Index is already at the right spot and calling
421 +// SMRESTART instead of just going directly to SMGetRestart is a bit of
422 +// overkill.
423 +//
424 +// Note: Variable shift occurs if Digits is not a constant.
425 +
426 +#ifdef JUDYPREV
427 +#define LEAF_EDGE(MinIndex,Digits) \
428 + { \
429 + if (MinIndex) { --Index; RET_SUCCESS; } \
430 + SMRESTART(Digits); \
431 + }
432 +#else
433 +#define LEAF_EDGE(MaxIndex,Digits) \
434 + { \
435 + if ((MaxIndex) != JU_LEASTBYTES(cJU_ALLONES, Digits)) \
436 + { ++Index; RET_SUCCESS; } \
437 + SMRESTART(Digits); \
438 + }
439 +#endif
440 +
441 +// Same as above except Index is not already set to match the lowest/highest
442 +// index, so do that before decrementing/incrementing it:
443 +
444 +#ifdef JUDYPREV
445 +#define LEAF_EDGE_SET(MinIndex,Digits) \
446 + { \
447 + if (MinIndex) \
448 + { JU_SETDIGITS(Index, MinIndex, Digits); --Index; RET_SUCCESS; } \
449 + SMRESTART(Digits); \
450 + }
451 +#else
452 +#define LEAF_EDGE_SET(MaxIndex,Digits) \
453 + { \
454 + if ((MaxIndex) != JU_LEASTBYTES(cJU_ALLONES, Digits)) \
455 + { JU_SETDIGITS(Index, MaxIndex, Digits); ++Index; RET_SUCCESS; } \
456 + SMRESTART(Digits); \
457 + }
458 +#endif
459 +
460 +
461 +// FIND A HOLE (EMPTY INDEX) IN AN IMMEDIATE OR LEAF:
462 +//
463 +// Given an index location in a leaf (or equivalently an immediate JP) known to
464 +// contain a usable hole (an empty index less/greater than Index), and the LSBs
465 +// of a minimum/maximum index to locate, find the previous/next empty index and
466 +// return it.
467 +//
468 +// Note: "Even" index sizes (1,2,4[,8] bytes) have corresponding native C
469 +// types; "odd" index sizes dont, but they are not represented here because
470 +// they are handled completely differently; see elsewhere.
471 +
472 +#ifdef JUDYPREV
473 +
474 +#define LEAF_HOLE_EVEN(cDigits,Pjll,IndexLSB) \
475 + { \
476 + while (*(Pjll) > (IndexLSB)) --(Pjll); /* too high */ \
477 + if (*(Pjll) < (IndexLSB)) RET_SUCCESS /* Index is empty */ \
478 + while (*(--(Pjll)) == --(IndexLSB)) /* null, find a hole */;\
479 + JU_SETDIGITS(Index, IndexLSB, cDigits); \
480 + RET_SUCCESS; \
481 + }
482 +#else
483 +#define LEAF_HOLE_EVEN(cDigits,Pjll,IndexLSB) \
484 + { \
485 + while (*(Pjll) < (IndexLSB)) ++(Pjll); /* too low */ \
486 + if (*(Pjll) > (IndexLSB)) RET_SUCCESS /* Index is empty */ \
487 + while (*(++(Pjll)) == ++(IndexLSB)) /* null, find a hole */;\
488 + JU_SETDIGITS(Index, IndexLSB, cDigits); \
489 + RET_SUCCESS; \
490 + }
491 +#endif
492 +
493 +
494 +// SEARCH FOR AN EMPTY INDEX IN AN IMMEDIATE OR LEAF:
495 +//
496 +// Given a pointer to the first index in a leaf (or equivalently an immediate
497 +// JP), the population of the leaf, and a first empty Index to find (inclusive,
498 +// as Index in the context), where Index is known to fall within the expanse of
499 +// the leaf to search, efficiently find the previous/next empty index in the
500 +// leaf, if any. For simplicity the following overview is stated in terms of
501 +// Judy*NextEmpty() only, but the same concepts apply symmetrically for
502 +// Judy*PrevEmpty(). Also, in each case the comparisons are for the LSBs of
503 +// Index and leaf indexes, according to the leafs level.
504 +//
505 +// 1. If Index is GREATER than the last (highest) index in the leaf
506 +// (maxindex), return success, Index is empty. (Remember, Index is known
507 +// to be in the leafs expanse.)
508 +//
509 +// 2. If Index is EQUAL to maxindex: If maxindex is not at the edge of the
510 +// leafs expanse, increment Index and return success, there is an empty
511 +// Index one higher than any in the leaf; otherwise restart with Index
512 +// reset to the upper edge of the leafs expanse. Note: This might cause
513 +// an extra cache line fill, but this is OK for repeatedly-called search
514 +// code, and it saves CPU time.
515 +//
516 +// 3. If Index is LESS than maxindex, check for "dense to end of leaf":
517 +// Subtract Index from maxindex, and back up that many slots in the leaf.
518 +// If the resulting offset is not before the start of the leaf then compare
519 +// the index at this offset (baseindex) with Index:
520 +//
521 +// 3a. If GREATER, the leaf must be corrupt, since indexes are sorted and
522 +// there are no duplicates.
523 +//
524 +// 3b. If EQUAL, the leaf is "dense" from Index to maxindex, meaning there is
525 +// no reason to search it. "Slide right" to the high end of the leaf
526 +// (modify Index to maxindex) and continue with step 2 above.
527 +//
528 +// 3c. If LESS, continue with step 4.
529 +//
530 +// 4. If the offset based on maxindex minus Index falls BEFORE the start of
531 +// the leaf, or if, per 3c above, baseindex is LESS than Index, the leaf is
532 +// guaranteed "not dense to the end" and a usable empty Index must exist.
533 +// This supports a more efficient search loop. Start at the FIRST index in
534 +// the leaf, or one BEYOND baseindex, respectively, and search the leaf as
535 +// follows, comparing each current index (currindex) with Index:
536 +//
537 +// 4a. If LESS, keep going to next index. Note: This is certain to terminate
538 +// because maxindex is known to be greater than Index, hence the loop can
539 +// be small and fast.
540 +//
541 +// 4b. If EQUAL, loop and increment Index until finding currindex greater than
542 +// Index, and return success with the modified Index.
543 +//
544 +// 4c. If GREATER, return success, Index (unmodified) is empty.
545 +//
546 +// Note: These are macros rather than functions for speed.
547 +
548 +#ifdef JUDYPREV
549 +
550 +#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
551 + { \
552 + LeafType * PjllLSB = (LeafType *) (Addr); \
553 + LeafType IndexLSB = Index; /* auto-masking */ \
554 + \
555 + /* Index before or at start of leaf: */ \
556 + \
557 + if (*PjllLSB >= IndexLSB) /* no need to search */ \
558 + { \
559 + if (*PjllLSB > IndexLSB) RET_SUCCESS; /* Index empty */ \
560 + LEAF_EDGE(*PjllLSB, cDigits); \
561 + } \
562 + \
563 + /* Index in or after leaf: */ \
564 + \
565 + offset = IndexLSB - *PjllLSB; /* tentative offset */ \
566 + if (offset <= (Pop0)) /* can check density */ \
567 + { \
568 + PjllLSB += offset; /* move to slot */ \
569 + \
570 + if (*PjllLSB <= IndexLSB) /* dense or corrupt */ \
571 + { \
572 + if (*PjllLSB == IndexLSB) /* dense, check edge */ \
573 + LEAF_EDGE_SET(PjllLSB[-offset], cDigits); \
574 + RET_CORRUPT; \
575 + } \
576 + --PjllLSB; /* not dense, start at previous */ \
577 + } \
578 + else PjllLSB = ((LeafType *) (Addr)) + (Pop0); /* start at max */ \
579 + \
580 + LEAF_HOLE_EVEN(cDigits, PjllLSB, IndexLSB); \
581 + }
582 +
583 +// JSLE_ODD is completely different from JSLE_EVEN because its important to
584 +// minimize copying odd indexes to compare them (see 4.14). Furthermore, a
585 +// very complex version (4.17, but abandoned before fully debugged) that
586 +// avoided calling j__udySearchLeaf*() ran twice as fast as 4.14, but still
587 +// half as fast as SearchValid. Doug suggested that to minimize complexity and
588 +// share common code we should use j__udySearchLeaf*() for the initial search
589 +// to establish if Index is empty, which should be common. If Index is valid
590 +// in a leaf or immediate indexes, odds are good that an empty Index is nearby,
591 +// so for simplicity just use a *COPY* function to linearly search the
592 +// remainder.
593 +//
594 +// TBD: Pathological case? Average performance should be good, but worst-case
595 +// might suffer. When Search says the initial Index is valid, so a linear
596 +// copy-and-compare is begun, if the caller builds fairly large leaves with
597 +// dense clusters AND frequently does a SearchEmpty at one end of such a
598 +// cluster, performance wont be very good. Might a dense-check help? This
599 +// means checking offset against the index at offset, and then against the
600 +// first/last index in the leaf. We doubt the pathological case will appear
601 +// much in real applications because they will probably alternate SearchValid
602 +// and SearchEmpty calls.
603 +
604 +#define JSLE_ODD(cDigits,Pjll,Pop0,Search,Copy) \
605 + { \
606 + Word_t IndexLSB; /* least bytes only */ \
607 + Word_t IndexFound; /* in leaf */ \
608 + \
609 + if ((offset = Search(Pjll, (Pop0) + 1, Index)) < 0) \
610 + RET_SUCCESS; /* Index is empty */ \
611 + \
612 + IndexLSB = JU_LEASTBYTES(Index, cDigits); \
613 + offset *= (cDigits); \
614 + \
615 + while ((offset -= (cDigits)) >= 0) \
616 + { /* skip until empty or start */ \
617 + Copy(IndexFound, ((uint8_t *) (Pjll)) + offset); \
618 + if (IndexFound != (--IndexLSB)) /* found an empty */ \
619 + { JU_SETDIGITS(Index, IndexLSB, cDigits); RET_SUCCESS; }\
620 + } \
621 + LEAF_EDGE_SET(IndexLSB, cDigits); \
622 + }
623 +
624 +#else // JUDYNEXT
625 +
626 +#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
627 + { \
628 + LeafType * PjllLSB = ((LeafType *) (Addr)) + (Pop0); \
629 + LeafType IndexLSB = Index; /* auto-masking */ \
630 + \
631 + /* Index at or after end of leaf: */ \
632 + \
633 + if (*PjllLSB <= IndexLSB) /* no need to search */ \
634 + { \
635 + if (*PjllLSB < IndexLSB) RET_SUCCESS; /* Index empty */\
636 + LEAF_EDGE(*PjllLSB, cDigits); \
637 + } \
638 + \
639 + /* Index before or in leaf: */ \
640 + \
641 + offset = *PjllLSB - IndexLSB; /* tentative offset */ \
642 + if (offset <= (Pop0)) /* can check density */ \
643 + { \
644 + PjllLSB -= offset; /* move to slot */ \
645 + \
646 + if (*PjllLSB >= IndexLSB) /* dense or corrupt */ \
647 + { \
648 + if (*PjllLSB == IndexLSB) /* dense, check edge */ \
649 + LEAF_EDGE_SET(PjllLSB[offset], cDigits); \
650 + RET_CORRUPT; \
651 + } \
652 + ++PjllLSB; /* not dense, start at next */ \
653 + } \
654 + else PjllLSB = (LeafType *) (Addr); /* start at minimum */ \
655 + \
656 + LEAF_HOLE_EVEN(cDigits, PjllLSB, IndexLSB); \
657 + }
658 +
659 +#define JSLE_ODD(cDigits,Pjll,Pop0,Search,Copy) \
660 + { \
661 + Word_t IndexLSB; /* least bytes only */ \
662 + Word_t IndexFound; /* in leaf */ \
663 + int offsetmax; /* in bytes */ \
664 + \
665 + if ((offset = Search(Pjll, (Pop0) + 1, Index)) < 0) \
666 + RET_SUCCESS; /* Index is empty */ \
667 + \
668 + IndexLSB = JU_LEASTBYTES(Index, cDigits); \
669 + offset *= (cDigits); \
670 + offsetmax = (Pop0) * (cDigits); /* single multiply */ \
671 + \
672 + while ((offset += (cDigits)) <= offsetmax) \
673 + { /* skip until empty or end */ \
674 + Copy(IndexFound, ((uint8_t *) (Pjll)) + offset); \
675 + if (IndexFound != (++IndexLSB)) /* found an empty */ \
676 + { JU_SETDIGITS(Index, IndexLSB, cDigits); RET_SUCCESS; } \
677 + } \
678 + LEAF_EDGE_SET(IndexLSB, cDigits); \
679 + }
680 +
681 +#endif // JUDYNEXT
682 +
683 +// Note: Immediate indexes never fill a single index group, so for odd index
684 +// sizes, save time by calling JSLE_ODD_IMM instead of JSLE_ODD.
685 +
686 +#define j__udySearchLeafEmpty1(Addr,Pop0) \
687 + JSLE_EVEN(Addr, Pop0, 1, uint8_t)
688 +
689 +#define j__udySearchLeafEmpty2(Addr,Pop0) \
690 + JSLE_EVEN(Addr, Pop0, 2, uint16_t)
691 +
692 +#define j__udySearchLeafEmpty3(Addr,Pop0) \
693 + JSLE_ODD(3, Addr, Pop0, j__udySearchLeaf3, JU_COPY3_PINDEX_TO_LONG)
694 +
695 +#ifndef JU_64BIT
696 +
697 +#define j__udySearchLeafEmptyL(Addr,Pop0) \
698 + JSLE_EVEN(Addr, Pop0, 4, Word_t)
699 +
700 +#else
701 +
702 +#define j__udySearchLeafEmpty4(Addr,Pop0) \
703 + JSLE_EVEN(Addr, Pop0, 4, uint32_t)
704 +
705 +#define j__udySearchLeafEmpty5(Addr,Pop0) \
706 + JSLE_ODD(5, Addr, Pop0, j__udySearchLeaf5, JU_COPY5_PINDEX_TO_LONG)
707 +
708 +#define j__udySearchLeafEmpty6(Addr,Pop0) \
709 + JSLE_ODD(6, Addr, Pop0, j__udySearchLeaf6, JU_COPY6_PINDEX_TO_LONG)
710 +
711 +#define j__udySearchLeafEmpty7(Addr,Pop0) \
712 + JSLE_ODD(7, Addr, Pop0, j__udySearchLeaf7, JU_COPY7_PINDEX_TO_LONG)
713 +
714 +#define j__udySearchLeafEmptyL(Addr,Pop0) \
715 + JSLE_EVEN(Addr, Pop0, 8, Word_t)
716 +
717 +#endif // JU_64BIT
718 +
719 +
720 +// ----------------------------------------------------------------------------
721 +// START OF CODE:
722 +//
723 +// CHECK FOR SHORTCUTS:
724 +//
725 +// Error out if PIndex is null.
726 +
727 + if (PIndex == (PWord_t) NULL)
728 + {
729 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
730 + return(JERRI);
731 + }
732 +
733 + Index = *PIndex; // fast local copy.
734 +
735 +// Set and pre-decrement/increment Index, watching for underflow/overflow:
736 +//
737 +// An out-of-bounds Index means failure: No previous/next empty index.
738 +
739 +SMGetRestart: // return here with revised Index.
740 +
741 +#ifdef JUDYPREV
742 + if (Index-- == 0) return(0);
743 +#else
744 + if (++Index == 0) return(0);
745 +#endif
746 +
747 +// An empty array with an in-bounds (not underflowed/overflowed) Index means
748 +// success:
749 +//
750 +// Note: This check is redundant after restarting at SMGetRestart, but should
751 +// take insignificant time.
752 +
753 + if (PArray == (Pvoid_t) NULL) RET_SUCCESS;
754 +
755 +// ----------------------------------------------------------------------------
756 +// ROOT-LEVEL LEAF that starts with a Pop0 word; just look within the leaf:
757 +//
758 +// If Index is not in the leaf, return success; otherwise return the first
759 +// empty Index, if any, below/above where it would belong.
760 +
761 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
762 + {
763 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
764 + pop0 = Pjlw[0];
765 +
766 +#ifdef JUDY1
767 + if (pop0 == 0) // special case.
768 + {
769 +#ifdef JUDYPREV
770 + if ((Index != Pjlw[1]) || (Index-- != 0)) RET_SUCCESS;
771 +#else
772 + if ((Index != Pjlw[1]) || (++Index != 0)) RET_SUCCESS;
773 +#endif
774 + return(0); // no previous/next empty index.
775 + }
776 +#endif // JUDY1
777 +
778 + j__udySearchLeafEmptyL(Pjlw + 1, pop0);
779 +
780 +// No return -- thanks ALAN
781 +
782 + }
783 + else
784 +
785 +// ----------------------------------------------------------------------------
786 +// HANDLE JRP Branch:
787 +//
788 +// For JRP branches, traverse the JPM; handle LEAFW
789 +// directly; but look for the most common cases first.
790 +
791 + {
792 + Pjpm_t Pjpm = P_JPM(PArray);
793 + Pjp = &(Pjpm->jpm_JP);
794 +
795 +// goto SMGetContinue;
796 + }
797 +
798 +
799 +// ============================================================================
800 +// STATE MACHINE -- GET INDEX:
801 +//
802 +// Search for Index (already decremented/incremented so as to be an inclusive
803 +// search). If not found (empty index), return success. Otherwise do a
804 +// previous/next search, and if successful modify Index to the empty index
805 +// found. See function header comments.
806 +//
807 +// ENTRY: Pjp points to next JP to interpret, whose Decode bytes have not yet
808 +// been checked.
809 +//
810 +// Note: Check Decode bytes at the start of each loop, not after looking up a
811 +// new JP, so its easy to do constant shifts/masks.
812 +//
813 +// EXIT: Return, or branch to SMGetRestart with modified Index, or branch to
814 +// SMGetContinue with a modified Pjp, as described elsewhere.
815 +//
816 +// WARNING: For run-time efficiency the following cases replicate code with
817 +// varying constants, rather than using common code with variable values!
818 +
819 +SMGetContinue: // return here for next branch/leaf.
820 +
821 +#ifdef TRACEJPSE
822 + JudyPrintJP(Pjp, "sf", __LINE__);
823 +#endif
824 +
825 + switch (JU_JPTYPE(Pjp))
826 + {
827 +
828 +
829 +// ----------------------------------------------------------------------------
830 +// LINEAR BRANCH:
831 +//
832 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
833 +// next digit in Index.
834 +
835 + case cJU_JPBRANCH_L2: CHECKDCD(2); SMPREPB2(SMBranchL);
836 + case cJU_JPBRANCH_L3: CHECKDCD(3); SMPREPB3(SMBranchL);
837 +#ifdef JU_64BIT
838 + case cJU_JPBRANCH_L4: CHECKDCD(4); SMPREPB4(SMBranchL);
839 + case cJU_JPBRANCH_L5: CHECKDCD(5); SMPREPB5(SMBranchL);
840 + case cJU_JPBRANCH_L6: CHECKDCD(6); SMPREPB6(SMBranchL);
841 + case cJU_JPBRANCH_L7: CHECKDCD(7); SMPREPB7(SMBranchL);
842 +#endif
843 + case cJU_JPBRANCH_L: SMPREPBL(SMBranchL);
844 +
845 +// Common code (state-independent) for all cases of linear branches:
846 +
847 +SMBranchL:
848 + Pjbl = P_JBL(Pjp->jp_Addr);
849 +
850 +// First, check if Indexs expanse (digit) is below/above the first/last
851 +// populated expanse in the BranchL, in which case Index is empty; otherwise
852 +// find the offset of the lowest/highest populated expanse at or above/below
853 +// digit, if any:
854 +//
855 +// Note: The for-loop is guaranteed to exit eventually because the first/last
856 +// expanse is known to be a terminator.
857 +//
858 +// Note: Cannot use j__udySearchLeaf*Empty1() here because it only applies to
859 +// leaves and does not know about partial versus full JPs, unlike the use of
860 +// j__udySearchLeaf1() for BranchLs in SearchValid code. Also, since linear
861 +// leaf expanse lists are small, dont waste time calling j__udySearchLeaf1(),
862 +// just scan the expanse list.
863 +
864 +#ifdef JUDYPREV
865 + if ((Pjbl->jbl_Expanse[0]) > digit) RET_SUCCESS;
866 +
867 + for (offset = (Pjbl->jbl_NumJPs) - 1; /* null */; --offset)
868 +#else
869 + if ((Pjbl->jbl_Expanse[(Pjbl->jbl_NumJPs) - 1]) < digit)
870 + RET_SUCCESS;
871 +
872 + for (offset = 0; /* null */; ++offset)
873 +#endif
874 + {
875 +
876 +// Too low/high, keep going; or too high/low, meaning the loop passed a hole
877 +// and the initial Index is empty:
878 +
879 +#ifdef JUDYPREV
880 + if ((Pjbl->jbl_Expanse[offset]) > digit) continue;
881 + if ((Pjbl->jbl_Expanse[offset]) < digit) RET_SUCCESS;
882 +#else
883 + if ((Pjbl->jbl_Expanse[offset]) < digit) continue;
884 + if ((Pjbl->jbl_Expanse[offset]) > digit) RET_SUCCESS;
885 +#endif
886 +
887 +// Found expanse matching digit; if its not full, traverse through it:
888 +
889 + if (! JPFULL((Pjbl->jbl_jp) + offset))
890 + {
891 + Pjp = (Pjbl->jbl_jp) + offset;
892 + goto SMGetContinue;
893 + }
894 +
895 +// Common code: While searching for a lower/higher hole or a non-full JP, upon
896 +// finding a lower/higher hole, adjust Index using the revised digit and
897 +// return; or upon finding a consecutive lower/higher expanse, if the expanses
898 +// JP is non-full, modify Index and traverse through the JP:
899 +
900 +#define BRANCHL_CHECK(OpIncDec,OpLeastDigits,Digit,Digits) \
901 + { \
902 + if ((Pjbl->jbl_Expanse[offset]) != OpIncDec digit) \
903 + SET_AND_RETURN(OpLeastDigits, Digit, Digits); \
904 + \
905 + if (! JPFULL((Pjbl->jbl_jp) + offset)) \
906 + { \
907 + Pjp = (Pjbl->jbl_jp) + offset; \
908 + SET_AND_CONTINUE(OpLeastDigits, Digit, Digits); \
909 + } \
910 + }
911 +
912 +// BranchL primary dead end: Expanse matching Index/digit is full (rare except
913 +// for dense/sequential indexes):
914 +//
915 +// Search for a lower/higher hole, a non-full JP, or the end of the expanse
916 +// list, while decrementing/incrementing digit.
917 +
918 +#ifdef JUDYPREV
919 + while (--offset >= 0)
920 + BRANCHL_CHECK(--, SETLEASTDIGITS_D, digit, digits)
921 +#else
922 + while (++offset < Pjbl->jbl_NumJPs)
923 + BRANCHL_CHECK(++, CLEARLEASTDIGITS_D, digit, digits)
924 +#endif
925 +
926 +// Passed end of BranchL expanse list after finding a matching but full
927 +// expanse:
928 +//
929 +// Digit now matches the lowest/highest expanse, which is a full expanse; if
930 +// digit is at the end of BranchLs expanse (no hole before/after), break out
931 +// of the loop; otherwise modify Index to the next lower/higher digit and
932 +// return success:
933 +
934 +#ifdef JUDYPREV
935 + if (digit == 0) break;
936 + --digit; SET_AND_RETURN(SETLEASTDIGITS_D, digit, digits);
937 +#else
938 + if (digit == JU_LEASTBYTES(cJU_ALLONES, 1)) break;
939 + ++digit; SET_AND_RETURN(CLEARLEASTDIGITS_D, digit, digits);
940 +#endif
941 + } // for-loop
942 +
943 +// BranchL secondary dead end, no non-full previous/next JP:
944 +
945 + SMRESTART(digits);
946 +
947 +
948 +// ----------------------------------------------------------------------------
949 +// BITMAP BRANCH:
950 +//
951 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
952 +// next digit in Index.
953 +
954 + case cJU_JPBRANCH_B2: CHECKDCD(2); SMPREPB2(SMBranchB);
955 + case cJU_JPBRANCH_B3: CHECKDCD(3); SMPREPB3(SMBranchB);
956 +#ifdef JU_64BIT
957 + case cJU_JPBRANCH_B4: CHECKDCD(4); SMPREPB4(SMBranchB);
958 + case cJU_JPBRANCH_B5: CHECKDCD(5); SMPREPB5(SMBranchB);
959 + case cJU_JPBRANCH_B6: CHECKDCD(6); SMPREPB6(SMBranchB);
960 + case cJU_JPBRANCH_B7: CHECKDCD(7); SMPREPB7(SMBranchB);
961 +#endif
962 + case cJU_JPBRANCH_B: SMPREPBL(SMBranchB);
963 +
964 +// Common code (state-independent) for all cases of bitmap branches:
965 +
966 +SMBranchB:
967 + Pjbb = P_JBB(Pjp->jp_Addr);
968 +
969 +// Locate the digits JP in the subexpanse list, if present:
970 +
971 + subexp = digit / cJU_BITSPERSUBEXPB;
972 + assert(subexp < cJU_NUMSUBEXPB); // falls in expected range.
973 + bitposmaskB = JU_BITPOSMASKB(digit);
974 +
975 +// Absent JP = no JP matches current digit in Index:
976 +
977 +// if (! JU_BITMAPTESTB(Pjbb, digit)) // slower.
978 + if (! (JU_JBB_BITMAP(Pjbb, subexp) & bitposmaskB)) // faster.
979 + RET_SUCCESS;
980 +
981 +// Non-full JP matches current digit in Index:
982 +//
983 +// Iterate to the subsidiary non-full JP.
984 +
985 + offset = SEARCHBITMAPB(JU_JBB_BITMAP(Pjbb, subexp), digit,
986 + bitposmaskB);
987 + // not negative since at least one bit is set:
988 + assert(offset >= 0);
989 + assert(offset < (int) cJU_BITSPERSUBEXPB);
990 +
991 +// Watch for null JP subarray pointer with non-null bitmap (a corruption):
992 +
993 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp)))
994 + == (Pjp_t) NULL) RET_CORRUPT;
995 +
996 + Pjp += offset;
997 + if (! JPFULL(Pjp)) goto SMGetContinue;
998 +
999 +// BranchB primary dead end:
1000 +//
1001 +// Upon hitting a full JP in a BranchB for the next digit in Index, search
1002 +// sideways for a previous/next absent JP (unset bit) or non-full JP (set bit
1003 +// with non-full JP); first in the current bitmap subexpanse, then in
1004 +// lower/higher subexpanses. Upon entry, Pjp points to a known-unusable JP,
1005 +// ready to decrement/increment.
1006 +//
1007 +// Note: The preceding code is separate from this loop because Index does not
1008 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1009 +//
1010 +// TBD: For speed, shift bitposmaskB instead of using JU_BITMAPTESTB or
1011 +// JU_BITPOSMASKB, but this shift has knowledge of bit order that really should
1012 +// be encapsulated in a header file.
1013 +
1014 +#define BRANCHB_CHECKBIT(OpLeastDigits) \
1015 + if (! (JU_JBB_BITMAP(Pjbb, subexp) & bitposmaskB)) /* absent JP */ \
1016 + SET_AND_RETURN(OpLeastDigits, digit, digits)
1017 +
1018 +#define BRANCHB_CHECKJPFULL(OpLeastDigits) \
1019 + if (! JPFULL(Pjp)) \
1020 + SET_AND_CONTINUE(OpLeastDigits, digit, digits)
1021 +
1022 +#define BRANCHB_STARTSUBEXP(OpLeastDigits) \
1023 + if (! JU_JBB_BITMAP(Pjbb, subexp)) /* empty subexpanse, shortcut */ \
1024 + SET_AND_RETURN(OpLeastDigits, digit, digits) \
1025 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL) RET_CORRUPT
1026 +
1027 +#ifdef JUDYPREV
1028 +
1029 + --digit; // skip initial digit.
1030 + bitposmaskB >>= 1; // see TBD above.
1031 +
1032 +BranchBNextSubexp: // return here to check next bitmap subexpanse.
1033 +
1034 + while (bitposmaskB) // more bits to check in subexp.
1035 + {
1036 + BRANCHB_CHECKBIT(SETLEASTDIGITS_D);
1037 + --Pjp; // previous in subarray.
1038 + BRANCHB_CHECKJPFULL(SETLEASTDIGITS_D);
1039 + assert(digit >= 0);
1040 + --digit;
1041 + bitposmaskB >>= 1;
1042 + }
1043 +
1044 + if (subexp-- > 0) // more subexpanses.
1045 + {
1046 + BRANCHB_STARTSUBEXP(SETLEASTDIGITS_D);
1047 + Pjp += SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp)) + 1;
1048 + bitposmaskB = (1U << (cJU_BITSPERSUBEXPB - 1));
1049 + goto BranchBNextSubexp;
1050 + }
1051 +
1052 +#else // JUDYNEXT
1053 +
1054 + ++digit; // skip initial digit.
1055 + bitposmaskB <<= 1; // note: BITMAPB_t.
1056 +
1057 +BranchBNextSubexp: // return here to check next bitmap subexpanse.
1058 +
1059 + while (bitposmaskB) // more bits to check in subexp.
1060 + {
1061 + BRANCHB_CHECKBIT(CLEARLEASTDIGITS_D);
1062 + ++Pjp; // previous in subarray.
1063 + BRANCHB_CHECKJPFULL(CLEARLEASTDIGITS_D);
1064 + assert(digit < cJU_SUBEXPPERSTATE);
1065 + ++digit;
1066 + bitposmaskB <<= 1; // note: BITMAPB_t.
1067 + }
1068 +
1069 + if (++subexp < cJU_NUMSUBEXPB) // more subexpanses.
1070 + {
1071 + BRANCHB_STARTSUBEXP(CLEARLEASTDIGITS_D);
1072 + --Pjp; // pre-decrement.
1073 + bitposmaskB = 1;
1074 + goto BranchBNextSubexp;
1075 + }
1076 +
1077 +#endif // JUDYNEXT
1078 +
1079 +// BranchB secondary dead end, no non-full previous/next JP:
1080 +
1081 + SMRESTART(digits);
1082 +
1083 +
1084 +// ----------------------------------------------------------------------------
1085 +// UNCOMPRESSED BRANCH:
1086 +//
1087 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
1088 +// next digit in Index.
1089 +
1090 + case cJU_JPBRANCH_U2: CHECKDCD(2); SMPREPB2(SMBranchU);
1091 + case cJU_JPBRANCH_U3: CHECKDCD(3); SMPREPB3(SMBranchU);
1092 +#ifdef JU_64BIT
1093 + case cJU_JPBRANCH_U4: CHECKDCD(4); SMPREPB4(SMBranchU);
1094 + case cJU_JPBRANCH_U5: CHECKDCD(5); SMPREPB5(SMBranchU);
1095 + case cJU_JPBRANCH_U6: CHECKDCD(6); SMPREPB6(SMBranchU);
1096 + case cJU_JPBRANCH_U7: CHECKDCD(7); SMPREPB7(SMBranchU);
1097 +#endif
1098 + case cJU_JPBRANCH_U: SMPREPBL(SMBranchU);
1099 +
1100 +// Common code (state-independent) for all cases of uncompressed branches:
1101 +
1102 +SMBranchU:
1103 + Pjbu = P_JBU(Pjp->jp_Addr);
1104 + Pjp = (Pjbu->jbu_jp) + digit;
1105 +
1106 +// Absent JP = null JP for current digit in Index:
1107 +
1108 + if (JPNULL(JU_JPTYPE(Pjp))) RET_SUCCESS;
1109 +
1110 +// Non-full JP matches current digit in Index:
1111 +//
1112 +// Iterate to the subsidiary JP.
1113 +
1114 + if (! JPFULL(Pjp)) goto SMGetContinue;
1115 +
1116 +// BranchU primary dead end:
1117 +//
1118 +// Upon hitting a full JP in a BranchU for the next digit in Index, search
1119 +// sideways for a previous/next null or non-full JP. BRANCHU_CHECKJP() is
1120 +// shorthand for common code.
1121 +//
1122 +// Note: The preceding code is separate from this loop because Index does not
1123 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1124 +
1125 +#define BRANCHU_CHECKJP(OpIncDec,OpLeastDigits) \
1126 + { \
1127 + OpIncDec Pjp; \
1128 + \
1129 + if (JPNULL(JU_JPTYPE(Pjp))) \
1130 + SET_AND_RETURN(OpLeastDigits, digit, digits) \
1131 + \
1132 + if (! JPFULL(Pjp)) \
1133 + SET_AND_CONTINUE(OpLeastDigits, digit, digits) \
1134 + }
1135 +
1136 +#ifdef JUDYPREV
1137 + while (digit-- > 0)
1138 + BRANCHU_CHECKJP(--, SETLEASTDIGITS_D);
1139 +#else
1140 + while (++digit < cJU_BRANCHUNUMJPS)
1141 + BRANCHU_CHECKJP(++, CLEARLEASTDIGITS_D);
1142 +#endif
1143 +
1144 +// BranchU secondary dead end, no non-full previous/next JP:
1145 +
1146 + SMRESTART(digits);
1147 +
1148 +
1149 +// ----------------------------------------------------------------------------
1150 +// LINEAR LEAF:
1151 +//
1152 +// Check Decode bytes, if any, in the current JP, then search the leaf for the
1153 +// previous/next empty index starting at Index. Primary leaf dead end is
1154 +// hidden within j__udySearchLeaf*Empty*(). In case of secondary leaf dead
1155 +// end, restart at the top of the tree.
1156 +//
1157 +// Note: Pword is the name known to GET*; think of it as Pjlw.
1158 +
1159 +#define SMLEAFL(cDigits,Func) \
1160 + Pword = (PWord_t) P_JLW(Pjp->jp_Addr); \
1161 + pop0 = JU_JPLEAF_POP0(Pjp); \
1162 + Func(Pword, pop0)
1163 +
1164 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1165 + case cJU_JPLEAF1: CHECKDCD(1); SMLEAFL(1, j__udySearchLeafEmpty1);
1166 +#endif
1167 + case cJU_JPLEAF2: CHECKDCD(2); SMLEAFL(2, j__udySearchLeafEmpty2);
1168 + case cJU_JPLEAF3: CHECKDCD(3); SMLEAFL(3, j__udySearchLeafEmpty3);
1169 +
1170 +#ifdef JU_64BIT
1171 + case cJU_JPLEAF4: CHECKDCD(4); SMLEAFL(4, j__udySearchLeafEmpty4);
1172 + case cJU_JPLEAF5: CHECKDCD(5); SMLEAFL(5, j__udySearchLeafEmpty5);
1173 + case cJU_JPLEAF6: CHECKDCD(6); SMLEAFL(6, j__udySearchLeafEmpty6);
1174 + case cJU_JPLEAF7: CHECKDCD(7); SMLEAFL(7, j__udySearchLeafEmpty7);
1175 +#endif
1176 +
1177 +
1178 +// ----------------------------------------------------------------------------
1179 +// BITMAP LEAF:
1180 +//
1181 +// Check Decode bytes, if any, in the current JP, then search the leaf for the
1182 +// previous/next empty index starting at Index.
1183 +
1184 + case cJU_JPLEAF_B1:
1185 +
1186 + CHECKDCD(1);
1187 +
1188 + Pjlb = P_JLB(Pjp->jp_Addr);
1189 + digit = JU_DIGITATSTATE(Index, 1);
1190 + subexp = digit / cJU_BITSPERSUBEXPL;
1191 + bitposmaskL = JU_BITPOSMASKL(digit);
1192 + assert(subexp < cJU_NUMSUBEXPL); // falls in expected range.
1193 +
1194 +// Absent index = no index matches current digit in Index:
1195 +
1196 +// if (! JU_BITMAPTESTL(Pjlb, digit)) // slower.
1197 + if (! (JU_JLB_BITMAP(Pjlb, subexp) & bitposmaskL)) // faster.
1198 + RET_SUCCESS;
1199 +
1200 +// LeafB1 primary dead end:
1201 +//
1202 +// Upon hitting a valid (non-empty) index in a LeafB1 for the last digit in
1203 +// Index, search sideways for a previous/next absent index, first in the
1204 +// current bitmap subexpanse, then in lower/higher subexpanses.
1205 +// LEAFB1_CHECKBIT() is shorthand for common code to handle one bit in one
1206 +// bitmap subexpanse.
1207 +//
1208 +// Note: The preceding code is separate from this loop because Index does not
1209 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1210 +//
1211 +// TBD: For speed, shift bitposmaskL instead of using JU_BITMAPTESTL or
1212 +// JU_BITPOSMASKL, but this shift has knowledge of bit order that really should
1213 +// be encapsulated in a header file.
1214 +
1215 +#define LEAFB1_CHECKBIT(OpLeastDigits) \
1216 + if (! (JU_JLB_BITMAP(Pjlb, subexp) & bitposmaskL)) \
1217 + SET_AND_RETURN(OpLeastDigits, digit, 1)
1218 +
1219 +#define LEAFB1_STARTSUBEXP(OpLeastDigits) \
1220 + if (! JU_JLB_BITMAP(Pjlb, subexp)) /* empty subexp */ \
1221 + SET_AND_RETURN(OpLeastDigits, digit, 1)
1222 +
1223 +#ifdef JUDYPREV
1224 +
1225 + --digit; // skip initial digit.
1226 + bitposmaskL >>= 1; // see TBD above.
1227 +
1228 +LeafB1NextSubexp: // return here to check next bitmap subexpanse.
1229 +
1230 + while (bitposmaskL) // more bits to check in subexp.
1231 + {
1232 + LEAFB1_CHECKBIT(SETLEASTDIGITS_D);
1233 + assert(digit >= 0);
1234 + --digit;
1235 + bitposmaskL >>= 1;
1236 + }
1237 +
1238 + if (subexp-- > 0) // more subexpanses.
1239 + {
1240 + LEAFB1_STARTSUBEXP(SETLEASTDIGITS_D);
1241 + bitposmaskL = (1UL << (cJU_BITSPERSUBEXPL - 1));
1242 + goto LeafB1NextSubexp;
1243 + }
1244 +
1245 +#else // JUDYNEXT
1246 +
1247 + ++digit; // skip initial digit.
1248 + bitposmaskL <<= 1; // note: BITMAPL_t.
1249 +
1250 +LeafB1NextSubexp: // return here to check next bitmap subexpanse.
1251 +
1252 + while (bitposmaskL) // more bits to check in subexp.
1253 + {
1254 + LEAFB1_CHECKBIT(CLEARLEASTDIGITS_D);
1255 + assert(digit < cJU_SUBEXPPERSTATE);
1256 + ++digit;
1257 + bitposmaskL <<= 1; // note: BITMAPL_t.
1258 + }
1259 +
1260 + if (++subexp < cJU_NUMSUBEXPL) // more subexpanses.
1261 + {
1262 + LEAFB1_STARTSUBEXP(CLEARLEASTDIGITS_D);
1263 + bitposmaskL = 1;
1264 + goto LeafB1NextSubexp;
1265 + }
1266 +
1267 +#endif // JUDYNEXT
1268 +
1269 +// LeafB1 secondary dead end, no empty index:
1270 +
1271 + SMRESTART(1);
1272 +
1273 +
1274 +#ifdef JUDY1
1275 +// ----------------------------------------------------------------------------
1276 +// FULL POPULATION:
1277 +//
1278 +// If the Decode bytes do not match, Index is empty (without modification);
1279 +// otherwise restart.
1280 +
1281 + case cJ1_JPFULLPOPU1:
1282 +
1283 + CHECKDCD(1);
1284 + SMRESTART(1);
1285 +#endif
1286 +
1287 +
1288 +// ----------------------------------------------------------------------------
1289 +// IMMEDIATE:
1290 +//
1291 +// Pop1 = 1 Immediate JPs:
1292 +//
1293 +// If Index is not in the immediate JP, return success; otherwise check if
1294 +// there is an empty index below/above the immediate JPs index, and if so,
1295 +// return success with modified Index, else restart.
1296 +//
1297 +// Note: Doug says its fast enough to calculate the index size (digits) in
1298 +// the following; no need to set it separately for each case.
1299 +
1300 + case cJU_JPIMMED_1_01:
1301 + case cJU_JPIMMED_2_01:
1302 + case cJU_JPIMMED_3_01:
1303 +#ifdef JU_64BIT
1304 + case cJU_JPIMMED_4_01:
1305 + case cJU_JPIMMED_5_01:
1306 + case cJU_JPIMMED_6_01:
1307 + case cJU_JPIMMED_7_01:
1308 +#endif
1309 + if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) RET_SUCCESS;
1310 + digits = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_01 + 1;
1311 + LEAF_EDGE(JU_LEASTBYTES(JU_JPDCDPOP0(Pjp), digits), digits);
1312 +
1313 +// Immediate JPs with Pop1 > 1:
1314 +
1315 +#define IMM_MULTI(Func,BaseJPType) \
1316 + JUDY1CODE(Pword = (PWord_t) (Pjp->jp_1Index);) \
1317 + JUDYLCODE(Pword = (PWord_t) (Pjp->jp_LIndex);) \
1318 + Func(Pword, JU_JPTYPE(Pjp) - (BaseJPType) + 1)
1319 +
1320 + case cJU_JPIMMED_1_02:
1321 + case cJU_JPIMMED_1_03:
1322 +#if (defined(JUDY1) || defined(JU_64BIT))
1323 + case cJU_JPIMMED_1_04:
1324 + case cJU_JPIMMED_1_05:
1325 + case cJU_JPIMMED_1_06:
1326 + case cJU_JPIMMED_1_07:
1327 +#endif
1328 +#if (defined(JUDY1) && defined(JU_64BIT))
1329 + case cJ1_JPIMMED_1_08:
1330 + case cJ1_JPIMMED_1_09:
1331 + case cJ1_JPIMMED_1_10:
1332 + case cJ1_JPIMMED_1_11:
1333 + case cJ1_JPIMMED_1_12:
1334 + case cJ1_JPIMMED_1_13:
1335 + case cJ1_JPIMMED_1_14:
1336 + case cJ1_JPIMMED_1_15:
1337 +#endif
1338 + IMM_MULTI(j__udySearchLeafEmpty1, cJU_JPIMMED_1_02);
1339 +
1340 +#if (defined(JUDY1) || defined(JU_64BIT))
1341 + case cJU_JPIMMED_2_02:
1342 + case cJU_JPIMMED_2_03:
1343 +#endif
1344 +#if (defined(JUDY1) && defined(JU_64BIT))
1345 + case cJ1_JPIMMED_2_04:
1346 + case cJ1_JPIMMED_2_05:
1347 + case cJ1_JPIMMED_2_06:
1348 + case cJ1_JPIMMED_2_07:
1349 +#endif
1350 +#if (defined(JUDY1) || defined(JU_64BIT))
1351 + IMM_MULTI(j__udySearchLeafEmpty2, cJU_JPIMMED_2_02);
1352 +#endif
1353 +
1354 +#if (defined(JUDY1) || defined(JU_64BIT))
1355 + case cJU_JPIMMED_3_02:
1356 +#endif
1357 +#if (defined(JUDY1) && defined(JU_64BIT))
1358 + case cJ1_JPIMMED_3_03:
1359 + case cJ1_JPIMMED_3_04:
1360 + case cJ1_JPIMMED_3_05:
1361 +#endif
1362 +#if (defined(JUDY1) || defined(JU_64BIT))
1363 + IMM_MULTI(j__udySearchLeafEmpty3, cJU_JPIMMED_3_02);
1364 +#endif
1365 +
1366 +#if (defined(JUDY1) && defined(JU_64BIT))
1367 + case cJ1_JPIMMED_4_02:
1368 + case cJ1_JPIMMED_4_03:
1369 + IMM_MULTI(j__udySearchLeafEmpty4, cJ1_JPIMMED_4_02);
1370 +
1371 + case cJ1_JPIMMED_5_02:
1372 + case cJ1_JPIMMED_5_03:
1373 + IMM_MULTI(j__udySearchLeafEmpty5, cJ1_JPIMMED_5_02);
1374 +
1375 + case cJ1_JPIMMED_6_02:
1376 + IMM_MULTI(j__udySearchLeafEmpty6, cJ1_JPIMMED_6_02);
1377 +
1378 + case cJ1_JPIMMED_7_02:
1379 + IMM_MULTI(j__udySearchLeafEmpty7, cJ1_JPIMMED_7_02);
1380 +#endif
1381 +
1382 +
1383 +// ----------------------------------------------------------------------------
1384 +// INVALID JP TYPE:
1385 +
1386 + default: RET_CORRUPT;
1387 +
1388 + } // SMGet switch.
1389 +
1390 +} // Judy1PrevEmpty() / Judy1NextEmpty() / JudyLPrevEmpty() / JudyLNextEmpty()
libnetdata/libjudy/src/JudyL/JudyLPrev.c new
+1890
@@ -0,0 +1,1890 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.54 $ $Source: /judy/src/JudyCommon/JudyPrevNext.c $
19 +//
20 +// Judy*Prev() and Judy*Next() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DJUDYNEXT for the Judy*Next() function; otherwise defaults to
24 +// Judy*Prev().
25 +
26 +#if (! (defined(JUDY1) || defined(JUDYL)))
27 +#error: One of -DJUDY1 or -DJUDYL must be specified.
28 +#endif
29 +
30 +#ifndef JUDYNEXT
31 +#ifndef JUDYPREV
32 +#define JUDYPREV 1 // neither set => use default.
33 +#endif
34 +#endif
35 +
36 +#ifdef JUDY1
37 +#include "Judy1.h"
38 +#else
39 +#include "JudyL.h"
40 +#endif
41 +
42 +#include "JudyPrivate1L.h"
43 +
44 +
45 +// ****************************************************************************
46 +// J U D Y 1 P R E V
47 +// J U D Y 1 N E X T
48 +// J U D Y L P R E V
49 +// J U D Y L N E X T
50 +//
51 +// See the manual entry for the API.
52 +//
53 +// OVERVIEW OF Judy*Prev():
54 +//
55 +// Use a reentrant switch statement (state machine, SM1 = "get") to decode the
56 +// callers *PIndex-1, starting with the (PArray), through branches, if
57 +// any, down to an immediate or a leaf. Look for *PIndex-1 in that leaf, and
58 +// if found, return it.
59 +//
60 +// A dead end is either a branch that does not contain a JP for the appropriate
61 +// digit in *PIndex-1, or a leaf that does not contain the undecoded digits of
62 +// *PIndex-1. Upon reaching a dead end, backtrack through the leaf/branches
63 +// that were just traversed, using a list (history) of parent JPs that is built
64 +// while going forward in SM1Get. Start with the current leaf or branch. In a
65 +// backtracked leaf, look for an Index less than *PIndex-1. In each
66 +// backtracked branch, look "sideways" for the next JP, if any, lower than the
67 +// one for the digit (from *PIndex-1) that was previously decoded. While
68 +// backtracking, if a leaf has no previous Index or a branch has no lower JP,
69 +// go to its parent branch in turn. Upon reaching the JRP, return failure, "no
70 +// previous Index". The backtrack process is sufficiently different from
71 +// SM1Get to merit its own separate reentrant switch statement (SM2 =
72 +// "backtrack").
73 +//
74 +// While backtracking, upon finding a lower JP in a branch, there is certain to
75 +// be a "prev" Index under that JP (unless the Judy array is corrupt).
76 +// Traverse forward again, this time taking the last (highest, right-most) JP
77 +// in each branch, and the last (highest) Index upon reaching an immediate or a
78 +// leaf. This traversal is sufficiently different from SM1Get and SM2Backtrack
79 +// to merit its own separate reentrant switch statement (SM3 = "findlimit").
80 +//
81 +// "Decode" bytes in JPs complicate this process a little. In SM1Get, when a
82 +// JP is a narrow pointer, that is, when states are skipped (so the skipped
83 +// digits are stored in jp_DcdPopO), compare the relevant digits to the same
84 +// digits in *PIndex-1. If they are EQUAL, proceed in SM1Get as before. If
85 +// jp_DcdPopOs digits are GREATER, treat the JP as a dead end and proceed in
86 +// SM2Backtrack. If jp_DcdPopOs digits are LESS, treat the JP as if it had
87 +// just been found during a backtrack and proceed directly in SM3Findlimit.
88 +//
89 +// Note that Decode bytes can be ignored in SM3Findlimit; they dont matter.
90 +// Also note that in practice the Decode bytes are routinely compared with
91 +// *PIndex-1 because thats simpler and no slower than first testing for
92 +// narrowness.
93 +//
94 +// Decode bytes also make it unnecessary to construct the Index to return (the
95 +// revised *PIndex) during the search. This step is deferred until finding an
96 +// Index during backtrack or findlimit, before returning it. The first digit
97 +// of *PIndex is derived (saved) based on which JP is used in a JRP branch.
98 +// The remaining digits are obtained from the jp_DcdPopO field in the JP (if
99 +// any) above the immediate or leaf containing the found (prev) Index, plus the
100 +// remaining digit(s) in the immediate or leaf itself. In the case of a LEAFW,
101 +// the Index to return is found directly in the leaf.
102 +//
103 +// Note: Theoretically, as described above, upon reaching a dead end, SM1Get
104 +// passes control to SM2Backtrack to look sideways, even in a leaf. Actually
105 +// its a little more efficient for the SM1Get leaf cases to shortcut this and
106 +// take care of the sideways searches themselves. Hence the history list only
107 +// contains branch JPs, and SM2Backtrack only handles branches. In fact, even
108 +// the branch handling cases in SM1Get do some shortcutting (sideways
109 +// searching) to avoid pushing history and calling SM2Backtrack unnecessarily.
110 +//
111 +// Upon reaching an Index to return after backtracking, *PIndex must be
112 +// modified to the found Index. In principle this could be done by building
113 +// the Index from a saved rootdigit (in the top branch) plus the Dcd bytes from
114 +// the parent JP plus the appropriate Index bytes from the leaf. However,
115 +// Immediates are difficult because their parent JPs lack one (last) digit. So
116 +// instead just build the *PIndex to return "top down" while backtracking and
117 +// findlimiting.
118 +//
119 +// This function is written iteratively for speed, rather than recursively.
120 +//
121 +// CAVEATS:
122 +//
123 +// Why use a backtrack list (history stack), since it has finite size? The
124 +// size is small for Judy on both 32-bit and 64-bit systems, and a list (really
125 +// just an array) is fast to maintain and use. Other alternatives include
126 +// doing a lookahead (lookaside) in each branch while traversing forward
127 +// (decoding), and restarting from the top upon a dead end.
128 +//
129 +// A lookahead means noting the last branch traversed which contained a
130 +// non-null JP lower than the one specified by a digit in *PIndex-1, and
131 +// returning to that point for SM3Findlimit. This seems like a good idea, and
132 +// should be pretty cheap for linear and bitmap branches, but it could result
133 +// in up to 31 unnecessary additional cache line fills (in extreme cases) for
134 +// every uncompressed branch traversed. We have considered means of attaching
135 +// to or hiding within an uncompressed branch (in null JPs) a "cache line map"
136 +// or other structure, such as an offset to the next non-null JP, that would
137 +// speed this up, but it seems unnecessary merely to avoid having a
138 +// finite-length list (array). (If JudySL is ever made "native", the finite
139 +// list length will be an issue.)
140 +//
141 +// Restarting at the top of the Judy array after a dead end requires a careful
142 +// modification of *PIndex-1 to decrement the digit for the parent branch and
143 +// set the remaining lower digits to all 1s. This must be repeated each time a
144 +// parent branch contains another dead end, so even though it should all happen
145 +// in cache, the CPU time can be excessive. (For JudySL or an equivalent
146 +// "infinitely deep" Judy array, consider a hybrid of a large, finite,
147 +// "circular" list and a restart-at-top when the list is backtracked to
148 +// exhaustion.)
149 +//
150 +// Why search for *PIndex-1 instead of *PIndex during SM1Get? In rare
151 +// instances this prevents an unnecessary decode down the wrong path followed
152 +// by a backtrack; its pretty cheap to set up initially; and it means the
153 +// SM1Get machine can simply return if/when it finds that Index.
154 +//
155 +// TBD: Wed like to enhance this function to make successive searches faster.
156 +// This would require saving some previous state, including the previous Index
157 +// returned, and in which leaf it was found. If the next call is for the same
158 +// Index and the array has not been modified, start at the same leaf. This
159 +// should be much easier to implement since this is iterative rather than
160 +// recursive code.
161 +//
162 +// VARIATIONS FOR Judy*Next():
163 +//
164 +// The Judy*Next() code is nearly a perfect mirror of the Judy*Prev() code.
165 +// See the Judy*Prev() overview comments, and mentally switch the following:
166 +//
167 +// - "*PIndex-1" => "*PIndex+1"
168 +// - "less than" => "greater than"
169 +// - "lower" => "higher"
170 +// - "lowest" => "highest"
171 +// - "next-left" => "next-right"
172 +// - "right-most" => "left-most"
173 +//
174 +// Note: SM3Findlimit could be called SM3Findmax/SM3Findmin, but a common name
175 +// for both Prev and Next means many fewer ifdefs in this code.
176 +//
177 +// TBD: Currently this code traverses a JP whether its expanse is partially or
178 +// completely full (populated). For Judy1 (only), since there is no value area
179 +// needed, consider shortcutting to a "success" return upon encountering a full
180 +// JP in SM1Get (or even SM3Findlimit?) A full JP looks like this:
181 +//
182 +// (((JU_JPDCDPOP0(Pjp) ^ cJU_ALLONES) & cJU_POP0MASK(cLevel)) == 0)
183 +
184 +#ifdef JUDY1
185 +#ifdef JUDYPREV
186 +FUNCTION int Judy1Prev
187 +#else
188 +FUNCTION int Judy1Next
189 +#endif
190 +#else
191 +#ifdef JUDYPREV
192 +FUNCTION PPvoid_t JudyLPrev
193 +#else
194 +FUNCTION PPvoid_t JudyLNext
195 +#endif
196 +#endif
197 + (
198 + Pcvoid_t PArray, // Judy array to search.
199 + Word_t * PIndex, // starting point and result.
200 + PJError_t PJError // optional, for returning error info.
201 + )
202 +{
203 + Pjp_t Pjp, Pjp2; // current JPs.
204 + Pjbl_t Pjbl; // Pjp->jp_Addr masked and cast to types:
205 + Pjbb_t Pjbb;
206 + Pjbu_t Pjbu;
207 +
208 +// Note: The following initialization is not strictly required but it makes
209 +// gcc -Wall happy because there is an "impossible" path from Immed handling to
210 +// SM1LeafLImm code that looks like Pjll might be used before set:
211 +
212 + Pjll_t Pjll = (Pjll_t) NULL;
213 + Word_t state; // current state in SM.
214 + Word_t digit; // next digit to decode from Index.
215 +
216 +// Note: The following initialization is not strictly required but it makes
217 +// gcc -Wall happy because there is an "impossible" path from Immed handling to
218 +// SM1LeafLImm code (for JudyL & JudyPrev only) that looks like pop1 might be
219 +// used before set:
220 +
221 +#if (defined(JUDYL) && defined(JUDYPREV))
222 + Word_t pop1 = 0; // in a leaf.
223 +#else
224 + Word_t pop1; // in a leaf.
225 +#endif
226 + int offset; // linear branch/leaf, from j__udySearchLeaf*().
227 + int subexp; // subexpanse in a bitmap branch.
228 + Word_t bitposmask; // bit in bitmap for Index.
229 +
230 +// History for SM2Backtrack:
231 +//
232 +// For a given histnum, APjphist[histnum] is a parent JP that points to a
233 +// branch, and Aoffhist[histnum] is the offset of the NEXT JP in the branch to
234 +// which the parent JP points. The meaning of Aoffhist[histnum] depends on the
235 +// type of branch to which the parent JP points:
236 +//
237 +// Linear: Offset of the next JP in the JP list.
238 +//
239 +// Bitmap: Which subexpanse, plus the offset of the next JP in the
240 +// subexpanses JP list (to avoid bit-counting again), plus for Judy*Next(),
241 +// hidden one byte to the left, which digit, because Judy*Next() also needs
242 +// this.
243 +//
244 +// Uncompressed: Digit, which is actually the offset of the JP in the branch.
245 +//
246 +// Note: Only branch JPs are stored in APjphist[] because, as explained
247 +// earlier, SM1Get shortcuts sideways searches in leaves (and even in branches
248 +// in some cases), so SM2Backtrack only handles branches.
249 +
250 +#define HISTNUMMAX cJU_ROOTSTATE // maximum branches traversable.
251 + Pjp_t APjphist[HISTNUMMAX]; // list of branch JPs traversed.
252 + int Aoffhist[HISTNUMMAX]; // list of next JP offsets; see above.
253 + int histnum = 0; // number of JPs now in list.
254 +
255 +
256 +// ----------------------------------------------------------------------------
257 +// M A C R O S
258 +//
259 +// These are intended to make the code a bit more readable and less redundant.
260 +
261 +
262 +// "PUSH" AND "POP" Pjp AND offset ON HISTORY STACKS:
263 +//
264 +// Note: Ensure a corrupt Judy array does not overflow *hist[]. Meanwhile,
265 +// underflowing *hist[] simply means theres no more room to backtrack =>
266 +// "no previous/next Index".
267 +
268 +#define HISTPUSH(Pjp,Offset) \
269 + APjphist[histnum] = (Pjp); \
270 + Aoffhist[histnum] = (Offset); \
271 + \
272 + if (++histnum >= HISTNUMMAX) \
273 + { \
274 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT) \
275 + JUDY1CODE(return(JERRI );) \
276 + JUDYLCODE(return(PPJERR);) \
277 + }
278 +
279 +#define HISTPOP(Pjp,Offset) \
280 + if ((histnum--) < 1) JU_RET_NOTFOUND; \
281 + (Pjp) = APjphist[histnum]; \
282 + (Offset) = Aoffhist[histnum]
283 +
284 +// How to pack/unpack Aoffhist[] values for bitmap branches:
285 +
286 +#ifdef JUDYPREV
287 +
288 +#define HISTPUSHBOFF(Subexp,Offset,Digit) \
289 + (((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))
290 +
291 +#define HISTPOPBOFF(Subexp,Offset,Digit) \
292 + (Subexp) = (Offset) / cJU_BITSPERSUBEXPB; \
293 + (Offset) %= cJU_BITSPERSUBEXPB
294 +#else
295 +
296 +#define HISTPUSHBOFF(Subexp,Offset,Digit) \
297 + (((Digit) << cJU_BITSPERBYTE) \
298 + | ((Subexp) * cJU_BITSPERSUBEXPB) | (Offset))
299 +
300 +#define HISTPOPBOFF(Subexp,Offset,Digit) \
301 + (Digit) = (Offset) >> cJU_BITSPERBYTE; \
302 + (Subexp) = ((Offset) & JU_LEASTBYTESMASK(1)) / cJU_BITSPERSUBEXPB; \
303 + (Offset) %= cJU_BITSPERSUBEXPB
304 +#endif
305 +
306 +
307 +// CHECK FOR NULL JP:
308 +
309 +#define JPNULL(Type) (((Type) >= cJU_JPNULL1) && ((Type) <= cJU_JPNULLMAX))
310 +
311 +
312 +// SEARCH A BITMAP:
313 +//
314 +// This is a weak analog of j__udySearchLeaf*() for bitmaps. Return the actual
315 +// or next-left position, base 0, of Digit in the single uint32_t bitmap, also
316 +// given a Bitposmask for Digit.
317 +//
318 +// Unlike j__udySearchLeaf*(), the offset is not returned bit-complemented if
319 +// Digits bit is unset, because the caller can check the bitmap themselves to
320 +// determine that. Also, if Digits bit is unset, the returned offset is to
321 +// the next-left JP (including -1), not to the "ideal" position for the Index =
322 +// next-right JP.
323 +//
324 +// Shortcut and skip calling j__udyCountBits*() if the bitmap is full, in which
325 +// case (Digit % cJU_BITSPERSUBEXP*) itself is the base-0 offset.
326 +//
327 +// TBD for Judy*Next(): Should this return next-right instead of next-left?
328 +// That is, +1 from current value? Maybe not, if Digits bit IS set, +1 would
329 +// be wrong.
330 +
331 +#define SEARCHBITMAPB(Bitmap,Digit,Bitposmask) \
332 + (((Bitmap) == cJU_FULLBITMAPB) ? (Digit % cJU_BITSPERSUBEXPB) : \
333 + j__udyCountBitsB((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
334 +
335 +#define SEARCHBITMAPL(Bitmap,Digit,Bitposmask) \
336 + (((Bitmap) == cJU_FULLBITMAPL) ? (Digit % cJU_BITSPERSUBEXPL) : \
337 + j__udyCountBitsL((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
338 +
339 +#ifdef JUDYPREV
340 +// Equivalent to search for the highest offset in Bitmap:
341 +
342 +#define SEARCHBITMAPMAXB(Bitmap) \
343 + (((Bitmap) == cJU_FULLBITMAPB) ? cJU_BITSPERSUBEXPB - 1 : \
344 + j__udyCountBitsB(Bitmap) - 1)
345 +
346 +#define SEARCHBITMAPMAXL(Bitmap) \
347 + (((Bitmap) == cJU_FULLBITMAPL) ? cJU_BITSPERSUBEXPL - 1 : \
348 + j__udyCountBitsL(Bitmap) - 1)
349 +#endif
350 +
351 +
352 +// CHECK DECODE BYTES:
353 +//
354 +// Check Decode bytes in a JP against the equivalent portion of *PIndex. If
355 +// *PIndex is lower (for Judy*Prev()) or higher (for Judy*Next()), this JP is a
356 +// dead end (the same as if it had been absent in a linear or bitmap branch or
357 +// null in an uncompressed branch), enter SM2Backtrack; otherwise enter
358 +// SM3Findlimit to find the highest/lowest Index under this JP, as if the code
359 +// had already backtracked to this JP.
360 +
361 +#ifdef JUDYPREV
362 +#define CDcmp__ <
363 +#else
364 +#define CDcmp__ >
365 +#endif
366 +
367 +#define CHECKDCD(cState) \
368 + if (JU_DCDNOTMATCHINDEX(*PIndex, Pjp, cState)) \
369 + { \
370 + if ((*PIndex & cJU_DCDMASK(cState)) \
371 + CDcmp__(JU_JPDCDPOP0(Pjp) & cJU_DCDMASK(cState))) \
372 + { \
373 + goto SM2Backtrack; \
374 + } \
375 + goto SM3Findlimit; \
376 + }
377 +
378 +
379 +// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM1:
380 +//
381 +// Extract a state-dependent digit from Index in a "constant" way, then jump to
382 +// common code for multiple cases.
383 +
384 +#define SM1PREPB(cState,Next) \
385 + state = (cState); \
386 + digit = JU_DIGITATSTATE(*PIndex, cState); \
387 + goto Next
388 +
389 +
390 +// PREPARE TO HANDLE A LEAFW OR JRP BRANCH IN SM3:
391 +//
392 +// Optionally save Dcd bytes into *PIndex, then save state and jump to common
393 +// code for multiple cases.
394 +
395 +#define SM3PREPB_DCD(cState,Next) \
396 + JU_SETDCD(*PIndex, Pjp, cState); \
397 + SM3PREPB(cState,Next)
398 +
399 +#define SM3PREPB(cState,Next) state = (cState); goto Next
400 +
401 +
402 +// ----------------------------------------------------------------------------
403 +// CHECK FOR SHORTCUTS:
404 +//
405 +// Error out if PIndex is null. Execute JU_RET_NOTFOUND if the Judy array is
406 +// empty or *PIndex is already the minimum/maximum Index possible.
407 +//
408 +// Note: As documented, in case of failure *PIndex may be modified.
409 +
410 + if (PIndex == (PWord_t) NULL)
411 + {
412 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
413 + JUDY1CODE(return(JERRI );)
414 + JUDYLCODE(return(PPJERR);)
415 + }
416 +
417 +#ifdef JUDYPREV
418 + if ((PArray == (Pvoid_t) NULL) || ((*PIndex)-- == 0))
419 +#else
420 + if ((PArray == (Pvoid_t) NULL) || ((*PIndex)++ == cJU_ALLONES))
421 +#endif
422 + JU_RET_NOTFOUND;
423 +
424 +
425 +// HANDLE JRP:
426 +//
427 +// Before even entering SM1Get, check the JRP type. For JRP branches, traverse
428 +// the JPM; handle LEAFW leaves directly; but look for the most common cases
429 +// first.
430 +
431 +// ROOT-STATE LEAF that starts with a Pop0 word; just look within the leaf:
432 +//
433 +// If *PIndex is in the leaf, return it; otherwise return the Index, if any,
434 +// below where it would belong.
435 +
436 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
437 + {
438 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
439 + pop1 = Pjlw[0] + 1;
440 +
441 + if ((offset = j__udySearchLeafW(Pjlw + 1, pop1, *PIndex))
442 + >= 0) // Index is present.
443 + {
444 + assert(offset < pop1); // in expected range.
445 + JU_RET_FOUND_LEAFW(Pjlw, pop1, offset); // *PIndex is set.
446 + }
447 +
448 +#ifdef JUDYPREV
449 + if ((offset = ~offset) == 0) // no next-left Index.
450 +#else
451 + if ((offset = ~offset) >= pop1) // no next-right Index.
452 +#endif
453 + JU_RET_NOTFOUND;
454 +
455 + assert(offset <= pop1); // valid result.
456 +
457 +#ifdef JUDYPREV
458 + *PIndex = Pjlw[offset--]; // next-left Index, base 1.
459 +#else
460 + *PIndex = Pjlw[offset + 1]; // next-right Index, base 1.
461 +#endif
462 + JU_RET_FOUND_LEAFW(Pjlw, pop1, offset); // base 0.
463 +
464 + }
465 + else // JRP BRANCH
466 + {
467 + Pjpm_t Pjpm = P_JPM(PArray);
468 + Pjp = &(Pjpm->jpm_JP);
469 +
470 +// goto SM1Get;
471 + }
472 +
473 +// ============================================================================
474 +// STATE MACHINE 1 -- GET INDEX:
475 +//
476 +// Search for *PIndex (already decremented/incremented so as to be inclusive).
477 +// If found, return it. Otherwise in theory hand off to SM2Backtrack or
478 +// SM3Findlimit, but in practice "shortcut" by first sideways searching the
479 +// current branch or leaf upon hitting a dead end. During sideways search,
480 +// modify *PIndex to a new path taken.
481 +//
482 +// ENTRY: Pjp points to next JP to interpret, whose Decode bytes have not yet
483 +// been checked. This JP is not yet listed in history.
484 +//
485 +// Note: Check Decode bytes at the start of each loop, not after looking up a
486 +// new JP, so its easy to do constant shifts/masks, although this requires
487 +// cautious handling of Pjp, offset, and *hist[] for correct entry to
488 +// SM2Backtrack.
489 +//
490 +// EXIT: Return, or branch to SM2Backtrack or SM3Findlimit with correct
491 +// interface, as described elsewhere.
492 +//
493 +// WARNING: For run-time efficiency the following cases replicate code with
494 +// varying constants, rather than using common code with variable values!
495 +
496 +SM1Get: // return here for next branch/leaf.
497 +
498 + switch (JU_JPTYPE(Pjp))
499 + {
500 +
501 +
502 +// ----------------------------------------------------------------------------
503 +// LINEAR BRANCH:
504 +//
505 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
506 +// next digit in *PIndex.
507 +
508 + case cJU_JPBRANCH_L2: CHECKDCD(2); SM1PREPB(2, SM1BranchL);
509 + case cJU_JPBRANCH_L3: CHECKDCD(3); SM1PREPB(3, SM1BranchL);
510 +#ifdef JU_64BIT
511 + case cJU_JPBRANCH_L4: CHECKDCD(4); SM1PREPB(4, SM1BranchL);
512 + case cJU_JPBRANCH_L5: CHECKDCD(5); SM1PREPB(5, SM1BranchL);
513 + case cJU_JPBRANCH_L6: CHECKDCD(6); SM1PREPB(6, SM1BranchL);
514 + case cJU_JPBRANCH_L7: CHECKDCD(7); SM1PREPB(7, SM1BranchL);
515 +#endif
516 + case cJU_JPBRANCH_L: SM1PREPB(cJU_ROOTSTATE, SM1BranchL);
517 +
518 +// Common code (state-independent) for all cases of linear branches:
519 +
520 +SM1BranchL:
521 + Pjbl = P_JBL(Pjp->jp_Addr);
522 +
523 +// Found JP matching current digit in *PIndex; record parent JP and the next
524 +// JPs offset, and iterate to the next JP:
525 +
526 + if ((offset = j__udySearchLeaf1((Pjll_t) (Pjbl->jbl_Expanse),
527 + Pjbl->jbl_NumJPs, digit)) >= 0)
528 + {
529 + HISTPUSH(Pjp, offset);
530 + Pjp = (Pjbl->jbl_jp) + offset;
531 + goto SM1Get;
532 + }
533 +
534 +// Dead end, no JP in BranchL for next digit in *PIndex:
535 +//
536 +// Get the ideal location of digits JP, and if theres no next-left/right JP
537 +// in the BranchL, shortcut and start backtracking one level up; ignore the
538 +// current Pjp because it points to a BranchL with no next-left/right JP.
539 +
540 +#ifdef JUDYPREV
541 + if ((offset = (~offset) - 1) < 0) // no next-left JP in BranchL.
542 +#else
543 + if ((offset = (~offset)) >= Pjbl->jbl_NumJPs) // no next-right.
544 +#endif
545 + goto SM2Backtrack;
546 +
547 +// Theres a next-left/right JP in the current BranchL; save its digit in
548 +// *PIndex and shortcut to SM3Findlimit:
549 +
550 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
551 + Pjp = (Pjbl->jbl_jp) + offset;
552 + goto SM3Findlimit;
553 +
554 +
555 +// ----------------------------------------------------------------------------
556 +// BITMAP BRANCH:
557 +//
558 +// Check Decode bytes, if any, in the current JP, then look for a JP for the
559 +// next digit in *PIndex.
560 +
561 + case cJU_JPBRANCH_B2: CHECKDCD(2); SM1PREPB(2, SM1BranchB);
562 + case cJU_JPBRANCH_B3: CHECKDCD(3); SM1PREPB(3, SM1BranchB);
563 +#ifdef JU_64BIT
564 + case cJU_JPBRANCH_B4: CHECKDCD(4); SM1PREPB(4, SM1BranchB);
565 + case cJU_JPBRANCH_B5: CHECKDCD(5); SM1PREPB(5, SM1BranchB);
566 + case cJU_JPBRANCH_B6: CHECKDCD(6); SM1PREPB(6, SM1BranchB);
567 + case cJU_JPBRANCH_B7: CHECKDCD(7); SM1PREPB(7, SM1BranchB);
568 +#endif
569 + case cJU_JPBRANCH_B: SM1PREPB(cJU_ROOTSTATE, SM1BranchB);
570 +
571 +// Common code (state-independent) for all cases of bitmap branches:
572 +
573 +SM1BranchB:
574 + Pjbb = P_JBB(Pjp->jp_Addr);
575 +
576 +// Locate the digits JP in the subexpanse list, if present, otherwise the
577 +// offset of the next-left JP, if any:
578 +
579 + subexp = digit / cJU_BITSPERSUBEXPB;
580 + assert(subexp < cJU_NUMSUBEXPB); // falls in expected range.
581 + bitposmask = JU_BITPOSMASKB(digit);
582 + offset = SEARCHBITMAPB(JU_JBB_BITMAP(Pjbb, subexp), digit,
583 + bitposmask);
584 + // right range:
585 + assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPB));
586 +
587 +// Found JP matching current digit in *PIndex:
588 +//
589 +// Record the parent JP and the next JPs offset; and iterate to the next JP.
590 +
591 +// if (JU_BITMAPTESTB(Pjbb, digit)) // slower.
592 + if (JU_JBB_BITMAP(Pjbb, subexp) & bitposmask) // faster.
593 + {
594 + // not negative since at least one bit is set:
595 + assert(offset >= 0);
596 +
597 + HISTPUSH(Pjp, HISTPUSHBOFF(subexp, offset, digit));
598 +
599 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
600 + {
601 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
602 + JUDY1CODE(return(JERRI );)
603 + JUDYLCODE(return(PPJERR);)
604 + }
605 +
606 + Pjp += offset;
607 + goto SM1Get; // iterate to next JP.
608 + }
609 +
610 +// Dead end, no JP in BranchB for next digit in *PIndex:
611 +//
612 +// If theres a next-left/right JP in the current BranchB, shortcut to
613 +// SM3Findlimit. Note: offset is already set to the correct value for the
614 +// next-left/right JP.
615 +
616 +#ifdef JUDYPREV
617 + if (offset >= 0) // next-left JP is in this subexpanse.
618 + goto SM1BranchBFindlimit;
619 +
620 + while (--subexp >= 0) // search next-left subexpanses.
621 +#else
622 + if (JU_JBB_BITMAP(Pjbb, subexp) & JU_MASKHIGHEREXC(bitposmask))
623 + {
624 + ++offset; // next-left => next-right.
625 + goto SM1BranchBFindlimit;
626 + }
627 +
628 + while (++subexp < cJU_NUMSUBEXPB) // search next-right subexps.
629 +#endif
630 + {
631 + if (! JU_JBB_PJP(Pjbb, subexp)) continue; // empty subexpanse.
632 +
633 +#ifdef JUDYPREV
634 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
635 + // expected range:
636 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
637 +#else
638 + offset = 0;
639 +#endif
640 +
641 +// Save the next-left/right JPs digit in *PIndex:
642 +
643 +SM1BranchBFindlimit:
644 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
645 + offset);
646 + JU_SETDIGIT(*PIndex, digit, state);
647 +
648 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
649 + {
650 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
651 + JUDY1CODE(return(JERRI );)
652 + JUDYLCODE(return(PPJERR);)
653 + }
654 +
655 + Pjp += offset;
656 + goto SM3Findlimit;
657 + }
658 +
659 +// Theres no next-left/right JP in the BranchB:
660 +//
661 +// Shortcut and start backtracking one level up; ignore the current Pjp because
662 +// it points to a BranchB with no next-left/right JP.
663 +
664 + goto SM2Backtrack;
665 +
666 +
667 +// ----------------------------------------------------------------------------
668 +// UNCOMPRESSED BRANCH:
669 +//
670 +// Check Decode bytes, if any, in the current JP, then look for a JP for the
671 +// next digit in *PIndex.
672 +
673 + case cJU_JPBRANCH_U2: CHECKDCD(2); SM1PREPB(2, SM1BranchU);
674 + case cJU_JPBRANCH_U3: CHECKDCD(3); SM1PREPB(3, SM1BranchU);
675 +#ifdef JU_64BIT
676 + case cJU_JPBRANCH_U4: CHECKDCD(4); SM1PREPB(4, SM1BranchU);
677 + case cJU_JPBRANCH_U5: CHECKDCD(5); SM1PREPB(5, SM1BranchU);
678 + case cJU_JPBRANCH_U6: CHECKDCD(6); SM1PREPB(6, SM1BranchU);
679 + case cJU_JPBRANCH_U7: CHECKDCD(7); SM1PREPB(7, SM1BranchU);
680 +#endif
681 + case cJU_JPBRANCH_U: SM1PREPB(cJU_ROOTSTATE, SM1BranchU);
682 +
683 +// Common code (state-independent) for all cases of uncompressed branches:
684 +
685 +SM1BranchU:
686 + Pjbu = P_JBU(Pjp->jp_Addr);
687 + Pjp2 = (Pjbu->jbu_jp) + digit;
688 +
689 +// Found JP matching current digit in *PIndex:
690 +//
691 +// Record the parent JP and the next JPs digit, and iterate to the next JP.
692 +//
693 +// TBD: Instead of this, just goto SM1Get, and add cJU_JPNULL* cases to the
694 +// SM1Get state machine? Then backtrack? However, it means you cant detect
695 +// an inappropriate cJU_JPNULL*, when it occurs in other than a BranchU, and
696 +// return JU_RET_CORRUPT.
697 +
698 + if (! JPNULL(JU_JPTYPE(Pjp2))) // digit has a JP.
699 + {
700 + HISTPUSH(Pjp, digit);
701 + Pjp = Pjp2;
702 + goto SM1Get;
703 + }
704 +
705 +// Dead end, no JP in BranchU for next digit in *PIndex:
706 +//
707 +// Search for a next-left/right JP in the current BranchU, and if one is found,
708 +// save its digit in *PIndex and shortcut to SM3Findlimit:
709 +
710 +#ifdef JUDYPREV
711 + while (digit >= 1)
712 + {
713 + Pjp = (Pjbu->jbu_jp) + (--digit);
714 +#else
715 + while (digit < cJU_BRANCHUNUMJPS - 1)
716 + {
717 + Pjp = (Pjbu->jbu_jp) + (++digit);
718 +#endif
719 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
720 +
721 + JU_SETDIGIT(*PIndex, digit, state);
722 + goto SM3Findlimit;
723 + }
724 +
725 +// Theres no next-left/right JP in the BranchU:
726 +//
727 +// Shortcut and start backtracking one level up; ignore the current Pjp because
728 +// it points to a BranchU with no next-left/right JP.
729 +
730 + goto SM2Backtrack;
731 +
732 +
733 +// ----------------------------------------------------------------------------
734 +// LINEAR LEAF:
735 +//
736 +// Check Decode bytes, if any, in the current JP, then search the leaf for
737 +// *PIndex.
738 +
739 +#define SM1LEAFL(Func) \
740 + Pjll = P_JLL(Pjp->jp_Addr); \
741 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
742 + offset = Func(Pjll, pop1, *PIndex); \
743 + goto SM1LeafLImm
744 +
745 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
746 + case cJU_JPLEAF1: CHECKDCD(1); SM1LEAFL(j__udySearchLeaf1);
747 +#endif
748 + case cJU_JPLEAF2: CHECKDCD(2); SM1LEAFL(j__udySearchLeaf2);
749 + case cJU_JPLEAF3: CHECKDCD(3); SM1LEAFL(j__udySearchLeaf3);
750 +
751 +#ifdef JU_64BIT
752 + case cJU_JPLEAF4: CHECKDCD(4); SM1LEAFL(j__udySearchLeaf4);
753 + case cJU_JPLEAF5: CHECKDCD(5); SM1LEAFL(j__udySearchLeaf5);
754 + case cJU_JPLEAF6: CHECKDCD(6); SM1LEAFL(j__udySearchLeaf6);
755 + case cJU_JPLEAF7: CHECKDCD(7); SM1LEAFL(j__udySearchLeaf7);
756 +#endif
757 +
758 +// Common code (state-independent) for all cases of linear leaves and
759 +// immediates:
760 +
761 +SM1LeafLImm:
762 + if (offset >= 0) // *PIndex is in LeafL / Immed.
763 +#ifdef JUDY1
764 + JU_RET_FOUND;
765 +#else
766 + { // JudyL is trickier...
767 + switch (JU_JPTYPE(Pjp))
768 + {
769 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
770 + case cJU_JPLEAF1: JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
771 +#endif
772 + case cJU_JPLEAF2: JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
773 + case cJU_JPLEAF3: JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
774 +#ifdef JU_64BIT
775 + case cJU_JPLEAF4: JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
776 + case cJU_JPLEAF5: JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
777 + case cJU_JPLEAF6: JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
778 + case cJU_JPLEAF7: JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
779 +#endif
780 +
781 + case cJU_JPIMMED_1_01:
782 + case cJU_JPIMMED_2_01:
783 + case cJU_JPIMMED_3_01:
784 +#ifdef JU_64BIT
785 + case cJU_JPIMMED_4_01:
786 + case cJU_JPIMMED_5_01:
787 + case cJU_JPIMMED_6_01:
788 + case cJU_JPIMMED_7_01:
789 +#endif
790 + JU_RET_FOUND_IMM_01(Pjp);
791 +
792 + case cJU_JPIMMED_1_02:
793 + case cJU_JPIMMED_1_03:
794 +#ifdef JU_64BIT
795 + case cJU_JPIMMED_1_04:
796 + case cJU_JPIMMED_1_05:
797 + case cJU_JPIMMED_1_06:
798 + case cJU_JPIMMED_1_07:
799 + case cJU_JPIMMED_2_02:
800 + case cJU_JPIMMED_2_03:
801 + case cJU_JPIMMED_3_02:
802 +#endif
803 + JU_RET_FOUND_IMM(Pjp, offset);
804 + }
805 +
806 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // impossible?
807 + JUDY1CODE(return(JERRI );)
808 + JUDYLCODE(return(PPJERR);)
809 +
810 + } // found *PIndex
811 +
812 +#endif // JUDYL
813 +
814 +// Dead end, no Index in LeafL / Immed for remaining digit(s) in *PIndex:
815 +//
816 +// Get the ideal location of Index, and if theres no next-left/right Index in
817 +// the LeafL / Immed, shortcut and start backtracking one level up; ignore the
818 +// current Pjp because it points to a LeafL / Immed with no next-left/right
819 +// Index.
820 +
821 +#ifdef JUDYPREV
822 + if ((offset = (~offset) - 1) < 0) // no next-left Index.
823 +#else
824 + if ((offset = (~offset)) >= pop1) // no next-right Index.
825 +#endif
826 + goto SM2Backtrack;
827 +
828 +// Theres a next-left/right Index in the current LeafL / Immed; shortcut by
829 +// copying its digit(s) to *PIndex and returning it.
830 +//
831 +// Unfortunately this is pretty hairy, especially avoiding endian issues.
832 +//
833 +// The cJU_JPLEAF* cases are very similar to same-index-size cJU_JPIMMED* cases
834 +// for *_02 and above, but must return differently, at least for JudyL, so
835 +// spell them out separately here at the cost of a little redundant code for
836 +// Judy1.
837 +
838 + switch (JU_JPTYPE(Pjp))
839 + {
840 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
841 + case cJU_JPLEAF1:
842 +
843 + JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
844 + JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
845 +#endif
846 +
847 + case cJU_JPLEAF2:
848 +
849 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
850 + | ((uint16_t *) Pjll)[offset];
851 + JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
852 +
853 + case cJU_JPLEAF3:
854 + {
855 + Word_t lsb;
856 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
857 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
858 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
859 + }
860 +
861 +#ifdef JU_64BIT
862 + case cJU_JPLEAF4:
863 +
864 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
865 + | ((uint32_t *) Pjll)[offset];
866 + JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
867 +
868 + case cJU_JPLEAF5:
869 + {
870 + Word_t lsb;
871 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
872 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
873 + JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
874 + }
875 +
876 + case cJU_JPLEAF6:
877 + {
878 + Word_t lsb;
879 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
880 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
881 + JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
882 + }
883 +
884 + case cJU_JPLEAF7:
885 + {
886 + Word_t lsb;
887 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
888 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
889 + JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
890 + }
891 +
892 +#endif // JU_64BIT
893 +
894 +#define SET_01(cState) JU_SETDIGITS(*PIndex, JU_JPDCDPOP0(Pjp), cState)
895 +
896 + case cJU_JPIMMED_1_01: SET_01(1); goto SM1Imm_01;
897 + case cJU_JPIMMED_2_01: SET_01(2); goto SM1Imm_01;
898 + case cJU_JPIMMED_3_01: SET_01(3); goto SM1Imm_01;
899 +#ifdef JU_64BIT
900 + case cJU_JPIMMED_4_01: SET_01(4); goto SM1Imm_01;
901 + case cJU_JPIMMED_5_01: SET_01(5); goto SM1Imm_01;
902 + case cJU_JPIMMED_6_01: SET_01(6); goto SM1Imm_01;
903 + case cJU_JPIMMED_7_01: SET_01(7); goto SM1Imm_01;
904 +#endif
905 +SM1Imm_01: JU_RET_FOUND_IMM_01(Pjp);
906 +
907 +// Shorthand for where to find start of Index bytes array:
908 +
909 +#ifdef JUDY1
910 +#define PJI (Pjp->jp_1Index)
911 +#else
912 +#define PJI (Pjp->jp_LIndex)
913 +#endif
914 +
915 + case cJU_JPIMMED_1_02:
916 + case cJU_JPIMMED_1_03:
917 +#if (defined(JUDY1) || defined(JU_64BIT))
918 + case cJU_JPIMMED_1_04:
919 + case cJU_JPIMMED_1_05:
920 + case cJU_JPIMMED_1_06:
921 + case cJU_JPIMMED_1_07:
922 +#endif
923 +#if (defined(JUDY1) && defined(JU_64BIT))
924 + case cJ1_JPIMMED_1_08:
925 + case cJ1_JPIMMED_1_09:
926 + case cJ1_JPIMMED_1_10:
927 + case cJ1_JPIMMED_1_11:
928 + case cJ1_JPIMMED_1_12:
929 + case cJ1_JPIMMED_1_13:
930 + case cJ1_JPIMMED_1_14:
931 + case cJ1_JPIMMED_1_15:
932 +#endif
933 + JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
934 + JU_RET_FOUND_IMM(Pjp, offset);
935 +
936 +#if (defined(JUDY1) || defined(JU_64BIT))
937 + case cJU_JPIMMED_2_02:
938 + case cJU_JPIMMED_2_03:
939 +#endif
940 +#if (defined(JUDY1) && defined(JU_64BIT))
941 + case cJ1_JPIMMED_2_04:
942 + case cJ1_JPIMMED_2_05:
943 + case cJ1_JPIMMED_2_06:
944 + case cJ1_JPIMMED_2_07:
945 +#endif
946 +#if (defined(JUDY1) || defined(JU_64BIT))
947 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
948 + | ((uint16_t *) PJI)[offset];
949 + JU_RET_FOUND_IMM(Pjp, offset);
950 +#endif
951 +
952 +#if (defined(JUDY1) || defined(JU_64BIT))
953 + case cJU_JPIMMED_3_02:
954 +#endif
955 +#if (defined(JUDY1) && defined(JU_64BIT))
956 + case cJ1_JPIMMED_3_03:
957 + case cJ1_JPIMMED_3_04:
958 + case cJ1_JPIMMED_3_05:
959 +#endif
960 +#if (defined(JUDY1) || defined(JU_64BIT))
961 + {
962 + Word_t lsb;
963 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
964 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
965 + JU_RET_FOUND_IMM(Pjp, offset);
966 + }
967 +#endif
968 +
969 +#if (defined(JUDY1) && defined(JU_64BIT))
970 + case cJ1_JPIMMED_4_02:
971 + case cJ1_JPIMMED_4_03:
972 +
973 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
974 + | ((uint32_t *) PJI)[offset];
975 + JU_RET_FOUND_IMM(Pjp, offset);
976 +
977 + case cJ1_JPIMMED_5_02:
978 + case cJ1_JPIMMED_5_03:
979 + {
980 + Word_t lsb;
981 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
982 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
983 + JU_RET_FOUND_IMM(Pjp, offset);
984 + }
985 +
986 + case cJ1_JPIMMED_6_02:
987 + {
988 + Word_t lsb;
989 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
990 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
991 + JU_RET_FOUND_IMM(Pjp, offset);
992 + }
993 +
994 + case cJ1_JPIMMED_7_02:
995 + {
996 + Word_t lsb;
997 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
998 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
999 + JU_RET_FOUND_IMM(Pjp, offset);
1000 + }
1001 +
1002 +#endif // (JUDY1 && JU_64BIT)
1003 +
1004 + } // switch for not-found *PIndex
1005 +
1006 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // impossible?
1007 + JUDY1CODE(return(JERRI );)
1008 + JUDYLCODE(return(PPJERR);)
1009 +
1010 +
1011 +// ----------------------------------------------------------------------------
1012 +// BITMAP LEAF:
1013 +//
1014 +// Check Decode bytes, if any, in the current JP, then look in the leaf for
1015 +// *PIndex.
1016 +
1017 + case cJU_JPLEAF_B1:
1018 + {
1019 + Pjlb_t Pjlb;
1020 + CHECKDCD(1);
1021 +
1022 + Pjlb = P_JLB(Pjp->jp_Addr);
1023 + digit = JU_DIGITATSTATE(*PIndex, 1);
1024 + subexp = JU_SUBEXPL(digit);
1025 + bitposmask = JU_BITPOSMASKL(digit);
1026 + assert(subexp < cJU_NUMSUBEXPL); // falls in expected range.
1027 +
1028 +// *PIndex exists in LeafB1:
1029 +
1030 +// if (JU_BITMAPTESTL(Pjlb, digit)) // slower.
1031 + if (JU_JLB_BITMAP(Pjlb, subexp) & bitposmask) // faster.
1032 + {
1033 +#ifdef JUDYL // needs offset at this point:
1034 + offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit, bitposmask);
1035 +#endif
1036 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1037 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1038 + }
1039 +
1040 +// Dead end, no Index in LeafB1 for remaining digit in *PIndex:
1041 +//
1042 +// If theres a next-left/right Index in the current LeafB1, which for
1043 +// Judy*Next() is true if any bits are set for higher Indexes, shortcut by
1044 +// returning it. Note: For Judy*Prev(), offset is set here to the correct
1045 +// value for the next-left JP.
1046 +
1047 + offset = SEARCHBITMAPL(JU_JLB_BITMAP(Pjlb, subexp), digit,
1048 + bitposmask);
1049 + // right range:
1050 + assert((offset >= -1) && (offset < (int) cJU_BITSPERSUBEXPL));
1051 +
1052 +#ifdef JUDYPREV
1053 + if (offset >= 0) // next-left JP is in this subexpanse.
1054 + goto SM1LeafB1Findlimit;
1055 +
1056 + while (--subexp >= 0) // search next-left subexpanses.
1057 +#else
1058 + if (JU_JLB_BITMAP(Pjlb, subexp) & JU_MASKHIGHEREXC(bitposmask))
1059 + {
1060 + ++offset; // next-left => next-right.
1061 + goto SM1LeafB1Findlimit;
1062 + }
1063 +
1064 + while (++subexp < cJU_NUMSUBEXPL) // search next-right subexps.
1065 +#endif
1066 + {
1067 + if (! JU_JLB_BITMAP(Pjlb, subexp)) continue; // empty subexp.
1068 +
1069 +#ifdef JUDYPREV
1070 + offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
1071 + // expected range:
1072 + assert((offset >= 0) && (offset < (int) cJU_BITSPERSUBEXPL));
1073 +#else
1074 + offset = 0;
1075 +#endif
1076 +
1077 +// Save the next-left/right Indexess digit in *PIndex:
1078 +
1079 +SM1LeafB1Findlimit:
1080 + JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
1081 + JU_SETDIGIT1(*PIndex, digit);
1082 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1083 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1084 + }
1085 +
1086 +// Theres no next-left/right Index in the LeafB1:
1087 +//
1088 +// Shortcut and start backtracking one level up; ignore the current Pjp because
1089 +// it points to a LeafB1 with no next-left/right Index.
1090 +
1091 + goto SM2Backtrack;
1092 +
1093 + } // case cJU_JPLEAF_B1
1094 +
1095 +#ifdef JUDY1
1096 +// ----------------------------------------------------------------------------
1097 +// FULL POPULATION:
1098 +//
1099 +// If the Decode bytes match, *PIndex is found (without modification).
1100 +
1101 + case cJ1_JPFULLPOPU1:
1102 +
1103 + CHECKDCD(1);
1104 + JU_RET_FOUND_FULLPOPU1;
1105 +#endif
1106 +
1107 +
1108 +// ----------------------------------------------------------------------------
1109 +// IMMEDIATE:
1110 +
1111 +#ifdef JUDYPREV
1112 +#define SM1IMM_SETPOP1(cPop1)
1113 +#else
1114 +#define SM1IMM_SETPOP1(cPop1) pop1 = (cPop1)
1115 +#endif
1116 +
1117 +#define SM1IMM(Func,cPop1) \
1118 + SM1IMM_SETPOP1(cPop1); \
1119 + offset = Func((Pjll_t) (PJI), cPop1, *PIndex); \
1120 + goto SM1LeafLImm
1121 +
1122 +// Special case for Pop1 = 1 Immediate JPs:
1123 +//
1124 +// If *PIndex is in the immediate, offset is 0, otherwise the binary NOT of the
1125 +// offset where it belongs, 0 or 1, same as from the search functions.
1126 +
1127 +#ifdef JUDYPREV
1128 +#define SM1IMM_01_SETPOP1
1129 +#else
1130 +#define SM1IMM_01_SETPOP1 pop1 = 1
1131 +#endif
1132 +
1133 +#define SM1IMM_01 \
1134 + SM1IMM_01_SETPOP1; \
1135 + offset = ((JU_JPDCDPOP0(Pjp) < JU_TRIMTODCDSIZE(*PIndex)) ? ~1 : \
1136 + (JU_JPDCDPOP0(Pjp) == JU_TRIMTODCDSIZE(*PIndex)) ? 0 : \
1137 + ~0); \
1138 + goto SM1LeafLImm
1139 +
1140 + case cJU_JPIMMED_1_01:
1141 + case cJU_JPIMMED_2_01:
1142 + case cJU_JPIMMED_3_01:
1143 +#ifdef JU_64BIT
1144 + case cJU_JPIMMED_4_01:
1145 + case cJU_JPIMMED_5_01:
1146 + case cJU_JPIMMED_6_01:
1147 + case cJU_JPIMMED_7_01:
1148 +#endif
1149 + SM1IMM_01;
1150 +
1151 +// TBD: Doug says it would be OK to have fewer calls and calculate arg 2, here
1152 +// and in Judy*Count() also.
1153 +
1154 + case cJU_JPIMMED_1_02: SM1IMM(j__udySearchLeaf1, 2);
1155 + case cJU_JPIMMED_1_03: SM1IMM(j__udySearchLeaf1, 3);
1156 +#if (defined(JUDY1) || defined(JU_64BIT))
1157 + case cJU_JPIMMED_1_04: SM1IMM(j__udySearchLeaf1, 4);
1158 + case cJU_JPIMMED_1_05: SM1IMM(j__udySearchLeaf1, 5);
1159 + case cJU_JPIMMED_1_06: SM1IMM(j__udySearchLeaf1, 6);
1160 + case cJU_JPIMMED_1_07: SM1IMM(j__udySearchLeaf1, 7);
1161 +#endif
1162 +#if (defined(JUDY1) && defined(JU_64BIT))
1163 + case cJ1_JPIMMED_1_08: SM1IMM(j__udySearchLeaf1, 8);
1164 + case cJ1_JPIMMED_1_09: SM1IMM(j__udySearchLeaf1, 9);
1165 + case cJ1_JPIMMED_1_10: SM1IMM(j__udySearchLeaf1, 10);
1166 + case cJ1_JPIMMED_1_11: SM1IMM(j__udySearchLeaf1, 11);
1167 + case cJ1_JPIMMED_1_12: SM1IMM(j__udySearchLeaf1, 12);
1168 + case cJ1_JPIMMED_1_13: SM1IMM(j__udySearchLeaf1, 13);
1169 + case cJ1_JPIMMED_1_14: SM1IMM(j__udySearchLeaf1, 14);
1170 + case cJ1_JPIMMED_1_15: SM1IMM(j__udySearchLeaf1, 15);
1171 +#endif
1172 +
1173 +#if (defined(JUDY1) || defined(JU_64BIT))
1174 + case cJU_JPIMMED_2_02: SM1IMM(j__udySearchLeaf2, 2);
1175 + case cJU_JPIMMED_2_03: SM1IMM(j__udySearchLeaf2, 3);
1176 +#endif
1177 +#if (defined(JUDY1) && defined(JU_64BIT))
1178 + case cJ1_JPIMMED_2_04: SM1IMM(j__udySearchLeaf2, 4);
1179 + case cJ1_JPIMMED_2_05: SM1IMM(j__udySearchLeaf2, 5);
1180 + case cJ1_JPIMMED_2_06: SM1IMM(j__udySearchLeaf2, 6);
1181 + case cJ1_JPIMMED_2_07: SM1IMM(j__udySearchLeaf2, 7);
1182 +#endif
1183 +
1184 +#if (defined(JUDY1) || defined(JU_64BIT))
1185 + case cJU_JPIMMED_3_02: SM1IMM(j__udySearchLeaf3, 2);
1186 +#endif
1187 +#if (defined(JUDY1) && defined(JU_64BIT))
1188 + case cJ1_JPIMMED_3_03: SM1IMM(j__udySearchLeaf3, 3);
1189 + case cJ1_JPIMMED_3_04: SM1IMM(j__udySearchLeaf3, 4);
1190 + case cJ1_JPIMMED_3_05: SM1IMM(j__udySearchLeaf3, 5);
1191 +
1192 + case cJ1_JPIMMED_4_02: SM1IMM(j__udySearchLeaf4, 2);
1193 + case cJ1_JPIMMED_4_03: SM1IMM(j__udySearchLeaf4, 3);
1194 +
1195 + case cJ1_JPIMMED_5_02: SM1IMM(j__udySearchLeaf5, 2);
1196 + case cJ1_JPIMMED_5_03: SM1IMM(j__udySearchLeaf5, 3);
1197 +
1198 + case cJ1_JPIMMED_6_02: SM1IMM(j__udySearchLeaf6, 2);
1199 +
1200 + case cJ1_JPIMMED_7_02: SM1IMM(j__udySearchLeaf7, 2);
1201 +#endif
1202 +
1203 +
1204 +// ----------------------------------------------------------------------------
1205 +// INVALID JP TYPE:
1206 +
1207 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1208 + JUDY1CODE(return(JERRI );)
1209 + JUDYLCODE(return(PPJERR);)
1210 +
1211 + } // SM1Get switch.
1212 +
1213 + /*NOTREACHED*/
1214 +
1215 +
1216 +// ============================================================================
1217 +// STATE MACHINE 2 -- BACKTRACK BRANCH TO PREVIOUS JP:
1218 +//
1219 +// Look for the next-left/right JP in a branch, backing up the history list as
1220 +// necessary. Upon finding a next-left/right JP, modify the corresponding
1221 +// digit in *PIndex before passing control to SM3Findlimit.
1222 +//
1223 +// Note: As described earlier, only branch JPs are expected here; other types
1224 +// fall into the default case.
1225 +//
1226 +// Note: If a found JP contains needed Dcd bytes, thats OK, theyre copied to
1227 +// *PIndex in SM3Findlimit.
1228 +//
1229 +// TBD: This code has a lot in common with similar code in the shortcut cases
1230 +// in SM1Get. Can combine this code somehow?
1231 +//
1232 +// ENTRY: List, possibly empty, of JPs and offsets in APjphist[] and
1233 +// Aoffhist[]; see earlier comments.
1234 +//
1235 +// EXIT: Execute JU_RET_NOTFOUND if no previous/next JP; otherwise jump to
1236 +// SM3Findlimit to resume a new but different downward search.
1237 +
1238 +SM2Backtrack: // come or return here for first/next sideways search.
1239 +
1240 + HISTPOP(Pjp, offset);
1241 +
1242 + switch (JU_JPTYPE(Pjp))
1243 + {
1244 +
1245 +
1246 +// ----------------------------------------------------------------------------
1247 +// LINEAR BRANCH:
1248 +
1249 + case cJU_JPBRANCH_L2: state = 2; goto SM2BranchL;
1250 + case cJU_JPBRANCH_L3: state = 3; goto SM2BranchL;
1251 +#ifdef JU_64BIT
1252 + case cJU_JPBRANCH_L4: state = 4; goto SM2BranchL;
1253 + case cJU_JPBRANCH_L5: state = 5; goto SM2BranchL;
1254 + case cJU_JPBRANCH_L6: state = 6; goto SM2BranchL;
1255 + case cJU_JPBRANCH_L7: state = 7; goto SM2BranchL;
1256 +#endif
1257 + case cJU_JPBRANCH_L: state = cJU_ROOTSTATE; goto SM2BranchL;
1258 +
1259 +SM2BranchL:
1260 +#ifdef JUDYPREV
1261 + if (--offset < 0) goto SM2Backtrack; // no next-left JP in BranchL.
1262 +#endif
1263 + Pjbl = P_JBL(Pjp->jp_Addr);
1264 +#ifdef JUDYNEXT
1265 + if (++offset >= (Pjbl->jbl_NumJPs)) goto SM2Backtrack;
1266 + // no next-right JP in BranchL.
1267 +#endif
1268 +
1269 +// Theres a next-left/right JP in the current BranchL; save its digit in
1270 +// *PIndex and continue with SM3Findlimit:
1271 +
1272 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
1273 + Pjp = (Pjbl->jbl_jp) + offset;
1274 + goto SM3Findlimit;
1275 +
1276 +
1277 +// ----------------------------------------------------------------------------
1278 +// BITMAP BRANCH:
1279 +
1280 + case cJU_JPBRANCH_B2: state = 2; goto SM2BranchB;
1281 + case cJU_JPBRANCH_B3: state = 3; goto SM2BranchB;
1282 +#ifdef JU_64BIT
1283 + case cJU_JPBRANCH_B4: state = 4; goto SM2BranchB;
1284 + case cJU_JPBRANCH_B5: state = 5; goto SM2BranchB;
1285 + case cJU_JPBRANCH_B6: state = 6; goto SM2BranchB;
1286 + case cJU_JPBRANCH_B7: state = 7; goto SM2BranchB;
1287 +#endif
1288 + case cJU_JPBRANCH_B: state = cJU_ROOTSTATE; goto SM2BranchB;
1289 +
1290 +SM2BranchB:
1291 + Pjbb = P_JBB(Pjp->jp_Addr);
1292 + HISTPOPBOFF(subexp, offset, digit); // unpack values.
1293 +
1294 +// If theres a next-left/right JP in the current BranchB, which for
1295 +// Judy*Next() is true if any bits are set for higher Indexes, continue to
1296 +// SM3Findlimit:
1297 +//
1298 +// Note: offset is set to the JP previously traversed; go one to the
1299 +// left/right.
1300 +
1301 +#ifdef JUDYPREV
1302 + if (offset > 0) // next-left JP is in this subexpanse.
1303 + {
1304 + --offset;
1305 + goto SM2BranchBFindlimit;
1306 + }
1307 +
1308 + while (--subexp >= 0) // search next-left subexpanses.
1309 +#else
1310 + if (JU_JBB_BITMAP(Pjbb, subexp)
1311 + & JU_MASKHIGHEREXC(JU_BITPOSMASKB(digit)))
1312 + {
1313 + ++offset; // next-left => next-right.
1314 + goto SM2BranchBFindlimit;
1315 + }
1316 +
1317 + while (++subexp < cJU_NUMSUBEXPB) // search next-right subexps.
1318 +#endif
1319 + {
1320 + if (! JU_JBB_PJP(Pjbb, subexp)) continue; // empty subexpanse.
1321 +
1322 +#ifdef JUDYPREV
1323 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
1324 + // expected range:
1325 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
1326 +#else
1327 + offset = 0;
1328 +#endif
1329 +
1330 +// Save the next-left/right JPs digit in *PIndex:
1331 +
1332 +SM2BranchBFindlimit:
1333 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp),
1334 + offset);
1335 + JU_SETDIGIT(*PIndex, digit, state);
1336 +
1337 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
1338 + {
1339 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1340 + JUDY1CODE(return(JERRI );)
1341 + JUDYLCODE(return(PPJERR);)
1342 + }
1343 +
1344 + Pjp += offset;
1345 + goto SM3Findlimit;
1346 + }
1347 +
1348 +// Theres no next-left/right JP in the BranchB:
1349 +
1350 + goto SM2Backtrack;
1351 +
1352 +
1353 +// ----------------------------------------------------------------------------
1354 +// UNCOMPRESSED BRANCH:
1355 +
1356 + case cJU_JPBRANCH_U2: state = 2; goto SM2BranchU;
1357 + case cJU_JPBRANCH_U3: state = 3; goto SM2BranchU;
1358 +#ifdef JU_64BIT
1359 + case cJU_JPBRANCH_U4: state = 4; goto SM2BranchU;
1360 + case cJU_JPBRANCH_U5: state = 5; goto SM2BranchU;
1361 + case cJU_JPBRANCH_U6: state = 6; goto SM2BranchU;
1362 + case cJU_JPBRANCH_U7: state = 7; goto SM2BranchU;
1363 +#endif
1364 + case cJU_JPBRANCH_U: state = cJU_ROOTSTATE; goto SM2BranchU;
1365 +
1366 +SM2BranchU:
1367 +
1368 +// Search for a next-left/right JP in the current BranchU, and if one is found,
1369 +// save its digit in *PIndex and continue to SM3Findlimit:
1370 +
1371 + Pjbu = P_JBU(Pjp->jp_Addr);
1372 + digit = offset;
1373 +
1374 +#ifdef JUDYPREV
1375 + while (digit >= 1)
1376 + {
1377 + Pjp = (Pjbu->jbu_jp) + (--digit);
1378 +#else
1379 + while (digit < cJU_BRANCHUNUMJPS - 1)
1380 + {
1381 + Pjp = (Pjbu->jbu_jp) + (++digit);
1382 +#endif
1383 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
1384 +
1385 + JU_SETDIGIT(*PIndex, digit, state);
1386 + goto SM3Findlimit;
1387 + }
1388 +
1389 +// Theres no next-left/right JP in the BranchU:
1390 +
1391 + goto SM2Backtrack;
1392 +
1393 +
1394 +// ----------------------------------------------------------------------------
1395 +// INVALID JP TYPE:
1396 +
1397 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1398 + JUDY1CODE(return(JERRI );)
1399 + JUDYLCODE(return(PPJERR);)
1400 +
1401 + } // SM2Backtrack switch.
1402 +
1403 + /*NOTREACHED*/
1404 +
1405 +
1406 +// ============================================================================
1407 +// STATE MACHINE 3 -- FIND LIMIT JP/INDEX:
1408 +//
1409 +// Look for the highest/lowest (right/left-most) JP in each branch and the
1410 +// highest/lowest Index in a leaf or immediate, and return it. While
1411 +// traversing, modify appropriate digit(s) in *PIndex to reflect the path
1412 +// taken, including Dcd bytes in each JP (which could hold critical missing
1413 +// digits for skipped branches).
1414 +//
1415 +// ENTRY: Pjp set to a JP under which to find max/min JPs (if a branch JP) or
1416 +// a max/min Index and return (if a leaf or immediate JP).
1417 +//
1418 +// EXIT: Execute JU_RET_FOUND* upon reaching a leaf or immediate. Should be
1419 +// impossible to fail, unless the Judy array is corrupt.
1420 +
1421 +SM3Findlimit: // come or return here for first/next branch/leaf.
1422 +
1423 + switch (JU_JPTYPE(Pjp))
1424 + {
1425 +// ----------------------------------------------------------------------------
1426 +// LINEAR BRANCH:
1427 +//
1428 +// Simply use the highest/lowest (right/left-most) JP in the BranchL, but first
1429 +// copy the Dcd bytes to *PIndex if there are any (only if state <
1430 +// cJU_ROOTSTATE - 1).
1431 +
1432 + case cJU_JPBRANCH_L2: SM3PREPB_DCD(2, SM3BranchL);
1433 +#ifndef JU_64BIT
1434 + case cJU_JPBRANCH_L3: SM3PREPB( 3, SM3BranchL);
1435 +#else
1436 + case cJU_JPBRANCH_L3: SM3PREPB_DCD(3, SM3BranchL);
1437 + case cJU_JPBRANCH_L4: SM3PREPB_DCD(4, SM3BranchL);
1438 + case cJU_JPBRANCH_L5: SM3PREPB_DCD(5, SM3BranchL);
1439 + case cJU_JPBRANCH_L6: SM3PREPB_DCD(6, SM3BranchL);
1440 + case cJU_JPBRANCH_L7: SM3PREPB( 7, SM3BranchL);
1441 +#endif
1442 + case cJU_JPBRANCH_L: SM3PREPB( cJU_ROOTSTATE, SM3BranchL);
1443 +
1444 +SM3BranchL:
1445 + Pjbl = P_JBL(Pjp->jp_Addr);
1446 +
1447 +#ifdef JUDYPREV
1448 + if ((offset = (Pjbl->jbl_NumJPs) - 1) < 0)
1449 +#else
1450 + offset = 0; if ((Pjbl->jbl_NumJPs) == 0)
1451 +#endif
1452 + {
1453 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1454 + JUDY1CODE(return(JERRI );)
1455 + JUDYLCODE(return(PPJERR);)
1456 + }
1457 +
1458 + JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[offset], state);
1459 + Pjp = (Pjbl->jbl_jp) + offset;
1460 + goto SM3Findlimit;
1461 +
1462 +
1463 +// ----------------------------------------------------------------------------
1464 +// BITMAP BRANCH:
1465 +//
1466 +// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
1467 +// the highest/lowest JP in that subexpanse, but first copy Dcd bytes, if there
1468 +// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.
1469 +
1470 + case cJU_JPBRANCH_B2: SM3PREPB_DCD(2, SM3BranchB);
1471 +#ifndef JU_64BIT
1472 + case cJU_JPBRANCH_B3: SM3PREPB( 3, SM3BranchB);
1473 +#else
1474 + case cJU_JPBRANCH_B3: SM3PREPB_DCD(3, SM3BranchB);
1475 + case cJU_JPBRANCH_B4: SM3PREPB_DCD(4, SM3BranchB);
1476 + case cJU_JPBRANCH_B5: SM3PREPB_DCD(5, SM3BranchB);
1477 + case cJU_JPBRANCH_B6: SM3PREPB_DCD(6, SM3BranchB);
1478 + case cJU_JPBRANCH_B7: SM3PREPB( 7, SM3BranchB);
1479 +#endif
1480 + case cJU_JPBRANCH_B: SM3PREPB( cJU_ROOTSTATE, SM3BranchB);
1481 +
1482 +SM3BranchB:
1483 + Pjbb = P_JBB(Pjp->jp_Addr);
1484 +#ifdef JUDYPREV
1485 + subexp = cJU_NUMSUBEXPB;
1486 +
1487 + while (! (JU_JBB_BITMAP(Pjbb, --subexp))) // find non-empty subexp.
1488 + {
1489 + if (subexp <= 0) // wholly empty bitmap.
1490 + {
1491 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1492 + JUDY1CODE(return(JERRI );)
1493 + JUDYLCODE(return(PPJERR);)
1494 + }
1495 + }
1496 +
1497 + offset = SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp));
1498 + // expected range:
1499 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPB));
1500 +#else
1501 + subexp = -1;
1502 +
1503 + while (! (JU_JBB_BITMAP(Pjbb, ++subexp))) // find non-empty subexp.
1504 + {
1505 + if (subexp >= cJU_NUMSUBEXPB - 1) // didnt find one.
1506 + {
1507 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1508 + JUDY1CODE(return(JERRI );)
1509 + JUDYLCODE(return(PPJERR);)
1510 + }
1511 + }
1512 +
1513 + offset = 0;
1514 +#endif
1515 +
1516 + JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb, subexp), offset);
1517 + JU_SETDIGIT(*PIndex, digit, state);
1518 +
1519 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL)
1520 + {
1521 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1522 + JUDY1CODE(return(JERRI );)
1523 + JUDYLCODE(return(PPJERR);)
1524 + }
1525 +
1526 + Pjp += offset;
1527 + goto SM3Findlimit;
1528 +
1529 +
1530 +// ----------------------------------------------------------------------------
1531 +// UNCOMPRESSED BRANCH:
1532 +//
1533 +// Look for the highest/lowest (right/left-most) non-null JP, and use it, but
1534 +// first copy Dcd bytes to *PIndex if there are any (only if state <
1535 +// cJU_ROOTSTATE - 1).
1536 +
1537 + case cJU_JPBRANCH_U2: SM3PREPB_DCD(2, SM3BranchU);
1538 +#ifndef JU_64BIT
1539 + case cJU_JPBRANCH_U3: SM3PREPB( 3, SM3BranchU);
1540 +#else
1541 + case cJU_JPBRANCH_U3: SM3PREPB_DCD(3, SM3BranchU);
1542 + case cJU_JPBRANCH_U4: SM3PREPB_DCD(4, SM3BranchU);
1543 + case cJU_JPBRANCH_U5: SM3PREPB_DCD(5, SM3BranchU);
1544 + case cJU_JPBRANCH_U6: SM3PREPB_DCD(6, SM3BranchU);
1545 + case cJU_JPBRANCH_U7: SM3PREPB( 7, SM3BranchU);
1546 +#endif
1547 + case cJU_JPBRANCH_U: SM3PREPB( cJU_ROOTSTATE, SM3BranchU);
1548 +
1549 +SM3BranchU:
1550 + Pjbu = P_JBU(Pjp->jp_Addr);
1551 +#ifdef JUDYPREV
1552 + digit = cJU_BRANCHUNUMJPS;
1553 +
1554 + while (digit >= 1)
1555 + {
1556 + Pjp = (Pjbu->jbu_jp) + (--digit);
1557 +#else
1558 +
1559 + for (digit = 0; digit < cJU_BRANCHUNUMJPS; ++digit)
1560 + {
1561 + Pjp = (Pjbu->jbu_jp) + digit;
1562 +#endif
1563 + if (JPNULL(JU_JPTYPE(Pjp))) continue;
1564 +
1565 + JU_SETDIGIT(*PIndex, digit, state);
1566 + goto SM3Findlimit;
1567 + }
1568 +
1569 +// No non-null JPs in BranchU:
1570 +
1571 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1572 + JUDY1CODE(return(JERRI );)
1573 + JUDYLCODE(return(PPJERR);)
1574 +
1575 +
1576 +// ----------------------------------------------------------------------------
1577 +// LINEAR LEAF:
1578 +//
1579 +// Simply use the highest/lowest (right/left-most) Index in the LeafL, but the
1580 +// details vary depending on leaf Index Size. First copy Dcd bytes, if there
1581 +// are any (only if state < cJU_ROOTSTATE - 1), to *PIndex.
1582 +
1583 +#define SM3LEAFLDCD(cState) \
1584 + JU_SETDCD(*PIndex, Pjp, cState); \
1585 + SM3LEAFLNODCD
1586 +
1587 +#ifdef JUDY1
1588 +#define SM3LEAFL_SETPOP1 // not needed in any cases.
1589 +#else
1590 +#define SM3LEAFL_SETPOP1 pop1 = JU_JPLEAF_POP0(Pjp) + 1
1591 +#endif
1592 +
1593 +#ifdef JUDYPREV
1594 +#define SM3LEAFLNODCD \
1595 + Pjll = P_JLL(Pjp->jp_Addr); \
1596 + SM3LEAFL_SETPOP1; \
1597 + offset = JU_JPLEAF_POP0(Pjp); assert(offset >= 0)
1598 +#else
1599 +#define SM3LEAFLNODCD \
1600 + Pjll = P_JLL(Pjp->jp_Addr); \
1601 + SM3LEAFL_SETPOP1; \
1602 + offset = 0; assert(JU_JPLEAF_POP0(Pjp) >= 0);
1603 +#endif
1604 +
1605 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1606 + case cJU_JPLEAF1:
1607 +
1608 + SM3LEAFLDCD(1);
1609 + JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
1610 + JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
1611 +#endif
1612 +
1613 + case cJU_JPLEAF2:
1614 +
1615 + SM3LEAFLDCD(2);
1616 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
1617 + | ((uint16_t *) Pjll)[offset];
1618 + JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
1619 +
1620 +#ifndef JU_64BIT
1621 + case cJU_JPLEAF3:
1622 + {
1623 + Word_t lsb;
1624 + SM3LEAFLNODCD;
1625 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
1626 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1627 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
1628 + }
1629 +
1630 +#else
1631 + case cJU_JPLEAF3:
1632 + {
1633 + Word_t lsb;
1634 + SM3LEAFLDCD(3);
1635 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
1636 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1637 + JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
1638 + }
1639 +
1640 + case cJU_JPLEAF4:
1641 +
1642 + SM3LEAFLDCD(4);
1643 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
1644 + | ((uint32_t *) Pjll)[offset];
1645 + JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
1646 +
1647 + case cJU_JPLEAF5:
1648 + {
1649 + Word_t lsb;
1650 + SM3LEAFLDCD(5);
1651 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
1652 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
1653 + JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
1654 + }
1655 +
1656 + case cJU_JPLEAF6:
1657 + {
1658 + Word_t lsb;
1659 + SM3LEAFLDCD(6);
1660 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
1661 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
1662 + JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
1663 + }
1664 +
1665 + case cJU_JPLEAF7:
1666 + {
1667 + Word_t lsb;
1668 + SM3LEAFLNODCD;
1669 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
1670 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
1671 + JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
1672 + }
1673 +#endif
1674 +
1675 +
1676 +// ----------------------------------------------------------------------------
1677 +// BITMAP LEAF:
1678 +//
1679 +// Look for the highest/lowest (right/left-most) non-null subexpanse, then use
1680 +// the highest/lowest Index in that subexpanse, but first copy Dcd bytes
1681 +// (always present since state 1 < cJU_ROOTSTATE) to *PIndex.
1682 +
1683 + case cJU_JPLEAF_B1:
1684 + {
1685 + Pjlb_t Pjlb;
1686 +
1687 + JU_SETDCD(*PIndex, Pjp, 1);
1688 +
1689 + Pjlb = P_JLB(Pjp->jp_Addr);
1690 +#ifdef JUDYPREV
1691 + subexp = cJU_NUMSUBEXPL;
1692 +
1693 + while (! JU_JLB_BITMAP(Pjlb, --subexp)) // find non-empty subexp.
1694 + {
1695 + if (subexp <= 0) // wholly empty bitmap.
1696 + {
1697 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1698 + JUDY1CODE(return(JERRI );)
1699 + JUDYLCODE(return(PPJERR);)
1700 + }
1701 + }
1702 +
1703 +// TBD: Might it be faster to just use a variant of BITMAPDIGIT*() that yields
1704 +// the digit for the right-most Index with a bit set?
1705 +
1706 + offset = SEARCHBITMAPMAXL(JU_JLB_BITMAP(Pjlb, subexp));
1707 + // expected range:
1708 + assert((offset >= 0) && (offset < cJU_BITSPERSUBEXPL));
1709 +#else
1710 + subexp = -1;
1711 +
1712 + while (! JU_JLB_BITMAP(Pjlb, ++subexp)) // find non-empty subexp.
1713 + {
1714 + if (subexp >= cJU_NUMSUBEXPL - 1) // didnt find one.
1715 + {
1716 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1717 + JUDY1CODE(return(JERRI );)
1718 + JUDYLCODE(return(PPJERR);)
1719 + }
1720 + }
1721 +
1722 + offset = 0;
1723 +#endif
1724 +
1725 + JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
1726 + JU_SETDIGIT1(*PIndex, digit);
1727 + JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
1728 +// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + (offset)));
1729 +
1730 + } // case cJU_JPLEAF_B1
1731 +
1732 +#ifdef JUDY1
1733 +// ----------------------------------------------------------------------------
1734 +// FULL POPULATION:
1735 +//
1736 +// Copy Dcd bytes to *PIndex (always present since state 1 < cJU_ROOTSTATE),
1737 +// then set the highest/lowest possible digit as the LSB in *PIndex.
1738 +
1739 + case cJ1_JPFULLPOPU1:
1740 +
1741 + JU_SETDCD( *PIndex, Pjp, 1);
1742 +#ifdef JUDYPREV
1743 + JU_SETDIGIT1(*PIndex, cJU_BITSPERBITMAP - 1);
1744 +#else
1745 + JU_SETDIGIT1(*PIndex, 0);
1746 +#endif
1747 + JU_RET_FOUND_FULLPOPU1;
1748 +#endif // JUDY1
1749 +
1750 +
1751 +// ----------------------------------------------------------------------------
1752 +// IMMEDIATE:
1753 +//
1754 +// Simply use the highest/lowest (right/left-most) Index in the Imm, but the
1755 +// details vary depending on leaf Index Size and pop1. Note: There are no Dcd
1756 +// bytes in an Immediate JP, but in a cJU_JPIMMED_*_01 JP, the field holds the
1757 +// least bytes of the immediate Index.
1758 +
1759 + case cJU_JPIMMED_1_01: SET_01(1); goto SM3Imm_01;
1760 + case cJU_JPIMMED_2_01: SET_01(2); goto SM3Imm_01;
1761 + case cJU_JPIMMED_3_01: SET_01(3); goto SM3Imm_01;
1762 +#ifdef JU_64BIT
1763 + case cJU_JPIMMED_4_01: SET_01(4); goto SM3Imm_01;
1764 + case cJU_JPIMMED_5_01: SET_01(5); goto SM3Imm_01;
1765 + case cJU_JPIMMED_6_01: SET_01(6); goto SM3Imm_01;
1766 + case cJU_JPIMMED_7_01: SET_01(7); goto SM3Imm_01;
1767 +#endif
1768 +SM3Imm_01: JU_RET_FOUND_IMM_01(Pjp);
1769 +
1770 +#ifdef JUDYPREV
1771 +#define SM3IMM_OFFSET(cPop1) (cPop1) - 1 // highest.
1772 +#else
1773 +#define SM3IMM_OFFSET(cPop1) 0 // lowest.
1774 +#endif
1775 +
1776 +#define SM3IMM(cPop1,Next) \
1777 + offset = SM3IMM_OFFSET(cPop1); \
1778 + goto Next
1779 +
1780 + case cJU_JPIMMED_1_02: SM3IMM( 2, SM3Imm1);
1781 + case cJU_JPIMMED_1_03: SM3IMM( 3, SM3Imm1);
1782 +#if (defined(JUDY1) || defined(JU_64BIT))
1783 + case cJU_JPIMMED_1_04: SM3IMM( 4, SM3Imm1);
1784 + case cJU_JPIMMED_1_05: SM3IMM( 5, SM3Imm1);
1785 + case cJU_JPIMMED_1_06: SM3IMM( 6, SM3Imm1);
1786 + case cJU_JPIMMED_1_07: SM3IMM( 7, SM3Imm1);
1787 +#endif
1788 +#if (defined(JUDY1) && defined(JU_64BIT))
1789 + case cJ1_JPIMMED_1_08: SM3IMM( 8, SM3Imm1);
1790 + case cJ1_JPIMMED_1_09: SM3IMM( 9, SM3Imm1);
1791 + case cJ1_JPIMMED_1_10: SM3IMM(10, SM3Imm1);
1792 + case cJ1_JPIMMED_1_11: SM3IMM(11, SM3Imm1);
1793 + case cJ1_JPIMMED_1_12: SM3IMM(12, SM3Imm1);
1794 + case cJ1_JPIMMED_1_13: SM3IMM(13, SM3Imm1);
1795 + case cJ1_JPIMMED_1_14: SM3IMM(14, SM3Imm1);
1796 + case cJ1_JPIMMED_1_15: SM3IMM(15, SM3Imm1);
1797 +#endif
1798 +
1799 +SM3Imm1: JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
1800 + JU_RET_FOUND_IMM(Pjp, offset);
1801 +
1802 +#if (defined(JUDY1) || defined(JU_64BIT))
1803 + case cJU_JPIMMED_2_02: SM3IMM(2, SM3Imm2);
1804 + case cJU_JPIMMED_2_03: SM3IMM(3, SM3Imm2);
1805 +#endif
1806 +#if (defined(JUDY1) && defined(JU_64BIT))
1807 + case cJ1_JPIMMED_2_04: SM3IMM(4, SM3Imm2);
1808 + case cJ1_JPIMMED_2_05: SM3IMM(5, SM3Imm2);
1809 + case cJ1_JPIMMED_2_06: SM3IMM(6, SM3Imm2);
1810 + case cJ1_JPIMMED_2_07: SM3IMM(7, SM3Imm2);
1811 +#endif
1812 +
1813 +#if (defined(JUDY1) || defined(JU_64BIT))
1814 +SM3Imm2: *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
1815 + | ((uint16_t *) PJI)[offset];
1816 + JU_RET_FOUND_IMM(Pjp, offset);
1817 +#endif
1818 +
1819 +#if (defined(JUDY1) || defined(JU_64BIT))
1820 + case cJU_JPIMMED_3_02: SM3IMM(2, SM3Imm3);
1821 +#endif
1822 +#if (defined(JUDY1) && defined(JU_64BIT))
1823 + case cJ1_JPIMMED_3_03: SM3IMM(3, SM3Imm3);
1824 + case cJ1_JPIMMED_3_04: SM3IMM(4, SM3Imm3);
1825 + case cJ1_JPIMMED_3_05: SM3IMM(5, SM3Imm3);
1826 +#endif
1827 +
1828 +#if (defined(JUDY1) || defined(JU_64BIT))
1829 +SM3Imm3:
1830 + {
1831 + Word_t lsb;
1832 + JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
1833 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
1834 + JU_RET_FOUND_IMM(Pjp, offset);
1835 + }
1836 +#endif
1837 +
1838 +#if (defined(JUDY1) && defined(JU_64BIT))
1839 + case cJ1_JPIMMED_4_02: SM3IMM(2, SM3Imm4);
1840 + case cJ1_JPIMMED_4_03: SM3IMM(3, SM3Imm4);
1841 +
1842 +SM3Imm4: *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
1843 + | ((uint32_t *) PJI)[offset];
1844 + JU_RET_FOUND_IMM(Pjp, offset);
1845 +
1846 + case cJ1_JPIMMED_5_02: SM3IMM(2, SM3Imm5);
1847 + case cJ1_JPIMMED_5_03: SM3IMM(3, SM3Imm5);
1848 +
1849 +SM3Imm5:
1850 + {
1851 + Word_t lsb;
1852 + JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
1853 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
1854 + JU_RET_FOUND_IMM(Pjp, offset);
1855 + }
1856 +
1857 + case cJ1_JPIMMED_6_02: SM3IMM(2, SM3Imm6);
1858 +
1859 +SM3Imm6:
1860 + {
1861 + Word_t lsb;
1862 + JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
1863 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
1864 + JU_RET_FOUND_IMM(Pjp, offset);
1865 + }
1866 +
1867 + case cJ1_JPIMMED_7_02: SM3IMM(2, SM3Imm7);
1868 +
1869 +SM3Imm7:
1870 + {
1871 + Word_t lsb;
1872 + JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
1873 + *PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
1874 + JU_RET_FOUND_IMM(Pjp, offset);
1875 + }
1876 +#endif // (JUDY1 && JU_64BIT)
1877 +
1878 +
1879 +// ----------------------------------------------------------------------------
1880 +// OTHER CASES:
1881 +
1882 + default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
1883 + JUDY1CODE(return(JERRI );)
1884 + JUDYLCODE(return(PPJERR);)
1885 +
1886 + } // SM3Findlimit switch.
1887 +
1888 + /*NOTREACHED*/
1889 +
1890 +} // Judy1Prev() / Judy1Next() / JudyLPrev() / JudyLNext()
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c new
+1390
@@ -0,0 +1,1390 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.32 $ $Source: /judy/src/JudyCommon/JudyPrevNextEmpty.c $
19 +//
20 +// Judy*PrevEmpty() and Judy*NextEmpty() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +//
23 +// Compile with -DJUDYNEXT for the Judy*NextEmpty() function; otherwise
24 +// defaults to Judy*PrevEmpty().
25 +//
26 +// Compile with -DTRACEJPSE to trace JP traversals.
27 +//
28 +// This file is separate from JudyPrevNext.c because it differs too greatly for
29 +// ifdefs. This might be a bit surprising, but there are two reasons:
30 +//
31 +// - First, down in the details, searching for an empty index (SearchEmpty) is
32 +// remarkably asymmetric with searching for a valid index (SearchValid),
33 +// mainly with respect to: No return of a value area for JudyL; partially-
34 +// full versus totally-full JPs; and handling of narrow pointers.
35 +//
36 +// - Second, we chose to implement SearchEmpty without a backtrack stack or
37 +// backtrack engine, partly as an experiment, and partly because we think
38 +// restarting from the top of the tree is less likely for SearchEmpty than
39 +// for SearchValid, because empty indexes are more likely than valid indexes.
40 +//
41 +// A word about naming: A prior version of this feature (see 4.13) was named
42 +// Judy*Free(), but there were concerns about that being read as a verb rather
43 +// than an adjective. After prolonged debate and based on user input, we
44 +// changed "Free" to "Empty".
45 +
46 +#if (! (defined(JUDY1) || defined(JUDYL)))
47 +#error: One of -DJUDY1 or -DJUDYL must be specified.
48 +#endif
49 +
50 +#ifndef JUDYNEXT
51 +#ifndef JUDYPREV
52 +#define JUDYPREV 1 // neither set => use default.
53 +#endif
54 +#endif
55 +
56 +#ifdef JUDY1
57 +#include "Judy1.h"
58 +#else
59 +#include "JudyL.h"
60 +#endif
61 +
62 +#include "JudyPrivate1L.h"
63 +
64 +#ifdef TRACEJPSE
65 +#include "JudyPrintJP.c"
66 +#endif
67 +
68 +
69 +// ****************************************************************************
70 +// J U D Y 1 P R E V E M P T Y
71 +// J U D Y 1 N E X T E M P T Y
72 +// J U D Y L P R E V E M P T Y
73 +// J U D Y L N E X T E M P T Y
74 +//
75 +// See the manual entry for the API.
76 +//
77 +// OVERVIEW OF Judy*PrevEmpty() / Judy*NextEmpty():
78 +//
79 +// See also for comparison the equivalent comments in JudyPrevNext.c.
80 +//
81 +// Take the callers *PIndex and subtract/add 1, but watch out for
82 +// underflow/overflow, which means "no previous/next empty index found." Use a
83 +// reentrant switch statement (state machine, see SMGetRestart and
84 +// SMGetContinue) to decode Index, starting with the JRP (PArray), through a
85 +// JPM and branches, if any, down to an immediate or a leaf. Look for Index in
86 +// that immediate or leaf, and if not found (invalid index), return success
87 +// (Index is empty).
88 +//
89 +// This search can result in a dead end where taking a different path is
90 +// required. There are four kinds of dead ends:
91 +//
92 +// BRANCH PRIMARY dead end: Encountering a fully-populated JP for the
93 +// appropriate digit in Index. Search sideways in the branch for the
94 +// previous/next absent/null/non-full JP, and if one is found, set Index to the
95 +// highest/lowest index possible in that JPs expanse. Then if the JP is an
96 +// absent or null JP, return success; otherwise for a non-full JP, traverse
97 +// through the partially populated JP.
98 +//
99 +// BRANCH SECONDARY dead end: Reaching the end of a branch during a sideways
100 +// search after a branch primary dead end. Set Index to the lowest/highest
101 +// index possible in the whole branchs expanse (one higher/lower than the
102 +// previous/next branchs expanse), then restart at the top of the tree, which
103 +// includes pre-decrementing/incrementing Index (again) and watching for
104 +// underflow/overflow (again).
105 +//
106 +// LEAF PRIMARY dead end: Finding a valid (non-empty) index in an immediate or
107 +// leaf matching Index. Search sideways in the immediate/leaf for the
108 +// previous/next empty index; if found, set *PIndex to match and return success.
109 +//
110 +// LEAF SECONDARY dead end: Reaching the end of an immediate or leaf during a
111 +// sideways search after a leaf primary dead end. Just as for a branch
112 +// secondary dead end, restart at the top of the tree with Index set to the
113 +// lowest/highest index possible in the whole immediate/leafs expanse.
114 +// TBD: If leaf secondary dead end occurs, could shortcut and treat it as a
115 +// branch primary dead end; but this would require remembering the parent
116 +// branchs type and offset (a "one-deep stack"), and also wrestling with
117 +// narrow pointers, at least for leaves (but not for immediates).
118 +//
119 +// Note some ASYMMETRIES between SearchValid and SearchEmpty:
120 +//
121 +// - The SearchValid code, upon descending through a narrow pointer, if Index
122 +// is outside the expanse of the subsidiary node (effectively a secondary
123 +// dead end), must decide whether to backtrack or findlimit. But the
124 +// SearchEmpty code simply returns success (Index is empty).
125 +//
126 +// - Similarly, the SearchValid code, upon finding no previous/next index in
127 +// the expanse of a narrow pointer (again, a secondary dead end), can simply
128 +// start to backtrack at the parent JP. But the SearchEmpty code would have
129 +// to first determine whether or not the parent JPs narrow expanse contains
130 +// a previous/next empty index outside the subexpanse. Rather than keeping a
131 +// parent state stack and backtracking this way, upon a secondary dead end,
132 +// the SearchEmpty code simply restarts at the top of the tree, whether or
133 +// not a narrow pointer is involved. Again, see the equivalent comments in
134 +// JudyPrevNext.c for comparison.
135 +//
136 +// This function is written iteratively for speed, rather than recursively.
137 +//
138 +// TBD: Wed like to enhance this function to make successive searches faster.
139 +// This would require saving some previous state, including the previous Index
140 +// returned, and in which leaf it was found. If the next call is for the same
141 +// Index and the array has not been modified, start at the same leaf. This
142 +// should be much easier to implement since this is iterative rather than
143 +// recursive code.
144 +
145 +#ifdef JUDY1
146 +#ifdef JUDYPREV
147 +FUNCTION int Judy1PrevEmpty
148 +#else
149 +FUNCTION int Judy1NextEmpty
150 +#endif
151 +#else
152 +#ifdef JUDYPREV
153 +FUNCTION int JudyLPrevEmpty
154 +#else
155 +FUNCTION int JudyLNextEmpty
156 +#endif
157 +#endif
158 + (
159 + Pcvoid_t PArray, // Judy array to search.
160 + Word_t * PIndex, // starting point and result.
161 + PJError_t PJError // optional, for returning error info.
162 + )
163 +{
164 + Word_t Index; // fast copy, in a register.
165 + Pjp_t Pjp; // current JP.
166 + Pjbl_t Pjbl; // Pjp->jp_Addr masked and cast to types:
167 + Pjbb_t Pjbb;
168 + Pjbu_t Pjbu;
169 + Pjlb_t Pjlb;
170 + PWord_t Pword; // alternate name for use by GET* macros.
171 +
172 + Word_t digit; // next digit to decode from Index.
173 + Word_t digits; // current state in SM = digits left to decode.
174 + Word_t pop0; // in a leaf.
175 + Word_t pop0mask; // precalculated to avoid variable shifts.
176 + long offset; // within a branch or leaf (can be large).
177 + int subexp; // subexpanse in a bitmap branch.
178 + BITMAPB_t bitposmaskB; // bit in bitmap for bitmap branch.
179 + BITMAPL_t bitposmaskL; // bit in bitmap for bitmap leaf.
180 + Word_t possfullJP1; // JP types for possibly full subexpanses:
181 + Word_t possfullJP2;
182 + Word_t possfullJP3;
183 +
184 +
185 +// ----------------------------------------------------------------------------
186 +// M A C R O S
187 +//
188 +// These are intended to make the code a bit more readable and less redundant.
189 +
190 +
191 +// CHECK FOR NULL JP:
192 +//
193 +// TBD: In principle this can be reduced (here and in other *.c files) to just
194 +// the latter clause since no Type should ever be below cJU_JPNULL1, but in
195 +// fact some root pointer types can be lower, so for safety do both checks.
196 +
197 +#define JPNULL(Type) (((Type) >= cJU_JPNULL1) && ((Type) <= cJU_JPNULLMAX))
198 +
199 +
200 +// CHECK FOR A FULL JP:
201 +//
202 +// Given a JP, indicate if it is fully populated. Use digits, pop0mask, and
203 +// possfullJP1..3 in the context.
204 +//
205 +// This is a difficult problem because it requires checking the Pop0 bits for
206 +// all-ones, but the number of bytes depends on the JP type, which is not
207 +// directly related to the parent branchs type or level -- the JPs child
208 +// could be under a narrow pointer (hence not full). The simple answer
209 +// requires switching on or otherwise calculating the JP type, which could be
210 +// slow. Instead, in SMPREPB* precalculate pop0mask and also record in
211 +// possfullJP1..3 the child JP (branch) types that could possibly be full (one
212 +// level down), and use them here. For level-2 branches (with digits == 2),
213 +// the test for a full child depends on Judy1/JudyL.
214 +//
215 +// Note: This cannot be applied to the JP in a JPM because it doesnt have
216 +// enough pop0 digits.
217 +//
218 +// TBD: JPFULL_BRANCH diligently checks for BranchL or BranchB, where neither
219 +// of those can ever be full as it turns out. Could just check for a BranchU
220 +// at the right level. Also, pop0mask might be overkill, its not used much,
221 +// so perhaps just call cJU_POP0MASK(digits - 1) here?
222 +//
223 +// First, JPFULL_BRANCH checks for a full expanse for a JP whose child can be a
224 +// branch, that is, a JP in a branch at level 3 or higher:
225 +
226 +#define JPFULL_BRANCH(Pjp) \
227 + ((((JU_JPDCDPOP0(Pjp) ^ cJU_ALLONES) & pop0mask) == 0) \
228 + && ((JU_JPTYPE(Pjp) == possfullJP1) \
229 + || (JU_JPTYPE(Pjp) == possfullJP2) \
230 + || (JU_JPTYPE(Pjp) == possfullJP3)))
231 +
232 +#ifdef JUDY1
233 +#define JPFULL(Pjp) \
234 + ((digits == 2) ? \
235 + (JU_JPTYPE(Pjp) == cJ1_JPFULLPOPU1) : JPFULL_BRANCH(Pjp))
236 +#else
237 +#define JPFULL(Pjp) \
238 + ((digits == 2) ? \
239 + (JU_JPTYPE(Pjp) == cJU_JPLEAF_B1) \
240 + && (((JU_JPDCDPOP0(Pjp) & cJU_POP0MASK(1)) == cJU_POP0MASK(1))) : \
241 + JPFULL_BRANCH(Pjp))
242 +#endif
243 +
244 +
245 +// RETURN SUCCESS:
246 +//
247 +// This hides the need to set *PIndex back to the local value of Index -- use a
248 +// local value for faster operation. Note that the callers *PIndex is ALWAYS
249 +// modified upon success, at least decremented/incremented.
250 +
251 +#define RET_SUCCESS { *PIndex = Index; return(1); }
252 +
253 +
254 +// RETURN A CORRUPTION:
255 +
256 +#define RET_CORRUPT { JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); return(JERRI); }
257 +
258 +
259 +// SEARCH A BITMAP BRANCH:
260 +//
261 +// This is a weak analog of j__udySearchLeaf*() for bitmap branches. Return
262 +// the actual or next-left position, base 0, of Digit in a BITMAPB_t bitmap
263 +// (subexpanse of a full bitmap), also given a Bitposmask for Digit. The
264 +// position is the offset within the set bits.
265 +//
266 +// Unlike j__udySearchLeaf*(), the offset is not returned bit-complemented if
267 +// Digits bit is unset, because the caller can check the bitmap themselves to
268 +// determine that. Also, if Digits bit is unset, the returned offset is to
269 +// the next-left JP or index (including -1), not to the "ideal" position for
270 +// the index = next-right JP or index.
271 +//
272 +// Shortcut and skip calling j__udyCountBitsB() if the bitmap is full, in which
273 +// case (Digit % cJU_BITSPERSUBEXPB) itself is the base-0 offset.
274 +
275 +#define SEARCHBITMAPB(Bitmap,Digit,Bitposmask) \
276 + (((Bitmap) == cJU_FULLBITMAPB) ? (Digit % cJU_BITSPERSUBEXPB) : \
277 + j__udyCountBitsB((Bitmap) & JU_MASKLOWERINC(Bitposmask)) - 1)
278 +
279 +#ifdef JUDYPREV
280 +// Equivalent to search for the highest offset in Bitmap, that is, one less
281 +// than the number of bits set:
282 +
283 +#define SEARCHBITMAPMAXB(Bitmap) \
284 + (((Bitmap) == cJU_FULLBITMAPB) ? cJU_BITSPERSUBEXPB - 1 : \
285 + j__udyCountBitsB(Bitmap) - 1)
286 +#endif
287 +
288 +
289 +// CHECK DECODE BYTES:
290 +//
291 +// Check Decode bytes in a JP against the equivalent portion of Index. If they
292 +// dont match, Index is outside the subexpanse of a narrow pointer, hence is
293 +// empty.
294 +
295 +#define CHECKDCD(cDigits) \
296 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, cDigits)) RET_SUCCESS
297 +
298 +
299 +// REVISE REMAINDER OF INDEX:
300 +//
301 +// Put one digit in place in Index and clear/set the lower digits, if any, so
302 +// the resulting Index is at the start/end of an expanse, or just clear/set the
303 +// least digits.
304 +//
305 +// Actually, to make simple use of JU_LEASTBYTESMASK, first clear/set all least
306 +// digits of Index including the digit to be overridden, then set the value of
307 +// that one digit. If Digits == 1 the first operation is redundant, but either
308 +// very fast or even removed by the optimizer.
309 +
310 +#define CLEARLEASTDIGITS(Digits) Index &= ~JU_LEASTBYTESMASK(Digits)
311 +#define SETLEASTDIGITS( Digits) Index |= JU_LEASTBYTESMASK(Digits)
312 +
313 +#define CLEARLEASTDIGITS_D(Digit,Digits) \
314 + { \
315 + CLEARLEASTDIGITS(Digits); \
316 + JU_SETDIGIT(Index, Digit, Digits); \
317 + }
318 +
319 +#define SETLEASTDIGITS_D(Digit,Digits) \
320 + { \
321 + SETLEASTDIGITS(Digits); \
322 + JU_SETDIGIT(Index, Digit, Digits); \
323 + }
324 +
325 +
326 +// SET REMAINDER OF INDEX AND THEN RETURN OR CONTINUE:
327 +
328 +#define SET_AND_RETURN(OpLeastDigits,Digit,Digits) \
329 + { \
330 + OpLeastDigits(Digit, Digits); \
331 + RET_SUCCESS; \
332 + }
333 +
334 +#define SET_AND_CONTINUE(OpLeastDigits,Digit,Digits) \
335 + { \
336 + OpLeastDigits(Digit, Digits); \
337 + goto SMGetContinue; \
338 + }
339 +
340 +
341 +// PREPARE TO HANDLE A LEAFW OR JP BRANCH IN THE STATE MACHINE:
342 +//
343 +// Extract a state-dependent digit from Index in a "constant" way, then jump to
344 +// common code for multiple cases.
345 +//
346 +// TBD: Should this macro do more, such as preparing variable-shift masks for
347 +// use in CLEARLEASTDIGITS and SETLEASTDIGITS?
348 +
349 +#define SMPREPB(cDigits,Next,PossFullJP1,PossFullJP2,PossFullJP3) \
350 + digits = (cDigits); \
351 + digit = JU_DIGITATSTATE(Index, cDigits); \
352 + pop0mask = cJU_POP0MASK((cDigits) - 1); /* for branchs JPs */ \
353 + possfullJP1 = (PossFullJP1); \
354 + possfullJP2 = (PossFullJP2); \
355 + possfullJP3 = (PossFullJP3); \
356 + goto Next
357 +
358 +// Variations for specific-level branches and for shorthands:
359 +//
360 +// Note: SMPREPB2 need not initialize possfullJP* because JPFULL does not use
361 +// them for digits == 2, but gcc -Wall isnt quite smart enough to see this, so
362 +// waste a bit of time and space to get rid of the warning:
363 +
364 +#define SMPREPB2(Next) \
365 + digits = 2; \
366 + digit = JU_DIGITATSTATE(Index, 2); \
367 + pop0mask = cJU_POP0MASK(1); /* for branchs JPs */ \
368 + possfullJP1 = possfullJP2 = possfullJP3 = 0; \
369 + goto Next
370 +
371 +#define SMPREPB3(Next) SMPREPB(3, Next, cJU_JPBRANCH_L2, \
372 + cJU_JPBRANCH_B2, \
373 + cJU_JPBRANCH_U2)
374 +#ifndef JU_64BIT
375 +#define SMPREPBL(Next) SMPREPB(cJU_ROOTSTATE, Next, cJU_JPBRANCH_L3, \
376 + cJU_JPBRANCH_B3, \
377 + cJU_JPBRANCH_U3)
378 +#else
379 +#define SMPREPB4(Next) SMPREPB(4, Next, cJU_JPBRANCH_L3, \
380 + cJU_JPBRANCH_B3, \
381 + cJU_JPBRANCH_U3)
382 +#define SMPREPB5(Next) SMPREPB(5, Next, cJU_JPBRANCH_L4, \
383 + cJU_JPBRANCH_B4, \
384 + cJU_JPBRANCH_U4)
385 +#define SMPREPB6(Next) SMPREPB(6, Next, cJU_JPBRANCH_L5, \
386 + cJU_JPBRANCH_B5, \
387 + cJU_JPBRANCH_U5)
388 +#define SMPREPB7(Next) SMPREPB(7, Next, cJU_JPBRANCH_L6, \
389 + cJU_JPBRANCH_B6, \
390 + cJU_JPBRANCH_U6)
391 +#define SMPREPBL(Next) SMPREPB(cJU_ROOTSTATE, Next, cJU_JPBRANCH_L7, \
392 + cJU_JPBRANCH_B7, \
393 + cJU_JPBRANCH_U7)
394 +#endif
395 +
396 +
397 +// RESTART AFTER SECONDARY DEAD END:
398 +//
399 +// Set Index to the first/last index in the branch or leaf subexpanse and start
400 +// over at the top of the tree.
401 +
402 +#ifdef JUDYPREV
403 +#define SMRESTART(Digits) { CLEARLEASTDIGITS(Digits); goto SMGetRestart; }
404 +#else
405 +#define SMRESTART(Digits) { SETLEASTDIGITS( Digits); goto SMGetRestart; }
406 +#endif
407 +
408 +
409 +// CHECK EDGE OF LEAFS EXPANSE:
410 +//
411 +// Given the LSBs of the lowest/highest valid index in a leaf (or equivalently
412 +// in an immediate JP), the level (index size) of the leaf, and the full index
413 +// to return (as Index in the context) already set to the full index matching
414 +// the lowest/highest one, determine if there is an empty index in the leafs
415 +// expanse below/above the lowest/highest index, which is true if the
416 +// lowest/highest index is not at the "edge" of the leafs expanse based on its
417 +// LSBs. If so, return Index decremented/incremented; otherwise restart at the
418 +// top of the tree.
419 +//
420 +// Note: In many cases Index is already at the right spot and calling
421 +// SMRESTART instead of just going directly to SMGetRestart is a bit of
422 +// overkill.
423 +//
424 +// Note: Variable shift occurs if Digits is not a constant.
425 +
426 +#ifdef JUDYPREV
427 +#define LEAF_EDGE(MinIndex,Digits) \
428 + { \
429 + if (MinIndex) { --Index; RET_SUCCESS; } \
430 + SMRESTART(Digits); \
431 + }
432 +#else
433 +#define LEAF_EDGE(MaxIndex,Digits) \
434 + { \
435 + if ((MaxIndex) != JU_LEASTBYTES(cJU_ALLONES, Digits)) \
436 + { ++Index; RET_SUCCESS; } \
437 + SMRESTART(Digits); \
438 + }
439 +#endif
440 +
441 +// Same as above except Index is not already set to match the lowest/highest
442 +// index, so do that before decrementing/incrementing it:
443 +
444 +#ifdef JUDYPREV
445 +#define LEAF_EDGE_SET(MinIndex,Digits) \
446 + { \
447 + if (MinIndex) \
448 + { JU_SETDIGITS(Index, MinIndex, Digits); --Index; RET_SUCCESS; } \
449 + SMRESTART(Digits); \
450 + }
451 +#else
452 +#define LEAF_EDGE_SET(MaxIndex,Digits) \
453 + { \
454 + if ((MaxIndex) != JU_LEASTBYTES(cJU_ALLONES, Digits)) \
455 + { JU_SETDIGITS(Index, MaxIndex, Digits); ++Index; RET_SUCCESS; } \
456 + SMRESTART(Digits); \
457 + }
458 +#endif
459 +
460 +
461 +// FIND A HOLE (EMPTY INDEX) IN AN IMMEDIATE OR LEAF:
462 +//
463 +// Given an index location in a leaf (or equivalently an immediate JP) known to
464 +// contain a usable hole (an empty index less/greater than Index), and the LSBs
465 +// of a minimum/maximum index to locate, find the previous/next empty index and
466 +// return it.
467 +//
468 +// Note: "Even" index sizes (1,2,4[,8] bytes) have corresponding native C
469 +// types; "odd" index sizes dont, but they are not represented here because
470 +// they are handled completely differently; see elsewhere.
471 +
472 +#ifdef JUDYPREV
473 +
474 +#define LEAF_HOLE_EVEN(cDigits,Pjll,IndexLSB) \
475 + { \
476 + while (*(Pjll) > (IndexLSB)) --(Pjll); /* too high */ \
477 + if (*(Pjll) < (IndexLSB)) RET_SUCCESS /* Index is empty */ \
478 + while (*(--(Pjll)) == --(IndexLSB)) /* null, find a hole */;\
479 + JU_SETDIGITS(Index, IndexLSB, cDigits); \
480 + RET_SUCCESS; \
481 + }
482 +#else
483 +#define LEAF_HOLE_EVEN(cDigits,Pjll,IndexLSB) \
484 + { \
485 + while (*(Pjll) < (IndexLSB)) ++(Pjll); /* too low */ \
486 + if (*(Pjll) > (IndexLSB)) RET_SUCCESS /* Index is empty */ \
487 + while (*(++(Pjll)) == ++(IndexLSB)) /* null, find a hole */;\
488 + JU_SETDIGITS(Index, IndexLSB, cDigits); \
489 + RET_SUCCESS; \
490 + }
491 +#endif
492 +
493 +
494 +// SEARCH FOR AN EMPTY INDEX IN AN IMMEDIATE OR LEAF:
495 +//
496 +// Given a pointer to the first index in a leaf (or equivalently an immediate
497 +// JP), the population of the leaf, and a first empty Index to find (inclusive,
498 +// as Index in the context), where Index is known to fall within the expanse of
499 +// the leaf to search, efficiently find the previous/next empty index in the
500 +// leaf, if any. For simplicity the following overview is stated in terms of
501 +// Judy*NextEmpty() only, but the same concepts apply symmetrically for
502 +// Judy*PrevEmpty(). Also, in each case the comparisons are for the LSBs of
503 +// Index and leaf indexes, according to the leafs level.
504 +//
505 +// 1. If Index is GREATER than the last (highest) index in the leaf
506 +// (maxindex), return success, Index is empty. (Remember, Index is known
507 +// to be in the leafs expanse.)
508 +//
509 +// 2. If Index is EQUAL to maxindex: If maxindex is not at the edge of the
510 +// leafs expanse, increment Index and return success, there is an empty
511 +// Index one higher than any in the leaf; otherwise restart with Index
512 +// reset to the upper edge of the leafs expanse. Note: This might cause
513 +// an extra cache line fill, but this is OK for repeatedly-called search
514 +// code, and it saves CPU time.
515 +//
516 +// 3. If Index is LESS than maxindex, check for "dense to end of leaf":
517 +// Subtract Index from maxindex, and back up that many slots in the leaf.
518 +// If the resulting offset is not before the start of the leaf then compare
519 +// the index at this offset (baseindex) with Index:
520 +//
521 +// 3a. If GREATER, the leaf must be corrupt, since indexes are sorted and
522 +// there are no duplicates.
523 +//
524 +// 3b. If EQUAL, the leaf is "dense" from Index to maxindex, meaning there is
525 +// no reason to search it. "Slide right" to the high end of the leaf
526 +// (modify Index to maxindex) and continue with step 2 above.
527 +//
528 +// 3c. If LESS, continue with step 4.
529 +//
530 +// 4. If the offset based on maxindex minus Index falls BEFORE the start of
531 +// the leaf, or if, per 3c above, baseindex is LESS than Index, the leaf is
532 +// guaranteed "not dense to the end" and a usable empty Index must exist.
533 +// This supports a more efficient search loop. Start at the FIRST index in
534 +// the leaf, or one BEYOND baseindex, respectively, and search the leaf as
535 +// follows, comparing each current index (currindex) with Index:
536 +//
537 +// 4a. If LESS, keep going to next index. Note: This is certain to terminate
538 +// because maxindex is known to be greater than Index, hence the loop can
539 +// be small and fast.
540 +//
541 +// 4b. If EQUAL, loop and increment Index until finding currindex greater than
542 +// Index, and return success with the modified Index.
543 +//
544 +// 4c. If GREATER, return success, Index (unmodified) is empty.
545 +//
546 +// Note: These are macros rather than functions for speed.
547 +
548 +#ifdef JUDYPREV
549 +
550 +#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
551 + { \
552 + LeafType * PjllLSB = (LeafType *) (Addr); \
553 + LeafType IndexLSB = Index; /* auto-masking */ \
554 + \
555 + /* Index before or at start of leaf: */ \
556 + \
557 + if (*PjllLSB >= IndexLSB) /* no need to search */ \
558 + { \
559 + if (*PjllLSB > IndexLSB) RET_SUCCESS; /* Index empty */ \
560 + LEAF_EDGE(*PjllLSB, cDigits); \
561 + } \
562 + \
563 + /* Index in or after leaf: */ \
564 + \
565 + offset = IndexLSB - *PjllLSB; /* tentative offset */ \
566 + if (offset <= (Pop0)) /* can check density */ \
567 + { \
568 + PjllLSB += offset; /* move to slot */ \
569 + \
570 + if (*PjllLSB <= IndexLSB) /* dense or corrupt */ \
571 + { \
572 + if (*PjllLSB == IndexLSB) /* dense, check edge */ \
573 + LEAF_EDGE_SET(PjllLSB[-offset], cDigits); \
574 + RET_CORRUPT; \
575 + } \
576 + --PjllLSB; /* not dense, start at previous */ \
577 + } \
578 + else PjllLSB = ((LeafType *) (Addr)) + (Pop0); /* start at max */ \
579 + \
580 + LEAF_HOLE_EVEN(cDigits, PjllLSB, IndexLSB); \
581 + }
582 +
583 +// JSLE_ODD is completely different from JSLE_EVEN because its important to
584 +// minimize copying odd indexes to compare them (see 4.14). Furthermore, a
585 +// very complex version (4.17, but abandoned before fully debugged) that
586 +// avoided calling j__udySearchLeaf*() ran twice as fast as 4.14, but still
587 +// half as fast as SearchValid. Doug suggested that to minimize complexity and
588 +// share common code we should use j__udySearchLeaf*() for the initial search
589 +// to establish if Index is empty, which should be common. If Index is valid
590 +// in a leaf or immediate indexes, odds are good that an empty Index is nearby,
591 +// so for simplicity just use a *COPY* function to linearly search the
592 +// remainder.
593 +//
594 +// TBD: Pathological case? Average performance should be good, but worst-case
595 +// might suffer. When Search says the initial Index is valid, so a linear
596 +// copy-and-compare is begun, if the caller builds fairly large leaves with
597 +// dense clusters AND frequently does a SearchEmpty at one end of such a
598 +// cluster, performance wont be very good. Might a dense-check help? This
599 +// means checking offset against the index at offset, and then against the
600 +// first/last index in the leaf. We doubt the pathological case will appear
601 +// much in real applications because they will probably alternate SearchValid
602 +// and SearchEmpty calls.
603 +
604 +#define JSLE_ODD(cDigits,Pjll,Pop0,Search,Copy) \
605 + { \
606 + Word_t IndexLSB; /* least bytes only */ \
607 + Word_t IndexFound; /* in leaf */ \
608 + \
609 + if ((offset = Search(Pjll, (Pop0) + 1, Index)) < 0) \
610 + RET_SUCCESS; /* Index is empty */ \
611 + \
612 + IndexLSB = JU_LEASTBYTES(Index, cDigits); \
613 + offset *= (cDigits); \
614 + \
615 + while ((offset -= (cDigits)) >= 0) \
616 + { /* skip until empty or start */ \
617 + Copy(IndexFound, ((uint8_t *) (Pjll)) + offset); \
618 + if (IndexFound != (--IndexLSB)) /* found an empty */ \
619 + { JU_SETDIGITS(Index, IndexLSB, cDigits); RET_SUCCESS; }\
620 + } \
621 + LEAF_EDGE_SET(IndexLSB, cDigits); \
622 + }
623 +
624 +#else // JUDYNEXT
625 +
626 +#define JSLE_EVEN(Addr,Pop0,cDigits,LeafType) \
627 + { \
628 + LeafType * PjllLSB = ((LeafType *) (Addr)) + (Pop0); \
629 + LeafType IndexLSB = Index; /* auto-masking */ \
630 + \
631 + /* Index at or after end of leaf: */ \
632 + \
633 + if (*PjllLSB <= IndexLSB) /* no need to search */ \
634 + { \
635 + if (*PjllLSB < IndexLSB) RET_SUCCESS; /* Index empty */\
636 + LEAF_EDGE(*PjllLSB, cDigits); \
637 + } \
638 + \
639 + /* Index before or in leaf: */ \
640 + \
641 + offset = *PjllLSB - IndexLSB; /* tentative offset */ \
642 + if (offset <= (Pop0)) /* can check density */ \
643 + { \
644 + PjllLSB -= offset; /* move to slot */ \
645 + \
646 + if (*PjllLSB >= IndexLSB) /* dense or corrupt */ \
647 + { \
648 + if (*PjllLSB == IndexLSB) /* dense, check edge */ \
649 + LEAF_EDGE_SET(PjllLSB[offset], cDigits); \
650 + RET_CORRUPT; \
651 + } \
652 + ++PjllLSB; /* not dense, start at next */ \
653 + } \
654 + else PjllLSB = (LeafType *) (Addr); /* start at minimum */ \
655 + \
656 + LEAF_HOLE_EVEN(cDigits, PjllLSB, IndexLSB); \
657 + }
658 +
659 +#define JSLE_ODD(cDigits,Pjll,Pop0,Search,Copy) \
660 + { \
661 + Word_t IndexLSB; /* least bytes only */ \
662 + Word_t IndexFound; /* in leaf */ \
663 + int offsetmax; /* in bytes */ \
664 + \
665 + if ((offset = Search(Pjll, (Pop0) + 1, Index)) < 0) \
666 + RET_SUCCESS; /* Index is empty */ \
667 + \
668 + IndexLSB = JU_LEASTBYTES(Index, cDigits); \
669 + offset *= (cDigits); \
670 + offsetmax = (Pop0) * (cDigits); /* single multiply */ \
671 + \
672 + while ((offset += (cDigits)) <= offsetmax) \
673 + { /* skip until empty or end */ \
674 + Copy(IndexFound, ((uint8_t *) (Pjll)) + offset); \
675 + if (IndexFound != (++IndexLSB)) /* found an empty */ \
676 + { JU_SETDIGITS(Index, IndexLSB, cDigits); RET_SUCCESS; } \
677 + } \
678 + LEAF_EDGE_SET(IndexLSB, cDigits); \
679 + }
680 +
681 +#endif // JUDYNEXT
682 +
683 +// Note: Immediate indexes never fill a single index group, so for odd index
684 +// sizes, save time by calling JSLE_ODD_IMM instead of JSLE_ODD.
685 +
686 +#define j__udySearchLeafEmpty1(Addr,Pop0) \
687 + JSLE_EVEN(Addr, Pop0, 1, uint8_t)
688 +
689 +#define j__udySearchLeafEmpty2(Addr,Pop0) \
690 + JSLE_EVEN(Addr, Pop0, 2, uint16_t)
691 +
692 +#define j__udySearchLeafEmpty3(Addr,Pop0) \
693 + JSLE_ODD(3, Addr, Pop0, j__udySearchLeaf3, JU_COPY3_PINDEX_TO_LONG)
694 +
695 +#ifndef JU_64BIT
696 +
697 +#define j__udySearchLeafEmptyL(Addr,Pop0) \
698 + JSLE_EVEN(Addr, Pop0, 4, Word_t)
699 +
700 +#else
701 +
702 +#define j__udySearchLeafEmpty4(Addr,Pop0) \
703 + JSLE_EVEN(Addr, Pop0, 4, uint32_t)
704 +
705 +#define j__udySearchLeafEmpty5(Addr,Pop0) \
706 + JSLE_ODD(5, Addr, Pop0, j__udySearchLeaf5, JU_COPY5_PINDEX_TO_LONG)
707 +
708 +#define j__udySearchLeafEmpty6(Addr,Pop0) \
709 + JSLE_ODD(6, Addr, Pop0, j__udySearchLeaf6, JU_COPY6_PINDEX_TO_LONG)
710 +
711 +#define j__udySearchLeafEmpty7(Addr,Pop0) \
712 + JSLE_ODD(7, Addr, Pop0, j__udySearchLeaf7, JU_COPY7_PINDEX_TO_LONG)
713 +
714 +#define j__udySearchLeafEmptyL(Addr,Pop0) \
715 + JSLE_EVEN(Addr, Pop0, 8, Word_t)
716 +
717 +#endif // JU_64BIT
718 +
719 +
720 +// ----------------------------------------------------------------------------
721 +// START OF CODE:
722 +//
723 +// CHECK FOR SHORTCUTS:
724 +//
725 +// Error out if PIndex is null.
726 +
727 + if (PIndex == (PWord_t) NULL)
728 + {
729 + JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
730 + return(JERRI);
731 + }
732 +
733 + Index = *PIndex; // fast local copy.
734 +
735 +// Set and pre-decrement/increment Index, watching for underflow/overflow:
736 +//
737 +// An out-of-bounds Index means failure: No previous/next empty index.
738 +
739 +SMGetRestart: // return here with revised Index.
740 +
741 +#ifdef JUDYPREV
742 + if (Index-- == 0) return(0);
743 +#else
744 + if (++Index == 0) return(0);
745 +#endif
746 +
747 +// An empty array with an in-bounds (not underflowed/overflowed) Index means
748 +// success:
749 +//
750 +// Note: This check is redundant after restarting at SMGetRestart, but should
751 +// take insignificant time.
752 +
753 + if (PArray == (Pvoid_t) NULL) RET_SUCCESS;
754 +
755 +// ----------------------------------------------------------------------------
756 +// ROOT-LEVEL LEAF that starts with a Pop0 word; just look within the leaf:
757 +//
758 +// If Index is not in the leaf, return success; otherwise return the first
759 +// empty Index, if any, below/above where it would belong.
760 +
761 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
762 + {
763 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
764 + pop0 = Pjlw[0];
765 +
766 +#ifdef JUDY1
767 + if (pop0 == 0) // special case.
768 + {
769 +#ifdef JUDYPREV
770 + if ((Index != Pjlw[1]) || (Index-- != 0)) RET_SUCCESS;
771 +#else
772 + if ((Index != Pjlw[1]) || (++Index != 0)) RET_SUCCESS;
773 +#endif
774 + return(0); // no previous/next empty index.
775 + }
776 +#endif // JUDY1
777 +
778 + j__udySearchLeafEmptyL(Pjlw + 1, pop0);
779 +
780 +// No return -- thanks ALAN
781 +
782 + }
783 + else
784 +
785 +// ----------------------------------------------------------------------------
786 +// HANDLE JRP Branch:
787 +//
788 +// For JRP branches, traverse the JPM; handle LEAFW
789 +// directly; but look for the most common cases first.
790 +
791 + {
792 + Pjpm_t Pjpm = P_JPM(PArray);
793 + Pjp = &(Pjpm->jpm_JP);
794 +
795 +// goto SMGetContinue;
796 + }
797 +
798 +
799 +// ============================================================================
800 +// STATE MACHINE -- GET INDEX:
801 +//
802 +// Search for Index (already decremented/incremented so as to be an inclusive
803 +// search). If not found (empty index), return success. Otherwise do a
804 +// previous/next search, and if successful modify Index to the empty index
805 +// found. See function header comments.
806 +//
807 +// ENTRY: Pjp points to next JP to interpret, whose Decode bytes have not yet
808 +// been checked.
809 +//
810 +// Note: Check Decode bytes at the start of each loop, not after looking up a
811 +// new JP, so its easy to do constant shifts/masks.
812 +//
813 +// EXIT: Return, or branch to SMGetRestart with modified Index, or branch to
814 +// SMGetContinue with a modified Pjp, as described elsewhere.
815 +//
816 +// WARNING: For run-time efficiency the following cases replicate code with
817 +// varying constants, rather than using common code with variable values!
818 +
819 +SMGetContinue: // return here for next branch/leaf.
820 +
821 +#ifdef TRACEJPSE
822 + JudyPrintJP(Pjp, "sf", __LINE__);
823 +#endif
824 +
825 + switch (JU_JPTYPE(Pjp))
826 + {
827 +
828 +
829 +// ----------------------------------------------------------------------------
830 +// LINEAR BRANCH:
831 +//
832 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
833 +// next digit in Index.
834 +
835 + case cJU_JPBRANCH_L2: CHECKDCD(2); SMPREPB2(SMBranchL);
836 + case cJU_JPBRANCH_L3: CHECKDCD(3); SMPREPB3(SMBranchL);
837 +#ifdef JU_64BIT
838 + case cJU_JPBRANCH_L4: CHECKDCD(4); SMPREPB4(SMBranchL);
839 + case cJU_JPBRANCH_L5: CHECKDCD(5); SMPREPB5(SMBranchL);
840 + case cJU_JPBRANCH_L6: CHECKDCD(6); SMPREPB6(SMBranchL);
841 + case cJU_JPBRANCH_L7: CHECKDCD(7); SMPREPB7(SMBranchL);
842 +#endif
843 + case cJU_JPBRANCH_L: SMPREPBL(SMBranchL);
844 +
845 +// Common code (state-independent) for all cases of linear branches:
846 +
847 +SMBranchL:
848 + Pjbl = P_JBL(Pjp->jp_Addr);
849 +
850 +// First, check if Indexs expanse (digit) is below/above the first/last
851 +// populated expanse in the BranchL, in which case Index is empty; otherwise
852 +// find the offset of the lowest/highest populated expanse at or above/below
853 +// digit, if any:
854 +//
855 +// Note: The for-loop is guaranteed to exit eventually because the first/last
856 +// expanse is known to be a terminator.
857 +//
858 +// Note: Cannot use j__udySearchLeaf*Empty1() here because it only applies to
859 +// leaves and does not know about partial versus full JPs, unlike the use of
860 +// j__udySearchLeaf1() for BranchLs in SearchValid code. Also, since linear
861 +// leaf expanse lists are small, dont waste time calling j__udySearchLeaf1(),
862 +// just scan the expanse list.
863 +
864 +#ifdef JUDYPREV
865 + if ((Pjbl->jbl_Expanse[0]) > digit) RET_SUCCESS;
866 +
867 + for (offset = (Pjbl->jbl_NumJPs) - 1; /* null */; --offset)
868 +#else
869 + if ((Pjbl->jbl_Expanse[(Pjbl->jbl_NumJPs) - 1]) < digit)
870 + RET_SUCCESS;
871 +
872 + for (offset = 0; /* null */; ++offset)
873 +#endif
874 + {
875 +
876 +// Too low/high, keep going; or too high/low, meaning the loop passed a hole
877 +// and the initial Index is empty:
878 +
879 +#ifdef JUDYPREV
880 + if ((Pjbl->jbl_Expanse[offset]) > digit) continue;
881 + if ((Pjbl->jbl_Expanse[offset]) < digit) RET_SUCCESS;
882 +#else
883 + if ((Pjbl->jbl_Expanse[offset]) < digit) continue;
884 + if ((Pjbl->jbl_Expanse[offset]) > digit) RET_SUCCESS;
885 +#endif
886 +
887 +// Found expanse matching digit; if its not full, traverse through it:
888 +
889 + if (! JPFULL((Pjbl->jbl_jp) + offset))
890 + {
891 + Pjp = (Pjbl->jbl_jp) + offset;
892 + goto SMGetContinue;
893 + }
894 +
895 +// Common code: While searching for a lower/higher hole or a non-full JP, upon
896 +// finding a lower/higher hole, adjust Index using the revised digit and
897 +// return; or upon finding a consecutive lower/higher expanse, if the expanses
898 +// JP is non-full, modify Index and traverse through the JP:
899 +
900 +#define BRANCHL_CHECK(OpIncDec,OpLeastDigits,Digit,Digits) \
901 + { \
902 + if ((Pjbl->jbl_Expanse[offset]) != OpIncDec digit) \
903 + SET_AND_RETURN(OpLeastDigits, Digit, Digits); \
904 + \
905 + if (! JPFULL((Pjbl->jbl_jp) + offset)) \
906 + { \
907 + Pjp = (Pjbl->jbl_jp) + offset; \
908 + SET_AND_CONTINUE(OpLeastDigits, Digit, Digits); \
909 + } \
910 + }
911 +
912 +// BranchL primary dead end: Expanse matching Index/digit is full (rare except
913 +// for dense/sequential indexes):
914 +//
915 +// Search for a lower/higher hole, a non-full JP, or the end of the expanse
916 +// list, while decrementing/incrementing digit.
917 +
918 +#ifdef JUDYPREV
919 + while (--offset >= 0)
920 + BRANCHL_CHECK(--, SETLEASTDIGITS_D, digit, digits)
921 +#else
922 + while (++offset < Pjbl->jbl_NumJPs)
923 + BRANCHL_CHECK(++, CLEARLEASTDIGITS_D, digit, digits)
924 +#endif
925 +
926 +// Passed end of BranchL expanse list after finding a matching but full
927 +// expanse:
928 +//
929 +// Digit now matches the lowest/highest expanse, which is a full expanse; if
930 +// digit is at the end of BranchLs expanse (no hole before/after), break out
931 +// of the loop; otherwise modify Index to the next lower/higher digit and
932 +// return success:
933 +
934 +#ifdef JUDYPREV
935 + if (digit == 0) break;
936 + --digit; SET_AND_RETURN(SETLEASTDIGITS_D, digit, digits);
937 +#else
938 + if (digit == JU_LEASTBYTES(cJU_ALLONES, 1)) break;
939 + ++digit; SET_AND_RETURN(CLEARLEASTDIGITS_D, digit, digits);
940 +#endif
941 + } // for-loop
942 +
943 +// BranchL secondary dead end, no non-full previous/next JP:
944 +
945 + SMRESTART(digits);
946 +
947 +
948 +// ----------------------------------------------------------------------------
949 +// BITMAP BRANCH:
950 +//
951 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
952 +// next digit in Index.
953 +
954 + case cJU_JPBRANCH_B2: CHECKDCD(2); SMPREPB2(SMBranchB);
955 + case cJU_JPBRANCH_B3: CHECKDCD(3); SMPREPB3(SMBranchB);
956 +#ifdef JU_64BIT
957 + case cJU_JPBRANCH_B4: CHECKDCD(4); SMPREPB4(SMBranchB);
958 + case cJU_JPBRANCH_B5: CHECKDCD(5); SMPREPB5(SMBranchB);
959 + case cJU_JPBRANCH_B6: CHECKDCD(6); SMPREPB6(SMBranchB);
960 + case cJU_JPBRANCH_B7: CHECKDCD(7); SMPREPB7(SMBranchB);
961 +#endif
962 + case cJU_JPBRANCH_B: SMPREPBL(SMBranchB);
963 +
964 +// Common code (state-independent) for all cases of bitmap branches:
965 +
966 +SMBranchB:
967 + Pjbb = P_JBB(Pjp->jp_Addr);
968 +
969 +// Locate the digits JP in the subexpanse list, if present:
970 +
971 + subexp = digit / cJU_BITSPERSUBEXPB;
972 + assert(subexp < cJU_NUMSUBEXPB); // falls in expected range.
973 + bitposmaskB = JU_BITPOSMASKB(digit);
974 +
975 +// Absent JP = no JP matches current digit in Index:
976 +
977 +// if (! JU_BITMAPTESTB(Pjbb, digit)) // slower.
978 + if (! (JU_JBB_BITMAP(Pjbb, subexp) & bitposmaskB)) // faster.
979 + RET_SUCCESS;
980 +
981 +// Non-full JP matches current digit in Index:
982 +//
983 +// Iterate to the subsidiary non-full JP.
984 +
985 + offset = SEARCHBITMAPB(JU_JBB_BITMAP(Pjbb, subexp), digit,
986 + bitposmaskB);
987 + // not negative since at least one bit is set:
988 + assert(offset >= 0);
989 + assert(offset < (int) cJU_BITSPERSUBEXPB);
990 +
991 +// Watch for null JP subarray pointer with non-null bitmap (a corruption):
992 +
993 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp)))
994 + == (Pjp_t) NULL) RET_CORRUPT;
995 +
996 + Pjp += offset;
997 + if (! JPFULL(Pjp)) goto SMGetContinue;
998 +
999 +// BranchB primary dead end:
1000 +//
1001 +// Upon hitting a full JP in a BranchB for the next digit in Index, search
1002 +// sideways for a previous/next absent JP (unset bit) or non-full JP (set bit
1003 +// with non-full JP); first in the current bitmap subexpanse, then in
1004 +// lower/higher subexpanses. Upon entry, Pjp points to a known-unusable JP,
1005 +// ready to decrement/increment.
1006 +//
1007 +// Note: The preceding code is separate from this loop because Index does not
1008 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1009 +//
1010 +// TBD: For speed, shift bitposmaskB instead of using JU_BITMAPTESTB or
1011 +// JU_BITPOSMASKB, but this shift has knowledge of bit order that really should
1012 +// be encapsulated in a header file.
1013 +
1014 +#define BRANCHB_CHECKBIT(OpLeastDigits) \
1015 + if (! (JU_JBB_BITMAP(Pjbb, subexp) & bitposmaskB)) /* absent JP */ \
1016 + SET_AND_RETURN(OpLeastDigits, digit, digits)
1017 +
1018 +#define BRANCHB_CHECKJPFULL(OpLeastDigits) \
1019 + if (! JPFULL(Pjp)) \
1020 + SET_AND_CONTINUE(OpLeastDigits, digit, digits)
1021 +
1022 +#define BRANCHB_STARTSUBEXP(OpLeastDigits) \
1023 + if (! JU_JBB_BITMAP(Pjbb, subexp)) /* empty subexpanse, shortcut */ \
1024 + SET_AND_RETURN(OpLeastDigits, digit, digits) \
1025 + if ((Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp))) == (Pjp_t) NULL) RET_CORRUPT
1026 +
1027 +#ifdef JUDYPREV
1028 +
1029 + --digit; // skip initial digit.
1030 + bitposmaskB >>= 1; // see TBD above.
1031 +
1032 +BranchBNextSubexp: // return here to check next bitmap subexpanse.
1033 +
1034 + while (bitposmaskB) // more bits to check in subexp.
1035 + {
1036 + BRANCHB_CHECKBIT(SETLEASTDIGITS_D);
1037 + --Pjp; // previous in subarray.
1038 + BRANCHB_CHECKJPFULL(SETLEASTDIGITS_D);
1039 + assert(digit >= 0);
1040 + --digit;
1041 + bitposmaskB >>= 1;
1042 + }
1043 +
1044 + if (subexp-- > 0) // more subexpanses.
1045 + {
1046 + BRANCHB_STARTSUBEXP(SETLEASTDIGITS_D);
1047 + Pjp += SEARCHBITMAPMAXB(JU_JBB_BITMAP(Pjbb, subexp)) + 1;
1048 + bitposmaskB = (1U << (cJU_BITSPERSUBEXPB - 1));
1049 + goto BranchBNextSubexp;
1050 + }
1051 +
1052 +#else // JUDYNEXT
1053 +
1054 + ++digit; // skip initial digit.
1055 + bitposmaskB <<= 1; // note: BITMAPB_t.
1056 +
1057 +BranchBNextSubexp: // return here to check next bitmap subexpanse.
1058 +
1059 + while (bitposmaskB) // more bits to check in subexp.
1060 + {
1061 + BRANCHB_CHECKBIT(CLEARLEASTDIGITS_D);
1062 + ++Pjp; // previous in subarray.
1063 + BRANCHB_CHECKJPFULL(CLEARLEASTDIGITS_D);
1064 + assert(digit < cJU_SUBEXPPERSTATE);
1065 + ++digit;
1066 + bitposmaskB <<= 1; // note: BITMAPB_t.
1067 + }
1068 +
1069 + if (++subexp < cJU_NUMSUBEXPB) // more subexpanses.
1070 + {
1071 + BRANCHB_STARTSUBEXP(CLEARLEASTDIGITS_D);
1072 + --Pjp; // pre-decrement.
1073 + bitposmaskB = 1;
1074 + goto BranchBNextSubexp;
1075 + }
1076 +
1077 +#endif // JUDYNEXT
1078 +
1079 +// BranchB secondary dead end, no non-full previous/next JP:
1080 +
1081 + SMRESTART(digits);
1082 +
1083 +
1084 +// ----------------------------------------------------------------------------
1085 +// UNCOMPRESSED BRANCH:
1086 +//
1087 +// Check Decode bytes, if any, in the current JP, then search for a JP for the
1088 +// next digit in Index.
1089 +
1090 + case cJU_JPBRANCH_U2: CHECKDCD(2); SMPREPB2(SMBranchU);
1091 + case cJU_JPBRANCH_U3: CHECKDCD(3); SMPREPB3(SMBranchU);
1092 +#ifdef JU_64BIT
1093 + case cJU_JPBRANCH_U4: CHECKDCD(4); SMPREPB4(SMBranchU);
1094 + case cJU_JPBRANCH_U5: CHECKDCD(5); SMPREPB5(SMBranchU);
1095 + case cJU_JPBRANCH_U6: CHECKDCD(6); SMPREPB6(SMBranchU);
1096 + case cJU_JPBRANCH_U7: CHECKDCD(7); SMPREPB7(SMBranchU);
1097 +#endif
1098 + case cJU_JPBRANCH_U: SMPREPBL(SMBranchU);
1099 +
1100 +// Common code (state-independent) for all cases of uncompressed branches:
1101 +
1102 +SMBranchU:
1103 + Pjbu = P_JBU(Pjp->jp_Addr);
1104 + Pjp = (Pjbu->jbu_jp) + digit;
1105 +
1106 +// Absent JP = null JP for current digit in Index:
1107 +
1108 + if (JPNULL(JU_JPTYPE(Pjp))) RET_SUCCESS;
1109 +
1110 +// Non-full JP matches current digit in Index:
1111 +//
1112 +// Iterate to the subsidiary JP.
1113 +
1114 + if (! JPFULL(Pjp)) goto SMGetContinue;
1115 +
1116 +// BranchU primary dead end:
1117 +//
1118 +// Upon hitting a full JP in a BranchU for the next digit in Index, search
1119 +// sideways for a previous/next null or non-full JP. BRANCHU_CHECKJP() is
1120 +// shorthand for common code.
1121 +//
1122 +// Note: The preceding code is separate from this loop because Index does not
1123 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1124 +
1125 +#define BRANCHU_CHECKJP(OpIncDec,OpLeastDigits) \
1126 + { \
1127 + OpIncDec Pjp; \
1128 + \
1129 + if (JPNULL(JU_JPTYPE(Pjp))) \
1130 + SET_AND_RETURN(OpLeastDigits, digit, digits) \
1131 + \
1132 + if (! JPFULL(Pjp)) \
1133 + SET_AND_CONTINUE(OpLeastDigits, digit, digits) \
1134 + }
1135 +
1136 +#ifdef JUDYPREV
1137 + while (digit-- > 0)
1138 + BRANCHU_CHECKJP(--, SETLEASTDIGITS_D);
1139 +#else
1140 + while (++digit < cJU_BRANCHUNUMJPS)
1141 + BRANCHU_CHECKJP(++, CLEARLEASTDIGITS_D);
1142 +#endif
1143 +
1144 +// BranchU secondary dead end, no non-full previous/next JP:
1145 +
1146 + SMRESTART(digits);
1147 +
1148 +
1149 +// ----------------------------------------------------------------------------
1150 +// LINEAR LEAF:
1151 +//
1152 +// Check Decode bytes, if any, in the current JP, then search the leaf for the
1153 +// previous/next empty index starting at Index. Primary leaf dead end is
1154 +// hidden within j__udySearchLeaf*Empty*(). In case of secondary leaf dead
1155 +// end, restart at the top of the tree.
1156 +//
1157 +// Note: Pword is the name known to GET*; think of it as Pjlw.
1158 +
1159 +#define SMLEAFL(cDigits,Func) \
1160 + Pword = (PWord_t) P_JLW(Pjp->jp_Addr); \
1161 + pop0 = JU_JPLEAF_POP0(Pjp); \
1162 + Func(Pword, pop0)
1163 +
1164 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1165 + case cJU_JPLEAF1: CHECKDCD(1); SMLEAFL(1, j__udySearchLeafEmpty1);
1166 +#endif
1167 + case cJU_JPLEAF2: CHECKDCD(2); SMLEAFL(2, j__udySearchLeafEmpty2);
1168 + case cJU_JPLEAF3: CHECKDCD(3); SMLEAFL(3, j__udySearchLeafEmpty3);
1169 +
1170 +#ifdef JU_64BIT
1171 + case cJU_JPLEAF4: CHECKDCD(4); SMLEAFL(4, j__udySearchLeafEmpty4);
1172 + case cJU_JPLEAF5: CHECKDCD(5); SMLEAFL(5, j__udySearchLeafEmpty5);
1173 + case cJU_JPLEAF6: CHECKDCD(6); SMLEAFL(6, j__udySearchLeafEmpty6);
1174 + case cJU_JPLEAF7: CHECKDCD(7); SMLEAFL(7, j__udySearchLeafEmpty7);
1175 +#endif
1176 +
1177 +
1178 +// ----------------------------------------------------------------------------
1179 +// BITMAP LEAF:
1180 +//
1181 +// Check Decode bytes, if any, in the current JP, then search the leaf for the
1182 +// previous/next empty index starting at Index.
1183 +
1184 + case cJU_JPLEAF_B1:
1185 +
1186 + CHECKDCD(1);
1187 +
1188 + Pjlb = P_JLB(Pjp->jp_Addr);
1189 + digit = JU_DIGITATSTATE(Index, 1);
1190 + subexp = digit / cJU_BITSPERSUBEXPL;
1191 + bitposmaskL = JU_BITPOSMASKL(digit);
1192 + assert(subexp < cJU_NUMSUBEXPL); // falls in expected range.
1193 +
1194 +// Absent index = no index matches current digit in Index:
1195 +
1196 +// if (! JU_BITMAPTESTL(Pjlb, digit)) // slower.
1197 + if (! (JU_JLB_BITMAP(Pjlb, subexp) & bitposmaskL)) // faster.
1198 + RET_SUCCESS;
1199 +
1200 +// LeafB1 primary dead end:
1201 +//
1202 +// Upon hitting a valid (non-empty) index in a LeafB1 for the last digit in
1203 +// Index, search sideways for a previous/next absent index, first in the
1204 +// current bitmap subexpanse, then in lower/higher subexpanses.
1205 +// LEAFB1_CHECKBIT() is shorthand for common code to handle one bit in one
1206 +// bitmap subexpanse.
1207 +//
1208 +// Note: The preceding code is separate from this loop because Index does not
1209 +// need revising (see SET_AND_*()) if the initial index is an empty index.
1210 +//
1211 +// TBD: For speed, shift bitposmaskL instead of using JU_BITMAPTESTL or
1212 +// JU_BITPOSMASKL, but this shift has knowledge of bit order that really should
1213 +// be encapsulated in a header file.
1214 +
1215 +#define LEAFB1_CHECKBIT(OpLeastDigits) \
1216 + if (! (JU_JLB_BITMAP(Pjlb, subexp) & bitposmaskL)) \
1217 + SET_AND_RETURN(OpLeastDigits, digit, 1)
1218 +
1219 +#define LEAFB1_STARTSUBEXP(OpLeastDigits) \
1220 + if (! JU_JLB_BITMAP(Pjlb, subexp)) /* empty subexp */ \
1221 + SET_AND_RETURN(OpLeastDigits, digit, 1)
1222 +
1223 +#ifdef JUDYPREV
1224 +
1225 + --digit; // skip initial digit.
1226 + bitposmaskL >>= 1; // see TBD above.
1227 +
1228 +LeafB1NextSubexp: // return here to check next bitmap subexpanse.
1229 +
1230 + while (bitposmaskL) // more bits to check in subexp.
1231 + {
1232 + LEAFB1_CHECKBIT(SETLEASTDIGITS_D);
1233 + assert(digit >= 0);
1234 + --digit;
1235 + bitposmaskL >>= 1;
1236 + }
1237 +
1238 + if (subexp-- > 0) // more subexpanses.
1239 + {
1240 + LEAFB1_STARTSUBEXP(SETLEASTDIGITS_D);
1241 + bitposmaskL = (1UL << (cJU_BITSPERSUBEXPL - 1));
1242 + goto LeafB1NextSubexp;
1243 + }
1244 +
1245 +#else // JUDYNEXT
1246 +
1247 + ++digit; // skip initial digit.
1248 + bitposmaskL <<= 1; // note: BITMAPL_t.
1249 +
1250 +LeafB1NextSubexp: // return here to check next bitmap subexpanse.
1251 +
1252 + while (bitposmaskL) // more bits to check in subexp.
1253 + {
1254 + LEAFB1_CHECKBIT(CLEARLEASTDIGITS_D);
1255 + assert(digit < cJU_SUBEXPPERSTATE);
1256 + ++digit;
1257 + bitposmaskL <<= 1; // note: BITMAPL_t.
1258 + }
1259 +
1260 + if (++subexp < cJU_NUMSUBEXPL) // more subexpanses.
1261 + {
1262 + LEAFB1_STARTSUBEXP(CLEARLEASTDIGITS_D);
1263 + bitposmaskL = 1;
1264 + goto LeafB1NextSubexp;
1265 + }
1266 +
1267 +#endif // JUDYNEXT
1268 +
1269 +// LeafB1 secondary dead end, no empty index:
1270 +
1271 + SMRESTART(1);
1272 +
1273 +
1274 +#ifdef JUDY1
1275 +// ----------------------------------------------------------------------------
1276 +// FULL POPULATION:
1277 +//
1278 +// If the Decode bytes do not match, Index is empty (without modification);
1279 +// otherwise restart.
1280 +
1281 + case cJ1_JPFULLPOPU1:
1282 +
1283 + CHECKDCD(1);
1284 + SMRESTART(1);
1285 +#endif
1286 +
1287 +
1288 +// ----------------------------------------------------------------------------
1289 +// IMMEDIATE:
1290 +//
1291 +// Pop1 = 1 Immediate JPs:
1292 +//
1293 +// If Index is not in the immediate JP, return success; otherwise check if
1294 +// there is an empty index below/above the immediate JPs index, and if so,
1295 +// return success with modified Index, else restart.
1296 +//
1297 +// Note: Doug says its fast enough to calculate the index size (digits) in
1298 +// the following; no need to set it separately for each case.
1299 +
1300 + case cJU_JPIMMED_1_01:
1301 + case cJU_JPIMMED_2_01:
1302 + case cJU_JPIMMED_3_01:
1303 +#ifdef JU_64BIT
1304 + case cJU_JPIMMED_4_01:
1305 + case cJU_JPIMMED_5_01:
1306 + case cJU_JPIMMED_6_01:
1307 + case cJU_JPIMMED_7_01:
1308 +#endif
1309 + if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) RET_SUCCESS;
1310 + digits = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_01 + 1;
1311 + LEAF_EDGE(JU_LEASTBYTES(JU_JPDCDPOP0(Pjp), digits), digits);
1312 +
1313 +// Immediate JPs with Pop1 > 1:
1314 +
1315 +#define IMM_MULTI(Func,BaseJPType) \
1316 + JUDY1CODE(Pword = (PWord_t) (Pjp->jp_1Index);) \
1317 + JUDYLCODE(Pword = (PWord_t) (Pjp->jp_LIndex);) \
1318 + Func(Pword, JU_JPTYPE(Pjp) - (BaseJPType) + 1)
1319 +
1320 + case cJU_JPIMMED_1_02:
1321 + case cJU_JPIMMED_1_03:
1322 +#if (defined(JUDY1) || defined(JU_64BIT))
1323 + case cJU_JPIMMED_1_04:
1324 + case cJU_JPIMMED_1_05:
1325 + case cJU_JPIMMED_1_06:
1326 + case cJU_JPIMMED_1_07:
1327 +#endif
1328 +#if (defined(JUDY1) && defined(JU_64BIT))
1329 + case cJ1_JPIMMED_1_08:
1330 + case cJ1_JPIMMED_1_09:
1331 + case cJ1_JPIMMED_1_10:
1332 + case cJ1_JPIMMED_1_11:
1333 + case cJ1_JPIMMED_1_12:
1334 + case cJ1_JPIMMED_1_13:
1335 + case cJ1_JPIMMED_1_14:
1336 + case cJ1_JPIMMED_1_15:
1337 +#endif
1338 + IMM_MULTI(j__udySearchLeafEmpty1, cJU_JPIMMED_1_02);
1339 +
1340 +#if (defined(JUDY1) || defined(JU_64BIT))
1341 + case cJU_JPIMMED_2_02:
1342 + case cJU_JPIMMED_2_03:
1343 +#endif
1344 +#if (defined(JUDY1) && defined(JU_64BIT))
1345 + case cJ1_JPIMMED_2_04:
1346 + case cJ1_JPIMMED_2_05:
1347 + case cJ1_JPIMMED_2_06:
1348 + case cJ1_JPIMMED_2_07:
1349 +#endif
1350 +#if (defined(JUDY1) || defined(JU_64BIT))
1351 + IMM_MULTI(j__udySearchLeafEmpty2, cJU_JPIMMED_2_02);
1352 +#endif
1353 +
1354 +#if (defined(JUDY1) || defined(JU_64BIT))
1355 + case cJU_JPIMMED_3_02:
1356 +#endif
1357 +#if (defined(JUDY1) && defined(JU_64BIT))
1358 + case cJ1_JPIMMED_3_03:
1359 + case cJ1_JPIMMED_3_04:
1360 + case cJ1_JPIMMED_3_05:
1361 +#endif
1362 +#if (defined(JUDY1) || defined(JU_64BIT))
1363 + IMM_MULTI(j__udySearchLeafEmpty3, cJU_JPIMMED_3_02);
1364 +#endif
1365 +
1366 +#if (defined(JUDY1) && defined(JU_64BIT))
1367 + case cJ1_JPIMMED_4_02:
1368 + case cJ1_JPIMMED_4_03:
1369 + IMM_MULTI(j__udySearchLeafEmpty4, cJ1_JPIMMED_4_02);
1370 +
1371 + case cJ1_JPIMMED_5_02:
1372 + case cJ1_JPIMMED_5_03:
1373 + IMM_MULTI(j__udySearchLeafEmpty5, cJ1_JPIMMED_5_02);
1374 +
1375 + case cJ1_JPIMMED_6_02:
1376 + IMM_MULTI(j__udySearchLeafEmpty6, cJ1_JPIMMED_6_02);
1377 +
1378 + case cJ1_JPIMMED_7_02:
1379 + IMM_MULTI(j__udySearchLeafEmpty7, cJ1_JPIMMED_7_02);
1380 +#endif
1381 +
1382 +
1383 +// ----------------------------------------------------------------------------
1384 +// INVALID JP TYPE:
1385 +
1386 + default: RET_CORRUPT;
1387 +
1388 + } // SMGet switch.
1389 +
1390 +} // Judy1PrevEmpty() / Judy1NextEmpty() / JudyLPrevEmpty() / JudyLNextEmpty()
libnetdata/libjudy/src/JudyL/JudyLTablesGen.c new
+296
@@ -0,0 +1,296 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.37 $ $Source: /judy/src/JudyCommon/JudyTables.c $
19 +
20 +#ifndef JU_WIN
21 +#include <unistd.h> // unavailable on win_*.
22 +#endif
23 +
24 +#include <stdlib.h>
25 +#include <stdio.h>
26 +
27 +#if (! (defined(JUDY1) || defined(JUDYL)))
28 +#error: One of -DJUDY1 or -DJUDYL must be specified.
29 +#endif
30 +
31 +#define TERMINATOR 999 // terminator for Alloc tables
32 +
33 +#define BPW sizeof(Word_t) // define bytes per word
34 +
35 +#ifdef JUDY1
36 +#include "Judy1.h"
37 +#else
38 +#include "JudyL.h"
39 +#endif
40 +
41 +FILE *fd;
42 +
43 +// Definitions come from header files Judy1.h and JudyL.h:
44 +
45 +int AllocSizes[] = ALLOCSIZES;
46 +
47 +#define ROUNDUP(BYTES,BPW,OFFSETW) \
48 + ((((BYTES) + (BPW) - 1) / (BPW)) + (OFFSETW))
49 +
50 +
51 +// ****************************************************************************
52 +// G E N T A B L E
53 +//
54 +// Note: "const" is required for newer compilers.
55 +
56 +FUNCTION void GenTable(
57 + const char * TableName, // name of table string
58 + const char * TableSize, // dimentioned size string
59 + int IndexBytes, // bytes per Index
60 + int LeafSize, // number elements in object
61 + int ValueBytes, // bytes per Value
62 + int OffsetWords) // 1 for LEAFW
63 +{
64 + int * PAllocSizes = AllocSizes;
65 + int OWord;
66 + int CurWord;
67 + int IWord;
68 + int ii;
69 + int BytesOfIndex;
70 + int BytesOfObject;
71 + int Index;
72 + int LastWords;
73 + int Words [1000] = { 0 };
74 + int Offset[1000] = { 0 };
75 + int MaxWords;
76 +
77 + MaxWords = ROUNDUP((IndexBytes + ValueBytes) * LeafSize, BPW, OffsetWords);
78 + Words[0] = 0;
79 + Offset[0] = 0;
80 + CurWord = TERMINATOR;
81 +
82 +// Walk through all number of Indexes in table:
83 +
84 + for (Index = 1; /* null */; ++Index)
85 + {
86 +
87 +// Calculate byte required for next size:
88 +
89 + BytesOfIndex = IndexBytes * Index;
90 + BytesOfObject = (IndexBytes + ValueBytes) * Index;
91 +
92 +// Round up and calculate words required for next size:
93 +
94 + OWord = ROUNDUP(BytesOfObject, BPW, OffsetWords);
95 + IWord = ROUNDUP(BytesOfIndex, BPW, OffsetWords);
96 +
97 +// Root-level leaves of population of 1 and 2 do not have the 1 word offset:
98 +
99 +// Save minimum value of offset:
100 +
101 + Offset[Index] = IWord;
102 +
103 +// Round up to next available size of words:
104 +
105 + while (OWord > *PAllocSizes) PAllocSizes++;
106 +
107 + if (Index == LeafSize)
108 + {
109 + CurWord = Words[Index] = OWord;
110 + break;
111 + }
112 +// end of available sizes ?
113 +
114 + if (*PAllocSizes == TERMINATOR)
115 + {
116 + fprintf(stderr, "BUG, in %sPopToWords, sizes not big enough for object\n", TableName);
117 + exit(1);
118 + }
119 +
120 +// Save words required and last word:
121 +
122 + if (*PAllocSizes < MaxWords) { CurWord = Words[Index] = *PAllocSizes; }
123 + else { CurWord = Words[Index] = MaxWords; }
124 +
125 + } // for each index
126 +
127 + LastWords = TERMINATOR;
128 +
129 +// Round up to largest size in each group of malloc sizes:
130 +
131 + for (ii = LeafSize; ii > 0; ii--)
132 + {
133 + if (LastWords > (Words[ii] - ii)) LastWords = Offset[ii];
134 + else Offset[ii] = LastWords;
135 + }
136 +
137 +// Print the PopToWords[] table:
138 +
139 + fprintf(fd,"\n//\tobject uses %d words\n", CurWord);
140 + fprintf(fd,"//\t%s = %d\n", TableSize, LeafSize);
141 +
142 + fprintf(fd,"const uint8_t\n");
143 + fprintf(fd,"%sPopToWords[%s + 1] =\n", TableName, TableSize);
144 + fprintf(fd,"{\n\t 0,");
145 +
146 + for (ii = 1; ii <= LeafSize; ii++)
147 + {
148 +
149 +// 8 columns per line, starting with 1:
150 +
151 + if ((ii % 8) == 1) fprintf(fd,"\n\t");
152 +
153 + fprintf(fd,"%2d", Words[ii]);
154 +
155 +// If not last number place comma:
156 +
157 + if (ii != LeafSize) fprintf(fd,", ");
158 + }
159 + fprintf(fd,"\n};\n");
160 +
161 +// Print the Offset table if needed:
162 +
163 + if (! ValueBytes) return;
164 +
165 + fprintf(fd,"const uint8_t\n");
166 + fprintf(fd,"%sOffset[%s + 1] =\n", TableName, TableSize);
167 + fprintf(fd,"{\n");
168 + fprintf(fd,"\t 0,");
169 +
170 + for (ii = 1; ii <= LeafSize; ii++)
171 + {
172 + if ((ii % 8) == 1) fprintf(fd,"\n\t");
173 +
174 + fprintf(fd,"%2d", Offset[ii]);
175 +
176 + if (ii != LeafSize) fprintf(fd,", ");
177 + }
178 + fprintf(fd,"\n};\n");
179 +
180 +} // GenTable()
181 +
182 +
183 +// ****************************************************************************
184 +// M A I N
185 +
186 +FUNCTION int main()
187 +{
188 + int ii;
189 +
190 +#ifdef JUDY1
191 + char *fname = "Judy1Tables.c";
192 +#else
193 + char *fname = "JudyLTables.c";
194 +#endif
195 +
196 + if ((fd = fopen(fname, "w")) == NULL){
197 + perror("FATAL ERROR: could not write to Judy[1L]Tables.c file\n");
198 + return (-1);
199 + }
200 +
201 +
202 + fprintf(fd,"// @(#) From generation tool: $Revision: 4.37 $ $Source: /judy/src/JudyCommon/JudyTables.c $\n");
203 + fprintf(fd,"//\n\n");
204 +
205 +
206 +// ================================ Judy1 =================================
207 +#ifdef JUDY1
208 +
209 + fprintf(fd,"#include \"Judy1.h\"\n");
210 +
211 + fprintf(fd,"// Leave the malloc() sizes readable in the binary (via "
212 + "strings(1)):\n");
213 + fprintf(fd,"const char * Judy1MallocSizes = \"Judy1MallocSizes =");
214 +
215 + for (ii = 0; AllocSizes[ii] != TERMINATOR; ii++)
216 + fprintf(fd," %d,", AllocSizes[ii]);
217 +
218 +#ifndef JU_64BIT
219 + fprintf(fd," Leaf1 = %d\";\n\n", cJ1_LEAF1_MAXPOP1);
220 +#else
221 + fprintf(fd,"\";\n\n"); // no Leaf1 in this case.
222 +#endif
223 +
224 +// ================================ 32 bit ================================
225 +#ifndef JU_64BIT
226 +
227 + GenTable("j__1_BranchBJP","cJU_BITSPERSUBEXPB", 8, cJU_BITSPERSUBEXPB,0,0);
228 +
229 + GenTable("j__1_Leaf1", "cJ1_LEAF1_MAXPOP1", 1, cJ1_LEAF1_MAXPOP1, 0, 0);
230 + GenTable("j__1_Leaf2", "cJ1_LEAF2_MAXPOP1", 2, cJ1_LEAF2_MAXPOP1, 0, 0);
231 + GenTable("j__1_Leaf3", "cJ1_LEAF3_MAXPOP1", 3, cJ1_LEAF3_MAXPOP1, 0, 0);
232 + GenTable("j__1_LeafW", "cJ1_LEAFW_MAXPOP1", 4, cJ1_LEAFW_MAXPOP1, 0, 1);
233 +
234 +#endif
235 +
236 +// ================================ 64 bit ================================
237 +#ifdef JU_64BIT
238 + GenTable("j__1_BranchBJP","cJU_BITSPERSUBEXPB",16, cJU_BITSPERSUBEXPB,0,0);
239 +
240 + GenTable("j__1_Leaf2", "cJ1_LEAF2_MAXPOP1", 2, cJ1_LEAF2_MAXPOP1, 0, 0);
241 + GenTable("j__1_Leaf3", "cJ1_LEAF3_MAXPOP1", 3, cJ1_LEAF3_MAXPOP1, 0, 0);
242 + GenTable("j__1_Leaf4", "cJ1_LEAF4_MAXPOP1", 4, cJ1_LEAF4_MAXPOP1, 0, 0);
243 + GenTable("j__1_Leaf5", "cJ1_LEAF5_MAXPOP1", 5, cJ1_LEAF5_MAXPOP1, 0, 0);
244 + GenTable("j__1_Leaf6", "cJ1_LEAF6_MAXPOP1", 6, cJ1_LEAF6_MAXPOP1, 0, 0);
245 + GenTable("j__1_Leaf7", "cJ1_LEAF7_MAXPOP1", 7, cJ1_LEAF7_MAXPOP1, 0, 0);
246 + GenTable("j__1_LeafW", "cJ1_LEAFW_MAXPOP1", 8, cJ1_LEAFW_MAXPOP1, 0, 1);
247 +#endif
248 +#endif // JUDY1
249 +
250 +
251 +// ================================ JudyL =================================
252 +#ifdef JUDYL
253 +
254 + fprintf(fd,"#include \"JudyL.h\"\n");
255 +
256 + fprintf(fd,"// Leave the malloc() sizes readable in the binary (via "
257 + "strings(1)):\n");
258 + fprintf(fd,"const char * JudyLMallocSizes = \"JudyLMallocSizes =");
259 +
260 + for (ii = 0; AllocSizes[ii] != TERMINATOR; ii++)
261 + fprintf(fd," %d,", AllocSizes[ii]);
262 +
263 + fprintf(fd," Leaf1 = %ld\";\n\n", (Word_t)cJL_LEAF1_MAXPOP1);
264 +
265 +#ifndef JU_64BIT
266 +// ================================ 32 bit ================================
267 + GenTable("j__L_BranchBJP","cJU_BITSPERSUBEXPB", 8, cJU_BITSPERSUBEXPB, 0,0);
268 +
269 + GenTable("j__L_Leaf1", "cJL_LEAF1_MAXPOP1", 1, cJL_LEAF1_MAXPOP1, BPW,0);
270 + GenTable("j__L_Leaf2", "cJL_LEAF2_MAXPOP1", 2, cJL_LEAF2_MAXPOP1, BPW,0);
271 + GenTable("j__L_Leaf3", "cJL_LEAF3_MAXPOP1", 3, cJL_LEAF3_MAXPOP1, BPW,0);
272 + GenTable("j__L_LeafW", "cJL_LEAFW_MAXPOP1", 4, cJL_LEAFW_MAXPOP1, BPW,1);
273 + GenTable("j__L_LeafV", "cJU_BITSPERSUBEXPL", 4, cJU_BITSPERSUBEXPL, 0,0);
274 +#endif // 32 BIT
275 +
276 +#ifdef JU_64BIT
277 +// ================================ 64 bit ================================
278 + GenTable("j__L_BranchBJP","cJU_BITSPERSUBEXPB",16, cJU_BITSPERSUBEXPB, 0,0);
279 +
280 + GenTable("j__L_Leaf1", "cJL_LEAF1_MAXPOP1", 1, cJL_LEAF1_MAXPOP1, BPW,0);
281 + GenTable("j__L_Leaf2", "cJL_LEAF2_MAXPOP1", 2, cJL_LEAF2_MAXPOP1, BPW,0);
282 + GenTable("j__L_Leaf3", "cJL_LEAF3_MAXPOP1", 3, cJL_LEAF3_MAXPOP1, BPW,0);
283 + GenTable("j__L_Leaf4", "cJL_LEAF4_MAXPOP1", 4, cJL_LEAF4_MAXPOP1, BPW,0);
284 + GenTable("j__L_Leaf5", "cJL_LEAF5_MAXPOP1", 5, cJL_LEAF5_MAXPOP1, BPW,0);
285 + GenTable("j__L_Leaf6", "cJL_LEAF6_MAXPOP1", 6, cJL_LEAF6_MAXPOP1, BPW,0);
286 + GenTable("j__L_Leaf7", "cJL_LEAF7_MAXPOP1", 7, cJL_LEAF7_MAXPOP1, BPW,0);
287 + GenTable("j__L_LeafW", "cJL_LEAFW_MAXPOP1", 8, cJL_LEAFW_MAXPOP1, BPW,1);
288 + GenTable("j__L_LeafV", "cJU_BITSPERSUBEXPL", 8, cJU_BITSPERSUBEXPL, 0,0);
289 +#endif // 64 BIT
290 +
291 +#endif // JUDYL
292 + fclose(fd);
293 +
294 + return(0);
295 +
296 +} // main()
libnetdata/libjudy/src/JudyL/j__udyLGet.c new
+1094
@@ -0,0 +1,1094 @@
1 +// Copyright (C) 2000 - 2002 Hewlett-Packard Company
2 +//
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.
7 +//
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
11 +// for more details.
12 +//
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
16 +// _________________
17 +
18 +// @(#) $Revision: 4.43 $ $Source: /judy/src/JudyCommon/JudyGet.c $
19 +//
20 +// Judy1Test() and JudyLGet() functions for Judy1 and JudyL.
21 +// Compile with one of -DJUDY1 or -DJUDYL.
22 +
23 +#if (! (defined(JUDY1) || defined(JUDYL)))
24 +#error: One of -DJUDY1 or -DJUDYL must be specified.
25 +#endif
26 +
27 +#ifdef JUDY1
28 +#include "Judy1.h"
29 +#else
30 +#include "JudyL.h"
31 +#endif
32 +
33 +#include "JudyPrivate1L.h"
34 +
35 +#ifdef TRACEJPR // different macro name, for "retrieval" only.
36 +#include "JudyPrintJP.c"
37 +#endif
38 +
39 +
40 +// ****************************************************************************
41 +// J U D Y 1 T E S T
42 +// J U D Y L G E T
43 +//
44 +// See the manual entry for details. Note support for "shortcut" entries to
45 +// trees known to start with a JPM.
46 +
47 +#ifdef JUDY1
48 +
49 +#ifdef JUDYGETINLINE
50 +FUNCTION int j__udy1Test
51 +#else
52 +FUNCTION int Judy1Test
53 +#endif
54 +
55 +#else // JUDYL
56 +
57 +#ifdef JUDYGETINLINE
58 +FUNCTION PPvoid_t j__udyLGet
59 +#else
60 +FUNCTION PPvoid_t JudyLGet
61 +#endif
62 +
63 +#endif // JUDYL
64 + (
65 +#ifdef JUDYGETINLINE
66 + Pvoid_t PArray, // from which to retrieve.
67 + Word_t Index // to retrieve.
68 +#else
69 + Pcvoid_t PArray, // from which to retrieve.
70 + Word_t Index, // to retrieve.
71 + PJError_t PJError // optional, for returning error info.
72 +#endif
73 + )
74 +{
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;)
81 +
82 +#ifndef JUDYGETINLINE
83 +
84 + if (PArray == (Pcvoid_t) NULL) // empty array.
85 + {
86 + JUDY1CODE(return(0);)
87 + JUDYLCODE(return((PPvoid_t) NULL);)
88 + }
89 +
90 +// ****************************************************************************
91 +// PROCESS TOP LEVEL BRANCHES AND LEAF:
92 +
93 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
94 + {
95 + Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
96 + int posidx; // signed offset in leaf.
97 +
98 + Pop1 = Pjlw[0] + 1;
99 + posidx = j__udySearchLeafW(Pjlw + 1, Pop1, Index);
100 +
101 + if (posidx >= 0)
102 + {
103 + JUDY1CODE(return(1);)
104 + JUDYLCODE(return((PPvoid_t) (JL_LEAFWVALUEAREA(Pjlw, Pop1) + posidx));)
105 + }
106 + JUDY1CODE(return(0);)
107 + JUDYLCODE(return((PPvoid_t) NULL);)
108 + }
109 +
110 +#endif // ! JUDYGETINLINE
111 +
112 + Pjpm = P_JPM(PArray);
113 + Pjp = &(Pjpm->jpm_JP); // top branch is below JPM.
114 +
115 +// ****************************************************************************
116 +// WALK THE JUDY TREE USING A STATE MACHINE:
117 +
118 +ContinueWalk: // for going down one level; come here with Pjp set.
119 +
120 +#ifdef TRACEJPR
121 + JudyPrintJP(Pjp, "g", __LINE__);
122 +#endif
123 + switch (JU_JPTYPE(Pjp))
124 + {
125 +
126 +// Ensure the switch table starts at 0 for speed; otherwise more code is
127 +// executed:
128 +
129 + case 0: goto ReturnCorrupt; // save a little code.
130 +
131 +
132 +// ****************************************************************************
133 +// JPNULL*:
134 +//
135 +// Note: These are legitimate in a BranchU (only) and do not constitute a
136 +// fault.
137 +
138 + case cJU_JPNULL1:
139 + case cJU_JPNULL2:
140 + case cJU_JPNULL3:
141 +#ifdef JU_64BIT
142 + case cJU_JPNULL4:
143 + case cJU_JPNULL5:
144 + case cJU_JPNULL6:
145 + case cJU_JPNULL7:
146 +#endif
147 + assert(ParentJPType >= cJU_JPBRANCH_U2);
148 + assert(ParentJPType <= cJU_JPBRANCH_U);
149 + JUDY1CODE(return(0);)
150 + JUDYLCODE(return((PPvoid_t) NULL);)
151 +
152 +
153 +// ****************************************************************************
154 +// JPBRANCH_L*:
155 +//
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.
159 +
160 + case cJU_JPBRANCH_L2:
161 +
162 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
163 + Digit = JU_DIGITATSTATE(Index, 2);
164 + goto JudyBranchL;
165 +
166 + case cJU_JPBRANCH_L3:
167 +
168 +#ifdef JU_64BIT // otherwise its a no-op:
169 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
170 +#endif
171 + Digit = JU_DIGITATSTATE(Index, 3);
172 + goto JudyBranchL;
173 +
174 +#ifdef JU_64BIT
175 + case cJU_JPBRANCH_L4:
176 +
177 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
178 + Digit = JU_DIGITATSTATE(Index, 4);
179 + goto JudyBranchL;
180 +
181 + case cJU_JPBRANCH_L5:
182 +
183 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
184 + Digit = JU_DIGITATSTATE(Index, 5);
185 + goto JudyBranchL;
186 +
187 + case cJU_JPBRANCH_L6:
188 +
189 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
190 + Digit = JU_DIGITATSTATE(Index, 6);
191 + goto JudyBranchL;
192 +
193 + case cJU_JPBRANCH_L7:
194 +
195 + // JU_DCDNOTMATCHINDEX() would be a no-op.
196 + Digit = JU_DIGITATSTATE(Index, 7);
197 + goto JudyBranchL;
198 +
199 +#endif // JU_64BIT
200 +
201 + case cJU_JPBRANCH_L:
202 + {
203 + Pjbl_t Pjbl;
204 + int posidx;
205 +
206 + Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
207 +
208 +// Common code for all BranchLs; come here with Digit set:
209 +
210 +JudyBranchL:
211 + Pjbl = P_JBL(Pjp->jp_Addr);
212 +
213 + posidx = 0;
214 +
215 + do {
216 + if (Pjbl->jbl_Expanse[posidx] == Digit)
217 + { // found Digit; continue traversal:
218 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
219 + Pjp = Pjbl->jbl_jp + posidx;
220 + goto ContinueWalk;
221 + }
222 + } while (++posidx != Pjbl->jbl_NumJPs);
223 +
224 + break;
225 + }
226 +
227 +
228 +// ****************************************************************************
229 +// JPBRANCH_B*:
230 +
231 + case cJU_JPBRANCH_B2:
232 +
233 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
234 + Digit = JU_DIGITATSTATE(Index, 2);
235 + goto JudyBranchB;
236 +
237 + case cJU_JPBRANCH_B3:
238 +
239 +#ifdef JU_64BIT // otherwise its a no-op:
240 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
241 +#endif
242 + Digit = JU_DIGITATSTATE(Index, 3);
243 + goto JudyBranchB;
244 +
245 +
246 +#ifdef JU_64BIT
247 + case cJU_JPBRANCH_B4:
248 +
249 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
250 + Digit = JU_DIGITATSTATE(Index, 4);
251 + goto JudyBranchB;
252 +
253 + case cJU_JPBRANCH_B5:
254 +
255 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
256 + Digit = JU_DIGITATSTATE(Index, 5);
257 + goto JudyBranchB;
258 +
259 + case cJU_JPBRANCH_B6:
260 +
261 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
262 + Digit = JU_DIGITATSTATE(Index, 6);
263 + goto JudyBranchB;
264 +
265 + case cJU_JPBRANCH_B7:
266 +
267 + // JU_DCDNOTMATCHINDEX() would be a no-op.
268 + Digit = JU_DIGITATSTATE(Index, 7);
269 + goto JudyBranchB;
270 +
271 +#endif // JU_64BIT
272 +
273 + case cJU_JPBRANCH_B:
274 + {
275 + Pjbb_t Pjbb;
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.
279 +
280 + Digit = JU_DIGITATSTATE(Index, cJU_ROOTSTATE);
281 +
282 +// Common code for all BranchBs; come here with Digit set:
283 +
284 +JudyBranchB:
285 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
286 + Pjbb = P_JBB(Pjp->jp_Addr);
287 + subexp = Digit / cJU_BITSPERSUBEXPB;
288 +
289 + BitMap = JU_JBB_BITMAP(Pjbb, subexp);
290 + Pjp = P_JP(JU_JBB_PJP(Pjbb, subexp));
291 +
292 + BitMask = JU_BITPOSMASKB(Digit);
293 +
294 +// No JP in subexpanse for Index => Index not found:
295 +
296 + if (! (BitMap & BitMask)) break;
297 +
298 +// Count JPs in the subexpanse below the one for Index:
299 +
300 + Pjp += j__udyCountBitsB(BitMap & (BitMask - 1));
301 +
302 + goto ContinueWalk;
303 +
304 + } // case cJU_JPBRANCH_B*
305 +
306 +
307 +// ****************************************************************************
308 +// JPBRANCH_U*:
309 +//
310 +// Notice the reverse order of the cases, and falling through to the next case,
311 +// for performance.
312 +
313 + case cJU_JPBRANCH_U:
314 +
315 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
316 + Pjp = JU_JBU_PJP(Pjp, Index, cJU_ROOTSTATE);
317 +
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:
321 +
322 +#ifndef JU_64BIT
323 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
324 +#else
325 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U7) goto ContinueWalk;
326 +#endif
327 +
328 +#ifdef JU_64BIT
329 + case cJU_JPBRANCH_U7:
330 +
331 + // JU_DCDNOTMATCHINDEX() would be a no-op.
332 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
333 + Pjp = JU_JBU_PJP(Pjp, Index, 7);
334 +
335 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U6) goto ContinueWalk;
336 + // and fall through.
337 +
338 + case cJU_JPBRANCH_U6:
339 +
340 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
341 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
342 + Pjp = JU_JBU_PJP(Pjp, Index, 6);
343 +
344 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U5) goto ContinueWalk;
345 + // and fall through.
346 +
347 + case cJU_JPBRANCH_U5:
348 +
349 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
350 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
351 + Pjp = JU_JBU_PJP(Pjp, Index, 5);
352 +
353 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U4) goto ContinueWalk;
354 + // and fall through.
355 +
356 + case cJU_JPBRANCH_U4:
357 +
358 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
359 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
360 + Pjp = JU_JBU_PJP(Pjp, Index, 4);
361 +
362 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U3) goto ContinueWalk;
363 + // and fall through.
364 +
365 +#endif // JU_64BIT
366 +
367 + case cJU_JPBRANCH_U3:
368 +
369 +#ifdef JU_64BIT // otherwise its a no-op:
370 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
371 +#endif
372 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
373 + Pjp = JU_JBU_PJP(Pjp, Index, 3);
374 +
375 + if (JU_JPTYPE(Pjp) != cJU_JPBRANCH_U2) goto ContinueWalk;
376 + // and fall through.
377 +
378 + case cJU_JPBRANCH_U2:
379 +
380 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
381 + DBGCODE(ParentJPType = JU_JPTYPE(Pjp);)
382 + Pjp = JU_JBU_PJP(Pjp, Index, 2);
383 +
384 +// Note: BranchU2 is a special case that must continue traversal to a leaf,
385 +// immed, full, or null type:
386 +
387 + goto ContinueWalk;
388 +
389 +
390 +// ****************************************************************************
391 +// JPLEAF*:
392 +//
393 +// Note: Here the calls of JU_DCDNOTMATCHINDEX() are necessary and check
394 +// whether Index is out of the expanse of a narrow pointer.
395 +
396 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
397 +
398 + case cJU_JPLEAF1:
399 + {
400 + int posidx; // signed offset in leaf.
401 +
402 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
403 +
404 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
405 + Pjll = P_JLL(Pjp->jp_Addr);
406 +
407 + if ((posidx = j__udySearchLeaf1(Pjll, Pop1, Index)) < 0) break;
408 +
409 + JUDY1CODE(return(1);)
410 + JUDYLCODE(return((PPvoid_t) (JL_LEAF1VALUEAREA(Pjll, Pop1) + posidx));)
411 + }
412 +
413 +#endif // (JUDYL || (! JU_64BIT))
414 +
415 + case cJU_JPLEAF2:
416 + {
417 + int posidx; // signed offset in leaf.
418 +
419 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 2)) break;
420 +
421 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
422 + Pjll = P_JLL(Pjp->jp_Addr);
423 +
424 + if ((posidx = j__udySearchLeaf2(Pjll, Pop1, Index)) < 0) break;
425 +
426 + JUDY1CODE(return(1);)
427 + JUDYLCODE(return((PPvoid_t) (JL_LEAF2VALUEAREA(Pjll, Pop1) + posidx));)
428 + }
429 + case cJU_JPLEAF3:
430 + {
431 + int posidx; // signed offset in leaf.
432 +
433 +#ifdef JU_64BIT // otherwise its a no-op:
434 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 3)) break;
435 +#endif
436 +
437 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
438 + Pjll = P_JLL(Pjp->jp_Addr);
439 +
440 + if ((posidx = j__udySearchLeaf3(Pjll, Pop1, Index)) < 0) break;
441 +
442 + JUDY1CODE(return(1);)
443 + JUDYLCODE(return((PPvoid_t) (JL_LEAF3VALUEAREA(Pjll, Pop1) + posidx));)
444 + }
445 +#ifdef JU_64BIT
446 + case cJU_JPLEAF4:
447 + {
448 + int posidx; // signed offset in leaf.
449 +
450 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 4)) break;
451 +
452 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
453 + Pjll = P_JLL(Pjp->jp_Addr);
454 +
455 + if ((posidx = j__udySearchLeaf4(Pjll, Pop1, Index)) < 0) break;
456 +
457 + JUDY1CODE(return(1);)
458 + JUDYLCODE(return((PPvoid_t) (JL_LEAF4VALUEAREA(Pjll, Pop1) + posidx));)
459 + }
460 + case cJU_JPLEAF5:
461 + {
462 + int posidx; // signed offset in leaf.
463 +
464 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 5)) break;
465 +
466 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
467 + Pjll = P_JLL(Pjp->jp_Addr);
468 +
469 + if ((posidx = j__udySearchLeaf5(Pjll, Pop1, Index)) < 0) break;
470 +
471 + JUDY1CODE(return(1);)
472 + JUDYLCODE(return((PPvoid_t) (JL_LEAF5VALUEAREA(Pjll, Pop1) + posidx));)
473 + }
474 +
475 + case cJU_JPLEAF6:
476 + {
477 + int posidx; // signed offset in leaf.
478 +
479 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 6)) break;
480 +
481 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
482 + Pjll = P_JLL(Pjp->jp_Addr);
483 +
484 + if ((posidx = j__udySearchLeaf6(Pjll, Pop1, Index)) < 0) break;
485 +
486 + JUDY1CODE(return(1);)
487 + JUDYLCODE(return((PPvoid_t) (JL_LEAF6VALUEAREA(Pjll, Pop1) + posidx));)
488 + }
489 + case cJU_JPLEAF7:
490 + {
491 + int posidx; // signed offset in leaf.
492 +
493 + // JU_DCDNOTMATCHINDEX() would be a no-op.
494 + Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
495 + Pjll = P_JLL(Pjp->jp_Addr);
496 +
497 + if ((posidx = j__udySearchLeaf7(Pjll, Pop1, Index)) < 0) break;
498 +
499 + JUDY1CODE(return(1);)
500 + JUDYLCODE(return((PPvoid_t) (JL_LEAF7VALUEAREA(Pjll, Pop1) + posidx));)
501 + }
502 +#endif // JU_64BIT
503 +
504 +
505 +// ****************************************************************************
506 +// JPLEAF_B1:
507 +
508 + case cJU_JPLEAF_B1:
509 + {
510 + Pjlb_t Pjlb;
511 +#ifdef JUDYL
512 + int posidx;
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.
516 + Pjv_t Pjv;
517 +#endif
518 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
519 +
520 + Pjlb = P_JLB(Pjp->jp_Addr);
521 +
522 +#ifdef JUDY1
523 +
524 +// Simply check if Indexs bit is set in the bitmap:
525 +
526 + if (JU_BITMAPTESTL(Pjlb, Index)) return(1);
527 + break;
528 +
529 +#else // JUDYL
530 +
531 +// JudyL is much more complicated because of value area subarrays:
532 +
533 + Digit = JU_DIGITATSTATE(Index, 1);
534 + subexp = Digit / cJU_BITSPERSUBEXPL;
535 + BitMap = JU_JLB_BITMAP(Pjlb, subexp);
536 + BitMask = JU_BITPOSMASKL(Digit);
537 +
538 +// No value in subexpanse for Index => Index not found:
539 +
540 + if (! (BitMap & BitMask)) break;
541 +
542 +// Count value areas in the subexpanse below the one for Index:
543 +
544 + Pjv = P_JV(JL_JLB_PVALUE(Pjlb, subexp));
545 + assert(Pjv != (Pjv_t) NULL);
546 + posidx = j__udyCountBitsL(BitMap & (BitMask - 1));
547 +
548 + return((PPvoid_t) (Pjv + posidx));
549 +
550 +#endif // JUDYL
551 +
552 + } // case cJU_JPLEAF_B1
553 +
554 +#ifdef JUDY1
555 +
556 +// ****************************************************************************
557 +// JPFULLPOPU1:
558 +//
559 +// If the Index is in the expanse, it is necessarily valid (found).
560 +
561 + case cJ1_JPFULLPOPU1:
562 +
563 + if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
564 + return(1);
565 +
566 +#ifdef notdef // for future enhancements
567 +#ifdef JU_64BIT
568 +
569 +// Note: Need ? if (JU_DCDNOTMATCHINDEX(Index, Pjp, 1)) break;
570 +
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;
587 +#endif
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;
602 +
603 + return(1); // found, not in exclusion list
604 +
605 +#endif // JUDY1
606 +#endif // notdef
607 +
608 +// ****************************************************************************
609 +// JPIMMED*:
610 +//
611 +// Note that the contents of jp_DcdPopO are different for cJU_JPIMMED_*_01:
612 +
613 + case cJU_JPIMMED_1_01:
614 + case cJU_JPIMMED_2_01:
615 + case cJU_JPIMMED_3_01:
616 +#ifdef JU_64BIT
617 + case cJU_JPIMMED_4_01:
618 + case cJU_JPIMMED_5_01:
619 + case cJU_JPIMMED_6_01:
620 + case cJU_JPIMMED_7_01:
621 +#endif
622 + if (JU_JPDCDPOP0(Pjp) != JU_TRIMTODCDSIZE(Index)) break;
623 +
624 + JUDY1CODE(return(1);)
625 + JUDYLCODE(return((PPvoid_t) &(Pjp->jp_Addr));) // immediate value area.
626 +
627 +
628 +// Macros to make code more readable and avoid dup errors
629 +
630 +#ifdef JUDY1
631 +
632 +#define CHECKINDEXNATIVE(LEAF_T, PJP, IDX, INDEX) \
633 +if (((LEAF_T *)((PJP)->jp_1Index))[(IDX) - 1] == (LEAF_T)(INDEX)) \
634 + return(1)
635 +
636 +#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
637 +{ \
638 + Word_t i_ndex; \
639 + uint8_t *a_ddr; \
640 + a_ddr = (PJP)->jp_1Index + (((IDX) - 1) * (LFBTS)); \
641 + COPY(i_ndex, a_ddr); \
642 + if (i_ndex == JU_LEASTBYTES((INDEX), (LFBTS))) \
643 + return(1); \
644 +}
645 +#endif
646 +
647 +#ifdef JUDYL
648 +
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))
652 +
653 +#define CHECKLEAFNONNAT(LFBTS, PJP, INDEX, IDX, COPY) \
654 +{ \
655 + Word_t i_ndex; \
656 + uint8_t *a_ddr; \
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)); \
661 +}
662 +#endif
663 +
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);
673 +#endif
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);
679 +#endif
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);
683 + break;
684 +
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);
690 +#endif
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);
695 + break;
696 +#endif
697 +
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);
705 +#endif
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);
710 + break;
711 +#endif
712 +
713 +#if (defined(JUDY1) && defined(JU_64BIT))
714 +
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);
718 + break;
719 +
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);
725 + break;
726 +
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);
730 + break;
731 +
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);
735 + break;
736 +
737 +#endif // (JUDY1 && JU_64BIT)
738 +
739 +
740 +// ****************************************************************************
741 +// INVALID JP TYPE:
742 +
743 + default:
744 +
745 +ReturnCorrupt:
746 +
747 +#ifdef JUDYGETINLINE // Pjpm is known to be non-null:
748 + JU_SET_ERRNO_NONNULL(Pjpm, JU_ERRNO_CORRUPT);
749 +#else
750 + JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
751 +#endif
752 + JUDY1CODE(return(JERRI );)
753 + JUDYLCODE(return(PPJERR);)
754 +
755 + } // switch on JP type
756 +
757 +JUDY1CODE(return(0);)
758 +JUDYLCODE(return((PPvoid_t) NULL);)
759 +
760 +} // Judy1Test() / JudyLGet()
761 +
762 +
763 +#ifndef JUDYGETINLINE // only compile the following function once:
764 +#ifdef DEBUG
765 +
766 +// ****************************************************************************
767 +// J U D Y C H E C K P O P
768 +//
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.
771 +//
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.
775 +//
776 +// Note: Even though this function does nothing useful for LEAFW leaves, its
777 +// good practice to call it anyway, and cheap too.
778 +//
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.
782 +//
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?
787 +//
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:
792 +//
793 +// - Zero LS bits in jp_Addr field.
794 +//
795 +// - Correct Dcd bits.
796 +//
797 +// - Consistent JP types (always descending down the tree).
798 +//
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).
802 +//
803 +// - Any others possible?
804 +
805 +#include <stdlib.h> // for getenv() and atol().
806 +
807 +static Word_t JudyCheckPopSM(Pjp_t Pjp, Word_t RootPop1);
808 +
809 +FUNCTION void JudyCheckPop(
810 + Pvoid_t PArray)
811 +{
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.
817 +
818 +
819 +// CHECK FOR EXTERNAL ENABLING:
820 +
821 + if (! checked) // only check once.
822 + {
823 + char * value; // for getenv().
824 +
825 + checked = TRUE;
826 +
827 + if ((value = getenv("CHECKPOP")) == (char *) NULL)
828 + {
829 +#ifdef notdef
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:
832 +
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");
836 +#endif
837 + return;
838 + }
839 +
840 + callsmin = atol(value); // note: non-number evaluates to 0.
841 + enabled = TRUE;
842 +
843 + (void) printf("JudyCheckPop() present and enabled; callsmin = "
844 + "%lu\n", callsmin);
845 + }
846 + else if (! enabled) return;
847 +
848 +// Previously or just now enabled; check if non-active or newly active:
849 +
850 + if (! active)
851 + {
852 + if (++calls < callsmin) return;
853 +
854 + (void) printf("JudyCheckPop() activated at call %lu\n", calls);
855 + active = TRUE;
856 + }
857 +
858 +// IGNORE LEAFW AT TOP OF TREE:
859 +
860 + if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
861 + return;
862 +
863 +// Check JPM pop0 against tree, recursively:
864 +//
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.
870 +
871 + {
872 + Pjpm_t Pjpm = P_JPM(PArray);
873 + (void) JudyCheckPopSM(&(Pjpm->jpm_JP), Pjpm->jpm_Pop0 + 1);
874 + return;
875 + }
876 +
877 +} // JudyCheckPop()
878 +
879 +
880 +// ****************************************************************************
881 +// J U D Y C H E C K P O P S M
882 +//
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.
887 +//
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.
890 +
891 +FUNCTION static Word_t JudyCheckPopSM(
892 + Pjp_t Pjp, // top of subtree.
893 + Word_t RootPop1) // whole array, for top-level branches only.
894 +{
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.
898 +
899 +#define PREPBRANCH(cPopBytes,Next) \
900 + pop1_jp = JU_JPBRANCH_POP0(Pjp, cPopBytes) + 1; goto Next
901 +
902 +assert((((Word_t) (Pjp->jp_Addr)) & 7) == 3);
903 + switch (JU_JPTYPE(Pjp))
904 + {
905 +
906 + case cJU_JPBRANCH_L2: PREPBRANCH(2, BranchL);
907 + case cJU_JPBRANCH_L3: PREPBRANCH(3, BranchL);
908 +#ifdef JU_64BIT
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);
913 +#endif
914 + case cJU_JPBRANCH_L: pop1_jp = RootPop1;
915 + {
916 + Pjbl_t Pjbl;
917 +BranchL:
918 + Pjbl = P_JBL(Pjp->jp_Addr);
919 +
920 + for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
921 + pop1 += JudyCheckPopSM((Pjbl->jbl_jp) + offset, 0);
922 +
923 + assert(pop1_jp == pop1);
924 + return(pop1);
925 + }
926 +
927 + case cJU_JPBRANCH_B2: PREPBRANCH(2, BranchB);
928 + case cJU_JPBRANCH_B3: PREPBRANCH(3, BranchB);
929 +#ifdef JU_64BIT
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);
934 +#endif
935 + case cJU_JPBRANCH_B: pop1_jp = RootPop1;
936 + {
937 + Word_t subexp;
938 + Word_t jpcount;
939 + Pjbb_t Pjbb;
940 +BranchB:
941 + Pjbb = P_JBB(Pjp->jp_Addr);
942 +
943 + for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
944 + {
945 + jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
946 +
947 + for (offset = 0; offset < jpcount; ++offset)
948 + {
949 + pop1 += JudyCheckPopSM(P_JP(JU_JBB_PJP(Pjbb, subexp))
950 + + offset, 0);
951 + }
952 + }
953 +
954 + assert(pop1_jp == pop1);
955 + return(pop1);
956 + }
957 +
958 + case cJU_JPBRANCH_U2: PREPBRANCH(2, BranchU);
959 + case cJU_JPBRANCH_U3: PREPBRANCH(3, BranchU);
960 +#ifdef JU_64BIT
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);
965 +#endif
966 + case cJU_JPBRANCH_U: pop1_jp = RootPop1;
967 + {
968 + Pjbu_t Pjbu;
969 +BranchU:
970 + Pjbu = P_JBU(Pjp->jp_Addr);
971 +
972 + for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
973 + {
974 + if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
975 + && ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
976 + {
977 + continue; // skip null JP to save time.
978 + }
979 +
980 + pop1 += JudyCheckPopSM((Pjbu->jbu_jp) + offset, 0);
981 + }
982 +
983 + assert(pop1_jp == pop1);
984 + return(pop1);
985 + }
986 +
987 +
988 +// -- Cases below here terminate and do not recurse. --
989 +//
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.
993 +
994 +#define CHECKLEAF(MaxPop1) \
995 + pop1 = JU_JPLEAF_POP0(Pjp) + 1; \
996 + assert(pop1 >= 1); \
997 + assert(pop1 <= (MaxPop1)); \
998 + return(pop1)
999 +
1000 +#if (defined(JUDYL) || (! defined(JU_64BIT)))
1001 + case cJU_JPLEAF1: CHECKLEAF(cJU_LEAF1_MAXPOP1);
1002 +#endif
1003 + case cJU_JPLEAF2: CHECKLEAF(cJU_LEAF2_MAXPOP1);
1004 + case cJU_JPLEAF3: CHECKLEAF(cJU_LEAF3_MAXPOP1);
1005 +#ifdef JU_64BIT
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);
1010 +#endif
1011 +
1012 + case cJU_JPLEAF_B1:
1013 + {
1014 + Word_t subexp;
1015 + Pjlb_t Pjlb;
1016 +
1017 + pop1_jp = JU_JPLEAF_POP0(Pjp) + 1;
1018 +
1019 + Pjlb = P_JLB(Pjp->jp_Addr);
1020 +
1021 + for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
1022 + pop1 += j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
1023 +
1024 + assert(pop1_jp == pop1);
1025 + return(pop1);
1026 + }
1027 +
1028 + JUDY1CODE(case cJ1_JPFULLPOPU1: return(cJU_JPFULLPOPU1_POP0);)
1029 +
1030 + case cJU_JPIMMED_1_01: return(1);
1031 + case cJU_JPIMMED_2_01: return(1);
1032 + case cJU_JPIMMED_3_01: return(1);
1033 +#ifdef JU_64BIT
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);
1038 +#endif
1039 +
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);
1047 +#endif
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);
1057 +#endif
1058 +
1059 +#if (defined(JUDY1) || defined(JU_64BIT))
1060 + case cJU_JPIMMED_2_02: return(2);
1061 + case cJU_JPIMMED_2_03: return(3);
1062 +#endif
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);
1068 +#endif
1069 +
1070 +#if (defined(JUDY1) || defined(JU_64BIT))
1071 + case cJU_JPIMMED_3_02: return(2);
1072 +#endif
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);
1077 +
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);
1084 +#endif
1085 +
1086 + } // switch (JU_JPTYPE(Pjp))
1087 +
1088 + assert(FALSE); // unrecognized JP type => corruption.
1089 + return(0); // to make some compilers happy.
1090 +
1091 +} // JudyCheckPopSM()
1092 +
1093 +#endif // DEBUG
1094 +#endif // ! JUDYGETINLINE
netdata-installer.sh
-96
@@ -307,7 +307,6 @@ while [ -n "${1}" ]; do
307 "--disable-https") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-https)}" | sed 's/$/ --disable-plugin-https/g')" ;;
308 "--disable-dbengine")
309 NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-dbengine)}" | sed 's/$/ --disable-dbengine/g')"
310 - NETDATA_DISABLE_DBENGINE=1
310 ;;
311 "--enable-plugin-nfacct") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--enable-plugin-nfacct)}" | sed 's/$/ --enable-plugin-nfacct/g')" ;;
312 "--disable-plugin-nfacct") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-plugin-nfacct)}" | sed 's/$/ --disable-plugin-nfacct/g')" ;;
@@ -367,9 +366,6 @@ while [ -n "${1}" ]; do
366 "--build-json-c")
367 NETDATA_BUILD_JSON_C=1
368 ;;
370 - "--build-judy")
371 - NETDATA_BUILD_JUDY=1
372 - ;;
369 "--install")
370 NETDATA_PREFIX="${2}/netdata"
371 shift 1
@@ -658,98 +654,6 @@ bundle_protobuf() {
654
655 bundle_protobuf
656
661 -# -----------------------------------------------------------------------------
662 -
663 -build_judy() {
664 - env_cmd=''
665 - libtoolize="libtoolize"
666 -
667 - if [ -z "${DONT_SCRUB_CFLAGS_EVEN_THOUGH_IT_MAY_BREAK_THINGS}" ]; then
668 - env_cmd="env CFLAGS='-fPIC -pipe' CXXFLAGS='-fPIC -pipe' LDFLAGS="
669 - fi
670 -
671 - if [ "$(uname)" = "Darwin" ]; then
672 - libtoolize="glibtoolize"
673 - fi
674 -
675 - cd "${1}" > /dev/null || return 1
676 - if run eval "${env_cmd} ${libtoolize} --force --copy" &&
677 - run eval "${env_cmd} aclocal" &&
678 - run eval "${env_cmd} autoheader" &&
679 - run eval "${env_cmd} automake --add-missing --force --copy --include-deps" &&
680 - run eval "${env_cmd} autoconf" &&
681 - run eval "${env_cmd} ./configure" &&
682 - run eval "${env_cmd} ${make} ${MAKEOPTS} -C src" &&
683 - run eval "${env_cmd} ar -r src/libJudy.a src/Judy*/*.o"; then
684 - cd - > /dev/null || return 1
685 - else
686 - cd - > /dev/null || return 1
687 - return 1
688 - fi
689 -}
690 -
691 -copy_judy() {
692 - target_dir="${PWD}/externaldeps/libJudy"
693 -
694 - run mkdir -p "${target_dir}" || return 1
695 -
696 - run cp "${1}/src/libJudy.a" "${target_dir}/libJudy.a" || return 1
697 - run cp "${1}/src/Judy.h" "${target_dir}/Judy.h" || return 1
698 -}
699 -
700 -bundle_judy() {
701 - # If --build-judy flag or no Judy on the system and we're building the dbengine, bundle our own libJudy.
702 - # shellcheck disable=SC2235,SC2030,SC2031
703 - if [ -n "${NETDATA_DISABLE_DBENGINE}" ] || ([ -z "${NETDATA_BUILD_JUDY}" ] && [ -e /usr/include/Judy.h ]); then
704 - return 0
705 - elif [ -n "${NETDATA_BUILD_JUDY}" ]; then
706 - progress "User requested bundling of libJudy, building it now"
707 - elif [ ! -e /usr/include/Judy.h ]; then
708 - progress "/usr/include/Judy.h does not exist, but we need libJudy, building our own copy"
709 - fi
710 -
711 - [ -n "${GITHUB_ACTIONS}" ] && echo "::group::Bundling libJudy."
712 -
713 - progress "Prepare libJudy"
714 -
715 - JUDY_PACKAGE_VERSION="$(cat packaging/judy.version)"
716 -
717 - tmp="$(mktemp -d -t netdata-judy-XXXXXX)"
718 - JUDY_PACKAGE_BASENAME="v${JUDY_PACKAGE_VERSION}.tar.gz"
719 -
720 - if fetch_and_verify "judy" \
721 - "https://github.com/netdata/libjudy/archive/${JUDY_PACKAGE_BASENAME}" \
722 - "${JUDY_PACKAGE_BASENAME}" \
723 - "${tmp}" \
724 - "${NETDATA_LOCAL_TARBALL_OVERRIDE_JUDY}"; then
725 - if run tar --no-same-owner -xf "${tmp}/${JUDY_PACKAGE_BASENAME}" -C "${tmp}" &&
726 - build_judy "${tmp}/libjudy-${JUDY_PACKAGE_VERSION}" &&
727 - copy_judy "${tmp}/libjudy-${JUDY_PACKAGE_VERSION}" &&
728 - rm -rf "${tmp}"; then
729 - run_ok "libJudy built and prepared."
730 - NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --with-bundled-libJudy"
731 - else
732 - if [ -n "${NETDATA_BUILD_JUDY}" ]; then
733 - [ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
734 - fatal "failed to build libJudy." I0003
735 - else
736 - run_failed "Failed to build libJudy, dbengine support will be disabled."
737 - fi
738 - fi
739 - else
740 - if [ -n "${NETDATA_BUILD_JUDY}" ]; then
741 - [ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
742 - fatal "Unable to fetch sources for libJudy, which is required for this build of Netdata." I0004
743 - else
744 - run_failed "Unable to fetch sources for libJudy, which is required for this build of Netdata."
745 - fi
746 - fi
747 -
748 - [ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
749 -}
750 -
751 -bundle_judy
752 -
657 # -----------------------------------------------------------------------------
658 build_jsonc() {
659 env_cmd=''
netdata.spec.in
-9
@@ -143,14 +143,12 @@ BuildRequires: openssl-devel
143 %if 0%{?suse_version}
144 BuildRequires: protobuf-devel
145 BuildRequires: libprotobuf-c-devel
146 -BuildRequires: judy-devel
146 BuildRequires: liblz4-devel
147 BuildRequires: libjson-c-devel
148 %else
149 %if 0%{?fedora}
150 BuildRequires: protobuf-devel
151 BuildRequires: protobuf-c-devel
153 -BuildRequires: Judy-devel
152 BuildRequires: lz4-devel
153 BuildRequires: json-c-devel
154 %else
@@ -227,10 +225,6 @@ happened, on your systems and applications.
225
226 %prep
227 %setup -q -n %{name}-%{version}
230 -# Only bundle libJudy if this isn't Fedora or SUSE
231 -%if 0%{!?fedora:1} && 0%{!?suse_version:1}
232 -export CFLAGS="${CFLAGS} -fPIC" && ${RPM_BUILD_DIR}/%{name}-%{version}/packaging/bundle-judy.sh ${RPM_BUILD_DIR}/%{name}-%{version}
233 -%endif
228 # Only bundle protobuf on CentOS 7 or earlier
229 %if 0%{?centos_ver:1}
230 %if %{centos_ver} < 8
@@ -259,9 +253,6 @@ autoreconf -ivf
253 %if 0%{!?_have_ebpf}
254 --disable-ebpf
255 %endif
262 - %if 0%{!?fedora:1} && 0%{!?suse_version:1}
263 - --with-bundled-libJudy \
264 - %endif
256 %if 0%{?centos_ver:1}
257 %if %{centos_ver} < 8
258 --with-bundled-protobuf \
packaging/bundle-judy.sh deleted
-23
@@ -1,23 +0,0 @@
1 -#!/bin/sh
2 -
3 -JUDY_TARBALL="v$(cat "${1}/packaging/judy.version").tar.gz"
4 -JUDY_BUILD_PATH="${1}/externaldeps/libJudy/libjudy-$(cat "${1}/packaging/judy.version")"
5 -
6 -mkdir -p "${1}/externaldeps/libJudy" || exit 1
7 -curl -sSL --connect-timeout 10 --retry 3 "https://github.com/netdata/libjudy/archive/${JUDY_TARBALL}" > "${JUDY_TARBALL}" || exit 1
8 -sha256sum -c "${1}/packaging/judy.checksums" || exit 1
9 -tar -xzf "${JUDY_TARBALL}" -C "${1}/externaldeps/libJudy" || exit 1
10 -OLDPWD="${PWD}"
11 -cd "${JUDY_BUILD_PATH}" || exit 1
12 -libtoolize --force --copy || exit 1
13 -aclocal || exit 1
14 -autoheader || exit 1
15 -automake --add-missing --force --copy --include-deps || exit 1
16 -autoconf || exit 1
17 -./configure --disable-dependency-tracking || exit 1
18 -make -C src || exit 1
19 -ar -r src/libJudy.a src/Judy*/*.o || exit 1
20 -cd "${OLDPWD}" || exit 1
21 -
22 -cp -a "${JUDY_BUILD_PATH}/src/libJudy.a" "${1}/externaldeps/libJudy" || exit 1
23 -cp -a "${JUDY_BUILD_PATH}/src/Judy.h" "${1}/externaldeps/libJudy" || exit 1
packaging/docker/Dockerfile
-2
@@ -8,8 +8,6 @@ FROM netdata/builder:latest as builder
8 # One of 'nightly' or 'stable'
9 ARG RELEASE_CHANNEL=nightly
10
11 -ENV JUDY_VER 1.0.5
12 -
11 ARG CFLAGS
12
13 ENV CFLAGS=$CFLAGS
packaging/installer/dependencies/arch.sh
-1
@@ -24,7 +24,6 @@ declare -a package_tree=(
24 libuv
25 lz4
26 openssl
27 - judy
27 libelf
28 git
29 pkgconfig
packaging/installer/dependencies/centos.sh
-3
@@ -139,9 +139,6 @@ validate_tree_centos() {
139 echo >&2 " > Updating libarchive ..."
140 dnf ${opts} install libarchive
141
142 - echo >&2 " > Installing Judy-devel directly ..."
143 - dnf ${opts} install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.3.0+757+d382997d.x86_64.rpm
144 - dnf makecache --refresh
142 elif [[ $(os_version) =~ ^7(\..*)?$ ]]; then
143 package_manager=yum
144 echo >&2 " > Checking for EPEL ..."
packaging/installer/dependencies/debian.sh
-1
@@ -31,7 +31,6 @@ package_tree="
31 libuv1-dev
32 liblz4-dev
33 libssl-dev
34 - libjudy-dev
34 libelf-dev
35 python
36 python3
packaging/installer/dependencies/fedora.sh
-1
@@ -43,7 +43,6 @@ declare -a package_tree=(
43 libuv-devel
44 lz4-devel
45 openssl-devel
46 - Judy-devel
46 elfutils-libelf-devel
47 git
48 pkgconfig
packaging/installer/dependencies/freebsd.sh
-1
@@ -25,7 +25,6 @@ package_tree="
25 libuv
26 liblz4
27 openssl
28 - Judy
28 python3
29 "
30
packaging/installer/dependencies/gentoo.sh
-1
@@ -28,7 +28,6 @@ package_tree="
28 dev-libs/libuv
29 app-arch/lz4
30 dev-libs/openssl
31 - dev-libs/judy
31 virtual/libelf
32 dev-lang/python
33 dev-libs/libuv
packaging/installer/dependencies/opensuse.sh
-1
@@ -29,7 +29,6 @@ declare -a package_tree=(
29 libuv-devel
30 liblz4-devel
31 libopenssl-devel
32 - judy-devel
32 libelf-devel
33 git
34 tar
packaging/installer/dependencies/ubuntu.sh
-1
@@ -31,7 +31,6 @@ package_tree="
31 libuv1-dev
32 liblz4-dev
33 libssl-dev
34 - libjudy-dev
34 libelf-dev
35 python3
36 "
packaging/installer/install-required-packages.sh
-23
@@ -665,13 +665,6 @@ declare -A pkg_automake=(
665 ['default']="automake"
666 )
667
668 -# required to bundle libJudy
669 -declare -A pkg_libtool=(
670 - ['gentoo']="sys-devel/libtool"
671 - ['clearlinux']="c-basic"
672 - ['default']="libtool"
673 -)
674 -
668 # Required to build libwebsockets and libmosquitto on some systems.
669 declare -A pkg_cmake=(
670 ['gentoo']="dev-util/cmake"
@@ -1112,17 +1105,6 @@ declare -A pkg_openssl=(
1105 ['default']="openssl-devel"
1106 )
1107
1115 -declare -A pkg_judy=(
1116 - ['debian']="libjudy-dev"
1117 - ['ubuntu']="libjudy-dev"
1118 - ['suse']="judy-devel"
1119 - ['gentoo']="dev-libs/judy"
1120 - ['arch']="judy"
1121 - ['freebsd']="Judy"
1122 - ['fedora']="Judy-devel"
1123 - ['default']="NOTREQUIRED"
1124 -)
1125 -
1108 declare -A pkg_python3=(
1109 ['gentoo']="dev-lang/python"
1110 ['sabayon']="dev-lang/python:3.4"
@@ -1289,7 +1271,6 @@ packages() {
1271 suitable_package autoconf-archive
1272 require_cmd autogen || suitable_package autogen
1273 require_cmd automake || suitable_package automake
1292 - require_cmd libtoolize || suitable_package libtool
1274 require_cmd pkg-config || suitable_package pkg-config
1275 require_cmd cmake || suitable_package cmake
1276
@@ -1361,7 +1342,6 @@ packages() {
1342 suitable_package libuv
1343 suitable_package lz4
1344 suitable_package openssl
1364 - suitable_package judy
1345 fi
1346
1347 # -------------------------------------------------------------------------
@@ -1579,9 +1559,6 @@ validate_tree_centos() {
1559 echo >&2 " > Updating libarchive ..."
1560 run ${sudo} yum ${opts} install libarchive
1561
1582 - echo >&2 " > Installing Judy-devel directly ..."
1583 - run ${sudo} yum ${opts} install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.3.0+757+d382997d.x86_64.rpm
1584 -
1562 elif [[ "${version}" =~ ^7(\..*)?$ ]]; then
1563 echo >&2 " > Checking for EPEL ..."
1564 if ! rpm -qa | grep epel-release > /dev/null; then
packaging/installer/methods/freebsd.md
+1 -1
@@ -20,7 +20,7 @@ This is how to install the latest Netdata version on FreeBSD:
20 Install required packages (**need root permission**):
21
22 ```sh
23 -pkg install bash e2fsprogs-libuuid git curl autoconf automake pkgconf pidof Judy liblz4 libuv json-c cmake gmake
23 +pkg install bash e2fsprogs-libuuid git curl autoconf automake pkgconf pidof liblz4 libuv json-c cmake gmake
24 ```
25
26 Download Netdata:
packaging/installer/methods/manual.md
+4 -10
@@ -25,9 +25,6 @@ and other operating systems and is regularly tested. You can find this tool [her
25 - **Alpine** Linux and its derivatives
26 - You have to install `bash` yourself, before using the installer.
27
28 -- **Arch** Linux and its derivatives
29 - - You need arch/aur for package Judy.
30 -
28 - **Gentoo** Linux and its derivatives
29
30 - **Debian** Linux and its derivatives (including **Ubuntu**, **Mint**)
@@ -67,16 +64,16 @@ This is how to do it by hand:
64
65 ```sh
66 # Debian / Ubuntu
70 -apt-get install zlib1g-dev uuid-dev libuv1-dev liblz4-dev libjudy-dev libssl-dev libelf-dev libmnl-dev libprotobuf-dev protobuf-compiler gcc g++ make git autoconf autoconf-archive autogen automake pkg-config curl python cmake
67 +apt-get install zlib1g-dev uuid-dev libuv1-dev liblz4-dev libssl-dev libelf-dev libmnl-dev libprotobuf-dev protobuf-compiler gcc g++ make git autoconf autoconf-archive autogen automake pkg-config curl python cmake
68
69 # Fedora
73 -dnf install zlib-devel libuuid-devel libuv-devel lz4-devel Judy-devel openssl-devel elfutils-libelf-devel libmnl-devel protobuf-devel protobuf-compiler gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
70 +dnf install zlib-devel libuuid-devel libuv-devel lz4-devel openssl-devel elfutils-libelf-devel libmnl-devel protobuf-devel protobuf-compiler gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
71
72 # CentOS / Red Hat Enterprise Linux
76 -yum install autoconf automake curl gcc gcc-c++ git libmnl-devel libuuid-devel openssl-devel libuv-devel lz4-devel Judy-devel elfutils-libelf-devel protobuf protobuf-devel protobuf-compiler make nc pkgconfig python zlib-devel cmake
73 +yum install autoconf automake curl gcc gcc-c++ git libmnl-devel libuuid-devel openssl-devel libuv-devel lz4-devel elfutils-libelf-devel protobuf protobuf-devel protobuf-compiler make nc pkgconfig python zlib-devel cmake
74
75 # openSUSE
79 -zypper install zlib-devel libuuid-devel libuv-devel liblz4-devel judy-devel libopenssl-devel libelf-devel libmnl-devel protobuf-devel gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
76 +zypper install zlib-devel libuuid-devel libuv-devel liblz4-devel libopenssl-devel libelf-devel libmnl-devel protobuf-devel gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
77 ```
78
79 Once Netdata is compiled, to run it the following packages are required (already installed using the above commands):
@@ -117,7 +114,6 @@ Netdata DB engine can be enabled when these are installed (they are optional):
114 | package | description|
115 |:-----:|-----------|
116 | `liblz4` | Extremely fast compression algorithm, version r129 or greater|
120 -| `Judy` | General purpose dynamic array|
117 | `openssl`| Cryptography and SSL/TLS toolkit|
118
119 *Netdata will greatly benefit if you have the above packages installed, but it will still work without them.*
@@ -175,8 +171,6 @@ yum install -y http://repo.okay.com.mx/centos/8/x86_64/release/okay-release-1-3.
171 # Install Devel Packages
172 yum install autoconf automake curl gcc git cmake libuuid-devel openssl-devel libuv-devel lz4-devel make nc pkgconfig python3 zlib-devel
173
178 -# Install Judy-Devel directly
179 -yum install -y http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.1.0+217+4d875839.x86_64.rpm
174 ```
175
176 ## Install Netdata
packaging/installer/methods/pfsense.md
-1
@@ -25,7 +25,6 @@ pkg install -y pkgconf bash e2fsprogs-libuuid libuv nano
25 Then run the following commands to download various dependencies from the FreeBSD repository.
26
27 ```sh
28 -pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/Judy-1.0.5_3.txz
28 pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/json-c-0.15_1.txz
29 pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/py38-certifi-2021.10.8.txz
30 pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/py38-asn1crypto-1.4.0.txz
packaging/installer/methods/source.md
-1
@@ -32,7 +32,6 @@ Additionally, the following build time features require additional dependencies:
32 - dbengine metric storage:
33 - liblz4 r129 or newer
34 - OpenSSL 1.0 or newer (LibreSSL _amy_ work, but is largely untested).
35 - - [libJudy](http://judy.sourceforge.net/)
35 - Netdata Cloud support:
36 - A working internet connection
37 - A recent version of CMake
packaging/judy.checksums deleted
-1
@@ -1 +0,0 @@
1 -e623a06bf091758b43f5cd97c3609f8109442d1a0441bc44819b60f2861c61b1 v1.0.5-netdata2.tar.gz
packaging/judy.version deleted
-1
@@ -1 +0,0 @@
1 -1.0.5-netdata2