Seite 2 von 2

Verfasst: 14.12.2008 16:49
von cxAlex
Aktualisiert:

Code: Alles auswählen

; ------------------------------------------------------------------------------------
; String-Pool
; Beliebig großer dynamischer String Pool
; ------------------------------------------------------------------------------------

#PoolSize = $4000
#ArraySize = $100

Structure _SP_Entry
  Pos.i
  Size.i
EndStructure

Structure _SP_Array
  Entry._SP_Entry[0]
EndStructure

Structure _SP_Globals
  *Info._SP_Array
  *Data
  Size.i
  Count.i
  PoolSize.i
  ArraySize.i
EndStructure

Macro SP_Init()
  _SPG_\PoolSize = #PoolSize
  _SPG_\Data = Mem_Alloc(_SPG_\PoolSize)
  _SPG_\ArraySize = #ArraySize
  _SPG_\Info = Mem_Alloc(_SPG_\ArraySize*SizeOf(_SP_Entry))
  _SPG_\Info\Entry[0]\Pos = 0
  _SPG_\Info\Entry[0]\Size = 0
  _SPG_\Size = 0
  _SPG_\Count = 0
EndMacro

Global _SPG_._SP_Globals

; Startwerte setzen
SP_Init()

; Gibt den ganzen Speicher frei und stetzt alle Zähler zurück.
Procedure SP_Reset()
  Mem_Free(_SPG_\Data)
  Mem_Free(_SPG_\Info)
  SP_Init()
EndProcedure

; Exportiert den Stringpool + Index in einen Speicher und gibt die Adresse darauf zurück
Procedure SP_Export()
  Protected Info_Size = (_SPG_\Count + 1)*SizeOf(_SP_Entry)
  Protected *ExportMem = Mem_Alloc(Info_Size + _SPG_\Size + 2*SizeOf(LONG))
  
  PokeL(*ExportMem, _SPG_\Count)
  CopyMemory(_SPG_\Info, *ExportMem + SizeOf(LONG), Info_Size)
  PokeL(*ExportMem + SizeOf(LONG) + Info_Size, _SPG_\Size)
  CopyMemory(_SPG_\Data, *ExportMem + 2*SizeOf(LONG) + Info_Size, _SPG_\Size)
  
  ProcedureReturn *ExportMem
EndProcedure

; Importiert einen mit Sp_Export() erstellten Speicher
Procedure SP_Import(*Mem)
  Protected Info_Size
  
  Mem_Free(_SPG_\Data)
  Mem_Free(_SPG_\Info)
  _SPG_\Count = PeekL(*Mem)
  Info_Size = (_SPG_\Count + 1)*SizeOf(_SP_Entry)
  _SPG_\ArraySize = (Int(Info_Size/#ArraySize) + 1)*#ArraySize
  _SPG_\Info = Mem_Alloc(_SPG_\ArraySize)
  _SPG_\Size = PeekL(*Mem + SizeOf(LONG) + Info_Size)
  _SPG_\PoolSize = (Int(_SPG_\Size/#PoolSize) + 1)*#PoolSize
  _SPG_\Data = Mem_Alloc(_SPG_\PoolSize)
  CopyMemory(*Mem + SizeOf(LONG), _SPG_\Info, Info_Size)
  CopyMemory(*Mem + 2*SizeOf(LONG) + Info_Size, _SPG_\Data, _SPG_\Size)
  Mem_Free(*Mem)
EndProcedure

; Holt den String: Index
Macro SP_Get(Index)
  PeekS(_SPG_\Data + _SPG_\Info\Entry[Index]\Pos, _SPG_\Info\Entry[Index]\Size)
EndMacro

; Speichert einen String im Pool und gibt einen Index darauf zurück
Procedure SP_Add(String.s, Search = 0, DeepSearch = 0)
  Protected *SMem = @String
  Protected Slen = MemoryStringLength(*SMem)
  Protected tpos, i
  
  ; Doppelte finden
  If Search
    For i = 1 To _SPG_\Count
      If _SPG_\Info\Entry[i]\Size = Slen ; Zuerst nur Länge vergleichen
        If CompareMemory(_SPG_\Data + _SPG_\Info\Entry[i]\Pos, *SMem, Slen) ; Dann ganzen String
          ProcedureReturn i
        EndIf
      ElseIf DeepSearch And _SPG_\Info\Entry[i]\Size>Slen ; String in anderen Strings finden
        tpos = FindString(PeekS(_SPG_\Data + _SPG_\Info\Entry[i]\Pos, _SPG_\Info\Entry[i]\Size), String, 1)-1
        If tpos<>-1
          _SPG_\Count + 1
          If _SPG_\Count> = _SPG_\ArraySize
            _SPG_\ArraySize + #ArraySize
            _SPG_\Info = Mem_ReAlloc(_SPG_\Info, _SPG_\ArraySize*SizeOf(_SP_Entry))
          EndIf
          _SPG_\Info\Entry[_SPG_\Count]\Pos = _SPG_\Info\Entry[i]\Pos + tpos
          _SPG_\Info\Entry[_SPG_\Count]\Size = Slen
          ProcedureReturn _SPG_\Count
        EndIf
      EndIf
    Next
  EndIf
  _SPG_\Count + 1
  If Slen
    If _SPG_\Count> = _SPG_\ArraySize ; Index vergrößern
      _SPG_\ArraySize + #ArraySize
      _SPG_\Info = Mem_ReAlloc(_SPG_\Info, _SPG_\ArraySize*SizeOf(_SP_Entry))
    EndIf
    While _SPG_\PoolSize<_SPG_\Size + Slen + SizeOf(CHARACTER) ; Pool vergrößern
      _SPG_\PoolSize + #PoolSize
      _SPG_\Data = Mem_ReAlloc(_SPG_\Data, _SPG_\PoolSize)
    Wend
    PokeS(_SPG_\Data + _SPG_\Size, String)
    _SPG_\Info\Entry[_SPG_\Count]\Pos = _SPG_\Size
    _SPG_\Info\Entry[_SPG_\Count]\Size = Slen
    _SPG_\Size + Slen
    ProcedureReturn _SPG_\Count
  Else
    ProcedureReturn 0
  EndIf
EndProcedure
Auf Speed optimierte Version meines Stringpools. Ascii only, beim auslesen darf kein ungültiger Index übergeben werden, sonst IMA.