StringPool

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag 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.
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Antworten