Der Pool erweitert sich dynamisch, erkennt doppelt verwendete Strings und kann auch Teilstrings anderer Strings verwenden um Speicher zu sparen.
zb.: Wenn man "weder" im Pool gespeichert und "der" im Pool speichern will kann der Pool erkennen das "der" schon in "weder" vorkommt und verwendet nur diesen Teilstring und legt nicht mehr Speicher an.
Der ganze Pool kann exportiert und z.b. in einer Datei gespeichert werden und wieder importiert werden.
Das schreiben in den Pool ist sehr viel langsamer als das lesen:
Für mich ist die Schreibgeschwindigkeit irrelevant da ich nur am anfang in den Pool schreibe und danach nur noch lese.String Pool:
1.000.000 Schreiben : 10,87 Sek (ohne Tiefensuche)
1.000.000 Lesen : 16 ms
String Array:
1.000.000 Schreiben : 125 ms
1.000.000 Lesen : 78 ms
Wers braucht:
// EDIT: Neuer Code, kleiner Bug im alten
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; String-Pool
; Beliebig großer dynamischer String Pool
; ------------------------------------------------------------------------------------
Structure _SP_Entry
Pos.l
Size.l
EndStructure
Structure _SP_Array
Entry._SP_Entry[0]
EndStructure
Global *_SP_Info._SP_Array, *_SP_Data, _SP_Size = 0, _SP_Count = 0
; Startwerte setzen
*_SP_Data = AllocateMemory(1)
*_SP_Info = AllocateMemory(1*SizeOf(_SP_Entry))
; Leere Strings abfangen
*_SP_Info\Entry[0]\Pos = 0
*_SP_Info\Entry[0]\Size = 0
Procedure _FindInMem(*Mem1, *Mem2, len1, len2)
epos = len1-len2-1
For i = 0 To epos
If CompareMemory(*Mem1 + i, *Mem2, len2)
ProcedureReturn i
EndIf
Next
ProcedureReturn -1
EndProcedure
; Gibt den ganzen Speicher frei und stetzt alle Zähler zurück.
Procedure SP_Reset()
FreeMemory(*_SP_Data) : *_SP_Data = AllocateMemory(1)
FreeMemory(*_SP_Info) : *_SP_Info = AllocateMemory(1*SizeOf(_SP_Entry))
*_SP_Info\Entry[0]\Pos = 0
*_SP_Info\Entry[0]\Size = 0
_SP_Size = 0
_SP_Count = 0
EndProcedure
; Exportiert den Stringpool + Index in einen Speicher und gibt die Adresse darauf zurück
Procedure SP_Export()
_SP_Info_Size = (_SP_Count + 1)*SizeOf(_SP_Entry)
*ExportMem = AllocateMemory(_SP_Info_Size + _SP_Size + 2*SizeOf(LONG))
PokeL(*ExportMem, _SP_Count)
CopyMemory(*_SP_Info, *ExportMem + SizeOf(LONG), _SP_Info_Size)
PokeL(*ExportMem + SizeOf(LONG) + _SP_Info_Size, _SP_Size)
CopyMemory(*_SP_Data, *ExportMem + 2*SizeOf(LONG) + _SP_Info_Size, _SP_Size)
ProcedureReturn *ExportMem
EndProcedure
; Importiert einen mit Sp_Export() erstellten Speicher
Procedure SP_Import(*Mem)
FreeMemory(*_SP_Data)
FreeMemory(*_SP_Info)
_SP_Count = PeekL(*Mem)
_SP_Info_Size = (_SP_Count + 1)*SizeOf(_SP_Entry)
*_SP_Info = AllocateMemory(_SP_Info_Size)
CopyMemory(*Mem + SizeOf(LONG), *_SP_Info, _SP_Info_Size)
_SP_Size = PeekL(*Mem + SizeOf(LONG) + _SP_Info_Size)
*_SP_Data = AllocateMemory(_SP_Size)
CopyMemory(*Mem + 2*SizeOf(LONG) + _SP_Info_Size, *_SP_Data, _SP_Size)
FreeMemory(*Mem)
EndProcedure
; Holt den String: Index
Procedure.s SP_Get(Index)
If Index< = _Sp_Count
ProcedureReturn PeekS(*_SP_Data + *_SP_Info\Entry[Index]\Pos, *_SP_Info\Entry[Index]\Size)
EndIf
EndProcedure
; Speichert einen String im Pool und gibt einen Index darauf zurück
Procedure SP_Add(String.s, Search = 0, DeepSearch = 0)
*SMem = @String
Slen = MemoryStringLength(*SMem)
; Doppelte finden
If Search
For i = 0 To _SP_Count
If *_SP_Info\Entry[i]\Size = Slen ; Zuerst nur Länge vergleichen
If CompareMemory(*_SP_Data + *_SP_Info\Entry[i]\Pos, *SMem, Slen) ; Dann ganzen String
ProcedureReturn i
EndIf
ElseIf DeepSearch And *_SP_Info\Entry[i]\Size>Slen ; String in anderen Strings finden
tpos = _FindInMem(*_SP_Data + *_SP_Info\Entry[i]\Pos, *SMem, *_SP_Info\Entry[i]\Size, Slen)
If tpos<> -1
_SP_Count + 1
*_SP_Info = ReAllocateMemory(*_SP_Info, (_SP_Count + 1)*SizeOf(_SP_Entry))
*_SP_Info\Entry[_SP_Count]\Pos = *_SP_Info\Entry[i]\Pos + tpos
*_SP_Info\Entry[_SP_Count]\Size = Slen
ProcedureReturn _SP_Count
EndIf
EndIf
Next
EndIf
_SP_Count + 1
If Slen
*_SP_Data = ReAllocateMemory(*_SP_Data, _SP_Size + Slen)
*_SP_Info = ReAllocateMemory(*_SP_Info, (_SP_Count + 1)*SizeOf(_SP_Entry))
CopyMemory(*SMem, *_SP_Data + _SP_Size, Slen)
*_SP_Info\Entry[_SP_Count]\Pos = _SP_Size
*_SP_Info\Entry[_SP_Count]\Size = Slen
_SP_Size + Slen
ProcedureReturn _SP_Count
Else
ProcedureReturn 0
EndIf
EndProcedure