{******************************************************************************} { } { Library: Fundamentals 5.00 } { File name: flcStrings.pas } { File version: 5.71 } { Description: String utility functions } { } { Copyright: Copyright (c) 1999-2020, David J Butler } { All rights reserved. } { Redistribution and use in source and binary forms, with } { or without modification, are permitted provided that } { the following conditions are met: } { Redistributions of source code must retain the above } { copyright notice, this list of conditions and the } { following disclaimer. } { THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND } { CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED } { WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED } { WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A } { PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL } { THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, } { INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR } { CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, } { PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF } { USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) } { HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER } { IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING } { NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE } { USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE } { POSSIBILITY OF SUCH DAMAGE. } { } { Github: https://github.com/fundamentalslib } { E-mail: fundamentals.library at gmail.com } { } { Revision history: } { } { 1999/10/19 0.01 Split from Maths unit. } { 1999/10/26 0.02 Revision. } { 1999/10/30 0.03 Added Count, Reverse. } { 1999/10/31 0.04 Improved Match. } { Added Replace, Count, PadInside. } { 1999/11/06 1.05 Added Remove, TrimEllipse. } { 1999/11/09 1.06 Added Pack functions. } { 1999/11/17 1.07 Added PosN, Before, After, Between and Split. } { 1999/11/22 1.08 Added Join. } { 1999/11/23 1.09 Added Translate. } { 1999/12/02 1.10 Fixed bugs in Replace and Match reported by daiqingbo. } { 1999/12/27 1.11 Added SelfTest procedure and Bug fixes. } { 2000/01/04 1.12 Added InsensitiveCharSet. } { 2000/01/08 1.13 Added Append. } { 2000/05/08 1.14 Revision. } { 2000/07/20 1.15 Bug fixes. } { 2000/08/30 1.16 Bug fixes. } { 2000/09/04 1.17 Added MatchFileMask. } { 2000/09/31 1.18 Added HexEscapeText and HexUnescapeText. } { 2000/12/04 1.19 Changes to CopyRange, CopyLeft to avoid memory } { allocation in specific cases. } { 2001/04/22 1.20 Added CaseSensitive parameter to Match, PosNext, PosN } { 2001/04/25 1.21 Added CopyEx, MatchLeft and MatchRight. } { 2001/04/28 1.22 Refactoring. } { Replaced PosNext and PosPrev with Pos. } { 2001/04/29 1.23 Improvements. } { 2001/05/13 1.24 Added simple regular expression matching. } { Added CharClassStr conversion routines. } { 2001/06/01 1.25 Added TQuickLexer } { 2001/07/07 1.26 Optimizations. } { 2001/07/30 1.27 Revision. } { 2001/08/22 1.28 Revision. } { 2001/11/11 2.29 Revision. } { 2002/02/14 2.30 Added MatchPattern. } { 2002/04/03 3.31 Added string functions from cUtils. } { 2002/04/14 3.32 Moved TQuickLexer to unit cQuickLexer. } { 2002/12/14 3.33 Major revision. Removed rarely used functions. } { 2003/07/28 3.34 Minor changes. } { 2003/08/04 3.35 Changed parameters of StrMatch functions to be } { consistent with other string functions. } { Changed StrCompare functions to return integer result. } { 2003/09/06 3.36 Removed dependancy on Delphi's Math and Variant units. } { This saves about 25K when used in a DLL. } { 2003/11/07 3.37 Compilable with FreePascal 1.90 Win32 i386. } { 2004/07/31 3.38 Improved StrReplace function to efficiently handle } { cases where millions of matches are found. } { 2004/08/01 3.39 Added ToLongWord conversion functions. } { 2005/06/10 4.40 Compilable with FreePascal 2 Win32 i386. } { 2005/09/20 4.41 Added TStringBuilder class. } { 2005/09/21 4.42 Revised for Fundamentals 4. } { 2007/06/08 4.43 Compilable with FreePascal 2.0.4 Win32 i386 } { 2008/08/18 4.44 StrP functions; added Str prefix to some functions. } { 2009/01/04 4.45 Added AsciiChar and AsciiString. } { Initial update for Delphi 2009. } { 2009/10/09 4.46 Compilable with Delphi 2009 Win32/.NET. } { 2010/06/27 4.47 Compilable with FreePascal 2.4.0 OSX x86-64 } { 2011/03/17 4.48 Compilable with Delphi 5. } { 2011/05/28 4.49 Fix in TWideStringBuilder. } { 2011/06/14 4.50 Added Append(BufPtr) method to TStringBuilder. } { 2011/09/30 4.51 Improved UnicodeString support. } { 2011/10/17 4.52 WideString functions. } { 2012/03/26 4.53 Add A and W string functions. } { 2012/08/24 4.54 Improvements to StrZ functions. } { 2012/08/25 4.55 Add U string functions. } { 2012/08/28 4.56 Add Unicode character functions from cUnicode. } { 2012/08/29 4.57 Improve pattern matcher functions. } { 2013/05/12 4.58 Move string type definitions to Utils unit. } { 2014/08/26 4.59 StringBuilder unit tests. } { 2015/03/13 4.60 RawByteString functions. } { 2015/04/11 4.61 UnicodeString functions. } { 2016/01/09 5.62 Revised for Fundamentals 5. } { 2016/04/13 5.63 Change pattern match functions to RawByteString. } { 2016/04/16 5.64 Changes to compile with FreePascal 3.0.0. } { 2017/10/07 5.65 Created units flcStringPatternMatcher, flcStringBuilder } { 2017/10/24 5.66 Created units flcUnicodeChar, flcZeroTerminatedString } { 2018/07/17 5.67 Type changes. } { 2018/08/11 5.68 Created unit flcUnicodeString. } { 2018/08/11 5.69 Removed dependency on flcCharSet. } { 2018/08/12 5.70 Removed WideString functions and CLR code. } { 2018/08/14 5.71 ByteChar changes. } { } { Supported compilers: } { } { Delphi 2010-10.4 Win32/Win64 5.71 2020/06/02 } { Delphi 10.2-10.4 Linux64 5.71 2020/06/02 } { FreePascal 3.0.4 Win64 5.71 2020/06/02 } { } {******************************************************************************} {$INCLUDE ..\flcInclude.inc} {$IFDEF FREEPASCAL} {$WARNINGS OFF} {$HINTS OFF} {$ENDIF} {$IFDEF DEBUG} {$IFDEF TEST} {$DEFINE STRINGS_TEST} {$ENDIF} {$ENDIF} unit flcStrings; interface uses { System } SysUtils, { Fundamentals } flcStdTypes; { } { Exceptions } { } type EStringError = class(Exception); EStrInvalidArgument = class(EStringError); { } { ByteChar constants } { } const { Common characters } chTab = ByteChar(#9); chSpace = ByteChar(#32); chDecimalPoint = ByteChar('.'); chComma = ByteChar(','); chBackSlash = ByteChar('\'); chForwardSlash = ByteChar('/'); chPercent = ByteChar('%'); chAmpersand = ByteChar('&'); chPlus = ByteChar('+'); chMinus = ByteChar('-'); chEqual = ByteChar('='); chLessThan = ByteChar('<'); chGreaterThan = ByteChar('>'); chSingleQuote = ByteChar(''''); chDoubleQuote = ByteChar('"'); chExclamation = ByteChar('!'); chHash = ByteChar('#'); chDollar = ByteChar('$'); chCaret = ByteChar('^'); chAsterisk = ByteChar('*'); { Common sequences } CRLF = ByteChar(#13) + ByteChar(#10); LFCR = ByteChar(#10) + ByteChar(#13); DosNewLine = CRLF; UnixNewLine = ByteChar(#10); { Character sets } csComplete = [ByteChar(#0)..ByteChar(#255)]; csAnsi = [ByteChar(#0)..ByteChar(#255)]; csAscii = [ByteChar(#0)..ByteChar(#127)]; csNotAscii = csComplete - csAscii; csAsciiCtl = [ByteChar(#0)..ByteChar(#31)]; csAsciiText = [ByteChar(#32)..ByteChar(#127)]; csAlphaLow = [ByteChar('a')..ByteChar('z')]; csAlphaUp = [ByteChar('A')..ByteChar('Z')]; csAlpha = csAlphaLow + csAlphaUp; csNotAlpha = csComplete - csAlpha; csNumeric = [ByteChar('0')..ByteChar('9')]; csNotNumeric = csComplete - csNumeric; csAlphaNumeric = csNumeric + csAlpha; csNotAlphaNumeric = csComplete - csAlphaNumeric; csWhiteSpace = csAsciiCtl + [ByteChar(#32)]; csSign = [chPlus, chMinus]; csExponent = [ByteChar('E'), ByteChar('e')]; csBinaryDigit = [ByteChar('0')..ByteChar('1')]; csOctalDigit = [ByteChar('0')..ByteChar('7')]; csHexDigitLow = csNumeric + [ByteChar('a')..ByteChar('f')]; csHexDigitUp = csNumeric + [ByteChar('A')..ByteChar('F')]; csHexDigit = csNumeric + [ByteChar('A')..ByteChar('F'), ByteChar('a')..ByteChar('f')]; csQuotes = [chSingleQuote, chDoubleQuote]; csParentheses = [ByteChar('('), ByteChar(')')]; csCurlyBrackets = [ByteChar('{'), ByteChar('}')]; csBlockBrackets = [ByteChar('['), ByteChar(']')]; csPunctuation = [ByteChar('.'), ByteChar(','), ByteChar(':'), ByteChar('/'), ByteChar('?'), ByteChar('<'), ByteChar('>'), ByteChar(';'), ByteChar('"'), ByteChar(''''), ByteChar('['), ByteChar(']'), ByteChar('{'), ByteChar('}'), ByteChar('+'), ByteChar('='), ByteChar('-'), ByteChar('\'), ByteChar('('), ByteChar(')'), ByteChar('*'), ByteChar('&'), ByteChar('^'), ByteChar('%'), ByteChar('$'), ByteChar('#'), ByteChar('@'), ByteChar('!'), ByteChar('`'), ByteChar('~')]; csSlash = [chBackSlash, chForwardSlash]; { } { UCS4 constants } { } const Ucs4NULL = UCS4Char(0); Ucs4HT = UCS4Char(9); Ucs4LF = UCS4Char(10); Ucs4CR = UCS4Char(13); Ucs4StringTerminator = UCS4Char($9C); { } { String functions } { } {$IFDEF SupportAnsiString} procedure SetLengthAndZeroA(var S: AnsiString; const NewLength: Integer); {$ENDIF} procedure SetLengthAndZeroB(var S: RawByteString; const NewLength: Integer); procedure SetLengthAndZeroU(var S: UnicodeString; const NewLength: Integer); function ToStringChB(const A: ByteChar): String; {$IFDEF UseInline}inline;{$ENDIF} function ToStringChW(const A: WideChar): String; {$IFDEF UseInline}inline;{$ENDIF} {$IFDEF SupportAnsiString} function ToStringA(const A: AnsiString): String; {$IFDEF UseInline}inline;{$ENDIF} {$ENDIF} function ToStringB(const A: RawByteString): String; {$IFDEF UseInline}inline;{$ENDIF} function ToStringU(const A: UnicodeString): String; {$IFDEF UseInline}inline;{$ENDIF} { } { Match } { } function CharMatchNoAsciiCaseB(const A, B: ByteChar): Boolean; function CharMatchNoAsciiCaseW(const A, B: WideChar): Boolean; function CharMatchNoAsciiCaseBW(const A: ByteChar; const B: WideChar): Boolean; function CharMatchNoAsciiCaseBS(const A: ByteChar; const B: Char): Boolean; function CharMatchNoAsciiCase(const A, B: Char): Boolean; function CharMatchB(const A, B: ByteChar; const AsciiCaseSensitive: Boolean = True): Boolean; function CharMatchW(const A, B: WideChar; const AsciiCaseSensitive: Boolean = True): Boolean; function CharMatchBW(const A: ByteChar; const B: WideChar; const AsciiCaseSensitive: Boolean = True): Boolean; function CharMatchBS(const A: ByteChar; const B: Char; const AsciiCaseSensitive: Boolean = True): Boolean; function CharMatch(const A, B: Char; const AsciiCaseSensitive: Boolean = True): Boolean; function CharSetMatchCharB(const A: ByteCharSet; const B: ByteChar; const AsciiCaseSensitive: Boolean = True): Boolean; function CharSetMatchCharW(const A: ByteCharSet; const B: WideChar; const AsciiCaseSensitive: Boolean = True): Boolean; function CharSetMatchChar(const A: ByteCharSet; const B: Char; const AsciiCaseSensitive: Boolean = True): Boolean; function StrPMatchB(const A, B: PByteChar; const Len: Integer): Boolean; overload; function StrPMatchW(const A, B: PWideChar; const Len: Integer): Boolean; overload; function StrPMatchBW(const A: PWideChar; B: PByteChar; const Len: Integer): Boolean; overload; function StrPMatchBS(const A: PChar; B: PByteChar; const Len: Integer): Boolean; overload; function StrPMatch(const A, B: PChar; const Len: Integer): Boolean; overload; function StrPMatchB(const S, M: PByteChar; const LenS, LenM: Integer): Boolean; overload; function StrPMatchW(const S, M: PWideChar; const LenS, LenM: Integer): Boolean; overload; function StrPMatchBW(const S: PWideChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; overload; function StrPMatchBS(const S: PChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; overload; function StrPMatch(const S, M: PChar; const LenS, LenM: Integer): Boolean; overload; function StrPMatchStrPB(const S: PChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; {$IFDEF SupportAnsiString} function StrPMatchStrA(const S: PAnsiChar; const Len: Integer; const M: AnsiString): Boolean; {$ENDIF} function StrPMatchStrB(const S: PByteChar; const Len: Integer; const M: RawByteString): Boolean; {$IFDEF SupportAnsiString} function StrPMatchStrAW(const S: PWideChar; const Len: Integer; const M: AnsiString): Boolean; function StrPMatchStrAS(const S: PChar; const Len: Integer; const M: AnsiString): Boolean; {$ENDIF} function StrPMatchStrU(const S: PWideChar; const Len: Integer; const M: UnicodeString): Boolean; function StrPMatchStr(const S: PChar; const Len: Integer; const M: String): Boolean; function StrPMatchNoAsciiCaseB(const A, B: PByteChar; const Len: Integer): Boolean; function StrPMatchNoAsciiCaseW(const A, B: PWideChar; const Len: Integer): Boolean; function StrPMatchNoAsciiCaseBW(const A: PWideChar; const B: PByteChar; const Len: Integer): Boolean; function StrPMatchNoAsciiCaseBS(const A: PChar; const B: PByteChar; const Len: Integer): Boolean; function StrPMatchNoAsciiCase(const A, B: PChar; const Len: Integer): Boolean; function StrPMatchLenB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Integer; function StrPMatchLenW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Integer; overload; function StrPMatchLenW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Integer; overload; function StrPMatchLen(const P: PChar; const Len: Integer; const M: ByteCharSet): Integer; function StrPMatchCountB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Integer; function StrPMatchCountW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Integer; overload; function StrPMatchCountW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Integer; overload; function StrPMatchCharB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Boolean; function StrPMatchCharW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Boolean; overload; function StrPMatchCharW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Boolean; overload; function StrPMatchChar(const P: PChar; const Len: Integer; const M: ByteCharSet): Boolean; {$IFDEF SupportAnsiString} function StrMatchA(const S, M: AnsiString; const Index: Integer = 1): Boolean; {$ENDIF} function StrMatchB(const S, M: RawByteString; const Index: Integer = 1): Boolean; function StrMatchU(const S, M: UnicodeString; const Index: Integer = 1): Boolean; {$IFDEF SupportAnsiString} function StrMatchAU(const S: UnicodeString; const M: AnsiString; const Index: Integer = 1): Boolean; {$ENDIF} function StrMatchBU(const S: UnicodeString; const M: RawByteString; const Index: Integer = 1): Boolean; {$IFDEF SupportAnsiString} function StrMatchAS(const S: String; const M: AnsiString; const Index: Integer = 1): Boolean; {$ENDIF} function StrMatch(const S, M: String; const Index: Integer = 1): Boolean; {$IFDEF SupportAnsiString} function StrMatchNoAsciiCaseA(const S, M: AnsiString; const Index: Integer = 1): Boolean; {$ENDIF} function StrMatchNoAsciiCaseB(const S, M: RawByteString; const Index: Integer = 1): Boolean; function StrMatchNoAsciiCaseU(const S, M: UnicodeString; const Index: Integer = 1): Boolean; {$IFDEF SupportAnsiString} function StrMatchNoAsciiCaseAU(const S: UnicodeString; const M: AnsiString; const Index: Integer = 1): Boolean; function StrMatchNoAsciiCaseAS(const S: String; const M: AnsiString; const Index: Integer = 1): Boolean; {$ENDIF} function StrMatchNoAsciiCaseBU(const S: UnicodeString; const M: RawByteString; const Index: Integer = 1): Boolean; function StrMatchNoAsciiCase(const S, M: String; const Index: Integer = 1): Boolean; {$IFDEF SupportAnsiString} function StrMatchLeftA(const S, M: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrMatchLeftB(const S, M: RawByteString; const AsciiCaseSensitive: Boolean = True): Boolean; function StrMatchLeftU(const S, M: UnicodeString; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrMatchLeftAU(const S: UnicodeString; const M: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrMatchLeftBU(const S: UnicodeString; const M: RawByteString; const AsciiCaseSensitive: Boolean = True): Boolean; function StrMatchLeft(const S, M: String; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrMatchRightA(const S, M: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrMatchRightB(const S, M: RawByteString; const AsciiCaseSensitive: Boolean = True): Boolean; function StrMatchRightU(const S, M: UnicodeString; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrMatchRightAU(const S: UnicodeString; const M: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrMatchRight(const S, M: String; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrMatchLenA(const S: AnsiString; const M: ByteCharSet; const Index: Integer = 1): Integer; {$ENDIF} function StrMatchLenB(const S: RawByteString; const M: ByteCharSet; const Index: Integer = 1): Integer; function StrMatchLenU(const S: UnicodeString; const M: ByteCharSet; const Index: Integer = 1): Integer; overload; function StrMatchLenU(const S: UnicodeString; const M: TWideCharMatchFunction; const Index: Integer = 1): Integer; overload; function StrMatchLen(const S: String; const M: ByteCharSet; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function StrMatchCharA(const S: AnsiString; const M: ByteCharSet): Boolean; {$ENDIF} function StrMatchCharB(const S: RawByteString; const M: ByteCharSet): Boolean; function StrMatchCharU(const S: UnicodeString; const M: ByteCharSet): Boolean; overload; function StrMatchCharU(const S: UnicodeString; const M: TWideCharMatchFunction): Boolean; overload; function StrMatchChar(const S: String; const M: ByteCharSet): Boolean; { } { Equal } { } function StrPEqual(const P1, P2: PByteChar; const Len1, Len2: Integer; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrPEqualStr(const P: PAnsiChar; const Len: Integer; const S: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} {$IFDEF SupportAnsiString} function StrEqualA(const A, B: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrEqualB(const A, B: RawByteString; const AsciiCaseSensitive: Boolean = True): Boolean; function StrEqualU(const A, B: UnicodeString; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrEqualAU(const A: UnicodeString; const B: AnsiString; const AsciiCaseSensitive: Boolean = True): Boolean; {$ENDIF} function StrEqualBU(const A: UnicodeString; const B: RawByteString; const AsciiCaseSensitive: Boolean = True): Boolean; function StrEqual(const A, B: String; const AsciiCaseSensitive: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrEqualNoAsciiCaseA(const A, B: AnsiString): Boolean; {$ENDIF} function StrEqualNoAsciiCaseB(const A, B: RawByteString): Boolean; function StrEqualNoAsciiCaseU(const A, B: UnicodeString): Boolean; function StrEqualNoAsciiCaseBU(const A: UnicodeString; const B: RawByteString): Boolean; function StrEqualNoAsciiCase(const A, B: String): Boolean; { } { Validation } { } {$IFDEF SupportAnsiString} function StrIsNumericA(const S: AnsiString): Boolean; {$ENDIF} function StrIsNumericB(const S: RawByteString): Boolean; function StrIsNumericU(const S: UnicodeString): Boolean; function StrIsNumeric(const S: String): Boolean; {$IFDEF SupportAnsiString} function StrIsHexA(const S: AnsiString): Boolean; {$ENDIF} function StrIsHexB(const S: RawByteString): Boolean; function StrIsHexU(const S: UnicodeString): Boolean; function StrIsHex(const S: String): Boolean; {$IFDEF SupportAnsiString} function StrIsAlphaA(const S: AnsiString): Boolean; {$ENDIF} function StrIsAlphaB(const S: RawByteString): Boolean; function StrIsAlphaU(const S: UnicodeString): Boolean; function StrIsAlpha(const S: String): Boolean; {$IFDEF SupportAnsiString} function StrIsAlphaNumericA(const S: AnsiString): Boolean; {$ENDIF} function StrIsAlphaNumericB(const S: RawByteString): Boolean; function StrIsAlphaNumericU(const S: UnicodeString): Boolean; function StrIsAlphaNumeric(const S: String): Boolean; {$IFDEF SupportAnsiString} function StrIsIntegerA(const S: AnsiString): Boolean; {$ENDIF} function StrIsIntegerB(const S: RawByteString): Boolean; function StrIsIntegerU(const S: UnicodeString): Boolean; function StrIsInteger(const S: String): Boolean; { } { Pos } { } function StrPPosCharB(const F: ByteChar; const S: PByteChar; const Len: Integer): Integer; function StrPPosCharW(const F: WideChar; const S: PWideChar; const Len: Integer): Integer; function StrPPosCharSetB(const F: ByteCharSet; const S: PByteChar; const Len: Integer): Integer; function StrPPosCharSetW(const F: ByteCharSet; const S: PWideChar; const Len: Integer): Integer; function StrPPosB(const F, S: PByteChar; const LenF, LenS: Integer): Integer; function StrPPosW(const F, S: PWideChar; const LenF, LenS: Integer): Integer; {$IFDEF SupportAnsiString} function StrPPosStrA(const F: AnsiString; const S: PAnsiChar; const Len: Integer): Integer; {$ENDIF} function StrPPosStrB(const F: RawByteString; const S: PByteChar; const Len: Integer): Integer; {$IFDEF SupportAnsiString} function PosCharA(const F: AnsiChar; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosCharB(const F: ByteChar; const S: RawByteString; const Index: Integer = 1): Integer; function PosCharU(const F: WideChar; const S: UnicodeString; const Index: Integer = 1): Integer; function PosChar(const F: Char; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosCharSetA(const F: ByteCharSet; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosCharSetB(const F: ByteCharSet; const S: RawByteString; const Index: Integer = 1): Integer; function PosCharSetU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosCharSetU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosCharSet(const F: ByteCharSet; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosNotCharA(const F: AnsiChar; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosNotCharB(const F: ByteChar; const S: RawByteString; const Index: Integer = 1): Integer; function PosNotCharU(const F: WideChar; const S: UnicodeString; const Index: Integer = 1): Integer; function PosNotChar(const F: Char; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosNotCharSetA(const F: ByteCharSet; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosNotCharSetB(const F: ByteCharSet; const S: RawByteString; const Index: Integer = 1): Integer; function PosNotCharSetU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosNotCharSetU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosNotCharSet(const F: ByteCharSet; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosCharRevA(const F: AnsiChar; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosCharRevB(const F: ByteChar; const S: RawByteString; const Index: Integer = 1): Integer; function PosCharRevU(const F: WideChar; const S: UnicodeString; const Index: Integer = 1): Integer; function PosCharRev(const F: Char; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosCharSetRevA(const F: ByteCharSet; const S: AnsiString; const Index: Integer = 1): Integer; {$ENDIF} function PosCharSetRevB(const F: ByteCharSet; const S: RawByteString; const Index: Integer = 1): Integer; function PosCharSetRevU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosCharSetRevU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer = 1): Integer; overload; function PosCharSetRev(const F: ByteCharSet; const S: String; const Index: Integer = 1): Integer; {$IFDEF SupportAnsiString} function PosStrA(const F, S: AnsiString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$ENDIF} function PosStrB(const F, S: RawByteString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosStrU(const F, S: UnicodeString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$IFDEF SupportAnsiString} function PosStrAU(const F: AnsiString; const S: UnicodeString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$ENDIF} function PosStr(const F, S: String; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$IFDEF SupportAnsiString} function PosStrRevA(const F, S: AnsiString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$ENDIF} function PosStrRevB(const F, S: RawByteString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosStrRevU(const F, S: UnicodeString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosStrRev(const F, S: String; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$IFDEF SupportAnsiString} function PosStrRevIdxA(const F, S: AnsiString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$ENDIF} function PosStrRevIdxB(const F, S: RawByteString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosStrRevIdxU(const F, S: UnicodeString; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosStrRevIdx(const F, S: String; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$IFDEF SupportAnsiString} function PosNStrA(const F, S: AnsiString; const N: Integer; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; {$ENDIF} function PosNStrB(const F, S: RawByteString; const N: Integer; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosNStrU(const F, S: UnicodeString; const N: Integer; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; function PosNStr(const F, S: String; const N: Integer; const Index: Integer = 1; const AsciiCaseSensitive: Boolean = True): Integer; { } { Copy } { } { Out-of-range values of StartIndex, StopIndex and Count are clipped. } { These variants return a reference to the existing string if possible. } { } {$IFDEF SupportAnsiString} function CopyRangeA(const S: AnsiString; const StartIndex, StopIndex: Integer): AnsiString; {$ENDIF} function CopyRangeB(const S: RawByteString; const StartIndex, StopIndex: Integer): RawByteString; function CopyRangeU(const S: UnicodeString; const StartIndex, StopIndex: Integer): UnicodeString; function CopyRange(const S: String; const StartIndex, StopIndex: Integer): String; {$IFDEF SupportAnsiString} function CopyFromA(const S: AnsiString; const Index: Integer): AnsiString; {$ENDIF} function CopyFromB(const S: RawByteString; const Index: Integer): RawByteString; function CopyFromU(const S: UnicodeString; const Index: Integer): UnicodeString; function CopyFrom(const S: String; const Index: Integer): String; {$IFDEF SupportAnsiString} function CopyLeftA(const S: AnsiString; const Count: Integer): AnsiString; {$ENDIF} function CopyLeftB(const S: RawByteString; const Count: Integer): RawByteString; function CopyLeftU(const S: UnicodeString; const Count: Integer): UnicodeString; function CopyLeft(const S: String; const Count: Integer): String; {$IFDEF SupportAnsiString} function CopyRightA(const S: AnsiString; const Count: Integer): AnsiString; {$ENDIF} function CopyRightB(const S: RawByteString; const Count: Integer): RawByteString; function CopyRightU(const S: UnicodeString; const Count: Integer): UnicodeString; function CopyRight(const S: String; const Count: Integer): String; {$IFDEF SupportAnsiString} function CopyLeftEllipsedA(const S: AnsiString; const Count: Integer): AnsiString; {$ENDIF} function CopyLeftEllipsedU(const S: UnicodeString; const Count: Integer): UnicodeString; { } { CopyEx } { } { CopyEx functions extend Copy so that negative Start/Stop values reference } { indexes from the end of the string, eg. -2 will reference the second last } { character in the string. } { } {$IFDEF SupportAnsiString} function CopyExA(const S: AnsiString; const Start, Count: Integer): AnsiString; {$ENDIF} function CopyExB(const S: RawByteString; const Start, Count: Integer): RawByteString; function CopyExW(const S: String; const Start, Count: Integer): String; function CopyExU(const S: UnicodeString; const Start, Count: Integer): UnicodeString; function CopyEx(const S: String; const Start, Count: Integer): String; {$IFDEF SupportAnsiString} function CopyRangeExA(const S: AnsiString; const Start, Stop: Integer): AnsiString; {$ENDIF} function CopyRangeExB(const S: RawByteString; const Start, Stop: Integer): RawByteString; function CopyRangeExU(const S: UnicodeString; const Start, Stop: Integer): UnicodeString; function CopyRangeEx(const S: String; const Start, Stop: Integer): String; {$IFDEF SupportAnsiString} function CopyFromExA(const S: AnsiString; const Start: Integer): AnsiString; function CopyFromExB(const S: RawByteString; const Start: Integer): RawByteString; {$ENDIF} function CopyFromExU(const S: UnicodeString; const Start: Integer): UnicodeString; function CopyFromEx(const S: String; const Start: Integer): String; { } { Trim } { } {$IFDEF SupportAnsiString} function StrTrimLeftA(const S: AnsiString; const C: ByteCharSet = csWhiteSpace): AnsiString; {$ENDIF} function StrTrimLeftB(const S: RawByteString; const C: ByteCharSet = csWhiteSpace): RawByteString; function StrTrimLeftU(const S: UnicodeString; const C: ByteCharSet = csWhiteSpace): UnicodeString; overload; function StrTrimLeftU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; overload; function StrTrimLeft(const S: String; const C: ByteCharSet = csWhiteSpace): String; {$IFDEF SupportAnsiString} procedure StrTrimLeftInPlaceA(var S: AnsiString; const C: ByteCharSet = csWhiteSpace); {$ENDIF} procedure StrTrimLeftInPlaceB(var S: RawByteString; const C: ByteCharSet = csWhiteSpace); procedure StrTrimLeftInPlaceU(var S: UnicodeString; const C: ByteCharSet = csWhiteSpace); overload; procedure StrTrimLeftInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); overload; procedure StrTrimLeftInPlace(var S: String; const C: ByteCharSet = csWhiteSpace); {$IFDEF SupportAnsiString} function StrTrimLeftStrNoCaseA(const S: AnsiString; const TrimStr: AnsiString): AnsiString; {$ENDIF} function StrTrimLeftStrNoCaseB(const S: RawByteString; const TrimStr: RawByteString): RawByteString; function StrTrimLeftStrNoCaseU(const S: UnicodeString; const TrimStr: UnicodeString): UnicodeString; function StrTrimLeftStrNoCase(const S: String; const TrimStr: String): String; {$IFDEF SupportAnsiString} function StrTrimRightA(const S: AnsiString; const C: ByteCharSet = csWhiteSpace): AnsiString; {$ENDIF} function StrTrimRightB(const S: RawByteString; const C: ByteCharSet = csWhiteSpace): RawByteString; function StrTrimRightU(const S: UnicodeString; const C: ByteCharSet = csWhiteSpace): UnicodeString; overload; function StrTrimRightU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; overload; function StrTrimRight(const S: String; const C: ByteCharSet = csWhiteSpace): String; {$IFDEF SupportAnsiString} procedure StrTrimRightInPlaceA(var S: AnsiString; const C: ByteCharSet = csWhiteSpace); {$ENDIF} procedure StrTrimRightInPlaceB(var S: RawByteString; const C: ByteCharSet = csWhiteSpace); procedure StrTrimRightInPlaceU(var S: UnicodeString; const C: ByteCharSet = csWhiteSpace); overload; procedure StrTrimRightInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); overload; procedure StrTrimRightInPlace(var S: String; const C: ByteCharSet = csWhiteSpace); {$IFDEF SupportAnsiString} function StrTrimRightStrNoCaseA(const S: AnsiString; const TrimStr: AnsiString): AnsiString; {$ENDIF} function StrTrimRightStrNoCaseB(const S: RawByteString; const TrimStr: RawByteString): RawByteString; function StrTrimRightStrNoCaseU(const S: UnicodeString; const TrimStr: UnicodeString): UnicodeString; function StrTrimRightStrNoCase(const S: String; const TrimStr: String): String; {$IFDEF SupportAnsiString} function StrTrimA(const S: AnsiString; const C: ByteCharSet = csWhiteSpace): AnsiString; {$ENDIF} function StrTrimB(const S: RawByteString; const C: ByteCharSet = csWhiteSpace): RawByteString; function StrTrimU(const S: UnicodeString; const C: ByteCharSet = csWhiteSpace): UnicodeString; overload; function StrTrimU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; overload; function StrTrim(const S: String; const C: ByteCharSet): String; overload; {$IFDEF SupportAnsiString} procedure StrTrimInPlaceA(var S: AnsiString; const C: ByteCharSet = csWhiteSpace); {$ENDIF} procedure StrTrimInPlaceB(var S: RawByteString; const C: ByteCharSet = csWhiteSpace); procedure StrTrimInPlaceU(var S: UnicodeString; const C: ByteCharSet = csWhiteSpace); overload; procedure StrTrimInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); overload; procedure StrTrimInPlace(var S: String; const C: ByteCharSet = csWhiteSpace); {$IFDEF SupportAnsiString} procedure TrimStringsA(var S: AnsiStringArray; const C: ByteCharSet = csWhiteSpace); overload; {$ENDIF} procedure TrimStringsB(var S: RawByteStringArray; const C: ByteCharSet = csWhiteSpace); overload; procedure TrimStringsU(var S: UnicodeStringArray; const C: ByteCharSet = csWhiteSpace); overload; procedure TrimStrings(var S: StringArray; const C: ByteCharSet = csWhiteSpace); { } { Duplicate } { } {$IFDEF SupportAnsiString} function BufToStrA(const Buf; const BufSize: Integer): AnsiString; {$ENDIF} function BufToStrB(const Buf; const BufSize: Integer): RawByteString; function BufToStrU(const Buf; const BufSize: Integer): UnicodeString; function BufToStr(const Buf; const BufSize: Integer): String; {$IFDEF SupportAnsiString} function DupBufA(const Buf; const BufSize: Integer; const Count: Integer): AnsiString; {$ENDIF} function DupBufB(const Buf; const BufSize: Integer; const Count: Integer): RawByteString; function DupBufU(const Buf; const BufSize: Integer; const Count: Integer): UnicodeString; function DupBuf(const Buf; const BufSize: Integer; const Count: Integer): String; {$IFDEF SupportAnsiString} function DupStrA(const S: AnsiString; const Count: Integer): AnsiString; {$ENDIF} function DupStrB(const S: RawByteString; const Count: Integer): RawByteString; function DupStrU(const S: UnicodeString; const Count: Integer): UnicodeString; function DupStr(const S: String; const Count: Integer): String; {$IFDEF SupportAnsiString} function DupCharA(const Ch: AnsiChar; const Count: Integer): AnsiString; {$ENDIF} function DupCharB(const Ch: ByteChar; const Count: Integer): RawByteString; function DupCharU(const Ch: WideChar; const Count: Integer): UnicodeString; function DupChar(const Ch: Char; const Count: Integer): String; {$IFDEF SupportAnsiString} function DupSpaceA(const Count: Integer): AnsiString; {$ENDIF} function DupSpaceB(const Count: Integer): RawByteString; function DupSpaceU(const Count: Integer): UnicodeString; function DupSpace(const Count: Integer): String; { } { Pad } { } {$IFDEF SupportAnsiString} function StrPadA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean = False): AnsiString; {$ENDIF} function StrPadB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean = False): RawByteString; function StrPadU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean = False): UnicodeString; function StrPad(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean = False): String; {$IFDEF SupportAnsiString} function StrPadLeftA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean = False): AnsiString; {$ENDIF} function StrPadLeftB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean = False): RawByteString; function StrPadLeftU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean = False): UnicodeString; function StrPadLeft(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean = False): String; {$IFDEF SupportAnsiString} function StrPadRightA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean = False): AnsiString; {$ENDIF} function StrPadRightB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean = False): RawByteString; function StrPadRightU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean = False): UnicodeString; function StrPadRight(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean = False): String; { } { Delimited } { } {$IFDEF SupportAnsiString} function StrBetweenCharA(const S: AnsiString; const FirstDelim, SecondDelim: AnsiChar; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): AnsiString; overload; function StrBetweenCharA(const S: AnsiString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): AnsiString; overload; function StrBetweenCharB(const S: RawByteString; const FirstDelim, SecondDelim: ByteChar; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): RawByteString; overload; function StrBetweenCharB(const S: RawByteString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): RawByteString; overload; {$ENDIF} function StrBetweenCharU(const S: UnicodeString; const FirstDelim, SecondDelim: WideChar; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): UnicodeString; overload; function StrBetweenCharU(const S: UnicodeString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): UnicodeString; overload; function StrBetweenChar(const S: String; const FirstDelim, SecondDelim: Char; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): String; overload; function StrBetweenChar(const S: String; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False): String; overload; {$IFDEF SupportAnsiString} function StrBetweenA(const S: AnsiString; const FirstDelim: AnsiString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True): AnsiString; overload; function StrBetweenA(const S: AnsiString; const FirstDelim, SecondDelim: AnsiString; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True; const SecondDelimAsciiCaseSensitive: Boolean = True): AnsiString; overload; function StrBetweenB(const S: RawByteString; const FirstDelim: RawByteString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True): RawByteString; overload; function StrBetweenB(const S: RawByteString; const FirstDelim, SecondDelim: RawByteString; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True; const SecondDelimAsciiCaseSensitive: Boolean = True): RawByteString; overload; {$ENDIF} function StrBetweenU(const S: UnicodeString; const FirstDelim: UnicodeString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True): UnicodeString; overload; function StrBetweenU(const S: UnicodeString; const FirstDelim, SecondDelim: UnicodeString; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True; const SecondDelimAsciiCaseSensitive: Boolean = True): UnicodeString; overload; function StrBetween(const S: String; const FirstDelim: String; const SecondDelim: ByteCharSet; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True): String; overload; function StrBetween(const S: String; const FirstDelim, SecondDelim: String; const FirstOptional: Boolean = False; const SecondOptional: Boolean = False; const FirstDelimAsciiCaseSensitive: Boolean = True; const SecondDelimAsciiCaseSensitive: Boolean = True): String; overload; {$IFDEF SupportAnsiString} function StrBeforeA(const S, D: AnsiString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): AnsiString; function StrBeforeRevA(const S, D: AnsiString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): AnsiString; {$ENDIF} function StrBeforeB(const S, D: RawByteString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrBeforeRevB(const S, D: RawByteString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrBeforeU(const S, D: UnicodeString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrBeforeRevU(const S, D: UnicodeString; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrBefore(const S, D: String; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): String; function StrBeforeRev(const S, D: String; const Optional: Boolean = True; const AsciiCaseSensitive: Boolean = True): String; {$IFDEF SupportAnsiString} function StrBeforeCharA(const S: AnsiString; const D: AnsiChar; const Optional: Boolean = True): AnsiString; overload; function StrBeforeCharA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean = True): AnsiString; overload; function StrBeforeCharRevA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean = True): AnsiString; {$ENDIF} function StrBeforeCharB(const S: RawByteString; const D: ByteChar; const Optional: Boolean = True): RawByteString; overload; function StrBeforeCharB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean = True): RawByteString; overload; function StrBeforeCharRevB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean = True): RawByteString; function StrBeforeCharU(const S: UnicodeString; const D: WideChar; const Optional: Boolean = True): UnicodeString; overload; function StrBeforeCharU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean = True): UnicodeString; overload; function StrBeforeCharRevU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean = True): UnicodeString; function StrBeforeChar(const S: String; const D: Char; const Optional: Boolean = True): String; overload; function StrBeforeChar(const S: String; const D: ByteCharSet; const Optional: Boolean = True): String; overload; function StrBeforeCharRev(const S: String; const D: ByteCharSet; const Optional: Boolean = True): String; {$IFDEF SupportAnsiString} function StrAfterA(const S, D: AnsiString; const Optional: Boolean = False): AnsiString; function StrAfterRevA(const S, D: AnsiString; const Optional: Boolean = False): AnsiString; {$ENDIF} function StrAfterB(const S, D: RawByteString; const Optional: Boolean = False): RawByteString; function StrAfterRevB(const S, D: RawByteString; const Optional: Boolean = False): RawByteString; function StrAfterU(const S, D: UnicodeString; const Optional: Boolean = False): UnicodeString; function StrAfterRevU(const S, D: UnicodeString; const Optional: Boolean = False): UnicodeString; function StrAfter(const S, D: String; const Optional: Boolean = False): String; function StrAfterRev(const S, D: String; const Optional: Boolean = False): String; {$IFDEF SupportAnsiString} function StrAfterCharA(const S: AnsiString; const D: ByteCharSet): AnsiString; overload; function StrAfterCharA(const S: AnsiString; const D: AnsiChar): AnsiString; overload; {$ENDIF} function StrAfterCharB(const S: RawByteString; const D: ByteCharSet): RawByteString; overload; function StrAfterCharB(const S: RawByteString; const D: ByteChar): RawByteString; overload; function StrAfterCharU(const S: UnicodeString; const D: ByteCharSet): UnicodeString; overload; function StrAfterCharU(const S: UnicodeString; const D: WideChar): UnicodeString; overload; function StrAfterChar(const S: String; const D: ByteCharSet): String; overload; function StrAfterChar(const S: String; const D: Char): String; overload; {$IFDEF SupportAnsiString} function StrCopyToCharA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean = True): AnsiString; overload; function StrCopyToCharA(const S: AnsiString; const D: AnsiChar; const Optional: Boolean = True): AnsiString; overload; {$ENDIF} function StrCopyToCharB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean = True): RawByteString; overload; function StrCopyToCharB(const S: RawByteString; const D: ByteChar; const Optional: Boolean = True): RawByteString; overload; function StrCopyToCharU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean = True): UnicodeString; overload; function StrCopyToCharU(const S: UnicodeString; const D: WideChar; const Optional: Boolean = True): UnicodeString; overload; function StrCopyToChar(const S: String; const D: ByteCharSet; const Optional: Boolean = True): String; overload; function StrCopyToChar(const S: String; const D: Char; const Optional: Boolean = True): String; overload; {$IFDEF SupportAnsiString} function StrCopyFromCharA(const S: AnsiString; const D: ByteCharSet): AnsiString; overload; function StrCopyFromCharA(const S: AnsiString; const D: AnsiChar): AnsiString; overload; {$ENDIF} function StrCopyFromCharB(const S: RawByteString; const D: ByteCharSet): RawByteString; overload; function StrCopyFromCharB(const S: RawByteString; const D: ByteChar): RawByteString; overload; function StrCopyFromCharU(const S: UnicodeString; const D: ByteCharSet): UnicodeString; overload; function StrCopyFromCharU(const S: UnicodeString; const D: WideChar): UnicodeString; overload; function StrCopyFromChar(const S: String; const D: ByteCharSet): String; overload; function StrCopyFromChar(const S: String; const D: Char): String; overload; {$IFDEF SupportAnsiString} function StrRemoveCharDelimitedA(var S: AnsiString; const FirstDelim, SecondDelim: AnsiChar): AnsiString; {$ENDIF} function StrRemoveCharDelimitedB(var S: RawByteString; const FirstDelim, SecondDelim: ByteChar): RawByteString; function StrRemoveCharDelimitedU(var S: UnicodeString; const FirstDelim, SecondDelim: WideChar): UnicodeString; function StrRemoveCharDelimited(var S: String; const FirstDelim, SecondDelim: Char): String; { } { Count } { } {$IFDEF SupportAnsiString} function StrCountCharA(const S: AnsiString; const C: AnsiChar): Integer; overload; {$ENDIF} function StrCountCharB(const S: RawByteString; const C: ByteChar): Integer; overload; function StrCountCharU(const S: UnicodeString; const C: WideChar): Integer; overload; function StrCountChar(const S: String; const C: Char): Integer; overload; {$IFDEF SupportAnsiString} function StrCountCharA(const S: AnsiString; const C: ByteCharSet): Integer; overload; {$ENDIF} function StrCountCharB(const S: RawByteString; const C: ByteCharSet): Integer; overload; function StrCountCharU(const S: UnicodeString; const C: ByteCharSet): Integer; overload; function StrCountChar(const S: String; const C: ByteCharSet): Integer; overload; { } { Replace } { } {$IFDEF SupportAnsiString} function StrReplaceCharA(const Find, Replace: AnsiChar; const S: AnsiString): AnsiString; overload; {$ENDIF} function StrReplaceCharB(const Find, Replace: ByteChar; const S: RawByteString): RawByteString; overload; function StrReplaceCharU(const Find, Replace: WideChar; const S: UnicodeString): UnicodeString; overload; function StrReplaceChar(const Find, Replace: Char; const S: String): String; overload; {$IFDEF SupportAnsiString} function StrReplaceCharA(const Find: ByteCharSet; const Replace: AnsiChar; const S: AnsiString): AnsiString; overload; {$ENDIF} function StrReplaceCharB(const Find: ByteCharSet; const Replace: ByteChar; const S: RawByteString): RawByteString; overload; function StrReplaceCharU(const Find: ByteCharSet; const Replace: WideChar; const S: UnicodeString): UnicodeString; overload; function StrReplaceChar(const Find: ByteCharSet; const Replace: Char; const S: String): String; overload; {$IFDEF SupportAnsiString} function StrReplaceA(const Find, Replace, S: AnsiString; const AsciiCaseSensitive: Boolean = True): AnsiString; overload; {$ENDIF} function StrReplaceB(const Find, Replace, S: RawByteString; const AsciiCaseSensitive: Boolean = True): RawByteString; overload; function StrReplaceU(const Find, Replace, S: UnicodeString; const AsciiCaseSensitive: Boolean = True): UnicodeString; overload; function StrReplace(const Find, Replace, S: String; const AsciiCaseSensitive: Boolean = True): String; overload; {$IFDEF SupportAnsiString} function StrReplaceA(const Find: ByteCharSet; const Replace, S: AnsiString): AnsiString; overload; {$ENDIF} function StrReplaceB(const Find: ByteCharSet; const Replace, S: RawByteString): RawByteString; overload; function StrReplaceU(const Find: ByteCharSet; const Replace, S: UnicodeString): UnicodeString; overload; function StrReplace(const Find: ByteCharSet; const Replace, S: String): String; overload; {$IFDEF SupportAnsiString} function StrReplaceCharStrA(const Find: AnsiChar; const Replace, S: AnsiString): AnsiString; {$ENDIF} function StrReplaceCharStrU(const Find: WideChar; const Replace, S: UnicodeString): UnicodeString; {$IFDEF SupportAnsiString} function StrRemoveDupA(const S: AnsiString; const C: AnsiChar): AnsiString; {$ENDIF} function StrRemoveDupU(const S: UnicodeString; const C: WideChar): UnicodeString; function StrRemoveDup(const S: String; const C: Char): String; {$IFDEF SupportAnsiString} function StrRemoveCharA(const S: AnsiString; const C: AnsiChar): AnsiString; {$ENDIF} function StrRemoveCharU(const S: UnicodeString; const C: WideChar): UnicodeString; function StrRemoveChar(const S: String; const C: Char): String; {$IFDEF SupportAnsiString} function StrRemoveCharSetA(const S: AnsiString; const C: ByteCharSet): AnsiString; {$ENDIF} function StrRemoveCharSetB(const S: RawByteString; const C: ByteCharSet): RawByteString; function StrRemoveCharSetU(const S: UnicodeString; const C: ByteCharSet): UnicodeString; function StrRemoveCharSet(const S: String; const C: ByteCharSet): String; { } { Split } { } {$IFDEF SupportAnsiString} function StrSplitAtA(const S: AnsiString; const C: AnsiString; var Left, Right: AnsiString; const AsciiCaseSensitive: Boolean = True; const Optional: Boolean = True): Boolean; {$ENDIF} function StrSplitAtB(const S: RawByteString; const C: RawByteString; var Left, Right: RawByteString; const AsciiCaseSensitive: Boolean = True; const Optional: Boolean = True): Boolean; function StrSplitAtU(const S: UnicodeString; const C: UnicodeString; var Left, Right: UnicodeString; const AsciiCaseSensitive: Boolean = True; const Optional: Boolean = True): Boolean; function StrSplitAt(const S: String; const C: String; var Left, Right: String; const AsciiCaseSensitive: Boolean = True; const Optional: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrSplitAtCharA(const S: AnsiString; const C: AnsiChar; var Left, Right: AnsiString; const Optional: Boolean = True): Boolean; {$ENDIF} function StrSplitAtCharB(const S: RawByteString; const C: ByteChar; var Left, Right: RawByteString; const Optional: Boolean = True): Boolean; function StrSplitAtCharU(const S: UnicodeString; const C: WideChar; var Left, Right: UnicodeString; const Optional: Boolean = True): Boolean; function StrSplitAtChar(const S: String; const C: Char; var Left, Right: String; const Optional: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrSplitAtCharSetA(const S: AnsiString; const C: ByteCharSet; var Left, Right: AnsiString; const Optional: Boolean = True): Boolean; {$ENDIF} function StrSplitAtCharSetB(const S: RawByteString; const C: ByteCharSet; var Left, Right: RawByteString; const Optional: Boolean = True): Boolean; {$IFDEF SupportAnsiString} function StrSplitA(const S, D: AnsiString): AnsiStringArray; {$ENDIF} function StrSplitB(const S, D: RawByteString): RawByteStringArray; function StrSplitU(const S, D: UnicodeString): UnicodeStringArray; function StrSplit(const S, D: String): StringArray; {$IFDEF SupportAnsiString} function StrSplitCharA(const S: AnsiString; const D: AnsiChar): AnsiStringArray; {$ENDIF} function StrSplitCharB(const S: RawByteString; const D: ByteChar): RawByteStringArray; function StrSplitCharU(const S: UnicodeString; const D: WideChar): UnicodeStringArray; function StrSplitChar(const S: String; const D: Char): StringArray; {$IFDEF SupportAnsiString} function StrSplitCharSetA(const S: AnsiString; const D: ByteCharSet): AnsiStringArray; {$ENDIF} function StrSplitCharSetB(const S: RawByteString; const D: ByteCharSet): RawByteStringArray; function StrSplitCharSetU(const S: UnicodeString; const D: ByteCharSet): UnicodeStringArray; function StrSplitCharSet(const S: String; const D: ByteCharSet): StringArray; {$IFDEF SupportAnsiString} function StrSplitWords(const S: AnsiString; const C: ByteCharSet): AnsiStringArray; {$ENDIF} {$IFDEF SupportAnsiString} function StrJoinA(const S: array of AnsiString; const D: AnsiString): AnsiString; {$ENDIF} function StrJoinB(const S: array of RawByteString; const D: RawByteString): RawByteString; function StrJoinU(const S: array of UnicodeString; const D: UnicodeString): UnicodeString; function StrJoin(const S: array of String; const D: String): String; {$IFDEF SupportAnsiString} function StrJoinCharA(const S: array of AnsiString; const D: AnsiChar): AnsiString; {$ENDIF} function StrJoinCharB(const S: array of RawByteString; const D: ByteChar): RawByteString; function StrJoinCharU(const S: array of UnicodeString; const D: WideChar): UnicodeString; function StrJoinChar(const S: array of String; const D: Char): String; { } { Quoting } { } { QuoteText, UnquoteText converts text where the string is enclosed in a } { pair of the same quote characters, and two consequetive occurance of the } { quote character inside the quotes indicate a quote character in the text. } { Examples: } { } { StrQuote ('abc', '"') = '"abc"' } { StrQuote ('a"b"c', '"') = '"a""b""c"' } { StrUnquote ('"a""b""c"') = 'a"b"c' } { } {$IFDEF SupportAnsiString} function StrHasSurroundingQuotesA(const S: AnsiString; const Quotes: ByteCharSet = csQuotes): Boolean; function StrHasSurroundingQuotesB(const S: RawByteString; const Quotes: ByteCharSet = csQuotes): Boolean; {$ENDIF} function StrHasSurroundingQuotesU(const S: UnicodeString; const Quotes: ByteCharSet = csQuotes): Boolean; function StrHasSurroundingQuotes(const S: String; const Quotes: ByteCharSet = csQuotes): Boolean; {$IFDEF SupportAnsiString} function StrRemoveSurroundingQuotesA(const S: AnsiString; const Quotes: ByteCharSet = csQuotes): AnsiString; function StrRemoveSurroundingQuotesB(const S: RawByteString; const Quotes: ByteCharSet = csQuotes): RawByteString; {$ENDIF} function StrRemoveSurroundingQuotesU(const S: UnicodeString; const Quotes: ByteCharSet = csQuotes): UnicodeString; function StrRemoveSurroundingQuotes(const S: String; const Quotes: ByteCharSet = csQuotes): String; {$IFDEF SupportAnsiString} function StrQuoteA(const S: AnsiString; const Quote: AnsiChar = AnsiChar('"')): AnsiString; {$ENDIF} function StrQuoteB(const S: RawByteString; const Quote: ByteChar = ByteChar('"')): RawByteString; function StrQuoteU(const S: UnicodeString; const Quote: WideChar = WideChar('"')): UnicodeString; function StrQuote(const S: String; const Quote: Char = '"'): String; {$IFDEF SupportAnsiString} function StrUnquoteA(const S: AnsiString): AnsiString; {$ENDIF} function StrUnquoteB(const S: RawByteString): RawByteString; function StrUnquoteU(const S: UnicodeString): UnicodeString; function StrUnquote(const S: String): String; {$IFDEF SupportAnsiString} function StrMatchQuotedStrA(const S: AnsiString; const ValidQuotes: ByteCharSet = csQuotes; const Index: Integer = 1): Integer; function StrIsQuotedStrA(const S: AnsiString; const ValidQuotes: ByteCharSet = csQuotes): Boolean; function StrFindClosingQuoteA(const S: AnsiString; const OpenQuotePos: Integer): Integer; {$ENDIF} { } { Bracketing } { } function StrFindClosingBracketB(const S: RawByteString; const OpenBracketPos: Integer; const CloseBracket: ByteChar): Integer; { } { Escaping } { } function StrHexEscapeB(const S: RawByteString; const C: ByteCharSet; const EscPrefix: RawByteString = '\x'; const EscSuffix: RawByteString = ''; const UpperHex: Boolean = True; const TwoDigitHex: Boolean = True): RawByteString; function StrHexUnescapeB(const S: RawByteString; const EscPrefix: RawByteString = '\x'; const AsciiCaseSensitive: Boolean = True): RawByteString; {$IFDEF SupportAnsiString} function StrCharEscapeA(const S: AnsiString; const C: array of AnsiChar; const EscPrefix: AnsiString; const EscSeq: array of AnsiString): AnsiString; function StrCharUnescapeA(const S: AnsiString; const EscPrefix: AnsiString; const C: array of AnsiChar; const Replace: array of AnsiString; const PrefixAsciiCaseSensitive: Boolean = True; const AlwaysDropPrefix: Boolean = True): AnsiString; function StrCharUnescapeU(const S: UnicodeString; const EscPrefix: UnicodeString; const C: array of WideChar; const Replace: array of UnicodeString; const PrefixAsciiCaseSensitive: Boolean = True; const AlwaysDropPrefix: Boolean = True): UnicodeString; function StrCStyleEscapeA(const S: AnsiString): AnsiString; function StrCStyleUnescapeA(const S: AnsiString): AnsiString; {$ENDIF} { } { Prefix and Suffix } { } {$IFDEF SupportAnsiString} function StrInclPrefixA(const S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean = True): AnsiString; {$ENDIF} function StrInclPrefixB(const S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrInclPrefixU(const S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrInclPrefix(const S: String; const Prefix: String; const AsciiCaseSensitive: Boolean = True): String; {$IFDEF SupportAnsiString} function StrInclSuffixA(const S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean = True): AnsiString; {$ENDIF} function StrInclSuffixB(const S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrInclSuffixU(const S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrInclSuffix(const S: String; const Suffix: String; const AsciiCaseSensitive: Boolean = True): String; {$IFDEF SupportAnsiString} function StrExclPrefixA(const S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean = True): AnsiString; {$ENDIF} function StrExclPrefixB(const S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrExclPrefixU(const S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrExclPrefix(const S: String; const Prefix: String; const AsciiCaseSensitive: Boolean = True): String; {$IFDEF SupportAnsiString} function StrExclSuffixA(const S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean = True): AnsiString; {$ENDIF} function StrExclSuffixB(const S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean = True): RawByteString; function StrExclSuffixU(const S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean = True): UnicodeString; function StrExclSuffix(const S: String; const Suffix: String; const AsciiCaseSensitive: Boolean = True): String; {$IFDEF SupportAnsiString} procedure StrEnsurePrefixA(var S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean = True); {$ENDIF} procedure StrEnsurePrefixB(var S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsurePrefixU(var S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsurePrefix(var S: String; const Prefix: String; const AsciiCaseSensitive: Boolean = True); {$IFDEF SupportAnsiString} procedure StrEnsureSuffixA(var S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean = True); {$ENDIF} procedure StrEnsureSuffixB(var S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureSuffixU(var S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureSuffix(var S: String; const Suffix: String; const AsciiCaseSensitive: Boolean = True); {$IFDEF SupportAnsiString} procedure StrEnsureNoPrefixA(var S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean = True); {$ENDIF} procedure StrEnsureNoPrefixB(var S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureNoPrefixU(var S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureNoPrefix(var S: String; const Prefix: String; const AsciiCaseSensitive: Boolean = True); {$IFDEF SupportAnsiString} procedure StrEnsureNoSuffixA(var S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean = True); {$ENDIF} procedure StrEnsureNoSuffixB(var S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureNoSuffixU(var S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean = True); procedure StrEnsureNoSuffix(var S: String; const Suffix: String; const AsciiCaseSensitive: Boolean = True); { } { Reverse } { } {$IFDEF SupportAnsiString} function StrReverseA(const S: AnsiString): AnsiString; {$ENDIF} function StrReverseB(const S: RawByteString): RawByteString; function StrReverseU(const S: UnicodeString): UnicodeString; function StrReverse(const S: String): String; { } { Type conversion } { } function StrToFloatDef(const S: String; const Default: Extended): Extended; {$IFDEF SupportAnsiString} function BooleanToStrA(const B: Boolean): AnsiString; {$ENDIF} function BooleanToStrB(const B: Boolean): RawByteString; function BooleanToStrU(const B: Boolean): UnicodeString; function BooleanToStr(const B: Boolean): String; {$IFDEF SupportAnsiString} function StrToBooleanA(const S: AnsiString): Boolean; {$ENDIF} function StrToBooleanB(const S: RawByteString): Boolean; function StrToBooleanU(const S: UnicodeString): Boolean; function StrToBoolean(const S: String): Boolean; { } { Dynamic array functions } { } {$IFDEF SupportAnsiString} function StringsTotalLengthA(const S: array of AnsiString): Integer; {$ENDIF} function StringsTotalLengthB(const S: array of RawByteString): Integer; function StringsTotalLengthU(const S: array of UnicodeString): Integer; function StringsTotalLength(const S: array of String): Integer; {$IFDEF SupportAnsiString} function PosNextNoCaseA(const Find: AnsiString; const V: array of AnsiString; const PrevPos: Integer = -1; const IsSortedAscending: Boolean = False): Integer; {$ENDIF} function PosNextNoCaseB(const Find: RawByteString; const V: array of RawByteString; const PrevPos: Integer = -1; const IsSortedAscending: Boolean = False): Integer; function PosNextNoCaseU(const Find: UnicodeString; const V: array of UnicodeString; const PrevPos: Integer = -1; const IsSortedAscending: Boolean = False): Integer; { } { Natural language } { } function StorageSize(const Bytes: Int64; const ShortFormat: Boolean = False): String; function TransferRate(const Bytes, MillisecondsElapsed: Int64; const ShortFormat: Boolean = False): String; { } { Tests } { } {$IFDEF STRINGS_TEST} procedure Test; {$ENDIF} implementation uses { Fundamentals } flcUtils, flcASCII; { } { String functions } { } {$IFDEF SupportAnsiString} procedure SetLengthAndZeroA(var S: AnsiString; const NewLength: Integer); var L : Integer; P : PAnsiChar; begin L := Length(S); if L = NewLength then exit; SetLength(S, NewLength); if L > NewLength then exit; P := Pointer(S); Inc(P, L); ZeroMem(P^, NewLength - L); end; {$ENDIF} procedure SetLengthAndZeroB(var S: RawByteString; const NewLength: Integer); var L : Integer; P : PByteChar; begin L := Length(S); if L = NewLength then exit; SetLength(S, NewLength); if L > NewLength then exit; P := Pointer(S); Inc(P, L); ZeroMem(P^, NewLength - L); end; procedure SetLengthAndZeroU(var S: UnicodeString; const NewLength: Integer); var L : Integer; P : PWideChar; begin L := Length(S); if L = NewLength then exit; SetLength(S, NewLength); if L > NewLength then exit; P := Pointer(S); Inc(P, L); ZeroMem(P^, (NewLength - L) * SizeOf(WideChar)); end; function ToStringChB(const A: ByteChar): String; begin {$IFDEF StringIsUnicode} Result := WideChar(A); {$ELSE} Result := A; {$ENDIF} end; function ToStringChW(const A: WideChar): String; begin {$IFDEF StringIsUnicode} Result := A; {$ELSE} if Ord(A) <= $FF then Result := AnsiChar(Ord(A)) else raise EConvertError.Create('Invalid character'); {$ENDIF} end; {$IFDEF SupportAnsiString} function ToStringA(const A: AnsiString): String; begin {$IFDEF StringIsUnicode} Result := String(A); {$ELSE} Result := A; {$ENDIF} end; {$ENDIF} function ToStringB(const A: RawByteString): String; begin {$IFDEF StringIsUnicode} Result := String(A); {$ELSE} Result := A; {$ENDIF} end; function ToStringU(const A: UnicodeString): String; begin {$IFDEF StringIsUnicode} Result := String(A); {$ELSE} Result := AnsiString(A); {$ENDIF} end; { } { Match } { } {$IFDEF ASM386_DELPHI} function CharMatchNoAsciiCaseB(const A, B: ByteChar): Boolean; asm AND EAX, $000000FF AND EDX, $000000FF MOV AL, BYTE PTR [AsciiLowCaseLookup + EAX] CMP AL, BYTE PTR [AsciiLowCaseLookup + EDX] SETZ AL end; {$ELSE} function CharMatchNoAsciiCaseB(const A, B: ByteChar): Boolean; begin Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)]; end; {$ENDIF} function CharMatchNoAsciiCaseW(const A, B: WideChar): Boolean; begin if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; function CharMatchNoAsciiCaseBW(const A: ByteChar; const B: WideChar): Boolean; begin if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; function CharMatchNoAsciiCaseBS(const A: ByteChar; const B: Char): Boolean; begin if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; function CharMatchNoAsciiCase(const A, B: Char): Boolean; begin if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; {$IFDEF ASM386_DELPHI} function CharMatchB(const A, B: ByteChar; const AsciiCaseSensitive: Boolean): Boolean; asm OR CL, CL JZ CharMatchNoAsciiCaseB CMP AL, DL SETZ AL end; {$ELSE} function CharMatchB(const A, B: ByteChar; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := A = B else Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)]; end; {$ENDIF} function CharMatchW(const A, B: WideChar; const AsciiCaseSensitive: Boolean = True): Boolean; begin if AsciiCaseSensitive then Result := A = B else if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := A = B; end; function CharMatchBW(const A: ByteChar; const B: WideChar; const AsciiCaseSensitive: Boolean = True): Boolean; begin if AsciiCaseSensitive then Result := Ord(A) = Ord(B) else if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; function CharMatchBS(const A: ByteChar; const B: Char; const AsciiCaseSensitive: Boolean = True): Boolean; begin if AsciiCaseSensitive then Result := Ord(A) = Ord(B) else if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := Ord(A) = Ord(B); end; function CharMatch(const A, B: Char; const AsciiCaseSensitive: Boolean = True): Boolean; begin if AsciiCaseSensitive then Result := A = B else if (Ord(A) <= $7F) and (Ord(B) <= $7F) then Result := AsciiLowCaseLookup[Ord(A)] = AsciiLowCaseLookup[Ord(B)] else Result := A = B; end; function CharSetMatchCharB(const A: ByteCharSet; const B: ByteChar; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := B in A else Result := (AsciiUpCaseB(B) in A) or (AsciiLowCaseB(B) in A); end; function CharSetMatchCharW(const A: ByteCharSet; const B: WideChar; const AsciiCaseSensitive: Boolean): Boolean; begin if Ord(B) > $FF then Result := False else if AsciiCaseSensitive then Result := ByteChar(Ord(B)) in A else Result := (AsciiUpCaseB(ByteChar(Ord(B))) in A) or (AsciiLowCaseB(ByteChar(Ord(B))) in A); end; function CharSetMatchChar(const A: ByteCharSet; const B: Char; const AsciiCaseSensitive: Boolean): Boolean; begin {$IFDEF StringIsUnicode} if Ord(B) > $FF then Result := False else {$ENDIF} if AsciiCaseSensitive then Result := ByteChar(Ord(B)) in A else Result := (AsciiUpCaseB(ByteChar(Ord(B))) in A) or (AsciiLowCaseB(ByteChar(Ord(B))) in A); end; function StrPMatchB(const A, B: PByteChar; const Len: Integer): Boolean; var P, Q : PByteChar; I : Integer; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchW(const A, B: PWideChar; const Len: Integer): Boolean; var P, Q : PWideChar; I : Integer; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchBW(const A: PWideChar; B: PByteChar; const Len: Integer): Boolean; var P : PWideChar; Q : PByteChar; I : Integer; begin P := A; Q := B; for I := 1 to Len do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchBS(const A: PChar; B: PByteChar; const Len: Integer): Boolean; var P : PChar; Q : PByteChar; I : Integer; begin P := A; Q := B; for I := 1 to Len do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatch(const A, B: PChar; const Len: Integer): Boolean; var P, Q : PChar; I : Integer; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchB(const S, M: PByteChar; const LenS, LenM: Integer): Boolean; var P, Q : PByteChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; if Pointer(S) = Pointer(M) then begin Result := True; exit; end; P := S; Q := M; for I := 1 to LenM do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchW(const S, M: PWideChar; const LenS, LenM: Integer): Boolean; var P, Q : PWideChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; if Pointer(S) = Pointer(M) then begin Result := True; exit; end; P := S; Q := M; for I := 1 to LenM do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchBW(const S: PWideChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; var P : PWideChar; Q : PByteChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; P := S; Q := M; for I := 1 to LenM do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchBS(const S: PChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; var P : PChar; Q : PByteChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; P := S; Q := M; for I := 1 to LenM do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatch(const S, M: PChar; const LenS, LenM: Integer): Boolean; var P, Q : PChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; if Pointer(S) = Pointer(M) then begin Result := True; exit; end; P := S; Q := M; for I := 1 to LenM do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; function StrPMatchStrPB(const S: PChar; const M: PByteChar; const LenS, LenM: Integer): Boolean; var P : PChar; Q : PByteChar; I : Integer; begin if LenM = 0 then begin Result := True; exit; end; if LenM > LenS then begin Result := False; exit; end; P := S; Q := M; for I := 1 to LenM do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; Result := True; end; {$IFDEF SupportAnsiString} function StrPMatchStrA(const S: PAnsiChar; const Len: Integer; const M: AnsiString): Boolean; begin Result := StrPMatchB(Pointer(S), Pointer(M), Len, Length(M)); end; {$ENDIF} function StrPMatchStrB(const S: PByteChar; const Len: Integer; const M: RawByteString): Boolean; begin Result := StrPMatchB(S, Pointer(M), Len, Length(M)); end; {$IFDEF SupportAnsiString} function StrPMatchStrAW(const S: PWideChar; const Len: Integer; const M: AnsiString): Boolean; begin Result := StrPMatchBW(S, Pointer(M), Len, Length(M)); end; {$ENDIF} {$IFDEF SupportAnsiString} function StrPMatchStrAS(const S: PChar; const Len: Integer; const M: AnsiString): Boolean; begin Result := StrPMatchBS(S, Pointer(M), Len, Length(M)); end; {$ENDIF} function StrPMatchStrU(const S: PWideChar; const Len: Integer; const M: UnicodeString): Boolean; begin Result := StrPMatchW(S, Pointer(M), Len, Length(M)); end; function StrPMatchStr(const S: PChar; const Len: Integer; const M: String): Boolean; begin Result := StrPMatch(S, Pointer(M), Len, Length(M)); end; function StrPMatchNoAsciiCaseB(const A, B: PByteChar; const Len: Integer): Boolean; var P, Q : PByte; C, D : Byte; I : Integer; begin P := Pointer(A); Q := Pointer(B); if P <> Q then for I := 1 to Len do begin C := AsciiLowCaseLookup[P^]; D := AsciiLowCaseLookup[Q^]; if C = D then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; end; Result := True; end; function StrPMatchNoAsciiCaseW(const A, B: PWideChar; const Len: Integer): Boolean; var P, Q : PWideChar; I : Integer; begin P := A; Q := B; if P <> Q then for I := 1 to Len do begin if CharMatchNoAsciiCaseW(P^, Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; end; Result := True; end; function StrPMatchNoAsciiCaseBW(const A: PWideChar; const B: PByteChar; const Len: Integer): Boolean; var P : PWideChar; Q : PByteChar; I : Integer; begin P := A; Q := B; for I := 1 to Len do begin if CharMatchNoAsciiCaseBW(Q^, P^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; end; Result := True; end; function StrPMatchNoAsciiCaseBS(const A: PChar; const B: PByteChar; const Len: Integer): Boolean; var P : PChar; Q : PByteChar; I : Integer; begin P := A; Q := B; for I := 1 to Len do begin if CharMatchNoAsciiCaseBS(Q^, P^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; end; Result := True; end; function StrPMatchNoAsciiCase(const A, B: PChar; const Len: Integer): Boolean; var P, Q : PChar; I : Integer; begin P := A; Q := B; if P <> Q then for I := 1 to Len do begin if CharMatchNoAsciiCase(P^, Q^) then begin Inc(P); Inc(Q); end else begin Result := False; exit; end; end; Result := True; end; function StrPMatchLenB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Integer; var Q : PByteChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do if Q^ in M then begin Inc(Q); Dec(L); Inc(Result); end else exit; end; function StrPMatchLenW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Integer; var Q : PWideChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do if WideCharInCharSet(Q^, M) then begin Inc(Q); Dec(L); Inc(Result); end else exit; end; function StrPMatchLenW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Integer; var Q : PWideChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do if M(Q^) then begin Inc(Q); Dec(L); Inc(Result); end else exit; end; function StrPMatchLen(const P: PChar; const Len: Integer; const M: ByteCharSet): Integer; var Q : PChar; C : Char; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do begin C := Q^; {$IFDEF StringIsUnicode} if WideCharInCharSet(C, M) then {$ELSE} if C in M then {$ENDIF} begin Inc(Q); Dec(L); Inc(Result); end else exit; end; end; function StrPMatchCountB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Integer; var Q : PByteChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do begin if Q^ in M then Inc(Result); Inc(Q); Dec(L); end; end; function StrPMatchCountW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Integer; var Q : PWideChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do begin if WideCharInCharSet(Q^, M) then Inc(Result); Inc(Q); Dec(L); end; end; function StrPMatchCountW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Integer; var Q : PWideChar; L : Integer; begin Q := P; L := Len; Result := 0; if not Assigned(Q) then exit; while L > 0 do begin if M(Q^) then Inc(Result); Inc(Q); Dec(L); end; end; function StrPMatchCharB(const P: PByteChar; const Len: Integer; const M: ByteCharSet): Boolean; begin Result := StrPMatchLenB(P, Len, M) = Len; end; function StrPMatchCharW(const P: PWideChar; const Len: Integer; const M: ByteCharSet): Boolean; begin Result := StrPMatchLenW(P, Len, M) = Len; end; function StrPMatchCharW(const P: PWideChar; const Len: Integer; const M: TWideCharMatchFunction): Boolean; begin Result := StrPMatchLenW(P, Len, M) = Len; end; function StrPMatchChar(const P: PChar; const Len: Integer; const M: ByteCharSet): Boolean; begin Result := StrPMatchLen(P, Len, M) = Len; end; {$IFDEF SupportAnsiString} function StrMatchA(const S, M: AnsiString; const Index: Integer): Boolean; var N, T : Integer; Q : PByteChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchB(Pointer(M), Q, N); end; {$ENDIF} function StrMatchB(const S, M: RawByteString; const Index: Integer): Boolean; var N, T : Integer; Q : PByteChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchB(Pointer(M), Q, N); end; function StrMatchU(const S, M: UnicodeString; const Index: Integer): Boolean; var N, T, I : Integer; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; for I := 1 to N do if M[I] <> S[I + Index - 1] then begin Result := False; exit; end; Result := True; end; {$IFDEF SupportAnsiString} function StrMatchAU(const S: UnicodeString; const M: AnsiString; const Index: Integer): Boolean; var N, T, I : Integer; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; for I := 1 to N do if Ord(M[I]) <> Ord(S[I + Index - 1]) then begin Result := False; exit; end; Result := True; end; {$ENDIF} function StrMatchBU(const S: UnicodeString; const M: RawByteString; const Index: Integer): Boolean; var N, T, I : Integer; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; for I := 1 to N do if Ord(M[I]) <> Ord(S[I + Index - 1]) then begin Result := False; exit; end; Result := True; end; {$IFDEF SupportAnsiString} function StrMatchAS(const S: String; const M: AnsiString; const Index: Integer): Boolean; var N, T, I : Integer; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; for I := 1 to N do if Ord(M[I]) <> Ord(S[I + Index - 1]) then begin Result := False; exit; end; Result := True; end; {$ENDIF} function StrMatch(const S, M: String; const Index: Integer): Boolean; var N, T, I : Integer; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; for I := 1 to N do if M[I] <> S[I + Index - 1] then begin Result := False; exit; end; Result := True; end; {$IFDEF SupportAnsiString} function StrMatchNoAsciiCaseA(const S, M: AnsiString; const Index: Integer): Boolean; var N, T : Integer; Q : PAnsiChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseB(Pointer(M), Pointer(Q), N); end; {$ENDIF} function StrMatchNoAsciiCaseB(const S, M: RawByteString; const Index: Integer): Boolean; var N, T : Integer; Q : PByteChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseB(Pointer(M), Q, N); end; function StrMatchNoAsciiCaseU(const S, M: UnicodeString; const Index: Integer): Boolean; var N, T : Integer; Q : PWideChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseW(Pointer(M), Q, N); end; {$IFDEF SupportAnsiString} function StrMatchNoAsciiCaseAU(const S: UnicodeString; const M: AnsiString; const Index: Integer): Boolean; var N, T : Integer; Q : PWideChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseBW(Q, Pointer(M), N); end; {$ENDIF} {$IFDEF SupportAnsiString} function StrMatchNoAsciiCaseAS(const S: String; const M: AnsiString; const Index: Integer): Boolean; var N, T : Integer; Q : PChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseBS(Q, Pointer(M), N); end; {$ENDIF} function StrMatchNoAsciiCaseBU(const S: UnicodeString; const M: RawByteString; const Index: Integer): Boolean; var N, T : Integer; Q : PWideChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCaseBW(Q, Pointer(M), N); end; function StrMatchNoAsciiCase(const S, M: String; const Index: Integer = 1): Boolean; var N, T : Integer; Q : PChar; begin N := Length(M); T := Length(S); if (N = 0) or (T = 0) or (Index < 1) or (Index + N - 1 > T) then begin Result := False; exit; end; Q := Pointer(S); Inc(Q, Index - 1); Result := StrPMatchNoAsciiCase(Pointer(M), Q, N); end; {$IFDEF SupportAnsiString} function StrMatchLeftA(const S, M: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatchA(S, M, 1) else Result := StrMatchNoAsciiCaseA(S, M, 1); end; {$ENDIF} function StrMatchLeftB(const S, M: RawByteString; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatchB(S, M, 1) else Result := StrMatchNoAsciiCaseB(S, M, 1); end; function StrMatchLeftU(const S, M: UnicodeString; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatchU(S, M, 1) else Result := StrMatchNoAsciiCaseU(S, M, 1); end; {$IFDEF SupportAnsiString} function StrMatchLeftAU(const S: UnicodeString; const M: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatchAU(S, M, 1) else Result := StrMatchNoAsciiCaseAU(S, M, 1); end; {$ENDIF} function StrMatchLeftBU(const S: UnicodeString; const M: RawByteString; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatchBU(S, M, 1) else Result := StrMatchNoAsciiCaseBU(S, M, 1); end; function StrMatchLeft(const S, M: String; const AsciiCaseSensitive: Boolean): Boolean; begin if AsciiCaseSensitive then Result := StrMatch(S, M, 1) else Result := StrMatchNoAsciiCase(S, M, 1); end; {$IFDEF SupportAnsiString} function StrMatchRightA(const S, M: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; var I: Integer; begin I := Length(S) - Length(M) + 1; if AsciiCaseSensitive then Result := StrMatchA(S, M, I) else Result := StrMatchNoAsciiCaseA(S, M, I); end; {$ENDIF} function StrMatchRightB(const S, M: RawByteString; const AsciiCaseSensitive: Boolean): Boolean; var I: Integer; begin I := Length(S) - Length(M) + 1; if AsciiCaseSensitive then Result := StrMatchB(S, M, I) else Result := StrMatchNoAsciiCaseB(S, M, I); end; function StrMatchRightU(const S, M: UnicodeString; const AsciiCaseSensitive: Boolean): Boolean; var I: Integer; begin I := Length(S) - Length(M) + 1; if AsciiCaseSensitive then Result := StrMatchU(S, M, I) else Result := StrMatchNoAsciiCaseU(S, M, I); end; {$IFDEF SupportAnsiString} function StrMatchRightAU(const S: UnicodeString; const M: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; var I: Integer; begin I := Length(S) - Length(M) + 1; if AsciiCaseSensitive then Result := StrMatchAU(S, M, I) else Result := StrMatchNoAsciiCaseAU(S, M, I); end; {$ENDIF} function StrMatchRight(const S, M: String; const AsciiCaseSensitive: Boolean): Boolean; var I: Integer; begin I := Length(S) - Length(M) + 1; if AsciiCaseSensitive then Result := StrMatch(S, M, I) else Result := StrMatchNoAsciiCase(S, M, I); end; {$IFDEF SupportAnsiString} function StrMatchLenA(const S: AnsiString; const M: ByteCharSet; const Index: Integer): Integer; var P : PAnsiChar; L, I : Integer; begin I := Index; if I <= 0 then I := 1; L := Length(S); if I > L then Result := 0 else begin P := Pointer(S); Dec(I); Inc(P, I); Result := StrPMatchLenB(Pointer(P), L - I, M); end; end; {$ENDIF} function StrMatchLenB(const S: RawByteString; const M: ByteCharSet; const Index: Integer): Integer; var P : PByteChar; L, I : Integer; begin I := Index; if I <= 0 then I := 1; L := Length(S); if I > L then Result := 0 else begin P := Pointer(S); Dec(I); Inc(P, I); Result := StrPMatchLenB(P, L - I, M); end; end; function StrMatchLenU(const S: UnicodeString; const M: ByteCharSet; const Index: Integer): Integer; var P : PWideChar; L, I : Integer; begin I := Index; if I <= 0 then I := 1; L := Length(S); if I > L then Result := 0 else begin P := Pointer(S); Dec(I); Inc(P, I); Result := StrPMatchLenW(P, L - I, M); end; end; function StrMatchLenU(const S: UnicodeString; const M: TWideCharMatchFunction; const Index: Integer = 1): Integer; var P : PWideChar; L, I : Integer; begin I := Index; if I <= 0 then I := 1; L := Length(S); if I > L then Result := 0 else begin P := Pointer(S); Dec(I); Inc(P, I); Result := StrPMatchLenW(P, L - I, M); end; end; function StrMatchLen(const S: String; const M: ByteCharSet; const Index: Integer): Integer; var P : PChar; L, I : Integer; begin I := Index; if I <= 0 then I := 1; L := Length(S); if I > L then Result := 0 else begin P := Pointer(S); Dec(I); Inc(P, I); Result := StrPMatchLen(P, L - I, M); end; end; {$IFDEF SupportAnsiString} function StrMatchCharA(const S: AnsiString; const M: ByteCharSet): Boolean; var L: Integer; begin L := Length(S); Result := (L > 0) and (StrPMatchLenB(Pointer(S), L, M) = L); end; {$ENDIF} function StrMatchCharB(const S: RawByteString; const M: ByteCharSet): Boolean; var L: Integer; begin L := Length(S); Result := (L > 0) and (StrPMatchLenB(Pointer(S), L, M) = L); end; function StrMatchCharU(const S: UnicodeString; const M: ByteCharSet): Boolean; var L: Integer; begin L := Length(S); Result := (L > 0) and (StrPMatchLenW(Pointer(S), L, M) = L); end; function StrMatchCharU(const S: UnicodeString; const M: TWideCharMatchFunction): Boolean; var L: Integer; begin L := Length(S); Result := (L > 0) and (StrPMatchLenW(Pointer(S), L, M) = L); end; function StrMatchChar(const S: String; const M: ByteCharSet): Boolean; var L: Integer; begin L := Length(S); Result := (L > 0) and (StrPMatchLen(Pointer(S), L, M) = L); end; { } { Equal } { } function StrPEqual(const P1, P2: PByteChar; const Len1, Len2: Integer; const AsciiCaseSensitive: Boolean): Boolean; begin Result := Len1 = Len2; if not Result or (Len1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchB(P1, P2, Len1) else Result := StrPMatchNoAsciiCaseB(P1, P2, Len1); end; {$IFDEF SupportAnsiString} function StrPEqualStr(const P: PAnsiChar; const Len: Integer; const S: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; begin Result := Len = Length(S); if not Result or (Len = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchB(Pointer(P), Pointer(S), Len) else Result := StrPMatchNoAsciiCaseB(Pointer(P), Pointer(S), Len); end; {$ENDIF} {$IFDEF SupportAnsiString} function StrEqualA(const A, B: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchB(Pointer(A), Pointer(B), L1) else Result := StrPMatchNoAsciiCaseB(Pointer(A), Pointer(B), L1); end; {$ENDIF} function StrEqualB(const A, B: RawByteString; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchB(Pointer(A), Pointer(B), L1) else Result := StrPMatchNoAsciiCaseB(Pointer(A), Pointer(B), L1); end; function StrEqualU(const A, B: UnicodeString; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchW(Pointer(A), Pointer(B), L1) else Result := StrPMatchNoAsciiCaseW(Pointer(A), Pointer(B), L1); end; {$IFDEF SupportAnsiString} function StrEqualAU(const A: UnicodeString; const B: AnsiString; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchBW(Pointer(A), Pointer(B), L1, L1) else Result := StrPMatchNoAsciiCaseBW(Pointer(A), Pointer(B), L1); end; {$ENDIF} function StrEqualBU(const A: UnicodeString; const B: RawByteString; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatchBW(Pointer(A), Pointer(B), L1, L1) else Result := StrPMatchNoAsciiCaseBW(Pointer(A), Pointer(B), L1); end; function StrEqual(const A, B: String; const AsciiCaseSensitive: Boolean): Boolean; var L1, L2 : Integer; begin L1 := Length(A); L2 := Length(B); Result := L1 = L2; if not Result or (L1 = 0) then exit; if AsciiCaseSensitive then Result := StrPMatch(Pointer(A), Pointer(B), L1) else Result := StrPMatchNoAsciiCase(Pointer(A), Pointer(B), L1); end; {$IFDEF SupportAnsiString} function StrEqualNoAsciiCaseA(const A, B: AnsiString): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCaseB(Pointer(A), Pointer(B), L); end; {$ENDIF} function StrEqualNoAsciiCaseB(const A, B: RawByteString): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCaseB(Pointer(A), Pointer(B), L); end; function StrEqualNoAsciiCaseU(const A, B: UnicodeString): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCaseW(Pointer(A), Pointer(B), L); end; {$IFDEF SupportAnsiString} function StrEqualNoAsciiCaseAU(const A: UnicodeString; const B: AnsiString): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCaseBW(Pointer(A), Pointer(B), L); end; {$ENDIF} function StrEqualNoAsciiCaseBU(const A: UnicodeString; const B: RawByteString): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCaseBW(Pointer(A), Pointer(B), L); end; function StrEqualNoAsciiCase(const A, B: String): Boolean; var L, M : Integer; begin L := Length(A); M := Length(B); Result := L = M; if not Result or (L = 0) then exit; Result := StrPMatchNoAsciiCase(Pointer(A), Pointer(B), L); end; { } { Validation } { } {$IFDEF SupportAnsiString} function StrIsNumericA(const S: AnsiString): Boolean; begin Result := StrMatchCharA(S, csNumeric); end; {$ENDIF} function StrIsNumericB(const S: RawByteString): Boolean; begin Result := StrMatchCharB(S, csNumeric); end; function StrIsNumericU(const S: UnicodeString): Boolean; begin Result := StrMatchCharU(S, csNumeric); end; function StrIsNumeric(const S: String): Boolean; begin Result := StrMatchChar(S, csNumeric); end; {$IFDEF SupportAnsiString} function StrIsHexA(const S: AnsiString): Boolean; begin Result := StrMatchCharA(S, csHexDigit); end; {$ENDIF} function StrIsHexB(const S: RawByteString): Boolean; begin Result := StrMatchCharB(S, csHexDigit); end; function StrIsHexU(const S: UnicodeString): Boolean; begin Result := StrMatchCharU(S, csHexDigit); end; function StrIsHex(const S: String): Boolean; begin Result := StrMatchChar(S, csHexDigit); end; {$IFDEF SupportAnsiString} function StrIsAlphaA(const S: AnsiString): Boolean; begin Result := StrMatchCharA(S, csAlpha); end; {$ENDIF} function StrIsAlphaB(const S: RawByteString): Boolean; begin Result := StrMatchCharB(S, csAlpha); end; function StrIsAlphaU(const S: UnicodeString): Boolean; begin Result := StrMatchCharU(S, csAlpha); end; function StrIsAlpha(const S: String): Boolean; begin Result := StrMatchChar(S, csAlpha); end; {$IFDEF SupportAnsiString} function StrIsAlphaNumericA(const S: AnsiString): Boolean; begin Result := StrMatchCharA(S, csAlphaNumeric); end; {$ENDIF} function StrIsAlphaNumericB(const S: RawByteString): Boolean; begin Result := StrMatchCharB(S, csAlphaNumeric); end; function StrIsAlphaNumericU(const S: UnicodeString): Boolean; begin Result := StrMatchCharU(S, csAlphaNumeric); end; function StrIsAlphaNumeric(const S: String): Boolean; begin Result := StrMatchChar(S, csAlphaNumeric); end; {$IFDEF SupportAnsiString} function StrIsIntegerA(const S: AnsiString): Boolean; var L: Integer; P: PAnsiChar; begin L := Length(S); Result := L > 0; if not Result then exit; P := Pointer(S); if P^ in csSign then begin Inc(P); Dec(L); end; Result := (L > 0) and (StrPMatchLenB(Pointer(P), L, csNumeric) = L); end; {$ENDIF} function StrIsIntegerB(const S: RawByteString): Boolean; var L: Integer; P: PByteChar; begin L := Length(S); Result := L > 0; if not Result then exit; P := Pointer(S); if P^ in csSign then begin Inc(P); Dec(L); end; Result := (L > 0) and (StrPMatchLenB(P, L, csNumeric) = L); end; function StrIsIntegerU(const S: UnicodeString): Boolean; var L: Integer; P: PWideChar; begin L := Length(S); Result := L > 0; if not Result then exit; P := Pointer(S); case P^ of '+', '-' : begin Inc(P); Dec(L); end; end; Result := (L > 0) and (StrPMatchLenW(P, L, csNumeric) = L); end; function StrIsInteger(const S: String): Boolean; var L: Integer; P: PChar; begin L := Length(S); Result := L > 0; if not Result then exit; P := Pointer(S); case P^ of '+', '-' : begin Inc(P); Dec(L); end; end; Result := (L > 0) and (StrPMatchLen(P, L, csNumeric) = L); end; { } { Pos } { } function StrPPosCharB(const F: ByteChar; const S: PByteChar; const Len: Integer): Integer; var I : Integer; P : PByteChar; begin if Len <= 0 then begin Result := -1; exit; end; P := S; for I := 0 to Len - 1 do if P^ = F then begin Result := I; exit; end else Inc(P); Result := -1; end; function StrPPosCharW(const F: WideChar; const S: PWideChar; const Len: Integer): Integer; var I : Integer; P : PWideChar; begin if Len <= 0 then begin Result := -1; exit; end; P := S; for I := 0 to Len - 1 do if P^ = F then begin Result := I; exit; end else Inc(P); Result := -1; end; function StrPPosCharSetB(const F: ByteCharSet; const S: PByteChar; const Len: Integer): Integer; var I : Integer; P : PByteChar; begin if Len <= 0 then begin Result := -1; exit; end; P := S; for I := 0 to Len - 1 do if P^ in F then begin Result := I; exit; end else Inc(P); Result := -1; end; function StrPPosCharSetW(const F: ByteCharSet; const S: PWideChar; const Len: Integer): Integer; var I : Integer; P : PWideChar; begin if Len <= 0 then begin Result := -1; exit; end; P := S; for I := 0 to Len - 1 do if WideCharInCharSet(P^, F) then begin Result := I; exit; end else Inc(P); Result := -1; end; function StrPPosB(const F, S: PByteChar; const LenF, LenS: Integer): Integer; var I : Integer; P : PByteChar; begin if (LenF <= 0) or (LenS <= 0) or (LenF > LenS) then begin Result := -1; exit; end; P := S; for I := 0 to LenS - LenF do if StrPMatchB(P, F, LenF) then begin Result := I; exit; end else Inc(P); Result := -1; end; function StrPPosW(const F, S: PWideChar; const LenF, LenS: Integer): Integer; var I : Integer; P : PWideChar; begin if (LenF <= 0) or (LenS <= 0) or (LenF > LenS) then begin Result := -1; exit; end; P := S; for I := 0 to LenS - LenF do if StrPMatchW(P, F, LenF) then begin Result := I; exit; end else Inc(P); Result := -1; end; {$IFDEF SupportAnsiString} function StrPPosStrA(const F: AnsiString; const S: PAnsiChar; const Len: Integer): Integer; var LenF : Integer; I : Integer; P : PAnsiChar; begin LenF := Length(F); if (LenF <= 0) or (Len <= 0) or (LenF > Len) then begin Result := -1; exit; end; P := S; for I := 0 to Len - LenF do if StrPMatchStrA(P, LenF, F) then begin Result := I; exit; end else Inc(P); Result := -1; end; {$ENDIF} function StrPPosStrB(const F: RawByteString; const S: PByteChar; const Len: Integer): Integer; var LenF : Integer; I : Integer; P : PByteChar; begin LenF := Length(F); if (LenF <= 0) or (Len <= 0) or (LenF > Len) then begin Result := -1; exit; end; P := S; for I := 0 to Len - LenF do if StrPMatchStrB(P, LenF, F) then begin Result := I; exit; end else Inc(P); Result := -1; end; {$IFDEF SupportAnsiString} function PosCharA(const F: AnsiChar; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ = F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosCharB(const F: ByteChar; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ = F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; function PosCharU(const F: WideChar; const S: UnicodeString; const Index: Integer): Integer; var L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; while I <= L do if S[I] = F then begin Result := I; exit; end else Inc(I); Result := 0; end; function PosChar(const F: Char; const S: String; const Index: Integer): Integer; var L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; while I <= L do if S[I] = F then begin Result := I; exit; end else Inc(I); Result := 0; end; {$IFDEF SupportAnsiString} function PosCharSetA(const F: ByteCharSet; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ in F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosCharSetB(const F: ByteCharSet; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ in F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; function PosCharSetU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; C : WideChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; if Ord(C) <= $FF then if ByteChar(Ord(C)) in F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; function PosCharSetU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; C : WideChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; if F(C) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; function PosCharSet(const F: ByteCharSet; const S: String; const Index: Integer): Integer; var P : PChar; C : Char; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; {$IFDEF StringIsUnicode} if Ord(C) <= $FF then {$ENDIF} if ByteChar(Ord(C)) in F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; {$IFDEF SupportAnsiString} function PosNotCharA(const F: AnsiChar; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ <> F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosNotCharB(const F: ByteChar; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if P^ <> F then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; function PosNotCharU(const F: WideChar; const S: UnicodeString; const Index: Integer): Integer; var L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; while I <= L do if S[I] <> F then begin Result := I; exit; end else Inc(I); Result := 0; end; function PosNotChar(const F: Char; const S: String; const Index: Integer): Integer; var L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; while I <= L do if S[I] <> F then begin Result := I; exit; end else Inc(I); Result := 0; end; {$IFDEF SupportAnsiString} function PosNotCharSetA(const F: ByteCharSet; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if not (P^ in F) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosNotCharSetB(const F: ByteCharSet; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do if not (P^ in F) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; function PosNotCharSetU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; C : WideChar; L, I : Integer; R : Boolean; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; R := Ord(C) > $FF; if not R then R := not (ByteChar(Ord(C)) in F); if R then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; function PosNotCharSetU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; C : WideChar; L, I : Integer; R : Boolean; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; R := not F(C); if R then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; function PosNotCharSet(const F: ByteCharSet; const S: String; const Index: Integer): Integer; var P : PChar; C : Char; L, I : Integer; R : Boolean; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); while I <= L do begin C := P^; {$IFDEF StringIsUnicode} R := Ord(C) > $FF; if not R then {$ENDIF} R := not (ByteChar(Ord(C)) in F); if R then begin Result := I; exit; end else begin Inc(P); Inc(I); end; end; Result := 0; end; {$IFDEF SupportAnsiString} function PosCharRevA(const F: AnsiChar; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do if P^ = F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$ENDIF} function PosCharRevB(const F: ByteChar; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do if P^ = F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosCharRevU(const F: WideChar; const S: UnicodeString; const Index: Integer): Integer; var L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; J := L; while J >= I do if S[J] = F then begin Result := J; exit; end else Dec(J); Result := 0; end; function PosCharRev(const F: Char; const S: String; const Index: Integer): Integer; var L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; J := L; while J >= I do if S[J] = F then begin Result := J; exit; end else Dec(J); Result := 0; end; {$IFDEF SupportAnsiString} function PosCharSetRevA(const F: ByteCharSet; const S: AnsiString; const Index: Integer): Integer; var P : PAnsiChar; L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do if P^ in F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$ENDIF} function PosCharSetRevB(const F: ByteCharSet; const S: RawByteString; const Index: Integer): Integer; var P : PByteChar; L, I, J : Integer; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do if P^ in F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosCharSetRevU(const F: ByteCharSet; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; L, I, J : Integer; C : WideChar; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do begin C := P^; if Ord(C) <= $FF then if ByteChar(Ord(C)) in F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; end; Result := 0; end; function PosCharSetRevU(const F: TWideCharMatchFunction; const S: UnicodeString; const Index: Integer): Integer; var P : PWideChar; L, I, J : Integer; C : WideChar; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do begin C := P^; if F(C) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; end; Result := 0; end; function PosCharSetRev(const F: ByteCharSet; const S: String; const Index: Integer): Integer; var P : PChar; L, I, J : Integer; C : Char; begin L := Length(S); if (L = 0) or (Index > L) then begin Result := 0; exit; end; if Index < 1 then I := 1 else I := Index; P := Pointer(S); J := L; Inc(P, J - 1); while J >= I do begin C := P^; {$IFDEF StringIsUnicode} if Ord(C) <= $FF then {$ENDIF} if ByteChar(Ord(C)) in F then begin Result := J; exit; end else begin Dec(P); Dec(J); end; end; Result := 0; end; {$IFDEF SupportAnsiString} function PosStrA(const F, S: AnsiString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PAnsiChar; L, M, I : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); Dec(L, M - 1); if AsciiCaseSensitive then while I <= L do if StrPMatchB(Pointer(P), Pointer(Q), M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end else while I <= L do if StrPMatchNoAsciiCaseB(Pointer(P), Pointer(Q), M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosStrB(const F, S: RawByteString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PByteChar; L, M, I : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); Dec(L, M - 1); if AsciiCaseSensitive then while I <= L do if StrPMatchB(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end else while I <= L do if StrPMatchNoAsciiCaseB(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; function PosStrU(const F, S: UnicodeString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PWideChar; L, M, I : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); Dec(L, M - 1); if AsciiCaseSensitive then while I <= L do if StrPMatchW(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end else while I <= L do if StrPMatchNoAsciiCaseW(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$IFDEF SupportAnsiString} function PosStrAU(const F: AnsiString; const S: UnicodeString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P : PWideChar; Q : PAnsiChar; L, M, I : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); Dec(L, M - 1); if AsciiCaseSensitive then while I <= L do if StrPMatchBW(P, Pointer(Q), M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end else while I <= L do if StrPMatchNoAsciiCaseBW(P, Pointer(Q), M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$ENDIF} function PosStr(const F, S: String; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PChar; L, M, I : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Inc(P, I - 1); Dec(L, M - 1); if AsciiCaseSensitive then while I <= L do if StrPMatch(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end else while I <= L do if StrPMatchNoAsciiCase(P, Q, M) then begin Result := I; exit; end else begin Inc(P); Inc(I); end; Result := 0; end; {$IFDEF SupportAnsiString} function PosStrRevA(const F, S: AnsiString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PAnsiChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Dec(L, M - 1); Inc(P, L - 1); J := L; if AsciiCaseSensitive then while J >= I do if StrPMatchB(Pointer(P), Pointer(Q), M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= I do if StrPMatchNoAsciiCaseB(Pointer(P), Pointer(Q), M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$ENDIF} function PosStrRevB(const F, S: RawByteString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PByteChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Dec(L, M - 1); Inc(P, L - 1); J := L; if AsciiCaseSensitive then while J >= I do if StrPMatchB(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= I do if StrPMatchNoAsciiCaseB(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosStrRevU(const F, S: UnicodeString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PWideChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Dec(L, M - 1); Inc(P, L - 1); J := L; if AsciiCaseSensitive then while J >= I do if StrPMatchW(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= I do if StrPMatchNoAsciiCaseW(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosStrRev(const F, S: String; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := 1 else I := Index; P := Pointer(S); Dec(L, M - 1); Inc(P, L - 1); J := L; if AsciiCaseSensitive then while J >= I do if StrPMatch(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= I do if StrPMatchNoAsciiCase(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$IFDEF SupportAnsiString} function PosStrRevIdxA(const F, S: AnsiString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PAnsiChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := L else I := Index; P := Pointer(S); Inc(P, I - 1); J := I; if AsciiCaseSensitive then while J >= 1 do if StrPMatchB(Pointer(P), Pointer(Q), M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= 1 do if StrPMatchNoAsciiCaseB(Pointer(P), Pointer(Q), M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$ENDIF} function PosStrRevIdxB(const F, S: RawByteString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PByteChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := L else I := Index; P := Pointer(S); Inc(P, I - 1); J := I; if AsciiCaseSensitive then while J >= 1 do if StrPMatchB(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= 1 do if StrPMatchNoAsciiCaseB(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosStrRevIdxU(const F, S: UnicodeString; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PWideChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := L else I := Index; P := Pointer(S); Inc(P, I - 1); J := I; if AsciiCaseSensitive then while J >= 1 do if StrPMatchW(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= 1 do if StrPMatchNoAsciiCaseW(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; function PosStrRevIdx(const F, S: String; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var P, Q : PChar; L, M, I, J : Integer; begin L := Length(S); M := Length(F); if (L = 0) or (Index > L) or (M = 0) or (M > L) then begin Result := 0; exit; end; Q := Pointer(F); if Index < 1 then I := L else I := Index; P := Pointer(S); Inc(P, I - 1); J := I; if AsciiCaseSensitive then while J >= 1 do if StrPMatch(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end else while J >= 1 do if StrPMatchNoAsciiCase(P, Q, M) then begin Result := J; exit; end else begin Dec(P); Dec(J); end; Result := 0; end; {$IFDEF SupportAnsiString} function PosNStrA(const F, S: AnsiString; const N: Integer; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var I, J, M: Integer; begin Result := 0; if N <= 0 then exit; M := Length(F); if M = 0 then exit; J := Index; for I := 1 to N do begin Result := PosStrA(F, S, J, AsciiCaseSensitive); if Result = 0 then exit; J := Result + M; end; end; {$ENDIF} function PosNStrB(const F, S: RawByteString; const N: Integer; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var I, J, M: Integer; begin Result := 0; if N <= 0 then exit; M := Length(F); if M = 0 then exit; J := Index; for I := 1 to N do begin Result := PosStrB(F, S, J, AsciiCaseSensitive); if Result = 0 then exit; J := Result + M; end; end; function PosNStrU(const F, S: UnicodeString; const N: Integer; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var I, J, M: Integer; begin Result := 0; if N <= 0 then exit; M := Length(F); if M = 0 then exit; J := Index; for I := 1 to N do begin Result := PosStrU(F, S, J, AsciiCaseSensitive); if Result = 0 then exit; J := Result + M; end; end; function PosNStr(const F, S: String; const N: Integer; const Index: Integer; const AsciiCaseSensitive: Boolean): Integer; var I, J, M: Integer; begin Result := 0; if N <= 0 then exit; M := Length(F); if M = 0 then exit; J := Index; for I := 1 to N do begin Result := PosStr(F, S, J, AsciiCaseSensitive); if Result = 0 then exit; J := Result + M; end; end; { } { Copy variations } { } {$IFDEF SupportAnsiString} function CopyRangeA(const S: AnsiString; const StartIndex, StopIndex: Integer): AnsiString; var L, I : Integer; begin L := Length(S); if (StartIndex > StopIndex) or (StopIndex < 1) or (StartIndex > L) or (L = 0) then Result := '' else begin if StartIndex <= 1 then if StopIndex >= L then begin Result := S; exit; end else I := 1 else I := StartIndex; Result := Copy(S, I, StopIndex - I + 1); end; end; {$ENDIF} function CopyRangeB(const S: RawByteString; const StartIndex, StopIndex: Integer): RawByteString; var L, I : Integer; begin L := Length(S); if (StartIndex > StopIndex) or (StopIndex < 1) or (StartIndex > L) or (L = 0) then Result := '' else begin if StartIndex <= 1 then if StopIndex >= L then begin Result := S; exit; end else I := 1 else I := StartIndex; Result := Copy(S, I, StopIndex - I + 1); end; end; function CopyRangeU(const S: UnicodeString; const StartIndex, StopIndex: Integer): UnicodeString; var L, I : Integer; begin L := Length(S); if (StartIndex > StopIndex) or (StopIndex < 1) or (StartIndex > L) or (L = 0) then Result := '' else begin if StartIndex <= 1 then if StopIndex >= L then begin Result := S; exit; end else I := 1 else I := StartIndex; Result := Copy(S, I, StopIndex - I + 1); end; end; function CopyRange(const S: String; const StartIndex, StopIndex: Integer): String; var L, I : Integer; begin L := Length(S); if (StartIndex > StopIndex) or (StopIndex < 1) or (StartIndex > L) or (L = 0) then Result := '' else begin if StartIndex <= 1 then if StopIndex >= L then begin Result := S; exit; end else I := 1 else I := StartIndex; Result := Copy(S, I, StopIndex - I + 1); end; end; {$IFDEF SupportAnsiString} function CopyFromA(const S: AnsiString; const Index: Integer): AnsiString; var L : Integer; begin if Index <= 1 then Result := S else begin L := Length(S); if (L = 0) or (Index > L) then Result := '' else Result := Copy(S, Index, L - Index + 1); end; end; {$ENDIF} function CopyFromB(const S: RawByteString; const Index: Integer): RawByteString; var L : Integer; begin if Index <= 1 then Result := S else begin L := Length(S); if (L = 0) or (Index > L) then Result := '' else Result := Copy(S, Index, L - Index + 1); end; end; function CopyFromU(const S: UnicodeString; const Index: Integer): UnicodeString; var L : Integer; begin if Index <= 1 then Result := S else begin L := Length(S); if (L = 0) or (Index > L) then Result := '' else Result := Copy(S, Index, L - Index + 1); end; end; function CopyFrom(const S: String; const Index: Integer): String; var L : Integer; begin if Index <= 1 then Result := S else begin L := Length(S); if (L = 0) or (Index > L) then Result := '' else Result := Copy(S, Index, L - Index + 1); end; end; {$IFDEF SupportAnsiString} function CopyLeftA(const S: AnsiString; const Count: Integer): AnsiString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, 1, Count); end; {$ENDIF} function CopyLeftB(const S: RawByteString; const Count: Integer): RawByteString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, 1, Count); end; function CopyLeftU(const S: UnicodeString; const Count: Integer): UnicodeString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, 1, Count); end; function CopyLeft(const S: String; const Count: Integer): String; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, 1, Count); end; {$IFDEF SupportAnsiString} function CopyRightA(const S: AnsiString; const Count: Integer): AnsiString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, L - Count + 1, Count); end; {$ENDIF} function CopyRightB(const S: RawByteString; const Count: Integer): RawByteString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, L - Count + 1, Count); end; function CopyRightU(const S: UnicodeString; const Count: Integer): UnicodeString; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, L - Count + 1, Count); end; function CopyRight(const S: String; const Count: Integer): String; var L : Integer; begin L := Length(S); if (L = 0) or (Count <= 0) then Result := '' else if Count >= L then Result := S else Result := Copy(S, L - Count + 1, Count); end; {$IFDEF SupportAnsiString} function CopyLeftEllipsedA(const S: AnsiString; const Count: Integer): AnsiString; var L: Integer; begin if Count < 0 then begin Result := S; exit; end; if Count = 0 then begin Result := ''; exit; end; L := Length(S); if L <= Count then begin Result := S; exit; end; if Count <= 3 then begin Result := DupCharA(' ', Count); exit; end; Result := Copy(S, 1, Count - 3) + '...'; end; {$ENDIF} function CopyLeftEllipsedU(const S: UnicodeString; const Count: Integer): UnicodeString; var L: Integer; begin if Count < 0 then begin Result := S; exit; end; if Count = 0 then begin Result := ''; exit; end; L := Length(S); if L <= Count then begin Result := S; exit; end; if Count <= 3 then begin Result := DupCharU(' ', Count); exit; end; Result := Copy(S, 1, Count - 3) + '...'; end; { } { CopyEx } { } { TranslateStartStop translates Start, Stop parameters (negative values are } { indexed from back of string) into StartIdx and StopIdx (relative to start). } { Returns False if the Start, Stop does not specify a valid range. } function TranslateStart(const Len, Start: Integer; var StartIndex : Integer): Boolean; begin if Len = 0 then Result := False else begin StartIndex := Start; if Start < 0 then Inc(StartIndex, Len + 1); if StartIndex > Len then Result := False else begin if StartIndex < 1 then StartIndex := 1; Result := True; end; end; end; function TranslateStartStop(const Len, Start, Stop: Integer; var StartIndex, StopIndex: Integer): Boolean; begin if Len = 0 then Result := False else begin StartIndex := Start; if Start < 0 then Inc(StartIndex, Len + 1); StopIndex := Stop; if StopIndex < 0 then Inc(StopIndex, Len + 1); if (StopIndex < 1) or (StartIndex > Len) or (StopIndex < StartIndex) then Result := False else begin if StopIndex > Len then StopIndex:= Len; if StartIndex < 1 then StartIndex := 1; Result := True; end; end; end; {$IFDEF SupportAnsiString} function CopyExA(const S: AnsiString; const Start, Count: Integer): AnsiString; var I, L : Integer; begin L := Length(S); if (Count < 0) or not TranslateStart(L, Start, I) then Result := '' else if (I = 1) and (Count >= L) then Result := S else Result := Copy(S, I, Count); end; {$ENDIF} function CopyExB(const S: RawByteString; const Start, Count: Integer): RawByteString; var I, L : Integer; begin L := Length(S); if (Count < 0) or not TranslateStart(L, Start, I) then Result := '' else if (I = 1) and (Count >= L) then Result := S else Result := Copy(S, I, Count); end; function CopyExW(const S: String; const Start, Count: Integer): String; var I, L : Integer; begin L := Length(S); if (Count < 0) or not TranslateStart(L, Start, I) then Result := '' else if (I = 1) and (Count >= L) then Result := S else Result := Copy(S, I, Count); end; function CopyExU(const S: UnicodeString; const Start, Count: Integer): UnicodeString; var I, L : Integer; begin L := Length(S); if (Count < 0) or not TranslateStart(L, Start, I) then Result := '' else if (I = 1) and (Count >= L) then Result := S else Result := Copy(S, I, Count); end; function CopyEx(const S: String; const Start, Count: Integer): String; var I, L : Integer; begin L := Length(S); if (Count < 0) or not TranslateStart(L, Start, I) then Result := '' else if (I = 1) and (Count >= L) then Result := S else Result := Copy(S, I, Count); end; {$IFDEF SupportAnsiString} function CopyRangeExA(const S: AnsiString; const Start, Stop: Integer): AnsiString; var I, J, L : Integer; begin L := Length(S); if not TranslateStartStop(L, Start, Stop, I, J) then Result := '' else if (I = 1) and (J = L) then Result := S else Result := Copy(S, I, J - I + 1); end; {$ENDIF} function CopyRangeExB(const S: RawByteString; const Start, Stop: Integer): RawByteString; var I, J, L : Integer; begin L := Length(S); if not TranslateStartStop(L, Start, Stop, I, J) then Result := '' else if (I = 1) and (J = L) then Result := S else Result := Copy(S, I, J - I + 1); end; function CopyRangeExU(const S: UnicodeString; const Start, Stop: Integer): UnicodeString; var I, J, L : Integer; begin L := Length(S); if not TranslateStartStop(L, Start, Stop, I, J) then Result := '' else if (I = 1) and (J = L) then Result := S else Result := Copy(S, I, J - I + 1); end; function CopyRangeEx(const S: String; const Start, Stop: Integer): String; var I, J, L : Integer; begin L := Length(S); if not TranslateStartStop(L, Start, Stop, I, J) then Result := '' else if (I = 1) and (J = L) then Result := S else Result := Copy(S, I, J - I + 1); end; {$IFDEF SupportAnsiString} function CopyFromExA(const S: AnsiString; const Start: Integer): AnsiString; var I, L : Integer; begin L := Length(S); if not TranslateStart(L, Start, I) then Result := '' else if I <= 1 then Result := S else Result := Copy(S, I, L - I + 1); end; function CopyFromExB(const S: RawByteString; const Start: Integer): RawByteString; var I, L : Integer; begin L := Length(S); if not TranslateStart(L, Start, I) then Result := '' else if I <= 1 then Result := S else Result := Copy(S, I, L - I + 1); end; {$ENDIF} function CopyFromExU(const S: UnicodeString; const Start: Integer): UnicodeString; var I, L : Integer; begin L := Length(S); if not TranslateStart(L, Start, I) then Result := '' else if I <= 1 then Result := S else Result := Copy(S, I, L - I + 1); end; function CopyFromEx(const S: String; const Start: Integer): String; var I, L : Integer; begin L := Length(S); if not TranslateStart(L, Start, I) then Result := '' else if I <= 1 then Result := S else Result := Copy(S, I, L - I + 1); end; { } { Trim } { } {$IFDEF SupportAnsiString} function StrTrimLeftA(const S: AnsiString; const C: ByteCharSet): AnsiString; var F, L : Integer; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); Result := CopyFromA(S, F); end; {$ENDIF} function StrTrimLeftB(const S: RawByteString; const C: ByteCharSet): RawByteString; var F, L : Integer; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); Result := CopyFromB(S, F); end; function StrTrimLeftU(const S: UnicodeString; const C: ByteCharSet): UnicodeString; var F, L : Integer; begin L := Length(S); F := 1; while (F <= L) and WideCharInCharSet(S[F], C) do Inc(F); Result := CopyFromU(S, F); end; function StrTrimLeftU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; var F, L : Integer; begin L := Length(S); F := 1; while (F <= L) and C(S[F]) do Inc(F); Result := CopyFromU(S, F); end; function StrTrimLeft(const S: String; const C: ByteCharSet): String; begin {$IFDEF StringIsUnicode} Result := StrTrimLeftU(S, C); {$ELSE} Result := StrTrimLeftA(S, C); {$ENDIF} end; {$IFDEF SupportAnsiString} procedure StrTrimLeftInPlaceA(var S: AnsiString; const C: ByteCharSet); var F, L : Integer; P : PAnsiChar; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); if F > L then S := '' else if F > 1 then begin L := L - F + 1; if L > 0 then begin P := Pointer(S); Inc(P, F - 1); MoveMem(P^, Pointer(S)^, L); end; SetLength(S, L); end; end; {$ENDIF} procedure StrTrimLeftInPlaceB(var S: RawByteString; const C: ByteCharSet); var F, L : Integer; P : PByteChar; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); if F > L then S := '' else if F > 1 then begin L := L - F + 1; if L > 0 then begin P := Pointer(S); Inc(P, F - 1); MoveMem(P^, Pointer(S)^, L); end; SetLength(S, L); end; end; procedure StrTrimLeftInPlaceU(var S: UnicodeString; const C: ByteCharSet); var F, L : Integer; P : PWideChar; begin L := Length(S); F := 1; while (F <= L) and CharSetMatchCharW(C, S[F], True) do Inc(F); if F > L then S := '' else if F > 1 then begin L := L - F + 1; if L > 0 then begin P := Pointer(S); Inc(P, F - 1); MoveMem(P^, Pointer(S)^, L * SizeOf(WideChar)); end; SetLength(S, L); end; end; procedure StrTrimLeftInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); var F, L : Integer; P : PWideChar; begin L := Length(S); F := 1; while (F <= L) and C(S[F]) do Inc(F); if F > L then S := '' else if F > 1 then begin L := L - F + 1; if L > 0 then begin P := Pointer(S); Inc(P, F - 1); MoveMem(P^, Pointer(S)^, L * SizeOf(WideChar)); end; SetLength(S, L); end; end; procedure StrTrimLeftInPlace(var S: String; const C: ByteCharSet); var F, L : Integer; P : PChar; begin L := Length(S); F := 1; while (F <= L) and CharSetMatchChar(C, S[F], True) do Inc(F); if F > L then S := '' else if F > 1 then begin L := L - F + 1; if L > 0 then begin P := Pointer(S); Inc(P, F - 1); MoveMem(P^, Pointer(S)^, L * SizeOf(Char)); end; SetLength(S, L); end; end; {$IFDEF SupportAnsiString} function StrTrimLeftStrNoCaseA(const S: AnsiString; const TrimStr: AnsiString): AnsiString; var F, L, M : Integer; begin L := Length(TrimStr); M := Length(S); F := 1; while (F <= M) and StrMatchNoAsciiCaseA(S, TrimStr, F) do Inc(F, L); Result := CopyFromA(S, F); end; {$ENDIF} function StrTrimLeftStrNoCaseB(const S: RawByteString; const TrimStr: RawByteString): RawByteString; var F, L, M : Integer; begin L := Length(TrimStr); M := Length(S); F := 1; while (F <= M) and StrMatchNoAsciiCaseB(S, TrimStr, F) do Inc(F, L); Result := CopyFromB(S, F); end; function StrTrimLeftStrNoCaseU(const S: UnicodeString; const TrimStr: UnicodeString): UnicodeString; var F, L, M : Integer; begin L := Length(TrimStr); M := Length(S); F := 1; while (F <= M) and StrMatchNoAsciiCaseU(S, TrimStr, F) do Inc(F, L); Result := CopyFromU(S, F); end; function StrTrimLeftStrNoCase(const S: String; const TrimStr: String): String; var F, L, M : Integer; begin L := Length(TrimStr); M := Length(S); F := 1; while (F <= M) and StrMatchNoAsciiCase(S, TrimStr, F) do Inc(F, L); Result := CopyFrom(S, F); end; {$IFDEF SupportAnsiString} function StrTrimRightA(const S: AnsiString; const C: ByteCharSet): AnsiString; var F : Integer; begin F := Length(S); while (F >= 1) and (S[F] in C) do Dec(F); Result := CopyLeftA(S, F); end; {$ENDIF} function StrTrimRightB(const S: RawByteString; const C: ByteCharSet): RawByteString; var F : Integer; begin F := Length(S); while (F >= 1) and (S[F] in C) do Dec(F); Result := CopyLeftB(S, F); end; function StrTrimRightU(const S: UnicodeString; const C: ByteCharSet): UnicodeString; var F : Integer; begin F := Length(S); while (F >= 1) and WideCharInCharSet(S[F], C) do Dec(F); Result := CopyLeftU(S, F); end; function StrTrimRightU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; var F : Integer; begin F := Length(S); while (F >= 1) and C(S[F]) do Dec(F); Result := CopyLeftU(S, F); end; function StrTrimRight(const S: String; const C: ByteCharSet): String; begin {$IFDEF StringIsUnicode} Result := StrTrimRightU(S, C); {$ELSE} Result := StrTrimRightA(S, C); {$ENDIF} end; {$IFDEF SupportAnsiString} procedure StrTrimRightInPlaceA(var S: AnsiString; const C: ByteCharSet); var F : Integer; begin F := Length(S); while (F >= 1) and (S[F] in C) do Dec(F); if F = 0 then S := '' else SetLength(S, F); end; {$ENDIF} procedure StrTrimRightInPlaceB(var S: RawByteString; const C: ByteCharSet); var F : Integer; begin F := Length(S); while (F >= 1) and (S[F] in C) do Dec(F); if F = 0 then S := '' else SetLength(S, F); end; procedure StrTrimRightInPlaceU(var S: UnicodeString; const C: ByteCharSet); var F : Integer; begin F := Length(S); while (F >= 1) and CharSetMatchCharW(C, S[F], True) do Dec(F); if F = 0 then S := '' else SetLength(S, F); end; procedure StrTrimRightInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); var F : Integer; begin F := Length(S); while (F >= 1) and C(S[F]) do Dec(F); if F = 0 then S := '' else SetLength(S, F); end; procedure StrTrimRightInPlace(var S: String; const C: ByteCharSet); var F : Integer; begin F := Length(S); while (F >= 1) and CharSetMatchChar(C, S[F], True) do Dec(F); if F = 0 then S := '' else SetLength(S, F); end; {$IFDEF SupportAnsiString} function StrTrimRightStrNoCaseA(const S: AnsiString; const TrimStr: AnsiString): AnsiString; var F, L : Integer; begin L := Length(TrimStr); F := Length(S) - L + 1; while (F >= 1) and StrMatchNoAsciiCaseA(S, TrimStr, F) do Dec(F, L); Result := CopyLeftA(S, F + L - 1); end; {$ENDIF} function StrTrimRightStrNoCaseB(const S: RawByteString; const TrimStr: RawByteString): RawByteString; var F, L : Integer; begin L := Length(TrimStr); F := Length(S) - L + 1; while (F >= 1) and StrMatchNoAsciiCaseB(S, TrimStr, F) do Dec(F, L); Result := CopyLeftB(S, F + L - 1); end; function StrTrimRightStrNoCaseU(const S: UnicodeString; const TrimStr: UnicodeString): UnicodeString; var F, L : Integer; begin L := Length(TrimStr); F := Length(S) - L + 1; while (F >= 1) and StrMatchNoAsciiCaseU(S, TrimStr, F) do Dec(F, L); Result := CopyLeftU(S, F + L - 1); end; function StrTrimRightStrNoCase(const S: String; const TrimStr: String): String; var F, L : Integer; begin L := Length(TrimStr); F := Length(S) - L + 1; while (F >= 1) and StrMatchNoAsciiCase(S, TrimStr, F) do Dec(F, L); Result := CopyLeft(S, F + L - 1); end; {$IFDEF SupportAnsiString} function StrTrimA(const S: AnsiString; const C: ByteCharSet): AnsiString; var F, G, L : Integer; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); G := L; while (G >= F) and (S[G] in C) do Dec(G); Result := CopyRangeA(S, F, G); end; {$ENDIF} function StrTrimB(const S: RawByteString; const C: ByteCharSet): RawByteString; var F, G, L : Integer; begin L := Length(S); F := 1; while (F <= L) and (S[F] in C) do Inc(F); G := L; while (G >= F) and (S[G] in C) do Dec(G); Result := CopyRangeB(S, F, G); end; function StrTrimU(const S: UnicodeString; const C: ByteCharSet): UnicodeString; var F, G, L : Integer; begin L := Length(S); F := 1; while (F <= L) and WideCharInCharSet(S[F], C) do Inc(F); G := L; while (G >= F) and WideCharInCharSet(S[G], C) do Dec(G); Result := CopyRangeU(S, F, G); end; function StrTrimU(const S: UnicodeString; const C: TWideCharMatchFunction): UnicodeString; var F, G, L : Integer; begin L := Length(S); F := 1; while (F <= L) and C(S[F]) do Inc(F); G := L; while (G >= F) and C(S[G]) do Dec(G); Result := CopyRangeU(S, F, G); end; function StrTrim(const S: String; const C: ByteCharSet): String; begin {$IFDEF StringIsUnicode} Result := StrTrimU(S, C); {$ELSE} Result := StrTrimA(S, C); {$ENDIF} end; {$IFDEF SupportAnsiString} procedure StrTrimInPlaceA(var S: AnsiString; const C: ByteCharSet); begin StrTrimLeftInPlaceA(S, C); StrTrimRightInPlaceA(S, C); end; {$ENDIF} procedure StrTrimInPlaceB(var S: RawByteString; const C: ByteCharSet); begin StrTrimLeftInPlaceB(S, C); StrTrimRightInPlaceB(S, C); end; procedure StrTrimInPlaceU(var S : UnicodeString; const C: ByteCharSet); begin StrTrimLeftInPlaceU(S, C); StrTrimRightInPlaceU(S, C); end; procedure StrTrimInPlaceU(var S: UnicodeString; const C: TWideCharMatchFunction); begin StrTrimLeftInPlaceU(S, C); StrTrimRightInPlaceU(S, C); end; procedure StrTrimInPlace(var S : String; const C: ByteCharSet); begin StrTrimLeftInPlace(S, C); StrTrimRightInPlace(S, C); end; {$IFDEF SupportAnsiString} procedure TrimStringsA(var S : AnsiStringArray; const C: ByteCharSet); var I : Integer; begin for I := 0 to Length(S) - 1 do StrTrimInPlaceA(S[I], C); end; {$ENDIF} procedure TrimStringsB(var S : RawByteStringArray; const C: ByteCharSet); var I : Integer; begin for I := 0 to Length(S) - 1 do StrTrimInPlaceB(S[I], C); end; procedure TrimStringsU(var S : UnicodeStringArray; const C: ByteCharSet); var I : Integer; begin for I := 0 to Length(S) - 1 do StrTrimInPlaceU(S[I], C); end; procedure TrimStrings(var S : StringArray; const C: ByteCharSet); var I : Integer; begin for I := 0 to Length(S) - 1 do StrTrimInPlace(S[I], C); end; { } { Dup } { } {$IFDEF SupportAnsiString} function BufToStrA(const Buf; const BufSize: Integer): AnsiString; begin if BufSize <= 0 then Result := '' else begin SetLength(Result, BufSize); MoveMem(Buf, Pointer(Result)^, BufSize); end; end; {$ENDIF} function BufToStrB(const Buf; const BufSize: Integer): RawByteString; begin if BufSize <= 0 then Result := '' else begin SetLength(Result, BufSize); MoveMem(Buf, Pointer(Result)^, BufSize); end; end; function BufToStrU(const Buf; const BufSize: Integer): UnicodeString; var L : Integer; begin if BufSize <= 0 then Result := '' else begin L := (BufSize + 1) div SizeOf(WideChar); SetLength(Result, L); MoveMem(Buf, Pointer(Result)^, BufSize); end; end; function BufToStr(const Buf; const BufSize: Integer): String; var L : Integer; begin if BufSize <= 0 then Result := '' else begin {$IFDEF StringIsUnicode} L := (BufSize + 1) div SizeOf(Char); {$ELSE} L := BufSize; {$ENDIF} SetLength(Result, L); MoveMem(Buf, Pointer(Result)^, BufSize); end; end; {$IFDEF SupportAnsiString} function DupBufA(const Buf; const BufSize: Integer; const Count: Integer): AnsiString; var P : PAnsiChar; I : Integer; begin if (Count <= 0) or (BufSize <= 0) then Result := '' else begin SetLength(Result, Count * BufSize); P := Pointer(Result); for I := 1 to Count do begin MoveMem(Buf, P^, BufSize); Inc(P, BufSize); end; end; end; {$ENDIF} function DupBufB(const Buf; const BufSize: Integer; const Count: Integer): RawByteString; var P : PByteChar; I : Integer; begin if (Count <= 0) or (BufSize <= 0) then Result := '' else begin SetLength(Result, Count * BufSize); P := Pointer(Result); for I := 1 to Count do begin MoveMem(Buf, P^, BufSize); Inc(P, BufSize); end; end; end; function DupBufU(const Buf; const BufSize: Integer; const Count: Integer): UnicodeString; var P : PWideChar; I, L : Integer; begin if (Count <= 0) or (BufSize <= 0) then Result := '' else begin Assert(BufSize mod SizeOf(WideChar) = 0); L := BufSize div SizeOf(WideChar); SetLength(Result, Count * L); P := Pointer(Result); for I := 1 to Count do begin MoveMem(Buf, P^, BufSize); Inc(P, L); end; end; end; function DupBuf(const Buf; const BufSize: Integer; const Count: Integer): String; var P : PChar; I, L : Integer; begin if (Count <= 0) or (BufSize <= 0) then Result := '' else begin {$IFDEF StringIsUnicode} Assert(BufSize mod SizeOf(Char) = 0); L := BufSize div SizeOf(WideChar); {$ELSE} L := BufSize; {$ENDIF} SetLength(Result, Count * L); P := Pointer(Result); for I := 1 to Count do begin MoveMem(Buf, P^, BufSize); Inc(P, L); end; end; end; {$IFDEF SupportAnsiString} function DupStrA(const S: AnsiString; const Count: Integer): AnsiString; var L : Integer; begin L := Length(S); if L = 0 then Result := '' else Result := DupBufA(Pointer(S)^, L, Count); end; {$ENDIF} function DupStrB(const S: RawByteString; const Count: Integer): RawByteString; var L : Integer; begin L := Length(S); if L = 0 then Result := '' else Result := DupBufB(Pointer(S)^, L, Count); end; function DupStrU(const S: UnicodeString; const Count: Integer): UnicodeString; var L : Integer; begin L := Length(S); if L = 0 then Result := '' else Result := DupBufU(Pointer(S)^, L * SizeOf(WideChar), Count); end; function DupStr(const S: String; const Count: Integer): String; var L : Integer; begin L := Length(S); if L = 0 then Result := '' else Result := DupBuf(Pointer(S)^, L * SizeOf(Char), Count); end; {$IFDEF SupportAnsiString} function DupCharA(const Ch: AnsiChar; const Count: Integer): AnsiString; begin if Count <= 0 then begin Result := ''; exit; end; SetLength(Result, Count); FillMem(Pointer(Result)^, Count, Ord(Ch)); end; {$ENDIF} function DupCharB(const Ch: ByteChar; const Count: Integer): RawByteString; begin if Count <= 0 then begin Result := ''; exit; end; SetLength(Result, Count); FillMem(Pointer(Result)^, Count, Ord(Ch)); end; function DupCharU(const Ch: WideChar; const Count: Integer): UnicodeString; var I : Integer; begin if Count <= 0 then begin Result := ''; exit; end; SetLength(Result, Count); for I := 1 to Count do Result[I] := Ch; end; function DupChar(const Ch: Char; const Count: Integer): String; var I : Integer; begin if Count <= 0 then begin Result := ''; exit; end; SetLength(Result, Count); for I := 1 to Count do Result[I] := Ch; end; {$IFDEF SupportAnsiString} function DupSpaceA(const Count: Integer): AnsiString; begin Result := DupCharA(AsciiSP, Count); end; {$ENDIF} function DupSpaceB(const Count: Integer): RawByteString; begin Result := DupCharB(AsciiSP, Count); end; function DupSpaceU(const Count: Integer): UnicodeString; begin Result := DupCharU(WideSP, Count); end; function DupSpace(const Count: Integer): String; begin Result := DupChar(' ', Count); end; { } { Pad } { } {$IFDEF SupportAnsiString} function StrPadLeftA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean): AnsiString; var F, L, P, M : Integer; I, J : PAnsiChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if P > 0 then FillMem(Pointer(Result)^, P, Ord(PadChar)); if L > P then begin I := Pointer(Result); J := Pointer(S); Inc(I, P); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; end; {$ENDIF} function StrPadLeftB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean): RawByteString; var F, L, P, M : Integer; I, J : PByteChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if P > 0 then FillMem(Pointer(Result)^, P, Ord(PadChar)); if L > P then begin I := Pointer(Result); J := Pointer(S); Inc(I, P); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; end; function StrPadLeftU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean): UnicodeString; var F, L, P, M : Integer; I, J : PWideChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); for F := 1 to P do Result[F] := PadChar; if L > P then begin I := Pointer(Result); J := Pointer(S); Inc(I, P); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; end; function StrPadLeft(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean): String; var F, L, P, M : Integer; I, J : PChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); for F := 1 to P do Result[F] := PadChar; if L > P then begin I := Pointer(Result); J := Pointer(S); Inc(I, P); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; end; {$IFDEF SupportAnsiString} function StrPadRightA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean): AnsiString; var F, L, P, M : Integer; I, J : PAnsiChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if L > P then begin I := Pointer(Result); J := Pointer(S); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; if P > 0 then FillMem(Result[L - P + 1], P, Ord(PadChar)); end; {$ENDIF} function StrPadRightB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean): RawByteString; var F, L, P, M : Integer; I, J : PByteChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if L > P then begin I := Pointer(Result); J := Pointer(S); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; if P > 0 then FillMem(Result[L - P + 1], P, Ord(PadChar)); end; function StrPadRightU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean): UnicodeString; var F, L, P, M : Integer; I, J : PWideChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if L > P then begin I := Pointer(Result); J := Pointer(S); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; for F := L - P + 1 to L do Result[F] := PadChar; end; function StrPadRight(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean): String; var F, L, P, M : Integer; I, J : PChar; begin if Len = 0 then begin if Cut then Result := '' else Result := S; exit; end; M := Length(S); if Len = M then begin Result := S; exit; end; if Cut then L := Len else L := MaxInt(Len, M); P := L - M; if P < 0 then P := 0; SetLength(Result, L); if L > P then begin I := Pointer(Result); J := Pointer(S); for F := 1 to L - P do begin I^ := J^; Inc(I); Inc(J); end; end; for F := L - P + 1 to L do Result[F] := PadChar; end; {$IFDEF SupportAnsiString} function StrPadA(const S: AnsiString; const PadChar: AnsiChar; const Len: Integer; const Cut: Boolean): AnsiString; var I : Integer; begin I := Len - Length(S); Result := DupCharA(PadChar, I div 2) + S + DupCharA(PadChar, (I + 1) div 2); if Cut then SetLength(Result, Len); end; {$ENDIF} function StrPadB(const S: RawByteString; const PadChar: ByteChar; const Len: Integer; const Cut: Boolean): RawByteString; var I : Integer; begin I := Len - Length(S); Result := DupCharB(PadChar, I div 2) + S + DupCharB(PadChar, (I + 1) div 2); if Cut then SetLength(Result, Len); end; function StrPadU(const S: UnicodeString; const PadChar: WideChar; const Len: Integer; const Cut: Boolean): UnicodeString; var I : Integer; begin I := Len - Length(S); Result := DupCharU(PadChar, I div 2) + S + DupCharU(PadChar, (I + 1) div 2); if Cut then SetLength(Result, Len); end; function StrPad(const S: String; const PadChar: Char; const Len: Integer; const Cut: Boolean): String; var I : Integer; begin I := Len - Length(S); Result := DupChar(PadChar, I div 2) + S + DupChar(PadChar, (I + 1) div 2); if Cut then SetLength(Result, Len); end; { } { Delimited } { } {$IFDEF SupportAnsiString} function StrBetweenCharA(const S: AnsiString; const FirstDelim, SecondDelim: AnsiChar; const FirstOptional: Boolean; const SecondOptional: Boolean): AnsiString; var I, J : Integer; begin Result := ''; I := PosCharA(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharA(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeA(S, I + 1, J - 1); end; function StrBetweenCharA(const S: AnsiString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean): AnsiString; var I, J : Integer; begin Result := ''; I := PosCharSetA(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharSetA(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeA(S, I + 1, J - 1); end; function StrBetweenCharB(const S: RawByteString; const FirstDelim, SecondDelim: ByteChar; const FirstOptional: Boolean; const SecondOptional: Boolean): RawByteString; var I, J : Integer; begin Result := ''; I := PosCharB(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharB(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeB(S, I + 1, J - 1); end; function StrBetweenCharB(const S: RawByteString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean): RawByteString; var I, J : Integer; begin Result := ''; I := PosCharSetB(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharSetB(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeB(S, I + 1, J - 1); end; {$ENDIF} function StrBetweenCharU(const S: UnicodeString; const FirstDelim, SecondDelim: WideChar; const FirstOptional: Boolean; const SecondOptional: Boolean): UnicodeString; var I, J : Integer; begin Result := ''; I := PosCharU(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharU(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeU(S, I + 1, J - 1); end; function StrBetweenCharU(const S: UnicodeString; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean): UnicodeString; var I, J : Integer; begin Result := ''; I := PosCharSetU(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharSetU(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeU(S, I + 1, J - 1); end; function StrBetweenChar(const S: String; const FirstDelim, SecondDelim: Char; const FirstOptional: Boolean; const SecondOptional: Boolean): String; var I, J : Integer; begin Result := ''; I := PosChar(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosChar(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRange(S, I + 1, J - 1); end; function StrBetweenChar(const S: String; const FirstDelim, SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean): String; var I, J : Integer; begin Result := ''; I := PosCharSet(FirstDelim, S); if (I = 0) and not FirstOptional then exit; J := PosCharSet(SecondDelim, S, I + 1); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRange(S, I + 1, J - 1); end; {$IFDEF SupportAnsiString} function StrBetweenA(const S: AnsiString; const FirstDelim: AnsiString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean; const FirstDelimAsciiCaseSensitive: Boolean): AnsiString; var I, J : Integer; begin Result := ''; I := PosStrA(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosCharSetA(SecondDelim, S, I); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeA(S, I, J - 1); end; function StrBetweenA(const S: AnsiString; const FirstDelim, SecondDelim: AnsiString; const FirstOptional: Boolean; const SecondOptional: Boolean ; const FirstDelimAsciiCaseSensitive: Boolean; const SecondDelimAsciiCaseSensitive: Boolean): AnsiString; var I, J : Integer; begin Result := ''; I := PosStrA(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosStrA(SecondDelim, S, I, SecondDelimAsciiCaseSensitive); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeA(S, I, J - 1); end; function StrBetweenB(const S: RawByteString; const FirstDelim: RawByteString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean; const FirstDelimAsciiCaseSensitive: Boolean): RawByteString; var I, J : Integer; begin Result := ''; I := PosStrB(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosCharSetB(SecondDelim, S, I); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeB(S, I, J - 1); end; function StrBetweenB(const S: RawByteString; const FirstDelim, SecondDelim: RawByteString; const FirstOptional: Boolean; const SecondOptional: Boolean ; const FirstDelimAsciiCaseSensitive: Boolean; const SecondDelimAsciiCaseSensitive: Boolean): RawByteString; var I, J : Integer; begin Result := ''; I := PosStrB(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosStrB(SecondDelim, S, I, SecondDelimAsciiCaseSensitive); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeB(S, I, J - 1); end; {$ENDIF} function StrBetweenU(const S: UnicodeString; const FirstDelim: UnicodeString; const SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean; const FirstDelimAsciiCaseSensitive: Boolean): UnicodeString; var I, J : Integer; begin Result := ''; I := PosStrU(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosCharSetU(SecondDelim, S, I); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeU(S, I, J - 1); end; function StrBetweenU(const S: UnicodeString; const FirstDelim, SecondDelim: UnicodeString; const FirstOptional: Boolean; const SecondOptional: Boolean ; const FirstDelimAsciiCaseSensitive: Boolean; const SecondDelimAsciiCaseSensitive: Boolean): UnicodeString; var I, J : Integer; begin Result := ''; I := PosStrU(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosStrU(SecondDelim, S, I, SecondDelimAsciiCaseSensitive); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRangeU(S, I, J - 1); end; function StrBetween(const S: String; const FirstDelim: String; const SecondDelim: ByteCharSet; const FirstOptional: Boolean; const SecondOptional: Boolean; const FirstDelimAsciiCaseSensitive: Boolean): String; var I, J : Integer; begin Result := ''; I := PosStr(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosCharSet(SecondDelim, S, I); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRange(S, I, J - 1); end; function StrBetween(const S: String; const FirstDelim, SecondDelim: String; const FirstOptional: Boolean; const SecondOptional: Boolean ; const FirstDelimAsciiCaseSensitive: Boolean; const SecondDelimAsciiCaseSensitive: Boolean): String; var I, J : Integer; begin Result := ''; I := PosStr(FirstDelim, S, 1, FirstDelimAsciiCaseSensitive); if (I = 0) and not FirstOptional then exit; Inc(I, Length(FirstDelim)); J := PosStr(SecondDelim, S, I, SecondDelimAsciiCaseSensitive); if J = 0 then if not SecondOptional then exit else J := Length(S) + 1; Result := CopyRange(S, I, J - 1); end; {$IFDEF SupportAnsiString} function StrBeforeA(const S, D: AnsiString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): AnsiString; var I : Integer; begin I := PosStrA(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I - 1); end; function StrBeforeRevA(const S, D: AnsiString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): AnsiString; var I : Integer; begin I := PosStrRevA(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I - 1); end; {$ENDIF} function StrBeforeB(const S, D: RawByteString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): RawByteString; var I : Integer; begin I := PosStrB(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I - 1); end; function StrBeforeRevB(const S, D: RawByteString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): RawByteString; var I : Integer; begin I := PosStrRevB(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I - 1); end; function StrBeforeU(const S, D: UnicodeString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): UnicodeString; var I : Integer; begin I := PosStrU(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I - 1); end; function StrBeforeRevU(const S, D: UnicodeString; const Optional: Boolean; const AsciiCaseSensitive: Boolean): UnicodeString; var I : Integer; begin I := PosStrRevU(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I - 1); end; function StrBefore(const S, D: String; const Optional: Boolean; const AsciiCaseSensitive: Boolean): String; var I : Integer; begin I := PosStr(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I - 1); end; function StrBeforeRev(const S, D: String; const Optional: Boolean; const AsciiCaseSensitive: Boolean): String; var I : Integer; begin I := PosStrRev(D, S, 1, AsciiCaseSensitive); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I - 1); end; {$IFDEF SupportAnsiString} function StrBeforeCharA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosCharSetA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I - 1); end; function StrBeforeCharA(const S: AnsiString; const D: AnsiChar; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosCharA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I - 1); end; function StrBeforeCharRevA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosCharSetRevA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I - 1); end; {$ENDIF} function StrBeforeCharB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosCharSetB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I - 1); end; function StrBeforeCharB(const S: RawByteString; const D: ByteChar; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosCharB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I - 1); end; function StrBeforeCharRevB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosCharSetRevB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I - 1); end; function StrBeforeCharU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosCharSetU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I - 1); end; function StrBeforeCharU(const S: UnicodeString; const D: WideChar; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosCharU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I - 1); end; function StrBeforeCharRevU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosCharSetRevU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I - 1); end; function StrBeforeChar(const S: String; const D: ByteCharSet; const Optional: Boolean): String; var I : Integer; begin I := PosCharSet(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I - 1); end; function StrBeforeChar(const S: String; const D: Char; const Optional: Boolean): String; var I : Integer; begin I := PosChar(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I - 1); end; function StrBeforeCharRev(const S: String; const D: ByteCharSet; const Optional: Boolean): String; var I : Integer; begin I := PosCharSetRev(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I - 1); end; {$IFDEF SupportAnsiString} function StrAfterA(const S, D: AnsiString; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosStrA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromA(S, I + Length(D)); end; function StrAfterRevA(const S, D: AnsiString; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosStrRevA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromA(S, I + Length(D)); end; {$ENDIF} function StrAfterB(const S, D: RawByteString; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosStrB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromB(S, I + Length(D)); end; function StrAfterRevB(const S, D: RawByteString; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosStrRevB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromB(S, I + Length(D)); end; function StrAfterU(const S, D: UnicodeString; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosStrU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromU(S, I + Length(D)); end; function StrAfterRevU(const S, D: UnicodeString; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosStrRevU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFromU(S, I + Length(D)); end; function StrAfter(const S, D: String; const Optional: Boolean): String; var I : Integer; begin I := PosStr(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFrom(S, I + Length(D)); end; function StrAfterRev(const S, D: String; const Optional: Boolean): String; var I : Integer; begin I := PosStrRev(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyFrom(S, I + Length(D)); end; {$IFDEF SupportAnsiString} function StrAfterCharA(const S: AnsiString; const D: ByteCharSet): AnsiString; var I : Integer; begin I := PosCharSetA(D, S); if I = 0 then Result := '' else Result := CopyFromA(S, I + 1); end; function StrAfterCharA(const S: AnsiString; const D: AnsiChar): AnsiString; var I : Integer; begin I := PosCharA(D, S); if I = 0 then Result := '' else Result := CopyFromA(S, I + 1); end; {$ENDIF} function StrAfterCharB(const S: RawByteString; const D: ByteCharSet): RawByteString; var I : Integer; begin I := PosCharSetB(D, S); if I = 0 then Result := '' else Result := CopyFromB(S, I + 1); end; function StrAfterCharB(const S: RawByteString; const D: ByteChar): RawByteString; var I : Integer; begin I := PosCharB(D, S); if I = 0 then Result := '' else Result := CopyFromB(S, I + 1); end; function StrAfterCharU(const S: UnicodeString; const D: ByteCharSet): UnicodeString; var I : Integer; begin I := PosCharSetU(D, S); if I = 0 then Result := '' else Result := CopyFromU(S, I + 1); end; function StrAfterCharU(const S: UnicodeString; const D: WideChar): UnicodeString; var I : Integer; begin I := PosCharU(D, S); if I = 0 then Result := '' else Result := CopyFromU(S, I + 1); end; function StrAfterChar(const S: String; const D: ByteCharSet): String; var I : Integer; begin I := PosCharSet(D, S); if I = 0 then Result := '' else Result := CopyFrom(S, I + 1); end; function StrAfterChar(const S: String; const D: Char): String; var I : Integer; begin I := PosChar(D, S); if I = 0 then Result := '' else Result := CopyFrom(S, I + 1); end; {$IFDEF SupportAnsiString} function StrCopyToCharA(const S: AnsiString; const D: ByteCharSet; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosCharSetA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I); end; function StrCopyToCharA(const S: AnsiString; const D: AnsiChar; const Optional: Boolean): AnsiString; var I : Integer; begin I := PosCharA(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftA(S, I); end; {$ENDIF} function StrCopyToCharB(const S: RawByteString; const D: ByteCharSet; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosCharSetB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I); end; function StrCopyToCharB(const S: RawByteString; const D: ByteChar; const Optional: Boolean): RawByteString; var I : Integer; begin I := PosCharB(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftB(S, I); end; function StrCopyToCharU(const S: UnicodeString; const D: ByteCharSet; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosCharSetU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I); end; function StrCopyToCharU(const S: UnicodeString; const D: WideChar; const Optional: Boolean): UnicodeString; var I : Integer; begin I := PosCharU(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeftU(S, I); end; function StrCopyToChar(const S: String; const D: ByteCharSet; const Optional: Boolean): String; var I : Integer; begin I := PosCharSet(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I); end; function StrCopyToChar(const S: String; const D: Char; const Optional: Boolean): String; var I : Integer; begin I := PosChar(D, S); if I = 0 then if Optional then Result := S else Result := '' else Result := CopyLeft(S, I); end; {$IFDEF SupportAnsiString} function StrCopyFromCharA(const S: AnsiString; const D: ByteCharSet): AnsiString; var I : Integer; begin I := PosCharSetA(D, S); if I = 0 then Result := '' else Result := CopyFromA(S, I); end; function StrCopyFromCharA(const S: AnsiString; const D: AnsiChar): AnsiString; var I : Integer; begin I := PosCharB(D, S); if I = 0 then Result := '' else Result := CopyFromB(S, I); end; {$ENDIF} function StrCopyFromCharB(const S: RawByteString; const D: ByteCharSet): RawByteString; var I : Integer; begin I := PosCharSetB(D, S); if I = 0 then Result := '' else Result := CopyFromB(S, I); end; function StrCopyFromCharB(const S: RawByteString; const D: ByteChar): RawByteString; var I : Integer; begin I := PosCharB(D, S); if I = 0 then Result := '' else Result := CopyFromB(S, I); end; function StrCopyFromCharU(const S: UnicodeString; const D: ByteCharSet): UnicodeString; var I : Integer; begin I := PosCharSetU(D, S); if I = 0 then Result := '' else Result := CopyFromU(S, I); end; function StrCopyFromCharU(const S: UnicodeString; const D: WideChar): UnicodeString; var I : Integer; begin I := PosCharU(D, S); if I = 0 then Result := '' else Result := CopyFromU(S, I); end; function StrCopyFromChar(const S: String; const D: ByteCharSet): String; var I : Integer; begin I := PosCharSet(D, S); if I = 0 then Result := '' else Result := CopyFrom(S, I); end; function StrCopyFromChar(const S: String; const D: Char): String; var I : Integer; begin I := PosChar(D, S); if I = 0 then Result := '' else Result := CopyFrom(S, I); end; {$IFDEF SupportAnsiString} function StrRemoveCharDelimitedA(var S: AnsiString; const FirstDelim, SecondDelim: AnsiChar): AnsiString; var I, J : Integer; begin Result := ''; I := PosCharA(FirstDelim, S); if I = 0 then exit; J := PosCharA(SecondDelim, S, I + 1); if J = 0 then exit; Result := CopyRangeA(S, I + 1, J - 1); Delete(S, I, J - I + 1); end; {$ENDIF} function StrRemoveCharDelimitedB(var S: RawByteString; const FirstDelim, SecondDelim: ByteChar): RawByteString; var I, J : Integer; begin Result := ''; I := PosCharB(FirstDelim, S); if I = 0 then exit; J := PosCharB(SecondDelim, S, I + 1); if J = 0 then exit; Result := CopyRangeB(S, I + 1, J - 1); Delete(S, I, J - I + 1); end; function StrRemoveCharDelimitedU(var S: UnicodeString; const FirstDelim, SecondDelim: WideChar): UnicodeString; var I, J : Integer; begin Result := ''; I := PosCharU(FirstDelim, S); if I = 0 then exit; J := PosCharU(SecondDelim, S, I + 1); if J = 0 then exit; Result := CopyRangeU(S, I + 1, J - 1); Delete(S, I, J - I + 1); end; function StrRemoveCharDelimited(var S: String; const FirstDelim, SecondDelim: Char): String; var I, J : Integer; begin Result := ''; I := PosChar(FirstDelim, S); if I = 0 then exit; J := PosChar(SecondDelim, S, I + 1); if J = 0 then exit; Result := CopyRange(S, I + 1, J - 1); Delete(S, I, J - I + 1); end; { } { Count } { } {$IFDEF SupportAnsiString} function StrCountCharA(const S: AnsiString; const C: AnsiChar): Integer; var P : PAnsiChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ = C then Inc(Result); Inc(P); end; end; {$ENDIF} function StrCountCharB(const S: RawByteString; const C: ByteChar): Integer; var P : PByteChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ = C then Inc(Result); Inc(P); end; end; function StrCountCharU(const S: UnicodeString; const C: WideChar): Integer; var P : PWideChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ = C then Inc(Result); Inc(P); end; end; function StrCountChar(const S: String; const C: Char): Integer; var P : PChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ = C then Inc(Result); Inc(P); end; end; {$IFDEF SupportAnsiString} function StrCountCharA(const S: AnsiString; const C: ByteCharSet): Integer; var P : PAnsiChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ in C then Inc(Result); Inc(P); end; end; {$ENDIF} function StrCountCharB(const S: RawByteString; const C: ByteCharSet): Integer; var P : PByteChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin if P^ in C then Inc(Result); Inc(P); end; end; function StrCountCharU(const S: UnicodeString; const C: ByteCharSet): Integer; var P : PWideChar; D : WideChar; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin D := P^; if WideCharInCharSet(D, C) then Inc(Result); Inc(P); end; end; function StrCountChar(const S: String; const C: ByteCharSet): Integer; var P : PChar; D : Char; I : Integer; begin Result := 0; P := Pointer(S); for I := 1 to Length(S) do begin D := P^; {$IFDEF StringIsUnicode} if Ord(D) <= $FF then {$ENDIF} if ByteChar(Ord(D)) in C then Inc(Result); Inc(P); end; end; { } { Replace } { } {$IFDEF SupportAnsiString} function StrReplaceCharA(const Find, Replace: AnsiChar; const S: AnsiString): AnsiString; var P, Q : PAnsiChar; I, J : Integer; begin Result := S; I := PosCharA(Find, S); if I = 0 then exit; UniqueString(Result); Q := Pointer(Result); Inc(Q, I - 1); P := Pointer(S); Inc(P, I - 1); for J := I to Length(S) do begin if P^ = Find then Q^ := Replace; Inc(P); Inc(Q); end; end; {$ENDIF} function StrReplaceCharB(const Find, Replace: ByteChar; const S: RawByteString): RawByteString; var I, J : Integer; begin Result := S; I := PosCharB(Find, S); if I = 0 then exit; for J := I to Length(S) do if S[J] = Find then Result[J] := Replace; end; function StrReplaceCharU(const Find, Replace: WideChar; const S: UnicodeString): UnicodeString; var I, J : Integer; begin Result := S; I := PosCharU(Find, S); if I = 0 then exit; for J := I to Length(S) do if S[J] = Find then Result[J] := Replace; end; function StrReplaceChar(const Find, Replace: Char; const S: String): String; var I, J : Integer; begin Result := S; I := PosChar(Find, S); if I = 0 then exit; for J := I to Length(S) do if S[J] = Find then Result[J] := Replace; end; {$IFDEF SupportAnsiString} function StrReplaceCharA(const Find: ByteCharSet; const Replace: AnsiChar; const S: AnsiString): AnsiString; var P, Q : PAnsiChar; I, J : Integer; begin Result := S; I := PosCharSetA(Find, S); if I = 0 then exit; UniqueString(Result); Q := Pointer(Result); Inc(Q, I - 1); P := Pointer(S); Inc(P, I - 1); for J := I to Length(S) do begin if P^ in Find then Q^ := Replace; Inc(P); Inc(Q); end; end; {$ENDIF} function StrReplaceCharB(const Find: ByteCharSet; const Replace: ByteChar; const S: RawByteString): RawByteString; var I, J : Integer; begin Result := S; I := PosCharSetB(Find, S); if I = 0 then exit; for J := I to Length(S) do if S[J] in Find then Result[J] := Replace; end; function StrReplaceCharU(const Find: ByteCharSet; const Replace: WideChar; const S: UnicodeString): UnicodeString; var P, Q : PWideChar; I, J : Integer; C : WideChar; begin Result := S; I := PosCharSetU(Find, S); if I = 0 then exit; {$IFNDEF DELPHI5} UniqueString(Result); {$ENDIF} Q := Pointer(Result); Inc(Q, I - 1); P := Pointer(S); Inc(P, I - 1); for J := I to Length(S) do begin C := P^; if Ord(C) <= $FF then if ByteChar(Ord(C)) in Find then Q^ := Replace; Inc(P); Inc(Q); end; end; function StrReplaceChar(const Find: ByteCharSet; const Replace: Char; const S: String): String; var P, Q : PChar; I, J : Integer; C : Char; begin Result := S; I := PosCharSet(Find, S); if I = 0 then exit; UniqueString(Result); Q := Pointer(Result); Inc(Q, I - 1); P := Pointer(S); Inc(P, I - 1); for J := I to Length(S) do begin C := P^; {$IFDEF StringIsUnicode} if Ord(C) <= $FF then {$ENDIF} if ByteChar(Ord(C)) in Find then Q^ := Replace; Inc(P); Inc(Q); end; end; { } { StrReplace operates by replacing in 'batches' of 4096 matches. This has the } { advantage of fewer memory allocations and limited stack usage when there is } { a large number of matches. } { } type StrReplaceMatchArray = Array[0..4095] of Integer; {$IFDEF SupportAnsiString} function StrReplaceBlockA( // used by StrReplaceA const FindLen: Integer; const Replace, S: AnsiString; const StartIndex, StopIndex: Integer; const MatchCount: Integer; const Matches: StrReplaceMatchArray): AnsiString; var StrLen : Integer; ReplaceLen : Integer; NewLen : Integer; I, J, F, G : Integer; P, Q : PAnsiChar; begin ReplaceLen := Length(Replace); StrLen := StopIndex - StartIndex + 1; NewLen := StrLen + (ReplaceLen - FindLen) * MatchCount; if NewLen = 0 then begin Result := ''; exit; end; SetString(Result, nil, NewLen); P := Pointer(Result); Q := Pointer(S); F := StartIndex; Inc(Q, F - 1); for I := 0 to MatchCount - 1 do begin G := Matches[I]; J := G - F; if J > 0 then begin MoveMem(Q^, P^, J); Inc(P, J); Inc(Q, J); Inc(F, J); end; Inc(Q, FindLen); Inc(F, FindLen); if ReplaceLen > 0 then begin MoveMem(Pointer(Replace)^, P^, ReplaceLen); Inc(P, ReplaceLen); end; end; if F <= StopIndex then MoveMem(Q^, P^, StopIndex - F + 1); end; {$ENDIF} function StrReplaceBlockB( // used by StrReplaceB const FindLen: Integer; const Replace, S: RawByteString; const StartIndex, StopIndex: Integer; const MatchCount: Integer; const Matches: StrReplaceMatchArray): RawByteString; var StrLen : Integer; ReplaceLen : Integer; NewLen : Integer; I, J, F, G : Integer; P, Q : PByteChar; begin ReplaceLen := Length(Replace); StrLen := StopIndex - StartIndex + 1; NewLen := StrLen + (ReplaceLen - FindLen) * MatchCount; if NewLen = 0 then begin Result := ''; exit; end; SetLength(Result, NewLen); // FPC 3.0 has issue with SetString(Result, nil, NewLen) here P := PByteChar(Result); Q := PByteChar(S); F := StartIndex; Inc(Q, F - 1); for I := 0 to MatchCount - 1 do begin G := Matches[I]; J := G - F; if J > 0 then begin MoveMem(Q^, P^, J); Inc(P, J); Inc(Q, J); Inc(F, J); end; Inc(Q, FindLen); Inc(F, FindLen); if ReplaceLen > 0 then begin MoveMem(PByteChar(Replace)^, P^, ReplaceLen); Inc(P, ReplaceLen); end; end; if F <= StopIndex then MoveMem(Q^, P^, StopIndex - F + 1); end; function StrReplaceBlockU( // used by StrReplaceU const FindLen: Integer; const Replace, S: UnicodeString; const StartIndex, StopIndex: Integer; const MatchCount: Integer; const Matches: StrReplaceMatchArray): UnicodeString; var StrLen : Integer; ReplaceLen : Integer; NewLen : Integer; I, J, F, G : Integer; P, Q : PWideChar; begin ReplaceLen := Length(Replace); StrLen := StopIndex - StartIndex + 1; NewLen := StrLen + (ReplaceLen - FindLen) * MatchCount; if NewLen = 0 then begin Result := ''; exit; end; SetString(Result, nil, NewLen); P := Pointer(Result); Q := Pointer(S); F := StartIndex; Inc(Q, F - 1); for I := 0 to MatchCount - 1 do begin G := Matches[I]; J := G - F; if J > 0 then begin MoveMem(Q^, P^, J * SizeOf(WideChar)); Inc(P, J); Inc(Q, J); Inc(F, J); end; Inc(Q, FindLen); Inc(F, FindLen); if ReplaceLen > 0 then begin MoveMem(Pointer(Replace)^, P^, ReplaceLen * SizeOf(WideChar)); Inc(P, ReplaceLen); end; end; if F <= StopIndex then MoveMem(Q^, P^, (StopIndex - F + 1) * SizeOf(WideChar)); end; function StrReplaceBlock( // used by StrReplace const FindLen: Integer; const Replace, S: String; const StartIndex, StopIndex: Integer; const MatchCount: Integer; const Matches: StrReplaceMatchArray): String; var StrLen : Integer; ReplaceLen : Integer; NewLen : Integer; I, J, F, G : Integer; P, Q : PChar; begin ReplaceLen := Length(Replace); StrLen := StopIndex - StartIndex + 1; NewLen := StrLen + (ReplaceLen - FindLen) * MatchCount; if NewLen = 0 then begin Result := ''; exit; end; SetString(Result, nil, NewLen); P := Pointer(Result); Q := Pointer(S); F := StartIndex; Inc(Q, F - 1); for I := 0 to MatchCount - 1 do begin G := Matches[I]; J := G - F; if J > 0 then begin MoveMem(Q^, P^, J * SizeOf(Char)); Inc(P, J); Inc(Q, J); Inc(F, J); end; Inc(Q, FindLen); Inc(F, FindLen); if ReplaceLen > 0 then begin MoveMem(Pointer(Replace)^, P^, ReplaceLen * SizeOf(Char)); Inc(P, ReplaceLen); end; end; if F <= StopIndex then MoveMem(Q^, P^, (StopIndex - F + 1) * SizeOf(Char)); end; {$IFDEF SupportAnsiString} function StrReplaceA(const Find, Replace, S: AnsiString; const AsciiCaseSensitive: Boolean): AnsiString; var FindLen : Integer; Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin FindLen := Length(Find); if FindLen = 0 then // nothing to find begin Result := S; exit; end; I := PosStrA(Find, S, 1, AsciiCaseSensitive); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I, FindLen); I := PosStrA(Find, S, I, AsciiCaseSensitive); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockA(FindLen, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$ENDIF} function StrReplaceB(const Find, Replace, S: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; var FindLen : Integer; Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin FindLen := Length(Find); if FindLen = 0 then // nothing to find begin Result := S; exit; end; I := PosStrB(Find, S, 1, AsciiCaseSensitive); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I, FindLen); I := PosStrB(Find, S, I, AsciiCaseSensitive); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockB(FindLen, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; function StrReplaceU(const Find, Replace, S: UnicodeString; const AsciiCaseSensitive: Boolean): UnicodeString; var FindLen : Integer; Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin FindLen := Length(Find); if FindLen = 0 then // nothing to find begin Result := S; exit; end; I := PosStrU(Find, S, 1, AsciiCaseSensitive); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I, FindLen); I := PosStrU(Find, S, I, AsciiCaseSensitive); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockU(FindLen, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; function StrReplace(const Find, Replace, S: String; const AsciiCaseSensitive: Boolean): String; var FindLen : Integer; Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin FindLen := Length(Find); if FindLen = 0 then // nothing to find begin Result := S; exit; end; I := PosStr(Find, S, 1, AsciiCaseSensitive); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I, FindLen); I := PosStr(Find, S, I, AsciiCaseSensitive); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlock(FindLen, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$IFDEF SupportAnsiString} function StrReplaceA(const Find: ByteCharSet; const Replace, S: AnsiString): AnsiString; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharSetA(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharSetA(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockA(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$ENDIF} function StrReplaceB(const Find: ByteCharSet; const Replace, S: RawByteString): RawByteString; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharSetB(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharSetB(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockB(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; function StrReplaceU(const Find: ByteCharSet; const Replace, S: UnicodeString): UnicodeString; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharSetU(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharSetU(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockU(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; function StrReplace(const Find: ByteCharSet; const Replace, S: String): String; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharSet(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharSet(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlock(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$IFDEF SupportAnsiString} function StrReplaceCharStrA(const Find: AnsiChar; const Replace, S: AnsiString): AnsiString; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharA(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharA(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockA(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$ENDIF} function StrReplaceCharStrU(const Find: WideChar; const Replace, S: UnicodeString): UnicodeString; var Matches : StrReplaceMatchArray; C, I, J, K : Integer; begin I := PosCharU(Find, S, 1); if I = 0 then // not found begin Result := S; exit; end; J := 1; Result := ''; repeat C := 0; repeat Matches[C] := I; Inc(C); Inc(I); I := PosCharU(Find, S, I); until (I = 0) or (C = 4096); if I = 0 then K := Length(S) else K := I - 1; Result := Result + StrReplaceBlockU(1, Replace, S, J, K, C, Matches); J := K + 1; until I = 0; end; {$IFDEF SupportAnsiString} function StrRemoveDupA(const S: AnsiString; const C: AnsiChar): AnsiString; var P, Q : PAnsiChar; D, E : AnsiChar; I, L, M : Integer; R : Boolean; begin L := Length(S); if L <= 1 then begin Result := S; exit; end; // Check for duplicate P := Pointer(S); D := P^; Inc(P); R := False; for I := 2 to L do if (D = C) and (P^ = C) then begin R := True; break; end else begin D := P^; Inc(P); end; if not R then begin Result := S; exit; end; // Remove duplicates Result := S; UniqueString(Result); P := Pointer(S); Q := Pointer(Result); D := P^; Q^ := D; Inc(P); Inc(Q); M := 1; for I := 2 to L do begin E := P^; if (D <> C) or (E <> C) then begin D := E; Q^ := E; Inc(M); Inc(Q); end; Inc(P); end; if M < L then SetLength(Result, M); end; {$ENDIF} function StrRemoveDupU(const S: UnicodeString; const C: WideChar): UnicodeString; var P, Q : PWideChar; D, E : WideChar; I, L, M : Integer; R : Boolean; begin L := Length(S); if L <= 1 then begin Result := S; exit; end; // Check for duplicate P := Pointer(S); D := P^; Inc(P); R := False; for I := 2 to L do if (D = C) and (P^ = C) then begin R := True; break; end else begin D := P^; Inc(P); end; if not R then begin Result := S; exit; end; // Remove duplicates Result := S; {$IFNDEF DELPHI5} UniqueString(Result); {$ENDIF} P := Pointer(S); Q := Pointer(Result); D := P^; Q^ := D; Inc(P); Inc(Q); M := 1; for I := 2 to L do begin E := P^; if (D <> C) or (E <> C) then begin D := E; Q^ := E; Inc(M); Inc(Q); end; Inc(P); end; if M < L then SetLength(Result, M); end; function StrRemoveDup(const S: String; const C: Char): String; var P, Q : PChar; D, E : Char; I, L, M : Integer; R : Boolean; begin L := Length(S); if L <= 1 then begin Result := S; exit; end; // Check for duplicate P := Pointer(S); D := P^; Inc(P); R := False; for I := 2 to L do if (D = C) and (P^ = C) then begin R := True; break; end else begin D := P^; Inc(P); end; if not R then begin Result := S; exit; end; // Remove duplicates Result := S; UniqueString(Result); P := Pointer(S); Q := Pointer(Result); D := P^; Q^ := D; Inc(P); Inc(Q); M := 1; for I := 2 to L do begin E := P^; if (D <> C) or (E <> C) then begin D := E; Q^ := E; Inc(M); Inc(Q); end; Inc(P); end; if M < L then SetLength(Result, M); end; {$IFDEF SupportAnsiString} function StrRemoveCharA(const S: AnsiString; const C: AnsiChar): AnsiString; var P, Q : PAnsiChar; I, L, M : Integer; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin if P^ = C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin if P^ <> C then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; {$ENDIF} function StrRemoveCharU(const S: UnicodeString; const C: WideChar): UnicodeString; var P, Q : PWideChar; I, L, M : Integer; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin if P^ = C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin if P^ <> C then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; function StrRemoveChar(const S: String; const C: Char): String; var P, Q : PChar; I, L, M : Integer; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin if P^ = C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin if P^ <> C then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; {$IFDEF SupportAnsiString} function StrRemoveCharSetA(const S: AnsiString; const C: ByteCharSet): AnsiString; var P, Q : PAnsiChar; I, L, M : Integer; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin if P^ in C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin if not (P^ in C) then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; {$ENDIF} function StrRemoveCharSetB(const S: RawByteString; const C: ByteCharSet): RawByteString; var P, Q : PByteChar; I, L, M : Integer; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin if P^ in C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin if not (P^ in C) then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; function StrRemoveCharSetU(const S: UnicodeString; const C: ByteCharSet): UnicodeString; var P, Q : PWideChar; D : WideChar; I, L, M : Integer; R : Boolean; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin D := P^; if Ord(D) <= $FF then if ByteChar(Ord(D)) in C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin D := P^; R := Ord(D) > $FF; if not R then R := not (ByteChar(Ord(D)) in C); if R then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; function StrRemoveCharSet(const S: String; const C: ByteCharSet): String; var P, Q : PChar; D : Char; I, L, M : Integer; R : Boolean; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := 0; P := Pointer(S); for I := 1 to L do begin D := P^; {$IFDEF StringIsUnicode} if Ord(D) <= $FF then {$ENDIF} if ByteChar(Ord(D)) in C then Inc(M); Inc(P); end; if M = 0 then begin Result := S; exit; end; SetLength(Result, L - M); Q := Pointer(Result); P := Pointer(S); for I := 1 to L do begin D := P^; {$IFDEF StringIsUnicode} R := Ord(D) > $FF; if not R then {$ENDIF} R := not (ByteChar(Ord(D)) in C); if R then begin Q^ := P^; Inc(Q); end; Inc(P); end; end; { } { Split } { } {$IFDEF SupportAnsiString} function StrSplitAtA(const S: AnsiString; const C: AnsiString; var Left, Right: AnsiString; const AsciiCaseSensitive: Boolean; const Optional: Boolean): Boolean; var I : Integer; T : AnsiString; begin I := PosStrA(C, S, 1, AsciiCaseSensitive); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFromA(T, I + Length(C)); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$ENDIF} function StrSplitAtB(const S: RawByteString; const C: RawByteString; var Left, Right: RawByteString; const AsciiCaseSensitive: Boolean; const Optional: Boolean): Boolean; var I : Integer; T : RawByteString; begin I := PosStrB(C, S, 1, AsciiCaseSensitive); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFromB(T, I + Length(C)); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; function StrSplitAtU(const S: UnicodeString; const C: UnicodeString; var Left, Right: UnicodeString; const AsciiCaseSensitive: Boolean; const Optional: Boolean): Boolean; var I : Integer; T : UnicodeString; begin I := PosStrU(C, S, 1, AsciiCaseSensitive); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFromU(T, I + Length(C)); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; function StrSplitAt(const S: String; const C: String; var Left, Right: String; const AsciiCaseSensitive: Boolean; const Optional: Boolean): Boolean; var I : Integer; T : String; begin I := PosStr(C, S, 1, AsciiCaseSensitive); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFrom(T, I + Length(C)); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$IFDEF SupportAnsiString} function StrSplitAtCharA(const S: AnsiString; const C: AnsiChar; var Left, Right: AnsiString; const Optional: Boolean): Boolean; var I : Integer; T : AnsiString; begin I := PosCharA(C, S); Result := I > 0; if Result then begin T := S; // add reference to S (in case it is also Left or Right) Left := Copy(T, 1, I - 1); Right := CopyFromA(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$ENDIF} function StrSplitAtCharB(const S: RawByteString; const C: ByteChar; var Left, Right: RawByteString; const Optional: Boolean): Boolean; var I : Integer; T : RawByteString; begin I := PosCharB(C, S); Result := I > 0; if Result then begin T := S; // add reference to S (in case it is also Left or Right) Left := Copy(T, 1, I - 1); Right := CopyFromB(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; function StrSplitAtCharU(const S: UnicodeString; const C: WideChar; var Left, Right: UnicodeString; const Optional: Boolean): Boolean; var I : Integer; T : UnicodeString; begin I := PosCharU(C, S); Result := I > 0; if Result then begin T := S; // add reference to S (in case it is also Left or Right) Left := Copy(T, 1, I - 1); Right := CopyFromU(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; function StrSplitAtChar(const S: String; const C: Char; var Left, Right: String; const Optional: Boolean): Boolean; var I : Integer; T : String; begin I := PosChar(C, S); Result := I > 0; if Result then begin T := S; // add reference to S (in case it is also Left or Right) Left := Copy(T, 1, I - 1); Right := CopyFrom(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$IFDEF SupportAnsiString} function StrSplitAtCharSetA(const S: AnsiString; const C: ByteCharSet; var Left, Right: AnsiString; const Optional: Boolean): Boolean; var I : Integer; T : AnsiString; begin I := PosCharSetA(C, S); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFromA(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$ENDIF} function StrSplitAtCharSetB(const S: RawByteString; const C: ByteCharSet; var Left, Right: RawByteString; const Optional: Boolean): Boolean; var I : Integer; T : RawByteString; begin I := PosCharSetB(C, S); Result := I > 0; if Result then begin T := S; Left := Copy(T, 1, I - 1); Right := CopyFromB(T, I + 1); end else begin if Optional then Left := S else Left := ''; Right := ''; end; end; {$IFDEF SupportAnsiString} function StrSplitA(const S, D: AnsiString): AnsiStringArray; var I, J, L, M : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; M := Length(D); if M = 0 then begin SetLength(Result, 1); Result[0] := S; exit; end; // Count L := 0; I := 1; repeat I := PosStrA(D, S, I, True); if I = 0 then break; Inc(L); Inc(I, M); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosStrA(D, S, I, True); if J = 0 then begin Result[L] := CopyFromA(S, I); break; end; Result[L] := CopyRangeA(S, I, J - 1); Inc(L); I := J + M; until False; end; {$ENDIF} function StrSplitB(const S, D: RawByteString): RawByteStringArray; var I, J, L, M : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; M := Length(D); if M = 0 then begin SetLength(Result, 1); Result[0] := S; exit; end; // Count L := 0; I := 1; repeat I := PosStrB(D, S, I, True); if I = 0 then break; Inc(L); Inc(I, M); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosStrB(D, S, I, True); if J = 0 then begin Result[L] := CopyFromB(S, I); break; end; Result[L] := CopyRangeB(S, I, J - 1); Inc(L); I := J + M; until False; end; function StrSplitU(const S, D: UnicodeString): UnicodeStringArray; var I, J, L, M : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; M := Length(D); if M = 0 then begin SetLength(Result, 1); Result[0] := S; exit; end; // Count L := 0; I := 1; repeat I := PosStrU(D, S, I, True); if I = 0 then break; Inc(L); Inc(I, M); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosStrU(D, S, I, True); if J = 0 then begin Result[L] := CopyFromU(S, I); break; end; Result[L] := CopyRangeU(S, I, J - 1); Inc(L); I := J + M; until False; end; function StrSplit(const S, D: String): StringArray; var I, J, L, M : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; M := Length(D); if M = 0 then begin SetLength(Result, 1); Result[0] := S; exit; end; // Count L := 0; I := 1; repeat I := PosStr(D, S, I, True); if I = 0 then break; Inc(L); Inc(I, M); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosStr(D, S, I, True); if J = 0 then begin Result[L] := CopyFrom(S, I); break; end; Result[L] := CopyRange(S, I, J - 1); Inc(L); I := J + M; until False; end; {$IFDEF SupportAnsiString} function StrSplitCharA(const S: AnsiString; const D: AnsiChar): AnsiStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharA(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharA(D, S, I); if J = 0 then begin Result[L] := CopyFromA(S, I); break; end; Result[L] := CopyRangeA(S, I, J - 1); Inc(L); I := J + 1; until False; end; {$ENDIF} function StrSplitCharB(const S: RawByteString; const D: ByteChar): RawByteStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharB(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharB(D, S, I); if J = 0 then begin Result[L] := CopyFromB(S, I); break; end; Result[L] := CopyRangeB(S, I, J - 1); Inc(L); I := J + 1; until False; end; function StrSplitCharU(const S: UnicodeString; const D: WideChar): UnicodeStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharU(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharU(D, S, I); if J = 0 then begin Result[L] := CopyFromU(S, I); break; end; Result[L] := CopyRangeU(S, I, J - 1); Inc(L); I := J + 1; until False; end; function StrSplitChar(const S: String; const D: Char): StringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosChar(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosChar(D, S, I); if J = 0 then begin Result[L] := CopyFrom(S, I); break; end; Result[L] := CopyRange(S, I, J - 1); Inc(L); I := J + 1; until False; end; {$IFDEF SupportAnsiString} function StrSplitCharSetA(const S: AnsiString; const D: ByteCharSet): AnsiStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharSetA(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharSetA(D, S, I); if J = 0 then begin Result[L] := CopyFromA(S, I); break; end; Result[L] := CopyRangeA(S, I, J - 1); Inc(L); I := J + 1; until False; end; {$ENDIF} function StrSplitCharSetB(const S: RawByteString; const D: ByteCharSet): RawByteStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharSetB(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharSetB(D, S, I); if J = 0 then begin Result[L] := CopyFromB(S, I); break; end; Result[L] := CopyRangeB(S, I, J - 1); Inc(L); I := J + 1; until False; end; function StrSplitCharSetU(const S: UnicodeString; const D: ByteCharSet): UnicodeStringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharSetU(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharSetU(D, S, I); if J = 0 then begin Result[L] := CopyFromU(S, I); break; end; Result[L] := CopyRangeU(S, I, J - 1); Inc(L); I := J + 1; until False; end; function StrSplitCharSet(const S: String; const D: ByteCharSet): StringArray; var I, J, L : Integer; begin // Check valid parameters if S = '' then begin Result := nil; exit; end; // Count L := 0; I := 1; repeat I := PosCharSet(D, S, I); if I = 0 then break; Inc(L); Inc(I); until False; SetLength(Result, L + 1); if L = 0 then begin // No split Result[0] := S; exit; end; // Split L := 0; I := 1; repeat J := PosCharSet(D, S, I); if J = 0 then begin Result[L] := CopyFrom(S, I); break; end; Result[L] := CopyRange(S, I, J - 1); Inc(L); I := J + 1; until False; end; {$IFDEF SupportAnsiString} function StrSplitWords(const S: AnsiString; const C: ByteCharSet): AnsiStringArray; var P, Q : PAnsiChar; L, M : Integer; N : Integer; T : AnsiString; begin Result := nil; L := Length(S); P := Pointer(S); Q := P; M := 0; N := 0; while L > 0 do if P^ in C then begin Inc(P); Dec(L); Inc(M); end else begin if M > 0 then begin SetLength(T, M); MoveMem(Q^, Pointer(T)^, M); SetLength(Result, N + 1); Result[N] := T; Inc(N); end; M := 0; Inc(P); Dec(L); Q := P; end; if M > 0 then begin SetLength(T, M); MoveMem(Q^, Pointer(T)^, M); SetLength(Result, N + 1); Result[N] := T; end; end; {$ENDIF} {$IFDEF SupportAnsiString} function StrJoinA(const S: array of AnsiString; const D: AnsiString): AnsiString; var I, L, M, C : Integer; P : PAnsiChar; T : AnsiString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := Length(D); SetLength(Result, StringsTotalLengthA(S) + (L - 1) * M); P := Pointer(Result); for I := 0 to L - 1 do begin if (I > 0) and (M > 0) then begin MoveMem(Pointer(D)^, P^, M); Inc(P, M); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C); Inc(P, C); end; end; end; {$ENDIF} function StrJoinB(const S: array of RawByteString; const D: RawByteString): RawByteString; var I, L, M, C : Integer; P : PByteChar; T : RawByteString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := Length(D); SetLength(Result, StringsTotalLengthB(S) + (L - 1) * M); P := Pointer(Result); for I := 0 to L - 1 do begin if (I > 0) and (M > 0) then begin MoveMem(Pointer(D)^, P^, M); Inc(P, M); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C); Inc(P, C); end; end; end; function StrJoinU(const S: array of UnicodeString; const D: UnicodeString): UnicodeString; var I, L, M, C : Integer; P : PWideChar; T : UnicodeString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := Length(D); SetLength(Result, StringsTotalLengthU(S) + (L - 1) * M); P := Pointer(Result); for I := 0 to L - 1 do begin if (I > 0) and (M > 0) then begin MoveMem(Pointer(D)^, P^, M * SizeOf(WideChar)); Inc(P, M); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C * SizeOf(WideChar)); Inc(P, C); end; end; end; function StrJoin(const S: array of String; const D: String): String; var I, L, M, C : Integer; P : PChar; T : String; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; M := Length(D); SetLength(Result, StringsTotalLength(S) + (L - 1) * M); P := Pointer(Result); for I := 0 to L - 1 do begin if (I > 0) and (M > 0) then begin MoveMem(Pointer(D)^, P^, M * SizeOf(Char)); Inc(P, M); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C * SizeOf(Char)); Inc(P, C); end; end; end; {$IFDEF SupportAnsiString} function StrJoinCharA(const S: array of AnsiString; const D: AnsiChar): AnsiString; var I, L, C : Integer; P : PAnsiChar; T : AnsiString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; SetLength(Result, StringsTotalLengthA(S) + L - 1); P := Pointer(Result); for I := 0 to L - 1 do begin if I > 0 then begin P^ := D; Inc(P); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C); Inc(P, C); end; end; end; {$ENDIF} function StrJoinCharB(const S: array of RawByteString; const D: ByteChar): RawByteString; var I, L, C : Integer; P : PByteChar; T : RawByteString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; SetLength(Result, StringsTotalLengthB(S) + L - 1); P := Pointer(Result); for I := 0 to L - 1 do begin if I > 0 then begin P^ := D; Inc(P); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C); Inc(P, C); end; end; end; function StrJoinCharU(const S: array of UnicodeString; const D: WideChar): UnicodeString; var I, L, C : Integer; P : PWideChar; T : UnicodeString; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; SetLength(Result, StringsTotalLengthU(S) + L - 1); P := Pointer(Result); for I := 0 to L - 1 do begin if I > 0 then begin P^ := D; Inc(P); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C * SizeOf(WideChar)); Inc(P, C); end; end; end; function StrJoinChar(const S: array of String; const D: Char): String; var I, L, C : Integer; P : PChar; T : String; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; SetLength(Result, StringsTotalLength(S) + L - 1); P := Pointer(Result); for I := 0 to L - 1 do begin if I > 0 then begin P^ := D; Inc(P); end; T := S[I]; C := Length(T); if C > 0 then begin MoveMem(Pointer(T)^, P^, C * SizeOf(Char)); Inc(P, C); end; end; end; { } { Quoting } { } {$IFDEF SupportAnsiString} function StrHasSurroundingQuotesA(const S: AnsiString; const Quotes: ByteCharSet): Boolean; var P : PAnsiChar; Q : AnsiChar; L : Integer; begin Result := False; L := Length(S); if L >= 2 then begin P := Pointer(S); Q := P^; if Q in Quotes then begin Inc(P, L - 1); if P^ = Q then Result := True; end; end; end; {$ENDIF} function StrHasSurroundingQuotesB(const S: RawByteString; const Quotes: ByteCharSet): Boolean; var P : PByteChar; Q : ByteChar; L : Integer; begin Result := False; L := Length(S); if L >= 2 then begin P := Pointer(S); Q := P^; if Q in Quotes then begin Inc(P, L - 1); if P^ = Q then Result := True; end; end; end; function StrHasSurroundingQuotesU(const S: UnicodeString; const Quotes: ByteCharSet): Boolean; var P : PWideChar; Q : WideChar; L : Integer; begin Result := False; L := Length(S); if L >= 2 then begin P := Pointer(S); Q := P^; if WideCharInCharSet(Q, Quotes) then begin Inc(P, L - 1); if P^ = Q then Result := True; end; end; end; function StrHasSurroundingQuotes(const S: String; const Quotes: ByteCharSet): Boolean; var P : PChar; Q : Char; L : Integer; begin Result := False; L := Length(S); if L >= 2 then begin P := Pointer(S); Q := P^; {$IFDEF CharIsWide} if Ord(Q) <= $FF then {$ENDIF} if ByteChar(Byte(Q)) in Quotes then begin Inc(P, L - 1); if P^ = Q then Result := True; end; end; end; {$IFDEF SupportAnsiString} function StrRemoveSurroundingQuotesA(const S: AnsiString; const Quotes: ByteCharSet): AnsiString; begin if StrHasSurroundingQuotesA(S, Quotes) then Result := Copy(S, 2, Length(S) - 2) else Result := S; end; {$ENDIF} function StrRemoveSurroundingQuotesB(const S: RawByteString; const Quotes: ByteCharSet): RawByteString; begin if StrHasSurroundingQuotesB(S, Quotes) then Result := Copy(S, 2, Length(S) - 2) else Result := S; end; function StrRemoveSurroundingQuotesU(const S: UnicodeString; const Quotes: ByteCharSet): UnicodeString; begin if StrHasSurroundingQuotesU(S, Quotes) then Result := Copy(S, 2, Length(S) - 2) else Result := S; end; function StrRemoveSurroundingQuotes(const S: String; const Quotes: ByteCharSet): String; begin if StrHasSurroundingQuotes(S, Quotes) then Result := Copy(S, 2, Length(S) - 2) else Result := S; end; {$IFDEF SupportAnsiString} function StrQuoteA(const S: AnsiString; const Quote: AnsiChar): AnsiString; begin Result := Quote + StrReplaceA(Quote, DupCharA(Quote, 2), S) + Quote; end; {$ENDIF} function StrQuoteB(const S: RawByteString; const Quote: AnsiChar): RawByteString; begin Result := Quote + StrReplaceB(Quote, DupCharB(Quote, 2), S) + Quote; end; function StrQuoteU(const S: UnicodeString; const Quote: WideChar): UnicodeString; begin Result := Quote + StrReplaceU(Quote, DupCharU(Quote, 2), S) + Quote; end; function StrQuote(const S: String; const Quote: Char): String; begin Result := Quote + StrReplace(Quote, DupChar(Quote, 2), S) + Quote; end; {$IFDEF SupportAnsiString} function StrUnquoteA(const S: AnsiString): AnsiString; var Quote : AnsiChar; begin if not StrHasSurroundingQuotesA(S, csQuotes) then begin Result := S; exit; end; Quote := S[1]; Result := StrRemoveSurroundingQuotesA(S, csQuotes); Result := StrReplaceA(DupCharA(Quote, 2), Quote, Result); end; {$ENDIF} function StrUnquoteB(const S: RawByteString): RawByteString; var Quote : ByteChar; begin if not StrHasSurroundingQuotesB(S, csQuotes) then begin Result := S; exit; end; Quote := S[1]; Result := StrRemoveSurroundingQuotesB(S, csQuotes); Result := StrReplaceB(DupCharB(Quote, 2), Quote, Result); end; function StrUnquoteU(const S: UnicodeString): UnicodeString; var Quote : WideChar; begin if not StrHasSurroundingQuotesU(S, csQuotes) then begin Result := S; exit; end; Quote := S[1]; Result := StrRemoveSurroundingQuotesU(S, csQuotes); Result := StrReplaceU(DupCharU(Quote, 2), Quote, Result); end; function StrUnquote(const S: String): String; var Quote : Char; begin if not StrHasSurroundingQuotes(S, csQuotes) then begin Result := S; exit; end; Quote := S[1]; Result := StrRemoveSurroundingQuotes(S, csQuotes); Result := StrReplace(DupChar(Quote, 2), Quote, Result); end; {$IFDEF SupportAnsiString} function StrMatchQuotedStrA(const S: AnsiString; const ValidQuotes: ByteCharSet; const Index: Integer): Integer; var Quote : AnsiChar; I, L : Integer; R : Boolean; begin L := Length(S); if (Index < 1) or (L < Index + 1) or not (S[Index] in ValidQuotes) then begin Result := 0; exit; end; Quote := S[Index]; I := Index + 1; R := False; repeat I := PosCharA(Quote, S, I); if I = 0 then // no closing quote begin Result := 0; exit; end else if I = L then // closing quote is last character R := True else if S[I + 1] <> Quote then // not double quoted R := True else Inc(I, 2); until R; Result := I - Index + 1; end; function StrIsQuotedStrA(const S: AnsiString; const ValidQuotes: ByteCharSet): Boolean; var L : Integer; begin L := Length(S); if (L < 2) or (S[1] <> S[L]) or not (S[1] in ValidQuotes) then Result := False else Result := StrMatchQuotedStrA(S, ValidQuotes) = L; end; function StrFindClosingQuoteA(const S: AnsiString; const OpenQuotePos: Integer): Integer; var I : Integer; OpenQuote : AnsiChar; R : Boolean; begin if (OpenQuotePos <= 0) or (OpenQuotePos > Length(S)) then begin Result := 0; exit; end; I := OpenQuotePos; OpenQuote := S[I]; repeat I := PosCharA(OpenQuote, S, I + 1); if I = 0 then begin Result := 0; exit; end; R := (I = Length(S)) or (S[I + 1] <> OpenQuote); if not R then Inc(I); until R; Result := I; end; {$ENDIF} { } { Bracketing } { } function StrFindClosingBracketB(const S: RawByteString; const OpenBracketPos: Integer; const CloseBracket: ByteChar): Integer; var OpenBracket : ByteChar; Brackets : ByteCharSet; I, C : Integer; begin Result := 0; I := OpenBracketPos; if (I <= 0) or (I > Length(S)) then exit; OpenBracket := S[OpenBracketPos]; Brackets := [OpenBracket, CloseBracket]; C := 1; repeat I := PosCharSetB(Brackets, S, I + 1); if I = 0 then exit; if S[I] = OpenBracket then Inc(C) else Dec(C); until C = 0; Result := I; end; { } { Escaping } { } function StrHexEscapeB(const S: RawByteString; const C: ByteCharSet; const EscPrefix: RawByteString; const EscSuffix: RawByteString; const UpperHex: Boolean; const TwoDigitHex: Boolean): RawByteString; var I, J : Integer; HexStr : RawByteString; begin Result := ''; J := 1; I := PosCharSetB(C, S); while I > 0 do begin if TwoDigitHex then HexStr := Word32ToHexB(Ord(S[I]), 2) else HexStr := Word32ToHexB(Ord(S[I]), 1); if UpperHex then AsciiConvertUpperB(HexStr) else AsciiConvertLowerB(HexStr); Result := Result + CopyRangeB(S, J, I - 1) + EscPrefix + HexStr + EscSuffix; J := I + 1; I := PosCharSetB(C, S, J); end; if J = 1 then Result := S else Result := Result + CopyFromB(S, J); end; function StrHexUnescapeB(const S: RawByteString; const EscPrefix: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; var I, J, L, M : Integer; V : Byte; R : RawByteString; H1, H2 : ByteChar; H2Ch : Boolean; begin R := ''; L := Length(S); if L = 0 then exit; M := Length(EscPrefix); if M = 0 then exit; // Replace J := 1; repeat I := PosStrB(EscPrefix, S, J, AsciiCaseSensitive); if I > 0 then begin R := R + CopyRangeB(S, J, I - 1); Inc(I, M); if I <= L then begin H1 := S[I]; if IsHexByteCharDigit(H1) then begin H2Ch := False; if I < L then begin H2 := S[I + 1]; if IsHexByteCharDigit(H2) then begin V := HexByteCharDigitToInt(H1) * 16 + HexByteCharDigitToInt(H2); R := R + ByteChar(V); Inc(I, 2); H2Ch := True; end; end; if not H2Ch then begin V := HexByteCharDigitToInt(H1); R := R + ByteChar(V); Inc(I); end; end; end; J := I; end; until I = 0; if (I = 0) and (J = 0) then Result := S else Result := R + CopyFromB(S, J); end; {$IFDEF SupportAnsiString} function StrCharEscapeA(const S: AnsiString; const C: array of AnsiChar; const EscPrefix: AnsiString; const EscSeq: array of AnsiString): AnsiString; var I, J, L : Integer; F : ByteCharSet; T : AnsiChar; Lookup : Array[AnsiChar] of Integer; begin L := Length(C); if L = 0 then begin Result := S; exit; end; if L <> Length(EscSeq) then raise EStrInvalidArgument.Create('Invalid arguments'); // Initialize lookup ZeroMem(Lookup, Sizeof(Lookup)); F := []; for I := 0 to Length(C) - 1 do begin T := C[I]; Include(F, T); Lookup[T] := I; end; // Replace Result := ''; J := 1; I := PosCharSetA(F, S); while I > 0 do begin Result := Result + CopyRangeA(S, J, I - 1) + EscPrefix + EscSeq[Lookup[S[I]]]; J := I + 1; I := PosCharSetA(F, S, J); end; if J = 1 then Result := S else Result := Result + CopyFromA(S, J); end; function StrCharUnescapeA(const S: AnsiString; const EscPrefix: AnsiString; const C: array of AnsiChar; const Replace: array of AnsiString; const PrefixAsciiCaseSensitive: Boolean; const AlwaysDropPrefix: Boolean): AnsiString; var I, J, L : Integer; F, G, M : Integer; D : AnsiChar; begin if High(C) <> High(Replace) then raise EStrInvalidArgument.Create('Invalid arguments'); L := Length(EscPrefix); M := Length(S); if (L = 0) or (M <= L) then begin Result := S; exit; end; // Replace Result := ''; J := 1; repeat I := PosStrA(EscPrefix, S, J, PrefixAsciiCaseSensitive); if I > 0 then begin G := -1; if I < Length(S) then begin D := S[I + L]; for F := 0 to High(C) do if C[F] = D then begin G := F; break; end; end; Result := Result + CopyRangeA(S, J, I - 1); if G >= 0 then Result := Result + Replace[G] else if not AlwaysDropPrefix then Result := Result + EscPrefix; J := I + L + 1; end; until I = 0; if (I = 0) and (J = 0) then Result := S else Result := Result + CopyFromA(S, J); end; {$ENDIF} function StrCharUnescapeU(const S: UnicodeString; const EscPrefix: UnicodeString; const C: array of WideChar; const Replace: array of UnicodeString; const PrefixAsciiCaseSensitive: Boolean; const AlwaysDropPrefix: Boolean): UnicodeString; var I, J, L : Integer; F, G, M : Integer; D : WideChar; begin if High(C) <> High(Replace) then raise EStrInvalidArgument.Create('Invalid arguments'); L := Length(EscPrefix); M := Length(S); if (L = 0) or (M <= L) then begin Result := S; exit; end; // Replace Result := ''; J := 1; repeat I := PosStrU(EscPrefix, S, J, PrefixAsciiCaseSensitive); if I > 0 then begin G := -1; if I < Length(S) then begin D := S[I + L]; for F := 0 to High(C) do if C[F] = D then begin G := F; break; end; end; Result := Result + CopyRangeU(S, J, I - 1); if G >= 0 then Result := Result + Replace[G] else if not AlwaysDropPrefix then Result := Result + EscPrefix; J := I + L + 1; end; until I = 0; if (I = 0) and (J = 0) then Result := S else Result := Result + CopyFromU(S, J); end; {$IFDEF SupportAnsiString} function StrCStyleEscapeA(const S: AnsiString): AnsiString; begin Result := StrCharEscapeA(S, [AsciiCR, AsciiLF, AsciiNULL, AsciiBEL, AsciiBS, AsciiESC, AsciiHT, AsciiFF, AsciiVT, '\'], '\', ['n', 'l', '0', 'a', 'b', 'e', 't', 'f', 'v', '\']); end; function StrCStyleUnescapeA(const S: AnsiString): AnsiString; begin Result := StrCharUnescapeA(S, '\', ['n', 'l', '0', 'a', 'b', 'e', 't', 'f', 'v', '\', '''', '"', '?'], [AsciiCR, AsciiLF, AsciiNULL, AsciiBEL, AsciiBS, AsciiESC, AsciiHT, AsciiFF, AsciiVT, '\', '''', '"', '?'], True, False); Result := StrHexUnescapeB(Result, '\x', True); end; {$ENDIF} { } { Prefix and Suffix } { } {$IFDEF SupportAnsiString} function StrInclPrefixA(const S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean): AnsiString; begin if not StrMatchLeftA(S, Prefix, AsciiCaseSensitive) then Result := Prefix + S else Result := S; end; {$ENDIF} function StrInclPrefixB(const S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; begin if not StrMatchLeftB(S, Prefix, AsciiCaseSensitive) then Result := Prefix + S else Result := S; end; function StrInclPrefixU(const S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean): UnicodeString; begin if not StrMatchLeftU(S, Prefix, AsciiCaseSensitive) then Result := Prefix + S else Result := S; end; function StrInclPrefix(const S: String; const Prefix: String; const AsciiCaseSensitive: Boolean): String; begin if not StrMatchLeft(S, Prefix, AsciiCaseSensitive) then Result := Prefix + S else Result := S; end; {$IFDEF SupportAnsiString} function StrInclSuffixA(const S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean): AnsiString; begin if not StrMatchRightA(S, Suffix, AsciiCaseSensitive) then Result := S + Suffix else Result := S; end; {$ENDIF} function StrInclSuffixB(const S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; begin if not StrMatchRightB(S, Suffix, AsciiCaseSensitive) then Result := S + Suffix else Result := S; end; function StrInclSuffixU(const S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean): UnicodeString; begin if not StrMatchRightU(S, Suffix, AsciiCaseSensitive) then Result := S + Suffix else Result := S; end; function StrInclSuffix(const S: String; const Suffix: String; const AsciiCaseSensitive: Boolean): String; begin if not StrMatchRight(S, Suffix, AsciiCaseSensitive) then Result := S + Suffix else Result := S; end; {$IFDEF SupportAnsiString} function StrExclPrefixA(const S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean): AnsiString; begin if StrMatchLeftA(S, Prefix, AsciiCaseSensitive) then Result := CopyFromA(S, Length(Prefix) + 1) else Result := S; end; {$ENDIF} function StrExclPrefixB(const S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; begin if StrMatchLeftB(S, Prefix, AsciiCaseSensitive) then Result := CopyFromB(S, Length(Prefix) + 1) else Result := S; end; function StrExclPrefixU(const S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean): UnicodeString; begin if StrMatchLeftU(S, Prefix, AsciiCaseSensitive) then Result := CopyFromU(S, Length(Prefix) + 1) else Result := S; end; function StrExclPrefix(const S: String; const Prefix: String; const AsciiCaseSensitive: Boolean): String; begin if StrMatchLeft(S, Prefix, AsciiCaseSensitive) then Result := CopyFrom(S, Length(Prefix) + 1) else Result := S; end; {$IFDEF SupportAnsiString} function StrExclSuffixA(const S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean): AnsiString; begin if StrMatchRightA(S, Suffix, AsciiCaseSensitive) then Result := Copy(S, 1, Length(S) - Length(Suffix)) else Result := S; end; {$ENDIF} function StrExclSuffixB(const S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean): RawByteString; begin if StrMatchRightB(S, Suffix, AsciiCaseSensitive) then Result := Copy(S, 1, Length(S) - Length(Suffix)) else Result := S; end; function StrExclSuffixU(const S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean): UnicodeString; begin if StrMatchRightU(S, Suffix, AsciiCaseSensitive) then Result := Copy(S, 1, Length(S) - Length(Suffix)) else Result := S; end; function StrExclSuffix(const S: String; const Suffix: String; const AsciiCaseSensitive: Boolean): String; begin if StrMatchRight(S, Suffix, AsciiCaseSensitive) then Result := Copy(S, 1, Length(S) - Length(Suffix)) else Result := S; end; {$IFDEF SupportAnsiString} procedure StrEnsurePrefixA(var S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean); var L, M : Integer; P : PAnsiChar; begin if (Prefix <> '') and not StrMatchLeftA(S, Prefix, AsciiCaseSensitive) then begin L := Length(S); M := Length(Prefix); SetLength(S, L + M); if L > 0 then begin P := Pointer(S); Inc(P, M); MoveMem(Pointer(S)^, P^, L); end; MoveMem(Pointer(Prefix)^, Pointer(S)^, M); end; end; {$ENDIF} procedure StrEnsurePrefixB(var S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean); begin if (Prefix <> '') and not StrMatchLeftB(S, Prefix, AsciiCaseSensitive) then S := Prefix + S; end; procedure StrEnsurePrefixU(var S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean); begin if (Prefix <> '') and not StrMatchLeftU(S, Prefix, AsciiCaseSensitive) then S := Prefix + S; end; procedure StrEnsurePrefix(var S: String; const Prefix: String; const AsciiCaseSensitive: Boolean); begin if (Prefix <> '') and not StrMatchLeft(S, Prefix, AsciiCaseSensitive) then S := Prefix + S; end; {$IFDEF SupportAnsiString} procedure StrEnsureSuffixA(var S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean); var L, M : Integer; P : PAnsiChar; begin if (Suffix <> '') and not StrMatchRightA(S, Suffix, AsciiCaseSensitive) then begin L := Length(S); M := Length(Suffix); SetLength(S, L + M); P := Pointer(S); Inc(P, L); MoveMem(Pointer(Suffix)^, P^, M); end; end; {$ENDIF} procedure StrEnsureSuffixB(var S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean); begin if (Suffix <> '') and not StrMatchRightB(S, Suffix, AsciiCaseSensitive) then S := S + Suffix; end; procedure StrEnsureSuffixU(var S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean); begin if (Suffix <> '') and not StrMatchRightU(S, Suffix, AsciiCaseSensitive) then S := S + Suffix; end; procedure StrEnsureSuffix(var S: String; const Suffix: String; const AsciiCaseSensitive: Boolean); begin if (Suffix <> '') and not StrMatchRight(S, Suffix, AsciiCaseSensitive) then S := S + Suffix; end; {$IFDEF SupportAnsiString} procedure StrEnsureNoPrefixA(var S: AnsiString; const Prefix: AnsiString; const AsciiCaseSensitive: Boolean); var L, M : Integer; P : PAnsiChar; begin if StrMatchLeftA(S, Prefix, AsciiCaseSensitive) then begin L := Length(S); M := Length(Prefix); P := Pointer(S); Inc(P, M); MoveMem(P^, Pointer(S)^, L - M); SetLength(S, L - M); end; end; {$ENDIF} procedure StrEnsureNoPrefixB(var S: RawByteString; const Prefix: RawByteString; const AsciiCaseSensitive: Boolean); begin if StrMatchLeftB(S, Prefix, AsciiCaseSensitive) then Delete(S, 1, Length(Prefix)); end; procedure StrEnsureNoPrefixU(var S: UnicodeString; const Prefix: UnicodeString; const AsciiCaseSensitive: Boolean); begin if StrMatchLeftU(S, Prefix, AsciiCaseSensitive) then Delete(S, 1, Length(Prefix)); end; procedure StrEnsureNoPrefix(var S: String; const Prefix: String; const AsciiCaseSensitive: Boolean); begin if StrMatchLeft(S, Prefix, AsciiCaseSensitive) then Delete(S, 1, Length(Prefix)); end; {$IFDEF SupportAnsiString} procedure StrEnsureNoSuffixA(var S: AnsiString; const Suffix: AnsiString; const AsciiCaseSensitive: Boolean); begin if StrMatchRightA(S, Suffix, AsciiCaseSensitive) then SetLength(S, Length(S) - Length(Suffix)); end; {$ENDIF} procedure StrEnsureNoSuffixB(var S: RawByteString; const Suffix: RawByteString; const AsciiCaseSensitive: Boolean); begin if StrMatchRightB(S, Suffix, AsciiCaseSensitive) then SetLength(S, Length(S) - Length(Suffix)); end; procedure StrEnsureNoSuffixU(var S: UnicodeString; const Suffix: UnicodeString; const AsciiCaseSensitive: Boolean); begin if StrMatchRightU(S, Suffix, AsciiCaseSensitive) then SetLength(S, Length(S) - Length(Suffix)); end; procedure StrEnsureNoSuffix(var S: String; const Suffix: String; const AsciiCaseSensitive: Boolean); begin if StrMatchRight(S, Suffix, AsciiCaseSensitive) then SetLength(S, Length(S) - Length(Suffix)); end; { } { Reverse } { } {$IFDEF SupportAnsiString} function StrReverseA(const S: AnsiString): AnsiString; var I, L : Integer; P, Q : PAnsiChar; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; if L = 1 then begin Result := S; exit; end; SetLength(Result, L); P := Pointer(S); Q := Pointer(Result); Inc(Q, L - 1); for I := 1 to L do begin Q^ := P^; Dec(Q); Inc(P); end; end; {$ENDIF} function StrReverseB(const S: RawByteString): RawByteString; var I, L : Integer; P, Q : PByteChar; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; if L = 1 then begin Result := S; exit; end; SetLength(Result, L); P := Pointer(S); Q := Pointer(Result); Inc(Q, L - 1); for I := 1 to L do begin Q^ := P^; Dec(Q); Inc(P); end; end; function StrReverseU(const S: UnicodeString): UnicodeString; var I, L : Integer; P, Q : PWideChar; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; if L = 1 then begin Result := S; exit; end; SetLength(Result, L); P := Pointer(S); Q := Pointer(Result); Inc(Q, L - 1); for I := 1 to L do begin Q^ := P^; Dec(Q); Inc(P); end; end; function StrReverse(const S: String): String; var I, L : Integer; P, Q : PChar; begin L := Length(S); if L = 0 then begin Result := ''; exit; end; if L = 1 then begin Result := S; exit; end; SetLength(Result, L); P := Pointer(S); Q := Pointer(Result); Inc(Q, L - 1); for I := 1 to L do begin Q^ := P^; Dec(Q); Inc(P); end; end; { } { Type conversion } { } {$IFDEF DELPHI5} function StrToFloatDef(const S: String; const Default: Extended): Extended; begin try Result := StrToFloat(S); except Result := Default; end; end; {$ELSE} function StrToFloatDef(const S: String; const Default: Extended): Extended; begin if not TryStrToFloat(S, Result) then Result := Default; end; {$ENDIF} {$IFDEF SupportAnsiString} function BooleanToStrA(const B: Boolean): AnsiString; begin if B then Result := 'True' else Result := 'False'; end; {$ENDIF} function BooleanToStrB(const B: Boolean): RawByteString; begin if B then Result := 'True' else Result := 'False'; end; function BooleanToStrU(const B: Boolean): UnicodeString; begin if B then Result := 'True' else Result := 'False'; end; function BooleanToStr(const B: Boolean): String; begin if B then Result := 'True' else Result := 'False'; end; {$IFDEF SupportAnsiString} function StrToBooleanA(const S: AnsiString): Boolean; begin Result := StrEqualNoAsciiCaseA(S, 'True'); end; {$ENDIF} function StrToBooleanB(const S: RawByteString): Boolean; begin Result := StrEqualNoAsciiCaseB(S, 'True'); end; function StrToBooleanU(const S: UnicodeString): Boolean; begin Result := StrEqualNoAsciiCaseU(S, 'True'); end; function StrToBoolean(const S: String): Boolean; begin Result := StrEqualNoAsciiCase(S, 'True'); end; { } { Dynamic array functions } { } {$IFDEF SupportAnsiString} function StringsTotalLengthA(const S: array of AnsiString): Integer; var I : Integer; begin Result := 0; for I := 0 to Length(S) - 1 do Inc(Result, Length(S[I])); end; {$ENDIF} function StringsTotalLengthB(const S: array of RawByteString): Integer; var I : Integer; begin Result := 0; for I := 0 to Length(S) - 1 do Inc(Result, Length(S[I])); end; function StringsTotalLengthU(const S: array of UnicodeString): Integer; var I : Integer; begin Result := 0; for I := 0 to Length(S) - 1 do Inc(Result, Length(S[I])); end; function StringsTotalLength(const S: array of String): Integer; var I : Integer; begin Result := 0; for I := 0 to Length(S) - 1 do Inc(Result, Length(S[I])); end; {$IFDEF SupportAnsiString} function PosNextNoCaseA(const Find: AnsiString; const V: array of AnsiString; const PrevPos: Integer; const IsSortedAscending: Boolean): Integer; var I, L, H : Integer; begin if IsSortedAscending then // binary search begin if MaxInt(PrevPos + 1, 0) = 0 then // find first begin L := 0; H := Length(V) - 1; repeat I := (L + H) div 2; if StrEqualNoAsciiCaseA(V[I], Find) then begin while (I > 0) and StrEqualNoAsciiCaseA(V[I - 1], Find) do Dec(I); Result := I; exit; end else if StrCompareNoAsciiCaseA(V[I], Find) = 1 then H := I - 1 else L := I + 1; until L > H; Result := -1; end else // find next if PrevPos >= Length(V) - 1 then Result := -1 else if StrEqualNoAsciiCaseA(V[PrevPos + 1], Find) then Result := PrevPos + 1 else Result := -1; end else begin // linear search for I := MaxInt(PrevPos + 1, 0) to Length(V) - 1 do if StrEqualNoAsciiCaseA(V[I], Find) then begin Result := I; exit; end; Result := -1; end; end; {$ENDIF} function PosNextNoCaseB(const Find: RawByteString; const V: array of RawByteString; const PrevPos: Integer; const IsSortedAscending: Boolean): Integer; var I, L, H : Integer; begin if IsSortedAscending then // binary search begin if MaxInt(PrevPos + 1, 0) = 0 then // find first begin L := 0; H := Length(V) - 1; repeat I := (L + H) div 2; if StrEqualNoAsciiCaseB(V[I], Find) then begin while (I > 0) and StrEqualNoAsciiCaseB(V[I - 1], Find) do Dec(I); Result := I; exit; end else if StrCompareNoAsciiCaseB(V[I], Find) = 1 then H := I - 1 else L := I + 1; until L > H; Result := -1; end else // find next if PrevPos >= Length(V) - 1 then Result := -1 else if StrEqualNoAsciiCaseB(V[PrevPos + 1], Find) then Result := PrevPos + 1 else Result := -1; end else begin // linear search for I := MaxInt(PrevPos + 1, 0) to Length(V) - 1 do if StrEqualNoAsciiCaseB(V[I], Find) then begin Result := I; exit; end; Result := -1; end; end; function PosNextNoCaseU(const Find: UnicodeString; const V: array of UnicodeString; const PrevPos: Integer; const IsSortedAscending: Boolean): Integer; var I, L, H : Integer; begin if IsSortedAscending then // binary search begin if MaxInt(PrevPos + 1, 0) = 0 then // find first begin L := 0; H := Length(V) - 1; repeat I := (L + H) div 2; if StrEqualNoAsciiCaseU(V[I], Find) then begin while (I > 0) and StrEqualNoAsciiCaseU(V[I - 1], Find) do Dec(I); Result := I; exit; end else if StrCompareNoAsciiCaseU(V[I], Find) = 1 then H := I - 1 else L := I + 1; until L > H; Result := -1; end else // find next if PrevPos >= Length(V) - 1 then Result := -1 else if StrEqualNoAsciiCaseU(V[PrevPos + 1], Find) then Result := PrevPos + 1 else Result := -1; end else begin // linear search for I := MaxInt(PrevPos + 1, 0) to Length(V) - 1 do if StrEqualNoAsciiCaseU(V[I], Find) then begin Result := I; exit; end; Result := -1; end; end; { } { Natural language } { } function StorageSize(const Bytes: Int64; const ShortFormat: Boolean): String; var Size, Suffix : String; Fmt : String; Len : Integer; begin Fmt := iif(ShortFormat, '%1.0f', '%0.1f'); if Bytes < 1024 then begin Size := IntToStr(Bytes); Suffix := iif(ShortFormat, 'B', 'bytes'); end else if Bytes < 1024 * 1024 then begin Size := Format(Fmt, [Bytes / 1024.0]); Suffix := iif(ShortFormat, 'K', 'KB'); end else if Bytes < 1024 * 1024 * 1024 then begin Size := Format(Fmt, [Bytes / (1024.0 * 1024.0)]); Suffix := iif(ShortFormat, 'M', 'MB'); end else if Bytes < Int64(1024) * 1024 * 1024 * 1024 then begin Size := Format(Fmt, [Bytes / (1024.0 * 1024.0 * 1024.0)]); Suffix := iif(ShortFormat, 'G', 'GB'); end else if Bytes < Int64(1024) * 1024 * 1024 * 1024 * 1024 then begin Size := Format(Fmt, [Bytes / (1024.0 * 1024.0 * 1024.0 * 1024.0)]); Suffix := iif(ShortFormat, 'T', 'TB'); end else begin Size := Format(Fmt, [Bytes / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)]); Suffix := iif(ShortFormat, 'P', 'PB'); end; Len := Length(Size); if Copy(Size, Len - 1, 2) = '.0' then SetLength(Size, Len - 2); Result := Size + ' ' + Suffix; end; function TransferRate(const Bytes, MillisecondsElapsed: Int64; const ShortFormat: Boolean): String; begin if MillisecondsElapsed <= 0 then Result := '' else Result := StorageSize(Trunc(Bytes / (MillisecondsElapsed / 1000.0)), ShortFormat) + '/s'; end; { } { Test cases } { } {$IFDEF STRINGS_TEST} {$ASSERTIONS ON} procedure Test; var {$IFDEF SupportAnsiString} C : AnsiChar; {$ENDIF} D : WideChar; E : Char; {$IFDEF SupportAnsiString} S, T : AnsiString; {$ENDIF} W, X : UnicodeString; Y, Z : String; {$IFDEF SupportAnsiString} L : AnsiStringArray; I : Integer; {$ENDIF} begin { CharMatch } Assert(CharMatchB(AnsiChar('A'), AnsiChar('a'), False)); Assert(CharMatchB(AnsiChar('a'), AnsiChar('A'), False)); Assert(CharMatchB(AnsiChar('A'), AnsiChar('A'), False)); { CharMatchNoAsciiCase } Assert(CharMatchNoAsciiCaseBW(AnsiChar('A'), 'a'), 'CharMatchNoAsciiCase'); Assert(CharMatchNoAsciiCaseBW(AnsiChar('z'), 'Z'), 'CharMatchNoAsciiCase'); Assert(CharMatchNoAsciiCaseBW(AnsiChar('1'), '1'), 'CharMatchNoAsciiCase'); Assert(not CharMatchNoAsciiCaseBW(AnsiChar('A'), 'B'), 'CharMatchNoAsciiCase'); Assert(not CharMatchNoAsciiCaseBW(AnsiChar('0'), 'A'), 'CharMatchNoAsciiCase'); { CharSetMatchChar } Assert(CharSetMatchCharB([AnsiChar('a')..AnsiChar('z')], AnsiChar('a'), False)); Assert(CharSetMatchCharB([AnsiChar('a')..AnsiChar('z')], AnsiChar('A'), False)); Assert(not CharSetMatchCharB([AnsiChar('a')..AnsiChar('z')], AnsiChar('-'), False)); Assert(not CharSetMatchCharB([AnsiChar('a')..AnsiChar('z')], AnsiChar('A'), True)); Assert(not CharSetMatchCharB([], AnsiChar('A'))); { Type matching } {$IFDEF SupportAnsiChar} Assert(StrIsNumericA('1234567890'), 'StrIsNumeric'); Assert(not StrIsNumericA('1234567890X'), 'StrIsNumeric'); Assert(not StrIsNumericA(''), 'StrIsNumeric'); Assert(StrIsIntegerA('-1234567890'), 'StrIsInteger'); Assert(StrIsIntegerA('0'), 'StrIsInteger'); Assert(not StrIsIntegerA('-1234567890X'), 'StrIsInteger'); Assert(not StrIsIntegerA('-'), 'StrIsInteger'); Assert(StrIsNumericB('1234567890'), 'StrIsNumeric'); Assert(not StrIsNumericB('1234567890X'), 'StrIsNumeric'); Assert(not StrIsNumericB(''), 'StrIsNumeric'); Assert(StrIsIntegerB('-1234567890'), 'StrIsInteger'); Assert(StrIsIntegerB('0'), 'StrIsInteger'); Assert(not StrIsIntegerB('-1234567890X'), 'StrIsInteger'); Assert(not StrIsIntegerB('-'), 'StrIsInteger'); {$ENDIF} Assert(StrIsNumericU('1234567890'), 'StrIsNumeric'); Assert(not StrIsNumericU('1234567890X'), 'StrIsNumeric'); Assert(not StrIsNumericU(''), 'StrIsNumeric'); Assert(StrIsIntegerU('-1234567890'), 'StrIsInteger'); Assert(StrIsIntegerU('0'), 'StrIsInteger'); Assert(not StrIsIntegerU('-1234567890X'), 'StrIsInteger'); Assert(not StrIsIntegerU('-'), 'StrIsInteger'); Assert(StrIsNumeric('1234567890'), 'StrIsNumeric'); Assert(not StrIsNumeric('1234567890X'), 'StrIsNumeric'); Assert(not StrIsNumeric(''), 'StrIsNumeric'); Assert(StrIsInteger('-1234567890'), 'StrIsInteger'); Assert(StrIsInteger('0'), 'StrIsInteger'); Assert(not StrIsInteger('-1234567890X'), 'StrIsInteger'); Assert(not StrIsInteger('-'), 'StrIsInteger'); { CopyRange } {$IFDEF SupportAnsiChar} Assert(CopyRangeA('', 1, 2) = '', 'CopyRange'); Assert(CopyRangeA('', -1, -2) = '', 'CopyRange'); Assert(CopyRangeA('1234567890', 5, 7) = '567', 'CopyRange'); Assert(CopyRangeA('1234567890', 1, 1) = '1', 'CopyRange'); Assert(CopyRangeA('1234567890', 0, 11) = '1234567890', 'CopyRange'); Assert(CopyRangeA('1234567890', 7, 4) = '', 'CopyRange'); Assert(CopyRangeA('1234567890', 1, 0) = '', 'CopyRange'); Assert(CopyRangeA('1234567890', -2, 3) = '123', 'CopyRange'); Assert(CopyRangeA('1234567890', 2, -1) = '', 'CopyRange'); Assert(CopyRangeA('1234567890', -4, -2) = '', 'CopyRange'); Assert(CopyRangeB('', 1, 2) = '', 'CopyRange'); Assert(CopyRangeB('', -1, -2) = '', 'CopyRange'); Assert(CopyRangeB('1234567890', 5, 7) = '567', 'CopyRange'); Assert(CopyRangeB('1234567890', 1, 1) = '1', 'CopyRange'); Assert(CopyRangeB('1234567890', 0, 11) = '1234567890', 'CopyRange'); Assert(CopyRangeB('1234567890', 7, 4) = '', 'CopyRange'); Assert(CopyRangeB('1234567890', 1, 0) = '', 'CopyRange'); Assert(CopyRangeB('1234567890', -2, 3) = '123', 'CopyRange'); Assert(CopyRangeB('1234567890', 2, -1) = '', 'CopyRange'); Assert(CopyRangeB('1234567890', -4, -2) = '', 'CopyRange'); {$ENDIF} Assert(CopyRangeU('', 1, 2) = '', 'CopyRange'); Assert(CopyRangeU('', -1, -2) = '', 'CopyRange'); Assert(CopyRangeU('1234567890', 5, 7) = '567', 'CopyRange'); Assert(CopyRangeU('1234567890', 1, 1) = '1', 'CopyRange'); Assert(CopyRangeU('1234567890', 0, 11) = '1234567890', 'CopyRange'); Assert(CopyRangeU('1234567890', 7, 4) = '', 'CopyRange'); Assert(CopyRangeU('1234567890', 1, 0) = '', 'CopyRange'); Assert(CopyRangeU('1234567890', -2, 3) = '123', 'CopyRange'); Assert(CopyRangeU('1234567890', 2, -1) = '', 'CopyRange'); Assert(CopyRangeU('1234567890', -4, -2) = '', 'CopyRange'); Assert(CopyRange('', 1, 2) = '', 'CopyRange'); Assert(CopyRange('', -1, -2) = '', 'CopyRange'); Assert(CopyRange('1234567890', 5, 7) = '567', 'CopyRange'); Assert(CopyRange('1234567890', 1, 1) = '1', 'CopyRange'); Assert(CopyRange('1234567890', 0, 11) = '1234567890', 'CopyRange'); Assert(CopyRange('1234567890', 7, 4) = '', 'CopyRange'); Assert(CopyRange('1234567890', 1, 0) = '', 'CopyRange'); Assert(CopyRange('1234567890', -2, 3) = '123', 'CopyRange'); Assert(CopyRange('1234567890', 2, -1) = '', 'CopyRange'); Assert(CopyRange('1234567890', -4, -2) = '', 'CopyRange'); { CopyFrom } {$IFDEF SupportAnsiChar} Assert(CopyFromA('a', 0) = 'a', 'CopyFrom'); Assert(CopyFromA('a', -1) = 'a', 'CopyFrom'); Assert(CopyFromA('', 1) = '', 'CopyFrom'); Assert(CopyFromA('', -2) = '', 'CopyFrom'); Assert(CopyFromA('1234567890', 8) = '890', 'CopyFrom'); Assert(CopyFromA('1234567890', 11) = '', 'CopyFrom'); Assert(CopyFromA('1234567890', 0) = '1234567890', 'CopyFrom'); Assert(CopyFromA('1234567890', -2) = '1234567890', 'CopyFrom'); {$ENDIF} Assert(CopyFromU('a', 0) = 'a', 'CopyFrom'); Assert(CopyFromU('a', -1) = 'a', 'CopyFrom'); Assert(CopyFromU('', 1) = '', 'CopyFrom'); Assert(CopyFromU('', -2) = '', 'CopyFrom'); Assert(CopyFromU('1234567890', 8) = '890', 'CopyFrom'); Assert(CopyFromU('1234567890', 11) = '', 'CopyFrom'); Assert(CopyFromU('1234567890', 0) = '1234567890', 'CopyFrom'); Assert(CopyFromU('1234567890', -2) = '1234567890', 'CopyFrom'); Assert(CopyFrom('a', 0) = 'a', 'CopyFrom'); Assert(CopyFrom('a', -1) = 'a', 'CopyFrom'); Assert(CopyFrom('', 1) = '', 'CopyFrom'); Assert(CopyFrom('', -2) = '', 'CopyFrom'); Assert(CopyFrom('1234567890', 8) = '890', 'CopyFrom'); Assert(CopyFrom('1234567890', 11) = '', 'CopyFrom'); Assert(CopyFrom('1234567890', 0) = '1234567890', 'CopyFrom'); Assert(CopyFrom('1234567890', -2) = '1234567890', 'CopyFrom'); { CopyLeft } {$IFDEF SupportAnsiChar} Assert(CopyLeftA('a', 0) = '', 'CopyLeft'); Assert(CopyLeftA('a', -1) = '', 'CopyLeft'); Assert(CopyLeftA('', 1) = '', 'CopyLeft'); Assert(CopyLeftA('b', 1) = 'b', 'CopyLeft'); Assert(CopyLeftA('', -1) = '', 'CopyLeft'); Assert(CopyLeftA('1234567890', 3) = '123', 'CopyLeft'); Assert(CopyLeftA('1234567890', 11) = '1234567890', 'CopyLeft'); Assert(CopyLeftA('1234567890', 0) = '', 'CopyLeft'); Assert(CopyLeftA('1234567890', -2) = '', 'CopyLeft'); Assert(CopyLeftB('a', 0) = '', 'CopyLeft'); Assert(CopyLeftB('a', -1) = '', 'CopyLeft'); Assert(CopyLeftB('', 1) = '', 'CopyLeft'); Assert(CopyLeftB('b', 1) = 'b', 'CopyLeft'); Assert(CopyLeftB('', -1) = '', 'CopyLeft'); Assert(CopyLeftB('1234567890', 3) = '123', 'CopyLeft'); Assert(CopyLeftB('1234567890', 11) = '1234567890', 'CopyLeft'); Assert(CopyLeftB('1234567890', 0) = '', 'CopyLeft'); Assert(CopyLeftB('1234567890', -2) = '', 'CopyLeft'); {$ENDIF} Assert(CopyLeftU('a', 0) = '', 'CopyLeft'); Assert(CopyLeftU('a', -1) = '', 'CopyLeft'); Assert(CopyLeftU('', 1) = '', 'CopyLeft'); Assert(CopyLeftU('b', 1) = 'b', 'CopyLeft'); Assert(CopyLeftU('', -1) = '', 'CopyLeft'); Assert(CopyLeftU('1234567890', 3) = '123', 'CopyLeft'); Assert(CopyLeftU('1234567890', 11) = '1234567890', 'CopyLeft'); Assert(CopyLeftU('1234567890', 0) = '', 'CopyLeft'); Assert(CopyLeftU('1234567890', -2) = '', 'CopyLeft'); Assert(CopyLeft('a', 0) = '', 'CopyLeft'); Assert(CopyLeft('a', -1) = '', 'CopyLeft'); Assert(CopyLeft('', 1) = '', 'CopyLeft'); Assert(CopyLeft('b', 1) = 'b', 'CopyLeft'); Assert(CopyLeft('', -1) = '', 'CopyLeft'); Assert(CopyLeft('1234567890', 3) = '123', 'CopyLeft'); Assert(CopyLeft('1234567890', 11) = '1234567890', 'CopyLeft'); Assert(CopyLeft('1234567890', 0) = '', 'CopyLeft'); Assert(CopyLeft('1234567890', -2) = '', 'CopyLeft'); { CopyRight } {$IFDEF SupportAnsiChar} Assert(CopyRightA('a', 0) = '', 'CopyRight'); Assert(CopyRightA('a', -1) = '', 'CopyRight'); Assert(CopyRightA('', 1) = '', 'CopyRight'); Assert(CopyRightA('', -2) = '', 'CopyRight'); Assert(CopyRightA('1234567890', 3) = '890', 'CopyRight'); Assert(CopyRightA('1234567890', 11) = '1234567890', 'CopyRight'); Assert(CopyRightA('1234567890', 0) = '', 'CopyRight'); Assert(CopyRightA('1234567890', -2) = '', 'CopyRight'); Assert(CopyRightB('a', 0) = '', 'CopyRight'); Assert(CopyRightB('a', -1) = '', 'CopyRight'); Assert(CopyRightB('', 1) = '', 'CopyRight'); Assert(CopyRightB('', -2) = '', 'CopyRight'); Assert(CopyRightB('1234567890', 3) = '890', 'CopyRight'); Assert(CopyRightB('1234567890', 11) = '1234567890', 'CopyRight'); Assert(CopyRightB('1234567890', 0) = '', 'CopyRight'); Assert(CopyRightB('1234567890', -2) = '', 'CopyRight'); {$ENDIF} Assert(CopyRightU('a', 0) = '', 'CopyRight'); Assert(CopyRightU('a', -1) = '', 'CopyRight'); Assert(CopyRightU('', 1) = '', 'CopyRight'); Assert(CopyRightU('', -2) = '', 'CopyRight'); Assert(CopyRightU('1234567890', 3) = '890', 'CopyRight'); Assert(CopyRightU('1234567890', 11) = '1234567890', 'CopyRight'); Assert(CopyRightU('1234567890', 0) = '', 'CopyRight'); Assert(CopyRightU('1234567890', -2) = '', 'CopyRight'); Assert(CopyRight('a', 0) = '', 'CopyRight'); Assert(CopyRight('a', -1) = '', 'CopyRight'); Assert(CopyRight('', 1) = '', 'CopyRight'); Assert(CopyRight('', -2) = '', 'CopyRight'); Assert(CopyRight('1234567890', 3) = '890', 'CopyRight'); Assert(CopyRight('1234567890', 11) = '1234567890', 'CopyRight'); Assert(CopyRight('1234567890', 0) = '', 'CopyRight'); Assert(CopyRight('1234567890', -2) = '', 'CopyRight'); { CopyEx } {$IFDEF SupportAnsiChar} Assert(CopyExA('', 1, 1) = ''); Assert(CopyExA('', -2, -1) = ''); Assert(CopyExA('12345', -2, 2) = '45'); Assert(CopyExA('12345', -1, 2) = '5'); Assert(CopyExA('12345', -7, 2) = '12'); Assert(CopyExA('12345', -5, 2) = '12'); Assert(CopyExA('12345', 2, -2) = ''); Assert(CopyExA('12345', -4, 0) = ''); Assert(CopyExA('12345', -4, 7) = '2345'); Assert(CopyExA('12345', 2, 2) = '23'); Assert(CopyExA('12345', -7, -6) = ''); Assert(CopyExA('12345', 0, 2) = '12'); Assert(CopyExA('12345', 0, 7) = '12345'); {$ENDIF} Assert(CopyExW('', 1, 1) = ''); Assert(CopyExW('', -2, -1) = ''); Assert(CopyExW('12345', -2, 2) = '45'); Assert(CopyExW('12345', -1, 2) = '5'); Assert(CopyExW('12345', -7, 2) = '12'); Assert(CopyExW('12345', -5, 2) = '12'); Assert(CopyExW('12345', 2, -2) = ''); Assert(CopyExW('12345', -4, 0) = ''); Assert(CopyExW('12345', -4, 7) = '2345'); Assert(CopyExW('12345', 2, 2) = '23'); Assert(CopyExW('12345', -7, -6) = ''); Assert(CopyExW('12345', 0, 2) = '12'); Assert(CopyExW('12345', 0, 7) = '12345'); Assert(CopyEx('', 1, 1) = ''); Assert(CopyEx('', -2, -1) = ''); Assert(CopyEx('12345', -2, 2) = '45'); Assert(CopyEx('12345', -1, 2) = '5'); Assert(CopyEx('12345', -7, 2) = '12'); Assert(CopyEx('12345', -5, 2) = '12'); Assert(CopyEx('12345', 2, -2) = ''); Assert(CopyEx('12345', -4, 0) = ''); Assert(CopyEx('12345', -4, 7) = '2345'); Assert(CopyEx('12345', 2, 2) = '23'); Assert(CopyEx('12345', -7, -6) = ''); Assert(CopyEx('12345', 0, 2) = '12'); Assert(CopyEx('12345', 0, 7) = '12345'); { CopyRangeEx } Assert(CopyRangeEx('', -2, -1) = ''); Assert(CopyRangeEx('', 0, 0) = ''); Assert(CopyRangeEx('12345', -2, -1) = '45'); Assert(CopyRangeEx('12345', -2, -1) = '45'); Assert(CopyRangeEx('12345', -2, 5) = '45'); Assert(CopyRangeEx('12345', 2, -2) = '234'); Assert(CopyRangeEx('12345', 0, -2) = '1234'); Assert(CopyRangeEx('12345', 1, -7) = ''); Assert(CopyRangeEx('12345', 7, -1) = ''); Assert(CopyRangeEx('12345', -10, 2) = '12'); Assert(CopyRangeEx('12345', -10, -7) = ''); Assert(CopyRangeEx('12345', 2, -6) = ''); Assert(CopyRangeEx('12345', 0, -2) = '1234'); Assert(CopyRangeEx('12345', 2, 0) = ''); Assert(CopyRangeEx('', -1, 2) = ''); { CopyFromEx } Assert(CopyFromEx('', 0) = ''); Assert(CopyFromEx('', -1) = ''); Assert(CopyFromEx('12345', 0) = '12345'); Assert(CopyFromEx('12345', 1) = '12345'); Assert(CopyFromEx('12345', -5) = '12345'); Assert(CopyFromEx('12345', -6) = '12345'); Assert(CopyFromEx('12345', 2) = '2345'); Assert(CopyFromEx('12345', -4) = '2345'); Assert(CopyFromEx('12345', 6) = ''); { StrEqualNoCase } {$IFDEF SupportAnsiChar} Assert(StrEqualNoAsciiCaseA('A', 'a'), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseA('A', 'B'), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCaseA('@ABCDEFGHIJKLMNOPQRSTUVWXYZ` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseA('@ABCDEFGHIJKLMNOPQRSTUVWXY-` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCaseB('A', 'a'), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseB('A', 'B'), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCaseB('@ABCDEFGHIJKLMNOPQRSTUVWXYZ` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseB('@ABCDEFGHIJKLMNOPQRSTUVWXY-` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); {$ENDIF} Assert(StrEqualNoAsciiCaseU('A', 'a'), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseU('A', 'B'), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCaseU('@ABCDEFGHIJKLMNOPQRSTUVWXYZ` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCaseU('@ABCDEFGHIJKLMNOPQRSTUVWXY-` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCase('A', 'a'), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCase('A', 'B'), 'StrEqualNoCase'); Assert(StrEqualNoAsciiCase('@ABCDEFGHIJKLMNOPQRSTUVWXYZ` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); Assert(not StrEqualNoAsciiCase('@ABCDEFGHIJKLMNOPQRSTUVWXY-` ', '@abcdefghijklmnopqrstuvwxyz` '), 'StrEqualNoCase'); { StrReverse } {$IFDEF SupportAnsiChar} Assert(StrReverseA('12345') = '54321', 'StrReverse'); Assert(StrReverseA('1234') = '4321', 'StrReverse'); Assert(StrReverseB('12345') = '54321', 'StrReverse'); Assert(StrReverseB('1234') = '4321', 'StrReverse'); {$ENDIF} Assert(StrReverseU('12345') = '54321', 'StrReverse'); Assert(StrReverseU('1234') = '4321', 'StrReverse'); Assert(StrReverse('12345') = '54321', 'StrReverse'); Assert(StrReverse('1234') = '4321', 'StrReverse'); { Compare } {$IFDEF SupportAnsiChar} Assert(StrCompareA('A', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareA('a', 'A') = 1, 'StrCompareNoCase'); Assert(StrCompareA('a', 'aa') = -1, 'StrCompareNoCase'); Assert(StrCompareA('', '') = 0, 'StrCompareNoCase'); Assert(StrCompareA('', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareA('a', '') = 1, 'StrCompareNoCase'); Assert(StrCompareB('A', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareB('a', 'A') = 1, 'StrCompareNoCase'); Assert(StrCompareB('a', 'aa') = -1, 'StrCompareNoCase'); Assert(StrCompareB('', '') = 0, 'StrCompareNoCase'); Assert(StrCompareB('', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareB('a', '') = 1, 'StrCompareNoCase'); {$ENDIF} Assert(StrCompareU('A', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareU('a', 'A') = 1, 'StrCompareNoCase'); Assert(StrCompareU('a', 'aa') = -1, 'StrCompareNoCase'); Assert(StrCompareU('', '') = 0, 'StrCompareNoCase'); Assert(StrCompareU('', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompareU('a', '') = 1, 'StrCompareNoCase'); Assert(StrCompare('A', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompare('a', 'A') = 1, 'StrCompareNoCase'); Assert(StrCompare('a', 'aa') = -1, 'StrCompareNoCase'); Assert(StrCompare('', '') = 0, 'StrCompareNoCase'); Assert(StrCompare('', 'a') = -1, 'StrCompareNoCase'); Assert(StrCompare('a', '') = 1, 'StrCompareNoCase'); { Match } {$IFDEF SupportAnsiChar} Assert(not StrMatchA('', '', 1), 'StrMatch'); Assert(not StrMatchA('', 'a', 1), 'StrMatch'); Assert(not StrMatchA('a', '', 1), 'StrMatch'); Assert(not StrMatchA('a', 'A', 1), 'StrMatch'); Assert(StrMatchA('A', 'A', 1), 'StrMatch'); Assert(not StrMatchA('abcdef', 'xx', 1), 'StrMatch'); Assert(StrMatchA('xbcdef', 'x', 1), 'StrMatch'); Assert(StrMatchA('abcdxxxxx', 'xxxxx', 5), 'StrMatch'); Assert(StrMatchA('abcdef', 'abcdef', 1), 'StrMatch'); Assert(not StrMatchNoAsciiCaseA('abcdef', 'xx', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseA('xbCDef', 'xBCd', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseA('abcdxxX-xx', 'Xxx-xX', 5), 'StrMatchNoCase'); Assert(StrMatchA('abcde', 'abcd', 1), 'StrMatch'); Assert(StrMatchA('abcde', 'abc', 1), 'StrMatch'); Assert(StrMatchA('abcde', 'ab', 1), 'StrMatch'); Assert(StrMatchA('abcde', 'a', 1), 'StrMatch'); Assert(StrMatchNoAsciiCaseA(' abC-Def{', ' AbC-def{', 1), 'StrMatchNoCase'); Assert(StrMatchLeftA('ABC1D', 'aBc1', False), 'StrMatchLeft'); Assert(StrMatchLeftA('aBc1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchLeftA('AB1D', 'ABc1', False), 'StrMatchLeft'); Assert(not StrMatchLeftA('aBC1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchCharA('', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharA('a', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharA('d', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharA('acbba', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharA('acbd', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchLenA('abcd', ['a', 'b', 'c'], 1) = 3, 'StrMatchLen'); Assert(StrMatchLenA('abcd', ['a', 'b', 'c'], 3) = 1, 'StrMatchLen'); Assert(StrMatchLenA('abcd', ['a', 'b', 'c'], 4) = 0, 'StrMatchLen'); Assert(StrMatchLenA('', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); Assert(StrMatchLenA('dcba', ['a', 'b', 'c'], 2) = 3, 'StrMatchLen'); Assert(StrMatchLenA('dcba', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); Assert(not StrMatchB('', '', 1), 'StrMatch'); Assert(not StrMatchB('', 'a', 1), 'StrMatch'); Assert(not StrMatchB('a', '', 1), 'StrMatch'); Assert(not StrMatchB('a', 'A', 1), 'StrMatch'); Assert(StrMatchB('A', 'A', 1), 'StrMatch'); Assert(not StrMatchB('abcdef', 'xx', 1), 'StrMatch'); Assert(StrMatchB('xbcdef', 'x', 1), 'StrMatch'); Assert(StrMatchB('abcdxxxxx', 'xxxxx', 5), 'StrMatch'); Assert(StrMatchB('abcdef', 'abcdef', 1), 'StrMatch'); Assert(not StrMatchNoAsciiCaseB('abcdef', 'xx', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseB('xbCDef', 'xBCd', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseB('abcdxxX-xx', 'Xxx-xX', 5), 'StrMatchNoCase'); Assert(StrMatchB('abcde', 'abcd', 1), 'StrMatch'); Assert(StrMatchB('abcde', 'abc', 1), 'StrMatch'); Assert(StrMatchB('abcde', 'ab', 1), 'StrMatch'); Assert(StrMatchB('abcde', 'a', 1), 'StrMatch'); Assert(StrMatchNoAsciiCaseB(' abC-Def{', ' AbC-def{', 1), 'StrMatchNoCase'); Assert(StrMatchLeftB('ABC1D', 'aBc1', False), 'StrMatchLeft'); Assert(StrMatchLeftB('aBc1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchLeftB('AB1D', 'ABc1', False), 'StrMatchLeft'); Assert(not StrMatchLeftB('aBC1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchCharB('', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharB('a', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharB('d', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharB('acbba', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharB('acbd', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchLenB('abcd', ['a', 'b', 'c'], 1) = 3, 'StrMatchLen'); Assert(StrMatchLenB('abcd', ['a', 'b', 'c'], 3) = 1, 'StrMatchLen'); Assert(StrMatchLenB('abcd', ['a', 'b', 'c'], 4) = 0, 'StrMatchLen'); Assert(StrMatchLenB('', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); Assert(StrMatchLenB('dcba', ['a', 'b', 'c'], 2) = 3, 'StrMatchLen'); Assert(StrMatchLenB('dcba', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); {$ENDIF} Assert(not StrMatchU('', '', 1), 'StrMatch'); Assert(not StrMatchU('', 'a', 1), 'StrMatch'); Assert(not StrMatchU('a', '', 1), 'StrMatch'); Assert(not StrMatchU('a', 'A', 1), 'StrMatch'); Assert(StrMatchU('A', 'A', 1), 'StrMatch'); Assert(not StrMatchU('abcdef', 'xx', 1), 'StrMatch'); Assert(StrMatchU('xbcdef', 'x', 1), 'StrMatch'); Assert(StrMatchU('abcdxxxxx', 'xxxxx', 5), 'StrMatch'); Assert(StrMatchU('abcdef', 'abcdef', 1), 'StrMatch'); Assert(not StrMatchNoAsciiCaseU('abcdef', 'xx', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseU('xbCDef', 'xBCd', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCaseU('abcdxxX-xx', 'Xxx-xX', 5), 'StrMatchNoCase'); Assert(StrMatchU('abcde', 'abcd', 1), 'StrMatch'); Assert(StrMatchU('abcde', 'abc', 1), 'StrMatch'); Assert(StrMatchU('abcde', 'ab', 1), 'StrMatch'); Assert(StrMatchU('abcde', 'a', 1), 'StrMatch'); Assert(StrMatchNoAsciiCaseU(' abC-Def{', ' AbC-def{', 1), 'StrMatchNoCase'); Assert(StrMatchLeftU('ABC1D', 'aBc1', False), 'StrMatchLeft'); Assert(StrMatchLeftU('aBc1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchLeftU('AB1D', 'ABc1', False), 'StrMatchLeft'); Assert(not StrMatchLeftU('aBC1D', 'aBc1', True), 'StrMatchLeft'); {$IFDEF SupportAnsiChar} Assert(not StrMatchCharU('', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharU('a', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharU('d', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchCharU('acbba', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchCharU('acbd', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchLenU('abcd', ['a', 'b', 'c'], 1) = 3, 'StrMatchLen'); Assert(StrMatchLenU('abcd', ['a', 'b', 'c'], 3) = 1, 'StrMatchLen'); Assert(StrMatchLenU('abcd', ['a', 'b', 'c'], 4) = 0, 'StrMatchLen'); Assert(StrMatchLenU('', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); Assert(StrMatchLenU('dcba', ['a', 'b', 'c'], 2) = 3, 'StrMatchLen'); Assert(StrMatchLenU('dcba', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); {$ENDIF} Assert(not StrMatch('', '', 1), 'StrMatch'); Assert(not StrMatch('', 'a', 1), 'StrMatch'); Assert(not StrMatch('a', '', 1), 'StrMatch'); Assert(not StrMatch('a', 'A', 1), 'StrMatch'); Assert(StrMatch('A', 'A', 1), 'StrMatch'); Assert(not StrMatch('abcdef', 'xx', 1), 'StrMatch'); Assert(StrMatch('xbcdef', 'x', 1), 'StrMatch'); Assert(StrMatch('abcdxxxxx', 'xxxxx', 5), 'StrMatch'); Assert(StrMatch('abcdef', 'abcdef', 1), 'StrMatch'); Assert(not StrMatchNoAsciiCase('abcdef', 'xx', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCase('xbCDef', 'xBCd', 1), 'StrMatchNoCase'); Assert(StrMatchNoAsciiCase('abcdxxX-xx', 'Xxx-xX', 5), 'StrMatchNoCase'); Assert(StrMatch('abcde', 'abcd', 1), 'StrMatch'); Assert(StrMatch('abcde', 'abc', 1), 'StrMatch'); Assert(StrMatch('abcde', 'ab', 1), 'StrMatch'); Assert(StrMatch('abcde', 'a', 1), 'StrMatch'); Assert(StrMatchNoAsciiCase(' abC-Def{', ' AbC-def{', 1), 'StrMatchNoCase'); Assert(StrMatchLeft('ABC1D', 'aBc1', False), 'StrMatchLeft'); Assert(StrMatchLeft('aBc1D', 'aBc1', True), 'StrMatchLeft'); Assert(not StrMatchLeft('AB1D', 'ABc1', False), 'StrMatchLeft'); Assert(not StrMatchLeft('aBC1D', 'aBc1', True), 'StrMatchLeft'); {$IFDEF SupportAnsiChar} Assert(not StrMatchChar('', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchChar('a', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchChar('d', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchChar('acbba', ['a', 'b', 'c']), 'StrMatchChar'); Assert(not StrMatchChar('acbd', ['a', 'b', 'c']), 'StrMatchChar'); Assert(StrMatchLen('abcd', ['a', 'b', 'c'], 1) = 3, 'StrMatchLen'); Assert(StrMatchLen('abcd', ['a', 'b', 'c'], 3) = 1, 'StrMatchLen'); Assert(StrMatchLen('abcd', ['a', 'b', 'c'], 4) = 0, 'StrMatchLen'); Assert(StrMatchLen('', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); Assert(StrMatchLen('dcba', ['a', 'b', 'c'], 2) = 3, 'StrMatchLen'); Assert(StrMatchLen('dcba', ['a', 'b', 'c'], 1) = 0, 'StrMatchLen'); {$ENDIF} { Pos } {$IFDEF SupportAnsiString} Assert(PosStrA('', 'ABCABC') = 0, 'PosStr'); Assert(PosStrA('', 'a') = 0, 'PosStr'); Assert(PosStrA('A', '') = 0, 'PosStr'); Assert(PosStrA('A', 'ABCABC') = 1, 'PosStr'); Assert(PosStrA('A', 'ABCABC', 2) = 4, 'PosStr'); Assert(PosStrA('ab', 'a') = 0, 'PosStr'); Assert(PosStrA('ab', 'ab') = 1, 'PosStr'); Assert(PosStrA('ab', 'zxab') = 3, 'PosStr'); Assert(PosStrA('ab', '') = 0, 'PosStr'); Assert(PosStrA('ab', 'axdba') = 0, 'PosStr'); Assert(PosStrA('a', 'AbAc', 1, False) = 1, 'PosStr'); Assert(PosStrA('ba', 'ABAcabac', 1, False) = 2, 'PosStr'); Assert(PosStrA('a', 'abac', 2) = 3, 'PosStr'); Assert(PosStrA('ab', 'abacabac', 2) = 5, 'PosStr'); Assert(PosStrRevA('A', 'ABCABC') = 4, 'PosStrRev'); Assert(PosStrRevA('A', 'ABCABCA') = 7, 'PosStrRev'); Assert(PosStrRevA('CA', 'ABCABCA') = 6, 'PosStrRev'); Assert(PosStrRevA('ab', 'abacabac') = 5, 'PosStrRev'); Assert(PosNStrA('AB', 'ABCABCDAB', 3) = 8, 'PosNStr'); Assert(PosCharSetA([], 'a') = 0, 'PosChar'); Assert(PosCharSetA(['a'], 'a') = 1, 'PosChar'); Assert(PosCharSetA(['a'], '') = 0, 'PosChar'); Assert(PosCharSetA(['a'], 'aa') = 1, 'PosChar'); Assert(PosCharSetA(['a'], 'ba') = 2, 'PosChar'); Assert(PosCharSetA(['a'], 'zx') = 0, 'PosChar'); Assert(PosCharA(AnsiChar('a'), 'a') = 1, 'PosChar'); Assert(PosCharA(AnsiChar('a'), '') = 0, 'PosChar'); Assert(PosCharA(AnsiChar('a'), 'aa') = 1, 'PosChar'); Assert(PosCharA(AnsiChar('a'), 'ba') = 2, 'PosChar'); Assert(PosCharA(AnsiChar('a'), 'zx') = 0, 'PosChar'); Assert(PosCharSetA(['a'], 'abac', 2) = 3, 'PosChar'); Assert(PosCharRevA(AnsiChar('a'), 'abac') = 3, 'PosCharRev'); Assert(PosCharSetRevA(['a'..'z'], 'abac') = 4, 'PosCharRev'); Assert(PosNotCharA(AnsiChar('a'), 'abac') = 2, 'PosNotChar'); Assert(PosNotCharSetA(['a'..'z'], 'abac1a') = 5, 'PosNotChar'); Assert(PosStrB('', 'ABCABC') = 0, 'PosStr'); Assert(PosStrB('', 'a') = 0, 'PosStr'); Assert(PosStrB('A', '') = 0, 'PosStr'); Assert(PosStrB('A', 'ABCABC') = 1, 'PosStr'); Assert(PosStrB('A', 'ABCABC', 2) = 4, 'PosStr'); Assert(PosStrB('ab', 'a') = 0, 'PosStr'); Assert(PosStrB('ab', 'ab') = 1, 'PosStr'); Assert(PosStrB('ab', 'zxab') = 3, 'PosStr'); Assert(PosStrB('ab', '') = 0, 'PosStr'); Assert(PosStrB('ab', 'axdba') = 0, 'PosStr'); Assert(PosStrB('a', 'AbAc', 1, False) = 1, 'PosStr'); Assert(PosStrB('ba', 'ABAcabac', 1, False) = 2, 'PosStr'); Assert(PosStrB('a', 'abac', 2) = 3, 'PosStr'); Assert(PosStrB('ab', 'abacabac', 2) = 5, 'PosStr'); Assert(PosStrRevB('A', 'ABCABC') = 4, 'PosStrRev'); Assert(PosStrRevB('A', 'ABCABCA') = 7, 'PosStrRev'); Assert(PosStrRevB('CA', 'ABCABCA') = 6, 'PosStrRev'); Assert(PosStrRevB('ab', 'abacabac') = 5, 'PosStrRev'); Assert(PosNStrB('AB', 'ABCABCDAB', 3) = 8, 'PosNStr'); Assert(PosCharSetB([], 'a') = 0, 'PosChar'); Assert(PosCharSetB(['a'], 'a') = 1, 'PosChar'); Assert(PosCharSetB(['a'], '') = 0, 'PosChar'); Assert(PosCharSetB(['a'], 'aa') = 1, 'PosChar'); Assert(PosCharSetB(['a'], 'ba') = 2, 'PosChar'); Assert(PosCharSetB(['a'], 'zx') = 0, 'PosChar'); Assert(PosCharB(AnsiChar('a'), 'a') = 1, 'PosChar'); Assert(PosCharB(AnsiChar('a'), '') = 0, 'PosChar'); Assert(PosCharB(AnsiChar('a'), 'aa') = 1, 'PosChar'); Assert(PosCharB(AnsiChar('a'), 'ba') = 2, 'PosChar'); Assert(PosCharB(AnsiChar('a'), 'zx') = 0, 'PosChar'); Assert(PosCharSetB(['a'], 'abac', 2) = 3, 'PosChar'); Assert(PosCharRevB(AnsiChar('a'), 'abac') = 3, 'PosCharRev'); Assert(PosCharSetRevB(['a'..'z'], 'abac') = 4, 'PosCharRev'); Assert(PosNotCharB(AnsiChar('a'), 'abac') = 2, 'PosNotChar'); Assert(PosNotCharSetB(['a'..'z'], 'abac1a') = 5, 'PosNotChar'); {$ENDIF} Assert(PosStrU('', 'ABCABC') = 0, 'PosStr'); Assert(PosStrU('', 'a') = 0, 'PosStr'); Assert(PosStrU('A', '') = 0, 'PosStr'); Assert(PosStrU('A', 'ABCABC') = 1, 'PosStr'); Assert(PosStrU('A', 'ABCABC', 2) = 4, 'PosStr'); Assert(PosStrU('ab', 'a') = 0, 'PosStr'); Assert(PosStrU('ab', 'ab') = 1, 'PosStr'); Assert(PosStrU('ab', 'zxab') = 3, 'PosStr'); Assert(PosStrU('ab', '') = 0, 'PosStr'); Assert(PosStrU('ab', 'axdba') = 0, 'PosStr'); Assert(PosStrU('a', 'AbAc', 1, False) = 1, 'PosStr'); Assert(PosStrU('ba', 'ABAcabac', 1, False) = 2, 'PosStr'); Assert(PosStrU('a', 'abac', 2) = 3, 'PosStr'); Assert(PosStrU('ab', 'abacabac', 2) = 5, 'PosStr'); Assert(PosStrRevU('A', 'ABCABC') = 4, 'PosStrRev'); Assert(PosStrRevU('A', 'ABCABCA') = 7, 'PosStrRev'); Assert(PosStrRevU('CA', 'ABCABCA') = 6, 'PosStrRev'); Assert(PosStrRevU('ab', 'abacabac') = 5, 'PosStrRev'); Assert(PosNStrU('AB', 'ABCABCDAB', 3) = 8, 'PosNStr'); Assert(PosCharSetU([], 'a') = 0, 'PosChar'); {$IFDEF SupportAnsiChar} Assert(PosCharSetU(['a'], 'a') = 1, 'PosChar'); Assert(PosCharSetU(['a'], '') = 0, 'PosChar'); Assert(PosCharSetU(['a'], 'aa') = 1, 'PosChar'); Assert(PosCharSetU(['a'], 'ba') = 2, 'PosChar'); Assert(PosCharSetU(['a'], 'zx') = 0, 'PosChar'); Assert(PosCharU(AnsiChar('a'), 'a') = 1, 'PosChar'); Assert(PosCharU(AnsiChar('a'), '') = 0, 'PosChar'); Assert(PosCharU(AnsiChar('a'), 'aa') = 1, 'PosChar'); Assert(PosCharU(AnsiChar('a'), 'ba') = 2, 'PosChar'); Assert(PosCharU(AnsiChar('a'), 'zx') = 0, 'PosChar'); Assert(PosCharSetU(['a'], 'abac', 2) = 3, 'PosChar'); Assert(PosCharRevU(AnsiChar('a'), 'abac') = 3, 'PosCharRev'); Assert(PosCharSetRevU(['a'..'z'], 'abac') = 4, 'PosCharRev'); Assert(PosNotCharU(AnsiChar('a'), 'abac') = 2, 'PosNotChar'); Assert(PosNotCharSetU(['a'..'z'], 'abac1a') = 5, 'PosNotChar'); {$ENDIF} Assert(PosStr('', 'ABCABC') = 0, 'PosStr'); Assert(PosStr('', 'a') = 0, 'PosStr'); Assert(PosStr('A', '') = 0, 'PosStr'); Assert(PosStr('A', 'ABCABC') = 1, 'PosStr'); Assert(PosStr('A', 'ABCABC', 2) = 4, 'PosStr'); Assert(PosStr('ab', 'a') = 0, 'PosStr'); Assert(PosStr('ab', 'ab') = 1, 'PosStr'); Assert(PosStr('ab', 'zxab') = 3, 'PosStr'); Assert(PosStr('ab', '') = 0, 'PosStr'); Assert(PosStr('ab', 'axdba') = 0, 'PosStr'); Assert(PosStr('a', 'AbAc', 1, False) = 1, 'PosStr'); Assert(PosStr('ba', 'ABAcabac', 1, False) = 2, 'PosStr'); Assert(PosStr('a', 'abac', 2) = 3, 'PosStr'); Assert(PosStr('ab', 'abacabac', 2) = 5, 'PosStr'); Assert(PosStrRev('A', 'ABCABC') = 4, 'PosStrRev'); Assert(PosStrRev('A', 'ABCABCA') = 7, 'PosStrRev'); Assert(PosStrRev('CA', 'ABCABCA') = 6, 'PosStrRev'); Assert(PosStrRev('ab', 'abacabac') = 5, 'PosStrRev'); Assert(PosNStr('AB', 'ABCABCDAB', 3) = 8, 'PosNStr'); Assert(PosCharSet([], 'a') = 0, 'PosChar'); {$IFDEF SupportAnsiChar} Assert(PosCharSet(['a'], 'a') = 1, 'PosChar'); Assert(PosCharSet(['a'], '') = 0, 'PosChar'); Assert(PosCharSet(['a'], 'aa') = 1, 'PosChar'); Assert(PosCharSet(['a'], 'ba') = 2, 'PosChar'); Assert(PosCharSet(['a'], 'zx') = 0, 'PosChar'); Assert(PosChar(AnsiChar('a'), 'a') = 1, 'PosChar'); Assert(PosChar(AnsiChar('a'), '') = 0, 'PosChar'); Assert(PosChar(AnsiChar('a'), 'aa') = 1, 'PosChar'); Assert(PosChar(AnsiChar('a'), 'ba') = 2, 'PosChar'); Assert(PosChar(AnsiChar('a'), 'zx') = 0, 'PosChar'); Assert(PosCharSet(['a'], 'abac', 2) = 3, 'PosChar'); Assert(PosCharRev(AnsiChar('a'), 'abac') = 3, 'PosCharRev'); Assert(PosCharSetRev(['a'..'z'], 'abac') = 4, 'PosCharRev'); Assert(PosNotChar(AnsiChar('a'), 'abac') = 2, 'PosNotChar'); Assert(PosNotCharSet(['a'..'z'], 'abac1a') = 5, 'PosNotChar'); {$ENDIF} Assert(PosStrU('AB', 'XYZABCAACDEF', 1) = 4, 'PosStrU'); Assert(PosStrU('AA', 'XYZABCAACDEF', 1) = 7, 'PosStrU'); Assert(PosStrU('A', 'XYZABCAACDEF', 8) = 8, 'PosStrU'); Assert(PosStrU('AA', 'XYZABCAACDEF', 8) = 0, 'PosStrU'); Assert(PosStrU('AAQ', 'XYZABCAACDEF', 1) = 0, 'PosStrU'); Assert(PosCharU(WideChar('A'), 'XYZABCAACDEF', 1) = 4, 'PosCharU'); Assert(PosCharU(WideChar('A'), 'XYZABCAACDEF', 5) = 7, 'PosCharU'); Assert(PosCharU(WideChar('A'), 'XYZABCAACDEF', 8) = 8, 'PosCharU'); Assert(PosCharU(WideChar('A'), 'XYZABCAACDEF', 9) = 0, 'PosCharU'); Assert(PosCharU(WideChar('Q'), 'XYZABCAACDEF', 1) = 0, 'PosCharU'); { Trim } {$IFDEF SupportAnsiString} Assert(StrTrimLeftA(' 123 ') = '123 ', 'TrimLeft'); Assert(StrTrimLeftStrNoCaseA(' 123 ', ' ') = ' 123 ', 'TrimLeftStrNoCase'); Assert(StrTrimRightA(' 123 ') = ' 123', 'TrimRight'); Assert(StrTrimRightStrNoCaseA(' 123 ', ' ') = ' 123 ', 'TrimRightStrNoCase'); Assert(StrTrimA(' 123 ', [' ']) = '123', 'Trim'); Assert(StrTrimA('', [' ']) = '', 'Trim'); Assert(StrTrimA('X', [' ']) = 'X', 'Trim'); Assert(StrTrimLeftB(' 123 ') = '123 ', 'TrimLeft'); Assert(StrTrimLeftStrNoCaseB(' 123 ', ' ') = ' 123 ', 'TrimLeftStrNoCase'); Assert(StrTrimRightB(' 123 ') = ' 123', 'TrimRight'); Assert(StrTrimRightStrNoCaseB(' 123 ', ' ') = ' 123 ', 'TrimRightStrNoCase'); Assert(StrTrimB(' 123 ', [' ']) = '123', 'Trim'); Assert(StrTrimB('', [' ']) = '', 'Trim'); Assert(StrTrimB('X', [' ']) = 'X', 'Trim'); {$ENDIF} Assert(StrTrimLeftU(' 123 ') = '123 ', 'TrimLeft'); Assert(StrTrimLeftStrNoCaseU(' 123 ', ' ') = ' 123 ', 'TrimLeftStrNoCase'); Assert(StrTrimRightU(' 123 ') = ' 123', 'TrimRight'); Assert(StrTrimRightStrNoCaseU(' 123 ', ' ') = ' 123 ', 'TrimRightStrNoCase'); Assert(StrTrimU(' 123 ', [' ']) = '123', 'Trim'); Assert(StrTrimU('', [' ']) = '', 'Trim'); Assert(StrTrimU('X', [' ']) = 'X', 'Trim'); Assert(StrTrimLeft(' 123 ') = '123 ', 'TrimLeft'); Assert(StrTrimLeftStrNoCase(' 123 ', ' ') = ' 123 ', 'TrimLeftStrNoCase'); Assert(StrTrimRight(' 123 ') = ' 123', 'TrimRight'); Assert(StrTrimRightStrNoCase(' 123 ', ' ') = ' 123 ', 'TrimRightStrNoCase'); Assert(StrTrim(' 123 ', [' ']) = '123', 'Trim'); Assert(StrTrim('', [' ']) = '', 'Trim'); Assert(StrTrim('X', [' ']) = 'X', 'Trim'); Assert(StrTrimLeftU(' X ') = 'X ', 'StrTrimLeft'); Assert(StrTrimRightU(' X ') = ' X', 'StrTrimRight'); Assert(StrTrimU(' X ') = 'X', 'StrTrim'); { Dup } {$IFDEF SupportAnsiString} Assert(DupStrA('xy', 3) = 'xyxyxy', 'Dup'); Assert(DupStrA('', 3) = '', 'Dup'); Assert(DupStrA('a', 0) = '', 'Dup'); Assert(DupStrA('a', -1) = '', 'Dup'); C := 'x'; Assert(DupCharA(C, 6) = 'xxxxxx', 'Dup'); Assert(DupCharA(C, 0) = '', 'Dup'); Assert(DupCharA(C, -1) = '', 'Dup'); Assert(DupStrB('xy', 3) = 'xyxyxy', 'Dup'); Assert(DupStrB('', 3) = '', 'Dup'); Assert(DupStrB('a', 0) = '', 'Dup'); Assert(DupStrB('a', -1) = '', 'Dup'); C := 'x'; Assert(DupCharB(C, 6) = 'xxxxxx', 'Dup'); Assert(DupCharB(C, 0) = '', 'Dup'); Assert(DupCharB(C, -1) = '', 'Dup'); {$ENDIF} Assert(DupStrU('xy', 3) = 'xyxyxy', 'Dup'); Assert(DupStrU('', 3) = '', 'Dup'); Assert(DupStrU('a', 0) = '', 'Dup'); Assert(DupStrU('a', -1) = '', 'Dup'); D := 'x'; Assert(DupCharU(D, 6) = 'xxxxxx', 'Dup'); Assert(DupCharU(D, 0) = '', 'Dup'); Assert(DupCharU(D, -1) = '', 'Dup'); Assert(DupStr('xy', 3) = 'xyxyxy', 'Dup'); Assert(DupStr('', 3) = '', 'Dup'); Assert(DupStr('a', 0) = '', 'Dup'); Assert(DupStr('a', -1) = '', 'Dup'); E := 'x'; Assert(DupChar(E, 6) = 'xxxxxx', 'Dup'); Assert(DupChar(E, 0) = '', 'Dup'); Assert(DupChar(E, -1) = '', 'Dup'); { Pad } {$IFDEF SupportAnsiString} Assert(StrPadLeftA('xxx', 'y', 6) = 'yyyxxx', 'PadLeft'); Assert(StrPadLeftA('xxx', 'y', 2, True) = 'xx', 'PadLeft'); Assert(StrPadLeftA('x', ' ', 3, True) = ' x', 'PadLeft'); Assert(StrPadLeftA('xabc', ' ', 3, True) = 'xab', 'PadLeft'); Assert(StrPadRightA('xxx', 'y', 6) = 'xxxyyy', 'PadRight'); Assert(StrPadRightA('xxx', 'y', 2, True) = 'xx', 'PadRight'); Assert(StrPadA('xxx', 'y', 7) = 'yyxxxyy', 'Pad'); Assert(StrPadLeftB('xxx', 'y', 6) = 'yyyxxx', 'PadLeft'); Assert(StrPadLeftB('xxx', 'y', 2, True) = 'xx', 'PadLeft'); Assert(StrPadLeftB('x', ' ', 3, True) = ' x', 'PadLeft'); Assert(StrPadLeftB('xabc', ' ', 3, True) = 'xab', 'PadLeft'); Assert(StrPadRightB('xxx', 'y', 6) = 'xxxyyy', 'PadRight'); Assert(StrPadRightB('xxx', 'y', 2, True) = 'xx', 'PadRight'); Assert(StrPadB('xxx', 'y', 7) = 'yyxxxyy', 'Pad'); {$ENDIF} Assert(StrPadLeftU('xxx', 'y', 6) = 'yyyxxx', 'PadLeft'); Assert(StrPadLeftU('xxx', 'y', 2, True) = 'xx', 'PadLeft'); Assert(StrPadLeftU('x', ' ', 3, True) = ' x', 'PadLeft'); Assert(StrPadLeftU('xabc', ' ', 3, True) = 'xab', 'PadLeft'); Assert(StrPadRightU('xxx', 'y', 6) = 'xxxyyy', 'PadRight'); Assert(StrPadRightU('xxx', 'y', 2, True) = 'xx', 'PadRight'); Assert(StrPadU('xxx', 'y', 7) = 'yyxxxyy', 'Pad'); Assert(StrPadLeft('xxx', 'y', 6) = 'yyyxxx', 'PadLeft'); Assert(StrPadLeft('xxx', 'y', 2, True) = 'xx', 'PadLeft'); Assert(StrPadLeft('x', ' ', 3, True) = ' x', 'PadLeft'); Assert(StrPadLeft('xabc', ' ', 3, True) = 'xab', 'PadLeft'); Assert(StrPadRight('xxx', 'y', 6) = 'xxxyyy', 'PadRight'); Assert(StrPadRight('xxx', 'y', 2, True) = 'xx', 'PadRight'); Assert(StrPad('xxx', 'y', 7) = 'yyxxxyy', 'Pad'); { Prefix/Suffix } {$IFDEF SupportAnsiString} S := 'ABC'; StrEnsurePrefixA(S, '\'); Assert(S = '\ABC', 'StrEnsurePrefix'); StrEnsureSuffixA(S, '\'); Assert(S = '\ABC\', 'StrEnsureSuffix'); StrEnsureNoPrefixA(S, '\'); Assert(S = 'ABC\', 'StrEnsureNoPrefix'); StrEnsureNoSuffixA(S, '\'); Assert(S = 'ABC', 'StrEnsureNoSuffix'); for I := 0 to 256 do begin T := DupCharA('A', I); S := T; StrEnsurePrefixA(S, '\'); Assert(S = '\' + T, 'StrEnsurePrefix'); StrEnsureNoPrefixA(S, '\'); Assert(S = T, 'StrEnsureNoPrefix'); StrEnsureSuffixA(S, '\'); Assert(S = T + '\', 'StrEnsureSuffix'); StrEnsureNoSuffixA(S, '\'); Assert(S = T, 'StrEnsureSuffix'); end; {$ENDIF} { Split } {$IFDEF SupportAnsiString} Assert(StrSplitAtCharA('ABC:X', AnsiChar(':'), S, T), 'StrSplitAtChar'); Assert(S = 'ABC', 'StrSplitAtChar'); Assert(T = 'X', 'StrSplitAtChar'); Assert(not StrSplitAtCharA('ABC:X', AnsiChar(','), S, T), 'StrSplitAtChar'); Assert(S = 'ABC:X', 'StrSplitAtChar'); Assert(T = '', 'StrSplitAtChar'); L := StrSplitA('', ','); Assert(Length(L) = 0, 'StrSplit'); L := StrSplitA('ABC', ','); Assert(Length(L) = 1, 'StrSplit'); Assert(L[0] = 'ABC', 'StrSplit'); L := StrSplitA('ABC', ''); Assert(Length(L) = 1, 'StrSplit'); Assert(L[0] = 'ABC', 'StrSplit'); L := StrSplitA('A,B,C', ','); Assert(Length(L) = 3, 'StrSplit'); Assert(L[0] = 'A', 'StrSplit'); Assert(L[1] = 'B', 'StrSplit'); Assert(L[2] = 'C', 'StrSplit'); L := StrSplitA('1,23,456', ','); Assert(Length(L) = 3, 'StrSplit'); Assert(L[0] = '1', 'StrSplit'); Assert(L[1] = '23', 'StrSplit'); Assert(L[2] = '456', 'StrSplit'); L := StrSplitA(',1,2,,3,', ','); Assert(Length(L) = 6, 'StrSplit'); Assert(L[0] = '', 'StrSplit'); Assert(L[1] = '1', 'StrSplit'); Assert(L[2] = '2', 'StrSplit'); Assert(L[3] = '', 'StrSplit'); Assert(L[4] = '3', 'StrSplit'); Assert(L[5] = '', 'StrSplit'); L := StrSplitA('1..23..456', '..'); Assert(Length(L) = 3, 'StrSplit'); Assert(L[0] = '1', 'StrSplit'); Assert(L[1] = '23', 'StrSplit'); Assert(L[2] = '456', 'StrSplit'); {$ENDIF} { Count } {$IFDEF SupportAnsiString} Assert(StrCountCharA('abcxyzdexxyxyz', AnsiChar('x')) = 4); Assert(StrCountCharA('abcxyzdexxyxyz', AnsiChar('q')) = 0); Assert(StrCountCharA('abcxyzdexxyxyz', ['a'..'z']) = 14); Assert(StrCountCharB('abcxyzdexxyxyz', AnsiChar('x')) = 4); Assert(StrCountCharB('abcxyzdexxyxyz', AnsiChar('q')) = 0); Assert(StrCountCharB('abcxyzdexxyxyz', ['a'..'z']) = 14); {$ENDIF} Assert(StrCountCharU('abcxyzdexxyxyz', WideChar('x')) = 4); Assert(StrCountCharU('abcxyzdexxyxyz', WideChar('q')) = 0); {$IFDEF SupportAnsiChar} Assert(StrCountCharU('abcxyzdexxyxyz', ['a'..'z']) = 14); {$ENDIF} Assert(StrCountChar('abcxyzdexxyxyz', Char('x')) = 4); Assert(StrCountChar('abcxyzdexxyxyz', Char('q')) = 0); {$IFDEF SupportAnsiChar} Assert(StrCountChar('abcxyzdexxyxyz', ['a'..'z']) = 14); {$ENDIF} { Quoting } {$IFDEF SupportAnsiString} Assert(StrRemoveSurroundingQuotesA('"123"') = '123', 'StrRemoveSurroundingQuotes'); Assert(StrRemoveSurroundingQuotesA('"1""23"') = '1""23', 'StrRemoveSurroundingQuotes'); Assert(StrQuoteA('Abe''s', '''') = '''Abe''''s''', 'StrQuote'); Assert(StrUnquoteA('"123"') = '123', 'StrUnQuote'); Assert(StrUnquoteA('"1""23"') = '1"23', 'StrUnQuote'); {$ENDIF} Assert(StrRemoveSurroundingQuotesU('"123"') = '123', 'StrRemoveSurroundingQuotes'); Assert(StrRemoveSurroundingQuotesU('"1""23"') = '1""23', 'StrRemoveSurroundingQuotes'); Assert(StrQuoteU('Abe''s', '''') = '''Abe''''s''', 'StrQuote'); Assert(StrUnquoteU('"123"') = '123', 'StrUnQuote'); Assert(StrUnquoteU('"1""23"') = '1"23', 'StrUnQuote'); Assert(StrRemoveSurroundingQuotes('"123"') = '123', 'StrRemoveSurroundingQuotes'); Assert(StrRemoveSurroundingQuotes('"1""23"') = '1""23', 'StrRemoveSurroundingQuotes'); Assert(StrQuote('Abe''s', '''') = '''Abe''''s''', 'StrQuote'); Assert(StrUnquote('"123"') = '123', 'StrUnQuote'); Assert(StrUnquote('"1""23"') = '1"23', 'StrUnQuote'); {$IFDEF SupportAnsiString} Assert(StrIsQuotedStrA('"ABC""D"'), 'StrIsQuotedStr'); Assert(StrIsQuotedStrA('"A"'), 'StrIsQuotedStr'); Assert(not StrIsQuotedStrA('"ABC""D'''), 'StrIsQuotedStr'); Assert(not StrIsQuotedStrA('"ABC""D'), 'StrIsQuotedStr'); Assert(not StrIsQuotedStrA('"'), 'StrIsQuotedStr'); Assert(not StrIsQuotedStrA(''), 'StrIsQuotedStr'); Assert(StrIsQuotedStrA(''''''), 'StrIsQuotedStr'); Assert(not StrIsQuotedStrA('''a'''''), 'StrIsQuotedStr'); {$ENDIF} { Delimited } {$IFDEF SupportAnsiString} Assert(StrAfterA('ABCDEF', 'CD') = 'EF', 'StrAfter'); Assert(StrAfterA('ABCDEF', 'CE') = '', 'StrAfter'); Assert(StrAfterA('ABCDEF', 'CE', True) = 'ABCDEF', 'StrAfter'); Assert(StrAfterRevA('ABCABCABC', 'CA') = 'BC', 'StrAfterRev'); Assert(StrAfterRevA('ABCABCABC', 'CD') = '', 'StrAfterRev'); Assert(StrAfterRevA('ABCABCABC', 'CD', True) = 'ABCABCABC', 'StrAfterRev'); Assert(StrBetweenCharA('ABC', AnsiChar('<'), AnsiChar('>')) = '', 'StrBetweenChar'); Assert(StrBetweenCharA('ABC', AnsiChar('<'), AnsiChar('>')) = 'D', 'StrBetweenChar'); Assert(StrBetweenCharA('A*BC*D', AnsiChar('*'), AnsiChar('*')) = 'BC', 'StrBetweenChar'); Assert(StrBetweenCharA('(ABC)', AnsiChar('('), AnsiChar(')')) = 'ABC', 'StrBetweenChar'); Assert(StrBetweenCharA('XYZ(ABC)(DEF)', AnsiChar('('), AnsiChar(')')) = 'ABC', 'StrBetweenChar'); Assert(StrBetweenCharA('XYZ"ABC', AnsiChar('"'), AnsiChar('"')) = '', 'StrBetweenChar'); Assert(StrBetweenCharA('1234543210', AnsiChar('3'), AnsiChar('3'), False, False) = '454', 'StrBetweenChar'); Assert(StrBetweenCharA('1234543210', AnsiChar('3'), AnsiChar('4'), False, False) = '', 'StrBetweenChar'); Assert(StrBetweenCharA('1234543210', AnsiChar('4'), AnsiChar('3'), False, False) = '54', 'StrBetweenChar'); Assert(StrBetweenCharA('1234543210', AnsiChar('4'), AnsiChar('6'), False, False) = '', 'StrBetweenChar'); Assert(StrBetweenCharA('1234543210', AnsiChar('4'), AnsiChar('6'), False, True) = '543210', 'StrBetweenChar'); {$ENDIF} Assert(StrBetweenCharU('ABC', WideChar('<'), WideChar('>')) = '', 'StrBetweenChar'); Assert(StrBetweenCharU('ABC', WideChar('<'), WideChar('>')) = 'D', 'StrBetweenChar'); Assert(StrBetweenChar('ABC', Char('<'), Char('>')) = '', 'StrBetweenChar'); Assert(StrBetweenChar('ABC', Char('<'), Char('>')) = 'D', 'StrBetweenChar'); {$IFDEF SupportAnsiString} Assert(StrBetweenA('XYZ(ABC)(DEF)', '(', [')']) = 'ABC', 'StrBetween'); Assert(StrBetweenA('XYZ(ABC)(DEF)', 'Z(', [')']) = 'ABC', 'StrBetween'); S := 'XYZ(ABC)G"H"IJ"KLM"') = 'DEF', 'StrRemoveCharDelimited'); Assert(S = 'XYZ(ABC)G"H"IJ"KLM"') = '', 'StrRemoveCharDelimited'); Assert(S = 'XYZ(ABC)G"H"IJ"KLM"