strutils.pp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  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. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  392. var
  393. Len,I,SLen: Integer;
  394. C: Char;
  395. Found : Boolean;
  396. Direction: Shortint;
  397. CharMap: array[Char] of Char;
  398. Function GotoNextWord(var P : PChar): Boolean;
  399. begin
  400. if (Direction=1) then
  401. begin
  402. // Skip characters
  403. While (Len>0) and not (P^ in WordDelimiters) do
  404. begin
  405. Inc(P);
  406. Dec(Len);
  407. end;
  408. // skip delimiters
  409. While (Len>0) and (P^ in WordDelimiters) do
  410. begin
  411. Inc(P);
  412. Dec(Len);
  413. end;
  414. Result:=Len>0;
  415. end
  416. else
  417. begin
  418. // Skip Delimiters
  419. While (Len>0) and (P^ in WordDelimiters) do
  420. begin
  421. Dec(P);
  422. Dec(Len);
  423. end;
  424. // skip characters
  425. While (Len>0) and not (P^ in WordDelimiters) do
  426. begin
  427. Dec(P);
  428. Dec(Len);
  429. end;
  430. Result:=Len>0;
  431. // We're on the first delimiter. Pos back on char.
  432. Inc(P);
  433. Inc(Len);
  434. end;
  435. end;
  436. begin
  437. Result:=nil;
  438. Slen:=Length(SearchString);
  439. if (BufLen<=0) or (Slen=0) then
  440. Exit;
  441. if soDown in Options then
  442. begin
  443. Direction:=1;
  444. Inc(SelStart,SelLength);
  445. Len:=BufLen-SelStart-SLen+1;
  446. if (Len<=0) then
  447. Exit;
  448. end
  449. else
  450. begin
  451. Direction:=-1;
  452. Dec(SelStart,Length(SearchString));
  453. Len:=SelStart+1;
  454. end;
  455. if (SelStart<0) or (SelStart>BufLen) then
  456. Exit;
  457. Result:=@Buf[SelStart];
  458. for C:=Low(Char) to High(Char) do
  459. if (soMatchCase in Options) then
  460. CharMap[C]:=C
  461. else
  462. CharMap[C]:=Upcase(C);
  463. if Not (soMatchCase in Options) then
  464. SearchString:=UpCase(SearchString);
  465. Found:=False;
  466. while (Result<>Nil) and (Not Found) do
  467. begin
  468. if ((soWholeWord in Options) and
  469. (Result<>@Buf[SelStart]) and
  470. not GotoNextWord(Result)) then
  471. Result:=Nil
  472. else
  473. begin
  474. // try to match whole searchstring
  475. I:=0;
  476. while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
  477. Inc(I);
  478. // Whole searchstring matched ?
  479. if (I=SLen) then
  480. Found:=(Len=0) or
  481. (not (soWholeWord in Options)) or
  482. (Result[SLen] in WordDelimiters);
  483. if not Found then
  484. begin
  485. Inc(Result,Direction);
  486. Dec(Len);
  487. If (Len=0) then
  488. Result:=Nil;
  489. end;
  490. end;
  491. end;
  492. end;
  493. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar;inline; // ; Options: TStringSearchOptions = [soDown]
  494. begin
  495. Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
  496. end;
  497. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  498. var i : pchar;
  499. begin
  500. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  501. i:=strpos(@s[offset],@substr[1]);
  502. if i=nil then
  503. PosEx:=0
  504. else
  505. PosEx:=succ(i-pchar(pointer(s)));
  506. end;
  507. Function PosEx(const SubStr, S: string): Integer;inline; // Offset: Cardinal = 1
  508. begin
  509. posex:=posex(substr,s,1);
  510. end;
  511. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  512. var l : longint;
  513. begin
  514. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  515. l:=length(s);
  516. {$ifndef useindexbyte}
  517. while (SizeInt(offset)<=l) and (s[offset]<>c) do inc(offset);
  518. if SizeInt(offset)>l then
  519. posex:=0
  520. else
  521. posex:=offset;
  522. {$else}
  523. posex:=offset+indexbyte(s[offset],l-offset+1);
  524. if posex=(offset-1) then
  525. posex:=0;
  526. {$endif}
  527. end;
  528. function StringsReplace(const S: string; OldPattern, NewPattern: array of string; Flags: TReplaceFlags): string;
  529. var pc,pcc,lastpc : pchar;
  530. strcount : integer;
  531. ResStr,
  532. CompStr : string;
  533. Found : Boolean;
  534. sc : integer;
  535. begin
  536. sc := length(OldPattern);
  537. if sc <> length(NewPattern) then
  538. raise exception.Create(SErrAmountStrings);
  539. dec(sc);
  540. if rfIgnoreCase in Flags then
  541. begin
  542. CompStr:=AnsiUpperCase(S);
  543. for strcount := 0 to sc do
  544. OldPattern[strcount] := AnsiUpperCase(OldPattern[strcount]);
  545. end
  546. else
  547. CompStr := s;
  548. ResStr := '';
  549. pc := @CompStr[1];
  550. pcc := @s[1];
  551. lastpc := pc+Length(S);
  552. while pc < lastpc do
  553. begin
  554. Found := False;
  555. for strcount := 0 to sc do
  556. begin
  557. if (length(OldPattern[strcount])>0) and
  558. (OldPattern[strcount][1]=pc^) and
  559. (Length(OldPattern[strcount]) <= (lastpc-pc)) and
  560. (CompareByte(OldPattern[strcount][1],pc^,Length(OldPattern[strcount]))=0) then
  561. begin
  562. ResStr := ResStr + NewPattern[strcount];
  563. pc := pc+Length(OldPattern[strcount]);
  564. pcc := pcc+Length(OldPattern[strcount]);
  565. Found := true;
  566. end
  567. end;
  568. if not found then
  569. begin
  570. ResStr := ResStr + pcc^;
  571. inc(pc);
  572. inc(pcc);
  573. end
  574. else if not (rfReplaceAll in Flags) then
  575. begin
  576. ResStr := ResStr + StrPas(pcc);
  577. break;
  578. end;
  579. end;
  580. Result := ResStr;
  581. end;
  582. { ---------------------------------------------------------------------
  583. Soundex Functions.
  584. ---------------------------------------------------------------------}
  585. Const
  586. SScore : array[1..255] of Char =
  587. ('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
  588. '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
  589. '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
  590. '0','0','0','0','0','0', // 91..95
  591. '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
  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', // 123..154
  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', // 155..186
  594. '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
  595. '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
  596. '0','0','0','0','0'); // 251..255
  597. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  598. Var
  599. S,PS : Char;
  600. I,L : integer;
  601. begin
  602. Result:='';
  603. PS:=#0;
  604. If Length(AText)>0 then
  605. begin
  606. Result:=Upcase(AText[1]);
  607. I:=2;
  608. L:=Length(AText);
  609. While (I<=L) and (Length(Result)<ALength) do
  610. begin
  611. S:=SScore[Ord(AText[i])];
  612. If Not (S in ['0','i',PS]) then
  613. Result:=Result+S;
  614. If (S<>'i') then
  615. PS:=S;
  616. Inc(I);
  617. end;
  618. end;
  619. L:=Length(Result);
  620. If (L<ALength) then
  621. Result:=Result+StringOfChar('0',Alength-L);
  622. end;
  623. Function Soundex(const AText: string): string;inline; // ; ALength: TSoundexLength = 4
  624. begin
  625. Result:=Soundex(AText,4);
  626. end;
  627. Const
  628. Ord0 = Ord('0');
  629. OrdA = Ord('A');
  630. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  631. var
  632. SE: string;
  633. I: Integer;
  634. begin
  635. Result:=-1;
  636. SE:=Soundex(AText,ALength);
  637. If Length(SE)>0 then
  638. begin
  639. Result:=Ord(SE[1])-OrdA;
  640. if ALength > 1 then
  641. begin
  642. Result:=Result*26+(Ord(SE[2])-Ord0);
  643. for I:=3 to ALength do
  644. Result:=(Ord(SE[I])-Ord0)+Result*7;
  645. end;
  646. Result:=ALength+Result*9;
  647. end;
  648. end;
  649. Function SoundexInt(const AText: string): Integer;inline; //; ALength: TSoundexIntLength = 4
  650. begin
  651. Result:=SoundexInt(AText,4);
  652. end;
  653. Function DecodeSoundexInt(AValue: Integer): string;
  654. var
  655. I, Len: Integer;
  656. begin
  657. Result := '';
  658. Len := AValue mod 9;
  659. AValue := AValue div 9;
  660. for I:=Len downto 3 do
  661. begin
  662. Result:=Chr(Ord0+(AValue mod 7))+Result;
  663. AValue:=AValue div 7;
  664. end;
  665. if Len>2 then
  666. Result:=IntToStr(AValue mod 26)+Result;
  667. AValue:=AValue div 26;
  668. Result:=Chr(OrdA+AValue)+Result;
  669. end;
  670. Function SoundexWord(const AText: string): Word;
  671. Var
  672. S : String;
  673. begin
  674. S:=SoundEx(Atext,4);
  675. Result:=Ord(S[1])-OrdA;
  676. Result:=Result*26+ord(S[2])-48;
  677. Result:=Result*7+ord(S[3])-48;
  678. Result:=Result*7+ord(S[4])-48;
  679. end;
  680. Function DecodeSoundexWord(AValue: Word): string;
  681. begin
  682. Result := Chr(Ord0+ (AValue mod 7));
  683. AValue := AValue div 7;
  684. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  685. AValue := AValue div 7;
  686. Result := IntToStr(AValue mod 26) + Result;
  687. AValue := AValue div 26;
  688. Result := Chr(OrdA+AValue) + Result;
  689. end;
  690. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;inline;
  691. begin
  692. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  693. end;
  694. Function SoundexSimilar(const AText, AOther: string): Boolean;inline; //; ALength: TSoundexLength = 4
  695. begin
  696. Result:=SoundexSimilar(AText,AOther,4);
  697. end;
  698. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;inline;
  699. begin
  700. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  701. end;
  702. Function SoundexCompare(const AText, AOther: string): Integer;inline; //; ALength: TSoundexLength = 4
  703. begin
  704. Result:=SoundexCompare(AText,AOther,4);
  705. end;
  706. Function SoundexProc(const AText, AOther: string): Boolean;
  707. begin
  708. Result:=SoundexSimilar(AText,AOther);
  709. end;
  710. { ---------------------------------------------------------------------
  711. RxStrUtils-like functions.
  712. ---------------------------------------------------------------------}
  713. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  714. var
  715. i,l: Integer;
  716. begin
  717. l:=Length(S);
  718. i:=1;
  719. Result:=True;
  720. while Result and (i<=l) do
  721. begin
  722. Result:=Not (S[i] in EmptyChars);
  723. Inc(i);
  724. end;
  725. end;
  726. function DelSpace(const S: String): string;
  727. begin
  728. Result:=DelChars(S,' ');
  729. end;
  730. function DelChars(const S: string; Chr: Char): string;
  731. var
  732. I,J: Integer;
  733. begin
  734. Result:=S;
  735. I:=Length(Result);
  736. While I>0 do
  737. begin
  738. if Result[I]=Chr then
  739. begin
  740. J:=I-1;
  741. While (J>0) and (Result[J]=Chr) do
  742. Dec(j);
  743. Delete(Result,J+1,I-J);
  744. I:=J+1;
  745. end;
  746. dec(I);
  747. end;
  748. end;
  749. function DelSpace1(const S: string): string;
  750. var
  751. i: Integer;
  752. begin
  753. Result:=S;
  754. for i:=Length(Result) downto 2 do
  755. if (Result[i]=' ') and (Result[I-1]=' ') then
  756. Delete(Result,I,1);
  757. end;
  758. function Tab2Space(const S: string; Numb: Byte): string;
  759. var
  760. I: Integer;
  761. begin
  762. I:=1;
  763. Result:=S;
  764. while I <= Length(Result) do
  765. if Result[I]<>Chr(9) then
  766. inc(I)
  767. else
  768. begin
  769. Result[I]:=' ';
  770. If (Numb>1) then
  771. Insert(StringOfChar('0',Numb-1),Result,I);
  772. Inc(I,Numb);
  773. end;
  774. end;
  775. function NPos(const C: string; S: string; N: Integer): Integer;
  776. var
  777. i,p,k: Integer;
  778. begin
  779. Result:=0;
  780. if N<1 then
  781. Exit;
  782. k:=0;
  783. i:=1;
  784. Repeat
  785. p:=pos(C,S);
  786. Inc(k,p);
  787. if p>0 then
  788. delete(S,1,p);
  789. Inc(i);
  790. Until (i>n) or (p=0);
  791. If (P>0) then
  792. Result:=K;
  793. end;
  794. function AddChar(C: Char; const S: string; N: Integer): string;
  795. Var
  796. l : Integer;
  797. begin
  798. Result:=S;
  799. l:=Length(Result);
  800. if l<N then
  801. Result:=StringOfChar(C,N-l)+Result;
  802. end;
  803. function AddCharR(C: Char; const S: string; N: Integer): string;
  804. Var
  805. l : Integer;
  806. begin
  807. Result:=S;
  808. l:=Length(Result);
  809. if l<N then
  810. Result:=Result+StringOfChar(C,N-l);
  811. end;
  812. function PadRight(const S: string; N: Integer): string;inline;
  813. begin
  814. Result:=AddCharR(' ',S,N);
  815. end;
  816. function PadLeft(const S: string; N: Integer): string;inline;
  817. begin
  818. Result:=AddChar(' ',S,N);
  819. end;
  820. function Copy2Symb(const S: string; Symb: Char): string;
  821. var
  822. p: Integer;
  823. begin
  824. p:=Pos(Symb,S);
  825. if p=0 then
  826. p:=Length(S)+1;
  827. Result:=Copy(S,1,p-1);
  828. end;
  829. function Copy2SymbDel(var S: string; Symb: Char): string;
  830. var
  831. p: Integer;
  832. begin
  833. p:=Pos(Symb,S);
  834. if p=0 then
  835. begin
  836. result:=s;
  837. s:='';
  838. end
  839. else
  840. begin
  841. Result:=Copy(S,1,p-1);
  842. delete(s,1,p);
  843. end;
  844. end;
  845. function Copy2Space(const S: string): string;inline;
  846. begin
  847. Result:=Copy2Symb(S,' ');
  848. end;
  849. function Copy2SpaceDel(var S: string): string;inline;
  850. begin
  851. Result:=Copy2SymbDel(S,' ');
  852. end;
  853. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  854. var
  855. // l : Integer;
  856. P,PE : PChar;
  857. begin
  858. Result:=AnsiLowerCase(S);
  859. P:=PChar(pointer(Result));
  860. PE:=P+Length(Result);
  861. while (P<PE) do
  862. begin
  863. while (P<PE) and (P^ in WordDelims) do
  864. inc(P);
  865. if (P<PE) then
  866. P^:=UpCase(P^);
  867. while (P<PE) and not (P^ in WordDelims) do
  868. inc(P);
  869. end;
  870. end;
  871. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  872. var
  873. P,PE : PChar;
  874. begin
  875. Result:=0;
  876. P:=Pchar(pointer(S));
  877. PE:=P+Length(S);
  878. while (P<PE) do
  879. begin
  880. while (P<PE) and (P^ in WordDelims) do
  881. Inc(P);
  882. if (P<PE) then
  883. inc(Result);
  884. while (P<PE) and not (P^ in WordDelims) do
  885. inc(P);
  886. end;
  887. end;
  888. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  889. var
  890. PS,P,PE : PChar;
  891. Count: Integer;
  892. begin
  893. Result:=0;
  894. Count:=0;
  895. PS:=PChar(pointer(S));
  896. PE:=PS+Length(S);
  897. P:=PS;
  898. while (P<PE) and (Count<>N) do
  899. begin
  900. while (P<PE) and (P^ in WordDelims) do
  901. inc(P);
  902. if (P<PE) then
  903. inc(Count);
  904. if (Count<>N) then
  905. while (P<PE) and not (P^ in WordDelims) do
  906. inc(P)
  907. else
  908. Result:=(P-PS)+1;
  909. end;
  910. end;
  911. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;inline;
  912. var
  913. i: Integer;
  914. begin
  915. Result:=ExtractWordPos(N,S,WordDelims,i);
  916. end;
  917. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  918. var
  919. i,j,l: Integer;
  920. begin
  921. j:=0;
  922. i:=WordPosition(N, S, WordDelims);
  923. Pos:=i;
  924. if (i<>0) then
  925. begin
  926. j:=i;
  927. l:=Length(S);
  928. while (j<=L) and not (S[j] in WordDelims) do
  929. inc(j);
  930. end;
  931. SetLength(Result,j-i);
  932. If ((j-i)>0) then
  933. Move(S[i],Result[1],j-i);
  934. end;
  935. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  936. var
  937. w,i,l,len: Integer;
  938. begin
  939. w:=0;
  940. i:=1;
  941. l:=0;
  942. len:=Length(S);
  943. SetLength(Result, 0);
  944. while (i<=len) and (w<>N) do
  945. begin
  946. if s[i] in Delims then
  947. inc(w)
  948. else
  949. begin
  950. if (N-1)=w then
  951. begin
  952. inc(l);
  953. SetLength(Result,l);
  954. Result[L]:=S[i];
  955. end;
  956. end;
  957. inc(i);
  958. end;
  959. end;
  960. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  961. var
  962. i,l: Integer;
  963. begin
  964. i:=Pos;
  965. l:=Length(S);
  966. while (i<=l) and not (S[i] in Delims) do
  967. inc(i);
  968. Result:=Copy(S,Pos,i-Pos);
  969. while (i<=l) and (S[i] in Delims) do
  970. inc(i);
  971. Pos:=i;
  972. end;
  973. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  974. var
  975. i,Count : Integer;
  976. begin
  977. Result:=False;
  978. Count:=WordCount(S, WordDelims);
  979. I:=1;
  980. While (Not Result) and (I<=Count) do
  981. begin
  982. Result:=ExtractWord(i,S,WordDelims)=W;
  983. Inc(i);
  984. end;
  985. end;
  986. function Numb2USA(const S: string): string;
  987. var
  988. i, NA: Integer;
  989. begin
  990. i:=Length(S);
  991. Result:=S;
  992. NA:=0;
  993. while (i > 0) do begin
  994. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  995. begin
  996. insert(',', Result, i);
  997. inc(NA);
  998. end;
  999. Dec(i);
  1000. end;
  1001. end;
  1002. function PadCenter(const S: string; Len: Integer): string;
  1003. begin
  1004. if Length(S)<Len then
  1005. begin
  1006. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  1007. Result:=Result+StringOfChar(' ',Len-Length(Result));
  1008. end
  1009. else
  1010. Result:=S;
  1011. end;
  1012. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  1013. var
  1014. C: Integer;
  1015. Number: Longint;
  1016. begin
  1017. if N=0 then
  1018. Result:='0'
  1019. else
  1020. begin
  1021. Number:=N;
  1022. Result:='';
  1023. while Number>0 do
  1024. begin
  1025. C:=Number mod Base;
  1026. if C>9 then
  1027. C:=C+55
  1028. else
  1029. C:=C+48;
  1030. Result:=Chr(C)+Result;
  1031. Number:=Number div Base;
  1032. end;
  1033. end;
  1034. if (Result<>'') then
  1035. Result:=AddChar('0',Result,Len);
  1036. end;
  1037. function Numb2Dec(S: string; Base: Byte): Longint;
  1038. var
  1039. i, P: Longint;
  1040. begin
  1041. i:=Length(S);
  1042. Result:=0;
  1043. S:=UpperCase(S);
  1044. P:=1;
  1045. while (i>=1) do
  1046. begin
  1047. if (S[i]>'@') then
  1048. Result:=Result+(Ord(S[i])-55)*P
  1049. else
  1050. Result:=Result+(Ord(S[i])-48)*P;
  1051. Dec(i);
  1052. P:=P*Base;
  1053. end;
  1054. end;
  1055. function RomanToint(const S: string): Longint;
  1056. const
  1057. RomanChars = ['C','D','I','L','M','V','X'];
  1058. RomanValues : array['C'..'X'] of Word
  1059. = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
  1060. var
  1061. index, Next: Char;
  1062. i,l: Integer;
  1063. Negative: Boolean;
  1064. begin
  1065. Result:=0;
  1066. i:=0;
  1067. Negative:=(Length(S)>0) and (S[1]='-');
  1068. if Negative then
  1069. inc(i);
  1070. l:=Length(S);
  1071. while (i<l) do
  1072. begin
  1073. inc(i);
  1074. index:=UpCase(S[i]);
  1075. if index in RomanChars then
  1076. begin
  1077. if Succ(i)<=l then
  1078. Next:=UpCase(S[i+1])
  1079. else
  1080. Next:=#0;
  1081. if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
  1082. begin
  1083. inc(Result, RomanValues[Next]);
  1084. Dec(Result, RomanValues[index]);
  1085. inc(i);
  1086. end
  1087. else
  1088. inc(Result, RomanValues[index]);
  1089. end
  1090. else
  1091. begin
  1092. Result:=0;
  1093. Exit;
  1094. end;
  1095. end;
  1096. if Negative then
  1097. Result:=-Result;
  1098. end;
  1099. function intToRoman(Value: Longint): string;
  1100. const
  1101. Arabics : Array[1..13] of Integer
  1102. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  1103. Romans : Array[1..13] of String
  1104. = ('I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M');
  1105. var
  1106. i: Integer;
  1107. begin
  1108. Result:='';
  1109. for i:=13 downto 1 do
  1110. while (Value >= Arabics[i]) do
  1111. begin
  1112. Value:=Value-Arabics[i];
  1113. Result:=Result+Romans[i];
  1114. end;
  1115. end;
  1116. function intToBin(Value: Longint; Digits, Spaces: Integer): string;
  1117. var endpos : integer;
  1118. p,p2:pchar;
  1119. k: integer;
  1120. begin
  1121. Result:='';
  1122. if (Digits>32) then
  1123. Digits:=32;
  1124. if (spaces=0) then
  1125. begin
  1126. result:=inttobin(value,digits);
  1127. exit;
  1128. end;
  1129. endpos:=digits+ (digits-1) div spaces;
  1130. setlength(result,endpos);
  1131. p:=@result[endpos];
  1132. p2:=@result[1];
  1133. k:=spaces;
  1134. while (p>=p2) do
  1135. begin
  1136. if k=0 then
  1137. begin
  1138. p^:=' ';
  1139. dec(p);
  1140. k:=spaces;
  1141. end;
  1142. p^:=chr(48+(cardinal(value) and 1));
  1143. value:=cardinal(value) shr 1;
  1144. dec(p);
  1145. dec(k);
  1146. end;
  1147. end;
  1148. function intToBin(Value: Longint; Digits:integer): string;
  1149. var p,p2 : pchar;
  1150. begin
  1151. result:='';
  1152. if digits<=0 then exit;
  1153. setlength(result,digits);
  1154. p:=pchar(pointer(@result[digits]));
  1155. p2:=pchar(pointer(@result[1]));
  1156. // typecasts because we want to keep intto* delphi compat and take an integer
  1157. while (p>=p2) and (cardinal(value)>0) do
  1158. begin
  1159. p^:=chr(48+(cardinal(value) and 1));
  1160. value:=cardinal(value) shr 1;
  1161. dec(p);
  1162. end;
  1163. digits:=p-p2+1;
  1164. if digits>0 then
  1165. fillchar(result[1],digits,#48);
  1166. end;
  1167. function intToBin(Value: int64; Digits:integer): string;
  1168. var p,p2 : pchar;
  1169. begin
  1170. result:='';
  1171. if digits<=0 then exit;
  1172. setlength(result,digits);
  1173. p:=pchar(pointer(@result[digits]));
  1174. p2:=pchar(pointer(@result[1]));
  1175. // typecasts because we want to keep intto* delphi compat and take a signed val
  1176. // and avoid warnings
  1177. while (p>=p2) and (qword(value)>0) do
  1178. begin
  1179. p^:=chr(48+(cardinal(value) and 1));
  1180. value:=qword(value) shr 1;
  1181. dec(p);
  1182. end;
  1183. digits:=p-p2+1;
  1184. if digits>0 then
  1185. fillchar(result[1],digits,#48);
  1186. end;
  1187. function FindPart(const HelpWilds, inputStr: string): Integer;
  1188. var
  1189. i, J: Integer;
  1190. Diff: Integer;
  1191. begin
  1192. Result:=0;
  1193. i:=Pos('?',HelpWilds);
  1194. if (i=0) then
  1195. Result:=Pos(HelpWilds, inputStr)
  1196. else
  1197. begin
  1198. Diff:=Length(inputStr) - Length(HelpWilds);
  1199. for i:=0 to Diff do
  1200. begin
  1201. for J:=1 to Length(HelpWilds) do
  1202. if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
  1203. begin
  1204. if (J=Length(HelpWilds)) then
  1205. begin
  1206. Result:=i+1;
  1207. Exit;
  1208. end;
  1209. end
  1210. else
  1211. Break;
  1212. end;
  1213. end;
  1214. end;
  1215. function isWild(inputStr, Wilds: string; ignoreCase: Boolean): Boolean;
  1216. function SearchNext(var Wilds: string): Integer;
  1217. begin
  1218. Result:=Pos('*', Wilds);
  1219. if Result>0 then
  1220. Wilds:=Copy(Wilds,1,Result - 1);
  1221. end;
  1222. var
  1223. CWild, CinputWord: Integer; { counter for positions }
  1224. i, LenHelpWilds: Integer;
  1225. MaxinputWord, MaxWilds: Integer; { Length of inputStr and Wilds }
  1226. HelpWilds: string;
  1227. begin
  1228. if Wilds = inputStr then begin
  1229. Result:=True;
  1230. Exit;
  1231. end;
  1232. repeat { delete '**', because '**' = '*' }
  1233. i:=Pos('**', Wilds);
  1234. if i > 0 then
  1235. Wilds:=Copy(Wilds, 1, i - 1) + '*' + Copy(Wilds, i + 2, Maxint);
  1236. until i = 0;
  1237. if Wilds = '*' then begin { for fast end, if Wilds only '*' }
  1238. Result:=True;
  1239. Exit;
  1240. end;
  1241. MaxinputWord:=Length(inputStr);
  1242. MaxWilds:=Length(Wilds);
  1243. if ignoreCase then begin { upcase all letters }
  1244. inputStr:=AnsiUpperCase(inputStr);
  1245. Wilds:=AnsiUpperCase(Wilds);
  1246. end;
  1247. if (MaxWilds = 0) or (MaxinputWord = 0) then begin
  1248. Result:=False;
  1249. Exit;
  1250. end;
  1251. CinputWord:=1;
  1252. CWild:=1;
  1253. Result:=True;
  1254. repeat
  1255. if inputStr[CinputWord] = Wilds[CWild] then begin { equal letters }
  1256. { goto next letter }
  1257. inc(CWild);
  1258. inc(CinputWord);
  1259. Continue;
  1260. end;
  1261. if Wilds[CWild] = '?' then begin { equal to '?' }
  1262. { goto next letter }
  1263. inc(CWild);
  1264. inc(CinputWord);
  1265. Continue;
  1266. end;
  1267. if Wilds[CWild] = '*' then begin { handling of '*' }
  1268. HelpWilds:=Copy(Wilds, CWild + 1, MaxWilds);
  1269. i:=SearchNext(HelpWilds);
  1270. LenHelpWilds:=Length(HelpWilds);
  1271. if i = 0 then begin
  1272. { no '*' in the rest, compare the ends }
  1273. if HelpWilds = '' then Exit; { '*' is the last letter }
  1274. { check the rest for equal Length and no '?' }
  1275. for i:=0 to LenHelpWilds - 1 do begin
  1276. if (HelpWilds[LenHelpWilds - i] <> inputStr[MaxinputWord - i]) and
  1277. (HelpWilds[LenHelpWilds - i]<> '?') then
  1278. begin
  1279. Result:=False;
  1280. Exit;
  1281. end;
  1282. end;
  1283. Exit;
  1284. end;
  1285. { handle all to the next '*' }
  1286. inc(CWild, 1 + LenHelpWilds);
  1287. i:=FindPart(HelpWilds, Copy(inputStr, CinputWord, Maxint));
  1288. if i= 0 then begin
  1289. Result:=False;
  1290. Exit;
  1291. end;
  1292. CinputWord:=i + LenHelpWilds;
  1293. Continue;
  1294. end;
  1295. Result:=False;
  1296. Exit;
  1297. until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
  1298. { no completed evaluation }
  1299. if CinputWord <= MaxinputWord then Result:=False;
  1300. if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then Result:=False;
  1301. end;
  1302. function XorString(const Key, Src: ShortString): ShortString;
  1303. var
  1304. i: Integer;
  1305. begin
  1306. Result:=Src;
  1307. if Length(Key) > 0 then
  1308. for i:=1 to Length(Src) do
  1309. Result[i]:=Chr(Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
  1310. end;
  1311. function XorEncode(const Key, Source: string): string;
  1312. var
  1313. i: Integer;
  1314. C: Byte;
  1315. begin
  1316. Result:='';
  1317. for i:=1 to Length(Source) do
  1318. begin
  1319. if Length(Key) > 0 then
  1320. C:=Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Byte(Source[i])
  1321. else
  1322. C:=Byte(Source[i]);
  1323. Result:=Result+AnsiLowerCase(intToHex(C, 2));
  1324. end;
  1325. end;
  1326. function XorDecode(const Key, Source: string): string;
  1327. var
  1328. i: Integer;
  1329. C: Char;
  1330. begin
  1331. Result:='';
  1332. for i:=0 to Length(Source) div 2 - 1 do
  1333. begin
  1334. C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
  1335. if Length(Key) > 0 then
  1336. C:=Chr(Byte(Key[1 + (i mod Length(Key))]) xor Byte(C));
  1337. Result:=Result + C;
  1338. end;
  1339. end;
  1340. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  1341. var
  1342. i: Integer;
  1343. S: string;
  1344. begin
  1345. i:=1;
  1346. Result:='';
  1347. while (Result='') and (i<=ParamCount) do
  1348. begin
  1349. S:=ParamStr(i);
  1350. if (SwitchChars=[]) or ((S[1] in SwitchChars) and (Length(S) > 1)) and
  1351. (AnsiCompareText(Copy(S,2,Length(S)-1),Switch)=0) then
  1352. begin
  1353. inc(i);
  1354. if i<=ParamCount then
  1355. Result:=ParamStr(i);
  1356. end;
  1357. inc(i);
  1358. end;
  1359. end;
  1360. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  1361. var I : SizeUInt;
  1362. p,p2: pChar;
  1363. Begin
  1364. I:=Length(S);
  1365. If (I<>0) and (offs<=i) Then
  1366. begin
  1367. p:=@s[offs];
  1368. p2:=@s[1];
  1369. while (p2<=p) and (p^<>c) do dec(p);
  1370. RPosEx:=(p-p2)+1;
  1371. end
  1372. else
  1373. RPosEX:=0;
  1374. End;
  1375. Function RPos(c:char;const S : AnsiString):Integer; overload;
  1376. var I : Integer;
  1377. p,p2: pChar;
  1378. Begin
  1379. I:=Length(S);
  1380. If I<>0 Then
  1381. begin
  1382. p:=@s[i];
  1383. p2:=@s[1];
  1384. while (p2<=p) and (p^<>c) do dec(p);
  1385. i:=p-p2+1;
  1386. end;
  1387. RPos:=i;
  1388. End;
  1389. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  1390. var
  1391. MaxLen,llen : Integer;
  1392. c : char;
  1393. pc,pc2 : pchar;
  1394. begin
  1395. rPos:=0;
  1396. llen:=Length(SubStr);
  1397. maxlen:=length(source);
  1398. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1399. begin
  1400. // i:=maxlen;
  1401. pc:=@source[maxlen];
  1402. pc2:=@source[llen-1];
  1403. c:=substr[llen];
  1404. while pc>=pc2 do
  1405. begin
  1406. if (c=pc^) and
  1407. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1408. begin
  1409. rPos:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1410. exit;
  1411. end;
  1412. dec(pc);
  1413. end;
  1414. end;
  1415. end;
  1416. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  1417. var
  1418. MaxLen,llen : Integer;
  1419. c : char;
  1420. pc,pc2 : pchar;
  1421. begin
  1422. rPosex:=0;
  1423. llen:=Length(SubStr);
  1424. maxlen:=length(source);
  1425. if SizeInt(offs)<maxlen then maxlen:=offs;
  1426. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1427. begin
  1428. // i:=maxlen;
  1429. pc:=@source[maxlen];
  1430. pc2:=@source[llen-1];
  1431. c:=substr[llen];
  1432. while pc>=pc2 do
  1433. begin
  1434. if (c=pc^) and
  1435. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1436. begin
  1437. rPosex:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1438. exit;
  1439. end;
  1440. dec(pc);
  1441. end;
  1442. end;
  1443. end;
  1444. // def from delphi.about.com:
  1445. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  1446. Const
  1447. HexDigits='0123456789ABCDEF';
  1448. var
  1449. i : longint;
  1450. begin
  1451. for i:=0 to binbufsize-1 do
  1452. begin
  1453. HexValue[0]:=hexdigits[1+((ord(binvalue^) shr 4))];
  1454. HexValue[1]:=hexdigits[1+((ord(binvalue^) and 15))];
  1455. inc(hexvalue,2);
  1456. inc(binvalue);
  1457. end;
  1458. end;
  1459. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  1460. // more complex, have to accept more than bintohex
  1461. // A..F    1000001
  1462. // a..f    1100001
  1463. // 0..9     110000
  1464. var i,j,h,l : integer;
  1465. begin
  1466. i:=binbufsize;
  1467. while (i>0) do
  1468. begin
  1469. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1470. h:=((ord(hexvalue^)+9) and 15)
  1471. else if hexvalue^ IN ['0'..'9'] then
  1472. h:=((ord(hexvalue^)) and 15)
  1473. else
  1474. break;
  1475. inc(hexvalue);
  1476. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1477. l:=(ord(hexvalue^)+9) and 15
  1478. else if hexvalue^ IN ['0'..'9'] then
  1479. l:=(ord(hexvalue^)) and 15
  1480. else
  1481. break;
  1482. j := l + (h shl 4);
  1483. inc(hexvalue);
  1484. binvalue^:=chr(j);
  1485. inc(binvalue);
  1486. dec(i);
  1487. end;
  1488. result:=binbufsize-i;
  1489. end;
  1490. function possetex (const c:TSysCharSet;const s : ansistring;count:Integer ):Integer;
  1491. var i,j:Integer;
  1492. begin
  1493. if pchar(pointer(s))=nil then
  1494. j:=0
  1495. else
  1496. begin
  1497. i:=length(s);
  1498. j:=count;
  1499. if j>i then
  1500. begin
  1501. result:=0;
  1502. exit;
  1503. end;
  1504. while (j<=i) and (not (s[j] in c)) do inc(j);
  1505. if (j>i) then
  1506. j:=0; // not found.
  1507. end;
  1508. result:=j;
  1509. end;
  1510. function posset (const c:TSysCharSet;const s : ansistring ):Integer;
  1511. begin
  1512. result:=possetex(c,s,1);
  1513. end;
  1514. function possetex (const c:string;const s : ansistring;count:Integer ):Integer;
  1515. var cset : TSysCharSet;
  1516. i : integer;
  1517. begin
  1518. cset:=[];
  1519. if length(c)>0 then
  1520. for i:=1 to length(c) do
  1521. include(cset,c[i]);
  1522. result:=possetex(cset,s,count);
  1523. end;
  1524. function posset (const c:string;const s : ansistring ):Integer;
  1525. var cset : TSysCharSet;
  1526. i : integer;
  1527. begin
  1528. cset:=[];
  1529. if length(c)>0 then
  1530. for i:=1 to length(c) do
  1531. include(cset,c[i]);
  1532. result:=possetex(cset,s,1);
  1533. end;
  1534. Procedure Removeleadingchars(VAR S : AnsiString; Const CSet:TSysCharset);
  1535. VAR I,J : Longint;
  1536. Begin
  1537. I:=Length(S);
  1538. IF (I>0) Then
  1539. Begin
  1540. J:=1;
  1541. While (J<=I) And (S[J] IN CSet) DO
  1542. INC(J);
  1543. IF J>1 Then
  1544. Delete(S,1,J-1);
  1545. End;
  1546. End;
  1547. function TrimLeftSet(const S: String;const CSet:TSysCharSet): String;
  1548. begin
  1549. result:=s;
  1550. removeleadingchars(result,cset);
  1551. end;
  1552. Procedure RemoveTrailingChars(VAR S : AnsiString;Const CSet:TSysCharset);
  1553. VAR I,J: LONGINT;
  1554. Begin
  1555. I:=Length(S);
  1556. IF (I>0) Then
  1557. Begin
  1558. J:=I;
  1559. While (j>0) and (S[J] IN CSet) DO DEC(J);
  1560. IF J<>I Then
  1561. SetLength(S,J);
  1562. End;
  1563. End;
  1564. Function TrimRightSet(const S: String;const CSet:TSysCharSet): String;
  1565. begin
  1566. result:=s;
  1567. RemoveTrailingchars(result,cset);
  1568. end;
  1569. Procedure RemovePadChars(VAR S : AnsiString;Const CSet:TSysCharset);
  1570. VAR I,J,K: LONGINT;
  1571. Begin
  1572. I:=Length(S);
  1573. IF (I>0) Then
  1574. Begin
  1575. J:=I;
  1576. While (j>0) and (S[J] IN CSet) DO DEC(J);
  1577. if j=0 Then
  1578. begin
  1579. s:='';
  1580. exit;
  1581. end;
  1582. k:=1;
  1583. While (k<=I) And (S[k] IN CSet) DO
  1584. INC(k);
  1585. IF k>1 Then
  1586. begin
  1587. move(s[k],s[1],j-k+1);
  1588. setlength(s,j-k+1);
  1589. end
  1590. else
  1591. setlength(s,j);
  1592. End;
  1593. End;
  1594. function TrimSet(const S: String;const CSet:TSysCharSet): String;
  1595. begin
  1596. result:=s;
  1597. RemovePadChars(result,cset);
  1598. end;
  1599. end.