summaryrefslogtreecommitdiff
path: root/packages/fcl-base/src/csvreadwrite.pp
diff options
context:
space:
mode:
Diffstat (limited to 'packages/fcl-base/src/csvreadwrite.pp')
-rw-r--r--packages/fcl-base/src/csvreadwrite.pp31
1 files changed, 31 insertions, 0 deletions
diff --git a/packages/fcl-base/src/csvreadwrite.pp b/packages/fcl-base/src/csvreadwrite.pp
index 4c68f151ff..32f195d411 100644
--- a/packages/fcl-base/src/csvreadwrite.pp
+++ b/packages/fcl-base/src/csvreadwrite.pp
@@ -92,12 +92,16 @@ Type
{ TCSVParser }
+ TCSVByteOrderMark = (bomNone, bomUTF8, bomUTF16LE, bomUTF16BE);
+
TCSVParser = class(TCSVHandler)
private
FFreeStream: Boolean;
// fields
FSourceStream: TStream;
FStrStreamWrapper: TStringStream;
+ FBOM: TCSVByteOrderMark;
+ FDetectBOM: Boolean;
// parser state
EndOfFile: Boolean;
EndOfLine: Boolean;
@@ -140,6 +144,10 @@ Type
property MaxColCount: Integer read FMaxColCount;
// Does the parser own the stream ? If true, a previous stream is freed when set or when parser is destroyed.
Property FreeStream : Boolean Read FFreeStream Write FFreeStream;
+ // Return BOM found in file
+ property BOM: TCSVByteOrderMark read FBOM;
+ // Detect whether a BOM marker is present. If set to True, then BOM can be used to see what BOM marker there was.
+ property DetectBOM: Boolean read FDetectBOM write FDetectBOM default false;
end;
// Sequential output to CSV stream
@@ -441,9 +449,32 @@ begin
end;
procedure TCSVParser.ResetParser;
+var
+ b: packed array[0..2] of byte;
+ n: Integer;
begin
ClearOutput;
FSourceStream.Seek(0, soFromBeginning);
+ if FDetectBOM then
+ begin
+ FSourceStream.ReadBuffer(b[0], 3);
+ if (b[0] = $EF) and (b[1] = $BB) and (b[2] = $BF) then begin
+ FBOM := bomUTF8;
+ n := 3;
+ end else
+ if (b[0] = $FE) and (b[1] = $FF) then begin
+ FBOM := bomUTF16BE;
+ n := 2;
+ end else
+ if (b[0] = $FF) and (b[1] = $FE) then begin
+ FBOM := bomUTF16LE;
+ n := 2;
+ end else begin
+ FBOM := bomNone;
+ n := 0;
+ end;
+ FSourceStream.Seek(n, soFromBeginning);
+ end;
EndOfFile := False;
NextChar;
end;