;----------------------------------------------------------- ; ; Api92/Api89 Source Code ; ; (c) NeXO Software, Benoit SCHERRER ; e-mail : p.c.scherrer@wanadoo.fr ; ; ; File> array.xas ; Utility> Arrays Management ; ;----------------------------------------------------------- ;----------------------------------------------------- ; array_Create ; ; > Create an array, allocating a new buffer ; ;Input> d1.w : Constant size for each item ;Out> d0.l : 0 if failure ; else handle of created array ;----------------------------------------------------- apilib@0024: _array_Create: CreateList: movem.l d2-d3,-(a7) clr.w d0 clr.w d2 clr.l d3 bsr _array_oCreate \exit movem.l (a7)+,d2-d3 rts ;--------------------------------------------------- ; array_fCreate ; ; > Create an array inside an existing file ; ;input> d0.w : Handle of the file ; d1.w : Size of each item ; d2.w : Offset where to insert the array ;out> d0.w : Handle if successfull, else null ;--------------------------------------------------- apilib@0036: _array_fCreate: movem.l d3/a0,-(a7) bsr DEREFd0a0 move.w (a0)+,d3 addq.l #2,d3 bsr _array_oCreate tst.w d0 beq.s \exit subq.l #2,d3 bsr DEREFd0a0 move.w d3,(a0)+ \exit movem.l (a7)+,d3/a0 rts ;--------------------------------------------------- ; array_oCreate ; ; > Create an array into an existing buffer ; ;input> d0.w : Handle of existing buffer ; d1.w : Size of each item ; d2.w : Offset where to insert the array ; d3.w : Current size of the buffer ;out> d0.w : Handle if successfull, else null ; d3.l : New size of the buffer ;--------------------------------------------------- apilib@0033: _array_oCreate: movem.l d1-d2/d4/a0-a2,-(a7) and.l #$FFFF,d3 and.l #$FFFF,d1 mulu.w #10,d1 addq.l #4,d1 move.l d3,d4 sub.w d2,d4 ;nb bytes to move movem.l d1-d2,-(a7) add.w d1,d3 move.l d3,-(a7) ;push new size move.w d0,-(a7) ;push hdl TIOS_CALL HeapRealloc addq.l #6,a7 movem.l (a7)+,d1-d2 tst.l d0 beq.s \exit bsr DEREFd0a0 ;get addr of buffer tst.w d2 beq.s \skip adda.w d2,a0 ;offset movem.l d0/a0,-(a7) ;save d0/a0 move.l d4,-(a7) ;push new size move.l a0,-(a7) ;push src addr pea 0(a0,d1.w) ;push dst addr TIOS_CALL memmove ;mov mem lea 12(a7),a7 movem.l (a7)+,d0/a0 ;restore d0/a0 \skip move.w #$0A,(a0)+ clr.w (a0)+ \exit movem.l (a7)+,d1-d2/d4/a0-a2 rts ;------------------------------------------------------ ; array_AddItem ; ; > Add an item to a normal array ; ;input> d0.w : Handle of the array ; d1.w : Size of each item ; a0.l : Address of the item data that should be ; added ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; a1.l : Address of created item entry ;------------------------------------------------------ apilib@0022: AddToList: _array_AddItem: movem.l d2-d3,-(a7) bsr _prep_array bsr _array_oAddItem movem.l (a7)+,d2-d3 rts _prep_array: clr.w d2 ;Offset = 0 move.l a0,-(a7) ;Get size of buffer bsr DEREFd0a0 move.w (a0)+,d3 mulu.w d1,d3 addq.l #4,d3 ;add 2 first words move.l (a7)+,a0 rts ;------------------------------------------------------ ; array_fAddItem ; ; > Add an item to an array created in a file ; ;input> d0.w : Handle of the array ; d1.w : Size of each item ; d2.w : Offset of array in the file ; a0.l : Address of item ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; a1.l : Address of item entry ;------------------------------------------------------ apilib@0037: _array_fAddItem: movem.l d3/a0,-(a7) move.l a0,-(a7) bsr DEREFd0a0 move.w (a0)+,d3 addq.l #2,d3 move.l (a7)+,a0 bsr _array_oAddItem tst.w d0 beq.s \exit bsr DEREFd0a0 subq.l #2,d3 move.w d3,(a0)+ \exit movem.l (a7)+,d3/a0 rts ;------------------------------------------------------ ; array_oAddItem ; ; > Add an item to an array created in a buffer ; ;input> d0.w : Handle of the array ; d1.w : Size of each item ; d2.w : Offset of array in the buffer ; d3.w : Size of buffer ; a0.l : Address of item ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; d3.w : New size of buffer ; a1.l : Address of item entry ;------------------------------------------------------ apilib@0034: _array_oAddItem: movem.l d2/d4-d7/a0/a2-a3,-(a7) and.l #$FFFF,d3 move.l a0,a3 move.w d1,d5 ;save size of item beq \unknownerror ;if null exit bsr DEREFd0a0 ;get addr of buffer adda.w d2,a0 ;add offset move.w (a0)+,d6 ;nb before resize move.w (a0)+,d4 ;nb of items cmp.w d4,d6 bne.s \noresize move.w d3,d7 ;calc size to move sub.w d2,d7 move.w d6,d1 mulu.w d5,d1 addq.l #4,d1 ;4 first bytes sub.w d1,d7 add.w #10,d6 ;resize buffer moveq.w #10,d1 mulu.w d5,d1 add.w d1,d3 move.l d2,-(a7) ;save offset move.l d3,-(a7) ;new size move.w d0,-(a7) ;hdl TIOS_CALL HeapRealloc addq.l #6,a7 move.l (a7)+,d2 ;restore offset tst.w d0 beq.s \memerror \noerror bsr DEREFd0a0 tst.w d2 ;test offset beq.s \skip ;if null, exit adda.w d2,a0 ;add offset move.w (a0),d1 mulu.w d5,d1 movem.l d0-d2/a0,-(a7) ;save d0/a0 move.l d7,-(a7) ;size to move lea 4(a0,d1.w),a1 moveq.w #10,d1 mulu.w d5,d1 move.l a1,-(a7) pea 0(a1,d1.w) TIOS_CALL memmove ;mov mem lea 12(a7),a7 movem.l (a7)+,d0-d2/a0 ;restore d0/a0 \skip \noresize bsr DEREFd0a0 adda.w d2,a0 move.w d6,(a0)+ ;put new max add.w #1,(a0)+ ; mulu.w d5,d4 ; [nb item] x [item size] adda.w d4,a0 move.l a0,a1 subq.w #1,d5 ;for dbra \cpy move.b (a3)+,(a0)+ dbra.s d5,\cpy clr.w d1 ;no error \exit movem.l (a7)+,d2/d4-d7/a0/a2-a3 rts \unknownerror clr.w d0 moveq.w #EC_UNKNOWN,d1 bra.s \exit \memerror clr.w d0 moveq.w #EC_OUTOFMEMORY,d1 bra.s \exit ;------------------------------------------------------ ; array_DeleteItem ; ; > Delete an item of a normal array ; ;input> d0.w : Handle of array ; d1.w : Size of each item ; d2.w : Zero based item index to delete ;out> d0.w : Handle of array, or null if null ; d1.w : error code ;------------------------------------------------------ apilib@0023: _array_DeleteItem: movem.l d2-d4,-(a7) move.w d2,d4 bsr _prep_array bsr _array_oDeleteItem movem.l (a7)+,d2-d4 rts ;------------------------------------------------------ ; array_fDeleteItem ; ; > Delete an item of an array created in a file ; ;input> d0.w : Handle of array ; d1.w : Size of each item ; d2.w : Offset of the array in the buffer ; d3.w : Zero based item index to delete ;out> d0.w : Handle of array, or null if null ; d1.w : error code ; d3.w : New size of the buffer ;------------------------------------------------------ apilib@0038: _array_fDeleteItem: move.l d4,-(a7) move.l d3,d4 bsr DEREFd0a0 ;Get file address move.w (a0)+,d3 ;Get its size addq.l #2,d3 bsr _array_oDeleteItem tst.w d0 beq.s \exit bsr DEREFd0a0 subq.l #2,d3 move.w d3,(a0)+ \exit move.l (a7)+,d4 rts ;------------------------------------------------------ ; array_oDeleteItem ; ; > Delete an item of an array created in a buffer ; ;input> d0.w : Handle of array ; d1.w : Size of each item ; d2.w : Offset of the array in the buffer ; d3.w : Size of buffer ; d4.w : Zero based item index to delete ;out> d0.w : Handle of array, or null if null ; d1.w : error code ; d3.w : New size of the buffer ;------------------------------------------------------ apilib@0035: _array_oDeleteItem: movem.l d2-d6/a0-a1,-(a7) and.l #$0000FFFF,d3 move.w d0,d6 ;Save Handle bsr DEREFd0a0 ;Get address of buffer adda.w d2,a0 ;Add offset addq.l #2,a0 ;Skip first word move.w (a0),d5 ;Get Nb of item cmp.w d5,d4 bcc.s \error_invalidindex ;>= move.w d4,d0 ;Offset in d0 mulu.w d1,d0 ; x Size of each item subq.w #1,(a0)+ ;Decrement item counter adda.w d0,a0 ;Goto item to delete move.l a0,a1 adda.w d1,a1 sub.w d4,d5 ;If last item subq.w #1,d5 ;for dbra beq.s \noerror ; skip without moving memory subq.w #1,d5 subq.w #1,d1 ;for dbra \scroll move.w d1,d0 \cpy move.b (a1)+,(a0)+ dbra.s d0,\cpy dbra.s d5,\scroll \noerror clr.w d1 ;No error \exit move.w d6,d0 ;Resturn value movem.l (a7)+,d2-d6/a0-a1 rts \error_invalidindex moveq.w #EC_INVALIDINDEX,d1 clr.w d6 bra.s \exit ;---------------------------------------------------- ; array_FindItem ; ; > Look for an item in an array ; ;Input> d0.w : Handle of the array ; d1.w : Size of each item ; d3.w : Search mode : ; 0 : compare entire item ; -1 : use a callback function to compare ; else nb of bytes to compare ; a0.l : Address of data to find ; a1.l : Address of callback function if d2=-1 ;Out> d0.w : 0 if not found ; else 1-based index of item if found ; a1.l : Address of item entry in the array (if found) ;---------------------------------------------------- apilib@002E: _array_FindItem: move.l d2,-(a7) clr.w d2 bsr _array_oFindItem move.l (a7)+,d2 rts ;---------------------------------------------------- ; array_oFindItem ; ; > Look for an item in an array created in a buffer ; or a file ; ;Input> d0.w : Handle of the array ; d1.w : Size of each item ; d2.w : Offset ; d3.w : Search mode : ; 0 : compare entire item ; -1 : use a callback function to compare ; else nb of bytes to compare ; a0.l : Address of data to find ; a1.l : Address of callback function if d2=-1 ;Out> d0.w : 0 if not found ; else 1-based index of item if found ; a1.l : Address of item entry in the array (if found) ;---------------------------------------------------- _array_oFindItem: movem.l d1-d6/a0/a2,-(a7) move.l a0,a2 ;data to find in a2 bsr DEREFd0a0 adda.w d2,a0 addq.l #2,a0 move.w (a0)+,d4 ;nb items beq.s \error subq.w #1,d4 ;for dbra clr.l d5 ;index of item \find addq.w #1,d5 ;Increment item index movem.l d1-d7/a0-a6,-(a7) cmp.w #$FFFF,d3 ;use callback ? bne.s \skip1 ;if nno, skip movem.l d1-d7/a0-a6,-(a7) jsr (a1) movem.l (a7)+,d1-d7/a0-a6 tst.w d0 bne.s \found bra.s \next_item \skip1 tst.w d3 ;complete comparaison ? beq.s \skip2 ;if yes,skip move.w d3,d1 \skip2 subq.w #1,d1 ;for dbra \cmp cmp.b (a0)+,(a2)+ bne.s \next_item dbra.s d1,\cmp bra.s \found \next_item movem.l (a7)+,d1-d7/a0-a6 lea 0(a0,d1.w),a0 ;Get next item addr dbra.s d4,\find \error clr.w d0 ;item not found \exit move.l a0,a1 ;Addr of item movem.l (a7)+,d1-d6/a0/a2 rts \found move.w d5,d0 ;Index of found item in d0 movem.l (a7)+,d1-d7/a0-a6 bra.s \exit ;---------------------------------------------------- ; array_BubbleShort ; ; > Short an array, using a callback function ; ;Input> d0.w : Handle of array ; d1.w : Size of each item ; a0.l : Address of an api92CB_arrayShort ; function ; ;---------------------------------------------------- ;api92CB_arrayPbShort function : ; ; Input> a0.l : Address of 1st item ; a1.l : Address of 2nd item ; Out> d0.w : 0 : don't swap ; 1 : swap ;---------------------------------------------------- apilib@002F: _array_Short: move.l d2,-(a7) clr.w d2 bsr _array_oShort move.l (a7)+,d2 rts ;---------------------------------------------------- ; array_BubbleShort ; ; > Short an array, using a callback function ; ;Input> d0.w : Handle of array ; d1.w : Size of each item ; d2.w : offset of array in the buffer ; a0.l : Address of an api92CB_arrayShort ; function ; ;---------------------------------------------------- apilib@0061: _array_oShort: movem.l d0-d7/a0-a6,-(a7) move.l a0,a2 bsr DEREFd0a0 ;get addr of list adda.w d2,a0 addq.l #2,a0 ;skip first word move.w (a0)+,d4 ;nb items beq.s \exit ;if null, exit cmp.w #1,d4 ;if only one item beq.s \exit ;exit subq.w #2,d4 ;for dbra and for the test move.w d4,d5 ;save d4=nb item move.l a0,a3 ;save a0 \short move.w d5,d4 ;restore move.l a3,a0 clr.w d6 ;no swap \short2 lea 0(a0,d1.w),a1 ;addr of 2nd item movem.l d1-d7/a0-a6,-(a7) jsr (a2) movem.l (a7)+,d1-d7/a0-a6 tst.w d0 ;swap required ? beq.s \noswap ;if no, skip move.w d1,d2 ;size of each item subq.w #1,d2 ;for swap dbra \swap move.b (a0),d0 move.b (a1),(a0)+ move.b d0,(a1)+ dbra.s d2,\swap moveq.w #1,d6 ;one element swapped art least suba.w d1,a0 ;because lea \noswap lea 0(a0,d1.w),a0 ;next item dbra.s d4,\short2 tst.w d6 beq.s \exit dbra.s d5,\short \exit movem.l (a7)+,d0-d7/a0-a6 rts ;---------------------------------------------------- ; array_InsertItem ; ;Input> d0.w : hdl of list ; d1.w : size of each item ; d2.w : zero based index ; a0.l : address of data ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; a1.l : Address of item entry ;---------------------------------------------------- apilib@0062: _array_InsertItem: movem.l d2-d4,-(a7) move.l d2,d4 bsr _prep_array bsr _array_oInsertItem movem.l (a7)+,d2-d4 rts ;---------------------------------------------------- ; array_fInsertItem ; ;Input> d0.w : hdl of list ; d1.w : size of each item ; d2.w : offset ; d3.w : zero based index ; a0.l : address of data ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; a1.l : Address of item entry ;---------------------------------------------------- _array_fInsertItem: apilib@0063: movem.l d3-d4/a0,-(a7) move.l d3,d4 ;index move.l a0,-(a7) bsr DEREFd0a0 move.w (a0)+,d3 addq.l #2,d3 move.l (a7)+,a0 bsr _array_oInsertItem tst.w d0 beq.s \exit bsr DEREFd0a0 subq.l #2,d3 move.w d3,(a0)+ \exit movem.l (a7)+,d3-d4/a0 rts ;---------------------------------------------------- ; array_oInsertItem ; ;Input> d0.w : hdl of list ; d1.w : size of each item ; d2.w : offset ; d3.l : size ; d4.w : zero based index ; a0.l : address of data ;out> d0.w : Handle of array if successfull, else null ; d1.w : Error code ; d3.w : New size of buffer ; a1.l : Address of item entry ;---------------------------------------------------- _array_oInsertItem: apilib@0064: movem.l d2/d4-d7/a0/a2-a4,-(a7) move.l a0,a1 ;save addr move.l d1,d6 ;save size move.w d0,d5 ;check if bsr DEREFd0a0 addq.w #2,a0 adda.w d2,a0 cmp.w (a0),d4 ;if d4>(a0) bhi \out ;out move.l a1,a0 move.l a1,-(a7) bsr _array_oAddItem move.l (a7)+,a1 tst.w d1 ;if error bne.s \exit ;exit movem.l d0-d3/a0-a1,-(a7) move.w d5,d0 ;restore saved handle bsr DEREFd0a0 ;get addr adda.w d2,a0 ;add offset addq.l #2,a0 move.w (a0)+,d0 ;nb items mulu.w d6,d0 lea 0(a0,d0.w),a3 move.w d4,d0 mulu.w d6,d0 lea 0(a0,d0.w),a1 move.l a1,a4 ;save dest addr lea 0(a1,d6.w),a2 move.l a3,d0 sub.l a2,d0 move.l d0,-(a7) ;size move.l a1,-(a7) ;src move.l a2,-(a7) TIOS_CALL memmove lea 12(a7),a7 movem.l (a7)+,d0-d3/a0-a1 move.w d6,d0 ;copy subq.w #1,d0 ;dbra \copy move.b (a1)+,(a4)+ dbra.s d0,\copy clr.w d1 \exit movem.l (a7)+,d2/d4-d7/a0/a2-a4 rts \out move.w #EC_INVALIDINDEX,d1 bra.s \exit