strutils.pp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. {
  2. Delphi/Kylix compatibility unit: String handling routines.
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2005 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. {$inline on}
  14. unit strutils;
  15. interface
  16. uses
  17. SysUtils{, Types};
  18. { ---------------------------------------------------------------------
  19. Case insensitive search/replace
  20. ---------------------------------------------------------------------}
  21. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  22. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  23. Function AnsiStartsText(const ASubText, AText: string): Boolean;inline;
  24. Function AnsiEndsText(const ASubText, AText: string): Boolean;inline;
  25. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;inline;
  26. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;inline;
  27. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  28. { ---------------------------------------------------------------------
  29. Case sensitive search/replace
  30. ---------------------------------------------------------------------}
  31. Function AnsiContainsStr(const AText, ASubText: string): Boolean;inline;
  32. Function AnsiStartsStr(const ASubText, AText: string): Boolean;inline;
  33. Function AnsiEndsStr(const ASubText, AText: string): Boolean;inline;
  34. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;inline;
  35. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;inline;
  36. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  37. { ---------------------------------------------------------------------
  38. Playthingies
  39. ---------------------------------------------------------------------}
  40. Function DupeString(const AText: string; ACount: Integer): string;
  41. Function ReverseString(const AText: string): string;
  42. Function AnsiReverseString(const AText: AnsiString): AnsiString;inline;
  43. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  44. Function RandomFrom(const AValues: array of string): string; overload;
  45. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;inline;
  46. Function IfThen(AValue: Boolean; const ATrue: string): string;inline; // ; AFalse: string = ''
  47. { ---------------------------------------------------------------------
  48. VB emulations.
  49. ---------------------------------------------------------------------}
  50. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  51. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  52. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  53. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  54. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;inline;
  55. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  56. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  57. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  58. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  59. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;inline;
  60. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  61. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;inline;
  62. { ---------------------------------------------------------------------
  63. Extended search and replace
  64. ---------------------------------------------------------------------}
  65. const
  66. { Default word delimiters are any character except the core alphanumerics. }
  67. WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  68. type
  69. TStringSearchOption = (soDown, soMatchCase, soWholeWord);
  70. TStringSearchOptions = set of TStringSearchOption;
  71. TStringSeachOption = TStringSearchOption;
  72. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  73. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar;inline; // ; Options: TStringSearchOptions = [soDown]
  74. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  75. Function PosEx(const SubStr, S: string): Integer;inline; // Offset: Cardinal = 1
  76. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  77. { ---------------------------------------------------------------------
  78. Soundex Functions.
  79. ---------------------------------------------------------------------}
  80. type
  81. TSoundexLength = 1..MaxInt;
  82. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  83. Function Soundex(const AText: string): string;inline; // ; ALength: TSoundexLength = 4
  84. type
  85. TSoundexIntLength = 1..8;
  86. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  87. Function SoundexInt(const AText: string): Integer;inline; //; ALength: TSoundexIntLength = 4
  88. Function DecodeSoundexInt(AValue: Integer): string;
  89. Function SoundexWord(const AText: string): Word;
  90. Function DecodeSoundexWord(AValue: Word): string;
  91. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;inline;
  92. Function SoundexSimilar(const AText, AOther: string): Boolean;inline; //; ALength: TSoundexLength = 4
  93. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;inline;
  94. Function SoundexCompare(const AText, AOther: string): Integer;inline; //; ALength: TSoundexLength = 4
  95. Function SoundexProc(const AText, AOther: string): Boolean;
  96. type
  97. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  98. Const
  99. AnsiResemblesProc: TCompareTextProc = @SoundexProc;
  100. { ---------------------------------------------------------------------
  101. Other functions, based on RxStrUtils.
  102. ---------------------------------------------------------------------}
  103. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  104. function DelSpace(const S: string): string;
  105. function DelChars(const S: string; Chr: Char): string;
  106. function DelSpace1(const S: string): string;
  107. function Tab2Space(const S: string; Numb: Byte): string;
  108. function NPos(const C: string; S: string; N: Integer): Integer;
  109. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  110. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  111. Function RPos(c:char;const S : AnsiString):Integer; overload;
  112. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  113. function AddChar(C: Char; const S: string; N: Integer): string;
  114. function AddCharR(C: Char; const S: string; N: Integer): string;
  115. function PadLeft(const S: string; N: Integer): string;inline;
  116. function PadRight(const S: string; N: Integer): string;inline;
  117. function PadCenter(const S: string; Len: Integer): string;
  118. function Copy2Symb(const S: string; Symb: Char): string;
  119. function Copy2SymbDel(var S: string; Symb: Char): string;
  120. function Copy2Space(const S: string): string;inline;
  121. function Copy2SpaceDel(var S: string): string;inline;
  122. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  123. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  124. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  125. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;inline;
  126. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  127. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  128. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  129. function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  130. function FindPart(const HelpWilds, InputStr: string): Integer;
  131. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  132. function XorString(const Key, Src: ShortString): ShortString;
  133. function XorEncode(const Key, Source: string): string;
  134. function XorDecode(const Key, Source: string): string;
  135. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  136. function Numb2USA(const S: string): string;
  137. function Hex2Dec(const S: string): Longint;
  138. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  139. function Numb2Dec(S: string; Base: Byte): Longint;
  140. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  141. function IntToRoman(Value: Longint): string;
  142. function RomanToInt(const S: string): Longint;
  143. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  144. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  145. const
  146. DigitChars = ['0'..'9'];
  147. Brackets = ['(',')','[',']','{','}'];
  148. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  149. StdSwitchChars = ['-','/'];
  150. function PosSet (const c:TSysCharSet;const s : ansistring ):Integer;
  151. function PosSet (const c:string;const s : ansistring ):Integer;
  152. function PosSetEx (const c:TSysCharSet;const s : ansistring;count:Integer ):Integer;
  153. function PosSetEx (const c:string;const s : ansistring;count:Integer ):Integer;
  154. implementation
  155. { ---------------------------------------------------------------------
  156. Auxiliary functions
  157. ---------------------------------------------------------------------}
  158. Procedure NotYetImplemented (FN : String);
  159. begin
  160. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  161. end;
  162. { ---------------------------------------------------------------------
  163. Case insensitive search/replace
  164. ---------------------------------------------------------------------}
  165. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  166. begin
  167. if Assigned(AnsiResemblesProc) then
  168. Result:=AnsiResemblesProc(AText,AOther)
  169. else
  170. Result:=False;
  171. end;
  172. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  173. begin
  174. AnsiContainsText:=AnsiPos(AnsiUppercase(ASubText),AnsiUppercase(AText))>0;
  175. end;
  176. Function AnsiStartsText(const ASubText, AText: string): Boolean;inline;
  177. begin
  178. Result:=AnsiCompareText(Copy(AText,1,Length(AsubText)),ASubText)=0;
  179. end;
  180. Function AnsiEndsText(const ASubText, AText: string): Boolean;inline;
  181. begin
  182. result:=AnsiCompareText(Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText)),asubtext)=0;
  183. end;
  184. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;inline;
  185. begin
  186. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll,rfIgnoreCase]);
  187. end;
  188. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;inline;
  189. begin
  190. Result:=(AnsiIndexText(AText,AValues)<>-1)
  191. end;
  192. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  193. var i : longint;
  194. begin
  195. result:=-1;
  196. if high(AValues)=-1 Then
  197. Exit;
  198. for i:=low(AValues) to High(Avalues) do
  199. if CompareText(avalues[i],atext)=0 Then
  200. exit(i); // make sure it is the first val.
  201. end;
  202. { ---------------------------------------------------------------------
  203. Case sensitive search/replace
  204. ---------------------------------------------------------------------}
  205. Function AnsiContainsStr(const AText, ASubText: string): Boolean;inline;
  206. begin
  207. Result := AnsiPos(ASubText,AText)>0;
  208. end;
  209. Function AnsiStartsStr(const ASubText, AText: string): Boolean;inline;
  210. begin
  211. Result := AnsiPos(ASubText,AText)=1;
  212. end;
  213. Function AnsiEndsStr(const ASubText, AText: string): Boolean;inline;
  214. begin
  215. Result := AnsiCompareStr(Copy(AText,length(AText)-length(ASubText)+1,length(ASubText)),ASubText)=0;
  216. end;
  217. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;inline;
  218. begin
  219. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  220. end;
  221. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;inline;
  222. begin
  223. Result:=AnsiIndexStr(AText,Avalues)<>-1;
  224. end;
  225. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  226. var
  227. i : longint;
  228. begin
  229. result:=-1;
  230. if high(AValues)=-1 Then
  231. Exit;
  232. for i:=low(AValues) to High(Avalues) do
  233. if (avalues[i]=AText) Then
  234. exit(i); // make sure it is the first val.
  235. end;
  236. { ---------------------------------------------------------------------
  237. Playthingies
  238. ---------------------------------------------------------------------}
  239. Function DupeString(const AText: string; ACount: Integer): string;
  240. var i,l : integer;
  241. begin
  242. result:='';
  243. if aCount>=0 then
  244. begin
  245. l:=length(atext);
  246. SetLength(result,aCount*l);
  247. for i:=0 to ACount-1 do
  248. move(atext[1],Result[l*i+1],l);
  249. end;
  250. end;
  251. Function ReverseString(const AText: string): string;
  252. var
  253. i,j:longint;
  254. begin
  255. setlength(result,length(atext));
  256. i:=1; j:=length(atext);
  257. while (i<=j) do
  258. begin
  259. result[i]:=atext[j-i+1];
  260. inc(i);
  261. end;
  262. end;
  263. Function AnsiReverseString(const AText: AnsiString): AnsiString;inline;
  264. begin
  265. Result:=ReverseString(AText);
  266. end;
  267. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  268. var i,j : SizeUInt;
  269. begin
  270. j:=length(ASubText);
  271. i:=length(AText);
  272. SetLength(Result,i+j-ALength);
  273. move (AText[1],result[1],AStart-1);
  274. move (ASubText[1],result[AStart],j);
  275. move (AText[AStart+ALength], Result[AStart+j],i+1-AStart-ALength);
  276. end;
  277. Function RandomFrom(const AValues: array of string): string; overload;
  278. begin
  279. if high(AValues)=-1 then exit('');
  280. result:=Avalues[random(High(AValues)+1)];
  281. end;
  282. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;inline;
  283. begin
  284. if avalue then
  285. result:=atrue
  286. else
  287. result:=afalse;
  288. end;
  289. Function IfThen(AValue: Boolean; const ATrue: string): string;inline; // ; AFalse: string = ''
  290. begin
  291. if avalue then
  292. result:=atrue
  293. else
  294. result:='';
  295. end;
  296. { ---------------------------------------------------------------------
  297. VB emulations.
  298. ---------------------------------------------------------------------}
  299. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  300. begin
  301. Result:=Copy(AText,1,ACount);
  302. end;
  303. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  304. var j,l:integer;
  305. begin
  306. l:=length(atext);
  307. j:=ACount;
  308. if j>l then j:=l;
  309. Result:=Copy(AText,l-j+1,j);
  310. end;
  311. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  312. begin
  313. if (ACount=0) or (AStart>length(atext)) then
  314. exit('');
  315. Result:=Copy(AText,AStart,ACount);
  316. end;
  317. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  318. begin
  319. Result:=LeftStr(AText,AByteCount);
  320. end;
  321. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  322. begin
  323. Result:=RightStr(Atext,AByteCount);
  324. end;
  325. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;inline;
  326. begin
  327. Result:=MidStr(AText,AByteStart,AByteCount);
  328. end;
  329. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  330. begin
  331. Result := copy(AText,1,ACount);
  332. end;
  333. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  334. begin
  335. Result := copy(AText,length(AText)-ACount+1,ACount);
  336. end;
  337. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  338. begin
  339. Result:=Copy(AText,AStart,ACount);
  340. end;
  341. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;inline;
  342. begin
  343. Result:=Copy(AText,1,ACount);
  344. end;
  345. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  346. var
  347. j,l:integer;
  348. begin
  349. l:=length(atext);
  350. j:=ACount;
  351. if j>l then j:=l;
  352. Result:=Copy(AText,l-j+1,j);
  353. end;
  354. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;inline;
  355. begin
  356. Result:=Copy(AText,AStart,ACount);
  357. end;
  358. { ---------------------------------------------------------------------
  359. Extended search and replace
  360. ---------------------------------------------------------------------}
  361. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  362. var
  363. Len,I,SLen: Integer;
  364. C: Char;
  365. Found : Boolean;
  366. Direction: Shortint;
  367. CharMap: array[Char] of Char;
  368. Function GotoNextWord(var P : PChar): Boolean;
  369. begin
  370. if (Direction=1) then
  371. begin
  372. // Skip characters
  373. While (Len>0) and not (P^ in WordDelimiters) do
  374. begin
  375. Inc(P);
  376. Dec(Len);
  377. end;
  378. // skip delimiters
  379. While (Len>0) and (P^ in WordDelimiters) do
  380. begin
  381. Inc(P);
  382. Dec(Len);
  383. end;
  384. Result:=Len>0;
  385. end
  386. else
  387. begin
  388. // Skip Delimiters
  389. While (Len>0) and (P^ in WordDelimiters) do
  390. begin
  391. Dec(P);
  392. Dec(Len);
  393. end;
  394. // skip characters
  395. While (Len>0) and not (P^ in WordDelimiters) do
  396. begin
  397. Dec(P);
  398. Dec(Len);
  399. end;
  400. Result:=Len>0;
  401. // We're on the first delimiter. Pos back on char.
  402. Inc(P);
  403. Inc(Len);
  404. end;
  405. end;
  406. begin
  407. Result:=nil;
  408. Slen:=Length(SearchString);
  409. if (BufLen<=0) or (Slen=0) then
  410. Exit;
  411. if soDown in Options then
  412. begin
  413. Direction:=1;
  414. Inc(SelStart,SelLength);
  415. Len:=BufLen-SelStart-SLen+1;
  416. if (Len<=0) then
  417. Exit;
  418. end
  419. else
  420. begin
  421. Direction:=-1;
  422. Dec(SelStart,Length(SearchString));
  423. Len:=SelStart+1;
  424. end;
  425. if (SelStart<0) or (SelStart>BufLen) then
  426. Exit;
  427. Result:=@Buf[SelStart];
  428. for C:=Low(Char) to High(Char) do
  429. if (soMatchCase in Options) then
  430. CharMap[C]:=C
  431. else
  432. CharMap[C]:=Upcase(C);
  433. if Not (soMatchCase in Options) then
  434. SearchString:=UpCase(SearchString);
  435. Found:=False;
  436. while (Result<>Nil) and (Not Found) do
  437. begin
  438. if ((soWholeWord in Options) and
  439. (Result<>@Buf[SelStart]) and
  440. not GotoNextWord(Result)) then
  441. Result:=Nil
  442. else
  443. begin
  444. // try to match whole searchstring
  445. I:=0;
  446. while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
  447. Inc(I);
  448. // Whole searchstring matched ?
  449. if (I=SLen) then
  450. Found:=(Len=0) or
  451. (not (soWholeWord in Options)) or
  452. (Result[SLen] in WordDelimiters);
  453. if not Found then
  454. begin
  455. Inc(Result,Direction);
  456. Dec(Len);
  457. If (Len=0) then
  458. Result:=Nil;
  459. end;
  460. end;
  461. end;
  462. end;
  463. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar;inline; // ; Options: TStringSearchOptions = [soDown]
  464. begin
  465. Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
  466. end;
  467. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  468. var i : pchar;
  469. begin
  470. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  471. i:=strpos(@s[offset],@substr[1]);
  472. if i=nil then
  473. PosEx:=0
  474. else
  475. PosEx:=succ(i-pchar(s));
  476. end;
  477. Function PosEx(const SubStr, S: string): Integer;inline; // Offset: Cardinal = 1
  478. begin
  479. posex:=posex(substr,s,1);
  480. end;
  481. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  482. var l : longint;
  483. begin
  484. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  485. l:=length(s);
  486. {$ifndef useindexbyte}
  487. while (SizeInt(offset)<=l) and (s[offset]<>c) do inc(offset);
  488. if SizeInt(offset)>l then
  489. posex:=0
  490. else
  491. posex:=offset;
  492. {$else}
  493. posex:=offset+indexbyte(s[offset],l-offset+1);
  494. if posex=(offset-1) then
  495. posex:=0;
  496. {$endif}
  497. end;
  498. { ---------------------------------------------------------------------
  499. Soundex Functions.
  500. ---------------------------------------------------------------------}
  501. Const
  502. SScore : array[1..255] of Char =
  503. ('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
  504. '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
  505. '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
  506. '0','0','0','0','0','0', // 91..95
  507. '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
  508. '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
  509. '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
  510. '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
  511. '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
  512. '0','0','0','0','0'); // 251..255
  513. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  514. Var
  515. S,PS : Char;
  516. I,L : integer;
  517. begin
  518. Result:='';
  519. PS:=#0;
  520. If Length(AText)>0 then
  521. begin
  522. Result:=Upcase(AText[1]);
  523. I:=2;
  524. L:=Length(AText);
  525. While (I<=L) and (Length(Result)<ALength) do
  526. begin
  527. S:=SScore[Ord(AText[i])];
  528. If Not (S in ['0','i',PS]) then
  529. Result:=Result+S;
  530. If (S<>'i') then
  531. PS:=S;
  532. Inc(I);
  533. end;
  534. end;
  535. L:=Length(Result);
  536. If (L<ALength) then
  537. Result:=Result+StringOfChar('0',Alength-L);
  538. end;
  539. Function Soundex(const AText: string): string;inline; // ; ALength: TSoundexLength = 4
  540. begin
  541. Result:=Soundex(AText,4);
  542. end;
  543. Const
  544. Ord0 = Ord('0');
  545. OrdA = Ord('A');
  546. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  547. var
  548. SE: string;
  549. I: Integer;
  550. begin
  551. Result:=-1;
  552. SE:=Soundex(AText,ALength);
  553. If Length(SE)>0 then
  554. begin
  555. Result:=Ord(SE[1])-OrdA;
  556. if ALength > 1 then
  557. begin
  558. Result:=Result*26+(Ord(SE[2])-Ord0);
  559. for I:=3 to ALength do
  560. Result:=(Ord(SE[I])-Ord0)+Result*7;
  561. end;
  562. Result:=ALength+Result*9;
  563. end;
  564. end;
  565. Function SoundexInt(const AText: string): Integer;inline; //; ALength: TSoundexIntLength = 4
  566. begin
  567. Result:=SoundexInt(AText,4);
  568. end;
  569. Function DecodeSoundexInt(AValue: Integer): string;
  570. var
  571. I, Len: Integer;
  572. begin
  573. Result := '';
  574. Len := AValue mod 9;
  575. AValue := AValue div 9;
  576. for I:=Len downto 3 do
  577. begin
  578. Result:=Chr(Ord0+(AValue mod 7))+Result;
  579. AValue:=AValue div 7;
  580. end;
  581. if Len>2 then
  582. Result:=IntToStr(AValue mod 26)+Result;
  583. AValue:=AValue div 26;
  584. Result:=Chr(OrdA+AValue)+Result;
  585. end;
  586. Function SoundexWord(const AText: string): Word;
  587. Var
  588. S : String;
  589. begin
  590. S:=SoundEx(Atext,4);
  591. Result:=Ord(S[1])-OrdA;
  592. Result:=Result*26+StrToInt(S[2]);
  593. Result:=Result*7+StrToInt(S[3]);
  594. Result:=Result*7+StrToInt(S[4]);
  595. end;
  596. Function DecodeSoundexWord(AValue: Word): string;
  597. begin
  598. Result := Chr(Ord0+ (AValue mod 7));
  599. AValue := AValue div 7;
  600. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  601. AValue := AValue div 7;
  602. Result := IntToStr(AValue mod 26) + Result;
  603. AValue := AValue div 26;
  604. Result := Chr(OrdA+AValue) + Result;
  605. end;
  606. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;inline;
  607. begin
  608. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  609. end;
  610. Function SoundexSimilar(const AText, AOther: string): Boolean;inline; //; ALength: TSoundexLength = 4
  611. begin
  612. Result:=SoundexSimilar(AText,AOther,4);
  613. end;
  614. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;inline;
  615. begin
  616. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  617. end;
  618. Function SoundexCompare(const AText, AOther: string): Integer;inline; //; ALength: TSoundexLength = 4
  619. begin
  620. Result:=SoundexCompare(AText,AOther,4);
  621. end;
  622. Function SoundexProc(const AText, AOther: string): Boolean;
  623. begin
  624. Result:=SoundexSimilar(AText,AOther);
  625. end;
  626. { ---------------------------------------------------------------------
  627. RxStrUtils-like functions.
  628. ---------------------------------------------------------------------}
  629. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  630. var
  631. i,l: Integer;
  632. begin
  633. l:=Length(S);
  634. i:=1;
  635. Result:=True;
  636. while Result and (i<=l) do
  637. begin
  638. Result:=Not (S[i] in EmptyChars);
  639. Inc(i);
  640. end;
  641. end;
  642. function DelSpace(const S: String): string;
  643. begin
  644. Result:=DelChars(S,' ');
  645. end;
  646. function DelChars(const S: string; Chr: Char): string;
  647. var
  648. I,J: Integer;
  649. begin
  650. Result:=S;
  651. I:=Length(Result);
  652. While I>0 do
  653. begin
  654. if Result[I]=Chr then
  655. begin
  656. J:=I-1;
  657. While (J>0) and (Result[J]=Chr) do
  658. Dec(j);
  659. Delete(Result,J+1,I-J);
  660. I:=J+1;
  661. end;
  662. dec(I);
  663. end;
  664. end;
  665. function DelSpace1(const S: string): string;
  666. var
  667. i: Integer;
  668. begin
  669. Result:=S;
  670. for i:=Length(Result) downto 2 do
  671. if (Result[i]=' ') and (Result[I-1]=' ') then
  672. Delete(Result,I,1);
  673. end;
  674. function Tab2Space(const S: string; Numb: Byte): string;
  675. var
  676. I: Integer;
  677. begin
  678. I:=1;
  679. Result:=S;
  680. while I <= Length(Result) do
  681. if Result[I]<>Chr(9) then
  682. inc(I)
  683. else
  684. begin
  685. Result[I]:=' ';
  686. If (Numb>1) then
  687. Insert(StringOfChar('0',Numb-1),Result,I);
  688. Inc(I,Numb);
  689. end;
  690. end;
  691. function NPos(const C: string; S: string; N: Integer): Integer;
  692. var
  693. i,p,k: Integer;
  694. begin
  695. Result:=0;
  696. if N<1 then
  697. Exit;
  698. k:=0;
  699. i:=1;
  700. Repeat
  701. p:=pos(C,S);
  702. Inc(k,p);
  703. if p>0 then
  704. delete(S,1,p);
  705. Inc(i);
  706. Until (i>n) or (p=0);
  707. If (P>0) then
  708. Result:=K;
  709. end;
  710. function AddChar(C: Char; const S: string; N: Integer): string;
  711. Var
  712. l : Integer;
  713. begin
  714. Result:=S;
  715. l:=Length(Result);
  716. if l<N then
  717. Result:=StringOfChar(C,N-l)+Result;
  718. end;
  719. function AddCharR(C: Char; const S: string; N: Integer): string;
  720. Var
  721. l : Integer;
  722. begin
  723. Result:=S;
  724. l:=Length(Result);
  725. if l<N then
  726. Result:=Result+StringOfChar(C,N-l);
  727. end;
  728. function PadRight(const S: string; N: Integer): string;inline;
  729. begin
  730. Result:=AddCharR(' ',S,N);
  731. end;
  732. function PadLeft(const S: string; N: Integer): string;inline;
  733. begin
  734. Result:=AddChar(' ',S,N);
  735. end;
  736. function Copy2Symb(const S: string; Symb: Char): string;
  737. var
  738. p: Integer;
  739. begin
  740. p:=Pos(Symb,S);
  741. if p=0 then
  742. p:=Length(S)+1;
  743. Result:=Copy(S,1,p-1);
  744. end;
  745. function Copy2SymbDel(var S: string; Symb: Char): string;
  746. var
  747. p: Integer;
  748. begin
  749. p:=Pos(Symb,S);
  750. if p=0 then
  751. begin
  752. result:=s;
  753. s:='';
  754. end
  755. else
  756. begin
  757. Result:=Copy(S,1,p-1);
  758. delete(s,1,p);
  759. end;
  760. end;
  761. function Copy2Space(const S: string): string;inline;
  762. begin
  763. Result:=Copy2Symb(S,' ');
  764. end;
  765. function Copy2SpaceDel(var S: string): string;inline;
  766. begin
  767. Result:=Copy2SymbDel(S,' ');
  768. end;
  769. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  770. var
  771. // l : Integer;
  772. P,PE : PChar;
  773. begin
  774. Result:=AnsiLowerCase(S);
  775. P:=PChar(Result);
  776. PE:=P+Length(Result);
  777. while (P<PE) do
  778. begin
  779. while (P<PE) and (P^ in WordDelims) do
  780. inc(P);
  781. if (P<PE) then
  782. P^:=UpCase(P^);
  783. while (P<PE) and not (P^ in WordDelims) do
  784. inc(P);
  785. end;
  786. end;
  787. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  788. var
  789. P,PE : PChar;
  790. begin
  791. Result:=0;
  792. P:=Pchar(S);
  793. PE:=P+Length(S);
  794. while (P<PE) do
  795. begin
  796. while (P<PE) and (P^ in WordDelims) do
  797. Inc(P);
  798. if (P<PE) then
  799. inc(Result);
  800. while (P<PE) and not (P^ in WordDelims) do
  801. inc(P);
  802. end;
  803. end;
  804. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  805. var
  806. PS,P,PE : PChar;
  807. Count: Integer;
  808. begin
  809. Result:=0;
  810. Count:=0;
  811. PS:=PChar(S);
  812. PE:=PS+Length(S);
  813. P:=PS;
  814. while (P<PE) and (Count<>N) do
  815. begin
  816. while (P<PE) and (P^ in WordDelims) do
  817. inc(P);
  818. if (P<PE) then
  819. inc(Count);
  820. if (Count<>N) then
  821. while (P<PE) and not (P^ in WordDelims) do
  822. inc(P)
  823. else
  824. Result:=(P-PS)+1;
  825. end;
  826. end;
  827. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;inline;
  828. var
  829. i: Integer;
  830. begin
  831. Result:=ExtractWordPos(N,S,WordDelims,i);
  832. end;
  833. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  834. var
  835. i,j,l: Integer;
  836. begin
  837. j:=0;
  838. i:=WordPosition(N, S, WordDelims);
  839. Pos:=i;
  840. if (i<>0) then
  841. begin
  842. j:=i;
  843. l:=Length(S);
  844. while (j<=L) and not (S[j] in WordDelims) do
  845. inc(j);
  846. end;
  847. SetLength(Result,j-i);
  848. If ((j-i)>0) then
  849. Move(S[i],Result[1],j-i);
  850. end;
  851. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  852. var
  853. w,i,l,len: Integer;
  854. begin
  855. w:=0;
  856. i:=1;
  857. l:=0;
  858. len:=Length(S);
  859. SetLength(Result, 0);
  860. while (i<=len) and (w<>N) do
  861. begin
  862. if s[i] in Delims then
  863. inc(w)
  864. else
  865. begin
  866. if (N-1)=w then
  867. begin
  868. inc(l);
  869. SetLength(Result,l);
  870. Result[L]:=S[i];
  871. end;
  872. end;
  873. inc(i);
  874. end;
  875. end;
  876. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  877. var
  878. i,l: Integer;
  879. begin
  880. i:=Pos;
  881. l:=Length(S);
  882. while (i<=l) and not (S[i] in Delims) do
  883. inc(i);
  884. Result:=Copy(S,Pos,i-Pos);
  885. if (i<=l) and (S[i] in Delims) then
  886. inc(i);
  887. Pos:=i;
  888. end;
  889. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  890. var
  891. i,Count : Integer;
  892. begin
  893. Result:=False;
  894. Count:=WordCount(S, WordDelims);
  895. I:=1;
  896. While (Not Result) and (I<=Count) do
  897. begin
  898. Result:=ExtractWord(i,S,WordDelims)=W;
  899. Inc(i);
  900. end;
  901. end;
  902. function Numb2USA(const S: string): string;
  903. var
  904. i, NA: Integer;
  905. begin
  906. i:=Length(S);
  907. Result:=S;
  908. NA:=0;
  909. while (i > 0) do begin
  910. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  911. begin
  912. insert(',', Result, i);
  913. inc(NA);
  914. end;
  915. Dec(i);
  916. end;
  917. end;
  918. function PadCenter(const S: string; Len: Integer): string;
  919. begin
  920. if Length(S)<Len then
  921. begin
  922. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  923. Result:=Result+StringOfChar(' ',Len-Length(Result));
  924. end
  925. else
  926. Result:=S;
  927. end;
  928. function Hex2Dec(const S: string): Longint;
  929. var
  930. HexStr: string;
  931. begin
  932. if Pos('$',S)=0 then
  933. HexStr:='$'+ S
  934. else
  935. HexStr:=S;
  936. Result:=StrToInt(HexStr);
  937. end;
  938. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  939. var
  940. C: Integer;
  941. Number: Longint;
  942. begin
  943. if N=0 then
  944. Result:='0'
  945. else
  946. begin
  947. Number:=N;
  948. Result:='';
  949. while Number>0 do
  950. begin
  951. C:=Number mod Base;
  952. if C>9 then
  953. C:=C+55
  954. else
  955. C:=C+48;
  956. Result:=Chr(C)+Result;
  957. Number:=Number div Base;
  958. end;
  959. end;
  960. if (Result<>'') then
  961. Result:=AddChar('0',Result,Len);
  962. end;
  963. function Numb2Dec(S: string; Base: Byte): Longint;
  964. var
  965. i, P: Longint;
  966. begin
  967. i:=Length(S);
  968. Result:=0;
  969. S:=UpperCase(S);
  970. P:=1;
  971. while (i>=1) do
  972. begin
  973. if (S[i]>'@') then
  974. Result:=Result+(Ord(S[i])-55)*P
  975. else
  976. Result:=Result+(Ord(S[i])-48)*P;
  977. Dec(i);
  978. P:=P*Base;
  979. end;
  980. end;
  981. function RomanToint(const S: string): Longint;
  982. const
  983. RomanChars = ['C','D','i','L','M','V','X'];
  984. RomanValues : array['C'..'X'] of Word
  985. = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
  986. var
  987. index, Next: Char;
  988. i,l: Integer;
  989. Negative: Boolean;
  990. begin
  991. Result:=0;
  992. i:=0;
  993. Negative:=(Length(S)>0) and (S[1]='-');
  994. if Negative then
  995. inc(i);
  996. l:=Length(S);
  997. while (i<l) do
  998. begin
  999. inc(i);
  1000. index:=UpCase(S[i]);
  1001. if index in RomanChars then
  1002. begin
  1003. if Succ(i)<=l then
  1004. Next:=UpCase(S[i+1])
  1005. else
  1006. Next:=#0;
  1007. if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
  1008. begin
  1009. inc(Result, RomanValues[Next]);
  1010. Dec(Result, RomanValues[index]);
  1011. inc(i);
  1012. end
  1013. else
  1014. inc(Result, RomanValues[index]);
  1015. end
  1016. else
  1017. begin
  1018. Result:=0;
  1019. Exit;
  1020. end;
  1021. end;
  1022. if Negative then
  1023. Result:=-Result;
  1024. end;
  1025. function intToRoman(Value: Longint): string;
  1026. const
  1027. Arabics : Array[1..13] of Integer
  1028. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  1029. Romans : Array[1..13] of String
  1030. = ('I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M');
  1031. var
  1032. i: Integer;
  1033. begin
  1034. Result:='';
  1035. for i:=13 downto 1 do
  1036. while (Value >= Arabics[i]) do
  1037. begin
  1038. Value:=Value-Arabics[i];
  1039. Result:=Result+Romans[i];
  1040. end;
  1041. end;
  1042. function intToBin(Value: Longint; Digits, Spaces: Integer): string;
  1043. begin
  1044. Result:='';
  1045. if (Digits>32) then
  1046. Digits:=32;
  1047. while (Digits>0) do
  1048. begin
  1049. if (Digits mod Spaces)=0 then
  1050. Result:=Result+' ';
  1051. Dec(Digits);
  1052. Result:=Result+intToStr((Value shr Digits) and 1);
  1053. end;
  1054. end;
  1055. function FindPart(const HelpWilds, inputStr: string): Integer;
  1056. var
  1057. i, J: Integer;
  1058. Diff: Integer;
  1059. begin
  1060. Result:=0;
  1061. i:=Pos('?',HelpWilds);
  1062. if (i=0) then
  1063. Result:=Pos(HelpWilds, inputStr)
  1064. else
  1065. begin
  1066. Diff:=Length(inputStr) - Length(HelpWilds);
  1067. for i:=0 to Diff do
  1068. begin
  1069. for J:=1 to Length(HelpWilds) do
  1070. if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
  1071. begin
  1072. if (J=Length(HelpWilds)) then
  1073. begin
  1074. Result:=i+1;
  1075. Exit;
  1076. end;
  1077. end
  1078. else
  1079. Break;
  1080. end;
  1081. end;
  1082. end;
  1083. function isWild(inputStr, Wilds: string; ignoreCase: Boolean): Boolean;
  1084. function SearchNext(var Wilds: string): Integer;
  1085. begin
  1086. Result:=Pos('*', Wilds);
  1087. if Result>0 then
  1088. Wilds:=Copy(Wilds,1,Result - 1);
  1089. end;
  1090. var
  1091. CWild, CinputWord: Integer; { counter for positions }
  1092. i, LenHelpWilds: Integer;
  1093. MaxinputWord, MaxWilds: Integer; { Length of inputStr and Wilds }
  1094. HelpWilds: string;
  1095. begin
  1096. if Wilds = inputStr then begin
  1097. Result:=True;
  1098. Exit;
  1099. end;
  1100. repeat { delete '**', because '**' = '*' }
  1101. i:=Pos('**', Wilds);
  1102. if i > 0 then
  1103. Wilds:=Copy(Wilds, 1, i - 1) + '*' + Copy(Wilds, i + 2, Maxint);
  1104. until i = 0;
  1105. if Wilds = '*' then begin { for fast end, if Wilds only '*' }
  1106. Result:=True;
  1107. Exit;
  1108. end;
  1109. MaxinputWord:=Length(inputStr);
  1110. MaxWilds:=Length(Wilds);
  1111. if ignoreCase then begin { upcase all letters }
  1112. inputStr:=AnsiUpperCase(inputStr);
  1113. Wilds:=AnsiUpperCase(Wilds);
  1114. end;
  1115. if (MaxWilds = 0) or (MaxinputWord = 0) then begin
  1116. Result:=False;
  1117. Exit;
  1118. end;
  1119. CinputWord:=1;
  1120. CWild:=1;
  1121. Result:=True;
  1122. repeat
  1123. if inputStr[CinputWord] = Wilds[CWild] then begin { equal letters }
  1124. { goto next letter }
  1125. inc(CWild);
  1126. inc(CinputWord);
  1127. Continue;
  1128. end;
  1129. if Wilds[CWild] = '?' then begin { equal to '?' }
  1130. { goto next letter }
  1131. inc(CWild);
  1132. inc(CinputWord);
  1133. Continue;
  1134. end;
  1135. if Wilds[CWild] = '*' then begin { handling of '*' }
  1136. HelpWilds:=Copy(Wilds, CWild + 1, MaxWilds);
  1137. i:=SearchNext(HelpWilds);
  1138. LenHelpWilds:=Length(HelpWilds);
  1139. if i = 0 then begin
  1140. { no '*' in the rest, compare the ends }
  1141. if HelpWilds = '' then Exit; { '*' is the last letter }
  1142. { check the rest for equal Length and no '?' }
  1143. for i:=0 to LenHelpWilds - 1 do begin
  1144. if (HelpWilds[LenHelpWilds - i] <> inputStr[MaxinputWord - i]) and
  1145. (HelpWilds[LenHelpWilds - i]<> '?') then
  1146. begin
  1147. Result:=False;
  1148. Exit;
  1149. end;
  1150. end;
  1151. Exit;
  1152. end;
  1153. { handle all to the next '*' }
  1154. inc(CWild, 1 + LenHelpWilds);
  1155. i:=FindPart(HelpWilds, Copy(inputStr, CinputWord, Maxint));
  1156. if i= 0 then begin
  1157. Result:=False;
  1158. Exit;
  1159. end;
  1160. CinputWord:=i + LenHelpWilds;
  1161. Continue;
  1162. end;
  1163. Result:=False;
  1164. Exit;
  1165. until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
  1166. { no completed evaluation }
  1167. if CinputWord <= MaxinputWord then Result:=False;
  1168. if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then Result:=False;
  1169. end;
  1170. function XorString(const Key, Src: ShortString): ShortString;
  1171. var
  1172. i: Integer;
  1173. begin
  1174. Result:=Src;
  1175. if Length(Key) > 0 then
  1176. for i:=1 to Length(Src) do
  1177. Result[i]:=Chr(Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
  1178. end;
  1179. function XorEncode(const Key, Source: string): string;
  1180. var
  1181. i: Integer;
  1182. C: Byte;
  1183. begin
  1184. Result:='';
  1185. for i:=1 to Length(Source) do
  1186. begin
  1187. if Length(Key) > 0 then
  1188. C:=Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Byte(Source[i])
  1189. else
  1190. C:=Byte(Source[i]);
  1191. Result:=Result+AnsiLowerCase(intToHex(C, 2));
  1192. end;
  1193. end;
  1194. function XorDecode(const Key, Source: string): string;
  1195. var
  1196. i: Integer;
  1197. C: Char;
  1198. begin
  1199. Result:='';
  1200. for i:=0 to Length(Source) div 2 - 1 do
  1201. begin
  1202. C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
  1203. if Length(Key) > 0 then
  1204. C:=Chr(Byte(Key[1 + (i mod Length(Key))]) xor Byte(C));
  1205. Result:=Result + C;
  1206. end;
  1207. end;
  1208. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  1209. var
  1210. i: Integer;
  1211. S: string;
  1212. begin
  1213. i:=1;
  1214. Result:='';
  1215. while (Result='') and (i<=ParamCount) do
  1216. begin
  1217. S:=ParamStr(i);
  1218. if (SwitchChars=[]) or ((S[1] in SwitchChars) and (Length(S) > 1)) and
  1219. (AnsiCompareText(Copy(S,2,Length(S)-1),Switch)=0) then
  1220. begin
  1221. inc(i);
  1222. if i<=ParamCount then
  1223. Result:=ParamStr(i);
  1224. end;
  1225. inc(i);
  1226. end;
  1227. end;
  1228. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  1229. var I : SizeUInt;
  1230. p,p2: pChar;
  1231. Begin
  1232. I:=Length(S);
  1233. If (I<>0) and (offs<=i) Then
  1234. begin
  1235. p:=@s[offs];
  1236. p2:=@s[1];
  1237. while (p2<=p) and (p^<>c) do dec(p);
  1238. RPosEx:=(p-p2)+1;
  1239. end
  1240. else
  1241. RPosEX:=0;
  1242. End;
  1243. Function RPos(c:char;const S : AnsiString):Integer; overload;
  1244. var I : Integer;
  1245. p,p2: pChar;
  1246. Begin
  1247. I:=Length(S);
  1248. If I<>0 Then
  1249. begin
  1250. p:=@s[i];
  1251. p2:=@s[1];
  1252. while (p2<=p) and (p^<>c) do dec(p);
  1253. i:=p-p2+1;
  1254. end;
  1255. RPos:=i;
  1256. End;
  1257. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  1258. var
  1259. MaxLen,llen : Integer;
  1260. c : char;
  1261. pc,pc2 : pchar;
  1262. begin
  1263. rPos:=0;
  1264. llen:=Length(SubStr);
  1265. maxlen:=length(source);
  1266. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1267. begin
  1268. // i:=maxlen;
  1269. pc:=@source[maxlen];
  1270. pc2:=@source[llen-1];
  1271. c:=substr[llen];
  1272. while pc>=pc2 do
  1273. begin
  1274. if (c=pc^) and
  1275. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1276. begin
  1277. rPos:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1278. exit;
  1279. end;
  1280. dec(pc);
  1281. end;
  1282. end;
  1283. end;
  1284. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  1285. var
  1286. MaxLen,llen : Integer;
  1287. c : char;
  1288. pc,pc2 : pchar;
  1289. begin
  1290. rPosex:=0;
  1291. llen:=Length(SubStr);
  1292. maxlen:=length(source);
  1293. if SizeInt(offs)<maxlen then maxlen:=offs;
  1294. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1295. begin
  1296. // i:=maxlen;
  1297. pc:=@source[maxlen];
  1298. pc2:=@source[llen-1];
  1299. c:=substr[llen];
  1300. while pc>=pc2 do
  1301. begin
  1302. if (c=pc^) and
  1303. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1304. begin
  1305. rPosex:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1306. exit;
  1307. end;
  1308. dec(pc);
  1309. end;
  1310. end;
  1311. end;
  1312. // def from delphi.about.com:
  1313. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  1314. Const
  1315. HexDigits='0123456789ABCDEF';
  1316. var
  1317. i : longint;
  1318. begin
  1319. for i:=0 to binbufsize-1 do
  1320. begin
  1321. HexValue[0]:=hexdigits[1+((ord(binvalue^) shr 4))];
  1322. HexValue[1]:=hexdigits[1+((ord(binvalue^) and 15))];
  1323. inc(hexvalue,2);
  1324. inc(binvalue);
  1325. end;
  1326. end;
  1327. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  1328. // more complex, have to accept more than bintohex
  1329. // A..F    1000001
  1330. // a..f    1100001
  1331. // 0..9     110000
  1332. var i,j,h,l : integer;
  1333. begin
  1334. i:=binbufsize;
  1335. while (i>0) do
  1336. begin
  1337. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1338. h:=((ord(hexvalue^)+9) and 15)
  1339. else if hexvalue^ IN ['0'..'9'] then
  1340. h:=((ord(hexvalue^)) and 15)
  1341. else
  1342. break;
  1343. inc(hexvalue);
  1344. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1345. l:=(ord(hexvalue^)+9) and 15
  1346. else if hexvalue^ IN ['0'..'9'] then
  1347. l:=(ord(hexvalue^)) and 15
  1348. else
  1349. break;
  1350. j := l + (h shl 4);
  1351. inc(hexvalue);
  1352. binvalue^:=chr(j);
  1353. inc(binvalue);
  1354. dec(i);
  1355. end;
  1356. result:=binbufsize-i;
  1357. end;
  1358. function possetex (const c:TSysCharSet;const s : ansistring;count:Integer ):Integer;
  1359. var i,j:Integer;
  1360. begin
  1361. if pchar(s)=nil then
  1362. j:=0
  1363. else
  1364. begin
  1365. i:=length(s);
  1366. j:=count;
  1367. if j>i then
  1368. begin
  1369. result:=0;
  1370. exit;
  1371. end;
  1372. while (j<=i) and (not (s[j] in c)) do inc(j);
  1373. if (j>i) then
  1374. j:=0; // not found.
  1375. end;
  1376. result:=j;
  1377. end;
  1378. function posset (const c:TSysCharSet;const s : ansistring ):Integer;
  1379. begin
  1380. result:=possetex(c,s,1);
  1381. end;
  1382. function possetex (const c:string;const s : ansistring;count:Integer ):Integer;
  1383. var cset : TSysCharSet;
  1384. i : integer;
  1385. begin
  1386. cset:=[];
  1387. if length(c)>0 then
  1388. for i:=1 to length(c) do
  1389. include(cset,c[i]);
  1390. result:=possetex(cset,s,count);
  1391. end;
  1392. function posset (const c:string;const s : ansistring ):Integer;
  1393. var cset : TSysCharSet;
  1394. i : integer;
  1395. begin
  1396. cset:=[];
  1397. if length(c)>0 then
  1398. for i:=1 to length(c) do
  1399. include(cset,c[i]);
  1400. result:=possetex(cset,s,1);
  1401. end;
  1402. end.