31 #ifndef FLEXARR_INCLUDED
32 #define FLEXARR_INCLUDED
39 #include "../base/ver.h"
43 #include "../base/str.h"
47 #include "../base/err.h"
50 #ifndef CHECK_INCLUDED
51 #include "../base/check.h"
55 #include "../mem/page.h"
58 #ifndef MPOOL_INCLUDED
59 #include "../mem/mpool.h"
71 static const long FLEXARR_MAGIC = 0x464C450AL;
77 #define FLEXARR_LEAF_NULL (static_cast<T*>(PAGE_NULL))
78 #define FLEXARR_MID_NULL (static_cast<T**>(PAGE_NULL))
79 #define FLEXARR_TOP_NULL (static_cast<T***>(PAGE_NULL))
97 CHECK_PAR(mem_pool,
"flexarr_c::constructor");
102 CurrLeafNode = FLEXARR_LEAF_NULL;
103 CurrMidNode = FLEXARR_MID_NULL;
104 CurrTopNode = FLEXARR_TOP_NULL;
110 UnusedPage1 = PAGE_NULL;
111 UnusedPage2 = PAGE_NULL;
175 inline page_t alloc_page() {
176 if(UnusedPage1 == PAGE_NULL)
177 return MemPool->alloc_page();
178 page_t page = UnusedPage1;
179 UnusedPage1 = UnusedPage2;
180 UnusedPage2 = PAGE_NULL;
188 inline void free_page(page_t page) {
189 CHECK(page != PAGE_NULL,
"flexarr_c::free_page: page is NULL");
190 if(UnusedPage1 == PAGE_NULL)
193 CHECK(UnusedPage2 == PAGE_NULL,
194 "flexarr_c::free_page: too many pages");
209 inline int append(T elem) {
216 if(CurrLeafIndex > 0) {
217 CurrLeafNode[--CurrLeafIndex] = elem;
222 if(CurrLeafNode == FLEXARR_LEAF_NULL) {
224 if(page == PAGE_NULL)
227 CurrLeafNode =
reinterpret_cast<T*
>(page);
228 CurrLeafIndex = PAGE_SIZE(T) - 1;
229 CHECK(CurrLeafIndex >= 0,
230 "flexarr_c::append: T too large");
231 CurrLeafNode[CurrLeafIndex] = elem;
238 CHECK(CurrLeafNode != FLEXARR_LEAF_NULL,
239 "flexarr_c::append: LeafNode is NULL");
240 CHECK(CurrLeafIndex == 0,
241 "flexarr_c::append: LeafIndex not 0");
244 T* old_leaf_node = CurrLeafNode;
248 if(page == PAGE_NULL)
251 CurrLeafNode =
reinterpret_cast<T*
>(page);
252 CurrLeafIndex = PAGE_SIZE(T) - 1;
253 CHECK(CurrLeafIndex >= 0,
254 "flexarr_c::append: T too large (2)");
255 CurrLeafNode[CurrLeafIndex] = elem;
263 if(CurrMidNode == FLEXARR_MID_NULL) {
265 if(page == PAGE_NULL) {
267 free_page(CurrLeafNode);
268 CurrLeafNode = old_leaf_node;
273 CurrMidNode =
reinterpret_cast<T**
>(page);
274 CurrMidIndex = PAGE_SIZE(T*) - 1;
275 CHECK(CurrMidIndex > 0,
276 "flexarr_c::append: T* too large");
277 CurrMidNode[CurrMidIndex] = old_leaf_node;
278 CurrMidNode[--CurrMidIndex] = CurrLeafNode;
284 else if(CurrMidIndex > 0) {
285 CurrMidNode[--CurrMidIndex] = CurrLeafNode;
290 CHECK(CurrMidNode != FLEXARR_MID_NULL,
291 "flexarr_c::append: MidNode is NULL");
292 CHECK(CurrMidIndex == 0,
293 "flexarr_c::append: MidIndex not 0");
297 if(page == PAGE_NULL) {
299 free_page(CurrLeafNode);
300 CurrLeafNode = old_leaf_node;
305 T** old_mid_node = CurrMidNode;
306 CurrMidNode =
reinterpret_cast<T**
>(page);
307 CurrMidIndex = PAGE_SIZE(T*) - 1;
308 CHECK(CurrMidIndex >= 0,
309 "flexarr_c::append: T* too large (2)");
310 CurrMidNode[CurrMidIndex] = CurrLeafNode;
315 if(CurrTopNode != FLEXARR_TOP_NULL) {
318 if(CurrTopIndex <= 0) {
319 free_page(CurrLeafNode);
320 CurrLeafNode = old_leaf_node;
322 free_page(CurrMidNode);
323 CurrMidNode = old_mid_node;
329 CurrTopNode[--CurrTopIndex] = CurrMidNode;
335 CHECK(CurrTopNode == FLEXARR_TOP_NULL,
336 "flexarr_c::append: CurrTopNode is not null");
338 if(page == PAGE_NULL) {
340 free_page(CurrLeafNode);
341 CurrLeafNode = old_leaf_node;
343 free_page(CurrMidNode);
344 CurrMidNode = old_mid_node;
349 CurrTopNode =
reinterpret_cast<T***
>(page);
350 CurrTopIndex = PAGE_SIZE(T**) - 1;
351 CHECK(CurrTopIndex > 0,
352 "flexarr_c::append: T** too large");
353 CurrTopNode[CurrTopIndex] = old_mid_node;
354 CurrTopNode[--CurrTopIndex] = CurrMidNode;
363 inline T* ptr(
int i)
const {
368 CHECK(i >= 0,
"flexarr_c::ptr: Index is negative");
369 CHECK(i < Length,
"flexarr_c::ptr: Index is too large");
374 int index = (PAGE_SIZE(T) - 1) - i;
377 CHECK(index >= 0,
"flexarr_c::ptr: H1 Index<0");
378 CHECK(index >= CurrLeafIndex,
379 "flexarr_c::ptr: H1 Index too small");
380 CHECK(CurrLeafNode != FLEXARR_LEAF_NULL,
381 "flexarr_c::ptr: H1 LeafNode is null");
382 return &(CurrLeafNode[index]);
388 int mid_index = i / PAGE_SIZE(T);
389 int leaf_index = i % PAGE_SIZE(T);
392 leaf_index = (PAGE_SIZE(T) - 1) - leaf_index;
393 mid_index = (PAGE_SIZE(T*) - 1) - mid_index;
396 CHECK(mid_index >= 0,
"flexarr_c::ptr: H2 Index<0");
397 CHECK(mid_index >= CurrMidIndex,
398 "flexarr_c::ptr: H2 Index too small");
399 CHECK(CurrMidNode != FLEXARR_MID_NULL,
400 "flexarr_c::ptr: H2 MidNode is null");
401 T* leaf_node = CurrMidNode[mid_index];
404 CHECK(leaf_index >= 0,
405 "flexarr_c::ptr: H2 LeafIndex<0");
406 CHECK(leaf_node != CurrLeafNode ||
407 leaf_index >= CurrLeafIndex,
408 "flexarr_c::ptr: H2 LeafI too small");
409 CHECK(leaf_node != FLEXARR_LEAF_NULL,
410 "flexarr_c::ptr: H2 leaf_node null");
411 return &(leaf_node[leaf_index]);
417 int mid_index = i / PAGE_SIZE(T);
418 int leaf_index = i % PAGE_SIZE(T);
419 int top_index = mid_index / PAGE_SIZE(T*);
420 mid_index = mid_index % PAGE_SIZE(T*);
423 leaf_index = (PAGE_SIZE(T) - 1) - leaf_index;
424 mid_index = (PAGE_SIZE(T*) - 1) - mid_index;
425 top_index = (PAGE_SIZE(T**) - 1) - top_index;
428 CHECK(top_index >= 0,
"flexarr_c::ptr: H3 Index<0");
429 CHECK(top_index >= CurrMidIndex,
430 "flexarr_c::ptr: H3 Index too small");
431 CHECK(CurrTopNode != FLEXARR_TOP_NULL,
432 "flexarr_c::ptr: H3 TopNode is null");
433 T** mid_node = CurrTopNode[top_index];
436 CHECK(mid_index >= 0,
437 "flexarr_c::ptr: H3 MidIndex<0");
438 CHECK(mid_node != CurrMidNode ||
439 mid_index >= CurrMidIndex,
440 "flexarr_c::ptr: H3 MidI too small");
441 CHECK(mid_node != FLEXARR_MID_NULL,
442 "flexarr_c::ptr: H3 mid_node is null");
443 T* leaf_node = mid_node[mid_index];
446 CHECK(leaf_index >= 0,
447 "flexarr_c::ptr: H3 leaf_index<0");
448 CHECK(leaf_node != CurrLeafNode ||
449 leaf_index >= CurrLeafIndex,
450 "flexarr_c::ptr: H3 LeafI too small");
451 CHECK(leaf_node != FLEXARR_LEAF_NULL,
452 "flexarr_c::ptr: H3 leaf_node null");
453 return &(leaf_node[leaf_index]);
465 inline T
get(
int i)
const {
470 CHECK(i >= 0,
"flexarr_c::get: Index is negative");
471 CHECK(i < Length,
"flexarr_c::get: Index is too large");
490 int num_pages()
const {
505 str_t check()
const {
508 if(Magic != FLEXARR_MAGIC)
509 return "wrong magic number";
513 return "Length is negative";
514 if(CurrLeafIndex < 0)
515 return "CurrLeafIndex is negative";
517 return "CurrMidIndex is negative";
519 return "CurrTopIndex is negative";
520 if(CurrLeafIndex >= PAGE_SIZE(T))
521 return "CurrLeafIndex too large";
522 if(CurrMidIndex >= PAGE_SIZE(T*))
523 return "CurrMidIndex too large";
524 if(CurrTopIndex >= PAGE_SIZE(T**))
525 return "CurrTopIndex too large";
531 return "Height 0 - Length != 0";
532 if(CurrLeafNode != FLEXARR_LEAF_NULL)
533 return "Height 0 - Leaf not null";
534 if(CurrMidNode != FLEXARR_MID_NULL)
535 return "Height 0 - Mid not null";
536 if(CurrTopNode != FLEXARR_TOP_NULL)
537 return "Height 0 - Top not null";
538 if(CurrLeafIndex != 0)
539 return "Height 0 - LeafIndex != 0";
540 if(CurrMidIndex != 0)
541 return "Height 0 - MidIndex != 0";
542 if(CurrTopIndex != 0)
543 return "Height 0 - TopIndex != 0";
546 if(Length > PAGE_SIZE(T))
547 return "Height 1 - Length too large";
548 if(CurrLeafNode == FLEXARR_LEAF_NULL)
549 return "Height 1 - Leaf is null";
550 if(CurrMidNode != FLEXARR_MID_NULL)
551 return "Height 1 - Mid not null";
552 if(CurrTopNode != FLEXARR_TOP_NULL)
553 return "Height 1 - Top not null";
554 if(CurrMidIndex != 0)
555 return "Height 1 - MidIndex != 0";
556 if(CurrTopIndex != 0)
557 return "Height 1 - TopIndex != 0";
560 if(Length > PAGE_SIZE(T) * PAGE_SIZE(T*))
561 return "Height 2 - Length too large";
562 if(CurrLeafNode == FLEXARR_LEAF_NULL)
563 return "Height 2 - Leaf is null";
564 if(CurrMidNode == FLEXARR_MID_NULL)
565 return "Height 2 - Mid is null";
566 if(CurrTopNode != FLEXARR_TOP_NULL)
567 return "Height 2 - Top not null";
568 if(CurrTopIndex != 0)
569 return "Height 2 - TopIndex != 0";
572 if(Length > PAGE_SIZE(T) * PAGE_SIZE(T*)
574 return "Height 3 - Length too large";
575 if(CurrLeafNode == FLEXARR_LEAF_NULL)
576 return "Height 3 - Leaf is null";
577 if(CurrMidNode == FLEXARR_MID_NULL)
578 return "Height 3 - Mid is null";
579 if(CurrTopNode == FLEXARR_TOP_NULL)
580 return "Height 3 - Top is null";
583 return "Invalid height";
607 headline =
"Flexible Array";
Class Template for Flexible Arrays (Lists with Index Access)
Definition: flexarr.h:86
#define CHECK_CODE(CODE)
Definition: check.h:167
static void dump_ptr(const void *p)
Definition: err.cpp:791
static void dump_str(str_t str)
Definition: err.cpp:705
#define VER_PAGESIZE
Definition: ver.h:186
#define CHECK_IMPOSSIBLE(MSG)
Definition: check.h:151
#define CHECK_VALID(EX)
Definition: check.h:85
static void dump_begin(str_t headline)
Definition: err.cpp:685
const char * str_t
Definition: str.h:41
#define STR_NULL
Definition: str.h:52
static void flexarr_capacity_limit(str_t name, int curr_length)
Definition: err.cpp:184
static void dump_end()
Definition: err.cpp:811
static void dump_int(int n)
Definition: err.cpp:739
static void dump_nl()
Definition: err.cpp:717
#define CHECK(EX, MSG)
Definition: check.h:69
#define CHECK_PAR(PAR, PLACE)
Definition: check.h:102