BAM
Abstract Machine for Bottom-Up Evaluation with the Push Method
flexarr.h
Go to the documentation of this file.
1 // ============================================================================
2 // Project: Deductive Database
3 // Filename: flexarr.h
4 // Purpose: Flexible array / List with index access (Class Template)
5 // Last Change: 04.08.2017
6 // Language: C++
7 // EMail: brass@informatik.uni-halle.de
8 // WWW: http://www.informatik.uni-halle.de/~brass/
9 // Address: Feldschloesschen 15, D-06120 Halle (Saale), GERMANY
10 // Copyright: (c) 2015-2017 by Stefan Brass
11 // License: See file "LICENSE" for copying conditions.
12 // Note: There is no warranty at all - this code may contain bugs.
13 // ============================================================================
14 
15 
27 //=============================================================================
28 // Include File Frame:
29 //=============================================================================
30 
31 #ifndef FLEXARR_INCLUDED
32 #define FLEXARR_INCLUDED
33 
34 //=============================================================================
35 // Used Types and Macros:
36 //=============================================================================
37 
38 #ifndef VER_INCLUDED
39 #include "../base/ver.h"
40 #endif
41 
42 #ifndef STR_INCLUDED
43 #include "../base/str.h"
44 #endif
45 
46 #ifndef ERR_INCLUDED
47 #include "../base/err.h"
48 #endif
49 
50 #ifndef CHECK_INCLUDED
51 #include "../base/check.h"
52 #endif
53 
54 #ifndef PAGE_INCLUDED
55 #include "../mem/page.h"
56 #endif
57 
58 #ifndef MPOOL_INCLUDED
59 #include "../mem/mpool.h"
60 #endif
61 
62 
63 //=============================================================================
64 // Private Constants:
65 //=============================================================================
66 
67 //-----------------------------------------------------------------------------
68 // FLEXARR_MAGIC: Magic number (identifies objects of this class).
69 //-----------------------------------------------------------------------------
70 
71 static const long FLEXARR_MAGIC = 0x464C450AL; // 'FLE\n'
72 
73 //-----------------------------------------------------------------------------
74 // Null Pointers:
75 //-----------------------------------------------------------------------------
76 
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))
80 
81 
82 //=============================================================================
84 //=============================================================================
85 
86 template<class T> class flexarr_c {
87  public:
88 
89 //-----------------------------------------------------------------------------
90 // Constructor, Destructor:
91 //-----------------------------------------------------------------------------
92 
93  // Constructor:
94  flexarr_c(mpool_t mem_pool)
95  {
96  // Check parameter:
97  CHECK_PAR(mem_pool, "flexarr_c::constructor");
98 
99  // Initialize attributes:
100  Length = 0;
101  Height = 0;
102  CurrLeafNode = FLEXARR_LEAF_NULL;
103  CurrMidNode = FLEXARR_MID_NULL;
104  CurrTopNode = FLEXARR_TOP_NULL;
105  CurrLeafIndex = 0;
106  CurrMidIndex = 0;
107  CurrTopIndex = 0;
108  MemPool = mem_pool;
109  NumPages = 0;
110  UnusedPage1 = PAGE_NULL;
111  UnusedPage2 = PAGE_NULL;
112 
113  // Set Magic number:
114  CHECK_CODE(Magic = FLEXARR_MAGIC);
115  }
116 
117  // Destructor:
118  ~flexarr_c()
119  {
120  // Check this object:
121  CHECK_VALID("flexarr_c::destructor");
122 
123  // Make this object invalid:
124  CHECK_CODE(Magic = 0);
125  }
126 
127 //-----------------------------------------------------------------------------
128 // Copy-constructor and assignment operator are not supported for this class:
129 //-----------------------------------------------------------------------------
130 
131  private:
132 
133  flexarr_c(const flexarr_c& obj); // Not implemented
134  flexarr_c& operator=(const flexarr_c& obj); // Not implemented
135 
136 //=============================================================================
137 // Auxiliary Methods for Memory Page Management:
138 //=============================================================================
139 
140  private:
141 
142  // This handles the following problem:
143  // When a memory page allocation fails,
144  // we want to restore the state before the operation.
145  // However, append might have to allocate three memory pages,
146  // and if the last allocation fails, there are two unused memory pages.
147  // This is not a real memory leak, because the pages are stored
148  // in the memory pool, and the memory pool will free them
149  // when it is destroyed.
150  //
151  // It is also unlikely that a memory page allocation fails,
152  // and later it works again (in which case every append might
153  // allocate two unused pages in the worst case).
154  //
155  // However, to be very correct, we remember the unused pages
156  // in this object, and use them in the next memory allocation,
157  // before we allocate new pages from the memory pool.
158  // In this way, there can never be more than two unused pages
159  // in this object.
160  //
161  // Of course, if this object should be destroyed, it is important
162  // that the memory pool is destroyed, too.
163  // Because this object is used as part of a string table,
164  // which has a common memory pool for all its parts, this works
165  // (all parts are destroyed together).
166  //
167  // If one uses the flexible array in other contexts, one must make
168  // sure that the memory pool is destroyed whenever this object is
169  // destroyed. Otherwise there will be a memory leak.
170 
171 //-----------------------------------------------------------------------------
172 // alloc_page: Get a memory page.
173 //-----------------------------------------------------------------------------
174 
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;
181  return page;
182  }
183 
184 //-----------------------------------------------------------------------------
185 // free_page: De-allocate a memory page.
186 //-----------------------------------------------------------------------------
187 
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)
191  UnusedPage1 = page;
192  else {
193  CHECK(UnusedPage2 == PAGE_NULL,
194  "flexarr_c::free_page: too many pages");
195  UnusedPage2 = page;
196  }
197  }
198 
199 //=============================================================================
200 // (Object) Methods:
201 //=============================================================================
202 
203  public:
204 
205 //-----------------------------------------------------------------------------
206 // append: Append new element to the array (at the end). Returns index.
207 //-----------------------------------------------------------------------------
208 
209  inline int append(T elem) {
210  page_t page;
211 
212  // Ensure that object is valid:
213  CHECK_VALID("flexarr_c::append");
214 
215  // Most common case: Add elem to current leaf node:
216  if(CurrLeafIndex > 0) {
217  CurrLeafNode[--CurrLeafIndex] = elem;
218  return Length++;
219  }
220 
221  // Allocate first leaf:
222  if(CurrLeafNode == FLEXARR_LEAF_NULL) { // i.e. Height == 0
223  page = alloc_page();
224  if(page == PAGE_NULL)
225  return -1;
226  NumPages++;
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;
232  Height = 1;
233  Length = 1; // Length was 0,
234  return 0; // could also write Length++ here.
235  }
236 
237  // There is a leaf node, but it is full:
238  CHECK(CurrLeafNode != FLEXARR_LEAF_NULL,
239  "flexarr_c::append: LeafNode is NULL");
240  CHECK(CurrLeafIndex == 0,
241  "flexarr_c::append: LeafIndex not 0");
242 
243  // Remember old leaf node in case there is no mid node:
244  T* old_leaf_node = CurrLeafNode;
245 
246  // Allocate new leaf node:
247  page = alloc_page();
248  if(page == PAGE_NULL)
249  return -1;
250  NumPages++;
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;
256 
257  // Now we must enter the new leaf node to the mid branch level
258  // In case there was no mid branch level before, both nodes,
259  // the old leaf node and the new leaf node must be entered
260  // to the first mid level branch node.
261 
262  // Construct first mid level branch node:
263  if(CurrMidNode == FLEXARR_MID_NULL) {
264  page = alloc_page();
265  if(page == PAGE_NULL) {
266  // Restore state before failed append:
267  free_page(CurrLeafNode);
268  CurrLeafNode = old_leaf_node;
269  CurrLeafIndex = 0;
270  return -1;
271  }
272  NumPages++;
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;
279  Height = 2;
280  return Length++;
281  }
282 
283  // There is a mid level branch node and it is not yet full:
284  else if(CurrMidIndex > 0) {
285  CurrMidNode[--CurrMidIndex] = CurrLeafNode;
286  return Length++;
287  }
288 
289  // There is a mid level branch node, but it is full:
290  CHECK(CurrMidNode != FLEXARR_MID_NULL,
291  "flexarr_c::append: MidNode is NULL");
292  CHECK(CurrMidIndex == 0,
293  "flexarr_c::append: MidIndex not 0");
294 
295  // Construct additional (not first) mid level branch node:
296  page = alloc_page();
297  if(page == PAGE_NULL) {
298  // Restore state before failed append:
299  free_page(CurrLeafNode);
300  CurrLeafNode = old_leaf_node;
301  CurrLeafIndex = 0;
302  return -1;
303  }
304  NumPages++;
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;
311 
312  // Now we must enter the new mid node to top level
313  // (because it is not the first / only one).
314  // Simple case: There is already a top node.
315  if(CurrTopNode != FLEXARR_TOP_NULL) {
316  // If it has no space, we would need another level,
317  // which is not implemented:
318  if(CurrTopIndex <= 0) {
319  free_page(CurrLeafNode);
320  CurrLeafNode = old_leaf_node;
321  CurrLeafIndex = 0;
322  free_page(CurrMidNode);
323  CurrMidNode = old_mid_node;
324  CurrMidIndex = 0;
325  err_c::flexarr_capacity_limit(MemPool->name(),
326  Length);
327  return -1;
328  }
329  CurrTopNode[--CurrTopIndex] = CurrMidNode;
330  return Length++;
331  }
332 
333  // Finally handle the case that there is no top level node yet.
334  // Construct one (there will always be only one):
335  CHECK(CurrTopNode == FLEXARR_TOP_NULL,
336  "flexarr_c::append: CurrTopNode is not null");
337  page = alloc_page();
338  if(page == PAGE_NULL) {
339  // Restore state before failed append:
340  free_page(CurrLeafNode);
341  CurrLeafNode = old_leaf_node;
342  CurrLeafIndex = 0;
343  free_page(CurrMidNode);
344  CurrMidNode = old_mid_node;
345  CurrMidIndex = 0;
346  return -1;
347  }
348  NumPages++;
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;
355  Height = 3;
356  return Length++;
357  }
358 
359 //-----------------------------------------------------------------------------
360 // ptr: Get pointer to element at a given index.
361 //-----------------------------------------------------------------------------
362 
363  inline T* ptr(int i) const {
364  // Ensure that object is valid:
365  CHECK_VALID("flexarr_c::ptr");
366 
367  // Ensure that parameter (index) is valid:
368  CHECK(i >= 0, "flexarr_c::ptr: Index is negative");
369  CHECK(i < Length, "flexarr_c::ptr: Index is too large");
370 
371  // Height 1: There is only a single leaf node:
372  if(Height == 1) {
373  // Actual indexes start at end of page:
374  int index = (PAGE_SIZE(T) - 1) - i;
375 
376  // Get data value from leaf node (Root):
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]);
383  }
384 
385  // Height 2: Mid Level Node is Root
386  if(Height == 2) {
387  // Split index into parts for different tree levels:
388  int mid_index = i / PAGE_SIZE(T);
389  int leaf_index = i % PAGE_SIZE(T);
390 
391  // Actual indexes start at end of page:
392  leaf_index = (PAGE_SIZE(T) - 1) - leaf_index;
393  mid_index = (PAGE_SIZE(T*) - 1) - mid_index;
394 
395  // Get leaf node from CurrMidNode (Root):
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];
402 
403  // Get data value from leaf node:
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]);
412  }
413 
414  // Height 3:
415  if(Height == 3) {
416  // Split index into parts for different tree levels:
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*);
421 
422  // Actual indexes start at end of page:
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;
426 
427  // Get mid level node from CurrTopNode (Root):
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];
434 
435  // Get leaf node from mid level node:
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];
444 
445  // Get data value from leaf node:
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]);
454  }
455 
456  // Greater Heights are not implemented:
457  CHECK_IMPOSSIBLE("flexarr_c::ptr: Invalid Height");
458  return 0;
459  }
460 
461 //-----------------------------------------------------------------------------
462 // get: Get element at a given index.
463 //-----------------------------------------------------------------------------
464 
465  inline T get(int i) const {
466  // Ensure that object is valid:
467  CHECK_VALID("flexarr_c::get");
468 
469  // Ensure that parameter (index) is valid:
470  CHECK(i >= 0, "flexarr_c::get: Index is negative");
471  CHECK(i < Length, "flexarr_c::get: Index is too large");
472 
473  // The real work is done in Method ptr:
474  return *(ptr(i));
475  }
476 
477 
478 //-----------------------------------------------------------------------------
479 // length: Get the current length (number of elements) of this array.
480 //-----------------------------------------------------------------------------
481 
482  int length() const {
483  return Length;
484  }
485 
486 //-----------------------------------------------------------------------------
487 // num_pages: Get the number of pages used for this flexible array.
488 //-----------------------------------------------------------------------------
489 
490  int num_pages() const {
491  return NumPages;
492  }
493 
494 //=============================================================================
495 // Debugging Support:
496 //=============================================================================
497 
498 //-----------------------------------------------------------------------------
499 // check: Check the integrity of this object, return error message or NULL.
500 //-----------------------------------------------------------------------------
501 
502 #if VER_DEBUG
503  // Integrity check:
504  public:
505  str_t check() const {
506 
507  // Check magic number:
508  if(Magic != FLEXARR_MAGIC)
509  return "wrong magic number";
510 
511  // Check length and indexes:
512  if(Length < 0)
513  return "Length is negative";
514  if(CurrLeafIndex < 0)
515  return "CurrLeafIndex is negative";
516  if(CurrMidIndex < 0)
517  return "CurrMidIndex is negative";
518  if(CurrTopIndex < 0)
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";
526 
527  // Check by height:
528  switch(Height) {
529  case 0:
530  if(Length != 0)
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";
544  break;
545  case 1:
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";
558  break;
559  case 2:
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";
570  break;
571  case 3:
572  if(Length > PAGE_SIZE(T) * PAGE_SIZE(T*)
573  * 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";
581  break;
582  default:
583  return "Invalid height";
584  }
585 
586  // Ok:
587  return STR_NULL;
588  }
589 
590  // Magic number (identifies objects of this class for debugging).
591  private:
592  long Magic; // Must be "FLEXARR_MAGIC".
593 #endif
594 
595 //-----------------------------------------------------------------------------
596 // dump: Show data structure.
597 //-----------------------------------------------------------------------------
598 
599 #if VER_DUMP
600 
601  public:
602 
603 void dump(str_t headline = STR_NULL) const
604 {
605  // Headline:
606  if(headline == STR_NULL)
607  headline = "Flexible Array";
608  err_c::dump_begin(headline);
609 
610  // Basic information:
611  err_c::dump_str("MemPool Name: '");
612  err_c::dump_str(MemPool->name());
613  err_c::dump_str("'");
614  err_c::dump_nl();
615  err_c::dump_str("Length: ");
616  err_c::dump_int(Length);
617  err_c::dump_nl();
618  err_c::dump_str("Height: ");
619  err_c::dump_int(Height);
620  err_c::dump_nl();
621  err_c::dump_str("NumPages: ");
622  err_c::dump_int(NumPages);
623  err_c::dump_nl();
624  err_c::dump_str("Page Size: ");
626  err_c::dump_str(" Bytes");
627  err_c::dump_nl();
628  err_c::dump_str("PAGE_SIZE(T): ");
629  err_c::dump_int(PAGE_SIZE(T));
630  err_c::dump_nl();
631  err_c::dump_str("PAGE_SIZE(T*): ");
632  err_c::dump_int(PAGE_SIZE(T*));
633  err_c::dump_nl();
634  err_c::dump_str("CurrLeafIndex: ");
635  err_c::dump_int(CurrLeafIndex);
636  err_c::dump_nl();
637  err_c::dump_str("CurrMidIndex: ");
638  err_c::dump_int(CurrMidIndex);
639  err_c::dump_nl();
640  err_c::dump_str("CurrTopIndex: ");
641  err_c::dump_int(CurrTopIndex);
642  err_c::dump_nl();
643  err_c::dump_str("CurrLeafNode: ");
644  err_c::dump_ptr(CurrLeafNode);
645  err_c::dump_nl();
646  err_c::dump_str("CurrMidNode: ");
647  err_c::dump_ptr(CurrMidNode);
648  err_c::dump_nl();
649  err_c::dump_str("CurrTopNode: ");
650  err_c::dump_ptr(CurrTopNode);
651  err_c::dump_nl();
652  err_c::dump_nl();
653 
654  // Done:
655  err_c::dump_end();
656 }
657 
658 #endif
659 
660 
661 //=============================================================================
662 // Private Object Members:
663 //=============================================================================
664 
665  private:
666 
667  // Length: Number of elements in the array / list.
668  int Length;
669 
670  // Height: Height of the radix tree implementing the flexible array.
671  int Height; // Can only be 0 (empty tree), 1 (only leaf), 2, 3.
672 
673  // Current/Rightmost Leaf Node
674  T *CurrLeafNode; // If Height == 1, this is the root.
675 
676  // CurrMid: Current/Rightmost Branch Node One Level Above Leaves.
677  T **CurrMidNode; // If Height == 2, this is the root.
678 
679  // CurrTop: Branch node two Levels Above Leaves
680  T ***CurrTopNode; // Root for Height == 3. Otherwise unused.
681 
682  // CurrLeafIndex: Last used index in CurrLeafNode
683  int CurrLeafIndex;
684 
685  // CurrMidIndex: Last used index in CurrMidNode
686  int CurrMidIndex;
687 
688  // CurrTopIndex: Last used index in CurrTopNode
689  int CurrTopIndex;
690 
691  // MemPool: Memory pool from which new nodes are allocated.
692  mpool_t MemPool;
693 
694  // Unused pages left over from a failed append operation:
695  page_t UnusedPage1;
696  page_t UnusedPage2;
697 
698  // Number of memory pages used:
699  int NumPages;
700 
701 //=============================================================================
702 // End of Class Template:
703 //=============================================================================
704 
705 };
706 
707 
708 //=============================================================================
709 // End of Include File:
710 //=============================================================================
711 
712 #endif
713 
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
Definition: mpool.h:103
#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