I have also another solution to emulate dynamic udt-subsets which does not use strings but heap to store, check this example:
Uses "Console"
Alias DWord As DynamicVariable
Type t_Test
bBytes As DynamicVariable
lLongs As DynamicVariable
sStrings As DynamicVariable
End Type
Dim DynamicReserve As String ' use this in all subs + functions - so no local declaration-time needed
Dim foo As t_Test
Dim i As Long
' "SetBytes(foo.bBytes, 1, 2, 4, 8)" :
foo.bBytes = HEAP_AllocByStr(MKBYT$(1) + MKBYT$(2) + MKBYT$(4) + MKBYT$(8))
If foo.bBytes Then
PrintL "UBound foo.bBytes =" + Str$(HEAP_Size(foo.bBytes))
PrintL "------------------------------"
For i = 1 To HEAP_Size(foo.bBytes)' / SizeOf(Byte)
PrintL "foo.bBytes(" + TStr$(i) + ") = " + Str$(Peek(Byte, foo.bBytes + i-1))
Next
EndIf
foo.lLongs = HEAP_AllocByStr(MKL$(&H10000000) + MKL$(&H20000000) + MKL$(&H30000000) + MKL$(&H40000000))
If foo.lLongs Then
PrintL "UBound foo.lLongs =" + Str$(HEAP_Size(foo.lLongs)/SizeOf(Long))
PrintL "------------------------------"
For i = 1 To HEAP_Size(foo.lLongs) / SizeOf(Long)
PrintL "foo.lLongs(" + TStr$(i) + ") = " + Str$(Peek(Long, foo.lLongs + (i-1) * SizeOf(Long) ))
Next
EndIf
PrintL "------------------------------"
PrintL "append 1 byte value 32 to foo.bBytes..."
foo.bBytes = AddByte(foo.bBytes, 32)
PrintL "oops, forgot 16, so insert at position 5"
PrintL
foo.bBytes = InsertByte(foo.bBytes, 5, 16)
PrintL "now foo.bBytes has" + Str$(HEAP_Size(foo.bBytes)) + " elements"
PrintL "------------------------------"
If foo.bBytes Then
For i = 1 To HEAP_Size(foo.bBytes)' / SizeOf(Byte)
PrintL "foo.bBytes(" + TStr$(i) + ") = " + Str$(Peek(Byte, foo.bBytes + i-1))
Next
EndIf
PrintL "------------------------------"
foo.sStrings = AddString(foo.sStrings, "World")
foo.sStrings = AddString(foo.sStrings, "Hello")
PrintL GetString(foo.sStrings, 2)
PrintL GetString(foo.sStrings, 1)
WaitKey
' ------------------------------------------
Function AddByte(ByVal pBytes As DynamicVariable, Optional bVal As Byte) As DynamicVariable
If HEAP_Size(pBytes) Then
DynamicReserve = Peek$(pBytes, HEAP_Size(pBytes)) + MKBYT$(bVal)
HEAP_Free(pBytes)
pBytes = HEAP_AllocByStr(DynamicReserve)
Else
pBytes = HEAP_AllocByStr(MKBYT$(bVal))
EndIf
Function = pBytes
End Function
' ------------------------------
Function InsertByte(ByVal pBytes As DynamicVariable, ByVal Position As Long, Optional bVal As Byte) As DynamicVariable
If HEAP_Size(pBytes) Then
If Position <= 1 Then
DynamicReserve = MKBYT$(bVal) + Peek$(pBytes, HEAP_Size(pBytes))
ElseIf Position > HEAP_Size(pBytes) Then
DynamicReserve = Peek$(pBytes, HEAP_Size(pBytes)) + MKBYT$(bVal)
Else
DynamicReserve = Peek$(pBytes, Position - 1) + MKBYT$(bVal) + Peek$(pBytes + Position - 1, HEAP_Size(pBytes) + 1 - Position )
EndIf
HEAP_Free(pBytes)
pBytes = HEAP_AllocByStr(DynamicReserve)
Else
pBytes = HEAP_AllocByStr(MKBYT$(bVal))
EndIf
Function = pBytes
End Function
' ---------------------------------
Function AddString(ByVal pStrings As DynamicVariable, Optional sString As String) As DynamicVariable
If HEAP_Size(pStrings) Then
If sString = "" Then
DynamicReserve = Peek$(pStrings, HEAP_Size(pStrings)) + MKDWD$(0)
Else
DynamicReserve = Peek$(pStrings, HEAP_Size(pStrings)) + MKDWD$(HEAP_AllocByStr(sString))
EndIf
HEAP_Free(pStrings)
pStrings = HEAP_AllocByStr(DynamicReserve)
Else
If sString = "" Then
pStrings = HEAP_AllocByStr(MKDWD$(0))
Else
pStrings = HEAP_AllocByStr(MKDWD$(HEAP_AllocByStr(sString)) )
EndIf
EndIf
Function = pStrings
End Function
' --------------------
Function GetString( ByVal pStrings As DynamicVariable, ByVal Position As Long) As String
If Not Between(Position, 1, HEAP_Size(pStrings)/SizeOf(DynamicVariable)) Then Return ""
If Peek(DynamicVariable, pStrings + (Position-1) * SizeOf(DynamicVariable)) = 0 Then Return ""
Function = Peek$(Peek(DynamicVariable, pStrings + (Position-1) * SizeOf(DynamicVariable)), HEAP_Size(Peek(DynamicVariable, pStrings + (Position-1) * SizeOf(DynamicVariable) )) )
End Function
AddByte is not really needed as a seperate function, but to clear the example...Of course it would need Insert-Functions for all used types and also some special treatment when replacing Strings...
In any case you can Dim a virtual array over this - like
local myBytes(Heap_Size(foo.bBytes)) as Byte at foo.bBytes
for strings you put a Dword-Array over to read out the "String-Pointers"
Bookmarks