strutils.pp 47 KB

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