Mem Extended.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /******************************************************************************
  2. Use 'Memx' for extended block based dynamic array container.
  3. 'Memx' preserves elements memory address in every operation.
  4. 'Memx' stores elements in blocks, however unlike 'Memb' it allows to have "holes" between elements, for example:
  5. block 0: [A.CD]
  6. block 1: [.F.H]
  7. block 2: [IJ..]
  8. ..
  9. Creating new elements in 'Memx' container does not change the memory address of its elements.
  10. Only new blocks are allocated when needed.
  11. Removing existing elements does not change the memory address of its elements.
  12. Removed elements are marked as invalid ("holes").
  13. /******************************************************************************/
  14. T1(TYPE) struct Memx : _Memx // Block Based Extended Container
  15. {
  16. // manage
  17. Memx& clear(); // remove all elements
  18. Memx& del (); // remove all elements and free helper memory
  19. // get / set
  20. Int absElms ()C; // number of absolute elements
  21. Int validElms ()C; // number of valid elements
  22. Int elms ()C; // number of valid elements
  23. UInt elmSize ()C; // size of element
  24. UInt memUsage()C; // memory usage
  25. TYPE& absElm (Int i) ; // get i-th absolute element
  26. C TYPE& absElm (Int i)C; // get i-th absolute element
  27. TYPE& validElm (Int i) ; // get i-th valid element
  28. C TYPE& validElm (Int i)C; // get i-th valid element
  29. TYPE* addr (Int i) ; // get i-th valid element address, null is returned if index is out of range
  30. C TYPE* addr (Int i)C; // get i-th valid element address, null is returned if index is out of range
  31. TYPE& operator[](Int i) ; // get i-th valid element
  32. C TYPE& operator[](Int i)C; // get i-th valid element
  33. TYPE& first ( ) ; // get first valid element
  34. C TYPE& first ( )C; // get first valid element
  35. TYPE& last ( ) ; // get last valid element
  36. C TYPE& last ( )C; // get last valid element
  37. TYPE& New ( ) ; // create new element, this method does not change the memory address of any of the elements
  38. TYPE& NewAt (Int i) ; // create new element at i-th valid index, all old element valid indexes starting from i-th position will be moved to the right, this method does not change the memory address of any of the elements
  39. Int validToAbsIndex( Int valid)C; // convert valid to absolute index, -1 on fail
  40. Int absToValidIndex( Int abs)C; // convert absolute to valid index, -1 on fail
  41. Int validIndex (C TYPE *elm)C; // get valid index of element in container, -1 on fail, testing is done by comparing elements memory address only
  42. Int absIndex (C TYPE *elm)C; // get absolute index of element in container, -1 on fail, testing is done by comparing elements memory address only
  43. Bool contains (C TYPE *elm)C; // check if memory container actually contains element , testing is done by comparing elements memory address only
  44. // remove
  45. Memx& removeAbs ( Int i , Bool keep_order=false); // remove i-th absolute element , if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  46. Memx& removeValid( Int i , Bool keep_order=false); // remove i-th valid element , if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  47. Memx& removeData (C TYPE *elm, Bool keep_order=false); // remove element by giving its memory address, if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  48. Memx& removeLast ( ); // remove last valid element
  49. T1(VALUE) Bool binarySearch (C VALUE &value, Int &index, Int compare(C TYPE &a, C VALUE &b)=Compare)C; // search sorted container for presence of 'value' and return if it was found in the container, 'index'=if the function returned true then this index points to the location where the 'value' is located in the container, if the function returned false then it means that 'value' was not found in the container however the 'index' points to the place where it should be added in the container while preserving sorted data, 'index' will always be in range (0..elms) inclusive
  50. T1(VALUE) Bool binaryHas (C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare)C {Int i; return binarySearch(value, i, compare); } // check if 'value' (using binary search) is present in container
  51. T1(VALUE) TYPE* binaryFind (C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; return binarySearch(value, i, compare) ? &T[i] : null; } // check if 'value' (using binary search) is present in container and return it, null on fail
  52. T1(VALUE) C TYPE* binaryFind (C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare)C {return ConstCast(T).binaryFind(value, compare); } // check if 'value' (using binary search) is present in container and return it, null on fail
  53. T1(VALUE) Memx& binaryAdd (C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; binarySearch(value, i, compare); NewAt (i)=value; return T;} // add 'value' (using binary search) , this method does not change the memory address of any of the elements
  54. T1(VALUE) Bool binaryInclude(C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; if( !binarySearch(value, i, compare)){NewAt (i)=value; return true;} return false;} // include 'value' (using binary search) if it's not already present in container, returns true if value wasn't present and has been added , this method does not change the memory address of any of the elements
  55. T1(VALUE) Bool binaryExclude(C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; if( binarySearch(value, i, compare)){removeValid(i, true); return true;} return false;} // exclude 'value' (using binary search) if present in container , returns true if value was present and has been removed, this method does not change the memory address of any of the elements
  56. T1(VALUE) Bool binaryToggle (C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; if( !binarySearch(value, i, compare)){NewAt (i)=value; return true;} removeValid(i, true); return false;} // toggle 'value' (using binary search) presence in container , returns true if value is now present in container , this method does not change the memory address of any of the elements
  57. // order
  58. Memx& sort(Int compare(C TYPE &a, C TYPE &b)); // sort elements with custom comparing function (sorting modifies only "valid indexes"), this method does not change the memory address of any of the elements
  59. Memx& reverseOrder( ); // reverse order of elements (reversing modifies only "valid indexes"), this method does not change the memory address of any of the elements
  60. Memx& swapOrder(Int i , Int j ); // swap order of 'i' and 'j' valid elements (swapping modifies only "valid indexes"), this method does not change the memory address of any of the elements
  61. Memx& moveElm (Int elm, Int new_index ); // move 'elm' valid element to 'new_index' (moving modifies only "valid indexes"), this method does not change the memory address of any of the elements
  62. Memx& moveToStart (Int elm ); // move 'elm' valid element to the start (moving modifies only "valid indexes"), this method does not change the memory address of any of the elements
  63. Memx& moveToEnd (Int elm ); // move 'elm' valid element to the end (moving modifies only "valid indexes"), this method does not change the memory address of any of the elements
  64. // misc
  65. Memx& operator=(C Mems <TYPE > &src); // copy elements using assignment operator
  66. Memx& operator=(C Memc <TYPE > &src); // copy elements using assignment operator
  67. template<Int size> Memx& operator=(C Memt <TYPE, size> &src); // copy elements using assignment operator
  68. Memx& operator=(C Memb <TYPE > &src); // copy elements using assignment operator
  69. Memx& operator=(C Memx <TYPE > &src); // copy elements using assignment operator
  70. Memx& operator=(C Meml <TYPE > &src); // copy elements using assignment operator
  71. template<Int size> Memx& operator=(C MemPtr<TYPE, size> &src); // copy elements using assignment operator
  72. Memx& operator=( Memx <TYPE > &&src); // copy elements using assignment operator
  73. T1(EXTENDED) Memx& replaceClass(); // replace the type of class stored in the container, all elements are automatically removed before changing the type of the class, the new type must be extended from the base 'TYPE' (if you're receiving a compilation error pointing to this method this means that the new class isn't extended from the base class)
  74. T1(BASE) operator Memx<BASE>&() ; // casting to container of 'BASE' elements, 'TYPE' must be extended from BASE
  75. T1(BASE) operator C Memx<BASE>&()C; // casting to container of 'BASE' elements, 'TYPE' must be extended from BASE
  76. // io
  77. Bool save(File &f); Bool save(File &f)C; // save elements with their own 'save' method, this method first saves number of current elements, and then for each element calls its 'save' method, false on fail
  78. Bool load(File &f); // load elements with their own 'load' method, this method first loads number of saved elements, and then for each element calls its 'load' method, false on fail
  79. explicit Memx(Int block_elms=32); // 'block_elms'=number of elements per block
  80. Memx(C Memx &src );
  81. Memx( Memx &&src );
  82. };
  83. /******************************************************************************/
  84. T1(TYPE) struct MemxAbstract : _Memx // Block Based Extended Container which allows storage of abstract classes, 'replaceClass' should be called before creating new elements in it
  85. {
  86. // manage
  87. MemxAbstract& clear(); // remove all elements
  88. MemxAbstract& del (); // remove all elements and free helper memory
  89. // get / set
  90. Int absElms ()C; // number of absolute elements
  91. Int validElms ()C; // number of valid elements
  92. Int elms ()C; // number of valid elements
  93. UInt elmSize ()C; // size of element
  94. UInt memUsage()C; // memory usage
  95. TYPE& absElm (Int i) ; // get i-th absolute element
  96. C TYPE& absElm (Int i)C; // get i-th absolute element
  97. TYPE& validElm (Int i) ; // get i-th valid element
  98. C TYPE& validElm (Int i)C; // get i-th valid element
  99. TYPE* addr (Int i) ; // get i-th valid element address, null is returned if index is out of range
  100. C TYPE* addr (Int i)C; // get i-th valid element address, null is returned if index is out of range
  101. TYPE& operator[](Int i) ; // get i-th valid element
  102. C TYPE& operator[](Int i)C; // get i-th valid element
  103. TYPE& first ( ) ; // get first valid element
  104. C TYPE& first ( )C; // get first valid element
  105. TYPE& last ( ) ; // get last valid element
  106. C TYPE& last ( )C; // get last valid element
  107. TYPE& New ( ) ; // create new element, this method does not change the memory address of any of the elements
  108. TYPE& NewAt (Int i) ; // create new element at i-th valid index, all old element valid indexes starting from i-th position will be moved to the right, this method does not change the memory address of any of the elements
  109. Int validToAbsIndex( Int valid)C; // convert valid to absolute index, -1 on fail
  110. Int absToValidIndex( Int abs)C; // convert absolute to valid index, -1 on fail
  111. Int validIndex (C TYPE *elm)C; // get valid index of element in container, -1 on fail, testing is done by comparing elements memory address only
  112. Int absIndex (C TYPE *elm)C; // get absolute index of element in container, -1 on fail, testing is done by comparing elements memory address only
  113. Bool contains (C TYPE *elm)C; // check if memory container actually contains element , testing is done by comparing elements memory address only
  114. // remove
  115. MemxAbstract& removeAbs ( Int i , Bool keep_order=false); // remove i-th absolute element , if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  116. MemxAbstract& removeValid( Int i , Bool keep_order=false); // remove i-th valid element , if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  117. MemxAbstract& removeData (C TYPE *elm, Bool keep_order=false); // remove element by giving its memory address, if 'keep_order'=false then "valid index" of last valid element is changed to "valid index" of specified element, if 'keep_order'=true then all "valid indexes" are changed (keeping order), in both cases memory addressess of all elements are preserved (only order of "valid indexes" is handled differently), this method does not change the memory address of any of the elements
  118. MemxAbstract& removeLast ( ); // remove last valid element
  119. T1(EXTENDED) MemxAbstract& replaceClass(); // replace the type of class stored in the container, all elements are automatically removed before changing the type of the class, the new type must be extended from the base 'TYPE' (if you're receiving a compilation error pointing to this method this means that the new class isn't extended from the base class)
  120. T1(BASE) operator Memx<BASE>&() ; // casting to container of 'BASE' elements, 'TYPE' must be extended from BASE
  121. T1(BASE) operator C Memx<BASE>&()C; // casting to container of 'BASE' elements, 'TYPE' must be extended from BASE
  122. explicit MemxAbstract(Int block_elms=32); // 'block_elms'=number of elements per block
  123. };
  124. /******************************************************************************/
  125. inline Int Elms(C _Memx &memx) {return memx.elms();}
  126. /******************************************************************************/