Name Date Size

..25-Oct-20244 KiB

aes/H25-Oct-20244 KiB

alphacpuid.plH A D25-Oct-20243.9 KiB

aria/H25-Oct-20244 KiB

arm64cpuid.plH A D25-Oct-20243.2 KiB

arm_arch.hH A D25-Oct-20244.2 KiB

armcap.cH A D25-Oct-20247.3 KiB

armv4cpuid.plH A D25-Oct-20245.6 KiB

asn1/H25-Oct-20244 KiB

asn1_dsa.cH A D25-Oct-20247.4 KiB

async/H25-Oct-20244 KiB

bf/H25-Oct-20244 KiB

bio/H25-Oct-20244 KiB

bn/H25-Oct-20244 KiB

bsearch.cH A D25-Oct-20241.2 KiB

buffer/H25-Oct-20244 KiB

build.infoH A D25-Oct-20244.5 KiB

c64xpluscpuid.plH A D25-Oct-20245.3 KiB

camellia/H25-Oct-20244 KiB

cast/H25-Oct-20244 KiB

chacha/H25-Oct-20244 KiB

cmac/H25-Oct-20244 KiB

cmp/H25-Oct-20244 KiB

cms/H25-Oct-20244 KiB

comp/H25-Oct-20244 KiB

conf/H25-Oct-20244 KiB

context.cH A D25-Oct-202413.5 KiB

core_algorithm.cH A D25-Oct-20246.6 KiB

core_fetch.cH A D25-Oct-20245.7 KiB

core_namemap.cH A D25-Oct-202414.3 KiB

cpt_err.cH A D25-Oct-20242.7 KiB

cpuid.cH A D25-Oct-20245.7 KiB

crmf/H25-Oct-20244 KiB

cryptlib.cH A D25-Oct-20247.9 KiB

ct/H25-Oct-20244 KiB

ctype.cH A D25-Oct-202415 KiB

cversion.cH A D25-Oct-20241.9 KiB

der_writer.cH A D25-Oct-20246 KiB

des/H25-Oct-20244 KiB

dh/H25-Oct-20244 KiB

dllmain.cH A D25-Oct-20241.2 KiB

dsa/H25-Oct-20244 KiB

dso/H25-Oct-20244 KiB

ebcdic.cH A D25-Oct-202415 KiB

ec/H25-Oct-20244 KiB

encode_decode/H25-Oct-20244 KiB

engine/H25-Oct-20244 KiB

err/H25-Oct-20244 KiB

ess/H25-Oct-20244 KiB

evp/H25-Oct-20244 KiB

ex_data.cH A D25-Oct-202413.9 KiB

ffc/H25-Oct-20244 KiB

getenv.cH A D25-Oct-20243.1 KiB

hmac/H25-Oct-20244 KiB

http/H25-Oct-20244 KiB

ia64cpuid.SH A D25-Oct-20246.3 KiB

idea/H25-Oct-20244 KiB

info.cH A D25-Oct-20247.9 KiB

init.cH A D25-Oct-202421.2 KiB

initthread.cH A D25-Oct-202412.8 KiB

kdf/H25-Oct-20244 KiB

lhash/H25-Oct-20244 KiB

LPdir_nyi.cH A D25-Oct-20242 KiB

LPdir_unix.cH A D25-Oct-20244.9 KiB

LPdir_vms.cH A D25-Oct-20246.2 KiB

LPdir_win.cH A D25-Oct-20246.9 KiB

LPdir_win32.cH A D25-Oct-20241.9 KiB

LPdir_wince.cH A D25-Oct-20242 KiB

md2/H25-Oct-20244 KiB

md4/H25-Oct-20244 KiB

md5/H25-Oct-20244 KiB

mdc2/H25-Oct-20244 KiB

mem.cH A D25-Oct-20247.9 KiB

mem_clr.cH A D25-Oct-2024773

mem_sec.cH A D25-Oct-202419 KiB

mips_arch.hH A D25-Oct-20241.2 KiB

modes/H25-Oct-20244 KiB

o_dir.cH A D25-Oct-20241.1 KiB

o_fopen.cH A D25-Oct-20244.3 KiB

o_init.cH A D25-Oct-2024516

o_str.cH A D25-Oct-20248.9 KiB

o_time.cH A D25-Oct-20245.5 KiB

objects/H25-Oct-20244 KiB

ocsp/H25-Oct-20244 KiB

packet.cH A D25-Oct-202411.9 KiB

param_build.cH A D25-Oct-202411.3 KiB

param_build_set.cH A D25-Oct-20243.6 KiB

params.cH A D25-Oct-202437.6 KiB

params_dup.cH A D25-Oct-20247.2 KiB

params_from_text.cH A D25-Oct-20247 KiB

pariscid.plH A D25-Oct-20244.8 KiB

passphrase.cH A D25-Oct-202411.3 KiB

pem/H25-Oct-20244 KiB

perlasm/H25-Oct-20244 KiB

pkcs12/H25-Oct-20244 KiB

pkcs7/H25-Oct-20244 KiB

poly1305/H25-Oct-20244 KiB

ppccap.cH A D25-Oct-20248.3 KiB

ppccpuid.plH A D25-Oct-20247.3 KiB

property/H25-Oct-20244 KiB

provider.cH A D25-Oct-20244.2 KiB

provider_child.cH A D25-Oct-202410.2 KiB

provider_conf.cH A D25-Oct-202411.7 KiB

provider_core.cH A D25-Oct-202468 KiB

provider_local.hH A D25-Oct-20241 KiB

provider_predefined.cH A D25-Oct-20241.1 KiB

punycode.cH A D25-Oct-20249.1 KiB

rand/H25-Oct-20244 KiB

rc2/H25-Oct-20244 KiB

rc4/H25-Oct-20244 KiB

rc5/H25-Oct-20244 KiB

README-sparse_array.mdH A D25-Oct-20245.6 KiB

ripemd/H25-Oct-20244 KiB

rsa/H25-Oct-20244 KiB

s390x_arch.hH A D25-Oct-20246.3 KiB

s390xcap.cH A D25-Oct-202429.6 KiB

s390xcpuid.plH A D25-Oct-202411.4 KiB

seed/H25-Oct-20244 KiB

self_test_core.cH A D25-Oct-20244.6 KiB

sha/H25-Oct-20244 KiB

siphash/H25-Oct-20244 KiB

sm2/H25-Oct-20244 KiB

sm3/H25-Oct-20244 KiB

sm4/H25-Oct-20244 KiB

sparccpuid.SH A D25-Oct-202412 KiB

sparcv9cap.cH A D25-Oct-20247.3 KiB

sparse_array.cH A D25-Oct-20245.8 KiB

srp/H25-Oct-20244 KiB

stack/H25-Oct-20244 KiB

store/H25-Oct-20244 KiB

threads_lib.cH A D25-Oct-2024510

threads_none.cH A D25-Oct-20243.1 KiB

threads_pthread.cH A D25-Oct-20246.7 KiB

threads_win.cH A D25-Oct-20246 KiB

trace.cH A D25-Oct-202414.6 KiB

ts/H25-Oct-20244 KiB

txt_db/H25-Oct-20244 KiB

ui/H25-Oct-20244 KiB

uid.cH A D25-Oct-20241.3 KiB

vms_rms.hH A D25-Oct-20242.1 KiB

whrlpool/H25-Oct-20244 KiB

x509/H25-Oct-20244 KiB

x86_64cpuid.plH A D25-Oct-202410.4 KiB

x86cpuid.plH A D25-Oct-202412.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