csvdocument: performance improvements for QuoteCSVString

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1625 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
vvzh
2011-05-10 11:48:22 +00:00
parent c9863cb2e6
commit ef62720766

View File

@ -53,11 +53,18 @@ type
TCSVChar = Char; TCSVChar = Char;
TCSVHandler = class(TObject) TCSVHandler = class(TObject)
private
procedure SetDelimiter(const AValue: TCSVChar);
procedure SetQuoteChar(const AValue: TCSVChar);
procedure UpdateCachedChars;
protected protected
// special chars // special chars
FDelimiter: TCSVChar; FDelimiter: TCSVChar;
FQuoteChar: TCSVChar; FQuoteChar: TCSVChar;
FLineEnding: string; FLineEnding: String;
// cached values to speed up special chars operations
FSpecialChars: TSysCharSet;
FDoubleQuote: String;
// parser settings // parser settings
FIgnoreOuterWhitespace: Boolean; FIgnoreOuterWhitespace: Boolean;
// builder settings // builder settings
@ -67,8 +74,8 @@ type
public public
constructor Create; constructor Create;
procedure AssignCSVProperties(ASource: TCSVHandler); procedure AssignCSVProperties(ASource: TCSVHandler);
property Delimiter: TCSVChar read FDelimiter write FDelimiter; property Delimiter: TCSVChar read FDelimiter write SetDelimiter;
property QuoteChar: TCSVChar read FQuoteChar write FQuoteChar; property QuoteChar: TCSVChar read FQuoteChar write SetQuoteChar;
property LineEnding: String read FLineEnding write FLineEnding; property LineEnding: String read FLineEnding write FLineEnding;
property IgnoreOuterWhitespace: Boolean read FIgnoreOuterWhitespace write FIgnoreOuterWhitespace; property IgnoreOuterWhitespace: Boolean read FIgnoreOuterWhitespace write FIgnoreOuterWhitespace;
property QuoteOuterWhitespace: Boolean read FQuoteOuterWhitespace write FQuoteOuterWhitespace; property QuoteOuterWhitespace: Boolean read FQuoteOuterWhitespace write FQuoteOuterWhitespace;
@ -252,6 +259,30 @@ end;
{ TCSVHandler } { TCSVHandler }
procedure TCSVHandler.SetDelimiter(const AValue: TCSVChar);
begin
if FDelimiter <> AValue then
begin
FDelimiter := AValue;
UpdateCachedChars;
end;
end;
procedure TCSVHandler.SetQuoteChar(const AValue: TCSVChar);
begin
if FQuoteChar <> AValue then
begin
FQuoteChar := AValue;
UpdateCachedChars;
end;
end;
procedure TCSVHandler.UpdateCachedChars;
begin
FDoubleQuote := FQuoteChar + FQuoteChar;
FSpecialChars := [CR, LF, FDelimiter, FQuoteChar];
end;
constructor TCSVHandler.Create; constructor TCSVHandler.Create;
begin begin
inherited Create; inherited Create;
@ -261,6 +292,7 @@ begin
FIgnoreOuterWhitespace := False; FIgnoreOuterWhitespace := False;
FQuoteOuterWhitespace := True; FQuoteOuterWhitespace := True;
FEqualColCountPerRow := True; FEqualColCountPerRow := True;
UpdateCachedChars;
end; end;
procedure TCSVHandler.AssignCSVProperties(ASource: TCSVHandler); procedure TCSVHandler.AssignCSVProperties(ASource: TCSVHandler);
@ -271,6 +303,7 @@ begin
FIgnoreOuterWhitespace := ASource.FIgnoreOuterWhitespace; FIgnoreOuterWhitespace := ASource.FIgnoreOuterWhitespace;
FQuoteOuterWhitespace := ASource.FQuoteOuterWhitespace; FQuoteOuterWhitespace := ASource.FQuoteOuterWhitespace;
FEqualColCountPerRow := ASource.FEqualColCountPerRow; FEqualColCountPerRow := ASource.FEqualColCountPerRow;
UpdateCachedChars;
end; end;
{ TCSVParser } { TCSVParser }
@ -462,7 +495,6 @@ function TCSVBuilder.QuoteCSVString(const AValue: String): String;
var var
I: Integer; I: Integer;
ValueLen: Integer; ValueLen: Integer;
SpecialChars: TSysCharSet;
NeedQuotation: Boolean; NeedQuotation: Boolean;
begin begin
ValueLen := Length(AValue); ValueLen := Length(AValue);
@ -470,11 +502,10 @@ begin
NeedQuotation := (AValue <> '') and FQuoteOuterWhitespace NeedQuotation := (AValue <> '') and FQuoteOuterWhitespace
and ((AValue[1] in WhitespaceChars) or (AValue[ValueLen] in WhitespaceChars)); and ((AValue[1] in WhitespaceChars) or (AValue[ValueLen] in WhitespaceChars));
SpecialChars := [CR, LF, FDelimiter, FQuoteChar];
if not NeedQuotation then if not NeedQuotation then
for I := 1 to ValueLen do for I := 1 to ValueLen do
begin begin
if AValue[I] in SpecialChars then if AValue[I] in FSpecialChars then
begin begin
NeedQuotation := True; NeedQuotation := True;
Break; Break;
@ -484,9 +515,9 @@ begin
if NeedQuotation then if NeedQuotation then
begin begin
// double existing quotes // double existing quotes
Result := StringReplace(AValue, FQuoteChar, Result := FDoubleQuote;
FQuoteChar + FQuoteChar, [rfReplaceAll]); Insert(StringReplace(AValue, FQuoteChar, FDoubleQuote, [rfReplaceAll]),
Result := FQuoteChar + Result + FQuoteChar; Result, 2);
end else end else
Result := AValue; Result := AValue;
end; end;