strutils.pp 43 KB

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