mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 22:49:17 +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
|
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)
|
12/Mar/04 Lazarus version (Sergey Smirnov AKA SSY)
|
||||||
Locate and CheckString functions are removed because of Variant data type.
|
Locate and CheckString functions are removed because of Variant data type.
|
||||||
Many things are changed for FPC/Lazarus compatibility.
|
Many things are changed for FPC/Lazarus compatibility.
|
||||||
@ -251,6 +256,8 @@ type
|
|||||||
private
|
private
|
||||||
FDelimiter : Char;
|
FDelimiter : Char;
|
||||||
FFirstLineAsSchema : Boolean;
|
FFirstLineAsSchema : Boolean;
|
||||||
|
FFMultiLine :Boolean;
|
||||||
|
procedure SetMultiLine(const Value: Boolean);
|
||||||
procedure SetFirstLineAsSchema(Value : Boolean);
|
procedure SetFirstLineAsSchema(Value : Boolean);
|
||||||
procedure SetDelimiter(Value : Char);
|
procedure SetDelimiter(Value : Char);
|
||||||
protected
|
protected
|
||||||
@ -262,6 +269,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
published
|
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 Delimiter: Char read FDelimiter write SetDelimiter;
|
||||||
property FirstLineAsSchema: Boolean read FFirstLineAsSchema write SetFirstLineAsSchema;
|
property FirstLineAsSchema: Boolean read FFirstLineAsSchema write SetFirstLineAsSchema;
|
||||||
end;
|
end;
|
||||||
@ -843,6 +851,7 @@ begin
|
|||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
FDelimiter := ',';
|
FDelimiter := ',';
|
||||||
FFirstLineAsSchema := FALSE;
|
FFirstLineAsSchema := FALSE;
|
||||||
|
FFMultiLine :=False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSdfDataSet.InternalInitFieldDefs;
|
procedure TSdfDataSet.InternalInitFieldDefs;
|
||||||
@ -945,7 +954,21 @@ begin
|
|||||||
begin
|
begin
|
||||||
|
|
||||||
while Boolean(Byte(pStrEnd[0])) and (pStrEnd[0] in [#1..' ']) do
|
while Boolean(Byte(pStrEnd[0])) and (pStrEnd[0] in [#1..' ']) do
|
||||||
|
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);
|
Inc(pStrEnd);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if not Boolean(Byte(pStrEnd[0])) then
|
if not Boolean(Byte(pStrEnd[0])) then
|
||||||
break;
|
break;
|
||||||
@ -954,10 +977,22 @@ begin
|
|||||||
|
|
||||||
if (pStr[0] = '"') then
|
if (pStr[0] = '"') then
|
||||||
begin
|
begin
|
||||||
|
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
|
repeat
|
||||||
Inc(pStrEnd);
|
Inc(pStrEnd);
|
||||||
until not Boolean(Byte(pStrEnd[0])) or
|
until not Boolean(Byte(pStrEnd[0])) or
|
||||||
((pStrEnd[0] = '"') and ((pStrEnd + 1)[0] in [Delimiter,CR,LF, #0]));
|
((pStrEnd[0] = '"') and ((pStrEnd + 1)[0] in [Delimiter,CR,LF, #0]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
if (pStrEnd[0] = '"') then
|
if (pStrEnd[0] = '"') then
|
||||||
Inc(pStr);
|
Inc(pStr);
|
||||||
@ -985,18 +1020,36 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TSdfDataSet.BufToStore(Buffer: PChar): String;
|
function TSdfDataSet.BufToStore(Buffer: PChar): String;
|
||||||
|
const
|
||||||
|
QuoteDelimiter='"';
|
||||||
var
|
var
|
||||||
Str : String;
|
Str : String;
|
||||||
p, i : Integer;
|
p, i : Integer;
|
||||||
|
QuoteMe: boolean;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
p := 1;
|
p := 1;
|
||||||
|
QuoteMe:=false;
|
||||||
for i := 0 to FieldDefs.Count - 1 do
|
for i := 0 to FieldDefs.Count - 1 do
|
||||||
begin
|
begin
|
||||||
Str := Trim(Copy(Buffer, p, FieldDefs[i].Size));
|
Str := Trim(Copy(Buffer, p, FieldDefs[i].Size));
|
||||||
Inc(p, FieldDefs[i].Size);
|
Inc(p, FieldDefs[i].Size);
|
||||||
if (StrScan(PChar(Str), FDelimiter) <> nil) then
|
if FFMultiLine=true then
|
||||||
Str := '"' + Str + '"';
|
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;
|
Result := Result + Str + FDelimiter;
|
||||||
end;
|
end;
|
||||||
p := Length(Result);
|
p := Length(Result);
|
||||||
@ -1020,6 +1073,12 @@ begin
|
|||||||
FDataOffset:=Ord(FFirstLineAsSchema);
|
FDataOffset:=Ord(FFirstLineAsSchema);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSdfDataSet.SetMultiLine(const Value: Boolean);
|
||||||
|
begin
|
||||||
|
FFMultiLine:=Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// This procedure is used to register this component on the component palette
|
// This procedure is used to register this component on the component palette
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user