Complete BigTask
Sync changed files to Google Drive / sync (push) Successful in 29s

This commit is contained in:
admin_d committed 2026-09-18 00:06:15 +05:00
1 parent 1a5b20ca9f
commit 06baad3db6
4 files changed
+779 -52

No files matched your search

+107 -52
View File
@@ -65,13 +65,16 @@ uses
implementation
uses
StrUtils, KM_CommonUtils,
KM_Defaults;
KM_Defaults
{$IFDEF ANDROID}, KM_FileIO_Mobile{$ENDIF};
function ReadTextA(const aFilename: UnicodeString): AnsiString;
var
MS: TMemoryStream;
Head: Cardinal;
BOM: array[0..2] of Byte;
HasBOM: Boolean;
Remaining: Int64;
begin
MS := TMemoryStream.Create;
try
@@ -80,18 +83,23 @@ begin
// Instead we read plain ANSI text. If there's BOM - clip it
MS.LoadFromFile(aFileName);
// Read 4 bytes but check just 3, cos reading 3 bytes is a hassle
MS.Read(Head, SizeOf(Cardinal));
HasBOM := False;
if MS.Size >= 3 then
begin
MS.Position := 0;
MS.ReadBuffer(BOM, SizeOf(BOM));
HasBOM := (BOM[0] = $EF) and (BOM[1] = $BB) and (BOM[2] = $BF);
end;
// Trim UTF8 BOM (don't know how to deal with others yet)
if Head and $FFFFFF = $BFBBEF then
if HasBOM then
MS.Position := 3
else
MS.Position := 0;
SetLength(Result, MS.Size - MS.Position);
if MS.Size - MS.Position > 0 then
MS.Read(Result[1], MS.Size - MS.Position);
Remaining := MS.Size - MS.Position;
SetLength(Result, Remaining);
if Remaining > 0 then
MS.ReadBuffer(Result[1], Remaining);
finally
MS.Free;
end;
@@ -107,9 +115,10 @@ var
{$ENDIF}
{$IFDEF FPC}
MS: TMemoryStream;
Head: Cardinal;
BOM: array[0..2] of Byte;
HasBOM: Boolean;
TmpA: AnsiString;
TmpA: RawByteString;
Remaining: Int64;
{$ENDIF}
begin
{$IFDEF WDC}
@@ -129,23 +138,29 @@ begin
MS := TMemoryStream.Create;
try
MS.LoadFromFile(aFileName);
MS.Read(Head, 4);
//Trim UTF8 BOM (don't know how to deal with others yet)
HasBOM := Head and $FFFFFF = $BFBBEF;
HasBOM := False;
if MS.Size >= 3 then
begin
MS.Position := 0;
MS.ReadBuffer(BOM, SizeOf(BOM));
HasBOM := (BOM[0] = $EF) and (BOM[1] = $BB) and (BOM[2] = $BF);
end;
if HasBOM then
MS.Position := 3
else
MS.Position := 0;
SetLength(TmpA, MS.Size - MS.Position);
MS.Read(TmpA[1], MS.Size - MS.Position);
Remaining := MS.Size - MS.Position;
SetLength(TmpA, Remaining);
if Remaining > 0 then
MS.ReadBuffer(TmpA[1], Remaining);
{$IFDEF ANDROID}
if not HasBOM then
raise Exception.Create('KM_FileIO: ReadTextU codepage conversion is unsupported on Android');
Result := UTF8Decode(TmpA);
if HasBOM then
Result := UTF8Decode(TmpA)
else
Result := KMFileIODecodeLegacy(TmpA, aEncoding);
{$ELSE}
//Non-UTF8 files must be converted from their native encoding
if not HasBOM then
@@ -163,7 +178,7 @@ end;
procedure KMCopyFile(const aSrc, aDest: UnicodeString);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMCopyFile is unsupported on Android');
KMFileIOCopyFile(aSrc, aDest);
{$ELSE}
{$IFDEF FPC}
CopyFile(pchar(aSrc), pchar(aDest), True);
@@ -178,7 +193,9 @@ end;
procedure KMCopyFile(const aSrc, aDest: UnicodeString; aOverwrite: Boolean);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMCopyFile is unsupported on Android');
if aOverwrite and FileExists(aDest) and not SysUtils.DeleteFile(aDest) then
raise Exception.CreateFmt('KM_FileIO: unable to delete destination file: %s', [aDest]);
KMFileIOCopyFile(aSrc, aDest);
{$ELSE}
if aOverwrite and FileExists(aDest) then
DeleteFile(aDest);
@@ -211,7 +228,7 @@ end;
procedure KMDeleteFileToBin(const aPath: UnicodeString);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMDeleteFileToBin is unsupported on Android');
KMDeleteFile(aPath, True);
{$ELSE}
KMDeleteFile(aPath, True);
{$ENDIF}
@@ -242,10 +259,15 @@ begin
SHFileOperation(ShOp);
{$ELSE}
{$IFDEF ANDROID}
if not FileExists(aFilePath) then
Exit;
if aDeleteToBin then
raise Exception.Create('KM_FileIO: KMDeleteFile recycle-bin mode is unsupported on Android');
KMFileIOMoveToTrash(aFilePath, False)
else if not SysUtils.DeleteFile(aFilePath) then
raise Exception.CreateFmt('KM_FileIO: unable to delete file: %s', [aFilePath]);
{$ELSE}
DeleteFile(aFilePath);
{$ENDIF}
DeleteFile(aFilePath);
{$ENDIF}
end;
@@ -253,7 +275,7 @@ end;
procedure KMDeleteFolderToBin(const aPath: UnicodeString);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMDeleteFolderToBin is unsupported on Android');
KMDeleteFolder(aPath, True);
{$ELSE}
KMDeleteFolder(aPath, True);
{$ENDIF}
@@ -263,7 +285,7 @@ end;
procedure KMDeleteFolder(const aPath: UnicodeString);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMDeleteFolder is unsupported on Android');
KMDeleteFolder(aPath, False);
{$ELSE}
KMDeleteFolder(aPath, False);
{$ENDIF}
@@ -320,11 +342,14 @@ const
{$ENDIF}
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMDeleteFolder is unsupported on Android');
{$ELSE}
if DirectoryExists(aPath) then
begin
{$IFDEF ANDROID}
if aDeleteToBin then
KMFileIOMoveToTrash(aPath, True)
else
KMFileIORemoveDirectoryTree(aPath);
{$ELSE}
{$IFDEF MSWINDOWS}
if aDeleteToBin then
begin
@@ -344,8 +369,8 @@ begin
{$ELSE}
DeleteDefault;
{$ENDIF}
{$ENDIF}
end;
{$ENDIF}
end;
@@ -356,7 +381,12 @@ var
{$ENDIF}
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMDeleteFolderContent is unsupported on Android');
if DirectoryExists(aPath) then
begin
KMDeleteFolder(aPath, aDeleteToBin);
if not ForceDirectories(aPath) and not DirectoryExists(aPath) then
raise Exception.CreateFmt('KM_FileIO: unable to recreate folder: %s', [aPath]);
end;
{$ELSE}
if DirectoryExists(aPath) then
begin
@@ -393,7 +423,13 @@ end;
procedure KMRenameFolder(const aSourcePath, aDestPath: UnicodeString);
begin
{$IFDEF FPC} RenameFile(aSourcePath, aDestPath); {$ENDIF}
{$IFDEF FPC}
{$IFDEF ANDROID}
KMFileIORenameDirectory(aSourcePath, aDestPath);
{$ELSE}
RenameFile(aSourcePath, aDestPath);
{$ENDIF}
{$ENDIF}
{$IFDEF WDC} TDirectory.Move(aSourcePath, aDestPath); {$ENDIF}
end;
@@ -405,15 +441,19 @@ begin
if IsFilePath(aSourcePath) then
begin
if FileExists(aSourcePath) then
{$IFDEF FPC} RenameFile(aSourcePath, aDestPath); {$ENDIF}
{$IFDEF FPC}
{$IFDEF ANDROID}
if not SysUtils.RenameFile(aSourcePath, aDestPath) then
raise Exception.CreateFmt('KM_FileIO: unable to rename file from %s to %s', [aSourcePath, aDestPath]);
{$ELSE}
RenameFile(aSourcePath, aDestPath);
{$ENDIF}
{$ENDIF}
{$IFDEF WDC} TFile.Move(aSourcePath, aDestPath); {$ENDIF}
end
else
if DirectoryExists(aSourcePath) then
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMRenamePath directory mode is unsupported on Android');
{$ELSE}
//Try to delete folder up to 3 times. Sometimes folder could not be deleted for some reason
if not TryExecuteMethodProc(KMDeleteFolder, aDestPath, 'KMDeleteFolder', ErrorStr) then
raise Exception.Create('Can''t delete folder ' + aDestPath + ': ' + ErrorStr);
@@ -421,7 +461,6 @@ begin
//Try to rename folder up to 3 times. Sometimes folder could not be renamed for some reason
if not TryExecuteMethodProc(KMRenameFolder, aSourcePath, aDestPath, 'KMRenameFolder', ErrorStr) then
raise Exception.Create(Format('Can''t rename folder from %s to %s: %s', [aSourcePath, aDestPath, ErrorStr]));
{$ENDIF}
end;
end;
@@ -480,10 +519,6 @@ begin
or (aSourceFolder = aDestFolder)
or not DirectoryExists(aSourceFolder) then Exit;
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: KMMoveFolder is unsupported on Android');
{$ENDIF}
KMDeleteFolder(aDestFolder, False);
//Move directory to dest first
@@ -503,6 +538,10 @@ function KMFileSize(const aFilename: String): Int64;
var
info: TWin32FileAttributeData;
{$ENDIF}
{$IFDEF ANDROID}
var
Stream: TFileStream;
{$ENDIF}
begin
Result := -1;
@@ -512,6 +551,22 @@ begin
Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
{$ENDIF}
{$IFDEF ANDROID}
if not FileExists(aFilename) then
Exit;
try
Stream := TFileStream.Create(aFilename, fmOpenRead or fmShareDenyNone);
try
Result := Stream.Size;
finally
Stream.Free;
end;
except
Result := -1;
end;
{$ENDIF}
end;
@@ -526,10 +581,7 @@ procedure WriteText(const aText: string; aFilename: string; aEncoding: TEncoding
var
sl: TStringList;
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: WriteText is unsupported on Android');
{$ELSE}
{$IFDEF WDC}
{$IF DEFINED(WDC) OR DEFINED(ANDROID)}
sl := TStringList.Create;
try
sl.Text := aText;
@@ -538,7 +590,6 @@ begin
sl.Free;
end;
{$ENDIF}
{$ENDIF}
end;
@@ -551,10 +602,12 @@ begin
Stream := TFileStream.Create(aFileName, fmCreate);
try
BOM := TEncoding.UTF8.GetPreamble;
Stream.WriteBuffer(BOM, Length(BOM));
if Length(BOM) > 0 then
Stream.WriteBuffer(BOM[0], Length(BOM));
Buffer := TEncoding.UTF8.GetBytes(aText);
Stream.WriteBuffer(Buffer, Length(Buffer));
if Length(Buffer) > 0 then
Stream.WriteBuffer(Buffer[0], Length(Buffer));
finally
Stream.Free;
end;
@@ -569,7 +622,7 @@ var
{$ENDIF}
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: IsDirectoryWriteable is unsupported on Android');
Result := KMFileIOIsDirectoryWriteable(aDir);
{$ELSE}
{$IFDEF WDC}
tmpFilename := IncludeTrailingPathDelimiter(aDir) + 'chk.tmp';
@@ -594,7 +647,9 @@ end;
function CreateAndGetDocumentsSavePath: string;
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: CreateAndGetDocumentsSavePath is unsupported on Android');
Result := KMFileIOApplicationSavePath;
if not IsDirectoryWriteable(Result) then
raise Exception.CreateFmt('KM_FileIO: application save path is not writeable: %s', [Result]);
{$ELSE}
// Returns C:\Users\Username\My Documents\My Games\GAME_TITLE\
// According to GDSE this is the most commonly used savegame location (https://gamedev.stackexchange.com/a/108243)
@@ -681,7 +736,7 @@ end;
procedure CheckFolderPermission(const aPath: string; var aRead, aWrite, aExec: Boolean);
begin
{$IFDEF ANDROID}
raise Exception.Create('KM_FileIO: CheckFolderPermission is unsupported on Android');
KMFileIOCheckFolderPermission(aPath, aRead, aWrite, aExec);
{$ELSE}
{$IFDEF WDC}
aRead := (CheckFileAccess(aPath, FILE_GENERIC_READ) = FILE_GENERIC_READ);