NameDateSize

..04-Feb-202449

aes/H04-Oct-202314

alphacpuid.plH A D04-Feb-20243.9 KiB

aria/H29-Jun-20234

arm64cpuid.plH A D04-Oct-20233.5 KiB

arm_arch.hH A D26-Oct-20236.2 KiB

armcap.cH A D29-Jun-20237.3 KiB

armv4cpuid.plH A D29-Jun-20235.6 KiB

asn1/H04-Feb-202473

asn1_dsa.cH A D29-Jun-20237.4 KiB

async/H29-Jun-20238

bf/H29-Jun-202311

bio/H29-Jun-202331

bn/H04-Feb-202446

bsearch.cH A D29-Jun-20231.2 KiB

buffer/H29-Jun-20235

build.infoH A D04-Feb-20244.4 KiB

c64xpluscpuid.plH A D29-Jun-20235.3 KiB

camellia/H29-Jun-202312

cast/H29-Jun-202311

chacha/H29-Jun-20236

cmac/H29-Jun-20234

cmp/H10-Oct-202316

cms/H04-Feb-202421

comp/H29-Jun-20237

conf/H04-Feb-202414

context.cH A D29-Jun-202313.5 KiB

core_algorithm.cH A D29-Jun-20236.6 KiB

core_fetch.cH A D29-Jun-20235.7 KiB

core_namemap.cH A D11-Aug-202314.4 KiB

cpt_err.cH A D29-Jun-20232.7 KiB

cpuid.cH A D29-Jun-20235.7 KiB

crmf/H29-Jun-20238

cryptlib.cH A D29-Jun-20237.9 KiB

ct/H29-Jun-202314

ctype.cH A D29-Jun-202315 KiB

cversion.cH A D29-Jun-20231.9 KiB

der_writer.cH A D29-Jun-20236 KiB

des/H29-Jun-202326

dh/H04-Feb-202419

dllmain.cH A D29-Jun-20231.2 KiB

dsa/H26-Oct-202319

dso/H04-Feb-202411

ebcdic.cH A D29-Jun-202315 KiB

ec/H04-Feb-202447

encode_decode/H10-Oct-202312

engine/H26-Oct-202327

err/H04-Feb-202412

ess/H29-Jun-20236

evp/H04-Feb-202486

ex_data.cH A D26-Oct-202314 KiB

ffc/H26-Oct-202310

getenv.cH A D29-Jun-20233.1 KiB

hmac/H29-Jun-20235

http/H04-Feb-20246

ia64cpuid.SH A D29-Jun-20236.3 KiB

idea/H29-Jun-20239

info.cH A D29-Jun-20237.9 KiB

init.cH A D29-Jun-202321.2 KiB

initthread.cH A D29-Jun-202312.8 KiB

kdf/H29-Jun-20234

lhash/H26-Oct-20236

LPdir_nyi.cH A D04-Feb-20242 KiB

LPdir_unix.cH A D11-Aug-20234.9 KiB

LPdir_vms.cH A D04-Feb-20246.2 KiB

LPdir_win.cH A D04-Feb-20246.9 KiB

LPdir_win32.cH A D04-Feb-20241.9 KiB

LPdir_wince.cH A D04-Feb-20242 KiB

md2/H29-Jun-20235

md4/H29-Jun-20236

md5/H29-Jun-20238

mdc2/H29-Jun-20235

mem.cH A D26-Oct-20238.2 KiB

mem_clr.cH A D29-Jun-2023773

mem_sec.cH A D04-Feb-202419.1 KiB

mips_arch.hH A D29-Jun-20231.2 KiB

modes/H29-Jun-202315

o_dir.cH A D29-Jun-20231.1 KiB

o_fopen.cH A D29-Jun-20234.3 KiB

o_init.cH A D29-Jun-2023516

o_str.cH A D29-Jun-20238.9 KiB

o_time.cH A D29-Jun-20235.5 KiB

objects/H04-Feb-202419

ocsp/H29-Jun-202314

packet.cH A D29-Jun-202311.9 KiB

param_build.cH A D04-Feb-202411.3 KiB

param_build_set.cH A D26-Oct-20233.7 KiB

params.cH A D11-Aug-202337.9 KiB

params_dup.cH A D29-Jun-20237.2 KiB

params_from_text.cH A D04-Feb-20247.3 KiB

pariscid.plH A D29-Jun-20234.8 KiB

passphrase.cH A D29-Jun-202311.3 KiB

pem/H10-Oct-202315

perlasm/H04-Feb-202414

pkcs12/H04-Feb-202420

pkcs7/H04-Feb-202412

poly1305/H29-Jun-20238

ppccap.cH A D29-Jun-20238.4 KiB

ppccpuid.plH A D29-Jun-20237.3 KiB

property/H04-Feb-202411

provider.cH A D29-Jun-20234.2 KiB

provider_child.cH A D29-Jun-202310.2 KiB

provider_conf.cH A D04-Feb-202411.7 KiB

provider_core.cH A D04-Feb-202468.3 KiB

provider_local.hH A D29-Jun-20231 KiB

provider_predefined.cH A D29-Jun-20231.1 KiB

punycode.cH A D29-Jun-20239.1 KiB

rand/H11-Aug-202312

rc2/H29-Jun-20239

rc4/H11-Aug-20237

rc5/H29-Jun-202310

README-sparse_array.mdH A D29-Jun-20235.6 KiB

ripemd/H29-Jun-20238

rsa/H04-Feb-202431

s390x_arch.hH A D29-Jun-20236.3 KiB

s390xcap.cH A D29-Jun-202329.6 KiB

s390xcpuid.plH A D29-Jun-202311.4 KiB

seed/H29-Jun-20239

self_test_core.cH A D29-Jun-20234.6 KiB

sha/H04-Oct-202312

siphash/H29-Jun-20234

sm2/H29-Jun-20237

sm3/H29-Jun-20236

sm4/H29-Jun-20234

sparccpuid.SH A D29-Jun-202312 KiB

sparcv9cap.cH A D29-Jun-20237.3 KiB

sparse_array.cH A D29-Jun-20235.8 KiB

srp/H10-Oct-20235

stack/H29-Jun-20234

store/H10-Oct-202311

threads_lib.cH A D29-Jun-2023510

threads_none.cH A D29-Jun-20233.1 KiB

threads_pthread.cH A D10-Oct-20236.6 KiB

threads_win.cH A D04-Feb-20246 KiB

trace.cH A D29-Jun-202314.6 KiB

ts/H29-Jun-202315

txt_db/H29-Jun-20234

ui/H29-Jun-20239

uid.cH A D29-Jun-20231.3 KiB

vms_rms.hH A D29-Jun-20232.1 KiB

whrlpool/H29-Jun-20237

x509/H04-Feb-202484

x86_64cpuid.plH A D29-Jun-202310.4 KiB

x86cpuid.plH A D29-Jun-202312.2 KiB

README-sparse_array.md

1Sparse Arrays
2=============
3
4The `sparse_array.c` file contains an implementation of a sparse array that
5attempts to be both space and time efficient.
6
7The sparse array is represented using a tree structure.  Each node in the
8tree contains a block of pointers to either the user supplied leaf values or
9to another node.
10
11There are a number of parameters used to define the block size:
12
13    OPENSSL_SA_BLOCK_BITS   Specifies the number of bits covered by each block
14    SA_BLOCK_MAX            Specifies the number of pointers in each block
15    SA_BLOCK_MASK           Specifies a bit mask to perform modulo block size
16    SA_BLOCK_MAX_LEVELS     Indicates the maximum possible height of the tree
17
18These constants are inter-related:
19
20    SA_BLOCK_MAX        = 2 ^ OPENSSL_SA_BLOCK_BITS
21    SA_BLOCK_MASK       = SA_BLOCK_MAX - 1
22    SA_BLOCK_MAX_LEVELS = number of bits in size_t divided by
23                          OPENSSL_SA_BLOCK_BITS rounded up to the next multiple
24                          of OPENSSL_SA_BLOCK_BITS
25
26`OPENSSL_SA_BLOCK_BITS` can be defined at compile time and this overrides the
27built in setting.
28
29As a space and performance optimisation, the height of the tree is usually
30less than the maximum possible height.  Only sufficient height is allocated to
31accommodate the largest index added to the data structure.
32
33The largest index used to add a value to the array determines the tree height:
34
35        +----------------------+---------------------+
36        | Largest Added Index  |   Height of Tree    |
37        +----------------------+---------------------+
38        | SA_BLOCK_MAX     - 1 |          1          |
39        | SA_BLOCK_MAX ^ 2 - 1 |          2          |
40        | SA_BLOCK_MAX ^ 3 - 1 |          3          |
41        | ...                  |          ...        |
42        | size_t max           | SA_BLOCK_MAX_LEVELS |
43        +----------------------+---------------------+
44
45The tree height is dynamically increased as needed based on additions.
46
47An empty tree is represented by a NULL root pointer.  Inserting a value at
48index 0 results in the allocation of a top level node full of null pointers
49except for the single pointer to the user's data (N = SA_BLOCK_MAX for
50brevity):
51
52        +----+
53        |Root|
54        |Node|
55        +-+--+
56          |
57          |
58          |
59          v
60        +-+-+---+---+---+---+
61        | 0 | 1 | 2 |...|N-1|
62        |   |nil|nil|...|nil|
63        +-+-+---+---+---+---+
64          |
65          |
66          |
67          v
68        +-+--+
69        |User|
70        |Data|
71        +----+
72    Index 0
73
74Inserting at element 2N+1 creates a new root node and pushes down the old root
75node.  It then creates a second second level node to hold the pointer to the
76user's new data:
77
78        +----+
79        |Root|
80        |Node|
81        +-+--+
82          |
83          |
84          |
85          v
86        +-+-+---+---+---+---+
87        | 0 | 1 | 2 |...|N-1|
88        |   |nil|   |...|nil|
89        +-+-+---+-+-+---+---+
90          |       |
91          |       +------------------+
92          |                          |
93          v                          v
94        +-+-+---+---+---+---+      +-+-+---+---+---+---+
95        | 0 | 1 | 2 |...|N-1|      | 0 | 1 | 2 |...|N-1|
96        |nil|   |nil|...|nil|      |nil|   |nil|...|nil|
97        +-+-+---+---+---+---+      +---+-+-+---+---+---+
98          |                              |
99          |                              |
100          |                              |
101          v                              v
102        +-+--+                         +-+--+
103        |User|                         |User|
104        |Data|                         |Data|
105        +----+                         +----+
106    Index 0                       Index 2N+1
107
108The nodes themselves are allocated in a sparse manner.  Only nodes which exist
109along a path from the root of the tree to an added leaf will be allocated.
110The complexity is hidden and nodes are allocated on an as needed basis.
111Because the data is expected to be sparse this doesn't result in a large waste
112of space.
113
114Values can be removed from the sparse array by setting their index position to
115NULL.  The data structure does not attempt to reclaim nodes or reduce the
116height of the tree on removal.  For example, now setting index 0 to NULL would
117result in:
118
119        +----+
120        |Root|
121        |Node|
122        +-+--+
123          |
124          |
125          |
126          v
127        +-+-+---+---+---+---+
128        | 0 | 1 | 2 |...|N-1|
129        |   |nil|   |...|nil|
130        +-+-+---+-+-+---+---+
131          |       |
132          |       +------------------+
133          |                          |
134          v                          v
135        +-+-+---+---+---+---+      +-+-+---+---+---+---+
136        | 0 | 1 | 2 |...|N-1|      | 0 | 1 | 2 |...|N-1|
137        |nil|nil|nil|...|nil|      |nil|   |nil|...|nil|
138        +---+---+---+---+---+      +---+-+-+---+---+---+
139                                         |
140                                         |
141                                         |
142                                         v
143                                       +-+--+
144                                       |User|
145                                       |Data|
146                                       +----+
147                                  Index 2N+1
148
149Accesses to elements in the sparse array take O(log n) time where n is the
150largest element.  The base of the logarithm is `SA_BLOCK_MAX`, so for moderately
151small indices (e.g. NIDs), single level (constant time) access is achievable.
152Space usage is O(minimum(m, n log(n)) where m is the number of elements in the
153array.
154
155Note: sparse arrays only include pointers to types.
156Thus, `SPARSE_ARRAY_OF(char)` can be used to store a string.
157