mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			369 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			BlitzBasic
		
	
	
	
	
	
			
		
		
	
	
			369 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			BlitzBasic
		
	
	
	
	
	
| 
 | |
| ; Double-linked list container class
 | |
| ;====================================
 | |
| 
 | |
| ; with thanks to MusicianKool, for concept and issue fixes
 | |
| 
 | |
| 
 | |
| Type LList
 | |
| 	Field head_.ListNode
 | |
| 	Field tail_.ListNode
 | |
| End Type
 | |
| 
 | |
| Type ListNode
 | |
| 	Field pv_.ListNode
 | |
| 	Field nx_.ListNode
 | |
| 	Field Value
 | |
| End Type
 | |
| 
 | |
| Type Iterator
 | |
| 	Field Value
 | |
| 	Field l_.LList
 | |
| 	Field cn_.ListNode, cni_
 | |
| End Type
 | |
| 
 | |
| 
 | |
| ;Create a new LList object
 | |
| Function CreateList.LList()
 | |
| 	Local l.LList = New LList
 | |
| 	
 | |
| 	l\head_ = New ListNode
 | |
| 	l\tail_ = New ListNode
 | |
| 	
 | |
| 	l\head_\nx_ = l\tail_		;End caps
 | |
| 	l\head_\pv_ = l\head_		;These make it more or less safe to iterate freely
 | |
| 	l\head_\Value = 0
 | |
| 	
 | |
| 	l\tail_\nx_ = l\tail_
 | |
| 	l\tail_\pv_ = l\head_
 | |
| 	l\tail_\Value = 0
 | |
| 	
 | |
| 	Return l
 | |
| End Function
 | |
| 
 | |
| ;Free a list and all elements (not any values)
 | |
| Function FreeList(l.LList)
 | |
| 	ClearList l
 | |
| 	Delete l\head_
 | |
| 	Delete l\tail_
 | |
| 	Delete l
 | |
| End Function
 | |
| 
 | |
| ;Remove all the elements from a list (does not free values)
 | |
| Function ClearList(l.LList)
 | |
| 	Local n.ListNode = l\head_\nx_
 | |
| 	While n <> l\tail_
 | |
| 		Local nx.ListNode = n\nx_
 | |
| 		Delete n
 | |
| 		n = nx
 | |
| 	Wend
 | |
| 	l\head_\nx_ = l\tail_
 | |
| 	l\tail_\pv_ = l\head_
 | |
| End Function
 | |
| 
 | |
| ;Count the number of elements in a list (slow)
 | |
| Function ListLength(l.LList)
 | |
| 	Local i.Iterator = GetIterator(l), elems
 | |
| 	While EachIn(i)
 | |
| 		elems = elems + 1
 | |
| 	Wend
 | |
| 	Return elems
 | |
| End Function
 | |
| 
 | |
| ;Return True if a list contains a given value
 | |
| Function ListContains(l.LList, Value)
 | |
| 	Return (ListFindNode(l, Value) <> Null)
 | |
| End Function
 | |
| 
 | |
| ;Create a linked list from the intvalues in a bank (slow)
 | |
| Function ListFromBank.LList(bank)
 | |
| 	Local l.LList = CreateList()
 | |
| 	Local size = BankSize(bank), p
 | |
| 	
 | |
| 	For p = 0 To size - 4 Step 4
 | |
| 		ListAddLast l, PeekInt(bank, p)
 | |
| 	Next
 | |
| 	
 | |
| 	Return l
 | |
| End Function
 | |
| 
 | |
| ;Create a bank containing all the values in a list (slow)
 | |
| Function ListToBank(l.LList)
 | |
| 	Local size = ListLength(l) * 4
 | |
| 	Local bank = CreateBank(size)
 | |
| 	
 | |
| 	Local i.Iterator = GetIterator(l), p = 0
 | |
| 	While EachIn(i)
 | |
| 		PokeInt bank, p, i\Value
 | |
| 		p = p + 4
 | |
| 	Wend
 | |
| 	
 | |
| 	Return bank
 | |
| End Function
 | |
| 
 | |
| ;Swap the contents of two list objects
 | |
| Function SwapLists(l1.LList, l2.LList)
 | |
| 	Local tempH.ListNode = l1\head_, tempT.ListNode = l1\tail_
 | |
| 	l1\head_ = l2\head_
 | |
| 	l1\tail_ = l2\tail_
 | |
| 	l2\head_ = tempH
 | |
| 	l2\tail_ = tempT
 | |
| End Function
 | |
| 
 | |
| ;Create a new list containing the same values as the first
 | |
| Function CopyList.LList(lo.LList)
 | |
| 	Local ln.LList = CreateList()
 | |
| 	Local i.Iterator = GetIterator(lo) : While EachIn(i)
 | |
| 		ListAddLast ln, i\Value
 | |
| 	Wend
 | |
| 	Return ln
 | |
| End Function
 | |
| 
 | |
| ;Reverse the order of elements of a list
 | |
| Function ReverseList(l.LList)
 | |
| 	Local n1.ListNode, n2.ListNode, tmp.ListNode
 | |
| 	
 | |
| 	n1 = l\head_
 | |
| 	n2 = l\head_\nx_
 | |
| 	
 | |
| 	While n1 <> l\tail_
 | |
| 		n1\pv_ = n2
 | |
| 		tmp = n2\nx_
 | |
| 		n2\nx_ = n1
 | |
| 		n1 = n2
 | |
| 		n2 = tmp
 | |
| 	Wend
 | |
| 	
 | |
| 	tmp = l\head_
 | |
| 	l\head_ = l\tail_
 | |
| 	l\tail_ = tmp
 | |
| 	
 | |
| 	l\head_\pv_ = l\head_
 | |
| 	l\tail_\nx_ = l\tail_
 | |
| End Function
 | |
| 
 | |
| ;Search a list to retrieve the first node with the given value
 | |
| Function ListFindNode.ListNode(l.LList, Value)
 | |
| 	Local n.ListNode = l\head_\nx_
 | |
| 	
 | |
| 	While n <> l\tail_
 | |
| 		If n\Value = Value Then Return n
 | |
| 		n = n\nx_
 | |
| 	Wend
 | |
| 	
 | |
| 	Return Null
 | |
| End Function
 | |
| 
 | |
| ;Append a value to the end of a list (fast) and return the node
 | |
| Function ListAddLast.ListNode(l.LList, Value)
 | |
| 	Local n.ListNode = New ListNode
 | |
| 	
 | |
| 	n\pv_ = l\tail_\pv_
 | |
| 	n\nx_ = l\tail_
 | |
| 	n\Value = Value
 | |
| 	
 | |
| 	l\tail_\pv_ = n
 | |
| 	n\pv_\nx_ = n
 | |
| 	
 | |
| 	Return n
 | |
| End Function
 | |
| 
 | |
| ;Attach a value to the start of a list (fast) and return the node
 | |
| Function ListAddFirst.ListNode(l.LList, Value)
 | |
| 	Local n.ListNode = New ListNode
 | |
| 	
 | |
| 	n\pv_ = l\head_
 | |
| 	n\nx_ = l\head_\nx_
 | |
| 	n\Value = Value
 | |
| 	
 | |
| 	l\head_\nx_ = n
 | |
| 	n\nx_\pv_ = n
 | |
| 	
 | |
| 	Return n
 | |
| End Function
 | |
| 
 | |
| ;Remove the first occurence of the given value from a list
 | |
| Function ListRemove(l.LList, Value)
 | |
| 	Local n.ListNode = ListFindNode(l, Value)
 | |
| 	If n <> Null Then RemoveListNode n
 | |
| End Function
 | |
| 
 | |
| ;Remove a node from a list
 | |
| Function RemoveListNode(n.ListNode)
 | |
| 	n\pv_\nx_ = n\nx_
 | |
| 	n\nx_\pv_ = n\pv_
 | |
| 	Delete n
 | |
| End Function
 | |
| 
 | |
| ;Return the value of the element at the given position from the start of the list,
 | |
| ;or backwards from the end of the list for a negative index
 | |
| Function ValueAtIndex(l.LList, index)
 | |
| 	Local n.ListNode = ListNodeAtIndex(l, index)
 | |
| 	If n <> Null Then Return n\Value : Else Return 0
 | |
| End Function
 | |
| 
 | |
| ;Return the ListNode at the given position from the start of the list, or backwards
 | |
| ;from the end of the list for a negative index, or Null if invalid
 | |
| Function ListNodeAtIndex.ListNode(l.LList, index)
 | |
| 	Local e, n.ListNode
 | |
| 	
 | |
| 	If index >= 0
 | |
| 		n = l\head_
 | |
| 		For e = 0 To index
 | |
| 			n = n\nx_
 | |
| 		Next
 | |
| 		If n = l\tail_ Then n = Null	;Beyond the end of the list - not valid
 | |
| 		
 | |
| 	Else	;Negative index - count backward
 | |
| 		n = l\tail_
 | |
| 		For e = 0 To index Step -1
 | |
| 			n = n\pv_
 | |
| 		Next
 | |
| 		If n = l\head_ Then n = Null	;Before the start of the list - not valid
 | |
| 		
 | |
| 	EndIf
 | |
| 	
 | |
| 	Return n
 | |
| End Function
 | |
| 
 | |
| ;Replace a value at the given position (added by MusicianKool)
 | |
| Function ReplaceValueAtIndex(l.LList,index,value)
 | |
| 	Local n.ListNode = ListNodeAtIndex(l,index)
 | |
| 	If n <> Null Then n\Value = value:Else Return 0
 | |
| End Function
 | |
| 
 | |
| ;Remove and return a value at the given position (added by MusicianKool)
 | |
| Function RemoveNodeAtIndex(l.LList,index)
 | |
| 	Local n.ListNode = ListNodeAtIndex(l,index),tval
 | |
| 	If n <> Null Then tval = n\Value:RemoveListNode(n):Return tval:Else Return 0
 | |
| End Function
 | |
| 
 | |
| ;Retrieve the first value from a list
 | |
| Function ListFirst(l.LList)
 | |
| 	If l\head_\nx_ <> l\tail_ Then Return l\head_\nx_\Value
 | |
| End Function
 | |
| 
 | |
| ;Retrieve the last value from a list
 | |
| Function ListLast(l.LList)
 | |
| 	If l\tail_\pv_ <> l\head_ Then Return l\tail_\pv_\Value
 | |
| End Function
 | |
| 
 | |
| ;Remove the first element from a list, and return its value
 | |
| Function ListRemoveFirst(l.LList)
 | |
| 	Local val
 | |
| 	If l\head_\nx_ <> l\tail_
 | |
| 		val = l\head_\nx_\Value
 | |
| 		RemoveListNode l\head_\nx_
 | |
| 	EndIf
 | |
| 	Return val
 | |
| End Function
 | |
| 
 | |
| ;Remove the last element from a list, and return its value
 | |
| Function ListRemoveLast(l.LList)
 | |
| 	Local val
 | |
| 	If l\tail_\pv_ <> l\head_
 | |
| 		val = l\tail_\pv_\Value
 | |
| 		RemoveListNode l\tail_\pv_
 | |
| 	EndIf
 | |
| 	Return val
 | |
| End Function
 | |
| 
 | |
| ;Insert a value into a list before the specified node, and return the new node
 | |
| Function InsertBeforeNode.ListNode(Value, n.ListNode)
 | |
| 	Local bef.ListNode = New ListNode
 | |
| 	
 | |
| 	bef\pv_ = n\pv_
 | |
| 	bef\nx_ = n
 | |
| 	bef\Value = Value
 | |
| 	
 | |
| 	n\pv_ = bef
 | |
| 	bef\pv_\nx_ = bef
 | |
| 	
 | |
| 	Return bef
 | |
| End Function
 | |
| 
 | |
| ;Insert a value into a list after the specified node, and return then new node
 | |
| Function InsertAfterNode.ListNode(Value, n.ListNode)
 | |
| 	Local aft.ListNode = New ListNode
 | |
| 	
 | |
| 	aft\nx_ = n\nx_
 | |
| 	aft\pv_ = n
 | |
| 	aft\Value = Value
 | |
| 	
 | |
| 	n\nx_ = aft
 | |
| 	aft\nx_\pv_ = aft
 | |
| 	
 | |
| 	Return aft
 | |
| End Function
 | |
| 
 | |
| ;Get an iterator object to use with a loop
 | |
| ;This function means that most programs won't have to think about deleting iterators manually
 | |
| ;(in general only a small, constant number will be created)
 | |
| Function GetIterator.Iterator(l.LList)
 | |
| 	Local i.Iterator
 | |
| 	
 | |
| 	If l = Null Then RuntimeError "Cannot create Iterator for Null"
 | |
| 	
 | |
| 	For i = Each Iterator		;See if there's an available iterator at the moment
 | |
| 		If i\l_ = Null Then Exit
 | |
| 	Next
 | |
| 	
 | |
| 	If i = Null Then i = New Iterator	;If there wasn't, create one
 | |
| 	
 | |
| 	i\l_ = l
 | |
| 	i\cn_ = l\head_
 | |
| 	i\cni_ = -1
 | |
| 	i\Value = 0		;No especial reason why this has to be anything, but meh
 | |
| 	
 | |
| 	Return i
 | |
| End Function
 | |
| 
 | |
| ;Use as the argument to While to iterate over the members of a list
 | |
| Function EachIn(i.Iterator)
 | |
| 	
 | |
| 	i\cn_ = i\cn_\nx_
 | |
| 	
 | |
| 	If i\cn_ <> i\l_\tail_		;Still items in the list
 | |
| 		i\Value = i\cn_\Value
 | |
| 		i\cni_ = i\cni_ + 1
 | |
| 		Return True
 | |
| 		
 | |
| 	Else
 | |
| 		i\l_ = Null		;Disconnect from the list, having reached the end
 | |
| 		i\cn_ = Null
 | |
| 		i\cni_ = -1
 | |
| 		Return False
 | |
| 		
 | |
| 	EndIf
 | |
| End Function
 | |
| 
 | |
| ;Remove from the containing list the element currently pointed to by an iterator
 | |
| Function IteratorRemove(i.Iterator)
 | |
| 	If (i\cn_ <> i\l_\head_) And (i\cn_ <> i\l_\tail_)
 | |
| 		Local temp.ListNode = i\cn_
 | |
| 		
 | |
| 		i\cn_ = i\cn_\pv_
 | |
| 		i\cni_ = i\cni_ - 1
 | |
| 		i\Value = 0
 | |
| 		
 | |
| 		RemoveListNode temp
 | |
| 		
 | |
| 		Return True
 | |
| 	Else
 | |
| 		Return False
 | |
| 	EndIf
 | |
| End Function
 | |
| 
 | |
| ;Call this before breaking out of an EachIn loop, to disconnect the iterator from the list
 | |
| Function IteratorBreak(i.Iterator)
 | |
| 	i\l_ = Null
 | |
| 	i\cn_ = Null
 | |
| 	i\cni_ = -1
 | |
| 	i\Value = 0
 | |
| End Function
 | |
| 
 | |
| 
 | |
| ;~IDEal Editor Parameters:
 | |
| ;~F#5#A#10#18#2A#32#3E#47#4C#58#66#6F#78#8F#9B#A9#B7#BD#C5#CC
 | |
| ;~F#E3#E9#EF#F4#F9#103#10D#11B#12B#13F#152#163
 | |
| ;~C#Blitz3D |