Stringbuilder

Miscellaneous Forums/Blitz Showcase/Stringbuilder

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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.