strutils.pp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715
  1. {$mode objfpc}
  2. {$h+}
  3. {
  4. $Id$
  5. This file is part of the Free Pascal run time library.
  6. Copyright (c) 1999-2000 by the Free Pascal development team
  7. Delphi/Kylix compatibility unit: String handling routines.
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. unit strutils;
  15. interface
  16. uses
  17. SysUtils{, Types};
  18. { ---------------------------------------------------------------------
  19. Case sensitive 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;
  24. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  25. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  26. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  27. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  28. { ---------------------------------------------------------------------
  29. Case insensitive search/replace
  30. ---------------------------------------------------------------------}
  31. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  32. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  33. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  34. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  35. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  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;
  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;
  46. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  47. { ---------------------------------------------------------------------
  48. VB emulations.
  49. ---------------------------------------------------------------------}
  50. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  51. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  52. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  53. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  54. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  55. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  56. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  57. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  58. {$ifndef ver1_0}
  59. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  60. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  61. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  62. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  63. {$endif}
  64. { ---------------------------------------------------------------------
  65. Extended search and replace
  66. ---------------------------------------------------------------------}
  67. const
  68. { Default word delimiters are any character except the core alphanumerics. }
  69. WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  70. type
  71. TStringSearchOption = (soDown, soMatchCase, soWholeWord);
  72. TStringSearchOptions = set of TStringSearchOption;
  73. TStringSeachOption = TStringSearchOption;
  74. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  75. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  76. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  77. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  78. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  79. { ---------------------------------------------------------------------
  80. Soundex Functions.
  81. ---------------------------------------------------------------------}
  82. type
  83. TSoundexLength = 1..MaxInt;
  84. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  85. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  86. type
  87. TSoundexIntLength = 1..8;
  88. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  89. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  90. Function DecodeSoundexInt(AValue: Integer): string;
  91. Function SoundexWord(const AText: string): Word;
  92. Function DecodeSoundexWord(AValue: Word): string;
  93. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  94. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  95. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  96. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  97. Function SoundexProc(const AText, AOther: string): Boolean;
  98. type
  99. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  100. Const
  101. AnsiResemblesProc: TCompareTextProc = @SoundexProc;
  102. { ---------------------------------------------------------------------
  103. Other functions, based on RxStrUtils.
  104. ---------------------------------------------------------------------}
  105. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  106. function DelSpace(const S: string): string;
  107. function DelChars(const S: string; Chr: Char): string;
  108. function DelSpace1(const S: string): string;
  109. function Tab2Space(const S: string; Numb: Byte): string;
  110. function NPos(const C: string; S: string; N: Integer): Integer;
  111. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  112. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  113. Function RPos(c:char;const S : AnsiString):Integer; overload;
  114. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  115. function AddChar(C: Char; const S: string; N: Integer): string;
  116. function AddCharR(C: Char; const S: string; N: Integer): string;
  117. function PadLeft(const S: string; N: Integer): string;
  118. function PadRight(const S: string; N: Integer): string;
  119. function PadCenter(const S: string; Len: Integer): string;
  120. function Copy2Symb(const S: string; Symb: Char): string;
  121. function Copy2SymbDel(var S: string; Symb: Char): string;
  122. function Copy2Space(const S: string): string;
  123. function Copy2SpaceDel(var S: string): string;
  124. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  125. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  126. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  127. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  128. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  129. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  130. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  131. function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  132. function FindPart(const HelpWilds, InputStr: string): Integer;
  133. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  134. function XorString(const Key, Src: ShortString): ShortString;
  135. function XorEncode(const Key, Source: string): string;
  136. function XorDecode(const Key, Source: string): string;
  137. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  138. function Numb2USA(const S: string): string;
  139. function Hex2Dec(const S: string): Longint;
  140. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  141. function Numb2Dec(S: string; Base: Byte): Longint;
  142. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  143. function IntToRoman(Value: Longint): string;
  144. function RomanToInt(const S: string): Longint;
  145. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  146. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  147. const
  148. DigitChars = ['0'..'9'];
  149. Brackets = ['(',')','[',']','{','}'];
  150. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  151. StdSwitchChars = ['-','/'];
  152. implementation
  153. { ---------------------------------------------------------------------
  154. Auxiliary functions
  155. ---------------------------------------------------------------------}
  156. Procedure NotYetImplemented (FN : String);
  157. begin
  158. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  159. end;
  160. { ---------------------------------------------------------------------
  161. Case sensitive search/replace
  162. ---------------------------------------------------------------------}
  163. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  164. begin
  165. if Assigned(AnsiResemblesProc) then
  166. Result:=AnsiResemblesProc(AText,AOther)
  167. else
  168. Result:=False;
  169. end;
  170. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  171. begin
  172. AnsiContainsText:=Pos(ASubText,AText)<>0;
  173. end;
  174. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  175. begin
  176. Result:=Copy(AText,1,Length(AsubText))=ASubText;
  177. end;
  178. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  179. begin
  180. result:=Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText))=asubtext;
  181. end;
  182. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  183. var iFrom, iTo: longint;
  184. begin
  185. iTo:=Pos(AFromText,AText);
  186. if iTo=0 then
  187. result:=AText
  188. else
  189. begin
  190. result:='';
  191. iFrom:=1;
  192. while (ito<>0) do
  193. begin
  194. result:=Result+Copy(AText,IFrom,Ito-IFrom+1)+AToText;
  195. ifrom:=ITo+Length(afromtext);
  196. ito:=Posex(Afromtext,atext,ifrom);
  197. end;
  198. if ifrom<=length(atext) then
  199. result:=result+copy(AText,ifrom, length(atext));
  200. end;
  201. end;
  202. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  203. begin
  204. Result:=(AnsiIndexText(AText,AValues)<>-1)
  205. end;
  206. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  207. var i : longint;
  208. begin
  209. result:=-1;
  210. if high(AValues)=-1 Then
  211. Exit;
  212. for i:=low(AValues) to High(Avalues) do
  213. if CompareText(avalues[i],atext)=0 Then
  214. exit(i); // make sure it is the first val.
  215. end;
  216. { ---------------------------------------------------------------------
  217. Case insensitive search/replace
  218. ---------------------------------------------------------------------}
  219. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  220. begin
  221. Result := Pos(ASubText,AText)<>0;
  222. end;
  223. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  224. begin
  225. Result := Pos(ASubText,AText)=1;
  226. end;
  227. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  228. begin
  229. Result := Pos(ASubText,AText)=(length(AText)-length(ASubText)+1);
  230. end;
  231. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  232. begin
  233. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  234. end;
  235. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  236. begin
  237. Result:=AnsiIndexStr(AText,Avalues)<>-1;
  238. end;
  239. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  240. var i : longint;
  241. begin
  242. result:=-1;
  243. if high(AValues)=-1 Then
  244. Exit;
  245. for i:=low(AValues) to High(Avalues) do
  246. if (avalues[i]=AText) Then
  247. exit(i); // make sure it is the first val.
  248. end;
  249. { ---------------------------------------------------------------------
  250. Playthingies
  251. ---------------------------------------------------------------------}
  252. Function DupeString(const AText: string; ACount: Integer): string;
  253. var i,l : integer;
  254. begin
  255. result:='';
  256. if aCount>=0 then
  257. begin
  258. l:=length(atext);
  259. SetLength(result,aCount*l);
  260. for i:=0 to ACount-1 do
  261. move(atext[1],Result[l*i+1],l);
  262. end;
  263. end;
  264. Function ReverseString(const AText: string): string;
  265. var c: char;
  266. i,j:longint;
  267. begin
  268. setlength(result,length(atext));
  269. i:=1; j:=length(atext);
  270. while (i<=j) do
  271. begin
  272. result[i]:=atext[j-i+1];
  273. inc(i);
  274. end;
  275. end;
  276. Function AnsiReverseString(const AText: AnsiString): AnsiString;
  277. begin
  278. Result:=ReverseString(AText);
  279. end;
  280. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  281. var i,j : longint;
  282. begin
  283. j:=length(ASubText);
  284. i:=length(AText);
  285. SetLength(Result,i-ALength+j);
  286. move (AText[1],result[1],AStart-1);
  287. move (ASubText[1],result[AStart],j);
  288. move (AText[AStart+ALength], Result[AStart+j],i-AStart-ALength+1);
  289. end;
  290. Function RandomFrom(const AValues: array of string): string; overload;
  291. begin
  292. if high(AValues)=-1 then exit('');
  293. result:=Avalues[random(High(AValues)+1)];
  294. end;
  295. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
  296. begin
  297. if avalue then
  298. result:=atrue
  299. else
  300. result:=afalse;
  301. end;
  302. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  303. begin
  304. if avalue then
  305. result:=atrue
  306. else
  307. result:='';
  308. end;
  309. { ---------------------------------------------------------------------
  310. VB emulations.
  311. ---------------------------------------------------------------------}
  312. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  313. begin
  314. Result:=Copy(AText,1,ACount);
  315. end;
  316. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  317. var j,l:integer;
  318. begin
  319. l:=length(atext);
  320. j:=ACount;
  321. if j>l then j:=l;
  322. Result:=Copy(AText,l-j+1,j);
  323. end;
  324. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  325. begin
  326. if (ACount=0) or (AStart>length(atext)) then
  327. exit('');
  328. Result:=Copy(AText,AStart,ACount);
  329. end;
  330. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  331. begin
  332. Result:=LeftStr(AText,AByteCount);
  333. end;
  334. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  335. begin
  336. Result:=RightStr(Atext,AByteCount);
  337. end;
  338. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  339. begin
  340. Result:=MidStr(AText,AByteStart,AByteCount);
  341. end;
  342. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  343. begin
  344. Result := copy(AText,1,ACount);
  345. end;
  346. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  347. begin
  348. Result := copy(AText,length(AText)-ACount+1,ACount);
  349. end;
  350. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  351. begin
  352. Result:=Copy(AText,AStart,ACount);
  353. end;
  354. {$ifndef ver1_0}
  355. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  356. begin
  357. Result:=Copy(AText,1,ACount);
  358. end;
  359. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  360. var
  361. j,l:integer;
  362. begin
  363. l:=length(atext);
  364. j:=ACount;
  365. if j>l then j:=l;
  366. Result:=Copy(AText,l-j+1,j);
  367. end;
  368. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  369. begin
  370. Result:=Copy(AText,AStart,ACount);
  371. end;
  372. {$endif}
  373. { ---------------------------------------------------------------------
  374. Extended search and replace
  375. ---------------------------------------------------------------------}
  376. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  377. var
  378. Len,I,SLen: Integer;
  379. C: Char;
  380. Found : Boolean;
  381. Direction: Shortint;
  382. CharMap: array[Char] of Char;
  383. Function GotoNextWord(var P : PChar): Boolean;
  384. begin
  385. if (Direction=1) then
  386. begin
  387. // Skip characters
  388. While (Len>0) and not (P^ in WordDelimiters) do
  389. begin
  390. Inc(P);
  391. Dec(Len);
  392. end;
  393. // skip delimiters
  394. While (Len>0) and (P^ in WordDelimiters) do
  395. begin
  396. Inc(P);
  397. Dec(Len);
  398. end;
  399. Result:=Len>0;
  400. end
  401. else
  402. begin
  403. // Skip Delimiters
  404. While (Len>0) and (P^ in WordDelimiters) do
  405. begin
  406. Dec(P);
  407. Dec(Len);
  408. end;
  409. // skip characters
  410. While (Len>0) and not (P^ in WordDelimiters) do
  411. begin
  412. Dec(P);
  413. Dec(Len);
  414. end;
  415. Result:=Len>0;
  416. // We're on the first delimiter. Pos back on char.
  417. Inc(P);
  418. Inc(Len);
  419. end;
  420. end;
  421. begin
  422. Result:=nil;
  423. Slen:=Length(SearchString);
  424. if (BufLen<=0) or (Slen=0) then
  425. Exit;
  426. if soDown in Options then
  427. begin
  428. Direction:=1;
  429. Inc(SelStart,SelLength);
  430. Len:=BufLen-SelStart-SLen+1;
  431. if (Len<=0) then
  432. Exit;
  433. end
  434. else
  435. begin
  436. Direction:=-1;
  437. Dec(SelStart,Length(SearchString));
  438. Len:=SelStart+1;
  439. end;
  440. if (SelStart<0) or (SelStart>BufLen) then
  441. Exit;
  442. Result:=@Buf[SelStart];
  443. for C:=Low(Char) to High(Char) do
  444. if (soMatchCase in Options) then
  445. CharMap[C]:=C
  446. else
  447. CharMap[C]:=Upcase(C);
  448. if Not (soMatchCase in Options) then
  449. SearchString:=UpCase(SearchString);
  450. Found:=False;
  451. while (Result<>Nil) and (Not Found) do
  452. begin
  453. if ((soWholeWord in Options) and
  454. (Result<>@Buf[SelStart]) and
  455. not GotoNextWord(Result)) then
  456. Result:=Nil
  457. else
  458. begin
  459. // try to match whole searchstring
  460. I:=0;
  461. while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
  462. Inc(I);
  463. // Whole searchstring matched ?
  464. if (I=SLen) then
  465. Found:=(Len=0) or
  466. (not (soWholeWord in Options)) or
  467. (Result[SLen] in WordDelimiters);
  468. if not Found then
  469. begin
  470. Inc(Result,Direction);
  471. Dec(Len);
  472. If (Len=0) then
  473. Result:=Nil;
  474. end;
  475. end;
  476. end;
  477. end;
  478. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  479. begin
  480. Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
  481. end;
  482. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  483. var i : pchar;
  484. begin
  485. if (offset<1) or (offset>length(s)) then exit(0);
  486. i:=strpos(@s[offset],@substr[1]);
  487. if i=nil then
  488. PosEx:=0
  489. else
  490. PosEx:=succ(i-pchar(s));
  491. end;
  492. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  493. begin
  494. posex:=posex(substr,s,1);
  495. end;
  496. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  497. var l : longint;
  498. begin
  499. if (offset<1) or (offset>length(s)) then exit(0);
  500. l:=length(s);
  501. {$ifndef useindexbyte}
  502. while (offset<=l) and (s[offset]<>c) do inc(offset);
  503. if offset>l then
  504. posex:=0
  505. else
  506. posex:=offset;
  507. {$else}
  508. posex:=offset+indexbyte(s[offset],l-offset+1);
  509. if posex=(offset-1) then
  510. posex:=0;
  511. {$endif}
  512. end;
  513. { ---------------------------------------------------------------------
  514. Soundex Functions.
  515. ---------------------------------------------------------------------}
  516. Const
  517. SScore : array[1..255] of Char =
  518. ('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
  519. '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
  520. '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
  521. '0','0','0','0','0','0', // 91..95
  522. '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
  523. '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
  524. '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
  525. '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
  526. '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
  527. '0','0','0','0','0'); // 251..255
  528. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  529. Var
  530. S,PS : Char;
  531. I,L : integer;
  532. begin
  533. Result:='';
  534. PS:=#0;
  535. If Length(AText)>0 then
  536. begin
  537. Result:=Upcase(AText[1]);
  538. I:=2;
  539. L:=Length(AText);
  540. While (I<=L) and (Length(Result)<ALength) do
  541. begin
  542. S:=SScore[Ord(AText[i])];
  543. If Not (S in ['0','i',PS]) then
  544. Result:=Result+S;
  545. If (S<>'i') then
  546. PS:=S;
  547. Inc(I);
  548. end;
  549. end;
  550. L:=Length(Result);
  551. If (L<ALength) then
  552. Result:=Result+StringOfChar('0',Alength-L);
  553. end;
  554. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  555. begin
  556. Result:=Soundex(AText,4);
  557. end;
  558. Const
  559. Ord0 = Ord('0');
  560. OrdA = Ord('A');
  561. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  562. var
  563. SE: string;
  564. I: Integer;
  565. begin
  566. Result:=-1;
  567. SE:=Soundex(AText,ALength);
  568. If Length(SE)>0 then
  569. begin
  570. Result:=Ord(SE[1])-OrdA;
  571. if ALength > 1 then
  572. begin
  573. Result:=Result*26+(Ord(SE[2])-Ord0);
  574. for I:=3 to ALength do
  575. Result:=(Ord(SE[I])-Ord0)+Result*7;
  576. end;
  577. Result:=ALength+Result*9;
  578. end;
  579. end;
  580. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  581. begin
  582. Result:=SoundexInt(AText,4);
  583. end;
  584. Function DecodeSoundexInt(AValue: Integer): string;
  585. var
  586. I, Len: Integer;
  587. begin
  588. Result := '';
  589. Len := AValue mod 9;
  590. AValue := AValue div 9;
  591. for I:=Len downto 3 do
  592. begin
  593. Result:=Chr(Ord0+(AValue mod 7))+Result;
  594. AValue:=AValue div 7;
  595. end;
  596. if Len>2 then
  597. Result:=IntToStr(AValue mod 26)+Result;
  598. AValue:=AValue div 26;
  599. Result:=Chr(OrdA+AValue)+Result;
  600. end;
  601. Function SoundexWord(const AText: string): Word;
  602. Var
  603. S : String;
  604. begin
  605. S:=SoundEx(Atext,4);
  606. Result:=Ord(S[1])-OrdA;
  607. Result:=Result*26+StrToInt(S[2]);
  608. Result:=Result*7+StrToInt(S[3]);
  609. Result:=Result*7+StrToInt(S[4]);
  610. end;
  611. Function DecodeSoundexWord(AValue: Word): string;
  612. begin
  613. Result := Chr(Ord0+ (AValue mod 7));
  614. AValue := AValue div 7;
  615. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  616. AValue := AValue div 7;
  617. Result := IntToStr(AValue mod 26) + Result;
  618. AValue := AValue div 26;
  619. Result := Chr(OrdA+AValue) + Result;
  620. end;
  621. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  622. begin
  623. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  624. end;
  625. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  626. begin
  627. Result:=SoundexSimilar(AText,AOther,4);
  628. end;
  629. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  630. begin
  631. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  632. end;
  633. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  634. begin
  635. Result:=SoundexCompare(AText,AOther,4);
  636. end;
  637. Function SoundexProc(const AText, AOther: string): Boolean;
  638. begin
  639. Result:=SoundexSimilar(AText,AOther);
  640. end;
  641. { ---------------------------------------------------------------------
  642. RxStrUtils-like functions.
  643. ---------------------------------------------------------------------}
  644. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  645. var
  646. i,l: Integer;
  647. begin
  648. l:=Length(S);
  649. i:=1;
  650. Result:=True;
  651. while Result and (i<=l) do
  652. begin
  653. Result:=Not (S[i] in EmptyChars);
  654. Inc(i);
  655. end;
  656. end;
  657. function DelSpace(const S: String): string;
  658. begin
  659. Result:=DelChars(S,' ');
  660. end;
  661. function DelChars(const S: string; Chr: Char): string;
  662. var
  663. I,J: Integer;
  664. begin
  665. Result:=S;
  666. I:=Length(Result);
  667. While I>0 do
  668. begin
  669. if Result[I]=Chr then
  670. begin
  671. J:=I-1;
  672. While (J>0) and (Result[J]=Chr) do
  673. Dec(j);
  674. Delete(Result,J+1,I-J);
  675. I:=J+1;
  676. end;
  677. dec(I);
  678. end;
  679. end;
  680. function DelSpace1(const S: string): string;
  681. var
  682. i: Integer;
  683. begin
  684. Result:=S;
  685. for i:=Length(Result) downto 2 do
  686. if (Result[i]=' ') and (Result[I-1]=' ') then
  687. Delete(Result,I,1);
  688. end;
  689. function Tab2Space(const S: string; Numb: Byte): string;
  690. var
  691. I: Integer;
  692. begin
  693. I:=1;
  694. Result:=S;
  695. while I <= Length(Result) do
  696. if Result[I]<>Chr(9) then
  697. inc(I)
  698. else
  699. begin
  700. Result[I]:=' ';
  701. If (Numb>1) then
  702. Insert(StringOfChar('0',Numb-1),Result,I);
  703. Inc(I,Numb);
  704. end;
  705. end;
  706. function NPos(const C: string; S: string; N: Integer): Integer;
  707. var
  708. i,p,k: Integer;
  709. begin
  710. Result:=0;
  711. if N<1 then
  712. Exit;
  713. k:=0;
  714. i:=1;
  715. Repeat
  716. p:=pos(C,S);
  717. Inc(k,p);
  718. if p>0 then
  719. delete(S,1,p);
  720. Inc(i);
  721. Until (i>n) or (p=0);
  722. If (P>0) then
  723. Result:=K;
  724. end;
  725. function AddChar(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:=StringOfChar(C,N-l)+Result;
  733. end;
  734. function AddCharR(C: Char; const S: string; N: Integer): string;
  735. Var
  736. l : Integer;
  737. begin
  738. Result:=S;
  739. l:=Length(Result);
  740. if l<N then
  741. Result:=Result+StringOfChar(C,N-l);
  742. end;
  743. function PadRight(const S: string; N: Integer): string;
  744. begin
  745. Result:=AddCharR(' ',S,N);
  746. end;
  747. function PadLeft(const S: string; N: Integer): string;
  748. begin
  749. Result:=AddChar(' ',S,N);
  750. end;
  751. function Copy2Symb(const S: string; Symb: Char): string;
  752. var
  753. p: Integer;
  754. begin
  755. p:=Pos(Symb,S);
  756. if p=0 then
  757. p:=Length(S)+1;
  758. Result:=Copy(S,1,p-1);
  759. end;
  760. function Copy2SymbDel(var S: string; Symb: Char): string;
  761. begin
  762. Result:=Copy2Symb(S,Symb);
  763. S:=TrimRight(Copy(S,Length(Result)+1,Length(S)));
  764. end;
  765. function Copy2Space(const S: string): string;
  766. begin
  767. Result:=Copy2Symb(S,' ');
  768. end;
  769. function Copy2SpaceDel(var S: string): string;
  770. begin
  771. Result:=Copy2SymbDel(S,' ');
  772. end;
  773. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  774. var
  775. // l : Integer;
  776. P,PE : PChar;
  777. begin
  778. Result:=AnsiLowerCase(S);
  779. P:=PChar(Result);
  780. PE:=P+Length(Result);
  781. while (P<PE) do
  782. begin
  783. while (P<PE) and (P^ in WordDelims) do
  784. inc(P);
  785. if (P<PE) then
  786. P^:=UpCase(P^);
  787. while (P<PE) and not (P^ in WordDelims) do
  788. inc(P);
  789. end;
  790. end;
  791. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  792. var
  793. P,PE : PChar;
  794. begin
  795. Result:=0;
  796. P:=Pchar(S);
  797. PE:=P+Length(S);
  798. while (P<PE) do
  799. begin
  800. while (P<PE) and (P^ in WordDelims) do
  801. Inc(P);
  802. if (P<PE) then
  803. inc(Result);
  804. while (P<PE) and not (P^ in WordDelims) do
  805. inc(P);
  806. end;
  807. end;
  808. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  809. var
  810. PS,P,PE : PChar;
  811. Count: Integer;
  812. begin
  813. Result:=0;
  814. Count:=0;
  815. PS:=PChar(S);
  816. PE:=PS+Length(S);
  817. P:=PS;
  818. while (P<PE) and (Count<>N) do
  819. begin
  820. while (P<PE) and (P^ in WordDelims) do
  821. inc(P);
  822. if (P<PE) then
  823. inc(Count);
  824. if (Count<>N) then
  825. while (P<PE) and not (P^ in WordDelims) do
  826. inc(P)
  827. else
  828. Result:=(P-PS)+1;
  829. end;
  830. end;
  831. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  832. var
  833. i: Integer;
  834. begin
  835. Result:=ExtractWordPos(N,S,WordDelims,i);
  836. end;
  837. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  838. var
  839. i,j,l: Integer;
  840. begin
  841. j:=0;
  842. i:=WordPosition(N, S, WordDelims);
  843. Pos:=i;
  844. if (i<>0) then
  845. begin
  846. j:=i;
  847. l:=Length(S);
  848. while (j<=L) and not (S[j] in WordDelims) do
  849. inc(j);
  850. end;
  851. SetLength(Result,j-i);
  852. If ((j-i)>0) then
  853. Move(S[i],Result[1],j-i);
  854. end;
  855. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  856. var
  857. w,i,l,len: Integer;
  858. begin
  859. w:=0;
  860. i:=1;
  861. l:=0;
  862. len:=Length(S);
  863. SetLength(Result, 0);
  864. while (i<=len) and (w<>N) do
  865. begin
  866. if s[i] in Delims then
  867. inc(w)
  868. else
  869. begin
  870. if (N-1)=w then
  871. begin
  872. inc(l);
  873. SetLength(Result,l);
  874. Result[L]:=S[i];
  875. end;
  876. end;
  877. inc(i);
  878. end;
  879. end;
  880. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  881. var
  882. i,l: Integer;
  883. begin
  884. i:=Pos;
  885. l:=Length(S);
  886. while (i<=l) and not (S[i] in Delims) do
  887. inc(i);
  888. Result:=Copy(S,Pos,i-Pos);
  889. if (i<=l) and (S[i] in Delims) then
  890. inc(i);
  891. Pos:=i;
  892. end;
  893. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  894. var
  895. i,Count : Integer;
  896. begin
  897. Result:=False;
  898. Count:=WordCount(S, WordDelims);
  899. I:=1;
  900. While (Not Result) and (I<=Count) do
  901. Result:=ExtractWord(i,S,WordDelims)=W;
  902. end;
  903. function Numb2USA(const S: string): string;
  904. var
  905. i, NA: Integer;
  906. begin
  907. i:=Length(S);
  908. Result:=S;
  909. NA:=0;
  910. while (i > 0) do begin
  911. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  912. begin
  913. insert(',', Result, i);
  914. inc(NA);
  915. end;
  916. Dec(i);
  917. end;
  918. end;
  919. function PadCenter(const S: string; Len: Integer): string;
  920. begin
  921. if Length(S)<Len then
  922. begin
  923. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  924. Result:=Result+StringOfChar(' ',Len-Length(Result));
  925. end
  926. else
  927. Result:=S;
  928. end;
  929. function Hex2Dec(const S: string): Longint;
  930. var
  931. HexStr: string;
  932. begin
  933. if Pos('$',S)=0 then
  934. HexStr:='$'+ S
  935. else
  936. HexStr:=S;
  937. Result:=StrTointDef(HexStr,0);
  938. end;
  939. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  940. var
  941. C: Integer;
  942. Number: Longint;
  943. begin
  944. if N=0 then
  945. Result:='0'
  946. else
  947. begin
  948. Number:=N;
  949. Result:='';
  950. while Number>0 do
  951. begin
  952. C:=Number mod Base;
  953. if C>9 then
  954. C:=C+55
  955. else
  956. C:=C+48;
  957. Result:=Chr(C)+Result;
  958. Number:=Number div Base;
  959. end;
  960. end;
  961. if (Result<>'') then
  962. Result:=AddChar('0',Result,Len);
  963. end;
  964. function Numb2Dec(S: string; Base: Byte): Longint;
  965. var
  966. i, P: Longint;
  967. begin
  968. i:=Length(S);
  969. Result:=0;
  970. S:=UpperCase(S);
  971. P:=1;
  972. while (i>=1) do
  973. begin
  974. if (S[i]>'@') then
  975. Result:=Result+(Ord(S[i])-55)*P
  976. else
  977. Result:=Result+(Ord(S[i])-48)*P;
  978. Dec(i);
  979. P:=P*Base;
  980. end;
  981. end;
  982. function RomanToint(const S: string): Longint;
  983. const
  984. RomanChars = ['C','D','i','L','M','V','X'];
  985. RomanValues : array['C'..'X'] of Word
  986. = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
  987. var
  988. index, Next: Char;
  989. i,l: Integer;
  990. Negative: Boolean;
  991. begin
  992. Result:=0;
  993. i:=0;
  994. Negative:=(Length(S)>0) and (S[1]='-');
  995. if Negative then
  996. inc(i);
  997. l:=Length(S);
  998. while (i<l) do
  999. begin
  1000. inc(i);
  1001. index:=UpCase(S[i]);
  1002. if index in RomanChars then
  1003. begin
  1004. if Succ(i)<=l then
  1005. Next:=UpCase(S[i+1])
  1006. else
  1007. Next:=#0;
  1008. if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
  1009. begin
  1010. inc(Result, RomanValues[Next]);
  1011. Dec(Result, RomanValues[index]);
  1012. inc(i);
  1013. end
  1014. else
  1015. inc(Result, RomanValues[index]);
  1016. end
  1017. else
  1018. begin
  1019. Result:=0;
  1020. Exit;
  1021. end;
  1022. end;
  1023. if Negative then
  1024. Result:=-Result;
  1025. end;
  1026. function intToRoman(Value: Longint): string;
  1027. const
  1028. Arabics : Array[1..13] of Integer
  1029. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  1030. Romans : Array[1..13] of String
  1031. = ('i','iV','V','iX','X','XL','L','XC','C','CD','D','CM','M');
  1032. var
  1033. i: Integer;
  1034. begin
  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 : Integer;
  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 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 HexDigits='0123456789ABCDEF';
  1315. var i :integer;
  1316. begin
  1317. for i:=0 to binbufsize-1 do
  1318. begin
  1319. HexValue[0]:=hexdigits[(ord(binvalue^) and 15)];
  1320. HexValue[1]:=hexdigits[(ord(binvalue^) shr 4)];
  1321. inc(hexvalue,2);
  1322. inc(binvalue);
  1323. end;
  1324. end;
  1325. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  1326. // more complex, have to accept more than bintohex
  1327. // A..F 1000001
  1328. // a..f 1100001
  1329. // 0..9 110000
  1330. var i,j : integer;
  1331. begin
  1332. i:=binbufsize;
  1333. while (i>0) do
  1334. begin
  1335. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1336. j:=(ord(hexvalue^)+9) and 15
  1337. else
  1338. if hexvalue^ IN ['0'..'9'] then
  1339. j:=(ord(hexvalue^)) and 15
  1340. else
  1341. break;
  1342. inc(hexvalue);
  1343. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1344. j:=((ord(hexvalue^)+9) and 15)+ (j shl 4)
  1345. else
  1346. if hexvalue^ IN ['0'..'9'] then
  1347. j:=((ord(hexvalue^)) and 15) + (j shl 4)
  1348. else
  1349. break;
  1350. inc(hexvalue);
  1351. binvalue^:=chr(j);
  1352. inc(binvalue);
  1353. dec(i);
  1354. end;
  1355. result:=binbufsize-i;
  1356. end;
  1357. end.
  1358. {
  1359. $Log$
  1360. Revision 1.13 2005-02-03 21:38:17 marco
  1361. * committed bintohex and hextobin
  1362. Revision 1.12 2005/01/26 11:05:09 marco
  1363. * fix
  1364. Revision 1.11 2005/01/01 18:45:25 marco
  1365. * rpos and rposex, both two versions
  1366. Revision 1.10 2004/12/30 18:12:43 michael
  1367. + Fix for extractdelimited
  1368. Revision 1.9 2004/07/21 20:37:03 michael
  1369. + Implemented all functions
  1370. Revision 1.8 2004/07/13 18:42:39 michael
  1371. + Added some RxStrUtils functions for Rx compatibility
  1372. Revision 1.7 2004/07/01 15:42:18 peter
  1373. * fix 1.0.x compile
  1374. Revision 1.6 2004/06/29 19:37:17 marco
  1375. * updates from B. Tierens
  1376. Revision 1.5 2004/05/17 07:33:01 marco
  1377. * fixes from Luiz Am?rico
  1378. Revision 1.4 2004/03/19 12:54:22 marco
  1379. * more strutils small things
  1380. Revision 1.3 2004/03/18 16:55:47 marco
  1381. * more simple implementations done, based on copy() Largely untested
  1382. }