Virtual LinkedLists und Zusatzfunktionen mit PB-Syntax
Verfasst: 01.11.2006 23:59
Hi Leude
Ansätze für weitere LinkedList-Funktionen gibt es ja zur genüge, was mich nur nervte war das verlorengehen der PB-Syntax. die alternativen LinkedLists arbeiteten immer mit Pointern, was ich im Quelltext einfach zu unübersichtlich fand. (bei Liste() sieht man direkt, dass es ne liste is, bei *Liste() kann man´s nur vermuten)
Also hab ich mich ma dran begeben, sowas selbst zu bauen.
Zuersteinmal sei hier einigen Leuten zu danken:
1.)Deeem, der mir half, wenn mein "Wie geht nochma ASM"-Gedächtnis ma wieder versagte
2.)DarkDragon, der mir den Link zu
3.)HellHounds Ansatz für ein Template ( http://www.purebasic-lounge.de/viewtopi ... 8582#38582
zeigte
4.)Mama, Papa, Meinem Agenten und den Regisseuren uswusf
was ist das hier?
Ein BefehlsSatz von Zusatzfunktionen für LinkedLists, die es Erlauben, (fast) die PureBasic-Syntax bei zu behalten (um die Typenangabe kam ich leider net rum, aber das sollte nicht weiter stören)
Befehle:
InitVirtualType(Typ)
So, hier nun die IncludeDatei:
Dann Hier ein Beispiel für VirtualizeList
Ein Beispiel für SplitList:
Und eins für ConnectList:
Ob die Beispiele jetzt so passend sind, weiß ich nicht. Brauchbar
ist es aber überall, wo man auf komplexere Datenstrukturen trifft.
Feedback Willkommen, Bugreports geduldet
Achja, weitere Funktionen für LinkedLists natürlich auch

Ansätze für weitere LinkedList-Funktionen gibt es ja zur genüge, was mich nur nervte war das verlorengehen der PB-Syntax. die alternativen LinkedLists arbeiteten immer mit Pointern, was ich im Quelltext einfach zu unübersichtlich fand. (bei Liste() sieht man direkt, dass es ne liste is, bei *Liste() kann man´s nur vermuten)
Also hab ich mich ma dran begeben, sowas selbst zu bauen.
Zuersteinmal sei hier einigen Leuten zu danken:
1.)Deeem, der mir half, wenn mein "Wie geht nochma ASM"-Gedächtnis ma wieder versagte
2.)DarkDragon, der mir den Link zu
3.)HellHounds Ansatz für ein Template ( http://www.purebasic-lounge.de/viewtopi ... 8582#38582
zeigte
4.)Mama, Papa, Meinem Agenten und den Regisseuren uswusf
was ist das hier?
Ein BefehlsSatz von Zusatzfunktionen für LinkedLists, die es Erlauben, (fast) die PureBasic-Syntax bei zu behalten (um die Typenangabe kam ich leider net rum, aber das sollte nicht weiter stören)
Befehle:
InitVirtualType(Typ)
VirtualizeList(Liste(),Typ)Muss für jeden VariablenTyp, der in LinkedLists verwendet werden Soll angegeben werden. Dieses Macro erstellt die gebrauchten Funktionen für den Jeweiligen Typ
Virtual_SetList(Liste(),Typ,ListenHeader)Vorbereiten einer Liste für das Virtuelle Verarbeiten
UnVirtualizeAllListsMit Virtual_SetList kann man eine Liste auf jeden beliebigen Speicher zeigen lassen. Der ListenHeader muss die Structur LinkedList haben (siehe Code). Nach dem "umbiegen" des Zeigers kann mit der Liste gearbeitet werden wie immer. Wichtig: Da der Direkte Zeiger auf den Header umgebogen wird, bleiben etwaige altDaten vorhanden (siehe Bsp1.pb).
UnvirtualizeList(LinkedList(),Typ)Diese Funktion muss am Ende jedes Codes stehen, damit die ListenZeiger wieder auf die Richtige Stelle umgebogen werden, sodass PB die Listen wieder vernünftig entfernen kann
GetListPointer(LinkedList(),Typ)Macht die Liste wieder zu einer Normalen Liste. Der ListenHeaderZeiger zeigt nun wieder auf den von PB dieser Liste ehemals zugewiesenen Header.
GetListHeaderPointer(LinkedList(),Typ)Sagt, wohin der ListenZeiger zeigt
SplitList(Liste1(),Liste2(),Typ,element)Sagt, wohin der ListenHeaderZeiger zeigt
ConnectLists(Liste1(),Liste2(),Typ)Zerschneidet Liste1() VOR Element und erstellt aus dem Rest die Liste2
Fügt Liste1 und Liste2 zu Liste1 zusammen
So, hier nun die IncludeDatei:
Code: Alles auswählen
Enumeration
#VirtualTypes_s
#VirtualTypes_b
#VirtualTypes_c
#VirtualTypes_w
#VirtualTypes_l
#VirtualTypes_d
#VirtualTypes_q
EndEnumeration
Structure LinkedList
FirstEl.l
LastEl.l
elementSize.l
Menge.l
lindex.l
current_adr.l
EndStructure
Structure LL_Head
header.l
current.l
EndStructure
Structure LL_RealAdr
listadr.l
headeradr.l
EndStructure
Structure LL_Element
nachher.l
vorher.l
EndStructure
Global Virtual_Hold.l
Global NewList _Virtual_ListeHeaders.LL_RealAdr()
Macro InitVirtualType(mpqurkak_Typ)
;
Procedure VirtualizeList_#mpqurkak_Typ#(LinkedList.mpqurkak_Typ());Macht eine Normale Liste zur Virtuellen
!MOV eax,[esp+0] ;ListenHeader in Virtual_Hold lesen
!MOV dword[v_Virtual_Hold],eax
AddElement(_Virtual_ListeHeaders())
_Virtual_ListeHeaders()\listadr=Virtual_Hold
_Virtual_ListeHeaders()\headeradr=PeekL(Virtual_Hold)
ClearList(LinkedList())
EndProcedure
Procedure Virtual_SetList_#mpqurkak_Typ(LinkedList.mpqurkak_Typ(),*mp_adr_hold.linkedlist)
Protected *LLHead.LL_Head,*mp_adr_hold2.LinkedList
!MOV eax,[esp+0];Enthält den Pointer auf die Linkedlist (so wie t_worte bei ner Liste namens Worte())
!MOV dword[v_Virtual_Hold],eax;Verschiebt´s in nen zwischenhalter
*LLHead=virtual_hold;Setzt den LLHead auf den Listheader (muss ich nich so viel mit ASM arbeiten)
;Alten Header sichern
*mp_adr_hold2=*LLHead\header
;Richtige Elementgröße angeben
CompilerIf Defined(VirtualTypes_#mpqurkak_Typ,#PB_Constant)
#Vpqtest_#mpqurkak_Typ=#VirtualTypes_#mpqurkak_Typ
CompilerElse
#vpqtest_#mpqurkak_Typ=-1
CompilerEndIf
CompilerSelect #Vpqtest_#mpqurkak_Typ
CompilerCase #VirtualTypes_b
*mp_adr_hold\elementsize=SizeOf(BYTE)+8
CompilerCase #VirtualTypes_l
*mp_adr_hold\elementsize=SizeOf(LONG)+8
CompilerCase #VirtualTypes_s
*mp_adr_hold\elementsize=SizeOf(LONG)+8
CompilerCase #VirtualTypes_w
*mp_adr_hold\elementsize=SizeOf(WORD)+8
CompilerCase #VirtualTypes_c
*mp_adr_hold\elementsize=SizeOf(Character)+8
CompilerCase #VirtualTypes_d
*mp_adr_hold\elementsize=SizeOf(Double)+8
CompilerCase #VirtualTypes_q
*mp_adr_hold\elementsize=SizeOf(quad)+8
CompilerDefault
*mp_adr_hold\elementsize=SizeOf(mpqurkak_Typ)+8
CompilerEndSelect
;Alte currentadr sichern
If *mp_adr_hold2<>0 And MemorySize(*mp_adr_hold2)=SizeOf(LinkedList); gibt ne Alte Liste; Ist also ne Virtual List
*mp_adr_hold2\current_adr=*LLHead\current
EndIf
;Header neu verlinken
*LLHEAD\header=*mp_adr_hold
*LLHead\current=*mp_adr_hold\current_adr
EndProcedure
Procedure.l GetListPointer_#mpqurkak_Typ(LinkedList.mpqurkak_Typ())
!MOV Eax,[esp+0]
EndProcedure
Procedure.l GetListHeaderPointer_#mpqurkak_Typ(LinkedList.mpqurkak_Typ())
!MOV EBX,[esp+0]
!MOV EAX,dword[ebx]
!MOV dword[v_Virtual_Hold],EAX
ProcedureReturn Virtual_Hold
EndProcedure
Procedure RecountList_#mpqurkak_Typ(LinkedList.mpqurkak_Typ())
FirstElement(LinkedList())
*Element.LL_Element=@LinkedList()-8
menge=0
While *Element<>0
*Element=*Element\nachher
INC menge
Wend
ProcedureReturn menge
EndProcedure
Procedure SplitList_#mpqurkak_Typ(LinkedList_Anf.mpqurkak_Typ(),LinkedList_End.mpqurkak_Typ(),element.l)
If element>0 And element<CountList(LinkedList_Anf())
LastElement(LinkedList_Anf())
mylast.l=@LinkedList_Anf()-8
SelectElement(LinkedList_Anf(),element-1)
*NeuEnde.LL_Element=@LinkedLIst_Anf()-8
If *NeuEnde\nachher<>0
*NeuAnfang.LL_Element=*NeuEnde\nachher
*NeuEnde\nachher=0
*NeuAnfang\vorher=0
*Liste_Alt.LinkedList=GetListHeaderPointer_#mpqurkak_Typ(LinkedList_Anf())
*Liste_Alt\lastel=*NeuEnde
ClearList(LinkedList_End())
*Liste_Neu.LinkedList=GetListHeaderPointer_#mpqurkak_Typ(LinkedList_End())
*Liste_Neu\firstel=*NeuAnfang
*Liste_Neu\lastel=mylast
ResetList(LinkedList_End())
ResetList(LinkedList_Anf())
*Liste_Alt\menge=ReCountList_#mpqurkak_Typ(LinkedList_Anf())
*Liste_Neu\menge=ReCountList_#mpqurkak_Typ(LinkedList_End())
EndIf
EndIf
EndProcedure
Procedure ConnectLists_#mpqurkak_Typ(LinkedList_Anf.mpqurkak_Typ(),LinkedList_End.mpqurkak_Typ())
*Liste1.LinkedList=GetListHeaderPointer(LinkedList_Anf(),mpqurkak_Typ)
*Liste2.LinkedList=GetListHeaderPointer(LinkedList_End(),mpqurkak_Typ)
If *Liste1\firstel=0;Kein Element in Liste 1, wird also nur rüberkopiert
*Liste1\firstel=*Liste2\firstel
*Liste1\lastel=*Liste2\lastel
*Liste1\menge=*Liste2\menge
*Liste2\menge=0
*Liste2\firstel=0
*Liste2\lastel=0
ResetList(LinkedList_End())
ResetList(LinkedList_Anf())
ElseIf *Liste2\firstel<>0;Zweite Liste hat kein Element, also alles Egal
*MomLetztElement.LL_Element=*Liste1\lastel
*MomErstElement.LL_Element=*Liste2\firstel
*Liste1\lastel=*Liste2\lastel
*MomLetztElement\nachher=*momerstelement
*MomErstElement\vorher=*MomLetztElement
*Liste1\menge=*Liste1\menge+*Liste2\menge
*Liste2\menge=0
*Liste2\firstel=0
*Liste2\lastel=0
ResetList(LinkedList_End())
ResetList(LinkedList_Anf())
EndIf
EndProcedure
Procedure UnVirtualizeList_#mpqurkak_Typ(LinkedList.mpqurkak_Typ())
adr.l=GetListPointer(LinkedList(),mpqurkak_Typ)
ForEach _Virtual_ListeHeaders()
If _Virtual_ListeHeaders()\listadr=adr
PokeL(adr,_Virtual_ListeHeaders()\headeradr)
ResetList(LinkedList())
Break
EndIf
Next
EndProcedure
EndMacro
Macro VirtualizeList(LinkedList,mpqurkak_Typ)
VirtualizeList_#mpqurkak_Typ(LinkedList)
EndMacro
Macro UnVirtualizeList(LinkedList,mpqurkak_Typ)
UnVirtualizeList_#mpqurkak_Typ(LinkedList)
EndMacro
Macro Virtual_SetList(LinkedList,mpqurkak_Typ,mp_adr_hold)
Virtual_SetList_#mpqurkak_Typ(LinkedList,mp_adr_hold)
EndMacro
Procedure UnVirtualizeAllLists();Führt am Ende alles wieder zusammen, damit PB normal den Speicher reinigen kann und
ForEach _Virtual_ListeHeaders()
PokeL(_Virtual_ListeHeaders()\listadr,_Virtual_ListeHeaders()\headeradr)
Next
ClearList(_Virtual_ListeHeaders())
EndProcedure
Macro GetListPointer(LinkedList,Typ)
GetListPointer_#Typ(LinkedList)
EndMacro
Macro GetListHeaderPointer(LinkedList,Typ)
GetListHeaderPointer_#Typ(LinkedList)
EndMacro
Macro SplitList(LinkedList1,LinkedList2,element,Typ)
SplitList_#Typ(LinkedList1,LinkedList2,element)
EndMacro
Macro ConnectLists(LinkedList1,LinkedList2,Typ)
ConnectLists_#Typ(LinkedList1,LinkedList2)
EndMacro
Code: Alles auswählen
IncludeFile "Virtual_List.pb"
Enumeration
#w_Artikel
#w_Nomen
#w_Verben
#w_Adjektive
EndEnumeration
;Beispiel1: Verschiedene Listen in einem Array
Global Dim Listen.LinkedList(10)
Global NewList Worte.s()
InitVirtualType(s)
VirtualizeList(Worte(),s)
Macro LiesWoerter(Art)
Virtual_SetLIST(Worte(),s,Listen(#w_#ART))
string.s=""
Restore ART
Read string.s
While String<>"!§$last!$%"
AddElement(Worte())
Worte()=String
Read string
Wend
EndMacro
LiesWoerter(Artikel)
LiesWoerter(Nomen)
LiesWoerter(Verben)
LiesWoerter(Adjektive)
For a=1 To 10
string.s=""
For q=#w_Artikel To #w_Adjektive
Virtual_SetLIST(Worte(),s,Listen(q))
SelectElement(Worte(),Random(CountList(Worte())))
String=string+Worte()+" "
Next
Debug string.s
Next
CallDebugger
UnVirtualizeAllLists()
DataSection
Artikel:
Data.s "Ein","Eine","Der","Die","Das","Den","!§$last!$%"
Nomen:
Data.s "Haus","Boot","Baum","Garten","Wolkenkratzer","Hund","Katze","Maus","!§$last!$%"
Verben:
Data.s "ist","war","wird","wurde","!§$last!$%"
Adjektive:
Data.s "schön","blau","groß","genial","unglaublich","unbrauchbar","nervig","sensationsgeil","buggy","!§$last!$%"
EndDataSection
Code: Alles auswählen
IncludeFile "Virtual_List.pb"
Enumeration
#w_Artikel
#w_Nomen
#w_Verben
#w_Adjektive
EndEnumeration
;Beispiel 3: Eine Liste zerstückeln
Global NewList Artikel.s()
Global NewList Nomen.s()
Global NewList Verben.s()
Global NewList Adjektive.s()
InitVirtualType(s)
Macro LiesWoerter(Art)
string.s=""
Restore ART
Read string.s
While String<>"!§$last!$%"
AddElement(artikel())
Artikel()=String
Read string
Wend
EndMacro
LiesWoerter(Dinger)
;Alle Begriffe finden sich nun in Worte
ForEach Artikel()
Debug Artikel()
Next
Debug "________Artikel________"
;6 Artikel, daher muss Element 7 das erste Element für Nomen() werden
SplitList(Artikel(),Nomen(),6,s)
ForEach Artikel()
Debug Artikel()
Next
Debug "__________Nomen__________"
;Jetzt ist der Rest in Nomen().
;Da es nur 8 Nomen sind, kommt wiederum dieser Rest in Verben
SplitList(Nomen(),Verben(),8,s)
ForEach Nomen()
Debug Nomen()
Next
Debug "__________Verben__________"
;Jetzt ist der Rest in Verben().
;Da es nur 4 Verben sind, kommt wiederum dieser Rest in Verben
FirstElement(Verben())
SplitList(Verben(),Adjektive(),4,s)
ForEach Verben()
Debug Verben()
Next
Debug "___________Adjektive_______"
ForEach Adjektive()
Debug Adjektive()
Next
CallDebugger
UnVirtualizeAllLists()
DataSection
Dinger:
Data.s "Ein","Eine","Der","Die","Das","Den"
Data.s "Haus","Boot","Baum","Garten","Wolkenkratzer","Hund","Katze","Maus"
Data.s "ist","war","wird","wurde"
Data.s "schön","blau","groß","genial","unglaublich","unbrauchbar","nervig","sensationsgeil","buggy","!§$last!$%"
EndDataSection
Code: Alles auswählen
IncludeFile "Virtual_List.pb"
Enumeration
#w_Artikel
#w_Nomen
#w_Verben
#w_Adjektive
EndEnumeration
;Beispiel 2: Mehrere Listen zu einer connecten
Global NewList Worte.s()
Global NewList Nomen.s()
Global NewList Verben.s()
Global NewList Adjektive.s()
Global NewList Artikel.s()
InitVirtualType(s)
;Beispiel 1: Ein Array von Listen
Macro LiesWoerter(Art)
string.s=""
Restore ART
Read string.s
While String<>"!§$last!$%"
AddElement(Art())
Art()=string
Read string
Wend
EndMacro
LiesWoerter(Artikel)
LiesWoerter(Nomen)
LiesWoerter(Verben)
LiesWoerter(Adjektive)
ClearList(Worte())
ConnectLists(Worte(),Artikel(),s)
ForEach Worte()
Debug Worte()
Next
Debug "_______________________"
ConnectLists(Worte(),Nomen(),s)
ForEach Worte()
Debug Worte()
Next
Debug "_______________________"
ConnectLists(Worte(),Verben(),s)
ForEach Worte()
Debug Worte()
Next
Debug "_______________________"
ConnectLists(Worte(),Adjektive(),s)
Debug CountList(Worte())
ForEach Worte()
Debug Worte()
Next
Debug "_______________________"
CallDebugger
UnVirtualizeAllLists()
DataSection
Artikel:
Data.s "Ein","Eine","Der","Die","Das","Den","!§$last!$%"
Nomen:
Data.s "Haus","Boot","Baum","Garten","Wolkenkratzer","Hund","Katze","Maus","!§$last!$%"
Verben:
Data.s "ist","war","wird","wurde","!§$last!$%"
Adjektive:
Data.s "schön","blau","groß","genial","unglaublich","unbrauchbar","nervig","sensationsgeil","buggy","!§$last!$%"
EndDataSection
ist es aber überall, wo man auf komplexere Datenstrukturen trifft.
Feedback Willkommen, Bugreports geduldet

Achja, weitere Funktionen für LinkedLists natürlich auch
