Object - Manager Include
Verfasst: 30.12.2008 10:41
Hier mal ein kleines Object - Manager Include das ich gestern schnell zusammengeproggt habe.
Der Object - Manager funktioniert exakt wie der PB - ObjectManager:
http://www.purearea.net/pb/german/manua ... jects.html
d.H. er bietet Statische und Dynamische Indexierung, Automatische Deinitialsierung und ist leicht zu benutzen und verstehen.
Für was brauche ich das?
Nun, mit diesem Code könnt ihr allen euren Includes ein einfaches Managemant verpassen, wie es sämtliche PB Funktionen haben. (Window, Gadget, Image, Sprite, ....) . Unter anderem auch nützlich bei der Erstellung von DLLs, UserLibrarys usw. um "PB - Like" managed Funktionen zu bieten.
Am Ende des Includes steht ein kleines Beispiel um die Funktion des Managers zu demonstrieren:
Der Object - Manager funktioniert exakt wie der PB - ObjectManager:
http://www.purearea.net/pb/german/manua ... jects.html
d.H. er bietet Statische und Dynamische Indexierung, Automatische Deinitialsierung und ist leicht zu benutzen und verstehen.
Für was brauche ich das?
Nun, mit diesem Code könnt ihr allen euren Includes ein einfaches Managemant verpassen, wie es sämtliche PB Funktionen haben. (Window, Gadget, Image, Sprite, ....) . Unter anderem auch nützlich bei der Erstellung von DLLs, UserLibrarys usw. um "PB - Like" managed Funktionen zu bieten.
Am Ende des Includes steht ein kleines Beispiel um die Funktion des Managers zu demonstrieren:
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; Include: Object - Manager
; Autor: Alexander Aigner
; minimale PB - Version: 4.3
; ------------------------------------------------------------------------------------
EnableExplicit
Prototype _OM_Init(cId.i, *Entry)
Structure _OM_Entry ; OM - Eintrag
isInit.i ; Entry - ist Initialisiert
*Data ; Entry - Daten
EndStructure
Structure _OM_Entry_Holder
Holder._OM_Entry[0]
EndStructure
Structure _OM_Inits ; (De)Initialisierung - Aufrufe
; Init._OM_Init ; Initialisierung für jedes Entry
DeInit._OM_Init ; DeInitialisierung für jedes Entry
EndStructure
Structure _OM_Data ; OM - Informationen
Count.i ; Akteller Entry
RealEntryCount.i ; Wirkliche Anzahl der Entrys
BlockSize.i ; Größe eines Entrys
BlockCount.i ; Anzahl der Entry - Blöcke
Pt._OM_Inits ; Prototypes
*Entry._OM_Entry_Holder ; Entrys
EndStructure
Enumeration -1
#OM_Any
#OM_StandardBlockSize = 25
EndEnumeration
Declare OM_Init(*DeInit._OM_Init, BlockSize.i = #OM_StandardBlockSize)
Declare OM_DeInit(*OM._OM_Data)
Declare OM_SetEntry(*OM._OM_Data, Id.i, *EntryData)
Declare OM_GetEntry(*OM._OM_Data, Id.i)
Declare OM_DeleteEntry(*OM._OM_Data, Id.i)
Declare OM_IsEntry(*OM._OM_Data, Id.i)
Declare OM_ParseAllEntrys(*OM._OM_Data, *Pt._OM_Init)
Declare OM_GetEntryCount(*OM._OM_Data)
Declare OM_GetSize(*OM._OM_Data)
; ------------------------------------------------------------------------------------
; Internal
; ------------------------------------------------------------------------------------
Macro Mem_Alloc(_mem)
AllocateMemory(_mem)
EndMacro
Macro Mem_ReAlloc(_mem, _size)
ReAllocateMemory(_mem, _size)
EndMacro
Macro Mem_Free(_mem)
FreeMemory(_mem)
EndMacro
Procedure OM_Init(*DeInit._OM_Init, BlockSize.i = #OM_StandardBlockSize) ; Neuen Objekt - Manager erstellen
Protected currentEntry
Define *OM._OM_Data = Mem_Alloc(SizeOf(_OM_Data))
With *OM
\Pt\DeInit = *DeInit
\BlockSize = BlockSize
\BlockCount = 1
\Count = 0
\Entry = Mem_Alloc(\BlockSize*\BlockCount*SizeOf(_OM_Entry))
EndWith
ProcedureReturn *OM
EndProcedure
Procedure OM_DeInit(*OM._OM_Data) ; Objektmanager komplett freigeben
Protected currentId
With *OM
OM_ParseAllEntrys(*OM, \Pt\DeInit) ; Alle Entrys Freigeben
Mem_Free(\Entry) ; EntryIndex freigeben
Mem_Free(*OM) ; ObjektManager Struktur freigeben
EndWith
EndProcedure
Procedure OM_SetEntry(*OM._OM_Data, Id.i, *EntryData)
Protected currentId, RtVar
With *OM
If Id = #OM_Any ; Id ermitteln
\Count + 1
currentId = \Count
ElseIf Id>\Count
\Count = Id
currentId = \Count
Else
currentId = Id
EndIf
While currentId> = \BlockSize*\BlockCount ; Muss der Bereich vergrößert werden?
\BlockCount + 1
\Entry = Mem_ReAlloc(\Entry, \BlockSize*\BlockCount*SizeOf(_OM_Entry))
Wend
If \Entry\Holder[currentId]\isInit
If Not OM_GetEntry(*OM, currentID) <> *EntryData ; Wenn alte Speicheradresse <> neuer Speicheradresse
\Pt\DeInit(currentId, OM_GetEntry(*OM, currentID)) ; Alte Daten deinitialisieren
EndIf
Else
\RealEntryCount + 1 ; Wenn neuer Entry : Anzahl erhöhen
EndIf
\Entry\Holder[currentId]\Data = *EntryData ; Daten schreiben
\Entry\Holder[currentId]\isInit = #True ; Initialisiert = #True
If Id = #OM_Any ; Rückgabewert festlegen
RtVar = currentId
Else
RtVar = *EntryData;\Entry\Holder[currentId]\Data
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
Procedure OM_GetEntry(*OM._OM_Data, Id.i) ; Entry holen
Protected RtVar
With *OM
If OM_IsEntry(*OM, Id)
RtVar = \Entry\Holder[Id]\Data
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
Procedure OM_DeleteEntry(*OM._OM_Data, Id.i) ; Entry löschen
Protected RtVar
With *OM
If OM_IsEntry(*OM, Id)
\Pt\DeInit(Id, OM_GetEntry(*OM, Id)) ; Deinitialisieren
\Entry\Holder[Id]\isInit = #False
\RealEntryCount-1
If \Count = Id ; zu löschendes Element = Letztes Element: Count kann dekrementiert werden
\Count-1
EndIf
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
Procedure OM_IsEntry(*OM._OM_Data, Id.i) ; Prüfen: ist Entry gültig?
Protected RtVar
With *OM
If Id> = \BlockSize*\BlockCount
RtVar = #False
Else
If \Entry\Holder[Id]\isInit
RtVar = #True
Else
RtVar = #False
EndIf
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
Procedure OM_ParseAllEntrys(*OM._OM_Data, *Pt._OM_Init) ; Alle Entrys an Procedure senden
Protected currentId, EntryCount
With *OM
For currentId = 0 To \Count
If OM_IsEntry(*OM, currentId)
*Pt(currentId, OM_GetEntry(*OM, currentId))
EntryCount+1
If EntryCount >= \RealEntryCount
Break
EndIf
EndIf
Next
EndWith
EndProcedure
Procedure OM_GetEntryCount(*OM._OM_Data) ; Anzahl der Entrys ermitteln
Protected RtVar
With *OM
RtVar = \RealEntryCount
EndWith
ProcedureReturn RtVar
EndProcedure
Procedure OM_GetSize(*OM._OM_Data) ; Speichergröße des Managers ermitteln
Protected RtVar
With *OM
RtVar = SizeOf(_OM_Data)+\BlockCount*\BlockSize*SizeOf(_OM_Entry)
EndWith
ProcedureReturn RtVar
EndProcedure
DisableExplicit
; ------------------------------------------------------------------------------------
; Beispiel:
; ------------------------------------------------------------------------------------
; Beispiel - Struktur
Structure MyImage
x.i
y.i
width.i
height.i
oID.i
*RawData
EndStructure
; Deininitializer - callback
Procedure FreeMyImage(ImgId, *Img.MyImage)
Debug "Lösche: Id: " + Str(ImgId) + " Data: " + Str(*Img)
Mem_Free(*Img\RawData)
Mem_Free(*Img)
EndProcedure
; Neues Image machen
Procedure NewMyImage(x.i, y.i, width.i, height.i)
*Img.MyImage = Mem_Alloc(SizeOf(MyImage))
*Img\x = x
*Img\y = y
*Img\width = width
*Img\height = height
*Img\oID = Random(1000000)
*Img\RawData = Mem_Alloc(1000)
ProcedureReturn *Img
EndProcedure
; Object - Manager Initialisieren
Global ImageManager = OM_Init(@FreeMyImage())
Procedure ImageInfo(ImgId)
If OM_isEntry(ImageManager, ImgId)
*Image.MyImage = OM_GetEntry(ImageManager, ImgId)
Debug "X: " + Str(*Image\x)
Debug "Y: " + Str(*Image\y)
Debug "Width: " + Str(*Image\Width)
Debug "Height: " + Str(*Image\Height)
Debug "OS - ID: " + Str(*Image\oID)
Else
Debug "ImgID nicht gültig!"
EndIf
EndProcedure
; Images erstellen
*NewImage.MyImage = NewMyImage(12, 45, 800, 600)
*NewImage2.MyImage = NewMyImage(0, 12, 600, 825)
; Mit Any in den Object-Manager laden
Img1 = OM_SetEntry(ImageManager, #OM_Any, *NewImage)
; Feste ID
OM_SetEntry(ImageManager, 45, *NewImage2)
; Probe
ImageInfo(Img1)
ImageInfo(45)
ImageInfo(46) ; müsste Fehler geben
OM_DeInit(ImageManager) ; Alle Elemente Freigeben