y_jaggedarray.inc 9.5 KB

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