Stringbuilder

Community Forums/Showcase/Stringbuilder

Sweenie(Posted 2005) [#1]
Here is some code for concatenating strings using a stringbuilder instead of directly adding strings together.

[Edit]
Modified the increasefactor to allow smaller increases of the array.



'String Concatenation test...
'Pretty memoryconsumptive but WAY faster than OrgString = OrgString + NewString
'The memoryconsumption Vs speed can be balanced with the IncreaseFactor, but depends alot on your computer-specs.

Type StringBuilder

 Field Initsize:Int 
 Field Currentsize:Int
 Field Stringsize:Int
 Field StrArray:Byte[]
 Const IncreaseFactor:Float = 1.0 ' Increase the buffersize by 100 % (!!! never below or equal to 0 !!!)

 Method New()
  Initsize = 4096
  Currentsize = Initsize
  Stringsize = 0
  StrArray = New Byte[Initsize]
 End Method

 Method Append(txt:String)
   Local DstPtr:Byte Ptr
   Local SrcPtr:Byte Ptr

  If Stringsize + txt.length < Currentsize Then
   ' There is enough room, add the string to the stringbuilder
   DstPtr = Byte Ptr(StrArray)
   DstPtr :+ Stringsize	
   SrcPtr = Byte Ptr(txt)
   MemCopy (DstPtr,SrcPtr,txt.length)

   Stringsize :+ txt.length
   FlushMem()
  Else
   ' There is not enough room left, resize the array to double size
'TODO: Calculate the needed size at once to reduce several resizes of the array to just one if the inputstring is larger than the increased size.
   While Stringsize + txt.length > Currentsize 
    StrArray = StrArray[..Currentsize+(Currentsize*IncreaseFactor)] ' Resize the current array
    CurrentSize :+ Currentsize*IncreaseFactor
   Wend

   DstPtr = Byte Ptr(StrArray)
   DstPtr :+ Stringsize	
   SrcPtr = Byte Ptr(txt)
   MemCopy (DstPtr,SrcPtr,txt.length)

   Stringsize :+ txt.length
   FlushMem()
  EndIf
 End Method

 Method GetString:String()
  Return String.FromCString(Byte Ptr(StrArray))
 End Method

End Type


' String Concatenation using a Stringbuilder
Local StrBuilder:StringBuilder = New StringBuilder
Local FinalStr:String 
Local Loops:Int = 10000
Local i:Int
Local StartTime:Int
Local EndTime:Int

StartTime = MilliSecs()
For i = 1 To Loops
 StrBuilder.Append("Test " + Chr(13) + Chr(10))
Next
EndTime = MilliSecs()

FinalStr = StrBuilder.GetString()

Print "StringLength: "+String.FromInt(FinalStr.Length)
Print "Elapsed time: "+String.FromInt(EndTime-StartTime) + " ms"
Print "The StringBuilder buffer increased to a size of "+String.FromInt(StrBuilder.CurrentSize) + " bytes"

'file = WriteFile("C:\output.txt")
'WriteString file,FinalStr
'CloseStream file 

End



Then run the code below and compare the speed...
'  String concatenation using the "standard" method
Local FinalStr:String 
Local Loops:Int = 10000
Local i:Int
Local StartTime:Int
Local EndTime:Int

StartTime = MilliSecs()
For i = 1 To Loops
 FinalStr :+ "Test " + Chr(13) + Chr(10)
 FlushMem ' If you remove this your computers memory will be sucked dry in a few seconds...
Next
EndTime = MilliSecs()

Print "StringLength: "+String.FromInt(FinalStr.Length)
Print "Elapsed time: "+String.FromInt(EndTime-StartTime) + " ms"



Feel free to use it and modify it as you wish.
Suggestions and improvements are also welcome.