Re-dimensioning+arrays

//by Richard Russell, May 2014//

BBC BASIC does not have a **REDIM** or **REDIM PRESERVE** statement, as found in some other dialects of BASIC (REDIM allows you to increase the dimensions of an existing array - the contents are lost - and REDIM PRESERVE allows you to increase the dimensions of an array without destroying its contents). However it is not difficult to provide an equivalent functionality using user-defined procedures: code format="bb4w" DEF PROCredim1d(RETURN P%,S%,D%) LOCAL A%     IF ?P%<>1 ERROR 14, "Bad use of array" IF P%HIMEM SYS "GlobalFree", P%     SYS "GlobalAlloc", 64, 5+S%*(D%+1) TO A%      IF A%=0 ERROR 11, "DIM space" ?A%=1 : A%!1=D%+1 P% = A%     ENDPROC

DEF PROCredim2d(RETURN P%,S%,D%,E%) LOCAL A%     IF ?P%<>2 ERROR 14, "Bad use of array" IF P%HIMEM SYS "GlobalFree", P%     SYS "GlobalAlloc", 64, 9+S%*(D%+1)*(E%+1) TO A%      IF A%=0 ERROR 11, "DIM space" ?A%=2 : A%!1=D%+1 : A%!5=E%+1 P% = A%     ENDPROC

DEF PROCredimpreserve1d(RETURN P%,S%,D%) LOCAL A%,N%,O% IF ?P%<>1 ERROR 14, "Bad use of array" N% = 5+S%*(D%+1) O% = 5+S%*P%!1 SYS "GlobalAlloc", 64, N% TO A%     IF A%=0 ERROR 11, "DIM space" IF N%>O% SWAP N%,O% SYS "RtlMoveMemory", A%, P%, N%     A%!1=D%+1 IF P%HIMEM SYS "GlobalFree", P%     P% = A%      ENDPROC

DEF PROCredimpreserve2d(RETURN P%,S%,D%,E%) LOCAL A%,N%,O% IF ?P%<>2 ERROR 14, "Bad use of array" N% = 9+S%*(D%+1)*(E%+1) O% = 9+S%*P%!1*P%!5 SYS "GlobalAlloc", 64, N% TO A%     IF A%=0 ERROR 11, "DIM space" IF N%>O% SWAP N%,O% SYS "RtlMoveMemory", A%, P%, N%     A%!1=D%+1 : A%!5=E%+1 IF P%HIMEM SYS "GlobalFree", P%     P% = A%      ENDPROC code The above procedures support 1-dimensional and 2-dimensional arrays; equivalent routines for arrays with more dimensions can be derived if required. If you REDIM PRESERVE a 2-dimensional (or more) array you should normally only change the **first** dimension; if you change another dimension the data will be 'preserved' but will appear to have **moved**. Note that it isn't usually sensible to **reduce** the size of an array.

In each case the parameters to the procedure are the name of the array, the size of each element of the array (see table below) and the required dimension(s). As with the normal **DIM** statement, the available indices run from zero to the specified value.

Here is a simple demonstration program: code format="bb4w" DIM array(100) FOR I% = 0 TO 100 array(I%) = SQR(I%) NEXT PROCredimpreserve1d(array, ^array(1)-^array(0), 200) FOR I% = 101 TO 200 array(I%) = SQR(I%) NEXT FOR I% = 0 TO 200 IF array(I%) <> SQR(I%) STOP NEXT PRINT "Test completed successfully" END code Note that if you REDIM (not REDIM PRESERVE) a **string array** you must explicitly empty the array first: code format="bb4w" array$ = "" PROCredim1d(array$, ^array$(1)-^array$(0), newsize%) code

The most reliable way of determining the element size is to calculate it at run-time, as in the above examples, but for reference here are the appropriate sizes for each type of array:

* BB4W version 6 only
 * **byte** e.g. array&|| size=**1**||
 * **32-bit integer** e.g. array%|| size=**4**||
 * **40-bit float** e.g. array|| size=**5**||
 * **string** e.g. array$|| size=**6**||
 * **64-bit float** e.g. array#|| size=**8**||
 * **string** e.g. array$|| size=**8***||
 * **64-bit integer** e.g. array%% || size=**8***||
 * **80-bit float** e.g. array|| size=**10***||