strutils.pas 52 KB

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