Ответ 1
TPath.HasValidPathChars
полностью сломан. Это его реализация:
class function TPath.HasValidPathChars(const Path: string;
const UseWildcards: Boolean): Boolean;
var
PPath: PChar;
PathLen: Integer;
Ch: Char;
I: Integer;
begin
// Result will become True if an invalid path char is found
{$IFDEF MSWINDOWS}
I := GetPosAfterExtendedPrefix(Path) - 1;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
I := 0;
{$ENDIF POSIX}
PPath := PChar(Path);
PathLen := Length(Path);
Result := False;
while (not Result) and (i < PathLen) do
begin
Ch := PPath[i];
if not IsValidPathChar(Ch) then
if UseWildcards then
if not IsPathWildcardChar(Ch) then
Result := True
else
Inc(i)
else
Result := True
else
Inc(i);
end;
Result := not Result;
end;
Решающим моментом является вызов IsValidPathChar
. Давайте посмотрим, что это делает.
class function TPath.IsValidPathChar(const AChar: Char): Boolean;
begin
Result := not IsCharInOrderedArray(AChar, FInvalidPathChars);
end;
Теперь FInvalidPathChars
определяется как:
FInvalidPathChars := TCharArray.Create(
#0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12,
#13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24,
#25, #26, #27, #28, #29, #30, #31,
'"', '<', '>', '|'); // DO NOT LOCALIZE;
То есть все ординалы меньше 32 и "
, <
, >
и |
.
Нам также нужно понять, что делает IsPathWildcardChar
.
class function TPath.IsPathWildcardChar(const AChar: Char): Boolean;
begin
Result := IsCharInOrderedArray(AChar, FPathWildcardChars);
end;
Где FPathWildcardChars
:
FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE;
Теперь вернемся к TPath.HasValidPathChars
. Рассмотрим этот оператор if
:
if not IsValidPathChar(Ch) then
Условие not IsValidPathChar(Ch)
оценивается как True
, когда IsValidPathChar(Ch)
равно False
. Что произойдет, если Ch
находится в FInvalidPathChars
. То есть, если Ch
имеет порядковый номер меньше 32 или является одним из "
, <
, >
и |
.
Ваша тестовая строка 'C:\test\test?\'
, и на самом деле ни один из этих символов не находится в FInvalidPathChars
. Это означает, что условие в операторе if not IsValidPathChar(Ch) then
всегда оценивает False
. Поэтому, даже если ваша строка содержит подстановочный знак, она никогда не сможет достичь последующего теста:
if UseWildcards then
Нетрудно заключить, что HasValidPathChars
возвращает одно и то же значение независимо от значения входного параметра UseWildcards
. И если у вас есть какие-либо сомнения в анализе, эта программа должна развеять его:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.IOUtils;
procedure Main;
var
Ch: Char;
begin
for Ch := low(Ch) to high(Ch) do
if TPath.HasValidPathChars(Ch, False)<>TPath.HasValidPathChars(Ch, True) then
Writeln('different at #' + IntToStr(ord(Ch)));
Writeln('finished');
end;
begin
Main;
Readln;
end.
Это похоже на еще одну функцию в этом ужасном модуле IOUtils
, который был неправильно реализован и не протестирован.
Я отправил отчет об ошибке: RSP-18696.
Основываясь на том, что мы столкнулись с множеством таких проблем с IOUtils
, мой опыт в том, что устройству не нужно доверять. Я бы не использовал его. Найдите альтернативный способ решения вашей проблемы.