Template für Listen
Verfasst: 08.06.2008 17:50
Hier habe ich mal ein Template womit man Listen erstellen kann.
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
;/-----------------------------------------------------------------\
;| *** 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