1
/* Copyright (C) 2010 Philip Ashmore (contact@philipashmore.com) */
2
/* License: LGPLv3. See LICENSE.txt for the full license. */
4
#ifdef DOXYGEN_processing
8
#include "array-template-defines.h"
10
#ifdef DOXYGEN_processing
18
/* 10. pointer pack / unpack */
19
#ifndef ARRAY_TMPL_omit_unpack_array
20
#define ARRAY_TMPL_unpack_array(x) ARRAY_TMPL_NS(unpack_array)(runtime, x)
21
ARRAY_TMPL_prefix ARRAY_TMPL_array_ptr_t
22
ARRAY_TMPL_NS(unpack_array)
23
( ARRAY_TMPL_runtime_ptr_t runtime
24
, ARRAY_TMPL_packed_array_ptr_t p
26
ARRAY_TMPL_array_ptr_t ret
27
= (ARRAY_TMPL_array_ptr_t)ARRAY_TMPL_unpack_pointer(p);
28
TREEDB_printf8("array::unpack_array : %lu[0x%lx] -> %p\n"
30
, (uintptr_t)p, (void *)(uintptr_t)ret);
34
#ifndef ARRAY_TMPL_omit_pack_array
35
#define ARRAY_TMPL_pack_array(x) ARRAY_TMPL_NS(pack_array)(runtime, x)
36
ARRAY_TMPL_prefix ARRAY_TMPL_packed_array_ptr_t
37
ARRAY_TMPL_NS(pack_array)
38
( ARRAY_TMPL_runtime_ptr_t runtime
39
, ARRAY_TMPL_array_ptr_t p
41
ARRAY_TMPL_packed_array_ptr_t ret = ARRAY_TMPL_pack_pointer(p);
42
TREEDB_printf8("array::pack_array : %p -> %lu[0x%lx]\n"
43
, (void *)(uintptr_t)p, (uintptr_t)ret
48
#ifndef ARRAY_TMPL_omit_pack_data
49
#define ARRAY_TMPL_pack_data(x) ARRAY_TMPL_NS(pack_data)(runtime, x)
50
ARRAY_TMPL_prefix ARRAY_TMPL_packed_data_ptr_t
51
ARRAY_TMPL_NS(pack_data)
52
( ARRAY_TMPL_runtime_ptr_t runtime
53
, ARRAY_TMPL_data_t * p
55
ARRAY_TMPL_packed_data_ptr_t ret = ARRAY_TMPL_pack_pointer(p);
56
TREEDB_printf8("handle_array::pack_data : %p -> %lu[0x%lx]\n"
57
, (void *)(uintptr_t)p, (uintptr_t)ret
62
#ifndef ARRAY_TMPL_omit_unpack_data
63
#define ARRAY_TMPL_unpack_data(x) ARRAY_TMPL_NS(unpack_data)(runtime, x)
64
ARRAY_TMPL_prefix ARRAY_TMPL_data_t *
65
ARRAY_TMPL_NS(unpack_data)
66
( ARRAY_TMPL_runtime_ptr_t runtime
67
, ARRAY_TMPL_packed_data_ptr_t p
69
ARRAY_TMPL_data_t * ret = (ARRAY_TMPL_data_t *)ARRAY_TMPL_unpack_pointer(p);
70
TREEDB_printf8("handle_array::unpack_data : %lu[0x%lx] -> %p\n"
72
, (uintptr_t)p, (void *)(uintptr_t)ret);
78
Allocate array item storage.
80
The storage used must be write locked.
82
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(init)
83
( ARRAY_TMPL_runtime_ptr_t runtime
84
, ARRAY_TMPL_packed_array_ptr_t ha
85
, ARRAY_TMPL_size_t reserve
86
, ARRAY_TMPL_size_t increment
92
else if(ARRAY_TMPL_exceeds_count_limit(increment))
94
if(ARRAY_TMPL_exceeds_count_limit(reserve))
96
ARRAY_TMPL_count_t nitems = V3C_ROUND_UP_T(ARRAY_TMPL_count_t, reserve, increment);
97
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
98
ARRAY_TMPL_data_t * pd;
100
pd = (ARRAY_TMPL_data_t *)ARRAY_TMPL_alloc(nitems * ARRAY_TMPL_entry_size);
101
pa = ARRAY_TMPL_unpack_array(ha);
104
ARRAY_TMPL_count_MEMBER_SET(pa, 0);
105
ARRAY_TMPL_reserve_MEMBER_SET(pa, nitems);
106
ARRAY_TMPL_increment_MEMBER_SET(pa, increment);
107
ARRAY_TMPL_items_MEMBER_SET(pa, ARRAY_TMPL_pack_data(pd));
112
#ifndef ARRAY_TMPL_omit_init_empty_ptr
114
Set up an empty array.
116
The storage used must be write locked.
118
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(init_empty_ptr)
119
( ARRAY_TMPL_runtime_ptr_t runtime
120
, ARRAY_TMPL_array_ptr_t pa
121
, ARRAY_TMPL_size_t increment
125
else if(ARRAY_TMPL_exceeds_count_limit(increment))
127
ARRAY_TMPL_count_MEMBER_SET(pa, 0);
128
ARRAY_TMPL_reserve_MEMBER_SET(pa, 0);
129
ARRAY_TMPL_increment_MEMBER_SET(pa, increment);
130
ARRAY_TMPL_items_MEMBER_SET(pa, ARRAY_TMPL_pack_data(0));
134
#ifndef ARRAY_TMPL_omit_init_empty
136
Set up an empty array.
138
The storage used must be write locked.
140
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(init_empty)
141
( ARRAY_TMPL_runtime_ptr_t runtime
142
, ARRAY_TMPL_packed_array_ptr_t ha
143
, ARRAY_TMPL_size_t increment
145
return ARRAY_TMPL_NS(init_empty_ptr)(runtime, ARRAY_TMPL_unpack_array(ha)
150
#ifndef ARRAY_TMPL_omit_new
154
The storage used must be write locked.
156
ARRAY_TMPL_prefix ARRAY_TMPL_packed_array_ptr_t ARRAY_TMPL_NS(new)
157
( ARRAY_TMPL_runtime_ptr_t runtime
158
, ARRAY_TMPL_size_t reserve
159
, ARRAY_TMPL_size_t increment
161
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_alloc_array;
164
ARRAY_TMPL_packed_array_ptr_t ha = ARRAY_TMPL_pack_array(pa);
165
if(ARRAY_TMPL_NS(init)(runtime, ha, reserve, increment)) {
166
ARRAY_TMPL_free(ARRAY_TMPL_unpack_array(ha));
174
Free an array's entries.
176
The storage used must be write locked.
178
static void ARRAY_TMPL_NS(reset)
179
( ARRAY_TMPL_runtime_ptr_t runtime
180
, ARRAY_TMPL_packed_array_ptr_t ha
182
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
184
if(ARRAY_TMPL_items_MEMBER(pa)) {
185
if(ARRAY_TMPL_count_MEMBER(pa)) {
186
if(ARRAY_TMPL_clear_entries(ha, 0, ARRAY_TMPL_count_MEMBER(pa)))
187
pa = ARRAY_TMPL_unpack_array(ha);
188
ARRAY_TMPL_count_MEMBER_SET(pa, 0);
190
ARRAY_TMPL_free(ARRAY_TMPL_unpack_data(ARRAY_TMPL_items_MEMBER(pa)));
191
pa = ARRAY_TMPL_unpack_array(ha);
192
ARRAY_TMPL_items_MEMBER(pa) = ARRAY_TMPL_pack_data(0);
194
ARRAY_TMPL_reserve_MEMBER_SET(pa, 0);
195
ARRAY_TMPL_items_MEMBER_SET(pa, 0);
198
#ifndef ARRAY_TMPL_omit_free
202
The storage used must be write locked.
204
ARRAY_TMPL_prefix void ARRAY_TMPL_NS(free)
205
( ARRAY_TMPL_runtime_ptr_t runtime
206
, ARRAY_TMPL_packed_array_ptr_t ha
208
ARRAY_TMPL_NS(reset)(runtime, ha);
209
ARRAY_TMPL_free(ARRAY_TMPL_unpack_array(ha));
214
Clear (empty) the array.
216
The storage used must be write locked.
218
ARRAY_TMPL_prefix void ARRAY_TMPL_NS(clear)
219
( ARRAY_TMPL_runtime_ptr_t runtime
220
, ARRAY_TMPL_packed_array_ptr_t ha
222
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
223
ARRAY_TMPL_NS(remove_many)(runtime, ha, 0, ARRAY_TMPL_count_MEMBER(pa));
225
/** Make a copy (clone) of another array.
227
The storage used must be write locked.
229
The destination array must be initialised first.
231
If the destination array isn't empty, it is cleared.
233
If the allocator runs out of memory, the copy is cleared and clone() fails.
235
This is a "shallow copy" of the raw array data.
237
You may need to take extra steps to ensure that the copy is a consistant shallow
240
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(clone)
241
( ARRAY_TMPL_runtime_ptr_t runtime
242
, ARRAY_TMPL_packed_array_ptr_t ha_to
243
, ARRAY_TMPL_packed_array_ptr_t ha_from
245
ARRAY_TMPL_array_ptr_t pa_to = ARRAY_TMPL_unpack_array(ha_to);
246
if(ARRAY_TMPL_items_MEMBER(pa_to))
247
ARRAY_TMPL_NS(clear)(runtime, ha_to);
248
ARRAY_TMPL_array_ptr_t pa_from = ARRAY_TMPL_unpack_array(ha_from);
249
if(ARRAY_TMPL_NS(init)(runtime, ha_to, ARRAY_TMPL_count_MEMBER(pa_from)
250
, ARRAY_TMPL_increment_MEMBER(pa_to)))
252
pa_to = ARRAY_TMPL_unpack_array(ha_to);
253
pa_from = ARRAY_TMPL_unpack_array(ha_from);
254
ARRAY_TMPL_memcopy(ARRAY_TMPL_item_ptr(pa_to, 0)
255
, ARRAY_TMPL_item_ptr(pa_from, 0)
256
, ARRAY_TMPL_count_MEMBER(pa_from) * ARRAY_TMPL_entry_size);
259
#ifndef ARRAY_TMPL_omit_insert
263
The storage used must be write locked.
265
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(insert)
266
( ARRAY_TMPL_runtime_ptr_t runtime
267
, ARRAY_TMPL_packed_array_ptr_t ha
268
, ARRAY_TMPL_size_t where
269
, ARRAY_TMPL_input_t d
271
if(ARRAY_TMPL_exceeds_count_limit(where))
273
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
274
if(where > ARRAY_TMPL_count_MEMBER(pa))
276
if(ARRAY_TMPL_count_MEMBER(pa) < ARRAY_TMPL_reserve_MEMBER(pa)) {
277
; /* We have room to expand */
279
ARRAY_TMPL_count_t nitems
280
= V3C_ROUND_UP_T(ARRAY_TMPL_count_t, ARRAY_TMPL_count_MEMBER(pa) + 1
281
, ARRAY_TMPL_increment_MEMBER(pa));
282
if(ARRAY_TMPL_realloc_packed(ha, nitems))
284
pa = ARRAY_TMPL_unpack_array(ha);
285
ARRAY_TMPL_reserve_MEMBER_SET(pa, nitems);
287
if(where != ARRAY_TMPL_count_MEMBER(pa))
288
ARRAY_TMPL_memmove(ARRAY_TMPL_item_ptr(pa, where + 1)
289
, ARRAY_TMPL_item_ptr(pa, where)
290
, (ARRAY_TMPL_count_MEMBER(pa) - where) * ARRAY_TMPL_entry_size);
291
ARRAY_TMPL_assign(ARRAY_TMPL_item(pa, where), d);
292
ARRAY_TMPL_count_MEMBER_INCREMENT(pa);
296
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(insert_many)
297
( ARRAY_TMPL_runtime_ptr_t runtime
298
, ARRAY_TMPL_packed_array_ptr_t ha
299
, ARRAY_TMPL_size_t where
300
, ARRAY_TMPL_size_t count
304
if(ARRAY_TMPL_exceeds_count_limit(where + count - 1))
306
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
307
if(where > ARRAY_TMPL_count_MEMBER(pa))
309
if((ARRAY_TMPL_count_MEMBER(pa) + count) <= ARRAY_TMPL_reserve_MEMBER(pa)) {
310
; /* We have room to expand */
312
ARRAY_TMPL_count_t nitems
313
= V3C_ROUND_UP_T(ARRAY_TMPL_count_t
314
, ARRAY_TMPL_count_MEMBER(pa) + count
315
, ARRAY_TMPL_increment_MEMBER(pa));
316
if(ARRAY_TMPL_realloc_packed(ha, nitems))
318
pa = ARRAY_TMPL_unpack_array(ha);
319
ARRAY_TMPL_reserve_MEMBER_SET(pa, nitems);
321
if(where != ARRAY_TMPL_count_MEMBER(pa))
322
ARRAY_TMPL_memmove(ARRAY_TMPL_item_ptr(pa, where + count)
323
, ARRAY_TMPL_item_ptr(pa, where)
324
, (ARRAY_TMPL_count_MEMBER(pa) - where) * ARRAY_TMPL_entry_size);
325
ARRAY_TMPL_count_MEMBER_ADD(pa, count);
328
#ifndef ARRAY_TMPL_omit_remove
329
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(remove)
330
( ARRAY_TMPL_runtime_ptr_t runtime
331
, ARRAY_TMPL_packed_array_ptr_t ha
332
, ARRAY_TMPL_size_t where
334
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
335
if(where >= ARRAY_TMPL_count_MEMBER(pa))
337
if(ARRAY_TMPL_clear_entries(ha, where, 1))
338
pa = ARRAY_TMPL_unpack_array(ha); /* Just in case. */
339
if((where + 1) != ARRAY_TMPL_count_MEMBER(pa))
340
ARRAY_TMPL_memmove(ARRAY_TMPL_item_ptr(pa, where), ARRAY_TMPL_item_ptr(pa, where + 1)
341
, (ARRAY_TMPL_count_MEMBER(pa) - where - 1) * ARRAY_TMPL_entry_size);
342
if(ARRAY_TMPL_count_MEMBER(pa) % ARRAY_TMPL_increment_MEMBER(pa)) {
343
; /* We have room to shrink */
345
ARRAY_TMPL_count_t nitems
346
= V3C_ROUND_UP_T(ARRAY_TMPL_count_t, ARRAY_TMPL_count_MEMBER(pa) - 1
347
, ARRAY_TMPL_increment_MEMBER(pa));
349
if(ARRAY_TMPL_realloc_packed(ha, nitems))
351
pa = ARRAY_TMPL_unpack_array(ha);
353
ARRAY_TMPL_free(ARRAY_TMPL_unpack_data(ARRAY_TMPL_items_MEMBER(pa)));
354
pa = ARRAY_TMPL_unpack_array(ha);
355
ARRAY_TMPL_items_MEMBER(pa) = ARRAY_TMPL_pack_data(0);
357
ARRAY_TMPL_reserve_MEMBER_SET(pa, nitems);
359
ARRAY_TMPL_count_MEMBER_DECREMENT(pa);
363
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(remove_many)
364
( ARRAY_TMPL_runtime_ptr_t runtime
365
, ARRAY_TMPL_packed_array_ptr_t ha
366
, ARRAY_TMPL_size_t where
367
, ARRAY_TMPL_size_t count
371
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
372
if((where + count) > ARRAY_TMPL_count_MEMBER(pa))
374
if(ARRAY_TMPL_clear_entries(ha, where, count))
375
pa = ARRAY_TMPL_unpack_array(ha); /* Just in case. */
376
if((where + count) != ARRAY_TMPL_count_MEMBER(pa))
377
ARRAY_TMPL_memmove(ARRAY_TMPL_item_ptr(pa, where)
378
, ARRAY_TMPL_item_ptr(pa, where + count)
379
, (ARRAY_TMPL_count_MEMBER(pa) - where - count) * ARRAY_TMPL_entry_size);
380
if(((ARRAY_TMPL_count_MEMBER(pa) - count) / ARRAY_TMPL_increment_MEMBER(pa))
381
== (ARRAY_TMPL_count_MEMBER(pa) / ARRAY_TMPL_increment_MEMBER(pa))) {
382
; /* We have room to shrink */
384
ARRAY_TMPL_count_t nitems = V3C_ROUND_UP_T(ARRAY_TMPL_count_t
385
, ARRAY_TMPL_count_MEMBER(pa) - count, ARRAY_TMPL_increment_MEMBER(pa));
387
if(ARRAY_TMPL_realloc_packed(ha, nitems))
389
pa = ARRAY_TMPL_unpack_array(ha);
391
ARRAY_TMPL_free(ARRAY_TMPL_unpack_data(ARRAY_TMPL_items_MEMBER(pa)));
392
pa = ARRAY_TMPL_unpack_array(ha);
393
ARRAY_TMPL_items_MEMBER(pa) = ARRAY_TMPL_pack_data(0);
395
ARRAY_TMPL_reserve_MEMBER_SET(pa, nitems);
397
ARRAY_TMPL_count_MEMBER_SUBTRACT(pa, count);
400
#ifndef ARRAY_TMPL_omit_push_back
401
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(push_back)
402
( ARRAY_TMPL_runtime_ptr_t runtime
403
, ARRAY_TMPL_packed_array_ptr_t ha
404
, ARRAY_TMPL_input_t d
406
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
407
return ARRAY_TMPL_NS(insert)(runtime, ha, ARRAY_TMPL_count_MEMBER(pa), d);
410
#ifndef ARRAY_TMPL_omit_push_back_many
411
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(push_back_many)
412
( ARRAY_TMPL_runtime_ptr_t runtime
413
, ARRAY_TMPL_packed_array_ptr_t ha
414
, ARRAY_TMPL_size_t count
416
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
417
return ARRAY_TMPL_NS(insert_many)(runtime, ha, ARRAY_TMPL_count_MEMBER(pa), count);
420
#ifndef ARRAY_TMPL_omit_push_front
421
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(push_front)
422
( ARRAY_TMPL_runtime_ptr_t runtime
423
, ARRAY_TMPL_packed_array_ptr_t ha
424
, ARRAY_TMPL_input_t d
426
return ARRAY_TMPL_NS(insert)(runtime, ha, 0, d);
429
#ifndef ARRAY_TMPL_omit_push_front_many
430
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(push_front_many)
431
( ARRAY_TMPL_runtime_ptr_t runtime
432
, ARRAY_TMPL_packed_array_ptr_t ha
433
, ARRAY_TMPL_size_t count
435
return ARRAY_TMPL_NS(insert_many)(runtime, ha, 0, count);
438
#ifndef ARRAY_TMPL_omit_pop_back
439
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(pop_back)
440
( ARRAY_TMPL_runtime_ptr_t runtime
441
, ARRAY_TMPL_packed_array_ptr_t ha
443
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
444
return ARRAY_TMPL_NS(remove)(runtime, ha, ARRAY_TMPL_count_MEMBER(pa) - 1);
447
#ifndef ARRAY_TMPL_omit_pop_back_many
448
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(pop_back_many)
449
( ARRAY_TMPL_runtime_ptr_t runtime
450
, ARRAY_TMPL_packed_array_ptr_t ha
451
, ARRAY_TMPL_size_t count
453
ARRAY_TMPL_array_ptr_t pa = ARRAY_TMPL_unpack_array(ha);
454
return ARRAY_TMPL_NS(remove_many)(runtime, ha, ARRAY_TMPL_count_MEMBER(pa) - count
458
#ifndef ARRAY_TMPL_omit_pop_front
459
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(pop_front)
460
( ARRAY_TMPL_runtime_ptr_t runtime
461
, ARRAY_TMPL_packed_array_ptr_t ha
463
return ARRAY_TMPL_NS(remove)(runtime, ha, 0);
466
#ifndef ARRAY_TMPL_omit_pop_front_many
467
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(pop_front_many)
468
( ARRAY_TMPL_runtime_ptr_t runtime
469
, ARRAY_TMPL_packed_array_ptr_t ha
470
, ARRAY_TMPL_size_t count
472
return ARRAY_TMPL_NS(remove_many)(runtime, ha, 0, count);
475
#ifndef ARRAY_TMPL_omit_reverse_some
476
/** ARRAY_TMPL_NS(reverse_some)
478
Unfortunately there's no equivalent for ARRAY_TMPL_clear_entries here.
480
ARRAY_TMPL_prefix int ARRAY_TMPL_NS(reverse_some)
481
( ARRAY_TMPL_runtime_ptr_t runtime
482
, ARRAY_TMPL_array_ptr_t pa
483
, ARRAY_TMPL_size_t lower
484
, ARRAY_TMPL_size_t count
487
/* count includes the first item. */
488
if((lower + count) > ARRAY_TMPL_count_MEMBER(pa))
490
ARRAY_TMPL_count_t n, num = count/2, upper = lower + count - 1;
491
for(n = 0; n < num; ++n) {
492
ARRAY_TMPL_auto_data(item1);
493
ARRAY_TMPL_auto_data(item2);
494
ARRAY_TMPL_assign_to_auto(item1, ARRAY_TMPL_item(pa, lower));
495
ARRAY_TMPL_assign_to_auto(item2, ARRAY_TMPL_item(pa, upper));
496
/*printf("swapping %lu[%u] and %lu[%u].\n", (size_t)(lower)
497
, item1, (size_t)(upper), item2);*/
498
ARRAY_TMPL_assign_from_auto(ARRAY_TMPL_item(pa, lower), item2);
499
ARRAY_TMPL_assign_from_auto(ARRAY_TMPL_item(pa, upper), item1);
506
#ifndef ARRAY_TMPL_omit_reverse
507
ARRAY_TMPL_prefix void ARRAY_TMPL_NS(reverse)
508
( ARRAY_TMPL_runtime_ptr_t runtime
509
, ARRAY_TMPL_array_ptr_t pa
511
(void)ARRAY_TMPL_NS(reverse_some)(runtime, pa, 0, ARRAY_TMPL_count_MEMBER(pa));