strutils.pp 45 KB

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