ich habe hier mal wieder meine altbewährten Funktionen zum Schreiben und
Lesen von strukturierten Variablen in und aus einer Datei und zum Kopieren
einer strukturierten Variablen in eine andere ausgepackt und erneuert.
///Edit 1:
+ Funktionen etwas verkürzt.
///Edit 2:
+ Vielleicht etwas schneller
+ WriteSizeStructure() zum Ermitteln der Bytes, die bei WriteStructure() geschrieben werden
///Edit 3:
+ Vereinfachung für Strukturen mit statischen Arrays (s. Beispiel)
///Edit 4:
+ Ascii, Unicode und Integer hinzugefügt
+ CopyStructure() entfernt, da es das jetzt nativ gibt
+ Funktioniert erst ab der nächsten Beta
///Edit 5:
+ Jetzt geht es auch mit der aktuellen Beta
///Edit 6:
+ Proceduren geben nun einen Integer zurück (Danke ts-soft)
+ Beispiele sind kompatibel zu Windows und Linux (Danke ts-soft)
///Edit 7:
+ Code verkürzt
+ Code schneller gemacht
Der folgende Code funktioniert mit PB V4.50 beta 3 unter Linux und Windows.
Code: Alles auswählen
Structure test1
id.l
Name.s
points.f[10] ;<-----------
EndStructure ; |
Structure Strukt ; |
Byte.b ; |
word.w ; |
Long.l ; |
Quad.q ; |
String1.s ; |
Float.f ; |
test1.test1[5] ;<---- |
String2.s ; | |
Double.d ; | |
EndStructure ; | |
Global Struc_Strukt.s ;| |
Struc_Strukt = "bwlqsf[5ls[10f]]sd" ; Die Struktur selbst in einem String
Structure AllTypes
StructureUnion
b.b : c.c : w.w : l.l : f.f : d.d : q.q : a.a : u.u : i.i
EndStructureUnion
EndStructure
Procedure.i WriteSizeStructure(*Var.AllTypes, *Struc.Character, *extralength.Integer = 0)
Protected length.l = 0, mode.l = 0, c.l, *Start, alllength.l = 0, strlength.i
While *Struc\c And (*Struc\c <> ']' Or mode)
If mode = 0
If *Struc\c = 's'
*Var + length
alllength + length + SizeOf(String)
If *extralength
*extralength\i + Len(PeekS(*Var\i))
Else
strlength + Len(PeekS(*Var\i))
EndIf
*Var + SizeOf(String)
length = 0
ElseIf *Struc\c = '['
*Var + length
alllength + length
*Start = *Struc
mode = 1
c = 0
length = 0
Else
length + PeekA(?WriteReadStructure + *Struc\c - 'a')
EndIf
Else
Select *Struc\c
Case '[' : mode + 1 ;weitere Verschachtelungen ignorieren
Case ']' : mode - 1
Default
If *Struc\c >= '0' And *Struc\c <= '9' And mode = 1
c * 10 + *Struc\c - '0'
*Start + SizeOf(Character)
EndIf
EndSelect
If mode = 0 ;Wenn Ende der Verschachtelung gefunden
While c
length = WriteSizeStructure(*Var, *Start + SizeOf(Character), @strlength)
alllength + length
*Var + length
c - 1
Wend
length = 0
EndIf
EndIf
*Struc + SizeOf(Character)
Wend
ProcedureReturn alllength + length + strlength
EndProcedure
Procedure.i WriteStructure(FileID, *Var.AllTypes, *Struc.Character)
Protected length.l = 0, mode.l = 0, c.l, *Start, alllength.l = 0
While *Struc\c And (*Struc\c <> ']' Or mode)
If mode = 0
If *Struc\c = 's'
If length : WriteData(FileID, *Var, length) : *Var + length : alllength + length : EndIf
length = StringByteLength(PeekS(*Var\i))
WriteInteger(FileID, length)
If length : WriteData(FileID, *Var\i, length) : EndIf
alllength + SizeOf(Integer)
*Var + SizeOf(Integer)
length = 0
ElseIf *Struc\c = '['
If length : WriteData(FileID, *Var, length) : *Var + length : alllength + length : EndIf
*Start = *Struc
mode = 1
c = 0
length = 0
Else
length + PeekA(?WriteReadStructure + *Struc\c - 'a')
EndIf
Else
Select *Struc\c
Case '[' : mode + 1 ;weitere Verschachtelungen ignorieren
Case ']' : mode - 1
Default
If *Struc\c >= '0' And *Struc\c <= '9' And mode = 1
c * 10 + *Struc\c - '0'
*Start + SizeOf(Character)
EndIf
EndSelect
If mode = 0 ;Wenn Ende der Verschachtelung gefunden
While c
length = WriteStructure(FileID, *Var, *Start + SizeOf(Character))
alllength + length
*Var + length
c - 1
Wend
length = 0
EndIf
EndIf
*Struc + SizeOf(Character)
Wend
If length : WriteData(FileID, *Var, length) : EndIf
ProcedureReturn alllength + length
EndProcedure
Procedure.i ReadStructure(FileID, *Var.AllTypes, *Struc.Character)
Protected length.l, alllength.l, mode.l, c.l, *Start, *s.String, *mem
While *Struc\c And (*Struc\c <> ']' Or mode)
If mode = 0
If *Struc\c = 's'
If length : ReadData(FileID, *Var, length) : *Var + length : alllength + length : EndIf
length = ReadInteger(FileID)
*s = *Var
InitializeStructure(*s, String)
If length
*mem = AllocateMemory(length)
If *mem
ReadData(FileID, *mem, length)
*s\s = PeekS(*mem, length)
FreeMemory(*mem)
EndIf
EndIf
alllength + SizeOf(Integer)
*Var + SizeOf(Integer)
length = 0
ElseIf *Struc\c = '['
If length : ReadData(FileID, *Var, length) : *Var + length : alllength + length : EndIf
*Start = *Struc
mode = 1
c = 0
length = 0
Else
length + PeekA(?WriteReadStructure + *Struc\c - 'a')
EndIf
Else
Select *Struc\c
Case '[' : mode + 1
Case ']' : mode - 1
Default
If *Struc\c >= '0' And *Struc\c <= '9' And mode = 1
c * 10 + *Struc\c - '0'
*Start + SizeOf(Character)
EndIf
EndSelect
If mode = 0
While c
length = ReadStructure(FileID, *Var, *Start + SizeOf(Character))
alllength + length
*Var + length
c - 1
Wend
length = 0
EndIf
EndIf
*Struc + SizeOf(Character)
Wend
If length : ReadData(FileID, *Var, length) : EndIf
ProcedureReturn alllength + length
EndProcedure
DataSection
WriteReadStructure:
Data.a SizeOf(Ascii), SizeOf(Byte), SizeOf(Character), SizeOf(Double), 0
Data.a SizeOf(Float), 0, 0, SizeOf(Integer), 0
Data.a 0, SizeOf(Long), 0, 0, 0
Data.a 0, SizeOf(Quad), 0, 0, 0
Data.a SizeOf(Unicode), 0, SizeOf(Word), 0, 0
Data.a 0
EndDataSection
Var1.Strukt
Var1\Byte = 123
Var1\word = 23432
Var1\Long = 13579123
Var1\Quad = 2468012343344533
Var1\String1 = "Hallo du!"
Var1\Float = 1234.1234
Var1\String2 = "Ich bin NTQ!"
Var1\Double = 123456789.123456789
For a = 0 To 4
Var1\test1[a]\id = a + 1
Var1\test1[a]\Name = "Name: " + Str(Random(100000000))
For b = 0 To 9
Var1\test1[a]\points[b] = a * 100 + b + 101
Next
Next
MessageRequester("Struktur Größe", Str(WriteSizeStructure(Var1, @Struc_Strukt)) + " Bytes")
Var2.Strukt
CopyStructure(Var1, Var2, Strukt)
MessageRequester("Kopierte Struktur", "Byte: " + Str(Var2\Byte) + Chr(13) + "Word: " + Str(Var2\word) + Chr(13) + "Long: " + Str(Var2\Long) + Chr(13) + "Quad: " + Str(Var2\Quad) + Chr(13) + "String1: " + Var2\String1 + Chr(13) + "Float: " + Str(Var2\Float) + Chr(13) + "String2: " + Var2\String2 + Chr(13) + "Double: " + StrD(Var2\Double))
For a = 0 To 4
Debug Var2\test1[a]\id
Debug Var2\test1[a]\Name
For b = 0 To 9
Debug Var2\test1[a]\points[b]
Next
Next
Debug GetCurrentDirectory()
If CreateFile(0, ".\test_structure.txt")
WriteStructure(0, Var1, @Struc_Strukt)
CloseFile(0)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
If FileSize("/usr/bin/bless") >= 0
RunProgram("bless", ".\test_structure.txt", "./", #PB_Program_Wait)
Else
MessageRequester("Warnung!", "Hexeditor 'bless' wurde nicht gefunden.")
EndIf
CompilerCase #PB_OS_Windows
RunProgram(".\test_structure.txt", "", "./", #PB_Program_Wait)
CompilerEndSelect
EndIf
If ReadFile(0, ".\test_structure.txt")
Var3.Strukt
ReadStructure(0, Var3, @Struc_Strukt)
CloseFile(0)
MessageRequester("Ausgelesene Struktur", "Byte: " + Str(Var3\Byte) + Chr(13) + "Word: " + Str(Var3\word) + Chr(13) + "Long: " + Str(Var3\Long) + Chr(13) + "Quad: " + Str(Var3\Quad) + Chr(13) + "String1: " + Var3\String1 + Chr(13) + "Float: " + Str(Var3\Float) + Chr(13) + "String2: " + Var3\String2 + Chr(13) + "Double: " + StrD(Var3\Double))
For a = 0 To 4
Debug Var3\test1[a]\id
Debug Var3\test1[a]\Name
For b = 0 To 9
Debug Var3\test1[a]\points[b]
Next
Next
EndIf