y_jaggedarray.inc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. #if defined _INC_y_jaggedarray
  49. #endinput
  50. #endif
  51. #define _INC_y_jaggedarray
  52. #include "..\YSI_Internal\y_version"
  53. #include "..\YSI_Core\y_utils"
  54. #include "..\YSI_Core\y_debug"
  55. //#include "y_rewrite"
  56. // Helper macro so people don't need to enter all the sizes all the time.
  57. #define _Jagged(%0) (%0),sizeof(%0),sizeof(%0[])
  58. static stock Jagged_MovePtr(array[][], maxSize, slot, shift)
  59. {
  60. new
  61. tmp0,
  62. tmp1,
  63. ptr;
  64. // Get the slot pointer.
  65. #emit LOAD.S.alt array
  66. #emit LOAD.S.pri slot
  67. #emit IDXADDR
  68. #emit STOR.S.pri tmp0
  69. //#emit MOVE.alt
  70. #emit LOAD.I
  71. #emit STOR.S.pri ptr
  72. //printf("Jagged_MovePtr: Moving %d by %d to %d (mod %d)", ptr, shift, ptr + shift, maxSize);
  73. ptr += shift;
  74. // I have to do it this way to avoid a bug with "if" statements and "#emit".
  75. ptr = (ptr > maxSize) ? maxSize : ptr;
  76. #emit LOAD.S.alt array
  77. #emit LOAD.S.pri slot
  78. #emit IDXADDR
  79. #emit STOR.S.pri tmp1
  80. #emit STOR.S.pri shift
  81. #emit LOAD.S.pri ptr
  82. #emit SREF.S.pri shift
  83. //printf("%d %d %d %d", tmp0, tmp1, shift, ptr);
  84. #if _DEBUG >= 7
  85. printf("Jagged_MovePtr: Header:");
  86. _Jagged_PrintHeader(array, 4, 0);
  87. #endif
  88. }
  89. /**--------------------------------------------------------------------------**\
  90. <summary>Jagged_ResizeOne</summary>
  91. <param name="array[][]">The array we want to resize a slot in.</param>
  92. <param name="size1">The number of slots in the array.</param>
  93. <param name="size2">The ORIGINAL size of every slot.</param>
  94. <param name="slot">The slot to resize.</param>
  95. <param name="newSize">The new size of the slot.</param>
  96. <returns>
  97. -
  98. </returns>
  99. <remarks>
  100. The "slot" variable is usually used to hold the NEXT slot - we barely need
  101. the number of the current slot once we have its address.
  102. </remarks>
  103. \**--------------------------------------------------------------------------**/
  104. stock bool:Jagged_ResizeOne(array[][], size1, size2, slot, newSize)
  105. {
  106. if (newSize < 0)
  107. {
  108. return false;
  109. }
  110. // SLOT GETS INCREMENTED VERY FAST!
  111. if (0 < ++slot < size1)
  112. {
  113. // Get the slot's current size and address.
  114. newSize *= 4;
  115. new
  116. newEnd = _Jagged_Address(array, slot - 1) + newSize,
  117. arrayEnd = _Jagged_End(array, size1, size2);
  118. if (newEnd > arrayEnd)
  119. {
  120. P:1("Insufficient space to grow jagged array.");
  121. return false;
  122. }
  123. new
  124. slotEnd = _Jagged_Address(array, slot),
  125. //oldSize = slotEnd - slotStart,
  126. shift = newEnd - slotEnd; //newSize - oldSize;
  127. P:5("Jagged_ResizeOne: Resizing slot %d from %d to %d", slot - 1, _Jagged_SizeOf(array, size1, size2, slot - 1), newSize);
  128. if (shift != 0)
  129. {
  130. new
  131. remain = arrayEnd - newEnd;
  132. // Grow the slot. This has to be done largely in assembly to remove
  133. // the "BOUNDS" OpCodes that would otherwise be inserted. Actually,
  134. // we can't have "BOUNDS" here because there's no way for the
  135. // compiler to know the array's size in advance. This works even
  136. // when "shift" is negative.
  137. memcpy(array[slot][shift / 4], array[slot], 0, remain, remain / 4);
  138. // Now shift all the subsequent slots.
  139. size2 = size2 * size1 * 4;
  140. while (slot < size1)
  141. {
  142. Jagged_MovePtr(array, size2 + (size1 - slot) * 4, slot, shift);
  143. ++slot;
  144. }
  145. if (shift > 0)
  146. {
  147. // Blank the remainder of the slot we are growing.
  148. rawMemset(slotEnd, 0, shift);
  149. }
  150. else
  151. {
  152. // Blank the end of the array.
  153. rawMemset(arrayEnd + shift, 0, -shift);
  154. }
  155. }
  156. // Do nothing if they're the same.
  157. return true;
  158. }
  159. P:C(else if (slot == size1) printf("Cannot alter the last slot in an array."););
  160. return false;
  161. }
  162. /**--------------------------------------------------------------------------**\
  163. <summary>_Jagged_Resize</summary>
  164. <param name="array[][]">The array we want to resize a slot in.</param>
  165. <param name="size1">The number of slots in the array.</param>
  166. <param name="size2">The ORIGINAL size of every slot.</param>
  167. <param name="...">Multiple {slot, size} tuples.</param>
  168. <returns>
  169. -
  170. </returns>
  171. <remarks>
  172. -
  173. </remarks>
  174. \**--------------------------------------------------------------------------**/
  175. stock bool:_Jagged_Resize(array[][], size1, size2, ...)
  176. {
  177. new
  178. num = numargs();
  179. // Now, as you can imagine, this requires some tricky low-level code, but
  180. // that is all in other functions now.
  181. for (new i = 3; i != num; ++i)
  182. {
  183. P:7("_Jagged_Resize: loop %d %d %d", i, getarg(i, 0), getarg(i, 1));
  184. Jagged_ResizeOne(array, size1, size2, getarg(i, 0), getarg(i, 1));
  185. }
  186. //#pragma unused tuples
  187. }
  188. #define Jagged_Resize(%0,%1) _Jagged_Resize(_Jagged(%0),%1)
  189. #define _ALS_Jagged_Resize
  190. /**--------------------------------------------------------------------------**\
  191. <summary>_Jagged_SizeOf</summary>
  192. <param name="array[][]">The array we want to get the size of a slot in.</param>
  193. <param name="size1">The number of slots in the array.</param>
  194. <param name="size2">The ORIGINAL size of every slot.</param>
  195. <param name="slot">The slot to get the size of.</param>
  196. <returns>
  197. The current size of this slot. This is NOT a compile-time operation.
  198. </returns>
  199. <remarks>
  200. Returns the data in BYTES NOT CELLS.
  201. </remarks>
  202. \**--------------------------------------------------------------------------**/
  203. stock _Jagged_SizeOf(array[][], size1, size2, slot)
  204. {
  205. if (0 <= slot < size1)
  206. {
  207. new
  208. start = _Jagged_Address(array, slot);
  209. if (++slot == size1)
  210. {
  211. // Figure out the end address of the array.
  212. return _Jagged_End(array, size1, size2) - start;
  213. }
  214. else
  215. {
  216. return _Jagged_Address(array, slot) - start;
  217. }
  218. }
  219. return -1;
  220. }
  221. #define Jagged_SizeOf(%0,%1) _Jagged_SizeOf(_Jagged(%0),%1)
  222. #define _ALS_Jagged_SizeOf
  223. #define jaggedsizeof(%0[%1]) (_Jagged_SizeOf(_Jagged(%0),%1)>>2)
  224. /**--------------------------------------------------------------------------**\
  225. <summary>_Jagged_Address</summary>
  226. <param name="array[][]">The array we want to get the address of a slot in.</param>
  227. <param name="size1">The number of slots in the array.</param>
  228. <param name="size2">The ORIGINAL size of every slot.</param>
  229. <param name="slot">The slot to get the address of.</param>
  230. <returns>
  231. The absolute address of this slot.
  232. </returns>
  233. <remarks>
  234. -
  235. </remarks>
  236. \**--------------------------------------------------------------------------**/
  237. #if _DEBUG == 0
  238. static
  239. #endif
  240. stock _Jagged_Address(array[][], slot)
  241. {
  242. // Get the slot pointer.
  243. #emit LOAD.S.alt array
  244. #emit LOAD.S.pri slot
  245. #emit IDXADDR
  246. #emit MOVE.alt
  247. #emit LOAD.I
  248. #emit ADD
  249. #emit RETN
  250. return 0;
  251. }
  252. /**--------------------------------------------------------------------------**\
  253. <summary>_Jagged_End</summary>
  254. <param name="array[][]">The array we want to get the end of.</param>
  255. <param name="size1">The number of slots in the array.</param>
  256. <param name="size2">The ORIGINAL size of every slot.</param>
  257. <returns>
  258. The absolute address of the end of this array.
  259. </returns>
  260. <remarks>
  261. -
  262. </remarks>
  263. \**--------------------------------------------------------------------------**/
  264. #if _DEBUG == 0
  265. static
  266. #endif
  267. stock _Jagged_End(array[][], size1, size2)
  268. {
  269. #emit LOAD.S.alt size2
  270. #emit INC.alt
  271. #emit LOAD.S.pri size1
  272. #emit UMUL
  273. #emit LOAD.S.alt array
  274. #emit IDXADDR
  275. #emit RETN
  276. return 0;
  277. }
  278. stock _Jagged_PrintHeader(array[][], size1, size2)
  279. {
  280. #pragma unused size2
  281. for (new ptr, slot = 0; slot != size1; ++slot)
  282. {
  283. // Get the slot pointer.
  284. #emit LOAD.S.alt array
  285. #emit LOAD.S.pri slot
  286. #emit IDXADDR
  287. //#emit MOVE.alt
  288. #emit LOAD.I
  289. #emit STOR.S.pri ptr
  290. printf("Array header: %d = %d", slot, ptr);
  291. }
  292. }