| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /**--------------------------------------------------------------------------**\
- ================================
- y_jaggedarray - Uneven arrays.
- ================================
- Description:
- Provides code to easilly manipulate the sizes of 2d array slots.
- Legal:
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the YSI group include.
-
- The Initial Developer of the Original Code is Alex "Y_Less" Cole.
- Portions created by the Initial Developer are Copyright (C) 2011
- the Initial Developer. All Rights Reserved.
-
- Contributors:
- ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
-
- Thanks:
- JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
- ZeeX - Very productive conversations.
- koolk - IsPlayerinAreaEx code.
- TheAlpha - Danish translation.
- breadfish - German translation.
- Fireburn - Dutch translation.
- yom - French translation.
- 50p - Polish translation.
- Zamaroht - Spanish translation.
- Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
- for me to strive to better.
- Pixels^ - Running XScripters where the idea was born.
- Matite - Pestering me to release it and using it.
-
- Very special thanks to:
- Thiadmer - PAWN, whose limits continue to amaze me!
- Kye/Kalcor - SA:MP.
- SA:MP Team past, present and future - SA:MP.
-
- Version:
- 1.0
- Changelog:
- 06/10/12:
- First version
- Fixed a bug calling "rawMemset".
- </remarks>
- \**--------------------------------------------------------------------------**/
- #include "internal\y_version"
- #include "y_utils"
- #include "y_debug"
- //#include "y_rewrite"
- // Helper macro so people don't need to enter all the sizes all the time.
- #define _Jagged(%0) (%0),sizeof(%0),sizeof(%0[])
- static stock Jagged_MovePtr(array[][], maxSize, slot, shift)
- {
- new
- tmp0,
- tmp1,
- ptr;
- // Get the slot pointer.
- #emit LOAD.S.alt array
- #emit LOAD.S.pri slot
- #emit IDXADDR
- #emit STOR.S.pri tmp0
- //#emit MOVE.alt
- #emit LOAD.I
- #emit STOR.S.pri ptr
- //printf("Jagged_MovePtr: Moving %d by %d to %d (mod %d)", ptr, shift, ptr + shift, maxSize);
- ptr += shift;
- // I have to do it this way to avoid a bug with "if" statements and "#emit".
- ptr = (ptr > maxSize) ? maxSize : ptr;
- #emit LOAD.S.alt array
- #emit LOAD.S.pri slot
- #emit IDXADDR
- #emit STOR.S.pri tmp1
- #emit STOR.S.pri shift
- #emit LOAD.S.pri ptr
- #emit SREF.S.pri shift
- //printf("%d %d %d %d", tmp0, tmp1, shift, ptr);
- #if _DEBUG >= 7
- printf("Jagged_MovePtr: Header:");
- _Jagged_PrintHeader(array, 4, 0);
- #endif
- }
- /**--------------------------------------------------------------------------**\
- <summary>Jagged_ResizeOne</summary>
- <param name="array[][]">The array we want to resize a slot in.</param>
- <param name="size1">The number of slots in the array.</param>
- <param name="size2">The ORIGINAL size of every slot.</param>
- <param name="slot">The slot to resize.</param>
- <param name="newSize">The new size of the slot.</param>
- <returns>
- -
- </returns>
- <remarks>
- The "slot" variable is usually used to hold the NEXT slot - we barely need
- the number of the current slot once we have its address.
- </remarks>
- \**--------------------------------------------------------------------------**/
- stock bool:Jagged_ResizeOne(array[][], size1, size2, slot, newSize)
- {
- if (newSize < 0)
- {
- return false;
- }
- // SLOT GETS INCREMENTED VERY FAST!
- if (0 < ++slot < size1)
- {
- // Get the slot's current size and address.
- newSize *= 4;
- new
- newEnd = _Jagged_Address(array, slot - 1) + newSize,
- arrayEnd = _Jagged_End(array, size1, size2);
- if (newEnd > arrayEnd)
- {
- P:1("Insufficient space to grow jagged array.");
- return false;
- }
- new
- slotEnd = _Jagged_Address(array, slot),
- //oldSize = slotEnd - slotStart,
- shift = newEnd - slotEnd; //newSize - oldSize;
- P:5("Jagged_ResizeOne: Resizing slot %d from %d to %d", slot - 1, _Jagged_SizeOf(array, size1, size2, slot - 1), newSize);
- if (shift != 0)
- {
- new
- remain = arrayEnd - newEnd;
- // Grow the slot. This has to be done largely in assembly to remove
- // the "BOUNDS" OpCodes that would otherwise be inserted. Actually,
- // we can't have "BOUNDS" here because there's no way for the
- // compiler to know the array's size in advance. This works even
- // when "shift" is negative.
- memcpy(array[slot][shift / 4], array[slot], 0, remain, remain / 4);
- // Now shift all the subsequent slots.
- size2 = size2 * size1 * 4;
- while (slot < size1)
- {
- Jagged_MovePtr(array, size2 + (size1 - slot) * 4, slot, shift);
- ++slot;
- }
- if (shift > 0)
- {
- // Blank the remainder of the slot we are growing.
- rawMemset(slotEnd, shift, 0);
- }
- else
- {
- // Blank the end of the array.
- rawMemset(arrayEnd + shift, -shift, 0);
- }
- }
- // Do nothing if they're the same.
- return true;
- }
- P:C(else if (slot == size1) printf("Cannot alter the last slot in an array."););
- return false;
- }
- /**--------------------------------------------------------------------------**\
- <summary>_Jagged_Resize</summary>
- <param name="array[][]">The array we want to resize a slot in.</param>
- <param name="size1">The number of slots in the array.</param>
- <param name="size2">The ORIGINAL size of every slot.</param>
- <param name="...">Multiple {slot, size} tuples.</param>
- <returns>
- -
- </returns>
- <remarks>
- -
- </remarks>
- \**--------------------------------------------------------------------------**/
- stock bool:_Jagged_Resize(array[][], size1, size2, ...)
- {
- new
- num = numargs();
- // Now, as you can imagine, this requires some tricky low-level code, but
- // that is all in other functions now.
- for (new i = 3; i != num; ++i)
- {
- P:7("_Jagged_Resize: loop %d %d %d", i, getarg(i, 0), getarg(i, 1));
- Jagged_ResizeOne(array, size1, size2, getarg(i, 0), getarg(i, 1));
- }
- //#pragma unused tuples
- }
- #define Jagged_Resize(%0,%1) _Jagged_Resize(_Jagged(%0),%1)
- #define _ALS_Jagged_Resize
- /**--------------------------------------------------------------------------**\
- <summary>_Jagged_SizeOf</summary>
- <param name="array[][]">The array we want to get the size of a slot in.</param>
- <param name="size1">The number of slots in the array.</param>
- <param name="size2">The ORIGINAL size of every slot.</param>
- <param name="slot">The slot to get the size of.</param>
- <returns>
- The current size of this slot. This is NOT a compile-time operation.
- </returns>
- <remarks>
- Returns the data in BYTES NOT CELLS.
- </remarks>
- \**--------------------------------------------------------------------------**/
- stock _Jagged_SizeOf(array[][], size1, size2, slot)
- {
- if (0 <= slot < size1)
- {
- new
- start = _Jagged_Address(array, slot);
- if (++slot == size1)
- {
- // Figure out the end address of the array.
- return _Jagged_End(array, size1, size2) - start;
- }
- else
- {
- return _Jagged_Address(array, slot) - start;
- }
- }
- return -1;
- }
- #define Jagged_SizeOf(%0,%1) _Jagged_SizeOf(_Jagged(%0),%1)
- #define _ALS_Jagged_SizeOf
- #define jaggedsizeof(%0[%1]) (_Jagged_SizeOf(_Jagged(%0),%1)>>2)
- /**--------------------------------------------------------------------------**\
- <summary>_Jagged_Address</summary>
- <param name="array[][]">The array we want to get the address of a slot in.</param>
- <param name="size1">The number of slots in the array.</param>
- <param name="size2">The ORIGINAL size of every slot.</param>
- <param name="slot">The slot to get the address of.</param>
- <returns>
- The absolute address of this slot.
- </returns>
- <remarks>
- -
- </remarks>
- \**--------------------------------------------------------------------------**/
- #if _DEBUG == 0
- static
- #endif
- stock _Jagged_Address(array[][], slot)
- {
- // Get the slot pointer.
- #emit LOAD.S.alt array
- #emit LOAD.S.pri slot
- #emit IDXADDR
- #emit MOVE.alt
- #emit LOAD.I
- #emit ADD
- #emit RETN
- return 0;
- }
- /**--------------------------------------------------------------------------**\
- <summary>_Jagged_End</summary>
- <param name="array[][]">The array we want to get the end of.</param>
- <param name="size1">The number of slots in the array.</param>
- <param name="size2">The ORIGINAL size of every slot.</param>
- <returns>
- The absolute address of the end of this array.
- </returns>
- <remarks>
- -
- </remarks>
- \**--------------------------------------------------------------------------**/
- #if _DEBUG == 0
- static
- #endif
- stock _Jagged_End(array[][], size1, size2)
- {
- #emit LOAD.S.alt size2
- #emit INC.alt
- #emit LOAD.S.pri size1
- #emit UMUL
- #emit LOAD.S.alt array
- #emit IDXADDR
- #emit RETN
- return 0;
- }
- stock _Jagged_PrintHeader(array[][], size1, size2)
- {
- #pragma unused size2
- for (new ptr, slot = 0; slot != size1; ++slot)
- {
- // Get the slot pointer.
- #emit LOAD.S.alt array
- #emit LOAD.S.pri slot
- #emit IDXADDR
- //#emit MOVE.alt
- #emit LOAD.I
- #emit STOR.S.pri ptr
- printf("Array header: %d = %d", slot, ptr);
- }
- }
|