Hi Everyone,
I have finally dove into the PB9 object world. I am loving it so far! It is really easy to model what I want to do using the COM objects. I decided to try building an object oriented single linked list in order to help my learning. I have run into a bit of trouble when I try to remove all nodes in the linked list. It appears (to me anyway) that the nodes are not being set to NOTHING and therefore I can still iterate the list even though there should be no valid nodes available to iterate.
The current state of the code is listed below. If anyone can spot the problem then I would be very grateful for advice to fix it. This is my first shot at PB9 objects so don't laugh if it looks stupid! ;D
'//
'// PB9 OOP Single Linked List
'//
#Include Once "win32api.inc"
'//
'// The definition of each node in the Linked List
'//
Class cLinkedListNode
Instance m_sKey As String
Instance m_sData As String
Instance m_nData As Long
Interface LinkedListNodeInterface: Inherit IUnknown
' Property to Get/Set the 'Key' for the item
Property Get sKey() As String
Property = m_sKey
End Property
Property Set sKey( ByVal sKey As String )
m_sKey = sKey
End Property
' Property to Get/Set the string 'Data' for the item (when UseStrings is TRUE)
Property Get sData() As String
Property = m_sData
End Property
Property Set sData( ByVal sData As String )
m_sData = sData
End Property
' Property to Get/Set the numeric 'Data' for the item (when UseStrings is FALSE)
Property Get nData() As Long
Property = m_nData
End Property
Property Set nData( ByVal nData As Long )
m_nData = nData
End Property
End Interface
End Class
'//
'// The main Linked List class. An instance of this class should
'// be made in the user's code and will be used to manipulate the
'// various nodes in the list.
'//
Class cLinkedList
' Private instance variables
Instance m_pChildNodes() As LinkedListNodeInterface
Instance m_nCurrentNodeNum As Long
Instance m_nIncreaseSize As Long
Instance m_nUseStrings As Long
Instance m_IsEndOfList As Long
Instance m_nCount As Long
Instance m_zPtr As Asciiz Ptr
Class Method AddNewNode( ByVal nPosition As Long ) As Long
Local y As Long
' Create a new node instance at the end of the linked list
' Do we need to make our array bigger?
If m_nCount + 1 > UBound(m_pChildNodes) Then
If m_nIncreaseSize = 0 Then m_nIncreaseSize = 100
ReDim Preserve m_pChildNodes( UBound(m_pChildNodes) + m_nIncreaseSize )
End If
' Determine if we need to insert into the array or simply
' add at the end of the array.
If nPosition <= m_nCount Then
Dim nArray(UBound(m_pChildNodes)) As Dword At VarPtr(m_pChildNodes(0))
Array Insert nArray(nPosition)
End If
If nPosition < 1 Then nPosition = 1
m_pChildNodes(nPosition) = Class "cLinkedListNode"
m_nCurrentNodeNum = nPosition
End Method
Class Method SetCurrentNodeData( ByVal sKey As String, _
ByVal nData As Long _
) As Long
m_pChildNodes(m_nCurrentNodeNum).sKey = sKey
If m_nUseStrings Then
m_zPtr = nData
m_pChildNodes(m_nCurrentNodeNum).sData = @m_zPtr
Else
m_pChildNodes(m_nCurrentNodeNum).nData = nData
End If
End Method
' Main interface
Interface LinkedListInterface: Inherit IUnknown
Property Get IsEndOfList() As Long
Property = m_IsEndOfList
End Property
Property Get GetCount() As Long
Property = m_nCount
End Property
Property Get UseStrings() As Long
Property = m_nUseStrings
End Property
Property Set UseStrings( ByVal nTrueFalse As Long )
m_nUseStrings = nTrueFalse
End Property
Property Get IncreaseSize() As Long
Property = m_nIncreaseSize
End Property
Property Set IncreaseSize( ByVal nIncreaseSize As Long )
If m_nIncreaseSize <= 0 Then m_nIncreaseSize = 10
m_nIncreaseSize = nIncreaseSize
End Property
Property Get sKey() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sKey
End Property
Property Get sData() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sData
End Property
Property Get nData() As Long
Property = m_pChildNodes(m_nCurrentNodeNum).nData
End Property
Property Get CurrentPosition() As Long
Property = m_nCurrentNodeNum
End Property
'//
'// Add an item to the Linked List
'//
Method AddItem( ByVal sKey As String, _
ByVal nData As Long _
) As Long
' Create a new node instance at the end of the linked list
Incr m_nCount
Me.AddNewNode( m_nCount )
Me.SetCurrentNodeData( sKey, nData )
End Method
'//
'// Add an item to the Linked List before the specified item
'//
Method AddItemBefore( ByVal nPosition As Long, _
ByVal sKey As String, _
ByVal nData As Long _
) As Long
Me.AddNewNode( nPosition )
Me.SetCurrentNodeData( sKey, nData )
Incr m_nCount
End Method
'//
'// Add an item to the Linked List after the specified item
'//
Method AddItemAfter( ByVal nPosition As Long, _
ByVal sKey As String, _
ByVal nData As Long _
) As Long
Me.AddNewNode( nPosition + 1 )
Me.SetCurrentNodeData( sKey, nData )
Incr m_nCount
End Method
'//
'// Move an item up one position in the Linked List
'//
Method MoveUp( ByVal nPosition As Long ) As Long
If nPosition <= 1 Then Exit Method
Local pTempNode As LinkedListNodeInterface
pTempNode = m_pChildNodes(nPosition)
m_pChildNodes(nPosition) = m_pChildNodes(nPosition-1)
m_pChildNodes(nPosition-1) = pTempNode
m_nCurrentNodeNum = nPosition - 1
End Method
'//
'// Move an item down one position in the Linked List
'//
Method MoveDown( ByVal nPosition As Long ) As Long
If nPosition >= m_nCount Then Exit Method
Local pTempNode As LinkedListNodeInterface
pTempNode = m_pChildNodes(nPosition)
m_pChildNodes(nPosition) = m_pChildNodes(nPosition+1)
m_pChildNodes(nPosition+1) = pTempNode
m_nCurrentNodeNum = nPosition + 1
End Method
'//
'// Find an item based on the Key (case insensitive)
'//
Method FindByKey( ByVal sKey As String ) As Long
Local y As Long
For y = 1 To m_nCount
If lstrcmpi( ByCopy m_pChildNodes(y).sKey, ByCopy sKey ) = 0 Then
m_nCurrentNodeNum = y
Method = %TRUE
Exit For
End If
Next
End Method
'//
'// Find an item based on the nData
'//
Method FindByData( ByVal nData As Long ) As Long
Local y As Long
For y = 1 To m_nCount
If m_pChildNodes(y).nData = nData Then
m_nCurrentNodeNum = y
Method = %TRUE
Exit For
End If
Next
End Method
'//
'// Remove all items from the Linked List.
'//
Method RemoveAll() As Long
If m_nCount = 0 Then Exit Method
Local y As Long
For y = 1 To UBound(m_pChildNodes)
Set m_pChildNodes(y) = Nothing
Next
m_nCount = 0
End Method
'//
'// Get the first item in the Linked List
'//
Method GetFirst() As Long
' Set the current node to the first node in the list
m_IsEndOfList = %FALSE
If m_nCount = 0 Then
m_IsEndOfList = %TRUE
Else
m_nCurrentNodeNum = 1
End If
End Method
'//
'// Get the next item in the Linked List
'//
Method GetNext() As Long
' Set the current node to the next node in the list
If m_nCurrentNodeNum + 1 > m_nCount Then
m_IsEndOfList = %TRUE
Else
Incr m_nCurrentNodeNum
End If
End Method
'//
'// Get the last item in the Linked List
'//
Method GetLast() As Long
' Set the current node to the last node in the list
m_IsEndOfList = %FALSE
If m_nCount = 0 Then
m_IsEndOfList = %TRUE
Else
m_nCurrentNodeNum = m_nCount
End If
End Method
'//
'// Get the previous item in the Linked List
'//
Method GetPrevious() As Long
' Set the current node to the previous node in the list
If m_nCurrentNodeNum - 1 < 1 Then
m_IsEndOfList = %TRUE
Else
Decr m_nCurrentNodeNum
End If
End Method
End Interface
End Class
'//
'//
'//
Function PBMain() As Long
Local st As String
' Create an instance of the list and add items to it.
Dim cList As LinkedListInterface
cList = Class "cLinkedList"
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %FALSE
' Tell the class how much to increase the list when
' it needs to be resized
cList.IncreaseSize = 100
cList.AddItem "Paul", 5
cList.AddItem "Tammy", 100
cList.AddItem "Bob", 200
cList.AddItem "Mark", 555
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
' Find a key that we know exists (the search is case insensitive)
If cList.FindByKey( "bob" ) Then
? "Found key: " & cList.sKey
Else
? "'bob' Key not found"
End If
' Look for a key that we know does not exist
If cList.FindByKey( "somebody" ) Then
? "Found key: " & cList.sKey
Else
? "'somebody' Key not found"
End If
' Look for an item based on nData that we know exists
If cList.FindByData( 555 ) Then
? "Found data: " & Str$(cList.nData)
Else
? "'555' data not found"
End If
' Look for an item based on nData that we know does not exist
If cList.FindByData( 999 ) Then
? "Found data: " & Str$(cList.nData)
Else
? "'999' data not found"
End If
st = "BEFORE MOVING ITEM" & $CrLf
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
st = st & $CrLf & $CrLf & "AFTER MOVING FIRST ITEM DOWN ONE SLOT" & $CrLf
cList.MoveDown 1
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
? st
st = "AFTER MOVE CURRENT ITEM '" & cList.sKey & "' UP ONE SLOT" & $CrLf
cList.MoveUp cList.CurrentPosition
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
? st
' Remove all items from the linked list
cList.RemoveAll
? "AFTER REMOVE" & $CrLf & _
"List Count =" & Str$(cList.GetCount)
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %TRUE
st = "Squires": cList.AddItem "Paul", StrPtr(st)
st = "Poirier": cList.AddItem "Tammy", StrPtr(st)
st = "Zale": cList.AddItem "Bob", StrPtr(st)
st = "Tobin": cList.AddItem "Mark", StrPtr(st)
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
st = "Position": cList.AddItemBefore 1, "New First", StrPtr(st)
st = "Position": cList.AddItemAfter 5, "New Last", StrPtr(st)
st = "AFTER ADDING ITEM AT START AND AT END OF LIST" & $CrLf
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & cList.sData & $CrLf
cList.GetNext
Loop
? st
ExitOut:
? "Completed."
End Function
Setting an object to NOTHING doesn't destroy it, just decrements its reference count by 1. The object destroys himself when the reference count is 0.
When you create the Node1, it has a reference count of 1, but when you create Node2 and set a reference to Node1 with m_pCurrentNode.SetNextNode = m_pFirstNode, now Node1 has a reference count of 2. Therefore, to destroy Node1, your have to destroy Node2 first. But if there is a Node3, with a reference to Node2, then you can't destroy Node2 and Node1 until you destroy Node3 first, and so on.
IMO you have chosen an inadequate subject for your first try. Imagine that you want to have two references, PreviousNode and NextNode, to be able to traverse the list forward and backward. As Node1 will hold a reference to Node2, and Node2 to Node1, there is no way to destroy them.
It was pretty easy to switch to using a dynamic object array within the class. :)
'//
'// PB9 OOP Single Linked List
'//
%TRUE = 1
%FALSE = 0
'//
'// The definition of each node in the Linked List
'//
Class cLinkedListNode
Instance m_sKey As String
Instance m_sData As String
Instance m_nData As Long
Interface LinkedListNodeInterface: Inherit IUnknown
' Property to Get/Set the 'Key' for the item
Property Get sKey() As String
Property = m_sKey
End Property
Property Set sKey( ByVal sKey As String )
m_sKey = sKey
End Property
' Property to Get/Set the string 'Data' for the item (when UseStrings is TRUE)
Property Get sData() As String
Property = m_sData
End Property
Property Set sData( ByVal sData As String )
m_sData = sData
End Property
' Property to Get/Set the numeric 'Data' for the item (when UseStrings is FALSE)
Property Get nData() As Long
Property = m_nData
End Property
Property Set nData( ByVal nData As Long )
m_nData = nData
End Property
End Interface
End Class
'//
'// The main Linked List class. An instance of this class should
'// be made in the user's code and will be used to manipulate the
'// various nodes in the list.
'//
Class cLinkedList
' Private instance variables
Instance m_pChildNodes() As LinkedListNodeInterface
Instance m_nCurrentNodeNum As Long
Instance m_nUseStrings As Long
Instance m_IsEndOfList As Long
Instance m_nCount As Long
Instance m_zPtr As Asciiz Ptr
' Main interface
Interface LinkedListInterface: Inherit IUnknown
Property Get IsEndOfList() As Long
Property = m_IsEndOfList
End Property
Property Get GetCount() As Long
Property = m_nCount
End Property
Property Get UseStrings() As Long
Property = m_nUseStrings
End Property
Property Set UseStrings( ByVal nTrueFalse As Long )
m_nUseStrings = nTrueFalse
End Property
Property Get sKey() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sKey
End Property
Property Get sData() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sData
End Property
Property Get nData() As Long
Property = m_pChildNodes(m_nCurrentNodeNum).nData
End Property
'//
'// Add an item to the Linked List
'//
Method AddItem( ByVal sKey As String, _
ByVal nData As Long _
) As Long
' Create a new node instance at the end of the linked list
' Do we need to make our array bigger?
If m_nCount + 1 > UBound(m_pChildNodes) Then
ReDim Preserve m_pChildNodes( UBound(m_pChildNodes) + 10 )
End If
Incr m_nCount
m_pChildNodes(m_nCount) = Class "cLinkedListNode"
m_nCurrentNodeNum = m_nCount
m_pChildNodes(m_nCurrentNodeNum).sKey = sKey
If m_nUseStrings Then
m_zPtr = nData
m_pChildNodes(m_nCurrentNodeNum).sData = @m_zPtr
Else
m_pChildNodes(m_nCurrentNodeNum).nData = nData
End If
End Method
'//
'// Remove all items from the Linked List.
'//
Method RemoveAll() As Long
If m_nCount = 0 Then Exit Method
Local y As Long
For y = 1 To UBound(m_pChildNodes)
Set m_pChildNodes(y) = Nothing
Next
m_nCount = 0
End Method
'//
'// Get the first item in the Linked List
'//
Method GetFirst() As Long
' Set the current node to the first node in the list
m_IsEndOfList = %FALSE
If m_nCount = 0 Then
m_IsEndOfList = %TRUE
Else
m_nCurrentNodeNum = 1
End If
End Method
'//
'// Get the next item in the Linked List
'//
Method GetNext() As Long
' Set the current node to the next node in the list
If m_nCurrentNodeNum + 1 > m_nCount Then
m_IsEndOfList = %TRUE
Else
Incr m_nCurrentNodeNum
End If
End Method
End Interface
End Class
'//
'// Sample code to test Linked List
'//
Function PBMain() As Long
' Create an instance of the list and add items to it.
Dim cList As LinkedListInterface
cList = Class "cLinkedList"
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %FALSE
cList.AddItem "Paul", 5
cList.AddItem "Tammy", 100
cList.AddItem "Bob", 200
cList.AddItem "Mark", 555
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
cList.GetFirst
Do Until cList.IsEndOfList
? cList.sKey & $CrLf & Str$(cList.nData)
cList.GetNext
Loop
' Remove all items from the linked list
cList.RemoveAll
? "AFTER REMOVE" & $CrLf & _
"List Count =" & Str$(cList.GetCount)
Local st As String
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %TRUE
st = "Squires": cList.AddItem "Paul", StrPtr(st)
st = "Poirier": cList.AddItem "Tammy", StrPtr(st)
st = "Zale": cList.AddItem "Bob", StrPtr(st)
st = "Tobin": cList.AddItem "Mark", StrPtr(st)
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
cList.GetFirst
Do Until cList.IsEndOfList
? cList.sKey & $CrLf & cList.sData
cList.GetNext
Loop
? "Completed."
End Function
I think this is a direction, where the new objects can be most useful.
They can use dynamic strings inside, which was not possible before, using UDT's.
Now is much more easy to define complex User Data structures, including dynamic strings.
Exactly Theo - being able to have dynamic strings and dynamic arrays in the Class is a HUGE advantage for my style of programming. No more will I have to manually allocate/deallocate strings in TYPE's. I have been working with Classes all day and I love it. Bob and Co. have done an outstanding job implementing this. Once I get the basics down then hopefully I can move into areas of COM that Jose plays with all the time.
Paul,
Did you look at the IDictionary sample I posted on the PB site comparing it to your hash table? It's faster up to about 25k items ( according to José).
http://www.powerbasic.com/support/pbforums/showthread.php?t=38402&page=2
I think it might be an area to investigate instead of dynamic allocation? And you can store anything include COM Objects.
James
Maybe you can also post it here, together with an explanation?
I have looked at it, but it was no way clear to me.
If I define my own Data-Structure in an Object the result is very clear.
There are examples here: http://www.jose.it-berater.org/smfforum/index.php?board=320.0
Here's a simple one that can be useful for debugging callback messages.
James
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'SED_PBWIN
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Dictionary Example
'Good for checking message #'s with string name
'******************************************************************************
' James C. Fuller
' August 8, 2008
' jcfuller@jcfuller.com
'******************************************************************************
#COMPILE EXE
#INCLUDE ONCE "Windows.inc"
#INCLUDE ONCE "SCRRUN.INC"
FUNCTION CreateDict() AS IDictionary
LOCAL oDic AS IDictionary
LOCAL v1,v2 AS VARIANT
oDic = NEWCOM $PROGID_ScriptingDictionary
IF ISNOTHING(oDic) THEN EXIT FUNCTION
v1 = %WM_USER : v2 = "%WM_USER"
oDic.Add(v1,v2)
v1 = %WM_CREATE : v2 = "%WM_CREATE"
oDic.Add(v1,v2)
v1 = %WM_DESTROY : v2 = "%WM_DESTROY"
oDic.Add(v1,v2)
v1 = %WM_ENABLE : v2 = "%WM_ENABLE"
oDic.Add(v1,v2)
v1 = %WM_MOVE : v2 = "%WM_MOVE"
oDic.Add(v1,v2)
v1 = %WM_SIZE : v2 = "%WM_SIZE"
oDic.Add(v1,v2)
v1 = %WM_ACTIVATE : v2 = "%WM_ACTIVATE"
oDic.Add(v1,v2)
v1 = %WM_SHOWWINDOW : v2 = "%WM_SHOWWINDOW"
oDic.Add(v1,v2)
v1 = %WM_SETFOCUS : v2 = "%WM_SETFOCUS"
oDic.Add(v1,v2)
v1 = %WM_KILLFOCUS : v2 = "%WM_KILLFOCUS"
oDic.Add(v1,v2)
v1 = %WM_SETREDRAW : v2 = "%WM_SETREDRAW"
oDic.Add(v1,v2)
v1 = %WM_SETTEXT : v2 = "%WM_SETTEXT"
oDic.Add(v1,v2)
v1 = %WM_GETTEXT : v2 = "%WM_GETTEXT"
oDic.Add(v1,v2)
v1 = %WM_GETTEXTLENGTH : v2 = "%WM_GETTEXTLENGTH"
oDic.Add(v1,v2)
v1 = %WM_PAINT : v2 = "%WM_PAINT"
oDic.Add(v1,v2)
v1 = %WM_CLOSE : v2 = "%WM_CLOSE"
oDic.Add(v1,v2)
v1 = %WM_QUERYENDSESSION : v2 = "%WM_QUERYENDSESSION"
oDic.Add(v1,v2)
v1 = %WM_QUIT : v2 = "%WM_QUIT"
oDic.Add(v1,v2)
v1 = %WM_QUERYOPEN : v2 = "%WM_QUERYOPEN"
oDic.Add(v1,v2)
v1 = %WM_ERASEBKGND : v2 = "%WM_ERASEBKGND"
oDic.Add(v1,v2)
v1 = %WM_SYSCOLORCHANGE : v2 = "%WM_SYSCOLORCHANGE"
oDic.Add(v1,v2)
v1 = %WM_ENDSESSION : v2 = "%WM_ENDSESSION"
oDic.Add(v1,v2)
v1 = %WM_WININICHANGE : v2 = "%WM_WININICHANGE"
oDic.Add(v1,v2)
v1 = %WM_SETTINGCHANGE : v2 = "%WM_SETTINGCHANGE"
oDic.Add(v1,v2)
v1 = %WM_DEVMODECHANGE : v2 = "%WM_DEVMODECHANGE"
oDic.Add(v1,v2)
v1 = %WM_ACTIVATEAPP : v2 = "%WM_ACTIVATEAPP"
oDic.Add(v1,v2)
v1 = %WM_FONTCHANGE : v2 = "%WM_FONTCHANGE"
oDic.Add(v1,v2)
v1 = %WM_TIMECHANGE : v2 = "%WM_TIMECHANGE"
oDic.Add(v1,v2)
v1 = %WM_CANCELMODE : v2 = "%WM_CANCELMODE"
oDic.Add(v1,v2)
v1 = %WM_SETCURSOR : v2 = "%WM_SETCURSOR"
oDic.Add(v1,v2)
v1 = %WM_HELP : v2 = "%WM_HELP"
oDic.Add(v1,v2)
v1 = %WM_MOUSEACTIVATE : v2 = "%WM_MOUSEACTIVATE"
oDic.Add(v1,v2)
v1 = %WM_CHILDACTIVATE : v2 = "%WM_CHILDACTIVATE"
oDic.Add(v1,v2)
v1 = %WM_QUEUESYNC : v2 = "%WM_QUEUESYNC"
oDic.Add(v1,v2)
v1 = %WM_GETMINMAXINFO : v2 = "%WM_GETMINMAXINFO"
oDic.Add(v1,v2)
v1 = %WM_PAINTICON : v2 = "%WM_PAINTICON"
oDic.Add(v1,v2)
v1 = %WM_ICONERASEBKGND : v2 = "%WM_ICONERASEBKGND"
oDic.Add(v1,v2)
v1 = %WM_NEXTDLGCTL : v2 = "%WM_NEXTDLGCTL"
oDic.Add(v1,v2)
v1 = %WM_SPOOLERSTATUS : v2 = "%WM_SPOOLERSTATUS"
oDic.Add(v1,v2)
v1 = %WM_DRAWITEM : v2 = "%WM_DRAWITEM"
oDic.Add(v1,v2)
v1 = %WM_MEASUREITEM : v2 = "%WM_MEASUREITEM"
oDic.Add(v1,v2)
v1 = %WM_DELETEITEM : v2 = "%WM_DELETEITEM"
oDic.Add(v1,v2)
v1 = %WM_VKEYTOITEM : v2 = "%WM_VKEYTOITEM"
oDic.Add(v1,v2)
v1 = %WM_CHARTOITEM : v2 = "%WM_CHARTOITEM"
oDic.Add(v1,v2)
v1 = %WM_SETFONT : v2 = "%WM_SETFONT"
oDic.Add(v1,v2)
v1 = %WM_GETFONT : v2 = "%WM_GETFONT"
oDic.Add(v1,v2)
v1 = %WM_SETHOTKEY : v2 = "%WM_SETHOTKEY"
oDic.Add(v1,v2)
v1 = %WM_GETHOTKEY : v2 = "%WM_GETHOTKEY"
oDic.Add(v1,v2)
v1 = %WM_QUERYDRAGICON : v2 = "%WM_QUERYDRAGICON"
oDic.Add(v1,v2)
v1 = %WM_COMPAREITEM : v2 = "%WM_COMPAREITEM"
oDic.Add(v1,v2)
v1 = %WM_COMPACTING : v2 = "%WM_COMPACTING"
oDic.Add(v1,v2)
v1 = %WM_OTHERWINDOWCREATED : v2 = "%WM_OTHERWINDOWCREATED"
oDic.Add(v1,v2)
v1 = %WM_OTHERWINDOWDESTROYED : v2 = "%WM_OTHERWINDOWDESTROYED"
oDic.Add(v1,v2)
v1 = %WM_COMMNOTIFY : v2 = "%WM_COMMNOTIFY"
oDic.Add(v1,v2)
v1 = %WM_WINDOWPOSCHANGING : v2 = "%WM_WINDOWPOSCHANGING"
oDic.Add(v1,v2)
v1 = %WM_WINDOWPOSCHANGED : v2 = "%WM_WINDOWPOSCHANGED"
oDic.Add(v1,v2)
v1 = %WM_POWER : v2 = "%WM_POWER"
oDic.Add(v1,v2)
v1 = %WM_COPYDATA : v2 = "%WM_COPYDATA"
oDic.Add(v1,v2)
v1 = %WM_CANCELJOURNAL : v2 = "%WM_CANCELJOURNAL"
oDic.Add(v1,v2)
v1 = %WM_NOTIFY : v2 = "%WM_NOTIFY"
oDic.Add(v1,v2)
v1 = %WM_INPUTLANGUAGECHANGEREQUEST : v2 = "%WM_INPUTLANGUAGECHANGEREQUEST"
oDic.Add(v1,v2)
v1 = %WM_INPUTLANGUAGECHANGE : v2 = "%WM_INPUTLANGUAGECHANGE"
oDic.Add(v1,v2)
v1 = %WM_TCARD : v2 = "%WM_TCARD"
oDic.Add(v1,v2)
v1 = %WM_USERCHANGED : v2 = "%WM_USERCHANGED"
oDic.Add(v1,v2)
v1 = %WM_NOTIFYFORMAT : v2 = "%WM_NOTIFYFORMAT"
oDic.Add(v1,v2)
v1 = %WM_CONTEXTMENU : v2 = "%WM_CONTEXTMENU"
oDic.Add(v1,v2)
v1 = %WM_STYLECHANGING : v2 = "%WM_STYLECHANGING"
oDic.Add(v1,v2)
v1 = %WM_STYLECHANGED : v2 = "%WM_STYLECHANGED"
oDic.Add(v1,v2)
v1 = %WM_DISPLAYCHANGE : v2 = "%WM_DISPLAYCHANGE"
oDic.Add(v1,v2)
v1 = %WM_GETICON : v2 = "%WM_GETICON"
oDic.Add(v1,v2)
v1 = %WM_SETICON : v2 = "%WM_SETICON"
oDic.Add(v1,v2)
v1 = %WM_NCCREATE : v2 = "%WM_NCCREATE"
oDic.Add(v1,v2)
v1 = %WM_NCDESTROY : v2 = "%WM_NCDESTROY"
oDic.Add(v1,v2)
v1 = %WM_NCCALCSIZE : v2 = "%WM_NCCALCSIZE"
oDic.Add(v1,v2)
v1 = %WM_NCHITTEST : v2 = "%WM_NCHITTEST"
oDic.Add(v1,v2)
v1 = %WM_NCPAINT : v2 = "%WM_NCPAINT"
oDic.Add(v1,v2)
v1 = %WM_NCACTIVATE : v2 = "%WM_NCACTIVATE"
oDic.Add(v1,v2)
v1 = %WM_GETDLGCODE : v2 = "%WM_GETDLGCODE"
oDic.Add(v1,v2)
v1 = %WM_NCMOUSEMOVE : v2 = "%WM_NCMOUSEMOVE"
oDic.Add(v1,v2)
v1 = %WM_NCLBUTTONDOWN : v2 = "%WM_NCLBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_NCLBUTTONUP : v2 = "%WM_NCLBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_NCLBUTTONDBLCLK : v2 = "%WM_NCLBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_NCRBUTTONDOWN : v2 = "%WM_NCRBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_NCRBUTTONUP : v2 = "%WM_NCRBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_NCRBUTTONDBLCLK : v2 = "%WM_NCRBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_NCMBUTTONDOWN : v2 = "%WM_NCMBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_NCMBUTTONUP : v2 = "%WM_NCMBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_NCMBUTTONDBLCLK : v2 = "%WM_NCMBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_KEYDOWN : v2 = "%WM_KEYDOWN"
oDic.Add(v1,v2)
v1 = %WM_KEYFIRST : v2 = "%WM_KEYFIRST"
oDic.Add(v1,v2)
v1 = %WM_KEYUP : v2 = "%WM_KEYUP"
oDic.Add(v1,v2)
v1 = %WM_CHAR : v2 = "%WM_CHAR"
oDic.Add(v1,v2)
v1 = %WM_DEADCHAR : v2 = "%WM_DEADCHAR"
oDic.Add(v1,v2)
v1 = %WM_SYSKEYDOWN : v2 = "%WM_SYSKEYDOWN"
oDic.Add(v1,v2)
v1 = %WM_SYSKEYUP : v2 = "%WM_SYSKEYUP"
oDic.Add(v1,v2)
v1 = %WM_SYSCHAR : v2 = "%WM_SYSCHAR"
oDic.Add(v1,v2)
v1 = %WM_SYSDEADCHAR : v2 = "%WM_SYSDEADCHAR"
oDic.Add(v1,v2)
v1 = %WM_KEYLAST : v2 = "%WM_KEYLAST"
oDic.Add(v1,v2)
v1 = %WM_INITDIALOG : v2 = "%WM_INITDIALOG"
oDic.Add(v1,v2)
v1 = %WM_COMMAND : v2 = "%WM_COMMAND"
oDic.Add(v1,v2)
v1 = %WM_SYSCOMMAND : v2 = "%WM_SYSCOMMAND"
oDic.Add(v1,v2)
v1 = %WM_TIMER : v2 = "%WM_TIMER"
oDic.Add(v1,v2)
v1 = %WM_HSCROLL : v2 = "%WM_HSCROLL"
oDic.Add(v1,v2)
v1 = %WM_VSCROLL : v2 = "%WM_VSCROLL"
oDic.Add(v1,v2)
v1 = %WM_INITMENU : v2 = "%WM_INITMENU"
oDic.Add(v1,v2)
v1 = %WM_INITMENUPOPUP : v2 = "%WM_INITMENUPOPUP"
oDic.Add(v1,v2)
v1 = %WM_MENUSELECT : v2 = "%WM_MENUSELECT"
oDic.Add(v1,v2)
v1 = %WM_MENUCHAR : v2 = "%WM_MENUCHAR"
oDic.Add(v1,v2)
v1 = %WM_ENTERIDLE : v2 = "%WM_ENTERIDLE"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORMSGBOX : v2 = "%WM_CTLCOLORMSGBOX"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLOREDIT : v2 = "%WM_CTLCOLOREDIT"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORLISTBOX : v2 = "%WM_CTLCOLORLISTBOX"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORBTN : v2 = "%WM_CTLCOLORBTN"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORDLG : v2 = "%WM_CTLCOLORDLG"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORSCROLLBAR : v2 = "%WM_CTLCOLORSCROLLBAR"
oDic.Add(v1,v2)
v1 = %WM_CTLCOLORSTATIC : v2 = "%WM_CTLCOLORSTATIC"
oDic.Add(v1,v2)
v1 = %WM_MOUSEMOVE : v2 = "%WM_MOUSEMOVE"
oDic.Add(v1,v2)
v1 = %WM_MOUSEFIRST : v2 = "%WM_MOUSEFIRST"
oDic.Add(v1,v2)
v1 = %WM_LBUTTONDOWN : v2 = "%WM_LBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_LBUTTONUP : v2 = "%WM_LBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_LBUTTONDBLCLK : v2 = "%WM_LBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_RBUTTONDOWN : v2 = "%WM_RBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_RBUTTONUP : v2 = "%WM_RBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_RBUTTONDBLCLK : v2 = "%WM_RBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_MBUTTONDOWN : v2 = "%WM_MBUTTONDOWN"
oDic.Add(v1,v2)
v1 = %WM_MBUTTONUP : v2 = "%WM_MBUTTONUP"
oDic.Add(v1,v2)
v1 = %WM_MBUTTONDBLCLK : v2 = "%WM_MBUTTONDBLCLK"
oDic.Add(v1,v2)
v1 = %WM_MOUSEWHEEL : v2 = "%WM_MOUSEWHEEL"
oDic.Add(v1,v2)
v1 = %WM_MOUSELAST : v2 = "%WM_MOUSELAST"
oDic.Add(v1,v2)
v1 = %WM_PARENTNOTIFY : v2 = "%WM_PARENTNOTIFY"
oDic.Add(v1,v2)
v1 = %WM_ENTERMENULOOP : v2 = "%WM_ENTERMENULOOP"
oDic.Add(v1,v2)
v1 = %WM_EXITMENULOOP : v2 = "%WM_EXITMENULOOP"
oDic.Add(v1,v2)
v1 = %WM_SIZING : v2 = "%WM_SIZING"
oDic.Add(v1,v2)
v1 = %WM_CAPTURECHANGED : v2 = "%WM_CAPTURECHANGED"
oDic.Add(v1,v2)
v1 = %WM_MOVING : v2 = "%WM_MOVING"
oDic.Add(v1,v2)
v1 = %WM_POWERBROADCAST : v2 = "%WM_POWERBROADCAST"
oDic.Add(v1,v2)
v1 = %WM_DEVICECHANGE : v2 = "%WM_DEVICECHANGE"
oDic.Add(v1,v2)
v1 = %WM_MDICREATE : v2 = "%WM_MDICREATE"
oDic.Add(v1,v2)
v1 = %WM_MDIDESTROY : v2 = "%WM_MDIDESTROY"
oDic.Add(v1,v2)
v1 = %WM_MDIACTIVATE : v2 = "%WM_MDIACTIVATE"
oDic.Add(v1,v2)
v1 = %WM_MDIRESTORE : v2 = "%WM_MDIRESTORE"
oDic.Add(v1,v2)
v1 = %WM_MDINEXT : v2 = "%WM_MDINEXT"
oDic.Add(v1,v2)
v1 = %WM_MDIMAXIMIZE : v2 = "%WM_MDIMAXIMIZE"
oDic.Add(v1,v2)
v1 = %WM_MDITILE : v2 = "%WM_MDITILE"
oDic.Add(v1,v2)
v1 = %WM_MDICASCADE : v2 = "%WM_MDICASCADE"
oDic.Add(v1,v2)
v1 = %WM_MDIICONARRANGE : v2 = "%WM_MDIICONARRANGE"
oDic.Add(v1,v2)
v1 = %WM_MDIGETACTIVE : v2 = "%WM_MDIGETACTIVE"
oDic.Add(v1,v2)
v1 = %WM_MDISETMENU : v2 = "%WM_MDISETMENU"
oDic.Add(v1,v2)
v1 = %WM_DROPFILES : v2 = "%WM_DROPFILES"
oDic.Add(v1,v2)
v1 = %WM_MDIREFRESHMENU : v2 = "%WM_MDIREFRESHMENU"
oDic.Add(v1,v2)
v1 = %WM_MOUSEHOVER : v2 = "%WM_MOUSEHOVER"
oDic.Add(v1,v2)
v1 = %WM_MOUSELEAVE : v2 = "%WM_MOUSELEAVE"
oDic.Add(v1,v2)
v1 = %WM_CUT : v2 = "%WM_CUT"
oDic.Add(v1,v2)
v1 = %WM_COPY : v2 = "%WM_COPY"
oDic.Add(v1,v2)
v1 = %WM_PASTE : v2 = "%WM_PASTE"
oDic.Add(v1,v2)
v1 = %WM_CLEAR : v2 = "%WM_CLEAR"
oDic.Add(v1,v2)
v1 = %WM_UNDO : v2 = "%WM_UNDO"
oDic.Add(v1,v2)
v1 = %WM_RENDERFORMAT : v2 = "%WM_RENDERFORMAT"
oDic.Add(v1,v2)
v1 = %WM_RENDERALLFORMATS : v2 = "%WM_RENDERALLFORMATS"
oDic.Add(v1,v2)
v1 = %WM_DESTROYCLIPBOARD : v2 = "%WM_DESTROYCLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_DRAWCLIPBOARD : v2 = "%WM_DRAWCLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_PAINTCLIPBOARD : v2 = "%WM_PAINTCLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_VSCROLLCLIPBOARD : v2 = "%WM_VSCROLLCLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_SIZECLIPBOARD : v2 = "%WM_SIZECLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_ASKCBFORMATNAME : v2 = "%WM_ASKCBFORMATNAME"
oDic.Add(v1,v2)
v1 = %WM_CHANGECBCHAIN : v2 = "%WM_CHANGECBCHAIN"
oDic.Add(v1,v2)
v1 = %WM_HSCROLLCLIPBOARD : v2 = "%WM_HSCROLLCLIPBOARD"
oDic.Add(v1,v2)
v1 = %WM_QUERYNEWPALETTE : v2 = "%WM_QUERYNEWPALETTE"
oDic.Add(v1,v2)
v1 = %WM_PALETTEISCHANGING : v2 = "%WM_PALETTEISCHANGING"
oDic.Add(v1,v2)
v1 = %WM_PALETTECHANGED : v2 = "%WM_PALETTECHANGED"
oDic.Add(v1,v2)
v1 = %WM_HOTKEY : v2 = "%WM_HOTKEY"
oDic.Add(v1,v2)
v1 = %WM_PRINTCLIENT : v2 = "%WM_PRINTCLIENT"
oDic.Add(v1,v2)
v1 = %WM_PENWINFIRST : v2 = "%WM_PENWINFIRST"
oDic.Add(v1,v2)
v1 = %WM_PENWINLAST : v2 = "%WM_PENWINLAST"
oDic.Add(v1,v2)
v1 = %WM_ENTERSIZEMOVE : v2 = "%WM_ENTERSIZEMOVE"
oDic.Add(v1,v2)
v1 = %WM_EXITSIZEMOVE : v2 = "%WM_EXITSIZEMOVE"
oDic.Add(v1,v2)
v1 = %WM_NULL : v2 = "%WM_NULL"
oDic.Add(v1,v2)
v1 = %WM_IME_STARTCOMPOSITION : v2 = "%WM_IME_STARTCOMPOSITION"
oDic.Add(v1,v2)
v1 = %WM_IME_ENDCOMPOSITION : v2 = "%WM_IME_ENDCOMPOSITION"
oDic.Add(v1,v2)
v1 = %WM_IME_COMPOSITION : v2 = "%WM_IME_COMPOSITION"
oDic.Add(v1,v2)
v1 = %WM_IME_KEYLAST : v2 = "%WM_IME_KEYLAST"
oDic.Add(v1,v2)
v1 = %WM_IME_SETCONTEXT : v2 = "%WM_IME_SETCONTEXT"
oDic.Add(v1,v2)
v1 = %WM_IME_NOTIFY : v2 = "%WM_IME_NOTIFY"
oDic.Add(v1,v2)
v1 = %WM_IME_CONTROL : v2 = "%WM_IME_CONTROL"
oDic.Add(v1,v2)
v1 = %WM_IME_COMPOSITIONFULL : v2 = "%WM_IME_COMPOSITIONFULL"
oDic.Add(v1,v2)
v1 = %WM_IME_SELECT : v2 = "%WM_IME_SELECT"
oDic.Add(v1,v2)
v1 = %WM_IME_CHAR : v2 = "%WM_IME_CHAR"
oDic.Add(v1,v2)
v1 = %WM_IME_REQUEST : v2 = "%WM_IME_REQUEST"
oDic.Add(v1,v2)
v1 = %WM_IME_KEYDOWN : v2 = "%WM_IME_KEYDOWN"
oDic.Add(v1,v2)
v1 = %WM_IME_KEYUP : v2 = "%WM_IME_KEYUP"
oDic.Add(v1,v2)
FUNCTION = oDic
END FUNCTION
'==============================================================================
FUNCTION PBMAIN() AS LONG
LOCAL oDic AS IDictionary
LOCAL v1,v2 AS VARIANT
oDic = CreateDict
IF ISNOTHING(oDic) THEN
?" No oDic"
EXIT FUNCTION
END IF
v1 = %WM_IME_KEYUP
IF oDic.Exists(v1) = 0 THEN
? "No Entry"
ELSE
v2 = oDic.Item(v1)
? "v2 = " + VARIANT$(v2)
END IF
END FUNCTION
What Limitations daoes it have per element?
Maximum Lenght?
Only NULL-Termianted?
Or would it eat a String up to 2 GB if I set "v2" to this string?
And will I get this string back?
Or is this just for short strings?
Here is the code to the linked list that I completed yesterday. It works well but I'm not sure if I would use it over my existing linked list code - maybe someone will find use for it.
'//
'// PB9 OOP Single Linked List
'//
#Include Once "win32api.inc"
'//
'// The definition of each node in the Linked List
'//
Class cLinkedListNode
Instance m_sKey As String
Instance m_sData As String
Instance m_nData As Long
Interface LinkedListNodeInterface: Inherit IUnknown
' Property to Get/Set the 'Key' for the item
Property Get sKey() As String
Property = m_sKey
End Property
Property Set sKey( ByVal sKey As String )
m_sKey = sKey
End Property
' Property to Get/Set the string 'Data' for the item (when UseStrings is TRUE)
Property Get sData() As String
Property = m_sData
End Property
Property Set sData( ByVal sData As String )
m_sData = sData
End Property
' Property to Get/Set the numeric 'Data' for the item (when UseStrings is FALSE)
Property Get nData() As Long
Property = m_nData
End Property
Property Set nData( ByVal nData As Long )
m_nData = nData
End Property
End Interface
End Class
'//
'// The main Linked List class. An instance of this class should
'// be made in the user's code and will be used to manipulate the
'// various nodes in the list.
'//
Class cLinkedList
' Private instance variables
Instance m_pChildNodes() As LinkedListNodeInterface
Instance m_nCurrentNodeNum As Long
Instance m_nIncreaseSize As Long
Instance m_nUseStrings As Long
Instance m_IsEndOfList As Long
Instance m_nCount As Long
Instance m_zPtr As Asciiz Ptr
Class Method AddNewNode( ByVal nPosition As Long ) As Long
Local y As Long
' Create a new node instance at the end of the linked list
' Do we need to make our array bigger?
If m_nCount + 1 > UBound(m_pChildNodes) Then
If m_nIncreaseSize = 0 Then m_nIncreaseSize = 100
ReDim Preserve m_pChildNodes( UBound(m_pChildNodes) + m_nIncreaseSize )
End If
' Determine if we need to insert into the array or simply
' add at the end of the array.
If nPosition <= m_nCount Then
Dim nArray(UBound(m_pChildNodes)) As Dword At VarPtr(m_pChildNodes(0))
Array Insert nArray(nPosition)
End If
If nPosition < 1 Then nPosition = 1
m_pChildNodes(nPosition) = Class "cLinkedListNode"
m_nCurrentNodeNum = nPosition
End Method
Class Method SetCurrentNodeData( ByVal sKey As String, _
ByVal nData As Long _
) As Long
m_pChildNodes(m_nCurrentNodeNum).sKey = sKey
If m_nUseStrings Then
m_zPtr = nData
m_pChildNodes(m_nCurrentNodeNum).sData = @m_zPtr
Else
m_pChildNodes(m_nCurrentNodeNum).nData = nData
End If
End Method
' Main interface
Interface LinkedListInterface: Inherit IUnknown
Property Get IsEndOfList() As Long
Property = m_IsEndOfList
End Property
Property Get GetCount() As Long
Property = m_nCount
End Property
Property Get UseStrings() As Long
Property = m_nUseStrings
End Property
Property Set UseStrings( ByVal nTrueFalse As Long )
m_nUseStrings = nTrueFalse
End Property
Property Get IncreaseSize() As Long
Property = m_nIncreaseSize
End Property
Property Set IncreaseSize( ByVal nIncreaseSize As Long )
If m_nIncreaseSize <= 0 Then m_nIncreaseSize = 10
m_nIncreaseSize = nIncreaseSize
End Property
Property Get sKey() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sKey
End Property
Property Get sData() As String
Property = m_pChildNodes(m_nCurrentNodeNum).sData
End Property
Property Get nData() As Long
Property = m_pChildNodes(m_nCurrentNodeNum).nData
End Property
Property Get CurrentPosition() As Long
Property = m_nCurrentNodeNum
End Property
'//
'// Add an item to the Linked List
'//
Method AddItem( ByVal sKey As String, _
ByVal nData As Long _
) As Long
' Create a new node instance at the end of the linked list
Incr m_nCount
Me.AddNewNode( m_nCount )
Me.SetCurrentNodeData( sKey, nData )
End Method
'//
'// Add an item to the Linked List before the specified item
'//
Method AddItemBefore( ByVal nPosition As Long, _
ByVal sKey As String, _
ByVal nData As Long _
) As Long
Me.AddNewNode( nPosition )
Me.SetCurrentNodeData( sKey, nData )
Incr m_nCount
End Method
'//
'// Add an item to the Linked List after the specified item
'//
Method AddItemAfter( ByVal nPosition As Long, _
ByVal sKey As String, _
ByVal nData As Long _
) As Long
Me.AddNewNode( nPosition + 1 )
Me.SetCurrentNodeData( sKey, nData )
Incr m_nCount
End Method
'//
'// Move an item up one position in the Linked List
'//
Method MoveUp( ByVal nPosition As Long ) As Long
If nPosition <= 1 Then Exit Method
Local pTempNode As LinkedListNodeInterface
pTempNode = m_pChildNodes(nPosition)
m_pChildNodes(nPosition) = m_pChildNodes(nPosition-1)
m_pChildNodes(nPosition-1) = pTempNode
m_nCurrentNodeNum = nPosition - 1
End Method
'//
'// Move an item down one position in the Linked List
'//
Method MoveDown( ByVal nPosition As Long ) As Long
If nPosition >= m_nCount Then Exit Method
Local pTempNode As LinkedListNodeInterface
pTempNode = m_pChildNodes(nPosition)
m_pChildNodes(nPosition) = m_pChildNodes(nPosition+1)
m_pChildNodes(nPosition+1) = pTempNode
m_nCurrentNodeNum = nPosition + 1
End Method
'//
'// Find an item based on the Key (case insensitive)
'//
Method FindByKey( ByVal sKey As String ) As Long
Local y As Long
For y = 1 To m_nCount
If lstrcmpi( ByCopy m_pChildNodes(y).sKey, ByCopy sKey ) = 0 Then
m_nCurrentNodeNum = y
Method = %TRUE
Exit For
End If
Next
End Method
'//
'// Find an item based on the nData
'//
Method FindByData( ByVal nData As Long ) As Long
Local y As Long
For y = 1 To m_nCount
If m_pChildNodes(y).nData = nData Then
m_nCurrentNodeNum = y
Method = %TRUE
Exit For
End If
Next
End Method
'//
'// Remove all items from the Linked List.
'//
Method RemoveAll() As Long
If m_nCount = 0 Then Exit Method
Local y As Long
For y = 1 To UBound(m_pChildNodes)
Set m_pChildNodes(y) = Nothing
Next
m_nCount = 0
End Method
'//
'// Get the first item in the Linked List
'//
Method GetFirst() As Long
' Set the current node to the first node in the list
m_IsEndOfList = %FALSE
If m_nCount = 0 Then
m_IsEndOfList = %TRUE
Else
m_nCurrentNodeNum = 1
End If
End Method
'//
'// Get the next item in the Linked List
'//
Method GetNext() As Long
' Set the current node to the next node in the list
If m_nCurrentNodeNum + 1 > m_nCount Then
m_IsEndOfList = %TRUE
Else
Incr m_nCurrentNodeNum
End If
End Method
'//
'// Get the last item in the Linked List
'//
Method GetLast() As Long
' Set the current node to the last node in the list
m_IsEndOfList = %FALSE
If m_nCount = 0 Then
m_IsEndOfList = %TRUE
Else
m_nCurrentNodeNum = m_nCount
End If
End Method
'//
'// Get the previous item in the Linked List
'//
Method GetPrevious() As Long
' Set the current node to the previous node in the list
If m_nCurrentNodeNum - 1 < 1 Then
m_IsEndOfList = %TRUE
Else
Decr m_nCurrentNodeNum
End If
End Method
End Interface
End Class
'//
'//
'//
Function PBMain() As Long
Local st As String
' Create an instance of the list and add items to it.
Dim cList As LinkedListInterface
cList = Class "cLinkedList"
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %FALSE
' Tell the class how much to increase the list when
' it needs to be resized
cList.IncreaseSize = 100
cList.AddItem "Paul", 5
cList.AddItem "Tammy", 100
cList.AddItem "Bob", 200
cList.AddItem "Mark", 555
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
' Find a key that we know exists (the search is case insensitive)
If cList.FindByKey( "bob" ) Then
? "Found key: " & cList.sKey
Else
? "'bob' Key not found"
End If
' Look for a key that we know does not exist
If cList.FindByKey( "somebody" ) Then
? "Found key: " & cList.sKey
Else
? "'somebody' Key not found"
End If
' Look for an item based on nData that we know exists
If cList.FindByData( 555 ) Then
? "Found data: " & Str$(cList.nData)
Else
? "'555' data not found"
End If
' Look for an item based on nData that we know does not exist
If cList.FindByData( 999 ) Then
? "Found data: " & Str$(cList.nData)
Else
? "'999' data not found"
End If
st = "BEFORE MOVING ITEM" & $CrLf
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
st = st & $CrLf & $CrLf & "AFTER MOVING FIRST ITEM DOWN ONE SLOT" & $CrLf
cList.MoveDown 1
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
? st
st = "AFTER MOVE CURRENT ITEM '" & cList.sKey & "' UP ONE SLOT" & $CrLf
cList.MoveUp cList.CurrentPosition
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & Str$(cList.nData) & $CrLf
cList.GetNext
Loop
? st
' Remove all items from the linked list
cList.RemoveAll
? "AFTER REMOVE" & $CrLf & _
"List Count =" & Str$(cList.GetCount)
' Tell the class that nData is a 32-bit number rather
' than a pointer to a string.
cList.UseStrings = %TRUE
st = "Squires": cList.AddItem "Paul", StrPtr(st)
st = "Poirier": cList.AddItem "Tammy", StrPtr(st)
st = "Zale": cList.AddItem "Bob", StrPtr(st)
st = "Tobin": cList.AddItem "Mark", StrPtr(st)
? "List Count =" & Str$(cList.GetCount) & $CrLf & _
"UseStrings =" & Str$(cList.UseStrings)
st = "Position": cList.AddItemBefore 1, "New First", StrPtr(st)
st = "Position": cList.AddItemAfter 5, "New Last", StrPtr(st)
st = "AFTER ADDING ITEM AT START AND AT END OF LIST" & $CrLf
cList.GetFirst
Do Until cList.IsEndOfList
st = st & cList.sKey & " " & cList.sData & $CrLf
cList.GetNext
Loop
? st
ExitOut:
? "Completed."
End Function
Quote from: Theo Gottwald on September 01, 2008, 10:15:12 AM
What Limitations daoes it have per element?
Maximum Lenght?
Only NULL-Termianted?
Or would it eat a String up to 2 GB if I set "v2" to this string?
And will I get this string back?
Or is this just for short strings?
Theo,
I just realized José had not spoken up on this. I have no idea and would like to know myself.
José??
James
These are questions whose answer you can find by yourselves. Just try it. Build an string of the wanted size and assign it to a variant to see if it works. I'm not so crazy as to build a dictionary with 2GB strings (4GB when converted to unicode) :)
My problem with these API/Windows system functions is mostly, that first i am depending on their reliability, and second, i do not know which limitations they have.
If I use pure PB, i know the Limitations, the weaknesses. And I know they are reliable.
A dictionary is not much more then a two-dimensional Array. Can even be two one-dimensional dynamic string arrays where the elements have the same index.
Actually something like this can quickly built with the new objects and dynamic strings.
And then I know each element can at least have 2 GB in the worst case and all runs at full speed.
This reminds me of something ... i think the new dynamic strings in PB 4 can even have up to 4 GB .-).
Theo,
You'll never match the speed using Arrays. It's even faster than Paul's hash table.
James
Arrays are in most cases faster then Linked Lists.
Thats because the organisation in Memory is better for the CPU-Cache.
Is true for PB Arrays too.
I worded that wrong. the IDictionary will beat anything up to about 25k items.
James