mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 18:29:27 +02:00
* Patch from Reinier Olislaegers to handle multiline data
git-svn-id: trunk@18027 -
This commit is contained in:
parent
f0bbea9319
commit
888ea8121c
@ -13,6 +13,11 @@ unit SdfData;
|
||||
---------------
|
||||
Modifications
|
||||
---------------
|
||||
14/Jul/11 BigChimp:
|
||||
Added AllowMultiLine property so user can use fields that have line endings
|
||||
(Carriage Return and/or Line Feed) embedded in their fields (fields need to be
|
||||
quoted). Enabled by default; will break compatibility with earlier versions of
|
||||
SdfData, but using multilines would have resulted in corrupted import anyway.
|
||||
12/Mar/04 Lazarus version (Sergey Smirnov AKA SSY)
|
||||
Locate and CheckString functions are removed because of Variant data type.
|
||||
Many things are changed for FPC/Lazarus compatibility.
|
||||
@ -251,6 +256,8 @@ type
|
||||
private
|
||||
FDelimiter : Char;
|
||||
FFirstLineAsSchema : Boolean;
|
||||
FFMultiLine :Boolean;
|
||||
procedure SetMultiLine(const Value: Boolean);
|
||||
procedure SetFirstLineAsSchema(Value : Boolean);
|
||||
procedure SetDelimiter(Value : Char);
|
||||
protected
|
||||
@ -262,6 +269,7 @@ type
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
published
|
||||
property AllowMultiLine: Boolean read FFMultiLine write SetMultiLine default True; //Whether or not to allow fields containing CR and/or LF
|
||||
property Delimiter: Char read FDelimiter write SetDelimiter;
|
||||
property FirstLineAsSchema: Boolean read FFirstLineAsSchema write SetFirstLineAsSchema;
|
||||
end;
|
||||
@ -843,6 +851,7 @@ begin
|
||||
inherited Create(AOwner);
|
||||
FDelimiter := ',';
|
||||
FFirstLineAsSchema := FALSE;
|
||||
FFMultiLine :=False;
|
||||
end;
|
||||
|
||||
procedure TSdfDataSet.InternalInitFieldDefs;
|
||||
@ -945,7 +954,21 @@ begin
|
||||
begin
|
||||
|
||||
while Boolean(Byte(pStrEnd[0])) and (pStrEnd[0] in [#1..' ']) do
|
||||
Inc(pStrEnd);
|
||||
begin
|
||||
if FFMultiLine=true then
|
||||
begin
|
||||
if ((pStrEnd[0]=CR) or (pStrEnd[0]=LF)) then
|
||||
begin
|
||||
//view this as text, not control characters, so do nothing
|
||||
//todo: check if this is really necessary, probably revert
|
||||
//to original code as quoted case is handled below
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Inc(pStrEnd);
|
||||
end;
|
||||
end;
|
||||
|
||||
if not Boolean(Byte(pStrEnd[0])) then
|
||||
break;
|
||||
@ -954,10 +977,22 @@ begin
|
||||
|
||||
if (pStr[0] = '"') then
|
||||
begin
|
||||
repeat
|
||||
Inc(pStrEnd);
|
||||
until not Boolean(Byte(pStrEnd[0])) or
|
||||
((pStrEnd[0] = '"') and ((pStrEnd + 1)[0] in [Delimiter,CR,LF, #0]));
|
||||
if FFMultiLine=true then
|
||||
begin
|
||||
repeat
|
||||
Inc(pStrEnd);
|
||||
until not Boolean(Byte(pStrEnd[0])) or
|
||||
((pStrEnd[0] = '"') and ((pStrEnd + 1)[0] in [Delimiter,#0]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
// No multiline, so treat cr/lf as end of record
|
||||
repeat
|
||||
Inc(pStrEnd);
|
||||
until not Boolean(Byte(pStrEnd[0])) or
|
||||
((pStrEnd[0] = '"') and ((pStrEnd + 1)[0] in [Delimiter,CR,LF, #0]));
|
||||
end;
|
||||
|
||||
|
||||
if (pStrEnd[0] = '"') then
|
||||
Inc(pStr);
|
||||
@ -985,18 +1020,36 @@ begin
|
||||
end;
|
||||
|
||||
function TSdfDataSet.BufToStore(Buffer: PChar): String;
|
||||
const
|
||||
QuoteDelimiter='"';
|
||||
var
|
||||
Str : String;
|
||||
p, i : Integer;
|
||||
QuoteMe: boolean;
|
||||
begin
|
||||
Result := '';
|
||||
p := 1;
|
||||
QuoteMe:=false;
|
||||
for i := 0 to FieldDefs.Count - 1 do
|
||||
begin
|
||||
Str := Trim(Copy(Buffer, p, FieldDefs[i].Size));
|
||||
Inc(p, FieldDefs[i].Size);
|
||||
if (StrScan(PChar(Str), FDelimiter) <> nil) then
|
||||
Str := '"' + Str + '"';
|
||||
if FFMultiLine=true then
|
||||
begin
|
||||
// If multiline enabled, quote whenever we find carriage return or linefeed
|
||||
if ((QuoteMe=False) and (StrScan(PChar(Str), #10) <> nil)) then QuoteMe:=true;
|
||||
if ((QuoteMe=False) and (StrScan(PChar(Str), #13) <> nil)) then QuoteMe:=true;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// If we don't allow multiline, remove all CR and LF because they mess with the record ends:
|
||||
StringReplace(Str, #10, '', [rfReplaceAll]);
|
||||
StringReplace(Str, #13, '', [rfReplaceAll]);
|
||||
end;
|
||||
// Check for any delimiters occurring in field text
|
||||
if ((QuoteMe=False) and (StrScan(PChar(Str), FDelimiter) <> nil)) then QuoteMe:=true;
|
||||
if (QuoteMe=True) then
|
||||
Str := QuoteDelimiter + Str + QuoteDelimiter;
|
||||
Result := Result + Str + FDelimiter;
|
||||
end;
|
||||
p := Length(Result);
|
||||
@ -1020,6 +1073,12 @@ begin
|
||||
FDataOffset:=Ord(FFirstLineAsSchema);
|
||||
end;
|
||||
|
||||
procedure TSdfDataSet.SetMultiLine(const Value: Boolean);
|
||||
begin
|
||||
FFMultiLine:=Value;
|
||||
end;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This procedure is used to register this component on the component palette
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user