strutils.pp 49 KB

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