Since I somehow "hijacked" the thread from mk-soft (my apologize), I've created a new thread now.
Code: Select all
;- Top
; -----------------------------------------------------------------------------
; Name : StringBuilder Interface
; Description : Fast String concatenation
; Author : HeX0R
; Date : 2023-02-16
; Original : https://www.purebasic.fr/english/viewtopic.php?p=558277#p558277
; OS : Cross-platform
; Forum : https://www.purebasic.fr/english/viewtopic.php?p=595972#p595972
;
; AND...ashes on my head!!:
; Base idea from mk-soft
; : https://www.purebasic.fr/english/viewtopic.php?t=75758
; -----------------------------------------------------------------------------
Structure struc_StringBuilder
VTable.i
*Address
*Pointer
MemSize.i
PacketSize.i
Length.i
EndStructure
Interface IF_StringBuilder
Add(String.s)
GetString.s()
Reset(KeepMemory = #False)
Release()
EndInterface
Procedure __SB_Reset(*THIS.struc_StringBuilder, KeepMemory = #False)
;Reset back to initial values, for reusing the interface
If KeepMemory = #False
If *THIS\MemSize > *THIS\PacketSize
*THIS\Address = ReAllocateMemory(*THIS\Address, *THIS\PacketSize, #PB_Memory_NoClear)
EndIf
*THIS\MemSize = *THIS\PacketSize
EndIf
*THIS\Pointer = *THIS\Address
*THIS\Length = 0
EndProcedure
Procedure __SB_Add(*THIS.struc_StringBuilder, String.s)
Protected Len, *Add, Result = #True
Len = StringByteLength(String)
If Len + *THIS\Length + 2 > *THIS\MemSize
*THIS\MemSize = *THIS\Length + Len + 2 + *THIS\PacketSize
*Add = ReAllocateMemory(*THIS\Address, *THIS\MemSize, #PB_Memory_NoClear)
If *Add
If *Add <> *THIS\Address
*THIS\Pointer = *THIS\Pointer - *THIS\Address + *Add
EndIf
*THIS\Address = *Add
Else
;not enough memory?
ProcedureReturn #False
EndIf
EndIf
CopyMemoryString(@String, @*THIS\Pointer)
*THIS\Length + Len
ProcedureReturn Result
EndProcedure
Procedure.s __SB_GetString(*THIS.struc_StringBuilder)
ProcedureReturn PeekS(*THIS\Address, *THIS\Length / SizeOf(Character))
EndProcedure
Procedure __SB_Release(*THIS.struc_StringBuilder)
If *THIS\Address
FreeMemory(*THIS\Address)
EndIf
FreeMemory(*THIS)
EndProcedure
Procedure New_StringBuilder(PacketSize.i = 65536)
Protected *THIS.struc_StringBuilder, *Buffer
*THIS = AllocateMemory(SizeOf(struc_StringBuilder))
*THIS\VTable = ?_VT_STRINGBUILDER_
If *THIS = 0
ProcedureReturn #False
EndIf
*Buffer = AllocateMemory(PacketSize, #PB_Memory_NoClear)
If *Buffer
*THIS\Address = *Buffer
*THIS\Pointer = *Buffer
*THIS\PacketSize = PacketSize
*THIS\MemSize = PacketSize
ProcedureReturn *THIS
Else
FreeMemory(*THIS)
EndIf
ProcedureReturn #False
DataSection
_VT_STRINGBUILDER_:
Data.i @__SB_Add()
Data.i @__SB_GetString()
Data.i @__SB_Reset()
Data.i @__SB_Release()
EndDataSection
EndProcedure
;----------------------------EOF-------------------------
CompilerIf #PB_Compiler_IsMainFile
Define i, a$, b$, c$, s1, s2
Define SB.IF_StringBuilder
SB = New_StringBuilder()
a$ = "abcdefghijklmnopqrstuvwxyz" + #CRLF$
s1 = ElapsedMilliseconds()
For i = 1 To 10000
SB\Add(a$)
Next i
b$ = SB\GetString()
s1 = ElapsedMilliseconds() - s1
s2 = ElapsedMilliseconds()
For i = 1 To 10000
c$ + a$
Next i
s2 = ElapsedMilliseconds() - s2
MessageRequester("Info", ~"Stringbuilder: \t" + Str(s1) + ~"ms\nPB-Way: \t" + Str(s2) + "ms")
;Debug b$
SB\Release()
CompilerEndIf