DynamicMemory
Verfasst: 22.07.2011 00:10
Hi Leute,
für mein aktuelles Projekt hab ich mir eine Include geschrieben, die man eigentlich immer wieder mal gebrauchen könnte: DynamicMemory
Sie hat zwei Funktionen: Sie aktuallisiert nach jedem Lesen bzw. Schreiben im Speicherblock die Position, an der danach gelesen bzw. geschrieben wird (je nach Länge der Daten), und sie vergrößert ggf. den Speicherblock, wenn er nicht mehr ausreicht. Das ist halt dann besonders hilfreich, wenn man eine Menge Daten in einen Speicherblock schreiben will, man aber vorher nicht weiß, wie groß er sein muss.
Die Include ist im OOP-Style geschrieben. DYMMemory ist das Interface, dieses hat viele Funktionen der MemoryLib, wie Peek und Poke. Mit DYMNewMemory() erzeugt man ein neuen Speicherblock, mit *dym\free() gibt man ihn wieder frei.
Hier ein Beispielcode:
DynamicMemoryTest.pb
Und hier die Include:
DynamicMemory.pbi:
lg Kevin
für mein aktuelles Projekt hab ich mir eine Include geschrieben, die man eigentlich immer wieder mal gebrauchen könnte: DynamicMemory
Sie hat zwei Funktionen: Sie aktuallisiert nach jedem Lesen bzw. Schreiben im Speicherblock die Position, an der danach gelesen bzw. geschrieben wird (je nach Länge der Daten), und sie vergrößert ggf. den Speicherblock, wenn er nicht mehr ausreicht. Das ist halt dann besonders hilfreich, wenn man eine Menge Daten in einen Speicherblock schreiben will, man aber vorher nicht weiß, wie groß er sein muss.
Die Include ist im OOP-Style geschrieben. DYMMemory ist das Interface, dieses hat viele Funktionen der MemoryLib, wie Peek und Poke. Mit DYMNewMemory() erzeugt man ein neuen Speicherblock, mit *dym\free() gibt man ihn wieder frei.
Hier ein Beispielcode:
DynamicMemoryTest.pb
Code: Alles auswählen
IncludeFile "DynamicMemory.pbi"
Define *dym.DYMMemory
Define size, *memory
; write new memory block
*dym = DYMNewMemory()
*dym\PokeI(0) ; reserved for the size
For i = 0 To 9
*dym\PokeI(i)
Next
*dym\PokeS("Hello World!")
*dym\fill(5,42)
; save the size
*dym\setPosition(0)
*dym\PokeI(*dym\getSize())
If CreateFile(0, GetTemporaryDirectory()+"DynamicMemoryTest")
WriteData(0, *dym\getMemory(), *dym\getSize())
CloseFile(0)
EndIf
*dym\free()
; read the memory block
If ReadFile(0, GetTemporaryDirectory()+"DynamicMemoryTest")
size = ReadInteger(0)
*memory = AllocateMemory(size)
FileSeek(0, 0)
ReadData(0, *memory, size)
*dym = DYMNewMemory(*memory)
*dym\PeekI()
For i = 0 To 9
Debug *dym\PeekI()
Next
Debug *dym\PeekS()
For i = 0 To 4
Debug *dym\PeekB()
Next
CloseFile(0)
EndIf
Und hier die Include:
DynamicMemory.pbi:
Code: Alles auswählen
; Name: DynamicMemory
; Author: Kevin Jasik (CSHW89)
; Date: 21.07.2011
Structure DYMValue
StructureUnion
byte.b
word.w
long.l
float.f
quad.q
double.d
character.c
ascii.a
unicode.c
integer.i
EndStructureUnion
EndStructure
Structure DYMMemoryObj
*VTable
*memory
*pos.DYMValue
size.i
EndStructure
Interface DYMMemory
free()
PokeB(byte.b)
PokeW(word.w)
PokeL(long.l)
PokeF(float.f)
PokeQ(quad.q)
PokeD(double.d)
PokeC(character.c)
PokeA(ascii.a)
PokeU(unicode.u)
PokeI(integer.i)
PokeS(string.s, length.i = -1, format.i = 0)
PeekB.b()
PeekW.w()
PeekL.l()
PeekF.f()
PeekQ.q()
PeekD.d()
PeekC.c()
PeekA.a()
PeekU.u()
PeekI.i()
PeekS.s(length.i = -1, format.i = 0)
copy(*source, length.i)
move(*source, length.i)
fill(size.i, value.i = 0, type.i = 0)
getMemory.i()
getPosition.i()
setPosition(position.i)
movePosition(move.i)
getSize.i()
expand(size.i)
EndInterface
; Free the memory previously allocated with DYMNewMemory
; and the dinamic-memory-object *dym
Procedure DYMFreeMemory(*dym.DYMMemoryObj)
FreeMemory(*dym\memory)
FreeMemory(*dym)
EndProcedure
Macro DYMCheckExpandMemory(_bytes_)
Protected position.i, newSize.i
Protected *savemem
; relative position to the memory
position = *dym\pos - *dym\memory
; while the space is not enough
While (position + _bytes_ >= *dym\size)
newSize = *dym\size * 2
*savemem = *dym\memory
*dym\memory = ReAllocateMemory(*dym\memory, newSize)
If (*dym\memory = #Null)
*dym\memory = *savemem
ProcedureReturn #False
EndIf
; set the new position, because the memory may be different
*dym\pos = *dym\memory + position
*dym\size = newSize
Wend
EndMacro
; Writes a byte number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeB(*dym.DYMMemoryObj, byte.b)
DYMCheckExpandMemory(SizeOf(Byte))
*dym\pos\byte = byte
*dym\pos + SizeOf(Byte)
ProcedureReturn #True
EndProcedure
; Writes a word number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeW(*dym.DYMMemoryObj, word.w)
DYMCheckExpandMemory(SizeOf(Word))
*dym\pos\word = word
*dym\pos + SizeOf(Word)
ProcedureReturn #True
EndProcedure
; Writes a long number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeL(*dym.DYMMemoryObj, long.l)
DYMCheckExpandMemory(SizeOf(Long))
*dym\pos\long = long
*dym\pos + SizeOf(Long)
ProcedureReturn #True
EndProcedure
; Writes a float number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeF(*dym.DYMMemoryObj, float.f)
DYMCheckExpandMemory(SizeOf(Float))
*dym\pos\float = float
*dym\pos + SizeOf(Float)
ProcedureReturn #True
EndProcedure
; Writes a quad number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeQ(*dym.DYMMemoryObj, quad.q)
DYMCheckExpandMemory(SizeOf(Quad))
*dym\pos\quad = quad
*dym\pos + SizeOf(Quad)
ProcedureReturn #True
EndProcedure
; Writes a double number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeD(*dym.DYMMemoryObj, double.d)
DYMCheckExpandMemory(SizeOf(Double))
*dym\pos\double = double
*dym\pos + SizeOf(Double)
ProcedureReturn #True
EndProcedure
; Writes a character number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeC(*dym.DYMMemoryObj, character.c)
DYMCheckExpandMemory(SizeOf(Character))
*dym\pos\character = character
*dym\pos + SizeOf(Character)
ProcedureReturn #True
EndProcedure
; Writes an ascii character to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeA(*dym.DYMMemoryObj, ascii.a)
DYMCheckExpandMemory(SizeOf(Ascii))
*dym\pos\ascii = ascii
*dym\pos + SizeOf(Ascii)
ProcedureReturn #True
EndProcedure
; Writes an unicode character to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeU(*dym.DYMMemoryObj, unicode.u)
DYMCheckExpandMemory(SizeOf(Unicode))
*dym\pos\unicode = unicode
*dym\pos + SizeOf(Unicode)
ProcedureReturn #True
EndProcedure
; Writes an integer number to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeI(*dym.DYMMemoryObj, integer.i)
DYMCheckExpandMemory(SizeOf(integer))
*dym\pos\integer = integer
*dym\pos + SizeOf(Integer)
ProcedureReturn #True
EndProcedure
; Writes a string (including the ending '0') to the dynamic-memory-object
; If space is not enough, the memory will be expanded automatically
Procedure DYMPokeS(*dym.DYMMemoryObj, string.s, length.i = -1, format.i = 0)
Protected size.i
If (length > -1)
string = Left(string, length)
EndIf
size = StringByteLength(string+" ", format)
DYMCheckExpandMemory(size)
PokeS(*dym\pos, string, -1, format)
*dym\pos + size
ProcedureReturn #True
EndProcedure
; Reads a byte number from the dynamic-memory-object
Procedure.b DYMPeekB(*dym.DYMMemoryObj)
Protected byte.b
byte = *dym\pos\byte
*dym\pos + SizeOf(Byte)
ProcedureReturn byte
EndProcedure
; Reads a word number from the dynamic-memory-object
Procedure.w DYMPeekW(*dym.DYMMemoryObj)
Protected word.w
word = *dym\pos\word
*dym\pos + SizeOf(Word)
ProcedureReturn word
EndProcedure
; Reads a long number from the dynamic-memory-object
Procedure.l DYMPeekL(*dym.DYMMemoryObj)
Protected long.l
long = *dym\pos\long
*dym\pos + SizeOf(Long)
ProcedureReturn long
EndProcedure
; Reads a float number from the dynamic-memory-object
Procedure.f DYMPeekF(*dym.DYMMemoryObj)
Protected float.f
float = *dym\pos\float
*dym\pos + SizeOf(Float)
ProcedureReturn float
EndProcedure
; Reads a quad number from the dynamic-memory-object
Procedure.q DYMPeekQ(*dym.DYMMemoryObj)
Protected quad.q
quad = *dym\pos\quad
*dym\pos + SizeOf(Quad)
ProcedureReturn quad
EndProcedure
; Reads a double number from the dynamic-memory-object
Procedure.d DYMPeekD(*dym.DYMMemoryObj)
Protected double.d
double = *dym\pos\double
*dym\pos + SizeOf(Double)
ProcedureReturn double
EndProcedure
; Reads a character number from the dynamic-memory-object
Procedure.c DYMPeekC(*dym.DYMMemoryObj)
Protected character.c
character = *dym\pos\character
*dym\pos + SizeOf(Character)
ProcedureReturn character
EndProcedure
; Reads an ascii character from the dynamic-memory-object
Procedure.a DYMPeekA(*dym.DYMMemoryObj)
Protected ascii.a
ascii = *dym\pos\ascii
*dym\pos + SizeOf(Ascii)
ProcedureReturn ascii
EndProcedure
; Reads an unicode character from the dynamic-memory-object
Procedure.u DYMPeekU(*dym.DYMMemoryObj)
Protected unicode.u
unicode = *dym\pos\unicode
*dym\pos + SizeOf(Unicode)
ProcedureReturn unicode
EndProcedure
; Reads an integer number from the dynamic-memory-object
Procedure.i DYMPeekI(*dym.DYMMemoryObj)
Protected integer.i
integer = *dym\pos\integer
*dym\pos + SizeOf(Integer)
ProcedureReturn integer
EndProcedure
; Reads a string from the dynamic-memory-object
; The string should be ended by a '0' character, else it
; will read the memory until a '0' character is encounter.
Procedure.s DYMPeekS(*dym.DYMMemoryObj, length.i = -1, format.i = 0)
Protected string.s
string = PeekS(*dym\pos, length, format)
*dym\pos + StringByteLength(string, format)
If (length < 0)
*dym\pos + StringByteLength(" ", format)
EndIf
ProcedureReturn string
EndProcedure
; Copy a memory area starting from the *source
; to the dynamic-memory-object with the spcified length
; If space is not enough, the memory will be expanded automatically
Procedure DYMCopyMemory(*dym.DYMMemoryObj, *source, length.i)
DYMCheckExpandMemory(length)
CopyMemory(*source, *dym\pos, length)
*dym\pos + length
ProcedureReturn #True
EndProcedure
; Copy a memory area starting from the *source
; to the dynamic-memory-object with the spcified length
; If space is not enough, the memory will be expanded automatically
Procedure DYMMoveMemory(*dym.DYMMemoryObj, *source, length.i)
DYMCheckExpandMemory(length)
MoveMemory(*source, *dym\pos, length)
*dym\pos + length
ProcedureReturn #True
EndProcedure
Procedure DYMFillMemory(*dym.DYMMemoryObj, size.i, value.i = 0, type.i = 0)
DYMCheckExpandMemory(size)
FillMemory(*dym\pos, size, value, type)
*dym\pos + size
ProcedureReturn #True
EndProcedure
; Returns the memory that was allocated
; to the dynamic-memory-object
Procedure DYMGetMemory(*dym.DYMMemoryObj)
ProcedureReturn *dym\memory
EndProcedure
; Returns the relative position to the memory
Procedure DYMGetPosition(*dym.DYMMemoryObj)
ProcedureReturn *dym\pos - *dym\memory
EndProcedure
; Sets the relative position of the memory
Procedure DYMSetPosition(*dym.DYMMemoryObj, position.i)
*dym\pos = *dym\memory + position
EndProcedure
Procedure DYMMovePosition(*dym.DYMMemoryObj, move.i)
*dym\pos + move
EndProcedure
Procedure DYMGetSize(*dym.DYMMemoryObj)
ProcedureReturn *dym\size
EndProcedure
Procedure DYMExpandMemory(*dym.DYMMemoryObj, size.i)
Protected position.i, newSize.i
position = *dym\pos - *dym\memory
newSize = *dym\size + size
*dym\memory = ReAllocateMemory(*dym\memory, newSize)
*dym\pos = *dym\memory + position
*dym\size = newSize
ProcedureReturn newSize
EndProcedure
; Create a new dynamic-memory-object
; and allocates a contiguous memory area
; @param: size is an optional parameter
; It is the initial size of the memory
Procedure DYMNewMemory(*memory=#Null, size=512)
Protected *dym.DYMMemoryObj
If (size <= 0) And (*memory = #Null)
; wrong parameter
; return error of the original function
ProcedureReturn AllocateMemory(size)
EndIf
; new dynamic-memory-object
*dym = AllocateMemory(SizeOf(DYMMemoryObj))
If (*dym <> #Null)
; set the virtual function table
*dym\VTable = ?DYMMemoryFunction
; initialize memory
If (*memory <> #Null)
*dym\memory = *memory
Else
*dym\memory = AllocateMemory(size)
EndIf
If (*dym\memory = #Null)
FreeMemory(*dym)
ProcedureReturn #Null
EndIf
; set the current position to the start of the memory
; (relative position is 0)
*dym\pos = *dym\memory
*dym\size = size
EndIf
ProcedureReturn *dym
DataSection
DYMMemoryFunction:
Data.i @DYMFreeMemory()
Data.i @DYMPokeB()
Data.i @DYMPokeW()
Data.i @DYMPokeL()
Data.i @DYMPokeF()
Data.i @DYMPokeQ()
Data.i @DYMPokeD()
Data.i @DYMPokeC()
Data.i @DYMPokeA()
Data.i @DYMPokeU()
Data.i @DYMPokeI()
Data.i @DYMPokeS()
Data.i @DYMPeekB()
Data.i @DYMPeekW()
Data.i @DYMPeekL()
Data.i @DYMPeekF()
Data.i @DYMPeekQ()
Data.i @DYMPeekD()
Data.i @DYMPeekC()
Data.i @DYMPeekA()
Data.i @DYMPeekU()
Data.i @DYMPeekI()
Data.i @DYMPeekS()
Data.i @DYMCopyMemory()
Data.i @DYMMoveMemory()
Data.i @DYMFillMemory()
Data.i @DYMGetMemory()
Data.i @DYMGetPosition()
Data.i @DYMSetPosition()
Data.i @DYMMovePosition()
Data.i @DYMGetSize()
Data.i @DYMExpandMemory()
EndDataSection
EndProcedure