Skip to content

Commit

Permalink
Strings, TStr: +SplitText, StrInArray, StringArrayToStr, refactorings
Browse files Browse the repository at this point in the history
  • Loading branch information
jackdp committed Jul 24, 2022
1 parent 4ec956b commit a0267e4
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 34 deletions.
170 changes: 136 additions & 34 deletions Base/JPL.Strings.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
https://www.pazera-software.com
https://github.com/jackdp
To jest mój stary moduł z roku 2000 dla Borland Pascala 7.0
W kolejnych latach rozbudowywany i dostosowywany do nowszych wersji Delphi i FPC.
Based on my old unit from 2000 for Borland Pascal 7.0
}


Expand Down Expand Up @@ -68,21 +67,23 @@ TSpecialChars = record
TArray<T> = array of T;
{$ENDIF}

function Rbs(Dir: string): string; // removes path delimiter from end
function Qs(const s: string): string; // adds " at the beginning and end of the input string
function Rbs(const Directory: string): string; // Removes path delimiter from the end of directory name.
function Qs(const s: string): string; // Adds " at the beginning and end of the input string. See also EnsureBounds, AddBounds
function Capitalize(const s: string): string;
function FixFileName(fName: string; s: string = '_'; ZamieniajCudzyslowy: Boolean = True): string;
function FixFileName(const ShortFileName: string; ReplaceInvalidCharsWith: string = '_'; ReplaceQuotationMarks: Boolean = True): string;
function IsValidShortFileName(const ShortFileName: string): Boolean;
function IsValidLongFileName(const LongFileName: string): Boolean;
function FixFileNameSlashes(const FileName: string): string; deprecated {$IFDEF DCC}{$IF CompilerVersion > 19}'Use FixPathDelimiters instead'{$IFEND}{$ENDIF};
function FixPathDelimiters(const FileName: string): string;

function PadString(Text: string; i: integer; znak: Char = ' '): string;
function Pad(Text: string; Len: integer; PaddingChar: Char = ' '): string; overload;
function Pad(const x: integer; Len: integer; PaddingChar: Char = '0'): string; overload;
function Pad(const x: Int64; Len: integer; PaddingChar: Char = '0'): string; overload;
function PadRight(Text: string; Len: integer; PaddingChar: Char = ' '): string; overload;
function PadRight(const x: integer; Len: integer; PaddingChar: Char = ' '): string; overload;
function PadRight(const x: Int64; Len: integer; PaddingChar: Char = ' '): string; overload;

function UnquoteStr(s: string; bDoubleQuote: Boolean = True): string;
function IntToStrEx(const x: int64; c: Char = ' '): string; overload;
function IntToStrEx(const x: integer; c: Char = ' '): string; overload;
Expand Down Expand Up @@ -168,6 +169,8 @@ procedure SplitStrToArrayEx(s: string; var Arr: TStringDynArray; const EndLineSt
function RemoveEmptyStrings(var Arr: TStringDynArray): integer; // Returns the number of removed empty strings
function SplitStr(const InStr: string; out LeftStr, RightStr: string; const Separator: string): Boolean; overload;
function SplitStr(const InStr: string; out LeftInt, RightInt: integer; const Separator: string): Boolean; overload;
// SplitText copied from JPL.CmdLineParser.pas
function SplitText(Text: string; MaxLen, Padding: integer; PadFirstLine: Boolean = False; PaddingChar: Char = ' '; ENDL: string = #13#10): string;

function TrimBounds(s: string; LeftBound, RightBound: string): string;
function IsBoundedWith(const s: string; LeftBound, RightBound: string; IgnoreCase: Boolean = False): Boolean;
Expand Down Expand Up @@ -205,10 +208,40 @@ function SaveStringToFile(const FileName, Content: string): Boolean; overload;
function LoadStringFromFile(const FileName: string; var s: string; Encoding: TEncoding; ForceEncoding: Boolean = False): Boolean; overload;
function LoadStringFromFile(const FileName: string; var s: string): Boolean; overload;

function StrInArray(const s: string; const Arr: array of string; const IgnoreCase: Boolean): Boolean;
function StringArrayToStr(Arr: TStringDynArray; ValueSeparator: string = ', '): string;


implementation


function StrInArray(const s: string; const Arr: array of string; const IgnoreCase: Boolean): Boolean;
var
i: integer;
us: string;
begin
Result := False;
if IgnoreCase then us := UpperCase(s);

for i := 0 to High(Arr) do
begin
if IgnoreCase then Result := UpperCase(Arr[i]) = us
else Result := Arr[i] = s;
if Result then Break;
end;
end;

function StringArrayToStr(Arr: TStringDynArray; ValueSeparator: string = ', '): string;
var
i: integer;
begin
Result := '';
if Length(Arr) = 0 then Exit;
for i := 0 to Length(Arr) - 1 do
Result := Result + Arr[i] + ValueSeparator;
Result := TrimFromEnd(Result, ValueSeparator);
end;

{$IFDEF FPC}
function SaveStringToFile(const FileName, Content: string; Encoding: TEncoding; const WriteBOM: Boolean = True): Boolean; overload;
var
Expand Down Expand Up @@ -353,6 +386,84 @@ function SplitStr(const InStr: string; out LeftInt, RightInt: integer; const Sep
Result := True;
end;

function SplitText(Text: string; MaxLen, Padding: integer; PadFirstLine: Boolean = False; PaddingChar: Char = ' '; ENDL: string = #13#10): string;
const
Delims: TSysCharset = [
' ',
'(', ')', '[', ']', '{', '}', '<', '>',
{'`',} '~', '!', '@', '#', '$', '%', '^', '*', '-', {'_',} '+', '=',
{'''',} '"', '\', '|', ';', ':', ',', '.'
];
var
i, xDelimPos: integer;
s, sr, PaddingStr: string;
A: array of string;

procedure Add(Line: string);
begin
SetLength(A, Length(A) + 1);
A[Length(A) - 1] := Line;
end;

function DelimPos(InStr: string; SearchPosStart: integer): integer;
var
i: integer;
begin
Result := -1;
if (InStr = '') or (SearchPosStart < 1) or (SearchPosStart > Length(InStr)) then Exit;
for i := SearchPosStart downto 1 do
begin
if CharInSet(InStr[i], Delims) then
begin
Result := i;
Break;
end;
end;
end;

begin
if (Length(Text) <= Padding) or (MaxLen = 0) then
begin
Result := Text;
Exit;
end;

SetLength(A, 0);
//if Padding > MaxLen then exit;
if not PadFirstLine then
begin
xDelimPos := DelimPos(Text, MaxLen);
if xDelimPos < 0 then xDelimPos := MaxLen;
s := Copy(Text, 1, xDelimPos);

Add(s);
Text := Copy(Text, xDelimPos + 1, Length(Text));
end;

sr := '';
PaddingStr := StringOfChar(PaddingChar, Padding);


while Text <> '' do
begin

xDelimPos := DelimPos(Text, MaxLen - Padding);
if xDelimPos < 0 then xDelimPos := MaxLen;

s := PaddingStr + Trim( Copy(Text, 1, xDelimPos) );
Add(s);
Text := Copy(Text, xDelimPos + 1, Length(Text));
//Writeln(Text);

end;


for i := 0 to Length(A) - 1 do sr := sr + A[i] + ENDL;
sr := TrimRight(sr);

Result := sr;
end;

function Capitalize(const s: string): string;
var
i: integer;
Expand Down Expand Up @@ -724,12 +835,8 @@ function GetFileSizeString(const FileSize: Int64; BytesStr: string = ' bytes'):
end;

function StrRemove(const s, StringToRemove: string; IgnoreCase: Boolean = False): string;
var
rf: TReplaceFlags;
begin
rf := [rfReplaceAll];
if IgnoreCase then Include(rf, rfIgnoreCase);
Result := StringReplace(s, StringToRemove, '', rf);
Result := ReplaceAll(s, StringToRemove, '', IgnoreCase);
end;

function MyDir(bExcludeTrailingPathDelim: Boolean = True): string;
Expand Down Expand Up @@ -814,7 +921,7 @@ function ReplaceHtmlEntities(const AStr: string; IgnoreCase: Boolean = False): s
rf: TReplaceFlags;
s: string;
begin
// HTML entities are case sensitive
// HTML entities are case sensitive!
rf := [rfReplaceAll];
if IgnoreCase then rf := rf + [rfIgnoreCase];

Expand Down Expand Up @@ -953,7 +1060,7 @@ function RemoveChars(const SrcStr: string; Chars: array of Char; IgnoreCase: Boo
Result := StringReplace(Result, Chars[i], '', rf);
end;

// A po co to?
// HINT: A po co to?
function AnsiUpCase(zn: Char; Default: Char): Char;
var
s: string;
Expand All @@ -963,7 +1070,7 @@ function AnsiUpCase(zn: Char; Default: Char): Char;
Result := s[1];
end;

// A po co to?
// HINT: A po co to?
function AnsiLowCase(zn: Char; Default: Char): Char;
var
s: string;
Expand Down Expand Up @@ -1155,6 +1262,7 @@ function ReplaceSpecialChars(s: string; sc: Char): string;
end;
{$hints on}

// TODO: Change name. This is not the best name for this function.
function RemoveSlashes(const Text: string): string;
var
s: string;
Expand Down Expand Up @@ -1359,22 +1467,19 @@ function PadRight(const x: Int64; Len: integer; PaddingChar: Char = ' '): string
Result := PadRight(IntToStr(x), Len, PaddingChar);
end;


{$hints off}
function FixFileName(fName: string; s: string = '_'; ZamieniajCudzyslowy: Boolean = True): string;
begin
if ZamieniajCudzyslowy then fName := StringReplace(fName, '"', '''', [rfReplaceAll]);
fName := StringReplace(fName, '?', s, [rfReplaceAll]);
fName := StringReplace(fName, '*', s, [rfReplaceAll]);
fName := StringReplace(fName, ':', s, [rfReplaceAll]);
fName := StringReplace(fName, '/', s, [rfReplaceAll]);
fName := StringReplace(fName, '\', s, [rfReplaceAll]);
fName := StringReplace(fName, '<', s, [rfReplaceAll]);
fName := StringReplace(fName, '>', s, [rfReplaceAll]);
fName := StringReplace(fName, '|', s, [rfReplaceAll]);
Result := fName;
function FixFileName(const ShortFileName: string; ReplaceInvalidCharsWith: string = '_'; ReplaceQuotationMarks: Boolean = True): string;
begin
Result := ShortFileName;
if ReplaceQuotationMarks then Result := ReplaceAll(Result, '"', '''');
Result := ReplaceAll(Result, '?', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '*', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, ':', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '/', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '\', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '<', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '>', ReplaceInvalidCharsWith);
Result := ReplaceAll(Result, '|', ReplaceInvalidCharsWith);
end;
{$hints on}

function IsValidShortFileName(const ShortFileName: string): Boolean;
const
Expand Down Expand Up @@ -1436,14 +1541,11 @@ function Qs(const s: string): string;
Result := '"' + s + '"';
end;

{$hints off}
function Rbs(Dir: string): string;
function Rbs(const Directory: string): string;
begin
if Copy(Dir, Length(Dir), 1) = '.' then Delete(Dir, Length(Dir), 1);
Dir := ExcludeTrailingPathDelimiter(Dir);
Result := Dir;
Result := TrimFromEnd(Directory, '.');
Result := ExcludeTrailingPathDelimiter(Result);
end;
{$hints on}

function IntToStrEx(const x: int64; c: Char = ' '): string;
var
Expand Down
13 changes: 13 additions & 0 deletions Base/JPL.TStr.pas
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ TStr = record

class function IsFileMask(const FileName: string): Boolean; static;

class function StrInArray(const s: string; const Arr: array of string; const IgnoreCase: Boolean): Boolean; static;
class function StringArrayToStr(Arr: TStringDynArray; ValueSeparator: string = ', '): string; static;

class property DecimalSeparator: Char read GetDecimalSeparator write SetDecimalSeparator;
class property ThousandSeparator: Char read GetThousandSeparator write SetThousandSeparator;
class property DateSeparator: Char read GetDateSeparator write SetDateSeparator;
Expand Down Expand Up @@ -471,6 +474,16 @@ class function TStr.IsFileMask(const FileName: string): Boolean;
Result := TStr.Contains(FileName, '*') or TStr.Contains(FileName, '?');
end;

class function TStr.StrInArray(const s: string; const Arr: array of string; const IgnoreCase: Boolean): Boolean;
begin
Result := JPL.Strings.StrInArray(s, Arr, IgnoreCase);
end;

class function TStr.StringArrayToStr(Arr: TStringDynArray; ValueSeparator: string = ', '): string;
begin
Result := JPL.Strings.StringArrayToStr(Arr, ValueSeparator);
end;

class function TStr.GetDecimalSeparator: Char;
begin
{$IFDEF FPC}Result := FormatSettings.DecimalSeparator;{$ENDIF}
Expand Down

0 comments on commit a0267e4

Please sign in to comment.