strutils.pp 46 KB

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