strutils.pp 45 KB

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