impl.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. // Helper macro so people don't need to enter all the sizes all the time.
  49. #define _Jagged(%0) (%0),sizeof(%0),sizeof(%0[])
  50. #define _Jagged_Sum:(%0,%1) _Jagged_Sum:(%0+%1)
  51. // Ceiling division so that all slots will be at least big enough. Otherwise
  52. //
  53. // Jagged:X[3]<12, 1 1>
  54. //
  55. // Would result in "[3][4]", which doesn't have 14 slots total.
  56. #define Jagged:%0[%1]<%2>; %0[%1][_:_Jagged_Sum:(%2,%1,-1) / (%1)];Jagged_ResizeAll(%0,%2);
  57. static stock Jagged_MovePtr(array[][], maxSize, slot, shift)
  58. {
  59. new
  60. tmp0,
  61. tmp1,
  62. ptr;
  63. // Get the slot pointer.
  64. #emit LOAD.S.alt array
  65. #emit LOAD.S.pri slot
  66. #emit IDXADDR
  67. #emit STOR.S.pri tmp0
  68. //#emit MOVE.alt
  69. #emit LOAD.I
  70. #emit STOR.S.pri ptr
  71. //printf("Jagged_MovePtr: Moving %d by %d to %d (mod %d)", ptr, shift, ptr + shift, maxSize);
  72. ptr += shift;
  73. // I have to do it this way to avoid a bug with "if" statements and "#emit".
  74. ptr = (ptr > maxSize) ? maxSize : ptr;
  75. #emit LOAD.S.alt array
  76. #emit LOAD.S.pri slot
  77. #emit IDXADDR
  78. #emit STOR.S.pri tmp1
  79. #emit STOR.S.pri shift
  80. #emit LOAD.S.pri ptr
  81. #emit SREF.S.pri shift
  82. //printf("%d %d %d %d", tmp0, tmp1, shift, ptr);
  83. #if _DEBUG >= 7
  84. printf("Jagged_MovePtr: Header:");
  85. _Jagged_PrintHeader(array, 4, 0);
  86. #endif
  87. }
  88. /**--------------------------------------------------------------------------**\
  89. <summary>Jagged_ResizeOne</summary>
  90. <param name="array[][]">The array we want to resize a slot in.</param>
  91. <param name="size1">The number of slots in the array.</param>
  92. <param name="size2">The ORIGINAL size of every slot.</param>
  93. <param name="slot">The slot to resize.</param>
  94. <param name="newSize">The new size of the slot.</param>
  95. <returns>
  96. -
  97. </returns>
  98. <remarks>
  99. Resize an array slot, maintining all of its data. The "slot" variable is
  100. usually used to hold the NEXT slot - we barely need the number of the
  101. 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. Resize multiple array slots, maintining all of their data.
  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. }
  187. #define Jagged_Resize(%0,%1) _Jagged_Resize(_Jagged(%0),%1)
  188. #define _ALS_Jagged_Resize
  189. /**--------------------------------------------------------------------------**\
  190. <summary>_Jagged_ResizeAll</summary>
  191. <param name="array[][]">The array we want to resize a slot in.</param>
  192. <param name="size1">The number of slots in the array.</param>
  193. <param name="size2">The ORIGINAL size of every slot.</param>
  194. <param name="...">New sizes for every slot.</param>
  195. <returns>
  196. -
  197. </returns>
  198. <remarks>
  199. Resize multilpe array slots, maintining all of their data.
  200. </remarks>
  201. \**--------------------------------------------------------------------------**/
  202. stock bool:_Jagged_ResizeAll(array[][], size1, size2, ...)
  203. {
  204. new
  205. num = min(numargs() - 3, size1);
  206. // Now, as you can imagine, this requires some tricky low-level code, but
  207. // that is all in other functions now.
  208. for (new i = 3, j = 0; j != num; ++i, ++j)
  209. {
  210. P:7("_Jagged_Resize: loop %d %d %d", i, j, getarg(i));
  211. Jagged_ResizeOne(array, size1, size2, j, getarg(i));
  212. }
  213. }
  214. #define Jagged_ResizeAll(%0,%1) _Jagged_ResizeAll(_Jagged(%0),%1)
  215. #define _ALS_Jagged_ResizeAll
  216. /**--------------------------------------------------------------------------**\
  217. <summary>Jagged_MoveOne</summary>
  218. <param name="array[][]">The array we want to resize a slot in.</param>
  219. <param name="size1">The number of slots in the array.</param>
  220. <param name="size2">The ORIGINAL size of every slot.</param>
  221. <param name="slot">The slot to resize.</param>
  222. <param name="newSize">The new size of the slot.</param>
  223. <returns>
  224. -
  225. </returns>
  226. <remarks>
  227. The "slot" variable is usually used to hold the NEXT slot - we barely need
  228. the number of the current slot once we have its address. "Resize" copies
  229. data to keep as much of the original data as possible. This just moves the
  230. boundaries.
  231. </remarks>
  232. \**--------------------------------------------------------------------------**/
  233. stock bool:Jagged_MoveOne(array[][], size1, size2, slot, newSize)
  234. {
  235. if (newSize < 0)
  236. {
  237. return false;
  238. }
  239. // SLOT GETS INCREMENTED VERY FAST!
  240. if (0 < ++slot < size1)
  241. {
  242. // Get the slot's current size and address.
  243. newSize *= 4;
  244. new
  245. newEnd = _Jagged_Address(array, slot - 1) + newSize,
  246. arrayEnd = _Jagged_End(array, size1, size2);
  247. if (newEnd > arrayEnd)
  248. {
  249. P:1("Insufficient space to grow jagged array.");
  250. return false;
  251. }
  252. new
  253. slotEnd = _Jagged_Address(array, slot),
  254. shift = newEnd - slotEnd;
  255. P:5("Jagged_MoveOne: Mov slot %d from %d to %d", slot - 1, _Jagged_SizeOf(array, size1, size2, slot - 1), newSize);
  256. if (shift != 0)
  257. {
  258. // Shift all the subsequent slots.
  259. size2 = size2 * size1 * 4;
  260. while (slot < size1)
  261. {
  262. Jagged_MovePtr(array, size2 + (size1 - slot) * 4, slot, shift);
  263. ++slot;
  264. }
  265. }
  266. // Do nothing if they're the same.
  267. return true;
  268. }
  269. P:C(else if (slot == size1) printf("Cannot alter the last slot in an array."););
  270. return false;
  271. }
  272. /**--------------------------------------------------------------------------**\
  273. <summary>_Jagged_Move</summary>
  274. <param name="array[][]">The array we want to resize a slot in.</param>
  275. <param name="size1">The number of slots in the array.</param>
  276. <param name="size2">The ORIGINAL size of every slot.</param>
  277. <param name="...">Multiple {slot, size} tuples.</param>
  278. <returns>
  279. -
  280. </returns>
  281. <remarks>
  282. "Resize" copies data to keep as much of the original data as possible. This
  283. just moves the boundaries.
  284. </remarks>
  285. \**--------------------------------------------------------------------------**/
  286. stock bool:_Jagged_Move(array[][], size1, size2, ...)
  287. {
  288. new
  289. num = numargs();
  290. // Now, as you can imagine, this requires some tricky low-level code, but
  291. // that is all in other functions now.
  292. for (new i = 3; i != num; ++i)
  293. {
  294. P:7("_Jagged_Move: loop %d %d %d", i, getarg(i, 0), getarg(i, 1));
  295. Jagged_MoveOne(array, size1, size2, getarg(i, 0), getarg(i, 1));
  296. }
  297. }
  298. #define Jagged_Move(%0,%1) _Jagged_Move(_Jagged(%0),%1)
  299. #define _ALS_Jagged_Move
  300. /**--------------------------------------------------------------------------**\
  301. <summary>_Jagged_MoveAll</summary>
  302. <param name="array[][]">The array we want to resize a slot in.</param>
  303. <param name="size1">The number of slots in the array.</param>
  304. <param name="size2">The ORIGINAL size of every slot.</param>
  305. <param name="...">New sizes for every slot.</param>
  306. <returns>
  307. -
  308. </returns>
  309. <remarks>
  310. "Resize" copies data to keep as much of the original data as possible. This
  311. just moves the boundaries.
  312. </remarks>
  313. \**--------------------------------------------------------------------------**/
  314. stock bool:_Jagged_MoveAll(array[][], size1, size2, ...)
  315. {
  316. new
  317. num = min(numargs() - 3, size1);
  318. // Now, as you can imagine, this requires some tricky low-level code, but
  319. // that is all in other functions now.
  320. for (new i = 3, j = 0; j != num; ++i, ++j)
  321. {
  322. P:7("_Jagged_Move: loop %d %d %d", i, j, getarg(i));
  323. Jagged_MoveOne(array, size1, size2, j, getarg(i));
  324. }
  325. }
  326. #define Jagged_MoveAll(%0,%1) _Jagged_MoveAll(_Jagged(%0),%1)
  327. #define _ALS_Jagged_MoveAll
  328. /**--------------------------------------------------------------------------**\
  329. <summary>_Jagged_SizeOf</summary>
  330. <param name="array[][]">The array we want to get the size of a slot in.</param>
  331. <param name="size1">The number of slots in the array.</param>
  332. <param name="size2">The ORIGINAL size of every slot.</param>
  333. <param name="slot">The slot to get the size of.</param>
  334. <returns>
  335. The current size of this slot. This is NOT a compile-time operation.
  336. </returns>
  337. <remarks>
  338. Returns the data in BYTES NOT CELLS.
  339. </remarks>
  340. \**--------------------------------------------------------------------------**/
  341. stock _Jagged_SizeOf(array[][], size1, size2, slot)
  342. {
  343. if (0 <= slot < size1)
  344. {
  345. new
  346. start = _Jagged_Address(array, slot);
  347. if (++slot == size1)
  348. {
  349. // Figure out the end address of the array.
  350. return _Jagged_End(array, size1, size2) - start;
  351. }
  352. else
  353. {
  354. return _Jagged_Address(array, slot) - start;
  355. }
  356. }
  357. return -1;
  358. }
  359. #define Jagged_SizeOf(%0,%1) _Jagged_SizeOf(_Jagged(%0),%1)
  360. #define _ALS_Jagged_SizeOf
  361. #define jaggedsizeof(%0[%1]) (_Jagged_SizeOf(_Jagged(%0),%1)>>2)
  362. /**--------------------------------------------------------------------------**\
  363. <summary>_Jagged_Address</summary>
  364. <param name="array[][]">The array we want to get the address of a slot in.</param>
  365. <param name="size1">The number of slots in the array.</param>
  366. <param name="size2">The ORIGINAL size of every slot.</param>
  367. <param name="slot">The slot to get the address of.</param>
  368. <returns>
  369. The absolute address of this slot.
  370. </returns>
  371. <remarks>
  372. -
  373. </remarks>
  374. \**--------------------------------------------------------------------------**/
  375. #if _DEBUG == 0
  376. static
  377. #endif
  378. stock _Jagged_Address(array[][], slot)
  379. {
  380. // Get the slot pointer.
  381. #emit LOAD.S.alt array
  382. #emit LOAD.S.pri slot
  383. #emit IDXADDR
  384. #emit MOVE.alt
  385. #emit LOAD.I
  386. #emit ADD
  387. #emit RETN
  388. return 0;
  389. }
  390. /**--------------------------------------------------------------------------**\
  391. <summary>_Jagged_End</summary>
  392. <param name="array[][]">The array we want to get the end of.</param>
  393. <param name="size1">The number of slots in the array.</param>
  394. <param name="size2">The ORIGINAL size of every slot.</param>
  395. <returns>
  396. The absolute address of the end of this array.
  397. </returns>
  398. <remarks>
  399. -
  400. </remarks>
  401. \**--------------------------------------------------------------------------**/
  402. #if _DEBUG == 0
  403. static
  404. #endif
  405. stock _Jagged_End(array[][], size1, size2)
  406. {
  407. #emit LOAD.S.alt size2
  408. #emit INC.alt
  409. #emit LOAD.S.pri size1
  410. #emit UMUL
  411. #emit LOAD.S.alt array
  412. #emit IDXADDR
  413. #emit RETN
  414. return 0;
  415. }
  416. stock _Jagged_PrintHeader(array[][], size1, size2)
  417. {
  418. #pragma unused size2
  419. for (new ptr, slot = 0; slot != size1; ++slot)
  420. {
  421. // Get the slot pointer.
  422. #emit LOAD.S.alt array
  423. #emit LOAD.S.pri slot
  424. #emit LIDX
  425. #emit PUSH.pri
  426. // Get the relative offset.
  427. #emit LOAD.S.pri slot
  428. #emit LOAD.S.alt size1
  429. #emit SUB.alt
  430. #emit SHL.C.pri 2
  431. // Adjust the output to absolute.
  432. #emit POP.alt
  433. #emit SUB.alt
  434. // #emit LOAD.S.alt array
  435. // #emit ADD
  436. #emit STOR.S.pri ptr
  437. printf("Array header: %d = %d", slot, ptr);
  438. }
  439. }
  440. #define Jagged_PrintHeader(%0) _Jagged_PrintHeader(_Jagged(%0))
  441. #define _ALS_Jagged_PrintHeader