mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-01 16:53:42 +02:00
1554 lines
37 KiB
ObjectPascal
1554 lines
37 KiB
ObjectPascal
{$mode objfpc}
|
|
{$h+}
|
|
{
|
|
$Id$
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2000 by the Free Pascal development team
|
|
|
|
Delphi/Kylix compatibility unit: String handling routines.
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
unit strutils;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils{, Types};
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Case sensitive search/replace
|
|
---------------------------------------------------------------------}
|
|
|
|
Function AnsiResemblesText(const AText, AOther: string): Boolean;
|
|
Function AnsiContainsText(const AText, ASubText: string): Boolean;
|
|
Function AnsiStartsText(const ASubText, AText: string): Boolean;
|
|
Function AnsiEndsText(const ASubText, AText: string): Boolean;
|
|
Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
|
|
Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
|
|
Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Case insensitive search/replace
|
|
---------------------------------------------------------------------}
|
|
|
|
Function AnsiContainsStr(const AText, ASubText: string): Boolean;
|
|
Function AnsiStartsStr(const ASubText, AText: string): Boolean;
|
|
Function AnsiEndsStr(const ASubText, AText: string): Boolean;
|
|
Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
|
|
Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
|
|
Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Playthingies
|
|
---------------------------------------------------------------------}
|
|
|
|
Function DupeString(const AText: string; ACount: Integer): string;
|
|
Function ReverseString(const AText: string): string;
|
|
Function AnsiReverseString(const AText: AnsiString): AnsiString;
|
|
Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
|
|
Function RandomFrom(const AValues: array of string): string; overload;
|
|
Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
|
|
Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
|
|
|
|
{ ---------------------------------------------------------------------
|
|
VB emulations.
|
|
---------------------------------------------------------------------}
|
|
|
|
Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
|
|
Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
|
|
Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
|
|
Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
|
|
{$ifndef ver1_0}
|
|
Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
|
|
Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
|
|
Function RightStr(const AText: WideString; const ACount: Integer): WideString;
|
|
Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
|
|
{$endif}
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Extended search and replace
|
|
---------------------------------------------------------------------}
|
|
|
|
const
|
|
{ Default word delimiters are any character except the core alphanumerics. }
|
|
WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
|
|
|
|
type
|
|
TStringSearchOption = (soDown, soMatchCase, soWholeWord);
|
|
TStringSearchOptions = set of TStringSearchOption;
|
|
TStringSeachOption = TStringSearchOption;
|
|
|
|
Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
|
|
Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
|
|
Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
|
|
Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
|
|
Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Soundex Functions.
|
|
---------------------------------------------------------------------}
|
|
|
|
type
|
|
TSoundexLength = 1..MaxInt;
|
|
|
|
Function Soundex(const AText: string; ALength: TSoundexLength): string;
|
|
Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
|
|
|
|
type
|
|
TSoundexIntLength = 1..8;
|
|
|
|
Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
|
|
Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
|
|
Function DecodeSoundexInt(AValue: Integer): string;
|
|
Function SoundexWord(const AText: string): Word;
|
|
Function DecodeSoundexWord(AValue: Word): string;
|
|
Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
|
|
Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
|
|
Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
|
|
Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
|
|
Function SoundexProc(const AText, AOther: string): Boolean;
|
|
|
|
type
|
|
TCompareTextProc = Function(const AText, AOther: string): Boolean;
|
|
|
|
Const
|
|
AnsiResemblesProc: TCompareTextProc = @SoundexProc;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Other functions, based on RxStrUtils.
|
|
---------------------------------------------------------------------}
|
|
|
|
function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
|
|
function DelSpace(const S: string): string;
|
|
function DelChars(const S: string; Chr: Char): string;
|
|
function DelSpace1(const S: string): string;
|
|
function Tab2Space(const S: string; Numb: Byte): string;
|
|
function NPos(const C: string; S: string; N: Integer): Integer;
|
|
function AddChar(C: Char; const S: string; N: Integer): string;
|
|
function AddCharR(C: Char; const S: string; N: Integer): string;
|
|
function PadLeft(const S: string; N: Integer): string;
|
|
function PadRight(const S: string; N: Integer): string;
|
|
function PadCenter(const S: string; Len: Integer): string;
|
|
function Copy2Symb(const S: string; Symb: Char): string;
|
|
function Copy2SymbDel(var S: string; Symb: Char): string;
|
|
function Copy2Space(const S: string): string;
|
|
function Copy2SpaceDel(var S: string): string;
|
|
function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
|
|
function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
|
|
function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
|
|
function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
|
|
function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
|
|
function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
|
|
function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
|
|
function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
|
|
function FindPart(const HelpWilds, InputStr: string): Integer;
|
|
function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
|
|
function XorString(const Key, Src: ShortString): ShortString;
|
|
function XorEncode(const Key, Source: string): string;
|
|
function XorDecode(const Key, Source: string): string;
|
|
function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
|
|
function Numb2USA(const S: string): string;
|
|
function Hex2Dec(const S: string): Longint;
|
|
function Dec2Numb(N: Longint; Len, Base: Byte): string;
|
|
function Numb2Dec(S: string; Base: Byte): Longint;
|
|
function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
|
|
function IntToRoman(Value: Longint): string;
|
|
function RomanToInt(const S: string): Longint;
|
|
|
|
const
|
|
DigitChars = ['0'..'9'];
|
|
Brackets = ['(',')','[',']','{','}'];
|
|
StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
|
|
|
|
implementation
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Auxiliary functions
|
|
---------------------------------------------------------------------}
|
|
|
|
Procedure NotYetImplemented (FN : String);
|
|
|
|
begin
|
|
Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
|
|
end;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Case sensitive search/replace
|
|
---------------------------------------------------------------------}
|
|
|
|
Function AnsiResemblesText(const AText, AOther: string): Boolean;
|
|
|
|
begin
|
|
if Assigned(AnsiResemblesProc) then
|
|
Result:=AnsiResemblesProc(AText,AOther)
|
|
else
|
|
Result:=False;
|
|
end;
|
|
|
|
Function AnsiContainsText(const AText, ASubText: string): Boolean;
|
|
|
|
begin
|
|
AnsiContainsText:=Pos(ASubText,AText)<>0;
|
|
end;
|
|
|
|
Function AnsiStartsText(const ASubText, AText: string): Boolean;
|
|
begin
|
|
Result:=Copy(AText,1,Length(AsubText))=ASubText;
|
|
end;
|
|
|
|
Function AnsiEndsText(const ASubText, AText: string): Boolean;
|
|
begin
|
|
result:=Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText))=asubtext;
|
|
end;
|
|
|
|
Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
|
|
|
|
var iFrom, iTo: longint;
|
|
|
|
begin
|
|
iTo:=Pos(AFromText,AText);
|
|
if iTo=0 then
|
|
result:=AText
|
|
else
|
|
begin
|
|
result:='';
|
|
iFrom:=1;
|
|
while (ito<>0) do
|
|
begin
|
|
result:=Result+Copy(AText,IFrom,Ito-IFrom+1)+AToText;
|
|
ifrom:=ITo+Length(afromtext);
|
|
ito:=Posex(Afromtext,atext,ifrom);
|
|
end;
|
|
if ifrom<=length(atext) then
|
|
result:=result+copy(AText,ifrom, length(atext));
|
|
end;
|
|
end;
|
|
|
|
Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
|
|
|
|
begin
|
|
Result:=(AnsiIndexText(AText,AValues)<>-1)
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
|
|
|
|
var i : longint;
|
|
|
|
begin
|
|
result:=-1;
|
|
if high(AValues)=-1 Then
|
|
Exit;
|
|
for i:=low(AValues) to High(Avalues) do
|
|
if CompareText(avalues[i],atext)=0 Then
|
|
exit(i); // make sure it is the first val.
|
|
end;
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Case insensitive search/replace
|
|
---------------------------------------------------------------------}
|
|
|
|
Function AnsiContainsStr(const AText, ASubText: string): Boolean;
|
|
|
|
begin
|
|
Result := Pos(ASubText,AText)<>0;
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiStartsStr(const ASubText, AText: string): Boolean;
|
|
|
|
begin
|
|
Result := Pos(ASubText,AText)=1;
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiEndsStr(const ASubText, AText: string): Boolean;
|
|
|
|
begin
|
|
Result := Pos(ASubText,AText)=(length(AText)-length(ASubText)+1);
|
|
end;
|
|
|
|
|
|
Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
|
|
|
|
begin
|
|
Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
|
|
|
|
begin
|
|
Result:=AnsiIndexStr(AText,Avalues)<>-1;
|
|
end;
|
|
|
|
|
|
Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
|
|
|
|
var i : longint;
|
|
|
|
begin
|
|
result:=-1;
|
|
if high(AValues)=-1 Then
|
|
Exit;
|
|
for i:=low(AValues) to High(Avalues) do
|
|
if (avalues[i]=AText) Then
|
|
exit(i); // make sure it is the first val.
|
|
end;
|
|
|
|
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Playthingies
|
|
---------------------------------------------------------------------}
|
|
|
|
Function DupeString(const AText: string; ACount: Integer): string;
|
|
|
|
var i,l : integer;
|
|
|
|
begin
|
|
result:='';
|
|
if aCount>=0 then
|
|
begin
|
|
l:=length(atext);
|
|
SetLength(result,aCount*l);
|
|
for i:=0 to ACount-1 do
|
|
move(atext[1],Result[l*i+1],l);
|
|
end;
|
|
end;
|
|
|
|
Function ReverseString(const AText: string): string;
|
|
|
|
var c: char;
|
|
i,j:longint;
|
|
|
|
begin
|
|
setlength(result,length(atext));
|
|
i:=1; j:=length(atext);
|
|
while (i<=j) do
|
|
begin
|
|
result[i]:=atext[j-i+1];
|
|
inc(i);
|
|
end;
|
|
end;
|
|
|
|
|
|
Function AnsiReverseString(const AText: AnsiString): AnsiString;
|
|
|
|
begin
|
|
Result:=ReverseString(AText);
|
|
end;
|
|
|
|
|
|
|
|
Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
|
|
|
|
var i,j : longint;
|
|
|
|
begin
|
|
j:=length(ASubText);
|
|
i:=length(AText);
|
|
SetLength(Result,i-ALength+j);
|
|
move (AText[1],result[1],AStart-1);
|
|
move (ASubText[1],result[AStart],j);
|
|
move (AText[AStart+ALength], Result[AStart+j],i-AStart-ALength+1);
|
|
end;
|
|
|
|
|
|
|
|
Function RandomFrom(const AValues: array of string): string; overload;
|
|
|
|
begin
|
|
if high(AValues)=-1 then exit('');
|
|
result:=Avalues[random(High(AValues)+1)];
|
|
end;
|
|
|
|
|
|
|
|
Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
|
|
|
|
begin
|
|
if avalue then
|
|
result:=atrue
|
|
else
|
|
result:=afalse;
|
|
end;
|
|
|
|
|
|
|
|
Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
|
|
|
|
begin
|
|
if avalue then
|
|
result:=atrue
|
|
else
|
|
result:='';
|
|
end;
|
|
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
VB emulations.
|
|
---------------------------------------------------------------------}
|
|
|
|
Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result:=Copy(AText,1,ACount);
|
|
end;
|
|
|
|
Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
|
|
var j,l:integer;
|
|
|
|
begin
|
|
l:=length(atext);
|
|
j:=ACount;
|
|
if j>l then j:=l;
|
|
Result:=Copy(AText,l-j+1,j);
|
|
end;
|
|
|
|
Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
|
|
|
|
begin
|
|
if (ACount=0) or (AStart>length(atext)) then
|
|
exit('');
|
|
Result:=Copy(AText,AStart,ACount);
|
|
end;
|
|
|
|
|
|
|
|
Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result:=LeftStr(AText,AByteCount);
|
|
end;
|
|
|
|
|
|
|
|
Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result:=RightStr(Atext,AByteCount);
|
|
end;
|
|
|
|
|
|
|
|
Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result:=MidStr(AText,AByteStart,AByteCount);
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result := copy(AText,1,ACount);
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result := copy(AText,length(AText)-ACount+1,ACount);
|
|
end;
|
|
|
|
|
|
|
|
Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
|
|
|
|
begin
|
|
Result:=Copy(AText,AStart,ACount);
|
|
end;
|
|
|
|
{$ifndef ver1_0}
|
|
Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
|
|
|
|
begin
|
|
Result:=Copy(AText,1,ACount);
|
|
end;
|
|
|
|
|
|
|
|
Function RightStr(const AText: WideString; const ACount: Integer): WideString;
|
|
|
|
var
|
|
j,l:integer;
|
|
|
|
begin
|
|
l:=length(atext);
|
|
j:=ACount;
|
|
if j>l then j:=l;
|
|
Result:=Copy(AText,l-j+1,j);
|
|
end;
|
|
|
|
|
|
|
|
Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
|
|
|
|
begin
|
|
Result:=Copy(AText,AStart,ACount);
|
|
end;
|
|
{$endif}
|
|
|
|
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Extended search and replace
|
|
---------------------------------------------------------------------}
|
|
|
|
Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
|
|
|
|
var
|
|
Len,I,SLen: Integer;
|
|
C: Char;
|
|
Found : Boolean;
|
|
Direction: Shortint;
|
|
CharMap: array[Char] of Char;
|
|
|
|
Function GotoNextWord(var P : PChar): Boolean;
|
|
|
|
begin
|
|
if (Direction=1) then
|
|
begin
|
|
// Skip characters
|
|
While (Len>0) and not (P^ in WordDelimiters) do
|
|
begin
|
|
Inc(P);
|
|
Dec(Len);
|
|
end;
|
|
// skip delimiters
|
|
While (Len>0) and (P^ in WordDelimiters) do
|
|
begin
|
|
Inc(P);
|
|
Dec(Len);
|
|
end;
|
|
Result:=Len>0;
|
|
end
|
|
else
|
|
begin
|
|
// Skip Delimiters
|
|
While (Len>0) and (P^ in WordDelimiters) do
|
|
begin
|
|
Dec(P);
|
|
Dec(Len);
|
|
end;
|
|
// skip characters
|
|
While (Len>0) and not (P^ in WordDelimiters) do
|
|
begin
|
|
Dec(P);
|
|
Dec(Len);
|
|
end;
|
|
Result:=Len>0;
|
|
// We're on the first delimiter. Pos back on char.
|
|
Inc(P);
|
|
Inc(Len);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result:=nil;
|
|
Slen:=Length(SearchString);
|
|
if (BufLen<=0) or (Slen=0) then
|
|
Exit;
|
|
if soDown in Options then
|
|
begin
|
|
Direction:=1;
|
|
Inc(SelStart,SelLength);
|
|
Len:=BufLen-SelStart-SLen+1;
|
|
if (Len<=0) then
|
|
Exit;
|
|
end
|
|
else
|
|
begin
|
|
Direction:=-1;
|
|
Dec(SelStart,Length(SearchString));
|
|
Len:=SelStart+1;
|
|
end;
|
|
if (SelStart<0) or (SelStart>BufLen) then
|
|
Exit;
|
|
Result:=@Buf[SelStart];
|
|
for C:=Low(Char) to High(Char) do
|
|
if (soMatchCase in Options) then
|
|
CharMap[C]:=C
|
|
else
|
|
CharMap[C]:=Upcase(C);
|
|
if Not (soMatchCase in Options) then
|
|
SearchString:=UpCase(SearchString);
|
|
Found:=False;
|
|
while (Result<>Nil) and (Not Found) do
|
|
begin
|
|
if ((soWholeWord in Options) and
|
|
(Result<>@Buf[SelStart]) and
|
|
not GotoNextWord(Result)) then
|
|
Result:=Nil
|
|
else
|
|
begin
|
|
// try to match whole searchstring
|
|
I:=0;
|
|
while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
|
|
Inc(I);
|
|
// Whole searchstring matched ?
|
|
if (I=SLen) then
|
|
Found:=(Len=0) or
|
|
(not (soWholeWord in Options)) or
|
|
(Result[SLen] in WordDelimiters);
|
|
if not Found then
|
|
begin
|
|
Inc(Result,Direction);
|
|
Dec(Len);
|
|
If (Len=0) then
|
|
Result:=Nil;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
|
|
|
|
begin
|
|
Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
|
|
end;
|
|
|
|
|
|
|
|
Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
|
|
|
|
var i : pchar;
|
|
begin
|
|
if (offset<1) or (offset>length(s)) then exit(0);
|
|
i:=strpos(@s[offset],@substr[1]);
|
|
if i=nil then
|
|
PosEx:=0
|
|
else
|
|
PosEx:=succ(i-pchar(s));
|
|
end;
|
|
|
|
|
|
Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
|
|
|
|
begin
|
|
posex:=posex(substr,s,1);
|
|
end;
|
|
|
|
Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
|
|
|
|
var l : longint;
|
|
begin
|
|
if (offset<1) or (offset>length(s)) then exit(0);
|
|
l:=length(s);
|
|
{$ifndef useindexbyte}
|
|
while (offset<=l) and (s[offset]<>c) do inc(offset);
|
|
if offset>l then
|
|
posex:=0
|
|
else
|
|
posex:=offset;
|
|
{$else}
|
|
posex:=offset+indexbyte(s[offset],l-offset+1);
|
|
if posex=(offset-1) then
|
|
posex:=0;
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
Soundex Functions.
|
|
---------------------------------------------------------------------}
|
|
Const
|
|
SScore : array[1..255] of Char =
|
|
('0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 1..32
|
|
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 33..64
|
|
'0','1','2','3','0','1','2','i','0','2','2','4','5','5','0','1','2','6','2','3','0','1','i','2','i','2', // 64..90
|
|
'0','0','0','0','0','0', // 91..95
|
|
'0','1','2','3','0','1','2','i','0','2','2','4','5','5','0','1','2','6','2','3','0','1','i','2','i','2', // 96..122
|
|
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 123..154
|
|
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 155..186
|
|
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 187..218
|
|
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 219..250
|
|
'0','0','0','0','0'); // 251..255
|
|
|
|
|
|
|
|
Function Soundex(const AText: string; ALength: TSoundexLength): string;
|
|
|
|
Var
|
|
S,PS : Char;
|
|
I,L : integer;
|
|
|
|
begin
|
|
Result:='';
|
|
PS:=#0;
|
|
If Length(AText)>0 then
|
|
begin
|
|
Result:=Upcase(AText[1]);
|
|
I:=2;
|
|
L:=Length(AText);
|
|
While (I<=L) and (Length(Result)<ALength) do
|
|
begin
|
|
S:=SScore[Ord(AText[i])];
|
|
If Not (S in ['0','i',PS]) then
|
|
Result:=Result+S;
|
|
If (S<>'i') then
|
|
PS:=S;
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
L:=Length(Result);
|
|
If (L<ALength) then
|
|
Result:=Result+StringOfChar('0',Alength-L);
|
|
end;
|
|
|
|
|
|
|
|
Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
|
|
|
|
begin
|
|
Result:=Soundex(AText,4);
|
|
end;
|
|
|
|
Const
|
|
Ord0 = Ord('0');
|
|
OrdA = Ord('A');
|
|
|
|
Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
|
|
|
|
var
|
|
SE: string;
|
|
I: Integer;
|
|
|
|
begin
|
|
Result:=-1;
|
|
SE:=Soundex(AText,ALength);
|
|
If Length(SE)>0 then
|
|
begin
|
|
Result:=Ord(SE[1])-OrdA;
|
|
if ALength > 1 then
|
|
begin
|
|
Result:=Result*26+(Ord(SE[2])-Ord0);
|
|
for I:=3 to ALength do
|
|
Result:=(Ord(SE[I])-Ord0)+Result*7;
|
|
end;
|
|
Result:=ALength+Result*9;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
|
|
|
|
begin
|
|
Result:=SoundexInt(AText,4);
|
|
end;
|
|
|
|
|
|
|
|
Function DecodeSoundexInt(AValue: Integer): string;
|
|
|
|
var
|
|
I, Len: Integer;
|
|
|
|
begin
|
|
Result := '';
|
|
Len := AValue mod 9;
|
|
AValue := AValue div 9;
|
|
for I:=Len downto 3 do
|
|
begin
|
|
Result:=Chr(Ord0+(AValue mod 7))+Result;
|
|
AValue:=AValue div 7;
|
|
end;
|
|
if Len>2 then
|
|
Result:=IntToStr(AValue mod 26)+Result;
|
|
AValue:=AValue div 26;
|
|
Result:=Chr(OrdA+AValue)+Result;
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexWord(const AText: string): Word;
|
|
|
|
Var
|
|
S : String;
|
|
|
|
begin
|
|
S:=SoundEx(Atext,4);
|
|
Result:=Ord(S[1])-OrdA;
|
|
Result:=Result*26+StrToInt(S[2]);
|
|
Result:=Result*7+StrToInt(S[3]);
|
|
Result:=Result*7+StrToInt(S[4]);
|
|
end;
|
|
|
|
|
|
|
|
Function DecodeSoundexWord(AValue: Word): string;
|
|
|
|
begin
|
|
Result := Chr(Ord0+ (AValue mod 7)) + Result;
|
|
AValue := AValue div 7;
|
|
Result := Chr(Ord0+ (AValue mod 7)) + Result;
|
|
AValue := AValue div 7;
|
|
Result := IntToStr(AValue mod 26) + Result;
|
|
AValue := AValue div 26;
|
|
Result := Chr(OrdA+AValue) + Result;
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
|
|
|
|
begin
|
|
Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
|
|
|
|
begin
|
|
Result:=SoundexSimilar(AText,AOther,4);
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
|
|
|
|
begin
|
|
Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
|
|
|
|
begin
|
|
Result:=SoundexCompare(AText,AOther,4);
|
|
end;
|
|
|
|
|
|
|
|
Function SoundexProc(const AText, AOther: string): Boolean;
|
|
|
|
begin
|
|
Result:=SoundexSimilar(AText,AOther);
|
|
end;
|
|
|
|
{ ---------------------------------------------------------------------
|
|
RxStrUtils-like functions.
|
|
---------------------------------------------------------------------}
|
|
|
|
|
|
function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
|
|
|
|
var
|
|
i,l: Integer;
|
|
|
|
begin
|
|
l:=Length(S);
|
|
i:=1;
|
|
Result:=True;
|
|
while Result and (i<=l) do
|
|
begin
|
|
Result:=Not (S[i] in EmptyChars);
|
|
Inc(i);
|
|
end;
|
|
end;
|
|
|
|
function DelSpace(const S: String): string;
|
|
|
|
begin
|
|
Result:=DelChars(S,' ');
|
|
end;
|
|
|
|
function DelChars(const S: string; Chr: Char): string;
|
|
|
|
var
|
|
I,J: Integer;
|
|
|
|
begin
|
|
Result:=S;
|
|
I:=Length(Result);
|
|
While I>0 do
|
|
begin
|
|
if Result[I]=Chr then
|
|
begin
|
|
J:=I-1;
|
|
While (J>0) and (Result[J]=Chr) do
|
|
Dec(j);
|
|
Delete(Result,J+1,I-J);
|
|
I:=J+1;
|
|
end;
|
|
dec(I);
|
|
end;
|
|
end;
|
|
|
|
function DelSpace1(const S: string): string;
|
|
|
|
var
|
|
i: Integer;
|
|
|
|
begin
|
|
Result:=S;
|
|
for i:=Length(Result) downto 2 do
|
|
if (Result[i]=' ') and (Result[I-1]=' ') then
|
|
Delete(Result,I,1);
|
|
end;
|
|
|
|
function Tab2Space(const S: string; Numb: Byte): string;
|
|
|
|
var
|
|
I: Integer;
|
|
|
|
begin
|
|
I:=1;
|
|
Result:=S;
|
|
while I <= Length(Result) do
|
|
if Result[I]<>Chr(9) then
|
|
inc(I)
|
|
else
|
|
begin
|
|
Result[I]:=' ';
|
|
If (Numb>1) then
|
|
Insert(StringOfChar('0',Numb-1),Result,I);
|
|
Inc(I,Numb);
|
|
end;
|
|
end;
|
|
|
|
function NPos(const C: string; S: string; N: Integer): Integer;
|
|
|
|
var
|
|
i,p,k: Integer;
|
|
|
|
begin
|
|
Result:=0;
|
|
if N<1 then
|
|
Exit;
|
|
k:=0;
|
|
i:=1;
|
|
Repeat
|
|
p:=pos(C,S);
|
|
Inc(k,p);
|
|
if p>0 then
|
|
delete(S,1,p);
|
|
Inc(i);
|
|
Until (i>n) or (p=0);
|
|
If (P>0) then
|
|
Result:=K;
|
|
end;
|
|
|
|
function AddChar(C: Char; const S: string; N: Integer): string;
|
|
|
|
Var
|
|
l : Integer;
|
|
|
|
begin
|
|
Result:=S;
|
|
l:=Length(Result);
|
|
if l<N then
|
|
Result:=StringOfChar(C,N-l)+Result;
|
|
end;
|
|
|
|
function AddCharR(C: Char; const S: string; N: Integer): string;
|
|
|
|
Var
|
|
l : Integer;
|
|
|
|
begin
|
|
Result:=S;
|
|
l:=Length(Result);
|
|
if l<N then
|
|
Result:=Result+StringOfChar(C,N-l);
|
|
end;
|
|
|
|
function PadRight(const S: string; N: Integer): string;
|
|
begin
|
|
Result:=AddCharR(' ',S,N);
|
|
end;
|
|
|
|
function PadLeft(const S: string; N: Integer): string;
|
|
begin
|
|
Result:=AddChar(' ',S,N);
|
|
end;
|
|
|
|
function Copy2Symb(const S: string; Symb: Char): string;
|
|
|
|
var
|
|
p: Integer;
|
|
|
|
begin
|
|
p:=Pos(Symb,S);
|
|
if p=0 then
|
|
p:=Length(S)+1;
|
|
Result:=Copy(S,1,p-1);
|
|
end;
|
|
|
|
function Copy2SymbDel(var S: string; Symb: Char): string;
|
|
|
|
begin
|
|
Result:=Copy2Symb(S,Symb);
|
|
S:=TrimRight(Copy(S,Length(Result)+1,Length(S)));
|
|
end;
|
|
|
|
function Copy2Space(const S: string): string;
|
|
begin
|
|
Result:=Copy2Symb(S,' ');
|
|
end;
|
|
|
|
function Copy2SpaceDel(var S: string): string;
|
|
begin
|
|
Result:=Copy2SymbDel(S,' ');
|
|
end;
|
|
|
|
function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
|
|
|
|
var
|
|
l : Integer;
|
|
P,PE : PChar;
|
|
|
|
begin
|
|
Result:=AnsiLowerCase(S);
|
|
P:=PChar(Result);
|
|
PE:=P+Length(Result);
|
|
while (P<PE) do
|
|
begin
|
|
while (P<PE) and (P^ in WordDelims) do
|
|
inc(P);
|
|
if (P<PE) then
|
|
P^:=UpCase(P^);
|
|
while (P<PE) and not (P^ in WordDelims) do
|
|
inc(P);
|
|
end;
|
|
end;
|
|
|
|
function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
|
|
|
|
var
|
|
P,PE : PChar;
|
|
|
|
begin
|
|
Result:=0;
|
|
P:=Pchar(S);
|
|
PE:=P+Length(S);
|
|
while (P<PE) do
|
|
begin
|
|
while (P<PE) and (P^ in WordDelims) do
|
|
Inc(P);
|
|
if (P<PE) then
|
|
inc(Result);
|
|
while (P<PE) and not (P^ in WordDelims) do
|
|
inc(P);
|
|
end;
|
|
end;
|
|
|
|
function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
|
|
|
|
var
|
|
PS,P,PE : PChar;
|
|
Count: Integer;
|
|
|
|
begin
|
|
Result:=0;
|
|
Count:=0;
|
|
PS:=PChar(S);
|
|
PE:=PS+Length(S);
|
|
P:=PS;
|
|
while (P<PE) and (Count<>N) do
|
|
begin
|
|
while (P<PE) and (P^ in WordDelims) do
|
|
inc(P);
|
|
if (P<PE) then
|
|
inc(Count);
|
|
if (Count<>N) then
|
|
while (P<PE) and not (P^ in WordDelims) do
|
|
inc(P)
|
|
else
|
|
Result:=(P-PS)+1;
|
|
end;
|
|
end;
|
|
|
|
function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
|
|
|
|
var
|
|
i: Integer;
|
|
|
|
begin
|
|
Result:=ExtractWordPos(N,S,WordDelims,i);
|
|
end;
|
|
|
|
function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
|
|
var
|
|
i,j,l: Integer;
|
|
begin
|
|
j:=0;
|
|
i:=WordPosition(N, S, WordDelims);
|
|
Pos:=i;
|
|
if (i<>0) then
|
|
begin
|
|
j:=i;
|
|
l:=Length(S);
|
|
while (j<=L) and not (S[j] in WordDelims) do
|
|
inc(j);
|
|
end;
|
|
SetLength(Result,j-i);
|
|
If ((j-i)>0) then
|
|
Move(S[i],Result[1],j-i);
|
|
end;
|
|
|
|
function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
|
|
var
|
|
w,i,l,len: Integer;
|
|
begin
|
|
w:=0;
|
|
i:=1;
|
|
l:=0;
|
|
len:=Length(S);
|
|
SetLength(Result, 0);
|
|
while (i<=len) and (w<>N) do
|
|
begin
|
|
if s[i] in Delims then
|
|
inc(w)
|
|
else
|
|
begin
|
|
if (N-1)=w then
|
|
begin
|
|
inc(l);
|
|
SetLength(Result,l);
|
|
Result[Len]:=S[i];
|
|
end;
|
|
end;
|
|
inc(i);
|
|
end;
|
|
end;
|
|
|
|
function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
|
|
|
|
var
|
|
i,l: Integer;
|
|
|
|
begin
|
|
i:=Pos;
|
|
l:=Length(S);
|
|
while (i<=l) and not (S[i] in Delims) do
|
|
inc(i);
|
|
Result:=Copy(S,Pos,i-Pos);
|
|
if (i<=l) and (S[i] in Delims) then
|
|
inc(i);
|
|
Pos:=i;
|
|
end;
|
|
|
|
function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
|
|
|
|
var
|
|
i,Count : Integer;
|
|
|
|
begin
|
|
Result:=False;
|
|
Count:=WordCount(S, WordDelims);
|
|
I:=1;
|
|
While (Not Result) and (I<=Count) do
|
|
Result:=ExtractWord(i,S,WordDelims)=W;
|
|
end;
|
|
|
|
|
|
function Numb2USA(const S: string): string;
|
|
var
|
|
i, NA: Integer;
|
|
begin
|
|
i:=Length(S);
|
|
Result:=S;
|
|
NA:=0;
|
|
while (i > 0) do begin
|
|
if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
|
|
begin
|
|
insert(',', Result, i);
|
|
inc(NA);
|
|
end;
|
|
Dec(i);
|
|
end;
|
|
end;
|
|
|
|
function PadCenter(const S: string; Len: Integer): string;
|
|
begin
|
|
if Length(S)<Len then
|
|
begin
|
|
Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
|
|
Result:=Result+StringOfChar(' ',Len-Length(Result));
|
|
end
|
|
else
|
|
Result:=S;
|
|
end;
|
|
|
|
function Hex2Dec(const S: string): Longint;
|
|
var
|
|
HexStr: string;
|
|
begin
|
|
if Pos('$',S)=0 then
|
|
HexStr:='$'+ S
|
|
else
|
|
HexStr:=S;
|
|
Result:=StrTointDef(HexStr,0);
|
|
end;
|
|
|
|
function Dec2Numb(N: Longint; Len, Base: Byte): string;
|
|
|
|
var
|
|
C: Integer;
|
|
Number: Longint;
|
|
|
|
begin
|
|
if N=0 then
|
|
Result:='0'
|
|
else
|
|
begin
|
|
Number:=N;
|
|
Result:='';
|
|
while Number>0 do
|
|
begin
|
|
C:=Number mod Base;
|
|
if C>9 then
|
|
C:=C+55
|
|
else
|
|
C:=C+48;
|
|
Result:=Chr(C)+Result;
|
|
Number:=Number div Base;
|
|
end;
|
|
end;
|
|
if (Result<>'') then
|
|
Result:=AddChar('0',Result,Len);
|
|
end;
|
|
|
|
function Numb2Dec(S: string; Base: Byte): Longint;
|
|
|
|
var
|
|
i, P: Longint;
|
|
|
|
begin
|
|
i:=Length(S);
|
|
Result:=0;
|
|
S:=UpperCase(S);
|
|
P:=1;
|
|
while (i>=1) do
|
|
begin
|
|
if (S[i]>'@') then
|
|
Result:=Result+(Ord(S[i])-55)*P
|
|
else
|
|
Result:=Result+(Ord(S[i])-48)*P;
|
|
Dec(i);
|
|
P:=P*Base;
|
|
end;
|
|
end;
|
|
|
|
function RomanToint(const S: string): Longint;
|
|
|
|
const
|
|
RomanChars = ['C','D','i','L','M','V','X'];
|
|
RomanValues : array['C'..'X'] of Word
|
|
= (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
|
|
|
|
var
|
|
index, Next: Char;
|
|
i,l: Integer;
|
|
Negative: Boolean;
|
|
|
|
begin
|
|
Result:=0;
|
|
i:=0;
|
|
Negative:=(Length(S)>0) and (S[1]='-');
|
|
if Negative then
|
|
inc(i);
|
|
l:=Length(S);
|
|
while (i<l) do
|
|
begin
|
|
inc(i);
|
|
index:=UpCase(S[i]);
|
|
if index in RomanChars then
|
|
begin
|
|
if Succ(i)<=l then
|
|
Next:=UpCase(S[i+1])
|
|
else
|
|
Next:=#0;
|
|
if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
|
|
begin
|
|
inc(Result, RomanValues[Next]);
|
|
Dec(Result, RomanValues[index]);
|
|
inc(i);
|
|
end
|
|
else
|
|
inc(Result, RomanValues[index]);
|
|
end
|
|
else
|
|
begin
|
|
Result:=0;
|
|
Exit;
|
|
end;
|
|
end;
|
|
if Negative then
|
|
Result:=-Result;
|
|
end;
|
|
|
|
function intToRoman(Value: Longint): string;
|
|
|
|
const
|
|
Arabics : Array[1..13] of Integer
|
|
= (1,4,5,9,10,40,50,90,100,400,500,900,1000);
|
|
Romans : Array[1..13] of String
|
|
= ('i','iV','V','iX','X','XL','L','XC','C','CD','D','CM','M');
|
|
|
|
var
|
|
i: Integer;
|
|
|
|
begin
|
|
for i:=13 downto 1 do
|
|
while (Value >= Arabics[i]) do
|
|
begin
|
|
Value:=Value-Arabics[i];
|
|
Result:=Result+Romans[i];
|
|
end;
|
|
end;
|
|
|
|
function intToBin(Value: Longint; Digits, Spaces: Integer): string;
|
|
begin
|
|
Result:='';
|
|
if (Digits>32) then
|
|
Digits:=32;
|
|
while (Digits>0) do
|
|
begin
|
|
if (Digits mod Spaces)=0 then
|
|
Result:=Result+' ';
|
|
Dec(Digits);
|
|
Result:=Result+intToStr((Value shr Digits) and 1);
|
|
end;
|
|
end;
|
|
|
|
function FindPart(const HelpWilds, inputStr: string): Integer;
|
|
var
|
|
i, J: Integer;
|
|
Diff: Integer;
|
|
begin
|
|
Result:=0;
|
|
i:=Pos('?',HelpWilds);
|
|
if (i=0) then
|
|
Result:=Pos(HelpWilds, inputStr)
|
|
else
|
|
begin
|
|
Diff:=Length(inputStr) - Length(HelpWilds);
|
|
for i:=0 to Diff do
|
|
begin
|
|
for J:=1 to Length(HelpWilds) do
|
|
if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
|
|
begin
|
|
if (J=Length(HelpWilds)) then
|
|
begin
|
|
Result:=i+1;
|
|
Exit;
|
|
end;
|
|
end
|
|
else
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function isWild(inputStr, Wilds: string; ignoreCase: Boolean): Boolean;
|
|
|
|
function SearchNext(var Wilds: string): Integer;
|
|
|
|
begin
|
|
Result:=Pos('*', Wilds);
|
|
if Result>0 then
|
|
Wilds:=Copy(Wilds,1,Result - 1);
|
|
end;
|
|
|
|
var
|
|
CWild, CinputWord: Integer; { counter for positions }
|
|
i, LenHelpWilds: Integer;
|
|
MaxinputWord, MaxWilds: Integer; { Length of inputStr and Wilds }
|
|
HelpWilds: string;
|
|
begin
|
|
if Wilds = inputStr then begin
|
|
Result:=True;
|
|
Exit;
|
|
end;
|
|
repeat { delete '**', because '**' = '*' }
|
|
i:=Pos('**', Wilds);
|
|
if i > 0 then
|
|
Wilds:=Copy(Wilds, 1, i - 1) + '*' + Copy(Wilds, i + 2, Maxint);
|
|
until i = 0;
|
|
if Wilds = '*' then begin { for fast end, if Wilds only '*' }
|
|
Result:=True;
|
|
Exit;
|
|
end;
|
|
MaxinputWord:=Length(inputStr);
|
|
MaxWilds:=Length(Wilds);
|
|
if ignoreCase then begin { upcase all letters }
|
|
inputStr:=AnsiUpperCase(inputStr);
|
|
Wilds:=AnsiUpperCase(Wilds);
|
|
end;
|
|
if (MaxWilds = 0) or (MaxinputWord = 0) then begin
|
|
Result:=False;
|
|
Exit;
|
|
end;
|
|
CinputWord:=1;
|
|
CWild:=1;
|
|
Result:=True;
|
|
repeat
|
|
if inputStr[CinputWord] = Wilds[CWild] then begin { equal letters }
|
|
{ goto next letter }
|
|
inc(CWild);
|
|
inc(CinputWord);
|
|
Continue;
|
|
end;
|
|
if Wilds[CWild] = '?' then begin { equal to '?' }
|
|
{ goto next letter }
|
|
inc(CWild);
|
|
inc(CinputWord);
|
|
Continue;
|
|
end;
|
|
if Wilds[CWild] = '*' then begin { handling of '*' }
|
|
HelpWilds:=Copy(Wilds, CWild + 1, MaxWilds);
|
|
i:=SearchNext(HelpWilds);
|
|
LenHelpWilds:=Length(HelpWilds);
|
|
if i = 0 then begin
|
|
{ no '*' in the rest, compare the ends }
|
|
if HelpWilds = '' then Exit; { '*' is the last letter }
|
|
{ check the rest for equal Length and no '?' }
|
|
for i:=0 to LenHelpWilds - 1 do begin
|
|
if (HelpWilds[LenHelpWilds - i] <> inputStr[MaxinputWord - i]) and
|
|
(HelpWilds[LenHelpWilds - i]<> '?') then
|
|
begin
|
|
Result:=False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Exit;
|
|
end;
|
|
{ handle all to the next '*' }
|
|
inc(CWild, 1 + LenHelpWilds);
|
|
i:=FindPart(HelpWilds, Copy(inputStr, CinputWord, Maxint));
|
|
if i= 0 then begin
|
|
Result:=False;
|
|
Exit;
|
|
end;
|
|
CinputWord:=i + LenHelpWilds;
|
|
Continue;
|
|
end;
|
|
Result:=False;
|
|
Exit;
|
|
until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
|
|
{ no completed evaluation }
|
|
if CinputWord <= MaxinputWord then Result:=False;
|
|
if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then Result:=False;
|
|
end;
|
|
|
|
function XorString(const Key, Src: ShortString): ShortString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result:=Src;
|
|
if Length(Key) > 0 then
|
|
for i:=1 to Length(Src) do
|
|
Result[i]:=Chr(Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
|
|
end;
|
|
|
|
function XorEncode(const Key, Source: string): string;
|
|
|
|
var
|
|
i: Integer;
|
|
C: Byte;
|
|
|
|
begin
|
|
Result:='';
|
|
for i:=1 to Length(Source) do
|
|
begin
|
|
if Length(Key) > 0 then
|
|
C:=Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Byte(Source[i])
|
|
else
|
|
C:=Byte(Source[i]);
|
|
Result:=Result+AnsiLowerCase(intToHex(C, 2));
|
|
end;
|
|
end;
|
|
|
|
function XorDecode(const Key, Source: string): string;
|
|
var
|
|
i: Integer;
|
|
C: Char;
|
|
begin
|
|
Result:='';
|
|
for i:=0 to Length(Source) div 2 - 1 do
|
|
begin
|
|
C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
|
|
if Length(Key) > 0 then
|
|
C:=Chr(Byte(Key[1 + (i mod Length(Key))]) xor Byte(C));
|
|
Result:=Result + C;
|
|
end;
|
|
end;
|
|
|
|
function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
|
|
var
|
|
i: Integer;
|
|
S: string;
|
|
begin
|
|
i:=1;
|
|
Result:='';
|
|
while (Result='') and (i<=ParamCount) do
|
|
begin
|
|
S:=ParamStr(i);
|
|
if (SwitchChars=[]) or ((S[1] in SwitchChars) and (Length(S) > 1)) and
|
|
(AnsiCompareText(Copy(S,2,Length(S)-1),Switch)=0) then
|
|
begin
|
|
inc(i);
|
|
if i<=ParamCount then
|
|
Result:=ParamStr(i);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.9 2004-07-21 20:37:03 michael
|
|
+ Implemented all functions
|
|
|
|
Revision 1.8 2004/07/13 18:42:39 michael
|
|
+ Added some RxStrUtils functions for Rx compatibility
|
|
|
|
Revision 1.7 2004/07/01 15:42:18 peter
|
|
* fix 1.0.x compile
|
|
|
|
Revision 1.6 2004/06/29 19:37:17 marco
|
|
* updates from B. Tierens
|
|
|
|
Revision 1.5 2004/05/17 07:33:01 marco
|
|
* fixes from Luiz Am?rico
|
|
|
|
Revision 1.4 2004/03/19 12:54:22 marco
|
|
* more strutils small things
|
|
|
|
Revision 1.3 2004/03/18 16:55:47 marco
|
|
* more simple implementations done, based on copy() Largely untested
|
|
|
|
}
|