strutils.pp 47 KB

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