Mem Block.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. void _Memb::_reset(Int elm_size, Int block_elms, void (*_new)(Ptr elm), void (*_del)(Ptr elm))
  6. {
  7. T.~_Memb();
  8. new(this)_Memb(elm_size, block_elms, _new, _del);
  9. }
  10. _Memb::_Memb(Int elm_size, Int block_elms, void (*_new)(Ptr elm), void (*_del)(Ptr elm))
  11. {
  12. T._ptr =null;
  13. T._elms =0;
  14. T._blocks=0;
  15. T._elm_size =elm_size;
  16. T._block_elms=Max (1, CeilPow2(block_elms));
  17. T._shr =BitHi(blockElms());
  18. T._new =_new;
  19. T._del =_del;
  20. }
  21. /******************************************************************************/
  22. void _Memb::clear()
  23. {
  24. if(_del)REPA(T)_del(T[i]);
  25. _elms=0;
  26. }
  27. void _Memb::del()
  28. {
  29. clear();
  30. REP(_blocks)Free(_ptr[i]); Free(_ptr);
  31. _blocks=0;
  32. }
  33. void _Memb::reset() // remove all elements and leave the first block if it exists
  34. {
  35. clear();
  36. if(_blocks>1)
  37. {
  38. for(Int i=_blocks; --i>=1; )Free(_ptr[i]); // release all blocks except #0
  39. Realloc(_ptr, 1, _blocks);
  40. _blocks=1;
  41. }
  42. }
  43. /******************************************************************************/
  44. void _Memb::setNum(Int num)
  45. {
  46. MAX(num, 0);
  47. if (num>elms()) // add elements
  48. {
  49. Int old_elms = elms(); _elms=num;
  50. Int new_blocks=(elms()+blockElms()-1)>>_shr;
  51. if( new_blocks>_blocks)
  52. {
  53. if(!elmSize())Exit("Attempting to create an object of zero size in 'Memb' container.\nThe container is not initialized or it is abstract and 'replaceClass' hasn't been called.");
  54. new_blocks=CeilPow2(new_blocks);
  55. Realloc(_ptr, new_blocks, _blocks);
  56. REP(new_blocks-_blocks)_ptr[_blocks++]=Alloc(blockSize());
  57. }
  58. if(_new)for(Int i=old_elms; i<elms(); i++)_new(T[i]);
  59. }else
  60. if(num<elms()) // remove elements
  61. {
  62. if(_del)for(Int i=elms(); --i>=num; )_del(T[i]);
  63. _elms=num;
  64. }
  65. }
  66. void _Memb::setNumZero(Int num)
  67. {
  68. MAX(num, 0);
  69. if (num>elms()) // add elements
  70. {
  71. Int old_elms = elms(); _elms=num;
  72. Int new_blocks=(elms()+blockElms()-1)>>_shr;
  73. if( new_blocks>_blocks)
  74. {
  75. if(!elmSize())Exit("Attempting to create an object of zero size in 'Memb' container.\nThe container is not initialized or it is abstract and 'replaceClass' hasn't been called.");
  76. new_blocks=CeilPow2(new_blocks);
  77. Realloc(_ptr, new_blocks, _blocks);
  78. REP(new_blocks-_blocks)_ptr[_blocks++]=Alloc(blockSize());
  79. }
  80. for(Int i=old_elms; i<elms(); i++){Ptr elm=T[i]; Zero(elm, elmSize()); if(_new)_new(elm);}
  81. }else
  82. if(num<elms()) // remove elements
  83. {
  84. if(_del)for(Int i=elms(); --i>=num; )_del(T[i]);
  85. _elms=num;
  86. }
  87. }
  88. /******************************************************************************/
  89. Int _Memb::addNum(Int num) {Int index=elms(); setNum(elms()+num); return index;}
  90. /******************************************************************************/
  91. Ptr _Memb::NewAt(Int i)
  92. {
  93. Clamp(i, 0, elms());
  94. New();
  95. for(Int j=elms()-1; j>i; j--)SwapFast(T[j], T[j-1], elmSize());
  96. return T[i];
  97. }
  98. /******************************************************************************/
  99. void _Memb::removeLast()
  100. {
  101. if(elms())
  102. {
  103. if(_del)_del(T[elms()-1]);
  104. _elms--;
  105. }
  106. }
  107. void _Memb::remove(Int i, Bool keep_order)
  108. {
  109. if(InRange(i, T))
  110. {
  111. if(_del)_del(T[i]);
  112. if(elms()-1>i)
  113. {
  114. if(!keep_order )CopyFast(T[i], T[elms()-1], elmSize());else
  115. for(Int j=i; j<elms()-1; j++)CopyFast(T[j], T[ j+1], elmSize());
  116. }
  117. _elms--;
  118. }
  119. }
  120. void _Memb::removeData(CPtr elm, Bool keep_order)
  121. {
  122. remove(index(elm), keep_order);
  123. }
  124. /******************************************************************************/
  125. Ptr _Memb::_element(Int i)C
  126. {
  127. return (Byte*)(_ptr[i>>_shr]) + (i&mask())*elmSize();
  128. }
  129. Ptr _Memb::operator()(Int i)
  130. {
  131. if(i< 0 )Exit("i<0 inside _Memb.operator()(Int i)");
  132. if(i>=elms())setNumZero(i+1);
  133. return T[i];
  134. }
  135. /******************************************************************************/
  136. Int _Memb::index(CPtr elm)C
  137. {
  138. if(elm)
  139. {
  140. UIntPtr data =UIntPtr(elm),
  141. block_size =blockSize();
  142. Int used_blocks=(elms()+blockElms()-1)>>_shr;
  143. FREPD(b, used_blocks)
  144. {
  145. UIntPtr p=data-UIntPtr(_ptr[b]);
  146. if(p<block_size) // if belongs to this block, unsigned compare will already guarantee "i>=0 && "
  147. {
  148. Int i=b*blockElms() + p/elmSize();
  149. return InRange(i, T) ? i : -1;
  150. }
  151. }
  152. }
  153. return -1;
  154. }
  155. /******************************************************************************/
  156. void _Memb::reverseOrder()
  157. {
  158. Int last=elms()-1;
  159. REP(elms()/2)SwapFast(T[i], T[last-i], elmSize());
  160. }
  161. void _Memb::swapOrder(Int i, Int j)
  162. {
  163. if(InRange(i, T) && InRange(j, T))Swap(T[i], T[j], elmSize());
  164. }
  165. void _Memb::moveElm(Int elm, Int new_index)
  166. {
  167. if(InRange(elm, elms()))
  168. {
  169. Clamp(new_index, 0, elms()-1); if(new_index!=elm)
  170. {
  171. Memt<Byte> buf; buf.setNum(elmSize()); Ptr temp=buf.data();
  172. CopyFast(temp, T[elm], elmSize()); // copy element from data to temp memory
  173. // E N E N
  174. if(elm<new_index) // element is on the left, and we're moving it to the right, move the data to the left "0X123" -> "012X3"
  175. {
  176. for(Int i=elm; i<new_index; i++)CopyFast(T[i], T[i+1], elmSize());
  177. } // N E N E
  178. else // element is on the right, and we're moving it to the left, move the data to the right "012X3" -> "0X123"
  179. {
  180. for(Int i=elm; i>new_index; i--)CopyFast(T[i], T[i-1], elmSize());
  181. }
  182. CopyFast(T[new_index], temp, elmSize()); // copy element from temp memory back to the data
  183. }
  184. }
  185. }
  186. void _Memb::moveElmLeftUnsafe(Int elm, Int new_index, Ptr temp) // !! assumes indexes are in range, "elm>=new_index", 'temp' can fit element !!
  187. {
  188. if(new_index!=elm)
  189. {
  190. CopyFast(temp, T[elm], elmSize()); // copy element from data to temp memory
  191. #if 0 // not needed since we're always moving left in this function
  192. // E N E N
  193. if(elm<new_index) // element is on the left, and we're moving it to the right, move the data to the left "0X123" -> "012X3"
  194. {
  195. for(Int i=elm; i<new_index; i++)CopyFast(T[i], T[i+1], elmSize());
  196. } // N E N E
  197. else // element is on the right, and we're moving it to the left, move the data to the right "012X3" -> "0X123"
  198. #endif
  199. {
  200. for(Int i=elm; i>new_index; i--)CopyFast(T[i], T[i-1], elmSize());
  201. }
  202. CopyFast(T[new_index], temp, elmSize()); // copy element from temp memory back to the data
  203. }
  204. }
  205. /******************************************************************************/
  206. Bool _Memb::saveRaw(File &f)C
  207. {
  208. f.cmpUIntV(elms());
  209. if(elms())
  210. {
  211. Int block_size =blockSize(),
  212. full_blocks=elms()>>_shr;
  213. FREP(full_blocks)f.put(_ptr[i ], block_size );
  214. f.put(_ptr[full_blocks], (elms()&mask())*elmSize()); // last block
  215. }
  216. return f.ok();
  217. }
  218. Bool _Memb::loadRaw(File &f)
  219. {
  220. setNum(f.decUIntV());
  221. if(elms())
  222. {
  223. Int block_size =blockSize(),
  224. full_blocks=elms()>>_shr;
  225. FREP(full_blocks)f.getFast(_ptr[i ], block_size );
  226. f.getFast(_ptr[full_blocks], (elms()&mask())*elmSize()); // last block
  227. }
  228. if(f.ok())return true;
  229. clear(); return false;
  230. }
  231. /******************************************************************************/
  232. void _Memb::copyTo(Ptr dest)C
  233. {
  234. if(elms() && dest)
  235. {
  236. Int block_size =blockSize(),
  237. full_blocks=elms()>>_shr;
  238. FREP(full_blocks){CopyFast(dest, _ptr[i ], block_size ); dest=(Byte*)dest+block_size;}
  239. CopyFast(dest, _ptr[full_blocks], (elms()&mask())*elmSize()); // last block
  240. }
  241. }
  242. void _Memb::copyFrom(CPtr src)
  243. {
  244. if(elms())
  245. {
  246. Int block_size =blockSize(),
  247. full_blocks=elms()>>_shr;
  248. FREP(full_blocks){Copy(_ptr[i ], src, block_size ); if(src)src=(Byte*)src+block_size;}
  249. Copy(_ptr[full_blocks], src, (elms()&mask())*elmSize()); // last block
  250. }
  251. }
  252. /******************************************************************************
  253. void _Memb::copyRaw(_Memb &dest)
  254. {
  255. if(this!=&dest)
  256. {
  257. dest.del();
  258. dest._ptr=null;
  259. dest._shr=_shr;
  260. dest._elm_size =elmSize (); dest._elms =0;
  261. dest._block_elms=blockElms(); dest._blocks=0;
  262. dest._new=_new;
  263. dest._del=_del;
  264. dest.setNum(_elms);
  265. if(_elms)
  266. {
  267. Int block_size =blockSize(),
  268. full_blocks=elms()>>_shr;
  269. FREP(full_blocks)CopyFast(dest._ptr[i ], _ptr[i ], block_size );
  270. CopyFast(dest._ptr[full_blocks], _ptr[full], (_elms&mask())*elmSize()); // last block
  271. }
  272. }
  273. }
  274. /******************************************************************************/
  275. }
  276. /******************************************************************************/