LCL: fixed FileIsText to skip BOMs

git-svn-id: trunk@27523 -
This commit is contained in:
mattias 2010-09-29 10:01:59 +00:00
parent 5ad19b1d4b
commit 250603ab78
3 changed files with 61 additions and 23 deletions

View File

@ -86,6 +86,7 @@ function FileIsExecutable(const AFilename: string): boolean;
function FileIsReadable(const AFilename: string): boolean; function FileIsReadable(const AFilename: string): boolean;
function FileIsWritable(const AFilename: string): boolean; function FileIsWritable(const AFilename: string): boolean;
function FileIsText(const AFilename: string): boolean; function FileIsText(const AFilename: string): boolean;
function FileIsText(const AFilename: string; out FileReadable: boolean): boolean;
function FilenameIsTrimmed(const TheFilename: string): boolean; function FilenameIsTrimmed(const TheFilename: string): boolean;
function FilenameIsTrimmed(StartPos: PChar; NameLen: integer): boolean; function FilenameIsTrimmed(StartPos: PChar; NameLen: integer): boolean;
function TrimFilename(const AFilename: string): string; function TrimFilename(const AFilename: string): string;
@ -1092,32 +1093,54 @@ begin
end; end;
function FileIsText(const AFilename: string): boolean; function FileIsText(const AFilename: string): boolean;
var fs: TFileStream; var
FileReadable: Boolean;
begin
Result:=FileIsText(AFilename,FileReadable);
if FileReadable then ;
end;
function FileIsText(const AFilename: string; out FileReadable: boolean): boolean;
var
fs: TFileStream;
Buf: string; Buf: string;
Len, i: integer; Len: integer;
NewLine: boolean; NewLine: boolean;
Size: Int64; p: PChar;
begin begin
Result:=false; Result:=false;
FileReadable:=true;
try try
fs := TFileStream.Create(UTF8ToSys(AFilename), fmOpenRead or fmShareDenyNone); fs := TFileStream.Create(UTF8ToSys(AFilename), fmOpenRead or fmShareDenyNone);
try try
// read the first 1024 bytes // read the first 1024 bytes
Len:=1024; Len:=1024;
Size:=fs.Size; SetLength(Buf,1024+1);
if Len>Size then Len:=integer(Size); Len:=fs.Read(Buf[1],length(Buf));
if Len>0 then begin if Len>0 then begin
SetLength(Buf,Len); Buf[Len+1]:=#0;
fs.Read(Buf[1],length(Buf)); p:=PChar(Buf);
if (p[0]=#$EF) and (p[1]=#$BB) and (p[2]=#$BF) then begin
// UTF-8 BOM (Byte Order Mark)
inc(p,3);
end else if (p[0]=#$FF) and (p[1]=#$FE) then begin
// ucs-2le BOM FF FE
inc(p,2);
end else if (p[0]=#$FE) and (p[1]=#$FF) then begin
// ucs-2be BOM FE FF
inc(p,2);
end;
NewLine:=false; NewLine:=false;
for i:=1 to length(Buf) do begin while true do begin
case Buf[i] of case p^ of
#0: if p-PChar(Buf)>=Len then break;
// #10,#13: new line // #10,#13: new line
// #12: form feed // #12: form feed
// #26: end of file // #26: end of file
#0..#8,#11,#14..#25,#27..#31: exit; #1..#8,#11,#14..#25,#27..#31: exit;
#10,#13: NewLine:=true; #10,#13: NewLine:=true;
end; end;
inc(p);
end; end;
if NewLine or (Len<1024) then if NewLine or (Len<1024) then
Result:=true; Result:=true;
@ -1127,6 +1150,9 @@ begin
fs.Free; fs.Free;
end; end;
except except
on E: Exception do begin
FileReadable:=false;
end;
end; end;
end; end;

View File

@ -558,9 +558,9 @@ function FileIsText(const AFilename: string; out FileReadable: boolean): boolean
var var
fs: TFileStream; fs: TFileStream;
Buf: string; Buf: string;
Len, i: integer; Len: integer;
NewLine: boolean; NewLine: boolean;
Size: Int64; p: PChar;
begin begin
Result:=false; Result:=false;
FileReadable:=true; FileReadable:=true;
@ -569,20 +569,32 @@ begin
try try
// read the first 1024 bytes // read the first 1024 bytes
Len:=1024; Len:=1024;
Size:=fs.Size; SetLength(Buf,1024+1);
if Len>Size then Len:=integer(Size); Len:=fs.Read(Buf[1],length(Buf));
if Len>0 then begin if Len>0 then begin
SetLength(Buf,Len); Buf[Len+1]:=#0;
fs.Read(Buf[1],length(Buf)); p:=PChar(Buf);
if (p[0]=#$EF) and (p[1]=#$BB) and (p[2]=#$BF) then begin
// UTF-8 BOM (Byte Order Mark)
inc(p,3);
end else if (p[0]=#$FF) and (p[1]=#$FE) then begin
// ucs-2le BOM FF FE
inc(p,2);
end else if (p[0]=#$FE) and (p[1]=#$FF) then begin
// ucs-2be BOM FE FF
inc(p,2);
end;
NewLine:=false; NewLine:=false;
for i:=1 to length(Buf) do begin while true do begin
case Buf[i] of case p^ of
#0: if p-PChar(Buf)>=Len then break;
// #10,#13: new line // #10,#13: new line
// #12: form feed // #12: form feed
// #26: end of file // #26: end of file
#0..#8,#11,#14..#25,#27..#31: exit; #1..#8,#11,#14..#25,#27..#31: exit;
#10,#13: NewLine:=true; #10,#13: NewLine:=true;
end; end;
inc(p);
end; end;
if NewLine or (Len<1024) then if NewLine or (Len<1024) then
Result:=true; Result:=true;

View File

@ -5841,19 +5841,19 @@ begin
exit; exit;
end; end;
// try BOM (Byte Order Mark) // try UTF-8 BOM (Byte Order Mark)
if CompareI(@s[1],#$EF#$BB#$BF,3) then begin if CompareI(@s[1],#$EF#$BB#$BF,3) then begin
Result:=EncodingUTF8BOM; Result:=EncodingUTF8BOM;
exit; exit;
end; end;
// try BOM FF FE for ucs-2le // try ucs-2le BOM FF FE
if (length(s)>=2) and (s[1]=#$FF) and (s[2]=#$FE) then begin if (length(s)>=2) and (s[1]=#$FF) and (s[2]=#$FE) then begin
Result:=EncodingUCS2LE; Result:=EncodingUCS2LE;
exit; exit;
end; end;
// try BOM FE FF for ucs-2be // try ucs-2be BOM FE FF
if (length(s)>=2) and (s[1]=#$FE) and (s[2]=#$FF) then begin if (length(s)>=2) and (s[1]=#$FE) and (s[2]=#$FF) then begin
Result:=EncodingUCS2BE; Result:=EncodingUCS2BE;
exit; exit;