diff options
-rw-r--r-- | unicode/src/base/UFilename.pas | 462 | ||||
-rw-r--r-- | unicode/src/base/UFilesystem.pas | 497 |
2 files changed, 959 insertions, 0 deletions
diff --git a/unicode/src/base/UFilename.pas b/unicode/src/base/UFilename.pas new file mode 100644 index 00000000..0cf12cc0 --- /dev/null +++ b/unicode/src/base/UFilename.pas @@ -0,0 +1,462 @@ +{* UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + *} + +unit UFilename; + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +interface + +uses + {$IFDEF MSWINDOWS} + TntClasses, + {$ENDIF} + Classes; + +type + TPathEncoding = ( + // pencLossless, + pencSystemUTF8, // use system encoding. Mac: UTF8, Linux: None, Win: UTF8 + // Note: + // - On windows, this format is lossless but is not + // supported direclty (UTF-16 only). + // - This is the best format to store filenames as there is + // no dataloss. + // - Do not use with glPrint() or other display functions + // as the resulting string is neither guaranteed to be + // UTF-8 nor ANSI. + + pencSystemANSI, // use system encoding. Mac: UTF8, Linux: None, Win: ANSI + // Note: + // - On windows, the ANSI format may break filenames + // that are not encoded in the active codepage. + // - Use only if there is no equivalent WideString + // filesystem function. + // - Do not use with glPrint() or other display functions + // as the resulting string is neither guaranteed to be + // UTF-8 nor ANSI. + + // pencPrintable, + pencUTF8 // tries to present the filename as UTF-8 encoded string + // that can be used for printing etc. + // Note: + // - Some characters whose encodings are unknown are + // represented either by '?' or as the representative of + // a different encoding. + // - On linux not all filenames can be represented + // correclty in UTF-8 as it does not have filename + // encodings (though most filenames are stored in UTF-8). + // - Never use the result to store filenames or open files + // as the filenames may break due to conversion. + ); + + IPath = interface; + + {$IFDEF MSWINDOWS} + TUniFileStream = class(TTntFileStream) + {$ELSE} + TUniFileStream = class(TFileStream) + {$ENDIF} + public + constructor Create(const FileName: IPath; Mode: Word); + end; + + TUniMemoryStream = class(TMemoryStream) + public + procedure LoadFromFile(const FileName: IPath); + procedure SaveToFile(const FileName: IPath); + end; + + IPath = interface + function ToString(Encoding: TPathEncoding = pencSystemUTF8): AnsiString; + function ToWideString(): WideString; + + function Adjust(): boolean; + + function Expand(): IPath; + {** File must be closed with FileClose(Handle) after usage } + function CreateFile(): integer; + function CreateDir(): boolean; + {** File must be closed with FileClose(Handle) after usage } + function Open(Mode: LongWord): integer; + {** Stream must be freed with TUniFileStream.Free after usage } + function OpenStream(Mode: Word): TUniFileStream; + function GetFileAge(): integer; overload; + function GetFileAge(out FileDateTime: TDateTime): boolean; overload; + function Exists(): boolean; + function IsFile(): boolean; + function IsDirectory(): boolean; + function GetAttr(): cardinal; + function SetAttr(Attr: Integer): boolean; + function IsReadOnly(): boolean; + function SetReadOnly(ReadOnly: boolean): boolean; + function ForceDirectories(): boolean; //- + function FileSearch(const DirList: IPath): IPath; //- + function Rename(const NewName: IPath): boolean; + function DeleteFile(): boolean; + function DeleteEmptyDir(): boolean; + function CopyFile(const Target: IPath; FailIfExists: boolean): boolean; + end; + +function Path(const Name: AnsiString; Encoding: TPathEncoding = pencSystemANSI): IPath; overload; +function Path(const Name: WideString): IPath; overload; +function Path(PathComponents: array of const): IPath; overload; + +implementation + +uses + UFilesystem, + SysUtils; + +type + TPathImpl = class(TInterfacedObject, IPath) + private + fName: AnsiString; + public + constructor Create(const Name: string); + destructor Destroy(); override; + + function ToString(Encoding: TPathEncoding = pencSystemANSI): AnsiString; + function ToWideString(): WideString; + + //function Append(const IPath): IPath; + function Adjust(): boolean; + {** + * Removes trailing path-delimiter and replaces path-delimiters with '/'. + *} + procedure Unify(); + function Expand(): IPath; + + (* + function IncludeTrailingPathDelimiter(): IPath; + function ExcludeTrailingPathDelimiter(): IPath; + function ChangeFileExt(const Extension: IPath): IPath; + function ExtractFilePath(): IPath; + function ExtractFileDir(): IPath; + function ExtractFileDrive(): IPath; + function ExtractFileName(): IPath; + function ExtractFileExt(): IPath; + function ExtractRelativePath(const BaseName: IPath): IPath; + *) + + function CreateFile(): integer; + function CreateDir(): boolean; + function Open(Mode: LongWord): integer; + function OpenStream(Mode: Word): TUniFileStream; + function GetFileAge(): integer; overload; + function GetFileAge(out FileDateTime: TDateTime): boolean; overload; + function Exists(): boolean; + function IsFile(): boolean; + function IsDirectory(): boolean; + function GetAttr(): cardinal; + function SetAttr(Attr: Integer): boolean; + function IsReadOnly(): boolean; + function SetReadOnly(ReadOnly: boolean): boolean; + function ForceDirectories(): boolean; + function FileSearch(const DirList: IPath): IPath; + function Rename(const NewName: IPath): boolean; + function DeleteFile(): boolean; + function DeleteEmptyDir(): boolean; + function CopyFile(const Target: IPath; FailIfExists: boolean): boolean; + end; + + IPathIterator = interface + function Next(): IPath; + end; + + TPathIteratorImpl = class(TInterfacedObject, IPathIterator) + private + fPath: IPath; + fPos: integer; + public + constructor Create(Path: IPath); + + function Next(): IPath; + end; + +function Path(const Name: AnsiString; Encoding: TPathEncoding): IPath; +begin + {$IFDEF MSWINDOWS} + case Encoding of + pencUTF8: + // TODO: Check if UTF8 + Result := TPathImpl.Create(Name); + pencSystemANSI: + Result := TPathImpl.Create(AnsiToUtf8(Name)); + else + raise Exception.Create('Unhandled encoding'); + end; + {$ELSE} + Result := TPathImpl.Create(Name); + {$ENDIF} +end; + +function Path(const Name: WideString): IPath; +begin + Result := TPathImpl.Create(UTF8Encode(Name)); +end; + +function Path(PathComponents: array of const): IPath; +var + CompIndex: integer; + Name: string; +begin + Name := ''; + for CompIndex := 0 to High(PathComponents) do + begin + with PathComponents[CompIndex] do + begin + case (VType) of + vtString: + Name := Name + VString^; + vtAnsiString: + Name := Name + AnsiString(VAnsiString); + vtWideString: + Name := Name + UTF8Encode(WideString(VWideString)); + vtObject: + raise Exception.Create('Unhandled Object type'); + else + raise Exception.Create('Unhandled Path type'); + end; + end; + Name := Name + PathDelim; + end; + Result := Path(Name); +end; + +constructor TPathImpl.Create(const Name: string); +begin + inherited Create(); + fName := Name; + Unify(); +end; + +destructor TPathImpl.Destroy(); +begin + inherited; +end; + +procedure TPathImpl.Unify(); +var + I: integer; +begin + for I := 1 to Length(fName) do + begin + if (fName[I] in ['\', '/']) then + fName[I] := PathDelim; + end; + fName := ExcludeTrailingPathDelimiter(fName); +end; + +function TPathImpl.ToString(Encoding: TPathEncoding): AnsiString; +begin + {$IFDEF MSWINDOWS} + case Encoding of + pencUTF8: + Result := fName; + pencSystemANSI: + Result := Utf8ToAnsi(fName); + else + raise Exception.Create('Unhandled encoding'); + end; + {$ELSE} + Result := fName; + {$ENDIF} +end; + +function TPathImpl.ToWideString(): WideString; +begin + Result := UTF8Decode(fName); +end; + +function TPathImpl.Adjust(): boolean; +begin + Result := false; //TODO +end; + + + +function TPathImpl.Expand(): IPath; +begin + Result := FileSystem.ExpandFileName(Self); +end; + +function TPathImpl.CreateFile(): integer; +begin + Result := FileSystem.FileCreate(Self); +end; + +function TPathImpl.CreateDir(): boolean; +begin + Result := FileSystem.DirectoryCreate(Self); +end; + +function TPathImpl.Open(Mode: LongWord): integer; +begin + Result := FileSystem.FileOpen(Self, Mode); +end; + +function TPathImpl.OpenStream(Mode: Word): TUniFileStream; +begin + Result := TUniFileStream.Create(Self, Mode); +end; + +function TPathImpl.GetFileAge(): integer; +begin + Result := FileSystem.FileAge(Self); +end; + +function TPathImpl.GetFileAge(out FileDateTime: TDateTime): boolean; +begin + Result := FileSystem.FileAge(Self, FileDateTime); +end; + +function TPathImpl.Exists(): boolean; +begin + Result := IsFile() or IsDirectory(); +end; + +function TPathImpl.IsFile(): boolean; +begin + Result := FileSystem.FileExists(Self); +end; + +function TPathImpl.IsDirectory(): boolean; +begin + Result := FileSystem.DirectoryExists(Self); +end; + +function TPathImpl.GetAttr(): cardinal; +begin + Result := FileSystem.FileGetAttr(Self); +end; + +function TPathImpl.SetAttr(Attr: Integer): boolean; +begin + Result := FileSystem.FileSetAttr(Self, Attr); +end; + +function TPathImpl.IsReadOnly(): boolean; +begin + Result := FileSystem.FileIsReadOnly(Self); +end; + +function TPathImpl.SetReadOnly(ReadOnly: boolean): boolean; +begin + Result := FileSystem.FileSetReadOnly(Self, ReadOnly); +end; + +function TPathImpl.ForceDirectories(): boolean; +begin + Result := FileSystem.ForceDirectories(Self); +end; + +function TPathImpl.FileSearch(const DirList: IPath): IPath; +begin + Result := FileSystem.FileSearch(Self, DirList); +end; + +function TPathImpl.Rename(const NewName: IPath): boolean; +begin + Result := FileSystem.RenameFile(Self, NewName); +end; + +function TPathImpl.DeleteFile(): boolean; +begin + Result := FileSystem.DeleteFile(Self); +end; + +function TPathImpl.DeleteEmptyDir(): boolean; +begin + Result := FileSystem.RemoveDir(Self); +end; + +function TPathImpl.CopyFile(const Target: IPath; FailIfExists: boolean): boolean; +begin + Result := FileSystem.CopyFile(Self, Target, FailIfExists); +end; + + + +{ TPathIteratorImpl } + +constructor TPathIteratorImpl.Create(Path: IPath); +begin + fPath := Path; + fPos := -1; +end; + +function TPathIteratorImpl.Next(): IPath; +begin +end; + + +{ TUniFileStream } + +{$IFDEF MSWINDOWS} + +constructor TUniFileStream.Create(const FileName: IPath; Mode: Word); +begin + inherited Create(FileName.ToWideString(), Mode); +end; + +{$ELSE} + +constructor TUniFileStream.Create(const FileName: IPath; Mode: Word); +begin + inherited Create(FileName.ToSystemString(), Mode); +end; + +{$ENDIF} + +{ TUniMemoryStream } + +procedure TUniMemoryStream.LoadFromFile(const FileName: IPath); +var + Stream: TStream; +begin + Stream := TUniFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); + try + LoadFromStream(Stream); + finally + Stream.Free; + end; +end; + +procedure TUniMemoryStream.SaveToFile(const FileName: IPath); +var + Stream: TStream; +begin + Stream := TUniFileStream.Create(FileName, fmCreate); + try + SaveToStream(Stream); + finally + Stream.Free; + end; +end; + +end. diff --git a/unicode/src/base/UFilesystem.pas b/unicode/src/base/UFilesystem.pas new file mode 100644 index 00000000..b9020391 --- /dev/null +++ b/unicode/src/base/UFilesystem.pas @@ -0,0 +1,497 @@ +{* UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + *} + +unit UFilesystem; + +interface + +uses + {$IFDEF MSWINDOWS} + Windows, + TntSysUtils, + {$ENDIF} + UFilename, + SysUtils, + Classes; + +type + {$IFDEF MSWINDOWSe} + TSytemSearchRec = TSearchRecW; + {$ELSE} + TSytemSearchRec = TSearchRec; + {$ENDIF} + + TUniSearchRec = record + Time: Integer; + Size: Int64; + Attr: Integer; + Name: IPath; + ExcludeAttr: Integer; + //FindHandle(): THandle; + end; + + IFileFindIterator = interface + function HasNext(): Boolean; + function Next(): TUniSearchRec; + end; + + IFileSystem = interface + function ExpandFileName(const FileName: IPath): IPath; + function FileCreate(const FileName: IPath): Integer; + function DirectoryCreate(const Dir: IPath): Boolean; + function FileOpen(const FileName: IPath; Mode: LongWord): Integer; + function FileAge(const FileName: IPath): Integer; overload; + function FileAge(const FileName: IPath; out FileDateTime: TDateTime): Boolean; overload; + function DirectoryExists(const Name: IPath): Boolean; + function FileExists(const Name: IPath): Boolean; + function FileGetAttr(const FileName: IPath): Cardinal; + function FileSetAttr(const FileName: IPath; Attr: Integer): Boolean; + function FileIsReadOnly(const FileName: IPath): Boolean; + function FileSetReadOnly(const FileName: IPath; ReadOnly: Boolean): Boolean; + function ForceDirectories(const Dir: IPath): Boolean; + function FileSearch(const Name: IPath; DirList: array of IPath): IPath; + function RenameFile(const OldName, NewName: IPath): Boolean; + function DeleteFile(const FileName: IPath): Boolean; + function RemoveDir(const Dir: IPath): Boolean; + function CopyFile(const Source, Target: IPath; FailIfExists: Boolean): Boolean; + + function FileFind(const FilePattern: IPath; Attr: Integer): IFileFindIterator; + + function FindFirst(const FilePattern: IPath; Attr: Integer; var F: TSytemSearchRec): Integer; + function FindNext(var F: TSytemSearchRec): Integer; + procedure FindClose(var F: TSytemSearchRec); + + function GetCurrentDir: IPath; + function SetCurrentDir(const Dir: IPath): Boolean; + + function CreateFileStream(const FileName: IPath; Mode: Word): THandleStream; + end; + +var + FileSystem: IFileSystem; + +implementation + +type + TFileSystemImpl = class(TInterfacedObject, IFileSystem) + public + function ExpandFileName(const FileName: IPath): IPath; + function FileCreate(const FileName: IPath): Integer; + function DirectoryCreate(const Dir: IPath): Boolean; + function FileOpen(const FileName: IPath; Mode: LongWord): Integer; + function FileAge(const FileName: IPath): Integer; overload; + function FileAge(const FileName: IPath; out FileDateTime: TDateTime): Boolean; overload; + function DirectoryExists(const Name: IPath): Boolean; + function FileExists(const Name: IPath): Boolean; + function FileGetAttr(const FileName: IPath): Cardinal; + function FileSetAttr(const FileName: IPath; Attr: Integer): Boolean; + function FileIsReadOnly(const FileName: IPath): Boolean; + function FileSetReadOnly(const FileName: IPath; ReadOnly: Boolean): Boolean; + function ForceDirectories(const Dir: IPath): Boolean; + function FileSearch(const Name: IPath; DirList: array of IPath): IPath; + function RenameFile(const OldName, NewName: IPath): Boolean; + function DeleteFile(const FileName: IPath): Boolean; + function RemoveDir(const Dir: IPath): Boolean; + function CopyFile(const Source, Target: IPath; FailIfExists: Boolean): Boolean; + + function FileFind(const FilePattern: IPath; Attr: Integer): IFileFindIterator; + + function FindFirst(const FilePattern: IPath; Attr: Integer; var F: TSytemSearchRec): Integer; + function FindNext(var F: TSytemSearchRec): Integer; + procedure FindClose(var F: TSytemSearchRec); + + function GetCurrentDir: IPath; + function SetCurrentDir(const Dir: IPath): Boolean; + + function CreateFileStream(const FileName: IPath; Mode: Word): THandleStream; + end; + + TFileFindIterator = class(TInterfacedObject, IFileFindIterator) + private + fHasNext: Boolean; + fSearchRec: TSytemSearchRec; + public + constructor Create(const FilePattern: IPath; Attr: Integer); + destructor Destroy(); override; + + function HasNext(): Boolean; + function Next(): TUniSearchRec; + end; + + +function TFileSystemImpl.CreateFileStream(const FileName: IPath; Mode: Word): THandleStream; +begin + Result := TUniFileStream.Create(FileName, Mode); +end; + +function TFileSystemImpl.FileFind(const FilePattern: IPath; Attr: Integer): IFileFindIterator; +begin + Result := TFileFindIterator.Create(FilePattern, Attr); +end; + +{$IFDEF MSWINDOWSs} + +function TFileSystemImpl.ExpandFileName(const FileName: IPath): IPath; +begin + Result := Path(WideExpandFileName(FileName.ToWideString())); +end; + +function TFileSystemImpl.FileCreate(const FileName: IPath): Integer; +begin + Result := WideFileCreate(FileName.ToWideString()); +end; + +function TFileSystemImpl.DirectoryCreate(const Dir: IPath): Boolean; +begin + Result := WideCreateDir(Dir.ToWideString()); +end; + +function TFileSystemImpl.FileOpen(const FileName: IPath; Mode: LongWord): Integer; +begin + Result := WideFileOpen(FileName.ToWideString(), Mode); +end; + +function TFileSystemImpl.FileAge(const FileName: IPath): Integer; +begin + Result := WideFileAge(FileName.ToWideString()); +end; + +function TFileSystemImpl.FileAge(const FileName: IPath; out FileDateTime: TDateTime): Boolean; +begin + Result := WideFileAge(FileName.ToWideString(), FileDateTime); +end; + +function TFileSystemImpl.DirectoryExists(const Name: IPath): Boolean; +begin + Result := WideDirectoryExists(Name.ToWideString()); +end; + +function TFileSystemImpl.FileExists(const Name: IPath): Boolean; +begin + Result := WideFileExists(Name.ToWideString()); +end; + +function TFileSystemImpl.FileGetAttr(const FileName: IPath): Cardinal; +begin + Result := WideFileGetAttr(FileName.ToWideString()); +end; + +function TFileSystemImpl.FileSetAttr(const FileName: IPath; Attr: Integer): Boolean; +begin + Result := WideFileSetAttr(FileName.ToWideString(), Attr); +end; + +function TFileSystemImpl.FileIsReadOnly(const FileName: IPath): Boolean; +begin + Result := WideFileIsReadOnly(FileName.ToWideString()); +end; + +function TFileSystemImpl.FileSetReadOnly(const FileName: IPath; ReadOnly: Boolean): Boolean; +begin + Result := WideFileSetReadOnly(FileName.ToWideString(), ReadOnly); +end; + +function TFileSystemImpl.ForceDirectories(const Dir: IPath): Boolean; +begin + Result := WideForceDirectories(Dir.ToWideString()); +end; + +function TFileSystemImpl.FileSearch(const Name: IPath; DirList: array of IPath): IPath; +var + I: integer; + DirListStr: WideString; +begin + DirListStr := ''; + for I := 0 to High(DirList) do + begin + if (I > 0) then + DirListStr := DirListStr + PathSep; + DirListStr := DirListStr + DirList[I].ToWideString(); + end; + Result := Path(WideFileSearch(Name.ToWideString(), DirListStr)); +end; + +function TFileSystemImpl.RenameFile(const OldName, NewName: IPath): Boolean; +begin + Result := WideRenameFile(OldName.ToWideString(), NewName.ToWideString()); +end; + +function TFileSystemImpl.DeleteFile(const FileName: IPath): Boolean; +begin + Result := WideDeleteFile(FileName.ToWideString()); +end; + +function TFileSystemImpl.RemoveDir(const Dir: IPath): Boolean; +begin + Result := WideRemoveDir(Dir.ToWideString()); +end; + +function TFileSystemImpl.CopyFile(const Source, Target: IPath; FailIfExists: Boolean): Boolean; +begin + Result := WideCopyFile(Source.ToWideString(), Target.ToWideString(), FailIfExists); +end; + +function TFileSystemImpl.FindFirst(const FilePattern: IPath; Attr: Integer; var F: TSytemSearchRec): Integer; +begin + Result := WideFindFirst(FilePattern.ToWideString(), Attr, F); +end; + +function TFileSystemImpl.FindNext(var F: TSytemSearchRec): Integer; +begin + Result := WideFindNext(F); +end; + +procedure TFileSystemImpl.FindClose(var F: TSytemSearchRec); +begin + WideFindClose(F); +end; + +function TFileSystemImpl.GetCurrentDir: IPath; +begin + Result := Path(WideGetCurrentDir()); +end; + +function TFileSystemImpl.SetCurrentDir(const Dir: IPath): Boolean; +begin + Result := WideSetCurrentDir(Dir.ToWideString()); +end; + +{$ELSE} // UNIX + +function TFileSystemImpl.ExpandFileName(const FileName: IPath): IPath; +begin + Result := Path(SysUtils.ExpandFileName(FileName.ToString(pencSystemANSI)), pencSystemANSI); +end; + +function TFileSystemImpl.FileCreate(const FileName: IPath): Integer; +begin + Result := SysUtils.FileCreate(FileName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.DirectoryCreate(const Dir: IPath): Boolean; +begin + Result := SysUtils.CreateDir(Dir.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileOpen(const FileName: IPath; Mode: LongWord): Integer; +begin + Result := SysUtils.FileOpen(FileName.ToString(pencSystemANSI), Mode); +end; + +function TFileSystemImpl.FileAge(const FileName: IPath): Integer; +begin + Result := SysUtils.FileAge(FileName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileAge(const FileName: IPath; out FileDateTime: TDateTime): Boolean; +begin + Result := SysUtils.FileAge(FileName.ToString(pencSystemANSI), FileDateTime); +end; + +function TFileSystemImpl.DirectoryExists(const Name: IPath): Boolean; +begin + Result := SysUtils.DirectoryExists(Name.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileExists(const Name: IPath): Boolean; +begin + Result := SysUtils.FileExists(Name.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileGetAttr(const FileName: IPath): Cardinal; +begin + Result := SysUtils.FileGetAttr(FileName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileSetAttr(const FileName: IPath; Attr: Integer): Boolean; +begin + Result := (SysUtils.FileSetAttr(FileName.ToString(pencSystemANSI), Attr) = 0); +end; + +function TFileSystemImpl.FileIsReadOnly(const FileName: IPath): Boolean; +begin + Result := SysUtils.FileIsReadOnly(FileName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileSetReadOnly(const FileName: IPath; ReadOnly: Boolean): Boolean; +begin + Result := SysUtils.FileSetReadOnly(FileName.ToString(pencSystemANSI), ReadOnly); +end; + +function TFileSystemImpl.ForceDirectories(const Dir: IPath): Boolean; +begin + Result := SysUtils.ForceDirectories(Dir.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.FileSearch(const Name: IPath; DirList: array of IPath): IPath; +var + I: integer; + DirListStr: AnsiString; +begin + DirListStr := ''; + for I := 0 to High(DirList) do + begin + if (I > 0) then + DirListStr := DirListStr + PathSep; + DirListStr := DirListStr + DirList[I].ToString(pencSystemANSI); + end; + Result := Path(SysUtils.FileSearch(Name.ToString(pencSystemANSI), DirListStr), pencSystemANSI); +end; + +function TFileSystemImpl.RenameFile(const OldName, NewName: IPath): Boolean; +begin + Result := SysUtils.RenameFile(OldName.ToString(pencSystemANSI), NewName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.DeleteFile(const FileName: IPath): Boolean; +begin + Result := SysUtils.DeleteFile(FileName.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.RemoveDir(const Dir: IPath): Boolean; +begin + Result := SysUtils.RemoveDir(Dir.ToString(pencSystemANSI)); +end; + +function TFileSystemImpl.CopyFile(const Source, Target: IPath; FailIfExists: Boolean): Boolean; +const + COPY_BUFFER_SIZE = 4096; // a good tradeoff between speed and memory consumption +var + SourceFile, TargetFile: TFileStream; + FileCopyBuffer: array [0..COPY_BUFFER_SIZE-1] of byte; // temporary copy-buffer. + NumberOfBytes: integer; // number of bytes read from SourceFile +begin + Result := false; + SourceFile := nil; + TargetFile := nil; + + // if overwrite is disabled return if the target file already exists + if (FailIfExists and FileExists(Target)) then + Exit; + + try + try + // open source and target file (might throw an exception on error) + SourceFile := TFileStream.Create(Source.ToString(pencSystemANSI), fmOpenRead); + TargetFile := TFileStream.Create(Target.ToString(pencSystemANSI), fmCreate or fmOpenWrite); + + while true do + begin + // read a block from the source file and check for errors or EOF + NumberOfBytes := SourceFile.Read(FileCopyBuffer, SizeOf(FileCopyBuffer)); + if (NumberOfBytes <= 0) then + Break; + // write block to target file and check if everything was written + if (TargetFile.Write(FileCopyBuffer, NumberOfBytes) <> NumberOfBytes) then + Exit; + end; + except + Exit; + end; + finally + SourceFile.Free; + TargetFile.Free; + end; + + Result := true; +end; + +function TFileSystemImpl.FindFirst(const FilePattern: IPath; Attr: Integer; var F: TSytemSearchRec): Integer; +begin + Result := SysUtils.FindFirst(FilePattern.ToString(pencSystemANSI), Attr, F); +end; + +function TFileSystemImpl.FindNext(var F: TSytemSearchRec): Integer; +begin + Result := SysUtils.FindNext(F); +end; + +procedure TFileSystemImpl.FindClose(var F: TSytemSearchRec); +begin + SysUtils.FindClose(F); +end; + +function TFileSystemImpl.GetCurrentDir: IPath; +begin + Result := Path(SysUtils.GetCurrentDir(), pencSystemANSI); +end; + +function TFileSystemImpl.SetCurrentDir(const Dir: IPath): Boolean; +begin + Result := SysUtils.SetCurrentDir(Dir.ToString(pencSystemANSI)); +end; + +{$ENDIF} + + +{ TFileFindIterator } + +constructor TFileFindIterator.Create(const FilePattern: IPath; Attr: Integer); +begin + inherited Create(); + fHasNext := (FileSystem.FindFirst(FilePattern, Attr, fSearchRec) = 0); +end; + +destructor TFileFindIterator.Destroy(); +begin + FileSystem.FindClose(fSearchRec); + inherited; +end; + +function TFileFindIterator.HasNext(): Boolean; +begin + Result := fHasNext; +end; + +function TFileFindIterator.Next(): TUniSearchRec; +begin + if (not fHasNext) then + begin + FillChar(Result, SizeOf(Result), 0); + Exit; + end; + + Result.Time := fSearchRec.Time; + Result.Size := fSearchRec.Size; + Result.Attr := fSearchRec.Attr; + {$IFDEF MSWINDOWS} + Result.Name := Path(fSearchRec.Name); + {$ELSE} + Result.Name := Path(fSearchRec.Name, pencSystem); + {$ENDIF} + Result.ExcludeAttr := fSearchRec.ExcludeAttr; + + // fetch next entry + fHasNext := (FileSystem.FindNext(fSearchRec) = 0); +end; + + +initialization + FileSystem := TFileSystemImpl.Create; + +finalization + FileSystem := nil; + +end. |