01-18-2024, 09:11 PM
Sorry to say, to my knowledge QB64 does not directly support that. However I have had a similar issue and have a couple of work arounds.
Two methods I have are to use STRINGS or to use _MEM's. They both have their pro and cons.
String method is the simpliest.
The demo above uses longs which is 4 bytes. Integers in QB64 are 2 bytes.
The _MEM method is a bit more complicated.
_MEM have to be initialized before use, but they can be resized.
Two methods I have are to use STRINGS or to use _MEM's. They both have their pro and cons.
String method is the simpliest.
Code: (Select All)
' String Array Test
' Arrays must start at index 1
TYPE tUDT
longArray AS STRING * 1028 ' arraysize * 4 + 4
END TYPE
DIM udt AS tUDT
DIM iter AS LONG
FOR iter = 1 TO 256
SetArrayLong udt.longArray, iter, iter * 2000000
PRINT iter; ": "; getArrayLong(udt.longArray, iter)
NEXT
FUNCTION getArrayLong& (s AS STRING, p AS LONG)
IF p > 0 AND p * 4 + 4 <= LEN(s) THEN getArrayLong = CVL(MID$(s, p * 4, 4))
END FUNCTION
SUB SetArrayLong (s AS STRING, p AS LONG, v AS LONG)
IF p > 0 AND p * 4 + 4 <= LEN(s) THEN MID$(s, p * 4) = MKL$(v)
END SUB
FUNCTION getArraySingle! (s AS STRING, p AS LONG)
IF p > 0 AND p * 4 + 4 <= LEN(s) THEN getArraySingle = CVS(MID$(s, p * 4, 4))
END FUNCTION
SUB SetArraySingle (s AS STRING, p AS LONG, v AS SINGLE)
IF p > 0 AND p * 4 + 4 <= LEN(s) THEN MID$(s, p * 4) = MKS$(v)
END SUB
FUNCTION getArrayInteger% (s AS STRING, p AS LONG)
IF p > 0 AND p * 2 + 2 <= LEN(s) THEN getArrayInteger = CVI(MID$(s, p * 2, 2))
END FUNCTION
SUB SetArrayInteger (s AS STRING, p AS LONG, v AS INTEGER)
IF p > 0 AND p * 2 + 2 <= LEN(s) THEN MID$(s, p * 2) = MKI$(v)
END SUB
FUNCTION getArrayDouble# (s AS STRING, p AS LONG)
IF p > 0 AND p * 8 + 8 <= LEN(s) THEN getArrayDouble = CVL(MID$(s, p * 8, 8))
END FUNCTION
SUB SetArrayDouble (s AS STRING, p AS LONG, v AS DOUBLE)
IF p > 0 AND p * 8 + 8 <= LEN(s) THEN MID$(s, p * 8) = MKD$(v)
END SUB
The demo above uses longs which is 4 bytes. Integers in QB64 are 2 bytes.
The _MEM method is a bit more complicated.
Code: (Select All)
' Program to create an arrays in a UDT
SCREEN 12: _FONT 8
_TITLE "UDT_ARRAYS.bas"
DIM AS LONG i
DIM AS DOUBLE v
CONST cMAXELEMENTS = 10
' set byte counts for the data types
CONST cDT_BYTE = 1
CONST cDT_INTEGER = 2
CONST cDT_LONG = 4
CONST cDT_SINGLE = 4
CONST cDT_DOUBLE = 8
CONST cDT_INTEGER64 = 8
CONST cDT_FLOAT = 32
TYPE tARRAYS
UDT_Array0 AS _MEM ' Array of Doubles
UDT_Array1 AS _MEM ' Array of Singles
UDT_Array2 AS _MEM ' Array of Integers
END TYPE
DIM AS tARRAYS UDT
' initialize the array
createUDTArray UDT.UDT_Array0, cDT_DOUBLE, cMAXELEMENTS
createUDTArray UDT.UDT_Array1, cDT_SINGLE, cMAXELEMENTS
createUDTArray UDT.UDT_Array2, cDT_INTEGER, cMAXELEMENTS
PRINT "ARRAY Doubles ARRAY Singles ARRAY Integers"
' set the array to random values
PRINT "Create initial Values, Store them, and retrieve"
FOR i = 0 TO cMAXELEMENTS
v = INT(RND * 5 * 100) / 100
setElementDBL UDT.UDT_Array0, i, v
PRINT USING "index: ##-> #.## "; i; getElementDBL(UDT.UDT_Array0, i);
v = INT(RND * 5 * 100) / 100
setElementSIGL UDT.UDT_Array1, i, v
PRINT USING "index: ##-> #.## "; i; getElementSIGL(UDT.UDT_Array1, i);
v = INT(RND * 5)
setElementINT UDT.UDT_Array2, i, v
PRINT USING "index: ##-> #.##"; i; getElementINT(UDT.UDT_Array2, i)
NEXT
'resize array
resizeUDTArray UDT.UDT_Array0, cDT_DOUBLE, cMAXELEMENTS * 2
resizeUDTArray UDT.UDT_Array1, cDT_SINGLE, cMAXELEMENTS * 2
resizeUDTArray UDT.UDT_Array2, cDT_INTEGER, cMAXELEMENTS * 2
' retrieve values from array
PRINT "Double the size of the array"
FOR i = 0 TO cMAXELEMENTS * 2
PRINT USING "index: ##-> #.## "; i; getElementDBL(UDT.UDT_Array0, i);
PRINT USING "index: ##-> #.## "; i; getElementSIGL(UDT.UDT_Array1, i);
PRINT USING "index: ##-> #.##"; i; getElementINT(UDT.UDT_Array2, i)
NEXT
'resize array
resizeUDTArray UDT.UDT_Array0, cDT_DOUBLE, cMAXELEMENTS / 2
resizeUDTArray UDT.UDT_Array1, cDT_SINGLE, cMAXELEMENTS / 2
resizeUDTArray UDT.UDT_Array2, cDT_INTEGER, cMAXELEMENTS / 2
' retrieve values from array
PRINT "Half the size of the array"
FOR i = 0 TO cMAXELEMENTS / 2
PRINT USING "index: ##-> #.## "; i; getElementDBL(UDT.UDT_Array0, i);
PRINT USING "index: ##-> #.## "; i; getElementSIGL(UDT.UDT_Array1, i);
PRINT USING "index: ##-> #.##"; i; getElementINT(UDT.UDT_Array2, i)
NEXT
SUB createUDTArray (o AS _MEM, dt AS LONG, size AS LONG)
' make array one larger than number of elements
o = _MEMNEW((size + 1) * dt) ' 'dt' is the number of bytes in the datatype
END SUB
SUB resizeUDTArray (o AS _MEM, dt AS LONG, size AS LONG)
DIM AS _MEM old
DIM AS LONG iter
' Copy old _MEM to a temp _MEM
old = o
' Create new array of the new size
createUDTArray o, dt, size
'clear new array
iter = 0: DO WHILE iter < o.SIZE
_MEMPUT o, o.OFFSET + iter, 0 AS _BYTE
iter = iter + 1: LOOP
' Copy data from old array to new array
iter = 0: DO WHILE iter < o.SIZE AND iter < old.SIZE
_MEMPUT o, o.OFFSET + iter, _MEMGET(old, old.OFFSET + iter, _BYTE) AS _BYTE
iter = iter + 1: LOOP
' free old array
_MEMFREE old
END SUB
FUNCTION getElementBYTE%% (o AS _MEM, element AS LONG)
getElementBYTE = _MEMGET(o, o.OFFSET + (element * cDT_BYTE), _BYTE)
END FUNCTION
SUB setElementBYTE (o AS _MEM, element AS LONG, v AS _BYTE)
_MEMPUT o, o.OFFSET + (element * cDT_BYTE), v AS _BYTE
END SUB
FUNCTION getElementINT% (o AS _MEM, element AS LONG)
getElementINT = _MEMGET(o, o.OFFSET + (element * cDT_INTEGER), INTEGER)
END FUNCTION
SUB setElementINT (o AS _MEM, element AS LONG, v AS INTEGER)
_MEMPUT o, o.OFFSET + (element * cDT_INTEGER), v AS INTEGER
END SUB
FUNCTION getElementLNG& (o AS _MEM, element AS LONG)
getElementLNG = _MEMGET(o, o.OFFSET + (element * cDT_LONG), LONG)
END FUNCTION
SUB setElementLNG (o AS _MEM, element AS LONG, v AS LONG)
_MEMPUT o, o.OFFSET + (element * cDT_LONG), v AS LONG
END SUB
FUNCTION getElementSIGL! (o AS _MEM, element AS LONG)
getElementSIGL = _MEMGET(o, o.OFFSET + (element * cDT_SINGLE), SINGLE)
END FUNCTION
SUB setElementSIGL (o AS _MEM, element AS LONG, v AS SINGLE)
_MEMPUT o, o.OFFSET + (element * cDT_SINGLE), v AS SINGLE
END SUB
FUNCTION getElementDBL# (o AS _MEM, element AS LONG)
getElementDBL = _MEMGET(o, o.OFFSET + (element * cDT_DOUBLE), DOUBLE)
END FUNCTION
SUB setElementDBL (o AS _MEM, element AS LONG, v AS DOUBLE)
_MEMPUT o, o.OFFSET + (element * cDT_DOUBLE), v AS DOUBLE
END SUB
FUNCTION getElementINT64&& (o AS _MEM, element AS LONG)
getElementINT64 = _MEMGET(o, o.OFFSET + (element * cDT_INTEGER64), _INTEGER64)
END FUNCTION
SUB setElementINT64 (o AS _MEM, element AS LONG, v AS _INTEGER64)
_MEMPUT o, o.OFFSET + (element * cDT_INTEGER64), v AS _INTEGER64
END SUB
FUNCTION getElementFLT## (o AS _MEM, element AS LONG)
getElementFLT = _MEMGET(o, o.OFFSET + (element * cDT_FLOAT), _FLOAT)
END FUNCTION
SUB setElementFLT (o AS _MEM, element AS LONG, v AS _FLOAT)
_MEMPUT o, o.OFFSET + (element * cDT_FLOAT), v AS _FLOAT
END SUB
_MEM have to be initialized before use, but they can be resized.
2D physics engine https://github.com/mechatronic3000/fzxNGN
Untitled Rouge-like https://github.com/mechatronic3000/Untitled-Rougelike
QB Pool https://github.com/mechatronic3000/QBPool
Untitled Rouge-like https://github.com/mechatronic3000/Untitled-Rougelike
QB Pool https://github.com/mechatronic3000/QBPool