strutils.pp 48 KB

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