This list works well but I don't understand the extra code in the get previous node function:
Code: Select all
Function ListGetPrev(list As listnode Ptr) As listnode Ptr
' can't do anything to a null list
If (list = 0) Then Return 0
' this is needed for below
If (list->pPrev = 0) Then Return 0 ' what is this and the line below for
' since the list starts with a null node (pPrev and pData = 0),
' the first should be the one right after the real first.
If (list->pPrev->pPrev = 0) Then Return 0
Return list->pPrev
End Function
I also created an oop version:
Code: Select all
Type TListNode
As Any Ptr pData
As TListNode Ptr pNext
As TListNode Ptr pPrev
End Type
Type TList
As TListNode Ptr null_node
As Integer node_count
Declare Constructor (ByRef node As TListNode Ptr = 0)
Declare Destructor()
Declare Function add_item(ByVal item As Any Ptr) As Any Ptr
Declare Function add_head(ByVal item As Any Ptr) As Any Ptr
Declare Function get_first_item() As TListNode Ptr
Declare Function get_last_item() As TListNode Ptr
Declare Function get_next_item(ByVal node As TListNode Ptr) As TListNode Ptr
Declare Function get_prev_item(ByVal node As TListNode Ptr) As TListNode Ptr
Declare Function get_data(ByVal node As TListNode Ptr) As Any Ptr
Declare Function remove_item(ByVal node As TListNode Ptr, ByVal bDelete As boolean = 0) As TListNode Ptr
Declare Sub remove_all(ByVal bDelete As boolean = 0)
End Type
Destructor TList()
'
Dim As TListNode Ptr node
this.remove_all(TRUE)
DeAllocate(this.null_node)
this.null_node = 0
End Destructor
Function TList.add_head(ByVal item As Any Ptr) As Any Ptr
Dim As TListNode Ptr pTemp
If (this.null_node = 0) Then Return 0
pTemp = this.null_node->pNext
this.null_node->pNext = CAllocate(Len(TListNode))
this.null_node->pNext->pPrev = this.null_node
this.null_node->pNext->pData = item
this.null_node->pNext->pNext = pTemp
If (pTemp <> 0) Then
pTemp->pPrev = this.null_node->pNext
End If
Return item
End Function
Sub TList.remove_all(ByVal bDelete As boolean = FALSE)
' does not remove null node
Dim As TListNode Ptr node, pTemp
node = this.get_last_item()
While node <> 0 And node <> this.null_node
pTemp = node->pPrev
If (cbool(node->pData <> 0) = TRUE AndAlso (bDelete = TRUE)) Then
DeAllocate node->pData
node->pData = 0
EndIf
this.remove_item(node)
node = pTemp
Wend
End Sub
Function TList.remove_item(ByVal node As TListNode Ptr, ByVal bDelete As boolean = 0) As TListNode Ptr
Dim As TListNode Ptr pPrev
Dim As TListNode Ptr pNext
If (node = 0) Then Return 0
pPrev = node->pPrev
pNext = node->pNext
If (cbool(node->pData <> 0) = TRUE AndAlso (bDelete = FALSE)) Then
Deallocate node->pData
node->pData = 0
EndIf
DeAllocate node
node = 0
If (pPrev <> 0) Then
pPrev->pNext = pNext
End If
If (pNext <> 0) Then
pNext->pPrev = pPrev
End If
this.node_count -= 1
Return pNext
End Function
Function TList.get_next_item(ByVal node As TListNode Ptr) As TListNode Ptr
If (node = 0) Then Return 0
Return node->pNext
End Function
Function TList.get_prev_item(ByVal node As TListNode Ptr) As TListNode Ptr
' can't do anything to a null list
If (node = 0) Then Return 0
' this is needed for below
'If (list->pPrev = 0) Then Return 0
'' since the list starts with a null node (pPrev and pData = 0),
'' the first should be the one right after the real first.
'If (node->pPrev->pPrev = 0) Then Return 0
Return node->pPrev
End Function
Function TList.get_first_item() As TListNode Ptr
If (this.null_node = 0) Then Return 0
Return this.null_node->pNext
End Function
Function TList.get_data(ByVal node As TListNode Ptr) As Any Ptr
If (this.null_node = 0) Then Return 0
Return node->pData
End Function
Function TList.get_last_item() As TListNode Ptr
Dim As TListNode Ptr pTemp
If (this.null_node = 0) Then Return 0
pTemp = this.null_node
While (pTemp->pNext <> 0)
pTemp = pTemp->pNext
Wend
Return pTemp
End Function
Function TList.add_item(ByVal item As Any Ptr) As Any Ptr
Dim As TListNode Ptr pTemp
If (this.null_node = 0) Then Return 0 'item
pTemp = this.get_last_item()
pTemp->pNext = CAllocate(Len(TListNode))
pTemp->pNext->pPrev = pTemp
pTemp->pNext->pData = item
this.node_count += 1
Return item
End Function
Constructor TList(ByRef node As TListNode Ptr = 0)
' this doubles as default constructor
Dim As TListNode Ptr pTemp
this.null_node = CAllocate(Len(TListNode))
node = this.null_node
'? "ppp";node
End Constructor
'----------------------------------------------------------------------------------------------------------------
'----------------------------------------------------------------------------------------------------------------
Dim As TList list
Dim As String Ptr item ', test
Dim As tlistnode Ptr test
'
item = list.add_item(Callocate(Len(String)))
*item = "hello"
item = list.add_item(Callocate(Len(String)))
*item = "world"
item = list.add_item(Callocate(Len(String)))
*item = "moo"
'
test = list.get_first_item()
item = list.get_data(test)
? *item
test = list.get_last_item()
item = list.get_data(test)
? *item
sleep
Is my version flawed?
I also tried another version where I replaced callocate and deallocate with new and delete
But since this is using any ptr as the node type, in the destructor there is no way to determine what type the node data is.
Trying to delete an any ptr gives you a warning (undefined). In my testing I believe that the pointer was in fact not deleted.
This is a very generic list and can contain different types in the same list. Is there a way to use new/delete in this list?
I have seen the macro work around for generic types. Is that the only way?