strutils.pp 43 KB

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