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