Mem Temporary.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /******************************************************************************
  2. Use 'Memt' for temporary memory based dynamic array container.
  3. 'Memt' stores elements in continuous memory, for example:
  4. [ABCDE...]
  5. 'Memt' uses a predefined chunk of memory which is kept on the stack.
  6. Initially this chunk of memory is used for creating new elements, thanks to which, memory allocation is not needed.
  7. If the number of elements becomes bigger than what the chunk can store,
  8. a memory allocation is made, and elements are moved to a new area.
  9. 'Memt' initially (for small number of elements) does not require memory allocation.
  10. 'Memt' container reserves some extra memory for adding new elements.
  11. If creating a new element when there is no extra memory available,
  12. the container will reallocate the whole array into a new bigger one,
  13. thus changing the address of all elements.
  14. 'Memt' is recommended to be used in performance critical operations.
  15. !! Warning: because 'Memt' uses decent amount of stack memory (by default set to 64 KB for each 'Memt')
  16. the application may crash if too many stack 'Memt' objects are used at once on one thread !!
  17. This does not affect 'Memt' objects allocated globally on the heap, or dynamically using memory containers.
  18. Typically thread stacks have 1 MB of memory.
  19. /******************************************************************************/
  20. template<const_mem_addr typename TYPE, Int size> struct Memt // Temporary Memory Based Container, 'TYPE'=type of elements to be stored in this container, 'size'=memory size (in bytes) that can be used for storing the elements without having to allocate any dynamic memory
  21. {
  22. // manage
  23. Memt& clear(); // remove all elements and free helper memory
  24. Memt& del (); // remove all elements and free helper memory
  25. // get / set
  26. Int elms ()C; // number of elements
  27. UInt elmSize ()C; // size of element
  28. UInt memUsage()C; // memory usage
  29. #if EE_PRIVATE
  30. UInt maxElms ()C {return _max_elms;}
  31. TYPE* dataNull() {return elms() ? data() : null;} // get pointer to the start of the elements and null if there are no elements
  32. C TYPE* dataNull()C {return elms() ? data() : null;} // get pointer to the start of the elements and null if there are no elements
  33. #endif
  34. TYPE* data ( ) ; // get pointer to the start of the elements
  35. C TYPE* data ( )C; // get pointer to the start of the elements
  36. TYPE* addr (Int i) ; // get i-th element address, null is returned if index is out of range
  37. C TYPE* addr (Int i)C; // get i-th element address, null is returned if index is out of range
  38. TYPE& operator[](Int i) ; // get i-th element, accessing element out of range is an invalid operation and may cause undefined behavior
  39. C TYPE& operator[](Int i)C; // get i-th element, accessing element out of range is an invalid operation and may cause undefined behavior
  40. TYPE& operator()(Int i) ; // get i-th element, accessing element out of range will cause creation of all elements before it, memory of those elements will be first zeroed before calling their constructor
  41. TYPE& first ( ) ; // get first element
  42. C TYPE& first ( )C; // get first element
  43. TYPE& last ( ) ; // get last element
  44. C TYPE& last ( )C; // get last element
  45. TYPE& New ( ) ; // create new element at the end , this method changes the memory address of all elements
  46. TYPE& NewAt (Int i) ; // create new element at i-th position, all old elements starting from i-th position will be moved to the right, this method changes the memory address of all elements
  47. Int index (C TYPE *elm)C; // get index of element in container, -1 on fail , testing is done by comparing elements memory address only
  48. Bool contains(C TYPE *elm)C; // check if memory container actually contains element, testing is done by comparing elements memory address only
  49. // remove
  50. Memt& removeLast( ); // remove last element , this method does not change the memory address of any of the remaining elements
  51. Memt& remove ( Int i , Bool keep_order=false); // remove i-th element , if 'keep_order'=false then moves the last element to i-th, if 'keep_order'=true then moves all elements after i-th to the left (keeping order), this method may change the memory address of some elements
  52. Memt& removeData(C TYPE *elm, Bool keep_order=false); // remove element by giving its memory address, if 'keep_order'=false then moves the last element to i-th, if 'keep_order'=true then moves all elements after i-th to the left (keeping order), this method may change the memory address of some elements
  53. TYPE popFirst( Bool keep_order=true); // get first element and remove it from the container, if 'keep_order'=true then moves all elements after i-th to the left (keeping order)
  54. TYPE pop (Int i, Bool keep_order=true); // get i-th element and remove it from the container, if 'keep_order'=true then moves all elements after i-th to the left (keeping order)
  55. TYPE pop ( ); // get last element and remove it from the container
  56. Memt& setNum (Int num); // set number of elements to 'num' , this method changes the memory address of all elements
  57. Memt& setNumZero(Int num); // set number of elements to 'num', memory of new elements will be first zeroed before calling their constructor, this method changes the memory address of all elements
  58. Int addNum (Int num); // add 'num' elements, return index of first added element , this method changes the memory address of all elements
  59. Memt& reserve (Int num); // pre-allocate memory for 'num' elements
  60. // values
  61. T1(VALUE) Int find (C VALUE &value )C {REPA(T)if(T[i]==value)return i; return -1; } // check if 'value' is present in container and return its index, -1 if not found
  62. T1(VALUE) Bool has (C VALUE &value )C {return find(value)>=0; } // check if 'value' is present in container
  63. T1(VALUE) Memt& add (C VALUE &value ) {New()=value; return T; } // add 'value' to container , this method changes the memory address of all elements
  64. T1(VALUE) Bool include(C VALUE &value ) {if(!has(value)){add(value); return true;} return false; } // include 'value' if it's not already present in container, returns true if value wasn't present and has been added , this method changes the memory address of all elements
  65. T1(VALUE) Bool exclude(C VALUE &value, Bool keep_order=false) {Int i=find(value); if(i>=0){remove(i, keep_order); return true ;} return false;} // exclude 'value' if present in container , returns true if value was present and has been removed, this method changes the memory address of all elements
  66. T1(VALUE) Bool toggle (C VALUE &value, Bool keep_order=false) {Int i=find(value); if(i>=0){remove(i, keep_order); return false;} add(value); return true ;} // toggle 'value' presence in container , returns true if value is now present in container , this method changes the memory address of all elements
  67. 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
  68. 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
  69. 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
  70. 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
  71. T1(VALUE) Memt& 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 changes the memory address of all elements
  72. 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 changes the memory address of all elements
  73. T1(VALUE) Bool binaryExclude(C VALUE &value, Int compare(C TYPE &a, C VALUE &b)=Compare) {Int i; if( binarySearch(value, i, compare)){remove(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 changes the memory address of all elements
  74. 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;} remove(i, true); return false;} // toggle 'value' (using binary search) presence in container , returns true if value is now present in container , this method changes the memory address of all elements
  75. // order
  76. Memt& sort(Int compare(C TYPE &a, C TYPE &b)); // sort elements with custom comparing function
  77. Memt& reverseOrder( ); // reverse order of elements
  78. Memt& randomizeOrder( ); // randomize order of elements
  79. Memt& rotateOrder(Int offset ); // rotate order of elements, changes the order of elements so "new_index=old_index+offset", 'offset'=offset of moving the original indexes into target indexes (-Inf..Inf)
  80. Memt& swapOrder(Int i , Int j ); // swap order of 'i' and 'j' elements
  81. Memt& moveElm (Int elm, Int new_index ); // move 'elm' element to new position located at 'new_index'
  82. // misc
  83. Memt& operator=(C Mems <TYPE > &src); // copy elements using assignment operator
  84. Memt& operator=(C Memc <TYPE > &src); // copy elements using assignment operator
  85. Memt& operator=(C Memt <TYPE, size> &src); // copy elements using assignment operator (this must be specified even though method below should do the same, because without it compiler will try to use the built-in 'operator=' which will just do raw memory copy)
  86. template<Int src_size> Memt& operator=(C Memt <TYPE, src_size> &src); // copy elements using assignment operator (this will allow copying from 'Memt' with other sizes)
  87. Memt& operator=(C Memb <TYPE > &src); // copy elements using assignment operator
  88. Memt& operator=(C Memx <TYPE > &src); // copy elements using assignment operator
  89. Memt& operator=(C Meml <TYPE > &src); // copy elements using assignment operator
  90. template<Int src_size> Memt& operator=(C MemPtr<TYPE, src_size> &src); // copy elements using assignment operator
  91. #if EE_PRIVATE
  92. void copyTo ( TYPE *dest)C {CopyN(dest , data(), elms()); } // copy raw memory of all elements to 'dest'
  93. Memt& copyFrom(C TYPE *src ) {CopyN(data(), src , elms()); return T;} // copy raw memory of all elements from 'src '
  94. #endif
  95. // io
  96. 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
  97. 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
  98. Bool saveRaw (File &f)C; // save raw memory of elements (number of elements + elements raw memory), false on fail
  99. Bool loadRaw (File &f) ; // load raw memory of elements (number of elements + elements raw memory), false on fail
  100. Bool saveRawData(File &f)C; // save raw memory of elements ( elements raw memory), false on fail
  101. Bool loadRawData(File &f) ; // load raw memory of elements ( elements raw memory), false on fail
  102. #if EE_PRIVATE
  103. Bool loadRawDataFast(File &f); // load raw memory of elements (elements raw memory), without zeroing on fail, false on fail
  104. Bool _saveRaw(File &f)C; // save raw memory of elements (number of elements + elements raw memory), false on fail, deprecated - do not use
  105. Bool _loadRaw(File &f) ; // load raw memory of elements (number of elements + elements raw memory), false on fail, deprecated - do not use
  106. #endif
  107. ~Memt( );
  108. Memt( );
  109. Memt(C Memt &src);
  110. private:
  111. TYPE *_data;
  112. Int _elms, _max_elms;
  113. Byte _temp[size];
  114. };
  115. /******************************************************************************/
  116. template<const_mem_addr typename TYPE, Int Memt_elms> struct MemtN : Memt<TYPE, SIZE(TYPE)*Memt_elms> // Temporary Memory Based Container, 'TYPE'=type of elements to be stored in this container, 'Memt_elms'=number of elements that can be stored without having to allocate any dynamic memory
  117. {
  118. MemtN& operator=(C Mems <TYPE > &src); // copy elements using assignment operator
  119. MemtN& operator=(C Memc <TYPE > &src); // copy elements using assignment operator
  120. template<Int src_size> MemtN& operator=(C Memt <TYPE, src_size> &src); // copy elements using assignment operator (this will allow copying from 'Memt' with other sizes)
  121. MemtN& operator=(C MemtN <TYPE, Memt_elms> &src); // copy elements using assignment operator (this must be specified even though method above should do the same, because without it compiler will try to use the built-in 'operator=' which will just do raw memory copy)
  122. MemtN& operator=(C Memb <TYPE > &src); // copy elements using assignment operator
  123. MemtN& operator=(C Memx <TYPE > &src); // copy elements using assignment operator
  124. MemtN& operator=(C Meml <TYPE > &src); // copy elements using assignment operator
  125. template<Int src_size> MemtN& operator=(C MemPtr<TYPE, src_size> &src); // copy elements using assignment operator
  126. };
  127. /******************************************************************************/
  128. template<typename TYPE, Int size> inline Int Elms(C Memt<TYPE, size> &memt) {return memt.elms();}
  129. /******************************************************************************/
  130. #if EE_PRIVATE
  131. inline UIntPtr MemtMemUsage(UIntPtr mem, UInt stack=65536) {return mem>stack ? mem : 0;}
  132. #endif
  133. /******************************************************************************/