ReneMiner
30-05-2013, 10:55
Today I have some small example to store any list of UDT to some enumerated List-Index without the need of creating arrays for those list-elements because it uses local virtual variables mostly and hides your data in the endless depth of heap.
It uses one small global array to organize this. The array-size depends on count of lists * 16 bytes - so the array uses only 16 Bytes for one complete list, no matter how many elements it has.
Size of a list is limited by your memory and the count of elements per list which must not exceed 2^31-1 (&H7FFFFFFF)
UserLists-Unit comes with 9 Functions, short description:
First of all you'll have to create some list, therefore call
List_CreateNew(yourListIndex, sizeOf(yourType))
- will return value <> 0 if succeeds
(value is the associated index of Userlists-array)
thereafter you can add new elements to your list using:
List_AddElement(yourListIndex)
which will return a pointer to the new created element or 0 if fails
List_Exists(yourListIndex)
will return a value <> 0 if a list with yourListIndex exists
the number represents the index of Userlists-array which is assigned to yourListIndex
List_CurrentElement(yourListIndex)
will return a pointer to the current element of your list or 0 if fails
List_FirstElement(yourListIndex)
will return a pointer to the first element of your list and make this the current element of yourListIndex or 0 if fails
List_LastElement(yourListIndex)
will return a pointer to the last element of your list and make this the current element of yourListIndex or 0 if fails
List_NextElement(yourListIndex)
will return a pointer to the next element of your list and make this the current element of yourListIndex or 0 if fails
List_PreviousElement(yourListIndex)
will return a pointer to the previous element of your list and make this the current element of yourListIndex or 0 if fails
List_Reset(yourListIndex)
will set the current element of yourListIndex to 0 - so you are before the first element and can go through the list using for example
While List_NextElement(yourListIndex)
' do something with current element
Wend
' this is demonstration how to use
Uses "Console"
#INCLUDE "UserLists.tBasicU"
Type t_myType
A As Long
B As Byte
C As String
End Type
%myList1 = 333 ' can be any from 1 To &H7FFFFFFF
Function TBMain()
If List_CreateNew(%myList1, SizeOf(t_myType)) Then
Local lType As t_myType At List_AddElement(%myList1)
lType.A = 123
lType.B = 1
lType.C = "Hello"
SetAt( lType, List_AddElement(%myList1) )
lType.A = 345
lType.B = 2
lType.C = "World"
SetAt( lType, List_AddElement(%myList1) )
lType.A = 567
lType.B = 3
lType.C = "Nice weather today..."
' go through list without use of additional variables:
List_Reset(%myList1) ' set current element-index before first listed element
While List_NextElement(%myList1)
SetAt( lType, List_CurrentElement(%myList1) )
PrintL lType.C
Wend
PrintL
' now backward, needs a storage-var:
DWord pElement = List_LastElement(%myList1)
While pElement
SetAt( lType, pElement)
PrintL Str$(lType.A)
pElement = List_PreviousElement(%myList1)
Wend
PrintL
' now total list- (create array of pointers):
Long lListNumber = List_Exists(%myList1)
Long i
Local dElement(HEAP_Size(Userlists(lListNumber).Elements)/SizeOf(DWord)) As DWord At Userlists(lListNumber).Elements
If UBound(dElement) Then
For i = 1 To UBound(dElement)
SetAt( lType, dElement(i) )
PrintL Str$(lType.B)
Next
EndIf
EndIf
WaitKey
End Function
and this is the Userlists.tBasicU, save next to the "main-file"
Type t_UserList
UserID As Long
lSize As Long
Current As Long
Elements As DWord
End Type
Dim Userlists() As t_UserList : ReDim Userlists(1)
' --------------------------------------------------------------------------
Function List_CreateNew(ByVal lID As Long, ByVal lSize As Long) As Long
If lID < 1 Or lSize < 1 Then Return 0
Local lList As Long
Local sID As String = MKL$(lID)
lList = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
If lList Then Return 0
sID = MKL$(0)
lList = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
If lList = 0 Then
ReDim Preserve Userlists(UBound(Userlists) + 1)
lList = UBound(Userlists)
EndIf
With Userlists(lList)
.UserID = lID
.lSize = lSize
End With
Function = lList
End Function
' --------------------------------------------------------------------------
Function List_Exists(ByVal lID As Long) As Long
Static sID As String
sID = MKL$(lID)
Function = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
End Function
' --------------------------------------------------------------------------
Function List_AddElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
Local sBuffer As String = String$(Userlists(lList).lSize, MKBYT$(0))
Local pResult As DWord = HEAP_AllocByStr(sBuffer)
If Userlists(lList).Elements Then
sBuffer = Peek$(Userlists(lList).Elements, HEAP_Size(Userlists(lList).Elements)) + MKDWD$(pResult)
Userlists(lList).Elements = HEAP_Realloc(Userlists(lList).Elements, StrPtrLen(StrPtr(sBuffer)) )
Poke$(Userlists(lList).Elements, sBuffer)
Else
Userlists(lList).Elements = HEAP_AllocByStr(MKDWD$(pResult))
EndIf
Userlists(lList).Current = HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord)
Function = pResult
End Function
' --------------------------------------------------------------------------
Function List_FirstElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
Userlists(lList).Current = 1
Function = Peek(DWord, Userlists(lList).Elements)
EndIf
End Function
' --------------------------------------------------------------------------
Function List_NextElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord) > Userlists(lList).Current Then
Function = Peek(DWord, Userlists(lList).Elements + Userlists(lList).Current * SizeOf(DWord) )
Userlists(lList).Current += 1
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_LastElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
Userlists(lList).Current = HEAP_Size( Userlists(lList).Elements) / SizeOf(DWord)
Function = Peek(DWord, Userlists(lList).Elements + HEAP_Size(Userlists(lList).Elements) - SizeOf(DWord) )
EndIf
End Function
' --------------------------------------------------------------------------
Function List_PreviousElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If Userlists(lList).Current > 1 Then
Userlists(lList).Current -= 1
Function = Peek(DWord, Userlists(lList).Elements + (Userlists(lList).Current - 1) * SizeOf(DWord) )
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_CurrentElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If Userlists(lList).Current Then
If HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord) >= Userlists(lList).Current Then
Function = Peek(DWord, Userlists(lList).Elements + (Userlists(lList).Current - 1) * SizeOf(DWord) )
EndIf
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_Reset(ByVal lID As Long) As Boolean
Local lList As Long = List_Exists(lID)
If Not lList Then Return FALSE
Userlists(lList).Current = 0
Function = TRUE
End Function
' --------------------------------------------------------------------------
'Function List_GetElementCount(ByVal lID as Long) as Long
' Local lList As Long = List_Exists(lID)
' If Not lList Then Return 0
' Function = HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord)
'End Function
have fun!
It uses one small global array to organize this. The array-size depends on count of lists * 16 bytes - so the array uses only 16 Bytes for one complete list, no matter how many elements it has.
Size of a list is limited by your memory and the count of elements per list which must not exceed 2^31-1 (&H7FFFFFFF)
UserLists-Unit comes with 9 Functions, short description:
First of all you'll have to create some list, therefore call
List_CreateNew(yourListIndex, sizeOf(yourType))
- will return value <> 0 if succeeds
(value is the associated index of Userlists-array)
thereafter you can add new elements to your list using:
List_AddElement(yourListIndex)
which will return a pointer to the new created element or 0 if fails
List_Exists(yourListIndex)
will return a value <> 0 if a list with yourListIndex exists
the number represents the index of Userlists-array which is assigned to yourListIndex
List_CurrentElement(yourListIndex)
will return a pointer to the current element of your list or 0 if fails
List_FirstElement(yourListIndex)
will return a pointer to the first element of your list and make this the current element of yourListIndex or 0 if fails
List_LastElement(yourListIndex)
will return a pointer to the last element of your list and make this the current element of yourListIndex or 0 if fails
List_NextElement(yourListIndex)
will return a pointer to the next element of your list and make this the current element of yourListIndex or 0 if fails
List_PreviousElement(yourListIndex)
will return a pointer to the previous element of your list and make this the current element of yourListIndex or 0 if fails
List_Reset(yourListIndex)
will set the current element of yourListIndex to 0 - so you are before the first element and can go through the list using for example
While List_NextElement(yourListIndex)
' do something with current element
Wend
' this is demonstration how to use
Uses "Console"
#INCLUDE "UserLists.tBasicU"
Type t_myType
A As Long
B As Byte
C As String
End Type
%myList1 = 333 ' can be any from 1 To &H7FFFFFFF
Function TBMain()
If List_CreateNew(%myList1, SizeOf(t_myType)) Then
Local lType As t_myType At List_AddElement(%myList1)
lType.A = 123
lType.B = 1
lType.C = "Hello"
SetAt( lType, List_AddElement(%myList1) )
lType.A = 345
lType.B = 2
lType.C = "World"
SetAt( lType, List_AddElement(%myList1) )
lType.A = 567
lType.B = 3
lType.C = "Nice weather today..."
' go through list without use of additional variables:
List_Reset(%myList1) ' set current element-index before first listed element
While List_NextElement(%myList1)
SetAt( lType, List_CurrentElement(%myList1) )
PrintL lType.C
Wend
PrintL
' now backward, needs a storage-var:
DWord pElement = List_LastElement(%myList1)
While pElement
SetAt( lType, pElement)
PrintL Str$(lType.A)
pElement = List_PreviousElement(%myList1)
Wend
PrintL
' now total list- (create array of pointers):
Long lListNumber = List_Exists(%myList1)
Long i
Local dElement(HEAP_Size(Userlists(lListNumber).Elements)/SizeOf(DWord)) As DWord At Userlists(lListNumber).Elements
If UBound(dElement) Then
For i = 1 To UBound(dElement)
SetAt( lType, dElement(i) )
PrintL Str$(lType.B)
Next
EndIf
EndIf
WaitKey
End Function
and this is the Userlists.tBasicU, save next to the "main-file"
Type t_UserList
UserID As Long
lSize As Long
Current As Long
Elements As DWord
End Type
Dim Userlists() As t_UserList : ReDim Userlists(1)
' --------------------------------------------------------------------------
Function List_CreateNew(ByVal lID As Long, ByVal lSize As Long) As Long
If lID < 1 Or lSize < 1 Then Return 0
Local lList As Long
Local sID As String = MKL$(lID)
lList = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
If lList Then Return 0
sID = MKL$(0)
lList = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
If lList = 0 Then
ReDim Preserve Userlists(UBound(Userlists) + 1)
lList = UBound(Userlists)
EndIf
With Userlists(lList)
.UserID = lID
.lSize = lSize
End With
Function = lList
End Function
' --------------------------------------------------------------------------
Function List_Exists(ByVal lID As Long) As Long
Static sID As String
sID = MKL$(lID)
Function = Array Scan Userlists, Byte(UDT_ElementByte(Userlists(1).UserID),SizeOf(Long)), = sID
End Function
' --------------------------------------------------------------------------
Function List_AddElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
Local sBuffer As String = String$(Userlists(lList).lSize, MKBYT$(0))
Local pResult As DWord = HEAP_AllocByStr(sBuffer)
If Userlists(lList).Elements Then
sBuffer = Peek$(Userlists(lList).Elements, HEAP_Size(Userlists(lList).Elements)) + MKDWD$(pResult)
Userlists(lList).Elements = HEAP_Realloc(Userlists(lList).Elements, StrPtrLen(StrPtr(sBuffer)) )
Poke$(Userlists(lList).Elements, sBuffer)
Else
Userlists(lList).Elements = HEAP_AllocByStr(MKDWD$(pResult))
EndIf
Userlists(lList).Current = HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord)
Function = pResult
End Function
' --------------------------------------------------------------------------
Function List_FirstElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
Userlists(lList).Current = 1
Function = Peek(DWord, Userlists(lList).Elements)
EndIf
End Function
' --------------------------------------------------------------------------
Function List_NextElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord) > Userlists(lList).Current Then
Function = Peek(DWord, Userlists(lList).Elements + Userlists(lList).Current * SizeOf(DWord) )
Userlists(lList).Current += 1
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_LastElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
Userlists(lList).Current = HEAP_Size( Userlists(lList).Elements) / SizeOf(DWord)
Function = Peek(DWord, Userlists(lList).Elements + HEAP_Size(Userlists(lList).Elements) - SizeOf(DWord) )
EndIf
End Function
' --------------------------------------------------------------------------
Function List_PreviousElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If Userlists(lList).Current > 1 Then
Userlists(lList).Current -= 1
Function = Peek(DWord, Userlists(lList).Elements + (Userlists(lList).Current - 1) * SizeOf(DWord) )
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_CurrentElement(ByVal lID As Long) As DWord
Local lList As Long = List_Exists(lID)
If Not lList Then Return 0
If Userlists(lList).Elements Then
If Userlists(lList).Current Then
If HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord) >= Userlists(lList).Current Then
Function = Peek(DWord, Userlists(lList).Elements + (Userlists(lList).Current - 1) * SizeOf(DWord) )
EndIf
EndIf
EndIf
End Function
' --------------------------------------------------------------------------
Function List_Reset(ByVal lID As Long) As Boolean
Local lList As Long = List_Exists(lID)
If Not lList Then Return FALSE
Userlists(lList).Current = 0
Function = TRUE
End Function
' --------------------------------------------------------------------------
'Function List_GetElementCount(ByVal lID as Long) as Long
' Local lList As Long = List_Exists(lID)
' If Not lList Then Return 0
' Function = HEAP_Size(Userlists(lList).Elements)/SizeOf(DWord)
'End Function
have fun!