unit dfiles;

{$MODE FPC}
{$MODESWITCH RESULT}

interface

uses
  dtypes;

function FileExists(const Filename: TString): Boolean;

function DirExists(const Dir: TString): Boolean;

function MakeDirectory(const Dir: TString): Boolean; inline;

function FileRename(const Src, Dst: TString): Boolean; inline;

function FileRemove(const FileName: TString): Boolean; inline;

implementation

{$IF Defined(WINDOWS)}
uses
  windows;
{$ENDIF}

function FileExists(const Filename: TString): Boolean;
var
  F: File;
begin
  FileMode := 64; // FIXME wtf?
  Assign(F, Filename);
  {$I-}
  Reset(F);
  {$I+}
  Result := IOResult = 0;
  if Result then
    Close(F);
end;

function DirExists(const Dir: TString): Boolean;
{$IF Defined(WINDOWS)}
var
  Attrib: DWORD;
begin
  Attrib := GetFileAttributes(PAnsiChar(Dir));
  Exit((Attrib <> (not DWORD(0))) and
       (Attrib and FILE_ATTRIBUTE_DIRECTORY <> 0));
end;
{$ELSE} // fallback
begin
  Exit(FileExists(Dir));
end;
{$ENDIF}

function MakeDirectory(const Dir: TString): Boolean; inline;
begin
  {$I-}
  Mkdir(Dir);
  {$I+}
  Result := IOResult = 0;
end;

function FileRename(const Src, Dst: TString): Boolean; inline;
{$IF Defined(WINDOWS)}
begin
  Result := MoveFileExA(@Src[1], @Dst[1], MOVEFILE_REPLACE_EXISTING);
  // Result := 0 <> ReplaceFileW(
  //     Dst,
  //     Src,
  //     Backup,
  //     0,      // dwReplaceFlags
  //     nil,    // lpExclude
  //     nil     // lpReserved
  //   );
end;
{$ELSE} // fallback
var
  F: File;
begin
  Assign(F, Src);
  {$I-}
  Rename(F, Dst);
  {$I+}
  Result := IOResult = 0;
end;
{$ENDIF}

function FileRemove(const FileName: TString): Boolean; inline;
var
  F: File;
begin
  Assign(F, FileName);
  {$I-}
  Erase(F);
  {$I+}
  Exit(IOResult = 0);
end;

end.
