Функция Pascal/Delphi SubStr, с полным поведением как PHP

Важно учитывать что Start (начало строки) начинается именно с 0 как в PHP, а не с 1 как в Pascal.

Это была необходимость для 100% совместимости. И код учитывает это добавляя 1 перед использованием System.Copy

Тесты функции были взяты напрямую с php.net из документации substr.

unRealSubstr.pas
unit unRealSubstr;
 
interface
 
uses SysUtils;
 
    function SubStr(const S: string; Start: Integer; Length: Integer = 2147483647): string;
 
implementation
 
    function SubStr(const S: string; Start: Integer; Length: Integer): string;
    var SLineLen: Integer;
        ActualStart: Integer;
        ActualLen: Integer;
    begin
        Result := '';
        SLineLen := System.Length(S);
        if SLineLen = 0 then Exit;
        if Start >= 0 then ActualStart := Start + 1 else ActualStart := SLineLen + Start + 1;
        if ActualStart > SLineLen then Exit;
        if ActualStart < 1 then ActualStart := 1;
        if Length >= 0 then begin
            ActualLen := Length;
            if (ActualStart + ActualLen - 1) > SLineLen then ActualLen := SLineLen - ActualStart + 1;
        end else begin
            ActualLen := (SLineLen + Length) - ActualStart + 1;
        end;
        if ActualLen <= 0 then Exit;
        Result := System.Copy(S, ActualStart, ActualLen);
    end;
 
{$IFDEF PHPLIKE_SUBSTR_TESTS}
implementation
Assert(substr('abcdef', -1) = 'f',          'substr("abcdef", -1)');
Assert(substr('abcdef', -2) = 'ef',         'substr("abcdef", -2)');
Assert(substr('abcdef', -3, 1) = 'd',       'substr("abcdef", -3, 1)');
Assert(substr('abcdef', 0, -1) = 'abcde',   'substr("abcdef", 0, -1)');
Assert(substr('abcdef', 2, -1) = 'cde',     'substr("abcdef", 2, -1)');
Assert(substr('abcdef', 4, -4) = '',        'substr("abcdef", 4, -4)');
Assert(substr('abcdef', -3, -1) = 'de',     'substr("abcdef", -3, -1)');
Assert(substr('abcdef', 1) = 'bcdef',       'substr("abcdef", 1)');
Assert(substr('abcdef', 1, 3) = 'bcd',      'substr("abcdef", 1, 3)');
Assert(substr('abcdef', 0, 4) = 'abcd',     'substr("abcdef", 0, 4)');
Assert(substr('abcdef', 0, 8) = 'abcdef',   'substr("abcdef", 0, 8)');
Assert(substr('abcdef', -1, 1) = 'f',       'substr("abcdef", -1, 1)');
{$ENDIF}
end.