strutils.pas 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  1. {
  2. Delphi/Kylix compatibility unit: String handling routines.
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2018 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. {$inline on}
  13. unit strutils;
  14. interface
  15. uses
  16. SysUtils;
  17. { ---------------------------------------------------------------------
  18. Case insensitive search/replace
  19. ---------------------------------------------------------------------}
  20. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  21. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  22. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  23. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  24. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  25. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  26. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  27. Function StartsText(const ASubText, AText: string): Boolean;
  28. Function EndsText(const ASubText, AText: string): Boolean;
  29. function ResemblesText(const AText, AOther: string): Boolean;
  30. function ContainsText(const AText, ASubText: string): Boolean;
  31. function MatchText(const AText: string; const AValues: array of string): Boolean;
  32. function IndexText(const AText: string; const AValues: array of string): Integer;
  33. { ---------------------------------------------------------------------
  34. Case sensitive search/replace
  35. ---------------------------------------------------------------------}
  36. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  37. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  38. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  39. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  40. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  41. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  42. Function MatchStr(const AText: String; const AValues: array of String): Boolean;
  43. Function IndexStr(const AText: String; const AValues: array of String): Integer;
  44. function ContainsStr(const AText, ASubText: string): Boolean;
  45. Function StartsStr(const ASubText, AText: string): Boolean;
  46. Function EndsStr(const ASubText, AText: string): Boolean;
  47. { ---------------------------------------------------------------------
  48. Miscellaneous
  49. ---------------------------------------------------------------------}
  50. Function DupeString(const AText: string; ACount: Integer): string;
  51. Function ReverseString(const AText: string): string;
  52. Function AnsiReverseString(const AText: String): String;
  53. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  54. Function RandomFrom(const AValues: array of string): string; overload;
  55. Function IfThen(AValue: Boolean; const ATrue: string; const AFalse: string = ''): string; overload;
  56. function NaturalCompareText (const S1 , S2 : string ): Integer ;
  57. function NaturalCompareText(const Str1, Str2: string; const ADecSeparator, AThousandSeparator: String): Integer;
  58. { ---------------------------------------------------------------------
  59. VB emulations.
  60. ---------------------------------------------------------------------}
  61. Function LeftStr(const AText: String; const ACount: SizeInt): String;
  62. Function RightStr(const AText: String; const ACount: SizeInt): String;
  63. Function MidStr(const AText: String; const AStart, ACount: SizeInt): String;
  64. Function RightBStr(const AText: String; const AByteCount: SizeInt): String;
  65. Function MidBStr(const AText: String; const AByteStart, AByteCount: SizeInt): String;
  66. Function AnsiLeftStr(const AText: String; const ACount: SizeInt): String;
  67. Function AnsiRightStr(const AText: String; const ACount: SizeInt): String;
  68. Function AnsiMidStr(const AText: String; const AStart, ACount: SizeInt): String;
  69. Function LeftBStr(const AText: String; const AByteCount: SizeInt): String;
  70. { ---------------------------------------------------------------------
  71. Extended search and replace
  72. ---------------------------------------------------------------------}
  73. Var
  74. { Default word delimiters are any character except the core alphanumerics. }
  75. WordDelimiters: Array of Char;// = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  76. Const
  77. SErrAmountStrings = 'Amount of search and replace strings don''t match';
  78. SInvalidRomanNumeral = '%s is not a valid Roman numeral';
  79. type
  80. TStringSearchOption = (soDown, soMatchCase, soWholeWord);
  81. TStringSearchOptions = set of TStringSearchOption;
  82. TStringSeachOption = TStringSearchOption;
  83. Function PosEx(const SubStr, S: string; Offset: SizeUint): SizeInt;
  84. Function PosEx(const SubStr, S: string): SizeInt; // Offset: Cardinal = 1
  85. Function PosEx(c:char; const S: string; Offset: SizeUint): SizeInt;
  86. function StringsReplace(const S: string; OldPattern, NewPattern: array of string; Flags: TReplaceFlags): string;
  87. { ---------------------------------------------------------------------
  88. Delphi compat
  89. ---------------------------------------------------------------------}
  90. Function ReplaceStr(const AText, AFromText, AToText: string): string;
  91. Function ReplaceText(const AText, AFromText, AToText: string): string;
  92. { ---------------------------------------------------------------------
  93. Soundex Functions.
  94. ---------------------------------------------------------------------}
  95. type
  96. TSoundexLength = 1..MaxInt;
  97. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  98. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  99. type
  100. TSoundexIntLength = 1..8;
  101. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  102. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  103. Function DecodeSoundexInt(AValue: Integer): string;
  104. Function SoundexWord(const AText: string): Word;
  105. Function DecodeSoundexWord(AValue: Word): string;
  106. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  107. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  108. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  109. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  110. Function SoundexProc(const AText, AOther: string): Boolean;
  111. type
  112. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  113. Var
  114. AnsiResemblesProc: TCompareTextProc;
  115. ResemblesProc: TCompareTextProc;
  116. { ---------------------------------------------------------------------
  117. Other functions, based on RxStrUtils.
  118. ---------------------------------------------------------------------}
  119. type
  120. TRomanConversionStrictness = (rcsStrict, rcsRelaxed, rcsDontCare);
  121. function IsEmptyStr(const S: string; const EmptyChars: Array of char): Boolean;
  122. function DelSpace(const S: string): string;
  123. function DelChars(const S: string; Chr: Char): string;
  124. function DelSpace1(const S: string): string;
  125. function Tab2Space(const S: string; Numb: Byte): string;
  126. function NPos(const C: string; S: string; N: Integer): SizeInt;
  127. Function RPosEX(C:char;const S : String;offs:cardinal):SizeInt; overload;
  128. Function RPosex (Const Substr : String; Const Source : String;offs:cardinal) : SizeInt; overload;
  129. Function RPos(c:char;const S : String):SizeInt; overload;
  130. Function RPos (Const Substr : String; Const Source : String) : SizeInt; overload;
  131. function AddChar(C: Char; const S: string; N: Integer): string;
  132. function AddCharR(C: Char; const S: string; N: Integer): string;
  133. function PadLeft(const S: string; N: Integer): string;
  134. function PadRight(const S: string; N: Integer): string;
  135. function PadCenter(const S: string; Len: SizeInt): string;
  136. function Copy2Symb(const S: string; Symb: Char): string;
  137. function Copy2SymbDel(var S: string; Symb: Char): string;
  138. function Copy2Space(const S: string): string;
  139. function Copy2SpaceDel(var S: string): string;
  140. function AnsiProperCase(const S: string; const WordDelims: Array of char): string;
  141. function WordCount(const S: string; const WordDelims: Array of char): SizeInt;
  142. function WordPosition(const N: Integer; const S: string; const WordDelims: Array of char): SizeInt;
  143. function ExtractWord(N: Integer; const S: string; const WordDelims: Array of char): string;
  144. function ExtractWordPos(N: Integer; const S: string; const WordDelims: Array of char; out Pos: Integer): string;
  145. function ExtractDelimited(N: Integer; const S: string; const Delims: Array of char): string;
  146. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: Array of char): string;
  147. function IsWordPresent(const W, S: string; const WordDelims: Array of char): Boolean;
  148. function FindPart(const HelpWilds, InputStr: string): SizeInt;
  149. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  150. function XorString(const Key, Src: String): String;
  151. function XorEncode(const Key, Source: string): string;
  152. function XorDecode(const Key, Source: string): string;
  153. function GetCmdLineArg(const Switch: string; SwitchChars: Array of char): string;
  154. function Numb2USA(const S: string): string;
  155. function Hex2Dec(const S: string): Longint;
  156. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  157. function Numb2Dec(S: string; Base: Byte): Longint;
  158. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  159. function IntToBin(Value: Longint; Digits: Integer): string;
  160. function IntToBin(Value: NativeInt; Digits:integer): string;
  161. function IntToRoman(Value: Longint): string;
  162. function TryRomanToInt(S: String; out N: LongInt; Strictness: TRomanConversionStrictness = rcsRelaxed): Boolean;
  163. function RomanToInt(const S: string; Strictness: TRomanConversionStrictness = rcsRelaxed): Longint;
  164. function RomanToIntDef(Const S : String; const ADefault: Longint = 0; Strictness: TRomanConversionStrictness = rcsRelaxed): Longint;
  165. const
  166. DigitChars = ['0'..'9'];
  167. Brackets = ['(',')','[',']','{','}'];
  168. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  169. StdSwitchChars = ['-','/'];
  170. function PosSet (const c:Array of char;const s : String ):SizeInt;
  171. function PosSet (const c:string;const s : String ):SizeInt;
  172. function PosSetEx (const c:Array of char;const s : String;count:Integer ):SizeInt;
  173. function PosSetEx (const c:string;const s : String;count:Integer ):SizeInt;
  174. Procedure Removeleadingchars(VAR S : String; Const CSet:Array of char);
  175. Procedure RemoveTrailingChars(VAR S : String;Const CSet:Array of char);
  176. Procedure RemovePadChars(VAR S : String;Const CSet:Array of char);
  177. function TrimLeftSet(const S: String;const CSet:Array of char): String;
  178. Function TrimRightSet(const S: String;const CSet:Array of char): String;
  179. function TrimSet(const S: String;const CSet:Array of char): String;
  180. type
  181. SizeIntArray = array of SizeInt;
  182. implementation
  183. uses js;
  184. { ---------------------------------------------------------------------
  185. Possibly Exception raising functions
  186. ---------------------------------------------------------------------}
  187. function Hex2Dec(const S: string): Longint;
  188. var
  189. HexStr: string;
  190. begin
  191. if Pos('$',S)=0 then
  192. HexStr:='$'+ S
  193. else
  194. HexStr:=S;
  195. Result:=StrToInt(HexStr);
  196. end;
  197. {
  198. We turn off implicit exceptions, since these routines are tested, and it
  199. saves 20% codesize (and some speed) and don't throw exceptions, except maybe
  200. heap related. If they don't, that is consider a bug.
  201. In the future, be wary with routines that use strtoint, floating point
  202. and/or format() derivatives. And check every divisor for 0.
  203. }
  204. {$IMPLICITEXCEPTIONS OFF}
  205. { ---------------------------------------------------------------------
  206. Case insensitive search/replace
  207. ---------------------------------------------------------------------}
  208. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  209. begin
  210. if Assigned(AnsiResemblesProc) then
  211. Result:=AnsiResemblesProc(AText,AOther)
  212. else
  213. Result:=False;
  214. end;
  215. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  216. begin
  217. Result:=Pos(Uppercase(ASubText),Uppercase(AText))>0;
  218. end;
  219. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  220. begin
  221. if (Length(AText) >= Length(ASubText)) and (ASubText <> '') then
  222. Result := SameText(ASubText,Copy(AText,1,Length(ASubText)))
  223. else
  224. Result := False;
  225. end;
  226. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  227. begin
  228. if Length(AText) >= Length(ASubText) then
  229. Result := SameText(aSubText,RightStr(aText,Length(ASubText)))
  230. else
  231. Result := False;
  232. end;
  233. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  234. begin
  235. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll,rfIgnoreCase]);
  236. end;
  237. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  238. begin
  239. Result:=(AnsiIndexText(AText,AValues)<>-1)
  240. end;
  241. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  242. var
  243. i : Integer;
  244. begin
  245. Result:=-1;
  246. if (high(AValues)=-1) or (High(AValues)>MaxInt) Then
  247. Exit;
  248. for i:=low(AValues) to High(Avalues) do
  249. if CompareText(avalues[i],atext)=0 Then
  250. exit(i); // make sure it is the first val.
  251. end;
  252. { ---------------------------------------------------------------------
  253. Case sensitive search/replace
  254. ---------------------------------------------------------------------}
  255. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  256. begin
  257. Result := Pos(ASubText,AText)>0;
  258. end;
  259. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  260. begin
  261. if (Length(AText) >= Length(ASubText)) and (ASubText <> '') then
  262. Result := (ASubText=Copy(aText,1,Length(ASubtext)))
  263. else
  264. Result := False;
  265. end;
  266. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  267. begin
  268. if Length(AText) >= Length(ASubText) then
  269. Result := (ASubText=RightStr(aText,Length(ASubText)))
  270. else
  271. Result := False;
  272. end;
  273. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  274. begin
  275. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  276. end;
  277. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  278. begin
  279. Result:=AnsiIndexStr(AText,Avalues)<>-1;
  280. end;
  281. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  282. var
  283. i : longint;
  284. begin
  285. result:=-1;
  286. if (high(AValues)=-1) or (High(AValues)>MaxInt) Then
  287. Exit;
  288. for i:=low(AValues) to High(Avalues) do
  289. if (avalues[i]=AText) Then
  290. exit(i); // make sure it is the first val.
  291. end;
  292. Function MatchStr(const AText: String; const AValues: array of String): Boolean;
  293. begin
  294. Result := IndexStr(AText,AValues) <> -1;
  295. end;
  296. Function IndexStr(const AText: String; const AValues: array of String): Integer;
  297. var
  298. i: longint;
  299. begin
  300. Result := -1;
  301. if (high(AValues) = -1) or (High(AValues) > MaxInt) Then
  302. Exit;
  303. for i := low(AValues) to High(Avalues) do
  304. if (avalues[i] = AText) Then
  305. exit(i); // make sure it is the first val.
  306. end;
  307. { ---------------------------------------------------------------------
  308. Playthingies
  309. ---------------------------------------------------------------------}
  310. Function DupeString(const AText: string; ACount: Integer): string;
  311. var i : SizeInt;
  312. begin
  313. result:='';
  314. for i:=1 to ACount do
  315. Result:=Result+aText;
  316. end;
  317. Function ReverseString(const AText: string): string;
  318. var
  319. i,j : SizeInt;
  320. begin
  321. setlength(result,length(atext));
  322. i:=1; j:=length(atext);
  323. while (i<=j) do
  324. begin
  325. result[i]:=atext[j-i+1];
  326. inc(i);
  327. end;
  328. end;
  329. Function AnsiReverseString(const AText: String): String;
  330. begin
  331. Result:=ReverseString(AText);
  332. end;
  333. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  334. var i,j,k : SizeUInt;
  335. begin
  336. j:=length(ASubText);
  337. i:=length(AText);
  338. if AStart>i then
  339. aStart:=i+1;
  340. k:=i+1-AStart;
  341. if ALength> k then
  342. ALength:=k;
  343. SetLength(Result,i+j-ALength);
  344. Result:=Copy(AText,1,AStart-1)+Copy(ASubText,1,J)+Copy(AText,AStart+ALength,I+1-AStart-ALength);
  345. end;
  346. Function RandomFrom(const AValues: array of string): string; overload;
  347. begin
  348. if high(AValues)=-1 then exit('');
  349. result:=Avalues[random(High(AValues)+1)];
  350. end;
  351. Function IfThen(AValue: Boolean; const ATrue: string; const AFalse: string = ''): string; overload;
  352. begin
  353. if avalue then
  354. result:=atrue
  355. else
  356. result:=afalse;
  357. end;
  358. function NaturalCompareText(const Str1, Str2: string; const ADecSeparator, AThousandSeparator: String): Integer;
  359. {
  360. NaturalCompareBase compares strings in a collated order and
  361. so numbers are sorted too. It sorts like this:
  362. 01
  363. 001
  364. 0001
  365. and
  366. 0
  367. 00
  368. 000
  369. 000_A
  370. 000_B
  371. in a intuitive order.
  372. }
  373. var
  374. Num1, Num2: double;
  375. pStr1, pStr2: integer;
  376. Len1, Len2: SizeInt;
  377. TextLen1, TextLen2: SizeInt;
  378. TextStr1: string = '';
  379. TextStr2: string = '';
  380. i: SizeInt;
  381. j: SizeInt;
  382. function Sign(const AValue: sizeint): integer;
  383. begin
  384. If Avalue<0 then
  385. Result:=-1
  386. else If Avalue>0 then
  387. Result:=1
  388. else
  389. Result:=0;
  390. end;
  391. function IsNumber(ch: char): boolean; overload;
  392. begin
  393. Result := ch in ['0'..'9'];
  394. end;
  395. function GetInteger(aString : String; var pch: integer; var Len: sizeint): double;
  396. begin
  397. Result := 0;
  398. while (pch<=length(astring)) and IsNumber(AString[pch]) do
  399. begin
  400. Result := (Result * 10) + Ord(Astring[pch]) - Ord('0');
  401. Inc(Len);
  402. Inc(pch);
  403. end;
  404. end;
  405. procedure GetChars;
  406. begin
  407. TextLen1 := 0;
  408. while not (Str1[pStr1 + TextLen1] in ['0'..'9']) and ((pStr1 + TextLen1)<=Length(Str1)) do
  409. Inc(TextLen1);
  410. TextStr1:='';
  411. i := 1;
  412. j := 0;
  413. while i <= TextLen1 do
  414. begin
  415. TextStr1 := TextStr1+Str1[pStr1 + j];
  416. Inc(i);
  417. Inc(j);
  418. end;
  419. TextLen2 := 0;
  420. while not (Str2[pStr2 + TextLen2] in ['0'..'9']) and ((pStr2 + TextLen2)<=Length(Str2)) do
  421. Inc(TextLen2);
  422. i := 1;
  423. j := 0;
  424. while i <= TextLen2 do
  425. begin
  426. TextStr2 := TextStr2+Str2[pStr2 + j];
  427. Inc(i);
  428. Inc(j);
  429. end;
  430. end;
  431. begin
  432. if (Str1 <> '') and (Str2 <> '') then
  433. begin
  434. pStr1 := 1;
  435. pStr2 := 1;
  436. Result := 0;
  437. while (pStr1<=Length(Str1)) and (pStr2 <=Length(Str2)) do
  438. begin
  439. TextLen1 := 1;
  440. TextLen2 := 1;
  441. Len1 := 0;
  442. Len2 := 0;
  443. while (Str1[pStr1] = ' ') do
  444. begin
  445. Inc(pStr1);
  446. Inc(Len1);
  447. end;
  448. while (Str2[pstr2] = ' ') do
  449. begin
  450. Inc(pStr2);
  451. Inc(Len2);
  452. end;
  453. if IsNumber(Str1[pStr1]) and IsNumber(Str2[pStr2]) then
  454. begin
  455. Num1 := GetInteger(Str1,pStr1, Len1);
  456. Num2 := GetInteger(Str2, pStr2, Len2);
  457. if Num1 < Num2 then
  458. Result := -1
  459. else if Num1 > Num2 then
  460. Result := 1
  461. else
  462. begin
  463. Result := Sign(Len1 - Len2);
  464. end;
  465. Dec(pStr1);
  466. Dec(pStr2);
  467. end
  468. else
  469. begin
  470. GetChars;
  471. if TextStr1 <> TextStr2 then
  472. Result := CompareText(TextStr1, TextStr2)
  473. else
  474. Result := 0;
  475. end;
  476. if Result <> 0 then
  477. Break;
  478. Inc(pStr1, TextLen1);
  479. Inc(pStr2, TextLen2);
  480. end;
  481. end;
  482. Num1:=Length(Str1);
  483. Num2:=Length(Str2);
  484. if (Result = 0) and (Num1 <> Num2) then
  485. begin
  486. if Num1 < Num2 then
  487. Result := -1
  488. else
  489. Result := 1;
  490. end;
  491. if ADecSeparator='' then ;
  492. if aThousandSeparator='' then ;
  493. end;
  494. function NaturalCompareText (const S1 , S2 : string ): Integer ;
  495. begin
  496. Result := NaturalCompareText(S1, S2, DecimalSeparator,ThousandSeparator);
  497. end;
  498. { ---------------------------------------------------------------------
  499. VB emulations.
  500. ---------------------------------------------------------------------}
  501. Function LeftStr(const AText: String; const ACount: SizeInt): String;
  502. begin
  503. Result:=Copy(AText,1,ACount);
  504. end;
  505. Function RightStr(const AText: String; const ACount: SizeInt): String;
  506. var j,l:SizeInt;
  507. begin
  508. l:=length(atext);
  509. j:=ACount;
  510. if j>l then j:=l;
  511. Result:=Copy(AText,l-j+1,j);
  512. end;
  513. Function MidStr(const AText: String; const AStart, ACount: SizeInt): String;
  514. begin
  515. if (ACount=0) or (AStart>length(atext)) then
  516. exit('');
  517. Result:=Copy(AText,AStart,ACount);
  518. end;
  519. Function LeftBStr(const AText: String; const AByteCount: SizeInt): String;
  520. begin
  521. Result:=LeftStr(AText,AByteCount);
  522. end;
  523. Function RightBStr(const AText: String; const AByteCount: SizeInt): String;
  524. begin
  525. Result:=RightStr(Atext,AByteCount);
  526. end;
  527. Function MidBStr(const AText: String; const AByteStart, AByteCount: SizeInt): String;
  528. begin
  529. Result:=MidStr(AText,AByteStart,AByteCount);
  530. end;
  531. Function AnsiLeftStr(const AText: String; const ACount: SizeInt): String;
  532. begin
  533. Result := copy(AText,1,ACount);
  534. end;
  535. Function AnsiRightStr(const AText: String; const ACount: SizeInt): String;
  536. begin
  537. Result := copy(AText,length(AText)-ACount+1,ACount);
  538. end;
  539. Function AnsiMidStr(const AText: String; const AStart, ACount: SizeInt): String;
  540. begin
  541. Result:=Copy(AText,AStart,ACount);
  542. end;
  543. Function PosEx(const SubStr, S: string; Offset: SizeUint): SizeInt;
  544. begin
  545. result:=TJSString.New(S).IndexOf(SubStr,offset-1)+1;
  546. end;
  547. Function PosEx(c:char; const S: string; Offset: SizeUint): SizeInt;
  548. begin
  549. result:=TJSString.New(S).IndexOf(c,offset-1)+1;
  550. end;
  551. Function PosEx(const SubStr, S: string): SizeInt; // Offset: Cardinal = 1
  552. begin
  553. Result:=posex(substr,s,1);
  554. end;
  555. function StringsReplace(const S: string; OldPattern, NewPattern: array of string; Flags: TReplaceFlags): string;
  556. var pc,pcc,lastpc : integer;
  557. strcount : integer;
  558. ResStr,
  559. CompStr : string;
  560. Found : Boolean;
  561. sc : sizeint;
  562. begin
  563. sc := length(OldPattern);
  564. if sc <> length(NewPattern) then
  565. raise exception.Create(SErrAmountStrings);
  566. dec(sc);
  567. if rfIgnoreCase in Flags then
  568. begin
  569. CompStr:=UpperCase(S);
  570. for strcount := 0 to sc do
  571. OldPattern[strcount] := UpperCase(OldPattern[strcount]);
  572. end
  573. else
  574. CompStr := s;
  575. ResStr := '';
  576. pc := 1;
  577. pcc := 1;
  578. lastpc := pc+Length(S);
  579. while pc < lastpc do
  580. begin
  581. Found := False;
  582. for strcount := 0 to sc do
  583. begin
  584. if (Copy(compStr,pc,Length(OldPattern[strcount]))=OldPattern[strcount]) then
  585. begin
  586. ResStr := ResStr + NewPattern[strcount];
  587. pc := pc+Length(OldPattern[strcount]);
  588. pcc := pcc+Length(OldPattern[strcount]);
  589. Found := true;
  590. end
  591. end;
  592. if not found then
  593. begin
  594. ResStr := ResStr + S[pcc];
  595. inc(pc);
  596. inc(pcc);
  597. end
  598. else if not (rfReplaceAll in Flags) then
  599. begin
  600. ResStr := ResStr + copy(S,pcc,Length(S)-pcc+1);
  601. break;
  602. end;
  603. end;
  604. Result := ResStr;
  605. end;
  606. { ---------------------------------------------------------------------
  607. Delphi compat
  608. ---------------------------------------------------------------------}
  609. Function ReplaceStr(const AText, AFromText, AToText: string): string;
  610. begin
  611. result:=AnsiReplaceStr(AText, AFromText, AToText);
  612. end;
  613. Function ReplaceText(const AText, AFromText, AToText: string): string;
  614. begin
  615. result:=AnsiReplaceText(AText, AFromText, AToText);
  616. end;
  617. { ---------------------------------------------------------------------
  618. Soundex Functions.
  619. ---------------------------------------------------------------------}
  620. Var
  621. SScore : String =
  622. '00000000000000000000000000000000'+ // 1..32
  623. '00000000000000000000000000000000'+ // 33..64
  624. '0123012i02245501262301i2i2'+ // 65..90
  625. '000000'+ // 91..96
  626. '0123012i02245501262301i2i2'+ // 97..122
  627. '00000000000000000000000000000000'+ // 123..154
  628. '00000000000000000000000000000000'+ // 155..186
  629. '00000000000000000000000000000000'+ // 187..218
  630. '00000000000000000000000000000000'+ // 219..250
  631. '00000'; // 251..255
  632. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  633. Var
  634. S,PS : Char;
  635. I,L : SizeInt;
  636. begin
  637. Result:='';
  638. PS:=#0;
  639. If Length(AText)>0 then
  640. begin
  641. Result:=Upcase(AText[1]);
  642. I:=2;
  643. L:=Length(AText);
  644. While (I<=L) and (Length(Result)<ALength) do
  645. begin
  646. S:=SScore[Ord(AText[i])];
  647. If Not (S in ['0','i',PS]) then
  648. Result:=Result+S;
  649. If (S<>'i') then
  650. PS:=S;
  651. Inc(I);
  652. end;
  653. end;
  654. L:=Length(Result);
  655. If (L<ALength) then
  656. Result:=Result+StringOfChar('0',Alength-L);
  657. end;
  658. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  659. begin
  660. Result:=Soundex(AText,4);
  661. end;
  662. Const
  663. Ord0 = Ord('0');
  664. OrdA = Ord('A');
  665. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  666. var
  667. SE: string;
  668. I: SizeInt;
  669. begin
  670. Result:=-1;
  671. SE:=Soundex(AText,ALength);
  672. If Length(SE)>0 then
  673. begin
  674. Result:=Ord(SE[1])-OrdA;
  675. if ALength > 1 then
  676. begin
  677. Result:=Result*26+(Ord(SE[2])-Ord0);
  678. for I:=3 to ALength do
  679. Result:=(Ord(SE[I])-Ord0)+Result*7;
  680. end;
  681. Result:=ALength+Result*9;
  682. end;
  683. end;
  684. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  685. begin
  686. Result:=SoundexInt(AText,4);
  687. end;
  688. Function DecodeSoundexInt(AValue: Integer): string;
  689. var
  690. I, Len: Integer;
  691. begin
  692. Result := '';
  693. Len := AValue mod 9;
  694. AValue := AValue div 9;
  695. for I:=Len downto 3 do
  696. begin
  697. Result:=Chr(Ord0+(AValue mod 7))+Result;
  698. AValue:=AValue div 7;
  699. end;
  700. if Len>1 then
  701. begin
  702. Result:=Chr(Ord0+(AValue mod 26))+Result;
  703. AValue:=AValue div 26;
  704. end;
  705. Result:=Chr(OrdA+AValue)+Result;
  706. end;
  707. Function SoundexWord(const AText: string): Word;
  708. Var
  709. S : String;
  710. begin
  711. S:=SoundEx(Atext,4);
  712. Result:=Ord(S[1])-OrdA;
  713. Result:=Result*26+ord(S[2])-48;
  714. Result:=Result*7+ord(S[3])-48;
  715. Result:=Result*7+ord(S[4])-48;
  716. end;
  717. Function DecodeSoundexWord(AValue: Word): string;
  718. begin
  719. Result := Chr(Ord0+ (AValue mod 7));
  720. AValue := AValue div 7;
  721. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  722. AValue := AValue div 7;
  723. Result := IntToStr(AValue mod 26) + Result;
  724. AValue := AValue div 26;
  725. Result := Chr(OrdA+AValue) + Result;
  726. end;
  727. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  728. begin
  729. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  730. end;
  731. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  732. begin
  733. Result:=SoundexSimilar(AText,AOther,4);
  734. end;
  735. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  736. begin
  737. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  738. end;
  739. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  740. begin
  741. Result:=SoundexCompare(AText,AOther,4);
  742. end;
  743. Function SoundexProc(const AText, AOther: string): Boolean;
  744. begin
  745. Result:=SoundexSimilar(AText,AOther);
  746. end;
  747. { ---------------------------------------------------------------------
  748. RxStrUtils-like functions.
  749. ---------------------------------------------------------------------}
  750. function IsEmptyStr(const S: string; const EmptyChars: Array of char): Boolean;
  751. var
  752. i,l: SizeInt;
  753. begin
  754. l:=Length(S);
  755. i:=1;
  756. Result:=True;
  757. while Result and (i<=l) do
  758. begin
  759. Result:=CharInSet(S[i],EmptyChars);
  760. Inc(i);
  761. end;
  762. end;
  763. function DelSpace(const S: String): string;
  764. begin
  765. Result:=DelChars(S,' ');
  766. end;
  767. function DelChars(const S: string; Chr: Char): string;
  768. var
  769. I,J: SizeInt;
  770. begin
  771. Result:=S;
  772. I:=Length(Result);
  773. While I>0 do
  774. begin
  775. if Result[I]=Chr then
  776. begin
  777. J:=I-1;
  778. While (J>0) and (Result[J]=Chr) do
  779. Dec(j);
  780. Delete(Result,J+1,I-J);
  781. I:=J+1;
  782. end;
  783. dec(I);
  784. end;
  785. end;
  786. function DelSpace1(const S: string): string;
  787. var
  788. I : SizeInt;
  789. begin
  790. Result:=S;
  791. for i:=Length(Result) downto 2 do
  792. if (Result[i]=' ') and (Result[I-1]=' ') then
  793. Delete(Result,I,1);
  794. end;
  795. function Tab2Space(const S: string; Numb: Byte): string;
  796. var
  797. I: SizeInt;
  798. begin
  799. I:=1;
  800. Result:=S;
  801. while I <= Length(Result) do
  802. if Result[I]<>Chr(9) then
  803. inc(I)
  804. else
  805. begin
  806. Result[I]:=' ';
  807. If (Numb>1) then
  808. Insert(StringOfChar(' ',Numb-1),Result,I);
  809. Inc(I,Numb);
  810. end;
  811. end;
  812. function NPos(const C: string; S: string; N: Integer): SizeInt;
  813. var
  814. i,p,k: SizeInt;
  815. begin
  816. Result:=0;
  817. if N<1 then
  818. Exit;
  819. k:=0;
  820. i:=1;
  821. Repeat
  822. p:=pos(C,S);
  823. Inc(k,p);
  824. if p>0 then
  825. delete(S,1,p);
  826. Inc(i);
  827. Until (i>n) or (p=0);
  828. If (P>0) then
  829. Result:=K;
  830. end;
  831. function AddChar(C: Char; const S: string; N: Integer): string;
  832. Var
  833. l : SizeInt;
  834. begin
  835. Result:=S;
  836. l:=Length(Result);
  837. if l<N then
  838. Result:=StringOfChar(C,N-l)+Result;
  839. end;
  840. function AddCharR(C: Char; const S: string; N: Integer): string;
  841. Var
  842. l : SizeInt;
  843. begin
  844. Result:=S;
  845. l:=Length(Result);
  846. if l<N then
  847. Result:=Result+StringOfChar(C,N-l);
  848. end;
  849. function PadRight(const S: string; N: Integer): string;
  850. begin
  851. Result:=AddCharR(' ',S,N);
  852. end;
  853. function PadLeft(const S: string; N: Integer): string;
  854. begin
  855. Result:=AddChar(' ',S,N);
  856. end;
  857. function Copy2Symb(const S: string; Symb: Char): string;
  858. var
  859. p: SizeInt;
  860. begin
  861. p:=Pos(Symb,S);
  862. if p=0 then
  863. p:=Length(S)+1;
  864. Result:=Copy(S,1,p-1);
  865. end;
  866. function Copy2SymbDel(var S: string; Symb: Char): string;
  867. var
  868. p: SizeInt;
  869. begin
  870. p:=Pos(Symb,S);
  871. if p=0 then
  872. begin
  873. result:=s;
  874. s:='';
  875. end
  876. else
  877. begin
  878. Result:=Copy(S,1,p-1);
  879. delete(s,1,p);
  880. end;
  881. end;
  882. function Copy2Space(const S: string): string;
  883. begin
  884. Result:=Copy2Symb(S,' ');
  885. end;
  886. function Copy2SpaceDel(var S: string): string;
  887. begin
  888. Result:=Copy2SymbDel(S,' ');
  889. end;
  890. function AnsiProperCase(const S: string; const WordDelims: Array of char): string;
  891. var
  892. P,L : Integer;
  893. begin
  894. Result:=LowerCase(S);
  895. P:=1;
  896. L:=Length(Result);
  897. while (P<=L) do
  898. begin
  899. while (P<=L) and (CharInSet(Result[P],WordDelims)) do
  900. inc(P);
  901. if (P<=L) then
  902. Result[P]:=UpCase(Result[P]);
  903. while (P<=L) and not CharInSet(Result[P],WordDelims) do
  904. inc(P);
  905. end;
  906. end;
  907. function WordCount(const S: string; const WordDelims: Array of char): SizeInt;
  908. var
  909. P,L : Integer;
  910. begin
  911. Result:=0;
  912. P:=1;
  913. L:=Length(S);
  914. while (P<=L) do
  915. begin
  916. while (P<=L) and (CharInSet(S[P],WordDelims)) do
  917. Inc(P);
  918. if (P<=L) then
  919. inc(Result);
  920. while (P<=L) and not (CharInSet(S[P],WordDelims)) do
  921. inc(P);
  922. end;
  923. end;
  924. function WordPosition(const N: Integer; const S: string; const WordDelims: Array of char): SizeInt;
  925. var
  926. PS,P,PE,Count : Integer;
  927. begin
  928. Result:=0;
  929. Count:=0;
  930. PS:=1;
  931. PE:=Length(S);
  932. P:=PS;
  933. while (P<=PE) and (Count<>N) do
  934. begin
  935. while (P<=PE) and CharInSet(S[P],WordDelims) do
  936. inc(P);
  937. if (P<=PE) then
  938. inc(Count);
  939. if (Count<>N) then
  940. while (P<=PE) and not CharInSet(S[P],WordDelims) do
  941. inc(P)
  942. else
  943. Result:=(P-PS)+1;
  944. end;
  945. end;
  946. function ExtractWord(N: Integer; const S: string; const WordDelims: Array of char): string;
  947. var
  948. i: LongInt;
  949. begin
  950. Result:=ExtractWordPos(N,S,WordDelims,i);
  951. end;
  952. function ExtractWordPos(N: Integer; const S: string; const WordDelims: Array of char; out Pos: Integer): string;
  953. var
  954. i,j,l: SizeInt;
  955. begin
  956. j:=0;
  957. i:=WordPosition(N, S, WordDelims);
  958. if (I>MaxInt) then
  959. begin
  960. Result:='';
  961. Pos:=-1;
  962. Exit;
  963. end;
  964. Pos:=i;
  965. if (i<>0) then
  966. begin
  967. j:=i;
  968. l:=Length(S);
  969. while (j<=L) and not CharInSet(S[j],WordDelims) do
  970. inc(j);
  971. end;
  972. Result:=Copy(S,I,j-I);
  973. end;
  974. function ExtractDelimited(N: Integer; const S: string; const Delims: Array of char): string;
  975. var
  976. w,i,l,len: SizeInt;
  977. begin
  978. w:=0;
  979. i:=1;
  980. l:=0;
  981. len:=Length(S);
  982. SetLength(Result, 0);
  983. while (i<=len) and (w<>N) do
  984. begin
  985. if CharInSet(S[i],Delims) then
  986. inc(w)
  987. else
  988. begin
  989. if (N-1)=w then
  990. begin
  991. inc(l);
  992. Result:=Result+S[i];
  993. end;
  994. end;
  995. inc(i);
  996. end;
  997. end;
  998. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: Array of char): string;
  999. var
  1000. i,l: SizeInt;
  1001. begin
  1002. i:=Pos;
  1003. l:=Length(S);
  1004. while (i<=l) and not CharInSet(S[i],Delims) do
  1005. inc(i);
  1006. Result:=Copy(S,Pos,i-Pos);
  1007. while (i<=l) and CharInSet(S[i],Delims) do
  1008. inc(i);
  1009. if I>MaxInt then
  1010. Pos:=MaxInt
  1011. else
  1012. Pos:=i;
  1013. end;
  1014. function isWordPresent(const W, S: string; const WordDelims: Array of char): Boolean;
  1015. var
  1016. i,Count : SizeInt;
  1017. begin
  1018. Result:=False;
  1019. Count:=WordCount(S, WordDelims);
  1020. I:=1;
  1021. While (Not Result) and (I<=Count) do
  1022. begin
  1023. Result:=ExtractWord(i,S,WordDelims)=W;
  1024. Inc(i);
  1025. end;
  1026. end;
  1027. function Numb2USA(const S: string): string;
  1028. var
  1029. i, NA: Integer;
  1030. begin
  1031. i:=Length(S);
  1032. Result:=S;
  1033. NA:=0;
  1034. while (i > 0) do begin
  1035. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  1036. begin
  1037. insert(',', Result, i);
  1038. inc(NA);
  1039. end;
  1040. Dec(i);
  1041. end;
  1042. end;
  1043. function PadCenter(const S: string; Len: SizeInt): string;
  1044. begin
  1045. if Length(S)<Len then
  1046. begin
  1047. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  1048. Result:=Result+StringOfChar(' ',Len-Length(Result));
  1049. end
  1050. else
  1051. Result:=S;
  1052. end;
  1053. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  1054. var
  1055. C: Integer;
  1056. Number: Longint;
  1057. begin
  1058. if N=0 then
  1059. Result:='0'
  1060. else
  1061. begin
  1062. Number:=N;
  1063. Result:='';
  1064. while Number>0 do
  1065. begin
  1066. C:=Number mod Base;
  1067. if C>9 then
  1068. C:=C+55
  1069. else
  1070. C:=C+48;
  1071. Result:=Chr(C)+Result;
  1072. Number:=Number div Base;
  1073. end;
  1074. end;
  1075. if (Result<>'') then
  1076. Result:=AddChar('0',Result,Len);
  1077. end;
  1078. function Numb2Dec(S: string; Base: Byte): Longint;
  1079. var
  1080. i, P: sizeint;
  1081. begin
  1082. i:=Length(S);
  1083. Result:=0;
  1084. S:=UpperCase(S);
  1085. P:=1;
  1086. while (i>=1) do
  1087. begin
  1088. if (S[i]>'@') then
  1089. Result:=Result+(Ord(S[i])-55)*P
  1090. else
  1091. Result:=Result+(Ord(S[i])-48)*P;
  1092. Dec(i);
  1093. P:=P*Base;
  1094. end;
  1095. end;
  1096. Function RomanValues(C : Char) : Word;
  1097. begin
  1098. Case c of
  1099. 'C' : Result:=100;
  1100. 'D' : Result:=500;
  1101. 'I' : Result:=1;
  1102. 'L' : Result:=50;
  1103. 'M' : Result:=1000;
  1104. 'V' : Result:=5;
  1105. 'X' : Result:=10;
  1106. else
  1107. Result:=0;
  1108. end;
  1109. end;
  1110. function RomanToIntDontCare(const S: String): Longint;
  1111. {This was the original implementation of RomanToInt,
  1112. it is internally used in TryRomanToInt when Strictness = rcsDontCare}
  1113. const
  1114. RomanChars = ['C','D','I','L','M','V','X'];
  1115. var
  1116. index, Next: Char;
  1117. i,l: SizeInt;
  1118. Negative: Boolean;
  1119. begin
  1120. Result:=0;
  1121. i:=0;
  1122. Negative:=(Length(S)>0) and (S[1]='-');
  1123. if Negative then
  1124. inc(i);
  1125. l:=Length(S);
  1126. while (i<l) do
  1127. begin
  1128. inc(i);
  1129. index:=UpCase(S[i]);
  1130. if index in RomanChars then
  1131. begin
  1132. if (i+1)<=l then
  1133. Next:=UpCase(S[i+1])
  1134. else
  1135. Next:=#0;
  1136. if (Next in RomanChars) and (RomanValues(index)<RomanValues(Next)) then
  1137. begin
  1138. inc(Result, RomanValues(Next));
  1139. Dec(Result, RomanValues(index));
  1140. inc(i);
  1141. end
  1142. else
  1143. inc(Result, RomanValues(index));
  1144. end
  1145. else
  1146. begin
  1147. Result:=0;
  1148. Exit;
  1149. end;
  1150. end;
  1151. if Negative then
  1152. Result:=-Result;
  1153. end;
  1154. { TryRomanToInt: try to convert a roman numeral to an integer
  1155. Parameters:
  1156. S: Roman numeral (like: 'MCMXXII')
  1157. N: Integer value of S (only meaningfull if the function succeeds)
  1158. Stricness: controls how strict the parsing of S is
  1159. - rcsStrict:
  1160. * Follow common subtraction rules
  1161. - only 1 preceding subtraction character allowed: IX = 9, but IIX <> 8
  1162. - from M you can only subtract C
  1163. - from D you can only subtract C
  1164. - from C you can only subtract X
  1165. - from L you can only subtract X
  1166. - from X you can only subtract I
  1167. - from V you can only subtract I
  1168. * The numeral is parsed in "groups" (first M's, then D's etc.), the next group to be parsed
  1169. must always be of a lower denomination than the previous one.
  1170. Example: 'MMDCCXX' is allowed but 'MMCCXXDD' is not
  1171. * There can only ever be 3 consecutive M's, C's, X's or I's
  1172. * There can only ever be 1 D, 1 L and 1 V
  1173. * After IX or IV there can be no more characters
  1174. * Negative numbers are not supported
  1175. // As a consequence the maximum allowed Roman numeral is MMMCMXCIX = 3999, also N can never become 0 (zero)
  1176. - rcsRelaxed: Like rcsStrict but with the following exceptions:
  1177. * An infinite number of (leading) M's is allowed
  1178. * Up to 4 consecutive M's, C's, X's and I's are allowed
  1179. // So this is allowed: 'MMMMMMCXIIII' = 6124
  1180. - rcsDontCare:
  1181. * no checking on the order of "groups" is done
  1182. * there are no restrictions on the number of consecutive chars
  1183. * negative numbers are supported
  1184. * an empty string as input will return True and N will be 0
  1185. * invalid input will return false
  1186. // for backwards comatibility: it supports rather ludicrous input like '-IIIMIII' -> -(2+(1000-1)+3)=-1004
  1187. }
  1188. function TryRomanToInt(S: String; out N: LongInt; Strictness: TRomanConversionStrictness = rcsRelaxed): Boolean;
  1189. var
  1190. i, Len: SizeInt;
  1191. Terminated: Boolean;
  1192. begin
  1193. Result := (False);
  1194. S := UpperCase(S); //don't use AnsiUpperCase please
  1195. Len := Length(S);
  1196. if (Strictness = rcsDontCare) then
  1197. begin
  1198. N := RomanToIntDontCare(S);
  1199. if (N = 0) then
  1200. begin
  1201. Result := (Len = 0);
  1202. end
  1203. else
  1204. Result := True;
  1205. Exit;
  1206. end;
  1207. if (Len = 0) then Exit;
  1208. i := 1;
  1209. N := 0;
  1210. Terminated := False;
  1211. //leading M's
  1212. while (i <= Len) and ((Strictness <> rcsStrict) or (i < 4)) and (S[i] = 'M') do
  1213. begin
  1214. //writeln('TryRomanToInt: Found 1000');
  1215. Inc(i);
  1216. N := N + 1000;
  1217. end;
  1218. //then CM or or CD or D or (C, CC, CCC, CCCC)
  1219. if (i <= Len) and (S[i] = 'D') then
  1220. begin
  1221. //writeln('TryRomanToInt: Found 500');
  1222. Inc(i);
  1223. N := N + 500;
  1224. end
  1225. else if (i + 1 <= Len) and (S[i] = 'C') then
  1226. begin
  1227. if (S[i+1] = 'M') then
  1228. begin
  1229. //writeln('TryRomanToInt: Found 900');
  1230. Inc(i,2);
  1231. N := N + 900;
  1232. end
  1233. else if (S[i+1] = 'D') then
  1234. begin
  1235. //writeln('TryRomanToInt: Found 400');
  1236. Inc(i,2);
  1237. N := N + 400;
  1238. end;
  1239. end ;
  1240. //next max 4 or 3 C's, depending on Strictness
  1241. if (i <= Len) and (S[i] = 'C') then
  1242. begin
  1243. //find max 4 C's
  1244. //writeln('TryRomanToInt: Found 100');
  1245. Inc(i);
  1246. N := N + 100;
  1247. if (i <= Len) and (S[i] = 'C') then
  1248. begin
  1249. //writeln('TryRomanToInt: Found 100');
  1250. Inc(i);
  1251. N := N + 100;
  1252. end;
  1253. if (i <= Len) and (S[i] = 'C') then
  1254. begin
  1255. //writeln('TryRomanToInt: Found 100');
  1256. Inc(i);
  1257. N := N + 100;
  1258. end;
  1259. if (Strictness <> rcsStrict) and (i <= Len) and (S[i] = 'C') then
  1260. begin
  1261. //writeln('TryRomanToInt: Found 100');
  1262. Inc(i);
  1263. N := N + 100;
  1264. end;
  1265. end;
  1266. //then XC or XL
  1267. if (i + 1 <= Len) and (S[i] = 'X') then
  1268. begin
  1269. if (S[i+1] = 'C') then
  1270. begin
  1271. //writeln('TryRomanToInt: Found 90');
  1272. Inc(i,2);
  1273. N := N + 90;
  1274. end
  1275. else if (S[i+1] = 'L') then
  1276. begin
  1277. //writeln('TryRomanToInt: Found 40');
  1278. Inc(i,2);
  1279. N := N + 40;
  1280. end;
  1281. end;
  1282. //then L
  1283. if (i <= Len) and (S[i] = 'L') then
  1284. begin
  1285. //writeln('TryRomanToInt: Found 50');
  1286. Inc(i);
  1287. N := N + 50;
  1288. end;
  1289. //then (X, xx, xxx, xxxx)
  1290. if (i <= Len) and (S[i] = 'X') then
  1291. begin
  1292. //find max 3 or 4 X's, depending on Strictness
  1293. //writeln('TryRomanToInt: Found 10');
  1294. Inc(i);
  1295. N := N + 10;
  1296. if (i <= Len) and (S[i] = 'X') then
  1297. begin
  1298. //writeln('TryRomanToInt: Found 10');
  1299. Inc(i);
  1300. N := N + 10;
  1301. end;
  1302. if (i <= Len) and (S[i] = 'X') then
  1303. begin
  1304. //writeln('TryRomanToInt: Found 10');
  1305. Inc(i);
  1306. N := N + 10;
  1307. end;
  1308. if (Strictness <> rcsStrict) and (i <= Len) and (S[i] = 'X') then
  1309. begin
  1310. //writeln('TryRomanToInt: Found 10');
  1311. Inc(i);
  1312. N := N + 10;
  1313. end;
  1314. end;
  1315. //then IX or IV
  1316. if (i + 1 <= Len) and (S[i] = 'I') then
  1317. begin
  1318. if (S[i+1] = 'X') then
  1319. begin
  1320. Terminated := (True);
  1321. //writeln('TryRomanToInt: Found 9');
  1322. Inc(i,2);
  1323. N := N + 9;
  1324. end
  1325. else if (S[i+1] = 'V') then
  1326. begin
  1327. Terminated := (True);
  1328. //writeln('TryRomanToInt: Found 4');
  1329. Inc(i,2);
  1330. N := N + 4;
  1331. end;
  1332. end;
  1333. //then V
  1334. if (not Terminated) and (i <= Len) and (S[i] = 'V') then
  1335. begin
  1336. //writeln('TryRomanToInt: Found 5');
  1337. Inc(i);
  1338. N := N + 5;
  1339. end;
  1340. //then I
  1341. if (not Terminated) and (i <= Len) and (S[i] = 'I') then
  1342. begin
  1343. Terminated := (True);
  1344. //writeln('TryRomanToInt: Found 1');
  1345. Inc(i);
  1346. N := N + 1;
  1347. //Find max 2 or 3 closing I's, depending on strictness
  1348. if (i <= Len) and (S[i] = 'I') then
  1349. begin
  1350. //writeln('TryRomanToInt: Found 1');
  1351. Inc(i);
  1352. N := N + 1;
  1353. end;
  1354. if (i <= Len) and (S[i] = 'I') then
  1355. begin
  1356. //writeln('TryRomanToInt: Found 1');
  1357. Inc(i);
  1358. N := N + 1;
  1359. end;
  1360. if (Strictness <> rcsStrict) and (i <= Len) and (S[i] = 'I') then
  1361. begin
  1362. //writeln('TryRomanToInt: Found 1');
  1363. Inc(i);
  1364. N := N + 1;
  1365. end;
  1366. end;
  1367. //writeln('TryRomanToInt: Len = ',Len,' i = ',i);
  1368. Result := (i > Len);
  1369. //if Result then writeln('TryRomanToInt: N = ',N);
  1370. end;
  1371. function RomanToInt(const S: string; Strictness: TRomanConversionStrictness = rcsRelaxed): Longint;
  1372. begin
  1373. if not TryRomanToInt(S, Result, Strictness) then
  1374. raise EConvertError.CreateFmt(SInvalidRomanNumeral,[S]);
  1375. end;
  1376. function RomanToIntDef(const S: String; const ADefault: Longint;
  1377. Strictness: TRomanConversionStrictness): Longint;
  1378. begin
  1379. if not TryRomanToInt(S, Result, Strictness) then
  1380. Result := ADefault;
  1381. end;
  1382. function intToRoman(Value: Longint): string;
  1383. const
  1384. Arabics : Array[1..13] of Integer
  1385. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  1386. Romans : Array[1..13] of String
  1387. = ('I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M');
  1388. var
  1389. i: Integer;
  1390. begin
  1391. Result:='';
  1392. for i:=13 downto 1 do
  1393. while (Value >= Arabics[i]) do
  1394. begin
  1395. Value:=Value-Arabics[i];
  1396. Result:=Result+Romans[i];
  1397. end;
  1398. end;
  1399. function intToBin(Value: Longint; Digits, Spaces: Integer): string;
  1400. var endpos : integer;
  1401. p,p2: integer;
  1402. k: integer;
  1403. begin
  1404. Result:='';
  1405. if (Digits>32) then
  1406. Digits:=32;
  1407. if (spaces=0) then
  1408. begin
  1409. result:=inttobin(value,digits);
  1410. exit;
  1411. end;
  1412. endpos:=digits+ (digits-1) div spaces;
  1413. setlength(result,endpos);
  1414. p:=endpos;
  1415. p2:=1;
  1416. k:=spaces;
  1417. while (p>=p2) do
  1418. begin
  1419. if k=0 then
  1420. begin
  1421. Result[p]:=' ';
  1422. dec(p);
  1423. k:=spaces;
  1424. end;
  1425. Result[P]:=chr(48+(cardinal(value) and 1));
  1426. value:=cardinal(value) shr 1;
  1427. dec(p);
  1428. dec(k);
  1429. end;
  1430. end;
  1431. function intToBin(Value: Longint; Digits:integer): string;
  1432. var
  1433. p,p2 : integer;
  1434. begin
  1435. result:='';
  1436. if digits<=0 then exit;
  1437. setlength(result,digits);
  1438. p:=digits;
  1439. p2:=1;
  1440. // typecasts because we want to keep intto* delphi compat and take an integer
  1441. while (p>=p2) and (cardinal(value)>0) do
  1442. begin
  1443. Result[p]:=chr(48+(cardinal(value) and 1));
  1444. value:=cardinal(value) shr 1;
  1445. dec(p);
  1446. end;
  1447. digits:=p-p2+1;
  1448. While digits>0 do
  1449. begin
  1450. Result[Digits]:=Chr(48);
  1451. Dec(Digits);
  1452. end;
  1453. end;
  1454. function IntToBin(Value: NativeInt; Digits:integer): string;
  1455. var
  1456. p,p2 : integer;
  1457. begin
  1458. result:='';
  1459. if digits<=0 then exit;
  1460. setlength(result,digits);
  1461. p:=digits;
  1462. p2:=1;
  1463. // typecasts because we want to keep intto* delphi compat and take a signed val
  1464. // and avoid warnings
  1465. while (p>=p2) and (value>0) do
  1466. begin
  1467. Result[p]:=chr(48+(cardinal(value) and 1));
  1468. value:=value div 2;
  1469. dec(p);
  1470. end;
  1471. digits:=p-p2+1;
  1472. While digits>0 do
  1473. result[digits]:=#48;
  1474. end;
  1475. function FindPart(const HelpWilds, inputStr: string): SizeInt;
  1476. var
  1477. Diff, i, J: SizeInt;
  1478. begin
  1479. Result:=0;
  1480. i:=Pos('?',HelpWilds);
  1481. if (i=0) then
  1482. Result:=Pos(HelpWilds, inputStr)
  1483. else
  1484. begin
  1485. Diff:=Length(inputStr) - Length(HelpWilds);
  1486. for i:=0 to Diff do
  1487. begin
  1488. for J:=1 to Length(HelpWilds) do
  1489. if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
  1490. begin
  1491. if (J=Length(HelpWilds)) then
  1492. begin
  1493. Result:=i+1;
  1494. Exit;
  1495. end;
  1496. end
  1497. else
  1498. Break;
  1499. end;
  1500. end;
  1501. end;
  1502. Function isMatch(level : integer;inputstr,wilds : string; CWild, CinputWord: SizeInt;MaxInputword,maxwilds : SizeInt; Out EOS : Boolean) : Boolean;
  1503. begin
  1504. EOS:=False;
  1505. Result:=True;
  1506. repeat
  1507. if Wilds[CWild] = '*' then { handling of '*' }
  1508. begin
  1509. inc(CWild);
  1510. while Wilds[CWild] = '?' do { equal to '?' }
  1511. begin
  1512. { goto next letter }
  1513. inc(CWild);
  1514. inc(CinputWord);
  1515. end;
  1516. { increase until a match }
  1517. Repeat
  1518. while (inputStr[CinputWord]<>Wilds[CWild]) and (CinputWord <= MaxinputWord) do
  1519. inc(CinputWord);
  1520. Result:=isMatch(Level+1,inputstr,wilds,CWild, CinputWord,MaxInputword,maxwilds,EOS);
  1521. if not Result then
  1522. Inc(cInputWord);
  1523. Until Result or (CinputWord>=MaxinputWord);
  1524. if Result and EOS then
  1525. Exit;
  1526. Continue;
  1527. end;
  1528. if Wilds[CWild] = '?' then { equal to '?' }
  1529. begin
  1530. { goto next letter }
  1531. inc(CWild);
  1532. inc(CinputWord);
  1533. Continue;
  1534. end;
  1535. if inputStr[CinputWord] = Wilds[CWild] then { equal letters }
  1536. begin
  1537. { goto next letter }
  1538. inc(CWild);
  1539. inc(CinputWord);
  1540. Continue;
  1541. end;
  1542. Result:=false;
  1543. Exit;
  1544. until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
  1545. { no completed evaluation, we need to check what happened }
  1546. if (CinputWord <= MaxinputWord) or (CWild < MaxWilds) then
  1547. Result:=false
  1548. else if (CWild>Maxwilds) then
  1549. EOS:=False
  1550. else
  1551. begin
  1552. EOS:=Wilds[CWild]='*';
  1553. if not EOS then
  1554. Result:=False;
  1555. end
  1556. end;
  1557. function isWild(inputStr, Wilds: string; ignoreCase: boolean): boolean;
  1558. var
  1559. i: SizeInt;
  1560. MaxinputWord, MaxWilds: SizeInt; { Length of inputStr and Wilds }
  1561. eos : Boolean;
  1562. begin
  1563. Result:=true;
  1564. if Wilds = inputStr then
  1565. Exit;
  1566. { delete '**', because '**' = '*' }
  1567. i:=Pos('**', Wilds);
  1568. while i > 0 do
  1569. begin
  1570. Delete(Wilds, i, 1);
  1571. i:=Pos('**', Wilds);
  1572. end;
  1573. if Wilds = '*' then { for fast end, if Wilds only '*' }
  1574. Exit;
  1575. MaxinputWord:=Length(inputStr);
  1576. MaxWilds:=Length(Wilds);
  1577. if (MaxWilds = 0) or (MaxinputWord = 0) then
  1578. begin
  1579. Result:=false;
  1580. Exit;
  1581. end;
  1582. if ignoreCase then { upcase all letters }
  1583. begin
  1584. inputStr:=UpperCase(inputStr);
  1585. Wilds:=UpperCase(Wilds);
  1586. end;
  1587. Result:=isMatch(1,inputStr,wilds,1,1,MaxinputWord, MaxWilds,EOS);
  1588. end;
  1589. function XorString(const Key, Src: String): String;
  1590. var
  1591. i: SizeInt;
  1592. begin
  1593. Result:=Src;
  1594. if Length(Key) > 0 then
  1595. for i:=1 to Length(Src) do
  1596. Result[i]:=Chr(Ord(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
  1597. end;
  1598. function XorEncode(const Key, Source: string): string;
  1599. var
  1600. i: Integer;
  1601. C: Byte;
  1602. begin
  1603. Result:='';
  1604. for i:=1 to Length(Source) do
  1605. begin
  1606. if Length(Key) > 0 then
  1607. C:=Ord(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Source[i])
  1608. else
  1609. C:=Ord(Source[i]);
  1610. Result:=Result+LowerCase(intToHex(C, 2));
  1611. end;
  1612. end;
  1613. function XorDecode(const Key, Source: string): string;
  1614. var
  1615. i: Integer;
  1616. C: Char;
  1617. begin
  1618. Result:='';
  1619. for i:=0 to Length(Source) div 2 - 1 do
  1620. begin
  1621. C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
  1622. if Length(Key) > 0 then
  1623. C:=Chr(Ord(Key[1 + (i mod Length(Key))]) xor Ord(C));
  1624. Result:=Result + C;
  1625. end;
  1626. end;
  1627. function GetCmdLineArg(const Switch: string; SwitchChars: Array of char): string;
  1628. var
  1629. i: Integer;
  1630. S: string;
  1631. begin
  1632. i:=1;
  1633. Result:='';
  1634. while (Result='') and (i<=ParamCount) do
  1635. begin
  1636. S:=ParamStr(i);
  1637. if (Length(SwitchChars)=0) or (CharInSet(S[1],SwitchChars) and (Length(S) > 1)) and
  1638. (CompareText(Copy(S,2,Length(S)-1),Switch)=0) then
  1639. begin
  1640. inc(i);
  1641. if i<=ParamCount then
  1642. Result:=ParamStr(i);
  1643. end;
  1644. inc(i);
  1645. end;
  1646. end;
  1647. Function RPosEX(C:char;const S : String;offs:cardinal):SizeInt; overload;
  1648. Begin
  1649. Result:=TJSString.New(S).lastIndexOf(c,offs-1)+1;
  1650. End;
  1651. Function RPos(c:char;const S : String):SizeInt;
  1652. begin
  1653. Result:=RPosEx(string(C),S,Length(S));
  1654. end;
  1655. Function RPos (Const Substr : String; Const Source : String) : SizeInt; overload;
  1656. begin
  1657. Result:=RPosEx(SubStr,Source,Length(Source));
  1658. end;
  1659. Function RPosex (Const Substr : String; Const Source : String;offs:cardinal) : SizeInt; overload;
  1660. begin
  1661. Result:=TJSString.New(Source).lastIndexOf(SubStr,offs-1)+1;
  1662. end;
  1663. function possetex (const c:Array of char;const s : String;count:Integer ):SizeInt;
  1664. var i,j:SizeInt;
  1665. begin
  1666. if s='' then
  1667. j:=0
  1668. else
  1669. begin
  1670. i:=length(s);
  1671. j:=count;
  1672. if j>i then
  1673. begin
  1674. result:=0;
  1675. exit;
  1676. end;
  1677. while (j<=i) and (not CharInSet(s[j],c)) do inc(j);
  1678. if (j>i) then
  1679. j:=0; // not found.
  1680. end;
  1681. result:=j;
  1682. end;
  1683. function PosSetEx (const c:string;const s : String;count:Integer ):SizeInt;
  1684. var
  1685. cset : Array of char;
  1686. i,l : SizeInt;
  1687. begin
  1688. L:=Length(C);
  1689. SetLength(Cset,L);
  1690. if L>0 then
  1691. for i:=1 to l do
  1692. cset[i-1]:=c[i];
  1693. Result:=PosSetEx(cset,s,count);
  1694. end;
  1695. function posset (const c:Array of char;const s : String ):SizeInt;
  1696. begin
  1697. result:=possetex(c,s,1);
  1698. end;
  1699. function PosSet (const c:string;const s : String ):SizeInt;
  1700. begin
  1701. Result:=PosSetEx(c,S,1);
  1702. end;
  1703. Procedure Removeleadingchars(Var S : String; Const CSet:Array of char);
  1704. var
  1705. I,J : Longint;
  1706. begin
  1707. I:=Length(S);
  1708. if (I>0) then
  1709. begin
  1710. J:=1;
  1711. while (J<=I) and CharInSet(S[J],CSet) DO
  1712. inc(J);
  1713. if J>1 then
  1714. Delete(S,1,J-1);
  1715. end;
  1716. end;
  1717. function TrimLeftSet(const S: String;const CSet:Array of char): String;
  1718. begin
  1719. result:=s;
  1720. removeleadingchars(result,cset);
  1721. end;
  1722. Procedure RemoveTrailingChars(VAR S : String;Const CSet:Array of char);
  1723. var
  1724. i,j : longint;
  1725. begin
  1726. I:=Length(S);
  1727. if (I>0) then
  1728. begin
  1729. J:=I;
  1730. while (j>0) and CharInSet(S[J],CSet) do
  1731. dec(J);
  1732. if J<>I then
  1733. setLength(S,J);
  1734. End;
  1735. End;
  1736. Function TrimRightSet(const S: String;const CSet:Array of char): String;
  1737. begin
  1738. result:=s;
  1739. RemoveTrailingchars(result,cset);
  1740. end;
  1741. Procedure RemovePadChars(VAR S : String;Const CSet:Array of char);
  1742. var
  1743. I,J,K: longint;
  1744. begin
  1745. I:=Length(S);
  1746. if I=0 then exit;
  1747. J:=I;
  1748. while (j>0) and CharInset(S[J],CSet) do
  1749. dec(J);
  1750. if j=0 Then
  1751. begin
  1752. s:='';
  1753. exit;
  1754. end;
  1755. SetLength(S,J);
  1756. I:=J;
  1757. k:=1;
  1758. while (k<=I) and CharInSet(S[k],CSet) do
  1759. inc(k);
  1760. if k>1 Then
  1761. Delete(S,1,K-1);
  1762. end;
  1763. function TrimSet(const S: String;const CSet:Array of char): String;
  1764. begin
  1765. Result:=s;
  1766. RemovePadChars(Result,cset);
  1767. end;
  1768. function StartsText(const ASubText, AText: string): Boolean; inline;
  1769. begin
  1770. Result := AnsiStartsText(ASubText, AText);
  1771. end;
  1772. function EndsText(const ASubText, AText: string): Boolean;
  1773. begin
  1774. Result := AnsiEndsText(ASubText, AText);
  1775. end;
  1776. function ResemblesText(const AText, AOther: string): Boolean;
  1777. begin
  1778. if Assigned(ResemblesProc) then
  1779. Result := ResemblesProc(AText, AOther)
  1780. else
  1781. Result := False;
  1782. end;
  1783. function ContainsText(const AText, ASubText: string): Boolean;
  1784. begin
  1785. Result := AnsiContainsText(AText, ASubText);
  1786. end;
  1787. function MatchText(const AText: string; const AValues: array of string): Boolean;
  1788. begin
  1789. Result := AnsiMatchText(AText, AValues);
  1790. end;
  1791. function IndexText(const AText: string; const AValues: array of string): Integer;
  1792. begin
  1793. Result := AnsiIndexText(AText, AValues);
  1794. end;
  1795. function ContainsStr(const AText, ASubText: string): Boolean;
  1796. begin
  1797. Result := AnsiContainsStr(AText, ASubText);
  1798. end;
  1799. Function StartsStr(const ASubText, AText: string): Boolean;
  1800. begin
  1801. Result := AnsiStartsStr(AText, ASubText);
  1802. end;
  1803. Function EndsStr(const ASubText, AText: string): Boolean;
  1804. begin
  1805. Result := AnsiEndsStr(AText, ASubText);
  1806. end;
  1807. initialization
  1808. AnsiResemblesProc:= @SoundexProc;
  1809. ResemblesProc:=@SoundexProc;
  1810. end.