y_jaggedarray.inc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*----------------------------------------------------------------------------*\
  2. ================================
  3. y_jaggedarray - Uneven arrays.
  4. ================================
  5. Description:
  6. Provides code to easilly manipulate the sizes of 2d array slots.
  7. Legal:
  8. Version: MPL 1.1
  9. The contents of this file are subject to the Mozilla Public License Version
  10. 1.1 (the "License"); you may not use this file except in compliance with
  11. the License. You may obtain a copy of the License at
  12. http://www.mozilla.org/MPL/
  13. Software distributed under the License is distributed on an "AS IS" basis,
  14. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15. for the specific language governing rights and limitations under the
  16. License.
  17. The Original Code is the YSI group include.
  18. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  19. Portions created by the Initial Developer are Copyright (C) 2011
  20. the Initial Developer. All Rights Reserved.
  21. Contributors:
  22. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  23. Thanks:
  24. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  25. ZeeX - Very productive conversations.
  26. koolk - IsPlayerinAreaEx code.
  27. TheAlpha - Danish translation.
  28. breadfish - German translation.
  29. Fireburn - Dutch translation.
  30. yom - French translation.
  31. 50p - Polish translation.
  32. Zamaroht - Spanish translation.
  33. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  34. for me to strive to better.
  35. Pixels^ - Running XScripters where the idea was born.
  36. Matite - Pestering me to release it and using it.
  37. Very special thanks to:
  38. Thiadmer - PAWN, whose limits continue to amaze me!
  39. Kye/Kalcor - SA:MP.
  40. SA:MP Team past, present and future - SA:MP.
  41. Version:
  42. 1.0
  43. Changelog:
  44. 06/10/12:
  45. First version
  46. Fixed a bug calling "rawMemset".
  47. \*----------------------------------------------------------------------------*/
  48. #include "internal\y_version"
  49. #include "y_utils"
  50. #include "y_debug"
  51. //#include "y_rewrite"
  52. // Helper macro so people don't need to enter all the sizes all the time.
  53. #define _Jagged(%0) (%0),sizeof(%0),sizeof(%0[])
  54. static stock Jagged_MovePtr(array[][], maxSize, slot, shift)
  55. {
  56. new
  57. tmp0,
  58. tmp1,
  59. ptr;
  60. // Get the slot pointer.
  61. #emit LOAD.S.alt array
  62. #emit LOAD.S.pri slot
  63. #emit IDXADDR
  64. #emit STOR.S.pri tmp0
  65. //#emit MOVE.alt
  66. #emit LOAD.I
  67. #emit STOR.S.pri ptr
  68. //printf("Jagged_MovePtr: Moving %d by %d to %d (mod %d)", ptr, shift, ptr + shift, maxSize);
  69. ptr += shift;
  70. // I have to do it this way to avoid a bug with "if" statements and "#emit".
  71. ptr = (ptr > maxSize) ? maxSize : ptr;
  72. #emit LOAD.S.alt array
  73. #emit LOAD.S.pri slot
  74. #emit IDXADDR
  75. #emit STOR.S.pri tmp1
  76. #emit STOR.S.pri shift
  77. #emit LOAD.S.pri ptr
  78. #emit SREF.S.pri shift
  79. //printf("%d %d %d %d", tmp0, tmp1, shift, ptr);
  80. #if _DEBUG >= 7
  81. printf("Jagged_MovePtr: Header:");
  82. _Jagged_PrintHeader(array, 4, 0);
  83. #endif
  84. }
  85. /*----------------------------------------------------------------------------*\
  86. Function:
  87. Jagged_ResizeOne
  88. Params:
  89. array[][] - The array we want to resize a slot in.
  90. size1 - The number of slots in the array.
  91. size2 - The ORIGINAL size of every slot.
  92. slot - The slot to resize.
  93. newSize - The new size of the slot.
  94. Return:
  95. -
  96. Notes:
  97. The "slot" variable is usually used to hold the NEXT slot - we barely need
  98. the number of the current slot once we have its address.
  99. \*----------------------------------------------------------------------------*/
  100. stock bool:Jagged_ResizeOne(array[][], size1, size2, slot, newSize)
  101. {
  102. if (newSize < 0)
  103. {
  104. return false;
  105. }
  106. // SLOT GETS INCREMENTED VERY FAST!
  107. if (0 < ++slot < size1)
  108. {
  109. // Get the slot's current size and address.
  110. newSize *= 4;
  111. new
  112. newEnd = _Jagged_Address(array, slot - 1) + newSize,
  113. arrayEnd = _Jagged_End(array, size1, size2);
  114. if (newEnd > arrayEnd)
  115. {
  116. P:1("Insufficient space to grow jagged array.");
  117. return false;
  118. }
  119. new
  120. slotEnd = _Jagged_Address(array, slot),
  121. //oldSize = slotEnd - slotStart,
  122. shift = newEnd - slotEnd; //newSize - oldSize;
  123. P:5("Jagged_ResizeOne: Resizing slot %d from %d to %d", slot - 1, _Jagged_SizeOf(array, size1, size2, slot - 1), newSize);
  124. if (shift != 0)
  125. {
  126. new
  127. remain = arrayEnd - newEnd;
  128. // Grow the slot. This has to be done largely in assembly to remove
  129. // the "BOUNDS" OpCodes that would otherwise be inserted. Actually,
  130. // we can't have "BOUNDS" here because there's no way for the
  131. // compiler to know the array's size in advance. This works even
  132. // when "shift" is negative.
  133. memcpy(array[slot][shift / 4], array[slot], 0, remain, remain / 4);
  134. // Now shift all the subsequent slots.
  135. size2 = size2 * size1 * 4;
  136. while (slot < size1)
  137. {
  138. Jagged_MovePtr(array, size2 + (size1 - slot) * 4, slot, shift);
  139. ++slot;
  140. }
  141. if (shift > 0)
  142. {
  143. // Blank the remainder of the slot we are growing.
  144. rawMemset(slotEnd, shift, 0);
  145. }
  146. else
  147. {
  148. // Blank the end of the array.
  149. rawMemset(arrayEnd + shift, -shift, 0);
  150. }
  151. }
  152. // Do nothing if they're the same.
  153. return true;
  154. }
  155. P:C(else if (slot == size1) printf("Cannot alter the last slot in an array."););
  156. return false;
  157. }
  158. /*----------------------------------------------------------------------------*\
  159. Function:
  160. _Jagged_Resize
  161. Params:
  162. array[][] - The array we want to resize a slot in.
  163. size1 - The number of slots in the array.
  164. size2 - The ORIGINAL size of every slot.
  165. ... - Multiple {slot, size} tuples.
  166. Return:
  167. -
  168. Notes:
  169. -
  170. \*----------------------------------------------------------------------------*/
  171. stock bool:_Jagged_Resize(array[][], size1, size2, ...)
  172. {
  173. new
  174. num = numargs();
  175. // Now, as you can imagine, this requires some tricky low-level code, but
  176. // that is all in other functions now.
  177. for (new i = 3; i != num; ++i)
  178. {
  179. P:7("_Jagged_Resize: loop %d %d %d", i, getarg(i, 0), getarg(i, 1));
  180. Jagged_ResizeOne(array, size1, size2, getarg(i, 0), getarg(i, 1));
  181. }
  182. //#pragma unused tuples
  183. }
  184. #define Jagged_Resize(%0,%1) _Jagged_Resize(_Jagged(%0),%1)
  185. #define _ALS_Jagged_Resize
  186. /*----------------------------------------------------------------------------*\
  187. Function:
  188. _Jagged_SizeOf
  189. Params:
  190. array[][] - The array we want to get the size of a slot in.
  191. size1 - The number of slots in the array.
  192. size2 - The ORIGINAL size of every slot.
  193. slot - The slot to get the size of.
  194. Return:
  195. The current size of this slot. This is NOT a compile-time operation.
  196. Notes:
  197. Returns the data in BYTES NOT CELLS.
  198. \*----------------------------------------------------------------------------*/
  199. stock _Jagged_SizeOf(array[][], size1, size2, slot)
  200. {
  201. if (0 <= slot < size1)
  202. {
  203. new
  204. start = _Jagged_Address(array, slot);
  205. if (++slot == size1)
  206. {
  207. // Figure out the end address of the array.
  208. return _Jagged_End(array, size1, size2) - start;
  209. }
  210. else
  211. {
  212. return _Jagged_Address(array, slot) - start;
  213. }
  214. }
  215. return -1;
  216. }
  217. #define Jagged_SizeOf(%0,%1) _Jagged_SizeOf(_Jagged(%0),%1)
  218. #define _ALS_Jagged_SizeOf
  219. #define jaggedsizeof(%0[%1]) (_Jagged_SizeOf(_Jagged(%0),%1)>>2)
  220. /*----------------------------------------------------------------------------*\
  221. Function:
  222. _Jagged_Address
  223. Params:
  224. array[][] - The array we want to get the address of a slot in.
  225. size1 - The number of slots in the array.
  226. size2 - The ORIGINAL size of every slot.
  227. slot - The slot to get the address of.
  228. Return:
  229. The absolute address of this slot.
  230. Notes:
  231. -
  232. \*----------------------------------------------------------------------------*/
  233. #if _DEBUG == 0
  234. static
  235. #endif
  236. stock _Jagged_Address(array[][], slot)
  237. {
  238. // Get the slot pointer.
  239. #emit LOAD.S.alt array
  240. #emit LOAD.S.pri slot
  241. #emit IDXADDR
  242. #emit MOVE.alt
  243. #emit LOAD.I
  244. #emit ADD
  245. #emit RETN
  246. return 0;
  247. }
  248. /*----------------------------------------------------------------------------*\
  249. Function:
  250. _Jagged_End
  251. Params:
  252. array[][] - The array we want to get the end of.
  253. size1 - The number of slots in the array.
  254. size2 - The ORIGINAL size of every slot.
  255. Return:
  256. The absolute address of the end of this array.
  257. Notes:
  258. -
  259. \*----------------------------------------------------------------------------*/
  260. #if _DEBUG == 0
  261. static
  262. #endif
  263. stock _Jagged_End(array[][], size1, size2)
  264. {
  265. #emit LOAD.S.alt size2
  266. #emit INC.alt
  267. #emit LOAD.S.pri size1
  268. #emit UMUL
  269. #emit LOAD.S.alt array
  270. #emit IDXADDR
  271. #emit RETN
  272. return 0;
  273. }
  274. stock _Jagged_PrintHeader(array[][], size1, size2)
  275. {
  276. #pragma unused size2
  277. for (new ptr, slot = 0; slot != size1; ++slot)
  278. {
  279. // Get the slot pointer.
  280. #emit LOAD.S.alt array
  281. #emit LOAD.S.pri slot
  282. #emit IDXADDR
  283. //#emit MOVE.alt
  284. #emit LOAD.I
  285. #emit STOR.S.pri ptr
  286. printf("Array header: %d = %d", slot, ptr);
  287. }
  288. }