I noticed that QB doesn't like variable-length arrays as TYPE members, so I decided to make my own array class. It supports insertion/removal of elements anywhere within the array, automatically dealing with element management. It is a variable-length array, but it does have a maximum default byte-length of 512, which is adjustable (QB didn't like "Array.MAXBYTELENGTH" for a name when using it with "string *"; didn't try using it with a fixed-length array, though).
I couldn't figure out how to keep indentation without < PRE >< /PRE > tags..
Some possible things to do:
- Fix the issue with Array.Insert when adding an element will cause a buffer overrun when the element is bigger than remaining buffer size
- Add API for removal of a range of elements
- Add API for insertion of multiple copies of an element
- Transform SUBs into FUNCTIONs, or use a global variable to indicate an error (right now the procedures simply return without doing anything)
- test, debug, test, debug.. PROFIT !!! hehehe
' Copyright(c) 2008, Laanan Fisher
' Use and modify freely but please keep copyright notice.
defint a-z
const ARRAYMAXBYTELENGTH = 512
type Array
elemsize as integer
elemcount as integer
elemdata as string * ARRAYMAXBYTELENGTH
end type
' Initializes an array. 'elemsize' is the size, in bytes, of an element,
' 'elemcount' is the initial number of elements.
declare sub Array.Init (self as Array, elemsize, elemcount)
' Gets the number of elements in the array.
declare function Array.Size (self as Array)
' Returns -1 if the array has no elements, zero otherwise.
declare function Array.Empty (self as Array)
' Gets an element of the array. 'i' is the element index, 's' and 'o' are the
' segment and offset in memory for storing element data.
declare sub Array.Index (self as Array, i, s, o)
' Adds an element to the end of the array. 's' and 'o' are the segment and
' offset in memory for retrieving element data.
declare sub Array.PushBack (self as Array, s, o)
' Removes a number of elements from the end of the array. 'n' must be positive
' and less than or equal to Array.Size(self).
declare sub Array.PopBack (self as Array, n)
' Adds an element into the array immediately before element 'i'. 's' and 'o'
' are the segment and offset in memory for storing element data.
declare sub Array.Insert (self as Array, i, s, o)
' Erases an element from the array.
declare sub Array.Erase (self as Array, i)
' Erases all elements from the array.
declare sub Array.Clear (self as Array)
' Some utility procedures..
declare sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
declare sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
declare function IntegerArrayToString$ (a as Array)
declare function SingleArrayToString$ (a as Array)
'' ::::: (main)
cls
dim i, a as Array
' Initialize an integer array to zero size.
Array.Init a, len(i), 0
' Add some elements to the array.
i = 10 : Array.PushBack a, varseg(i), varptr(i)
i = 20 : Array.PushBack a, varseg(i), varptr(i)
i = 30 : Array.PushBack a, varseg(i), varptr(i)
print IntegerArrayToString$(a)
dim s as single
' Initialize a single array to zero size.
Array.Init a, len(s), 0
' Add some more elements to the array.
s = 1.1 : Array.PushBack a, varseg(s), varptr(s)
s = 2.2 : Array.Insert a, 1, varseg(s), varptr(s)
s = 3.3 : Array.Insert a, 1, varseg(s), varptr(s)
s = 4.4 : Array.Insert a, 1, varseg(s), varptr(s)
print SingleArrayToString$(a)
' Remove the first and last 2 elements from the array.
Array.Erase a, 0
Array.PopBack a, 2
print SingleArrayToString$(a)
'' :::::
sub Array.Init (self as Array, elemsize, elemcount)
self.elemsize = elemsize
self.elemcount = elemcount
self.elemdata = ""
end sub
'' :::::
function Array.Size (self as Array)
Array.Size = self.elemcount
end function
'' :::::
sub Array.Index (self as Array, i, dstseg, dstoff)
if (i < 0) or (i > self.elemcount) then exit sub
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize
end sub
'' :::::
sub Array.PushBack (self as Array, srcseg, srcoff)
if self.elemcount * self.elemsize >= ARRAYMAXBYTELENGTH then exit sub
Array.Insert self, Array.Size(self), srcseg, srcoff
end sub
'' :::::
sub Array.PopBack (self as Array, n)
if n < 0 then exit sub
if n > self.elemcount then n = self.elemcount
self.elemcount = self.elemcount - n
end sub
'' :::::
sub Array.Insert (self as Array, i, s, o)
if self.elemcount * self.elemsize >= ARRAYMAXBYTELENGTH then exit sub
if (i < 0) or (i > self.elemcount) then exit sub
elemsafter = self.elemcount - i
' shift any elements to the right..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * (i + 1)
MemCopyBackward dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
' insert the new element..
MemCopy srcseg, srcoff, s, o, self.elemsize
self.elemcount = self.elemcount + 1
end sub
'' :::::
sub Array.Erase (self as Array, i)
if (i < 0) or (i >= self.elemcount) then exit sub
elemsafter = self.elemcount - i - 1
' shift any elements to the left..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * (i + 1)
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
self.elemcount = self.elemcount - 1
end sub
'' :::::
sub Array.Clear (self as Array)
self.elemcount = 0
end sub
'' :::::
sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = 0 to size - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
end sub
'' :::::
sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = size - 1 to 0 step - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
end sub
'' :::::
function IntegerArrayToString$ (a as Array)
dim result as string : result = "("
for i = 0 to Array.Size(a) - 1
dim e as integer : Array.Index a, i, varseg(e), varptr(e)
result = result + "(" + str$(e) + ")"
next
IntegerArrayToString$ = result + ")"
end function
'' :::::
function SingleArrayToString$ (a as Array)
dim result as string : result = "("
for i = 0 to Array.Size(a) - 1
dim e as single : Array.Index a, i, varseg(e), varptr(e)
result = result + "(" + str$(e) + ")"
next
- Array.Empty wasn't implemented (oops !)
- Array.InsertN/EraseRange added to insert multiple copies of an element and remove a range of elements
- Utility procedures MemCopy/MemCopyBackward weren't resetting default segment
- Array.Insert/InsertN now properly check for overrun
- Array.Begin/End added, returns indexes of first and one-past the last elements
- Array.Erase/EraseRange now check if shifting is needed to speed things up a bit (MemCopy/MemCopyBackward always checked for zero byte copies, so safety wasn't an issue)
- Array.Back/Front added to get the first and last elements
- Example updated to demonstrate some of the changes. Enjoy.
' Copyright(c) 2008, Laanan Fisher
' Use and modify freely but please keep copyright notice.
defint a-z
const ARRAYMAXBYTELENGTH = 512
type Array
elemsize as integer
elemcount as integer
elemdata as string * ARRAYMAXBYTELENGTH
end type
' Initializes an array. 'elemsize' is the size, in bytes, of an element,
' 'elemcount' is the initial number of elements.
declare sub Array.Init (self as Array, elemsize, elemcount)
' Gets the number of elements in the array.
declare function Array.Size (self as Array)
' Gets the total number of elements that will fit in the array.
declare function Array.Capacity (self as Array)
' Returns -1 if the array has no elements, zero otherwise.
declare function Array.Empty (self as Array)
' Gets an element of the array. 'position' is the element index, 's' and 'o'
' are the segment and offset in memory for storing element data.
declare sub Array.Index (self as Array, position, s, o)
' Gets an element of the array. 'position' is the element index, 's' and 'o'
' are the segment and offset in memory for storing element data. Same as
' Array.Index but destination is unchanged is 'position' is out of bounds.
declare function Array.At (self as Array, position, s, o)
' Gets the index of the first element in the array. Always zero, added for
' completeness.
declare function Array.Begin (self as Array)
' Gets the index of one-past the last element in the array.
declare function Array.End (self as Array)
' Adds an element to the end of the array. 's' and 'o' are the segment and
' offset in memory for storing element data.
declare sub Array.PushBack (self as Array, s, o)
' Removes a number of elements from the end of the array. 'n' must be positive
' and less than or equal to Array.Size(self).
declare sub Array.PopBack (self as Array, n)
' Gets the first element of the array. 'position' is the element index, 's' and
' 'o' are the segment and offset in memory for storing element data.
declare sub Array.Front (self as Array, s, o)
' Gets the last element of the array. 'position' is the element index, 's' and
' 'o' are the segment and offset in memory for storing element data.
declare sub Array.Back (self as Array, s, o)
' Adds an element into the array immediately before element 'position'. 's'
' and 'o' are the segment and offset in memory for retrieving element data.
declare sub Array.Insert (self as Array, position, s, o)
' Adds 'n' copies of an element into the array immediately before the element
' 'position'. 's' and 'o' are the segment and offset in memory for retrieving
' element data.
declare sub Array.InsertN (self as Array, position, n, s, o)
' Erases an element from the array.
declare sub Array.Erase (self as Array, position)
' Erases a range of elements from the array. 'first' and 'last' are indexes to
' the first and one-past the last element in the range to erase.
declare sub Array.EraseRange (self as Array, first, last)
' Erases all elements from the array.
declare sub Array.Clear (self as Array)
' Some utility procedures..
declare sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
declare sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
declare function IntegerArrayToString$ (a as Array)
'' ::::: (main)
cls
dim i, a as Array
' Initialize an integer array to zero size.
Array.Init a, len(i), 0
print "array capacity: " + str$(Array.Capacity(a))
' Add some elements to the array.
i = 10 : Array.PushBack a, varseg(i), varptr(i)
i = 20 : Array.PushBack a, varseg(i), varptr(i)
i = 30 : Array.PushBack a, varseg(i), varptr(i)
print IntegerArrayToString$(a)
' Insert some elements into the array.
i = 40 : Array.Insert a, 1, varseg(i), varptr(i)
i = 50 : Array.InsertN a, 2, 3, varseg(i), varptr(i)
print IntegerArrayToString$(a)
' Remove all elements in the middle of the array.
Array.EraseRange a, Array.Begin(a)+1, Array.End(a)-1
print IntegerArrayToString$(a)
Array.Front a, varseg(i), varptr(i) : print "front: " + str$(i)
Array.Back a, varseg(i), varptr(i) : print "back: " + str$(i)
'' :::::
sub Array.Init (self as Array, elemsize, elemcount)
self.elemsize = elemsize
self.elemcount = elemcount
self.elemdata = ""
end sub
'' :::::
function Array.Size (self as Array)
Array.Size = self.elemcount
end function
'' :::::
function Array.Capacity (self as Array)
Array.Capacity = ARRAYMAXBYTELENGTH \ self.elemsize
end function
'' :::::
function Array.Empty (self as Array)
Array.Empty = (self.elemcount = 0)
end function
'' :::::
sub Array.Index (self as Array, i, dstseg, dstoff)
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize
end sub
'' :::::
function Array.At (self as Array, i, dstseg, dstoff)
Array.At = -1 ' assume error ('i' is out of bounds)
if (i < 0) or (i > self.elemcount) then exit function
Array.Index self, i, dstseg, dstoff
Array.At = 0 ' no error
end function
'' :::::
function Array.Begin (self as Array)
Array.Begin = 0
end function
'' :::::
function Array.End (self as Array)
Array.End = self.elemcount
end function
'' :::::
sub Array.PushBack (self as Array, srcseg, srcoff)
Array.Insert self, self.elemcount, srcseg, srcoff
end sub
'' :::::
sub Array.PopBack (self as Array, n)
if n < 0 then exit sub
if n > self.elemcount then n = self.elemcount
self.elemcount = self.elemcount - n
end sub
'' :::::
sub Array.Front (self as Array, s, o)
Array.Index self, 0, s, o
end sub
'' :::::
sub Array.Back (self as Array, s, o)
Array.Index self, self.elemcount - 1, s, o
end sub
'' :::::
sub Array.Insert (self as Array, i, s, o)
if (self.elemcount+1) * self.elemsize >= ARRAYMAXBYTELENGTH then exit sub
if (i < 0) or (i > self.elemcount) then exit sub
elemsafter = self.elemcount - i
' shift any elements to the right..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * (i + 1)
MemCopyBackward dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
' insert the new element..
MemCopy srcseg, srcoff, s, o, self.elemsize
self.elemcount = self.elemcount + 1
end sub
'' :::::
sub Array.InsertN (self as Array, i, n, s, o)
if (self.elemcount+n) * self.elemsize >= ARRAYMAXBYTELENGTH then exit sub
for r = 0 to n - 1
Array.Insert self, i+r, s, o
next
end sub
'' :::::
sub Array.Erase (self as Array, i)
if (i < 0) or (i >= self.elemcount) then exit sub
elemsafter = self.elemcount - i - 1
if 0 < elemsafter then
' shift any elements to the left..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * (i + 1)
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
end if
self.elemcount = self.elemcount - 1
end sub
'' :::::
sub Array.EraseRange (self as Array, first, last)
if (first < 0) or (first >= self.elemcount) then exit sub
if (last <= first) or (last > self.elemcount) then exit sub
elemsafter = self.elemcount - last
if 0 < elemsafter then
' shift any elements to the left..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * last
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * first
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
end if
self.elemcount = self.elemcount - (last - first)
end sub
'' :::::
sub Array.Clear (self as Array)
self.elemcount = 0
end sub
'' :::::
sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = 0 to size - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
def seg
end sub
'' :::::
sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = size - 1 to 0 step - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
def seg
end sub
'' :::::
function IntegerArrayToString$ (a as Array)
dim result as string : result = "("
for i = 0 to Array.Size(a) - 1
dim e as integer : Array.Index a, i, varseg(e), varptr(e)
result = result + "(" + str$(e) + ")"
next
- Array.At was added, it's a bounds-checked version of Array.Index (which does not check bounds anymore). The target memory will not be affected if Array.At is given an invalid index, while with Array.Index it will (so be careful).
- Array.Capacity was added, it tells how many total elements can possibly fit into the array, given the ARRAYMAXBYTELENGTH.
Some more small updates:
- Array.Insert/InsertN weren't allowing insertion if the array was to be equal to ARRAYMAXBYTELENGTH
- Array.PushBack was giving Array.Insert a reference to the array data (see note below)
- Minor commenting errors fixed, and a comment about Array members (see note below)
- Array.Resize added, works like REDIM, but allows you to specify element data when resizing to a larger size
- Example updated to demonstrate some of the changes. Enjoy.
NOTE: If it wasn't obvious, Array members should never be used directly. When implementing Array.Resize, I was passing the .elemcount member directly to Array.InsertN, which is bad because QBasic always passes by reference (BYREF) and thus the .elemcount was eventually getting corrupted. Passing a temporary variable fixed the problem, and so Array.PushBack was changed for consistency as well, even though I don't think there was a problem in that particular case.
' Copyright(c) 2008, Laanan Fisher
' Use and modify freely but please keep copyright notice.
defint a-z
' Maximum byte length for Array element data, adjust to suit your needs.
const ARRAYMAXBYTELENGTH = 512
' Generic variable-length array class with a maximum capacity.
type Array
' these members are 'private' and should never be used directly..
elemsize as integer
elemcount as integer
elemdata as string * ARRAYMAXBYTELENGTH
end type
' Initializes an array. 'elemsize' is the size, in bytes, of an element,
' 'elemcount' is the initial number of elements.
declare sub Array.Init (self as Array, elemsize, elemcount)
' Gets the number of elements in the array.
declare function Array.Size (self as Array)
' Gets the total number of elements that will fit in the array.
declare function Array.Capacity (self as Array)
' Returns -1 if the array has no elements, zero otherwise.
declare function Array.Empty (self as Array)
' Resizes the array to 'n' elements. Smaller resizes will remove any extra
' elements, while larger resizes will use 's' and 'o' as the segment and
' offset in memory for retrieving extra element data. If these addresses are
' zero, any elements created will have their data zero'd out.
declare sub Array.Resize (self as Array, n, s, o)
' Gets an element of the array. 'position' is the element index, 's' and 'o'
' are the segment and offset in memory for storing element data. Does no
' bounds checking on 'position'.
declare sub Array.Index (self as Array, position, s, o)
' Gets an element of the array. 'position' is the element index, 's' and 'o'
' are the segment and offset in memory for storing element data. Same as
' Array.Index but destination is unchanged if 'position' is out of bounds.
declare function Array.At (self as Array, position, s, o)
' Gets the index of the first element in the array. Always zero, added for
' completeness.
declare function Array.Begin (self as Array)
' Gets the index of one-past the last element in the array.
declare function Array.End (self as Array)
' Adds an element to the end of the array. 's' and 'o' are the segment and
' offset in memory for storing element data.
declare sub Array.PushBack (self as Array, s, o)
' Removes a number of elements from the end of the array. 'n' must be positive
' and less than or equal to Array.Size(self).
declare sub Array.PopBack (self as Array, n)
' Gets the first element of the array. 's' and 'o' are the segment and offset
' in memory for storing element data.
declare sub Array.Front (self as Array, s, o)
' Gets the last element of the array. 's' and 'o' are the segment and offset
' in memory for storing element data.
declare sub Array.Back (self as Array, s, o)
' Adds an element into the array immediately before element 'position'. 's'
' and 'o' are the segment and offset in memory for retrieving element data.
declare sub Array.Insert (self as Array, position, s, o)
' Adds 'n' copies of an element into the array immediately before the element
' 'position'. 's' and 'o' are the segment and offset in memory for retrieving
' element data.
declare sub Array.InsertN (self as Array, position, n, s, o)
' Erases an element from the array. 'position' is the index of the element to
' remove.
declare sub Array.Erase (self as Array, position)
' Erases a range of elements from the array. 'first' and 'last' are indexes to
' the first and one-past the last element in the range to erase.
declare sub Array.EraseRange (self as Array, first, last)
' Erases all elements from the array.
declare sub Array.Clear (self as Array)
' Some utility procedures..
declare sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
declare sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
declare sub MemSet (dstseg, dstoff, value, size)
declare function IntegerArrayToString$ (a as Array)
'' ::::: (main)
cls
dim i, a as Array
' Initialize an integer array to zero size.
Array.Init a, len(i), 0
print "array capacity: " + str$(Array.Capacity(a))
' Add some elements to the array.
i = 10 : Array.PushBack a, varseg(i), varptr(i)
i = 20 : Array.PushBack a, varseg(i), varptr(i)
i = 30 : Array.PushBack a, varseg(i), varptr(i)
print IntegerArrayToString$(a)
' Insert some elements into the array.
i = 40 : Array.Insert a, 1, varseg(i), varptr(i)
i = 50 : Array.InsertN a, 2, 3, varseg(i), varptr(i)
print IntegerArrayToString$(a)
' Resize the array larger with element data.
i = 60 : Array.Resize a, 10, varseg(i), varptr(i)
print IntegerArrayToString$(a)
' Resize the array larger, zero'ing extra elements.
Array.Resize a, 13, 0, 0
print IntegerArrayToString$(a)
' Resize the array smaller.
Array.Resize a, 3, 0, 0
print IntegerArrayToString$(a)
'' :::::
sub Array.Init (self as Array, elemsize, elemcount)
self.elemsize = elemsize
self.elemcount = elemcount
end sub
'' :::::
function Array.Size (self as Array)
Array.Size = self.elemcount
end function
'' :::::
function Array.Capacity (self as Array)
Array.Capacity = ARRAYMAXBYTELENGTH \ self.elemsize
end function
'' :::::
function Array.Empty (self as Array)
Array.Empty = (self.elemcount = 0)
end function
'' :::::
sub Array.Resize (self as Array, n, s, o)
if (n < 0) or (n = self.elemcount) then exit sub
if n < self.elemcount then
Array.EraseRange self, n-1, self.elemcount-1
else
elemsafter = n - self.elemcount
if (s = 0) and (o = 0) then
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * (self.elemcount)
MemSet dstseg, dstoff, 0, self.elemsize * elemsafter
self.elemcount = n
else
elemcount = self.elemcount
Array.InsertN self, elemcount, elemsafter, s, o
end if
end if
end sub
'' :::::
sub Array.Index (self as Array, i, dstseg, dstoff)
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize
end sub
'' :::::
function Array.At (self as Array, i, dstseg, dstoff)
Array.At = -1 ' assume error ('i' is out of bounds)
if (i < 0) or (i >= self.elemcount) then exit function
Array.Index self, i, dstseg, dstoff
Array.At = 0 ' no error
end function
'' :::::
function Array.Begin (self as Array)
Array.Begin = 0
end function
'' :::::
function Array.End (self as Array)
Array.End = self.elemcount
end function
'' :::::
sub Array.PushBack (self as Array, srcseg, srcoff)
elemcount = self.elemcount
Array.Insert self, elemcount, srcseg, srcoff
end sub
'' :::::
sub Array.PopBack (self as Array, n)
if n < 0 then exit sub
if n > self.elemcount then n = self.elemcount
self.elemcount = self.elemcount - n
end sub
'' :::::
sub Array.Front (self as Array, s, o)
Array.Index self, 0, s, o
end sub
'' :::::
sub Array.Back (self as Array, s, o)
Array.Index self, self.elemcount - 1, s, o
end sub
'' :::::
sub Array.Insert (self as Array, i, s, o)
if (self.elemcount+1) * self.elemsize > ARRAYMAXBYTELENGTH then exit sub
if (i < 0) or (i > self.elemcount) then exit sub
elemsafter = self.elemcount - i
' shift any elements to the right..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * i
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * (i + 1)
MemCopyBackward dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
' insert the new element..
MemCopy srcseg, srcoff, s, o, self.elemsize
self.elemcount = self.elemcount + 1
end sub
'' :::::
sub Array.InsertN (self as Array, i, n, s, o)
if (self.elemcount+n) * self.elemsize > ARRAYMAXBYTELENGTH then exit sub
for r = 0 to n - 1
Array.Insert self, i+r, s, o
next
end sub
'' :::::
sub Array.Erase (self as Array, i)
if (i < 0) or (i >= self.elemcount) then exit sub
elemsafter = self.elemcount - i - 1
if 0 < elemsafter then
' shift any elements to the left..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * (i + 1)
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * i
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
end if
self.elemcount = self.elemcount - 1
end sub
'' :::::
sub Array.EraseRange (self as Array, first, last)
if (first < 0) or (first >= self.elemcount) then exit sub
if (last <= first) or (last > self.elemcount) then exit sub
elemsafter = self.elemcount - last
if 0 < elemsafter then
' shift any elements to the left..
srcseg = varseg(self.elemdata)
srcoff = varptr(self.elemdata) + self.elemsize * last
dstseg = varseg(self.elemdata)
dstoff = varptr(self.elemdata) + self.elemsize * first
MemCopy dstseg, dstoff, srcseg, srcoff, self.elemsize * elemsafter
end if
self.elemcount = self.elemcount - (last - first)
end sub
'' :::::
sub Array.Clear (self as Array)
self.elemcount = 0
end sub
'' :::::
sub MemCopy (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = 0 to size - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
def seg
end sub
'' :::::
sub MemCopyBackward (dstseg, dstoff, srcseg, srcoff, size)
if size <= 0 then exit sub
for x = size - 1 to 0 step - 1
def seg = srcseg
byte = peek(srcoff + x)
def seg = dstseg
poke(dstoff + x), byte
next
def seg
end sub
'' :::::
sub MemSet (dstseg, dstoff, value, size)
if size <= 0 then exit sub
for x = 0 to size - 1
def seg = dstseg
poke(dstoff + x), value
next
def seg
end sub
'' :::::
function IntegerArrayToString$ (a as Array)
dim result as string : result = "("
for i = 0 to Array.Size(a) - 1
dim e as integer : Array.Index a, i, varseg(e), varptr(e)
result = result + "(" + str$(e) + ")"
next