Code: Alles auswählen
;/-----------------------------------------------------------------\
;| *** List - template *** |
;| Created by Josef Sniatecki 2008. |
;\-----------------------------------------------------------------/
;/------------------------------------------\
;| Macros |
;\------------------------------------------/
Macro _NItem(List,Item,PItem,Item_Mem)
;_NextItem(List,Item,PreviousItem,Item_Memory)
Item=List_ItemN(List,PItem)
Item_Mem=Item\Mem
EndMacro
Macro _PItem(List,Item,NItem,Item_Mem)
;_PreviousItem(List,Item,NextItem,Item_Memory)
Item=List_ItemP(List,NItem)
Item_Mem=Item\Mem
EndMacro
Macro _FItem(List,Item,Item_Mem)
Item=List_ItemF(List)
Item_Mem=Item\Mem
EndMacro
Macro _LItem(List,Item,Item_Mem)
Item=List_ItemPokeL(List)
Item_Mem=Item\Mem
EndMacro
Macro _DelItem(List,Item,Item_Mem)
Item=List_DelItem(List,Item)
Item_Mem=Item\Mem
EndMacro
;/------------------------------------------\
;| Structures |
;\------------------------------------------/
Structure List_Item
;List_Item
*N.List_Item ;Next
*P.List_Item ;Previous
*Mem ;Memory
EndStructure
Structure List
;List
Item_MemSz.l ;Item_MemorySize
ItemAm.l ;ItemAmount
*FItem.List_Item ;FirstItem
*LItem.List_Item ;LastItem
EndStructure
;/------------------------------------------\
;| Functions |
;\------------------------------------------/
Procedure.l List(Item_MemSz.l)
;List(Item_Memory_Size)
;{
; Gibt einen Zeiger auf eine neue Liste zurück. Dabei muss die
; größe der Items[Item_MemSz] bestimmt werden.
;}
Protected *List.List
*List=AllocateMemory(SizeOf(List))
If *List
*List\Item_MemSz=Item_MemSz
ProcedureReturn *List
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l DelList(*List.List,*Item_Mem_DelFunc=0)
;DeleteList(List,Item_Memory_DeleteFunction=0)
;{
; Löscht die Liste[List] aus dem Speicher.
;}
Protected *Item.List_Item
*Item=*List\FItem
While *Item
*List\FItem=*List\FItem\N
If *Item_Mem_DelFunc
If CallFunctionFast(*Item_Mem_DelFunc,*Item\Mem)=#False
ProcedureReturn #False
EndIf
Else
If FreeMemory(*Item\Mem)=#False
ProcedureReturn #False
EndIf
EndIf
If FreeMemory(*Item)=#False
ProcedureReturn #False
EndIf
*Item=*List\FItem
Wend
If FreeMemory(*List)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l CopyList(*SList.List,*DList.List)
;CopyList(SoureList,DenistationList)
;{
; Kopiert alle Daten der Skriptliste[SList] in die Zielliste[DList].
;}
Protected *SItem.List_Item ;SourceItem
Protected *DItem.List_Item ;DenistationItem
*DList\Item_MemSz=*SList\Item_MemSz
*DList\ItemAm=*SList\ItemAm
*SItem=*SList\FItem
While *SItem
If *DItem
*DItem\N=AllocateMemory(SizeOf(List_Item))
If *DItem\N
*DItem\N\P=*DItem
*DItem=*DItem\N
*DItem\Mem=AllocateMemory(*DList\Item_MemSz)
If *DItem\Mem
*DList\LItem=*DItem
Else
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
Else
*DItem=AllocateMemory(SizeOf(List_Item))
If *DItem
*DItem\N=0
*DItem\P=0
*DItem\Mem=AllocateMemory(*DList\Item_MemSz)
If *DItem\Mem
CopyMemory(*SItem\Mem,*DItem\Mem,*DList\Item_MemSz)
*DList\FItem=*DItem
*DList\LItem=*DItem
Else
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
EndIf
*SItem=*SItem\N
Wend
ProcedureReturn #True
EndProcedure
Procedure.l CleList(*List.List,*Item_Mem_DelFunc=0)
;ClearList(List,Item_Memory_DeleteFunction=0)
;{
; Löscht alle Items aus der Liste[List].
;}
Protected *Item.List_Item ;Item
*List\ItemAm=0
*Item=*List\FItem
While *Item
*List\FItem=*List\FItem\N
If *Item_Mem_DelFunc
If CallFunctionFast(*Item_Mem_DelFunc,*Item\Mem)=#False
ProcedureReturn #False
EndIf
Else
If FreeMemory(*Item\Mem)=#False
ProcedureReturn #False
EndIf
EndIf
If FreeMemory(*Item)=#False
ProcedureReturn #False
EndIf
*Item=*List\FItem
Wend
*List\FItem=0
*List\LItem=0
ProcedureReturn #True
EndProcedure
Procedure.l List_Item(*List.List,*N.List_Item,*P.List_Item,*RetMem=0,*Mem=0)
;List_Item(List,Next,Previous,ReturnMemory=0,Memory=0)
;{
; Fügt ein Item zwischen dem Nächsten-[N] und dem vorherigen Item[P] ein.
; Falls verfügbar, werden die Daten[Mem] in das Item eingefügt.
; Mit [RetMem] kann der Zeiger der neuen Daten erhalten werden.
;}
Protected *Item.List_Item ;Item
*Item=AllocateMemory(SizeOf(List_Item))
If *Item
If *N
*Item\N=*N
*N\P=*Item
Else
*List\LItem=*Item
EndIf
If *P
*Item\P=*P
*P\N=*Item
Else
*List\FItem=*Item
EndIf
If *Mem=0
*Item\Mem=AllocateMemory(*List\Item_MemSz)
If *Item\Mem=#False
ProcedureReturn #False
EndIf
Else
*Item\Mem=*Mem
EndIf
If *RetMem : PokeL(*RetMem,*Item\Mem) : EndIf
*List\ItemAm+1
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l List_ItemN(*List.List,*P.List_Item,*RetMem=0,*Mem=0)
;List_ItemAsNext(List,Previous,ReturnMemory=0,Memory=0)
;{
; Fügt ein Item nach dem vorherigen Item[P] ein.
; Falls verfügbar, werden die Daten[Mem] in das Item eingefügt.
; Mit [RetMem] kann der Zeiger der neuen Daten erhalten werden.
;}
Protected *Item.List_Item ;Item
*Item=AllocateMemory(SizeOf(List_Item))
If *Item
If *P
*Item\P=*P
If *P\N
*Item\N=*P\N
*P\N\P=*Item
*P\N=*Item
Else
*List\LItem=*Item
EndIf
*P\N=*Item
Else
*List\FItem=*Item
*List\LItem=*Item
EndIf
If *Mem=0
*Item\Mem=AllocateMemory(*List\Item_MemSz)
If *Item\Mem=#False
ProcedureReturn #False
EndIf
Else
*Item\Mem=*Mem
EndIf
If *RetMem : PokeL(*RetMem,*Item\Mem) : EndIf
*List\ItemAm+1
ProcedureReturn *Item
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l List_ItemP(*List.List,*N.List_Item,*RetMem=0,*Mem=0)
;List_ItemAsPrevious(List,Next,ReturnMemory=0,Memory=0)
;{
; Fügt ein Item vor dem nächsten Item[N] ein.
; Falls verfügbar, werden die Daten[Mem] in das Item eingefügt.
; Mit [RetMem] kann der Zeiger der neuen Daten erhalten werden.
;}
Protected *Item.List_Item ;Item
*Item=AllocateMemory(SizeOf(List_Item))
If *Item
If *N
*Item\N=*N
If *N\P
*Item\P=*N
*N\P\N=*Item
*N\P=*Item
Else
*List\FItem=*Item
EndIf
Else
*List\FItem=*Item
*List\LItem=*Item
EndIf
If *Mem=0
*Item\Mem=AllocateMemory(*List\Item_MemSz)
If *Item\Mem=#False
ProcedureReturn #False
EndIf
Else
*Item\Mem=*Mem
EndIf
If *RetMem : PokeL(*RetMem,*Item\Mem) : EndIf
*List\ItemAm+1
ProcedureReturn *Item
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l List_ItemF(*List.List,*RetMem=0,*Mem=0)
;List_ItemAsFirst(List,ReturnMemory=0,Memory=0)
;{
; Fügt ein Item an erster stelle der Liste[List] ein.
; Falls verfügbar, werden die Daten[Mem] in das Item eingefügt.
; Mit [RetMem] kann der Zeiger der neuen Daten erhalten werden.
;}
Protected *Item.List_Item ;Item
*Item=AllocateMemory(SizeOf(List_Item))
If *Item
If *List\FItem
*Item\N=*List\FItem
*List\FItem\P=*Item
*List\FItem=*Item
Else
*List\FItem=*Item
*List\LItem=*Item
EndIf
If *Mem=0
*Item\Mem=AllocateMemory(*List\Item_MemSz)
If *Item\Mem=#False
ProcedureReturn #False
EndIf
Else
*Item\Mem=*Mem
EndIf
If *RetMem : PokeL(*RetMem,*Item\Mem) : EndIf
*List\ItemAm+1
ProcedureReturn *Item
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l List_ItemL(*List.List,*RetMem=0,*Mem=0)
;List_ItemAsLast(List,ReturnMemory=0,Memory=0)
;{
; Fügt ein Item an letzter stelle der Liste[List] ein.
; Falls verfügbar, werden die Daten[Mem] in das Item eingefügt.
; Mit [RetMem] kann der Zeiger der neuen Daten erhalten werden.
;}
Protected *Item.List_Item ;Item
*Item=AllocateMemory(SizeOf(List_Item))
If *Item
If *List\LItem
*Item\P=*List\LItem
*List\LItem\N=*Item
*List\LItem=*Item
Else
*List\FItem=*Item
*List\LItem=*Item
EndIf
If *Mem=0
*Item\Mem=AllocateMemory(*List\Item_MemSz)
If *Item\Mem=#False
ProcedureReturn #False
EndIf
Else
*Item\Mem=*Mem
EndIf
If *RetMem : PokeL(*RetMem,*Item\Mem) : EndIf
*List\ItemAm+1
ProcedureReturn *Item
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l List_DelItem(*List.List,*Item.List_Item,RetItem_Dir.b=1)
;List_DeleteItem(List,Item,ReturnItem_Direction=1)
;{
; Löscht ein Item[Item] aus der Liste[List].
; Entscheiden sie durch die Richtung[RetItem_Dir], welches Item
; neben dem zu zertörenden Item zurückgegeben werden soll.
;}
Protected *RetItem.List_Item ;ReturnItem
Select RetItem_Dir
Case 1
*RetItem=*Item\N
Case -1
*RetItem=*Item\P
EndSelect
If *List\ItemAm=1
*List\FItem=0
*List\LItem=0
ElseIf *Item=*List\FItem
*Item\N\P=0
*List\FItem=*Item\N
ElseIf *Item=*List\LItem
*Item\P\N=0
*List\LItem=*Item\P
Else
*Item\N\P=*Item\P
*Item\P\N=*Item\N
EndIf
If FreeMemory(*Item\Mem)
If FreeMemory(*Item)=#False
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
*List\ItemAm-1
If *RetItem
ProcedureReturn *RetItem
Else
ProcedureReturn #False
EndIf
EndProcedure
;/------------------------------------------\
;| Examples |
;\------------------------------------------/
;{[ Viewing of lists ]
; Structure House
; Street.s
; Number.w
; Age.l
; EndStructure
;
; ;[ Defining of variables ]
; Global *HouseList.List
; Global *Item.List_Item
; Global *House.House
;
; *HouseList=List(SizeOf(House)) ;SizeOf(House) : Size of the item data.
;
; ;[ Creating of items/houses ]
; *Item=List_ItemL(*HouseList,@*House)
; *House\Street="Bla"
; *House\Number=4
; *House\Age =12
; *Item=List_ItemL(*HouseList,@*House)
; *House\Street="Blabla"
; *House\Number=11
; *House\Age =1
; *Item=List_ItemL(*HouseList,@*House)
; *House\Street="Blablabla"
; *House\Number=8
; *House\Age =2
;
; ;[ Viewing ]
; *Item=*HouseList\FItem ;Item = the first item of 'HouseList'.
; While *Item
; *House=*Item\Mem ;Get item-data/memory
;
; Debug "---"
; Debug *House\Street
; Debug *House\Number
; Debug *House\Age
;
; *Item=*Item\N ;Sets the item to the next item.
; Wend
;}
Mit diesem Template ist es möglich Listen in Strukturen zu integrieren, da
eine Funktion ("List(Size)") einen Zeiger auf eine neue Liste zurückgibt.
Genauso ist es möglich Listen in Listen (TreeLists / Datenbäube) einzufügen.
Dieses Template habe ich auch in meinem Spiel "Box Wars" angewendet:
http://www.purebasic.fr/german/viewtopic.php?t=16829
So kann etwa eine Struktur für eine TreeList aussehen.
Code: Alles auswählen
IncludeFile "List.pbi"
Structure Item
Name.s
EndStructure
Structure TreeList_Item
Type.l
StructureUnion
*Item.Item ;Type = 0
*TreeList.List ;Type = 1
EndStructureUnion
EndStructure