2
0

strutils.pp 48 KB

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