Mega Code Archive

 
Categories / Delphi / Strings
 

Delphi Implementation of C# StringBuilder (Fast String Concat)

Title: Delphi Implementation of C# StringBuilder (Fast String Concat) Question: Those of you who use C# know that to concatenate a large number of strings takes forever unless you use the StringBulder class. This is a Delphi implementation of such and huge increase in performance can be gained by using it. On my machine the following timings were experienced. procedure TForm1.Button1Click(Sender: TObject); var oBuilder : TStringBuilder; sString : string; i,iCount : integer; begin iCount := 10000; oBuilder := TStringBuilder.Create; for i := 1 to iCount do oBuilder.Append(IntToStr(i)); sString := oBuilder.AsString; // 6 Milliseconds sString := ''; for i := 1 to iCount do sString := sString + IntToStr(i); // 404 Milliseconds FreeAndNil(oBuilder); end; As can be seen by the above the difference is dramatic as the normal Delphi concatenation must constantly increase and move the string memory around. One might be tempted to use a TStringList.Add(string) and then use the TStringList.Text property, but the Carriage Return and Line Feed pairs appear in the Text. Answer: unit MahStringBuilder; interface // ========================================================================== // Implementation of C# StringBuilder class. // Mike Heydon 2008 // // Allow fast string concatenation without excessive memory rellocs. // Default Initial Buffer Size is 4K and doubles for each reallocation, but // can be set to a higher or lower value for performance if the size of // the resulting string is predicatble. // // Example // // procedure TForm1.Button1Click(Sender: TObject); // var oString : TStringBuilder; // i : integer; // begin // oString := TStringBuilder.Create; // for i := 1 to 100 do oString.Append(IntToStr(i) + ' '); // oString.Append('100 Numbers '); // Memo1.Lines.Add(oString.AsString); // oString.Append('Some More ExtraText'); // Memo1.Lines.Add(oString.AsString); // FreeAndNil(oString); // end; // // ========================================================================== type { TStringBuilder Class } TStringBuilder = class(TObject) private FBuffMax, FBuffSize,FIndex : integer; FBuffer : PChar; procedure _ExpandBuffer; function GetFString : string; procedure SetFString(const AString : string); public constructor Create(ABufferSize : integer = 4096); destructor Destroy; override; procedure Append(const AString : string); procedure Clear; property AsString : string read GetFString write SetFString; end; // -------------------------------------------------------------------------- implementation procedure TStringBuilder._ExpandBuffer; begin FBuffSize := FBuffSize shl 1; FBuffMax := FBuffSize - 1; ReallocMem(FBuffer,FBuffSize); end; constructor TStringBuilder.Create(ABufferSize : integer = 4096); begin inherited Create; if ABufferSize FBuffSize := 1024 else FBuffSize := ABufferSize; GetMem(FBuffer,FBuffSize); FBuffMax := FBuffSize - 1; FIndex := 0; end; destructor TStringBuilder.Destroy; begin FreeMem(FBuffer); inherited Destroy; end; procedure TStringBuilder.Append(const AString : string); var iLen : integer; begin iLen := length(AString); if iLen + FIndex FBuffMax then _ExpandBuffer; move(AString[1],FBuffer[FIndex],iLen); inc(FIndex,iLen); end; function TStringBuilder.GetFString : string; begin FBuffer[FIndex] := #0; Result := FBuffer; end; procedure TStringBuilder.SetFString(const AString : string); begin self.Clear; self.Append(AString); end; procedure TStringBuilder.Clear; begin FIndex := 0; end; end.