feat(stdlib): add SameFileName to SysUtils

SameFileName compares two file names for equality. This is a partial,
Unix-only stub: an exact case-sensitive comparison, which is correct on
case-sensitive file systems. Case-insensitive platforms would need the
names folded before comparing, but the stdlib has no platform-variance
facility yet — system.pas hardcodes DirectorySeparator, PathSeparator
and LineEnding to their Unix values — so there is nothing to key the
case-folding on. When a FileNameCaseSensitive constant lands alongside
the other platform constants, the case-insensitive branch can be added.

e2e test asserts identical names match and differing names do not.
This commit is contained in:
Andrew Haines 2026-06-24 18:16:14 -04:00 committed by Graeme Geldenhuys
parent 4addcd1076
commit 4eeff7c2c0
2 changed files with 50 additions and 0 deletions

View file

@ -45,6 +45,7 @@ type
procedure TestRun_SetCurrentDir_ChangesDir;
procedure TestRun_ExtractFileExt_ReturnsExt;
procedure TestRun_BoolToStr_TrueAndFalse;
procedure TestRun_SameFileName_ExactMatch;
procedure TestRun_PlatformConstants;
procedure TestRun_GetCurrentDir_ReturnsNonEmpty;
procedure TestRun_FileAge_ReturnsTimestamp;
@ -534,6 +535,16 @@ const
end.
''';
SrcSameFileName =
'''
program P;
uses SysUtils;
begin
WriteLn(SameFileName('a/b.pas', 'a/b.pas'));
WriteLn(SameFileName('a/b.pas', 'a/c.pas'))
end.
''';
SrcPlatformConstants =
'''
program P;
@ -659,6 +670,25 @@ begin
end;
end;
procedure TE2ESysUtilsTests.TestRun_SameFileName_ExactMatch;
var
Output: string;
RCode: Integer;
Lines: TStringList;
begin
if not ToolchainAvailable() then begin Ignore('toolchain unavailable'); Exit; end;
AssertTrue('compile+run', CompileAndRunWithRTL(SrcSameFileName, Output, RCode));
AssertEquals('exit code 0', 0, RCode);
Lines := TStringList.Create();
try
Lines.Text := Trim(Output);
AssertEquals('identical names match', 'True', Lines.Strings[0]);
AssertEquals('different names differ', 'False', Lines.Strings[1]);
finally
Lines.Free();
end;
end;
procedure TE2ESysUtilsTests.TestRun_PlatformConstants;
var
Output: string;

View file

@ -64,6 +64,18 @@ function BoolToStr(B: Boolean; AUseBoolStrs: Boolean = False): string;
on paths that do not traverse symlinks. }
function ExpandFileName(const APath: string): string;
{ SameFileName compare two file names for equality.
PARTIAL STUB: an exact, case-sensitive string comparison. This is correct
only on case-sensitive file systems (Unix); case-insensitive platforms
(Windows) would need the names folded before comparing. Blaise has no
platform-variance facility yet system.pas hardcodes DirectorySeparator,
PathSeparator and LineEnding to their Unix values so there is nothing to
key the case-folding on. When a FileNameCaseSensitive constant lands
alongside the other platform constants, add the case-insensitive branch
here under that guard. }
function SameFileName(const S1, S2: string): Boolean;
implementation
constructor Exception.Create(AMessage: string);
@ -145,4 +157,12 @@ begin
Result := '/';
end;
{ PARTIAL STUB exact compare only; see the interface note. Correct on
case-sensitive (Unix) file systems; needs a case-insensitive branch for
Windows. }
function SameFileName(const S1, S2: string): Boolean;
begin
Result := S1 = S2;
end;
end.