PDA

View Full Version : User-defined typed lists



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!