strutils.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. {$mode objfpc}
  2. {$h+}
  3. {
  4. $Id$
  5. This file is part of the Free Pascal run time library.
  6. Copyright (c) 1999-2000 by the Free Pascal development team
  7. Delphi/Kylix compatibility unit: String handling routines.
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. unit strutils;
  15. interface
  16. uses
  17. SysUtils{, Types};
  18. { ---------------------------------------------------------------------
  19. Case sensitive 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;
  26. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  27. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  28. { ---------------------------------------------------------------------
  29. Case insensitive search/replace
  30. ---------------------------------------------------------------------}
  31. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  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;
  35. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  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;
  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;
  46. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  47. { ---------------------------------------------------------------------
  48. VB emulations.
  49. ---------------------------------------------------------------------}
  50. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  51. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  52. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  53. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  54. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  55. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  56. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  57. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  58. {$ifndef ver1_0}
  59. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  60. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  61. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  62. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  63. {$endif}
  64. { ---------------------------------------------------------------------
  65. Extended search and replace
  66. ---------------------------------------------------------------------}
  67. const
  68. { Default word delimiters are any character except the core alphanumerics. }
  69. WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  70. type
  71. TStringSeachOption = (soDown, soMatchCase, soWholeWord);
  72. TStringSearchOptions = set of TStringSeachOption;
  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; // ; Options: TStringSearchOptions = [soDown]
  75. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  76. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  77. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  78. { ---------------------------------------------------------------------
  79. Soundex Functions.
  80. ---------------------------------------------------------------------}
  81. type
  82. TSoundexLength = 1..MaxInt;
  83. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  84. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  85. type
  86. TSoundexIntLength = 1..8;
  87. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  88. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  89. Function DecodeSoundexInt(AValue: Integer): string;
  90. Function SoundexWord(const AText: string): Word;
  91. Function DecodeSoundexWord(AValue: Word): string;
  92. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  93. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  94. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  95. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  96. Function SoundexProc(const AText, AOther: string): Boolean;
  97. type
  98. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  99. Const
  100. AnsiResemblesProc: TCompareTextProc = @SoundexProc;
  101. implementation
  102. { ---------------------------------------------------------------------
  103. Auxiliary functions
  104. ---------------------------------------------------------------------}
  105. Procedure NotYetImplemented (FN : String);
  106. begin
  107. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  108. end;
  109. { ---------------------------------------------------------------------
  110. Case sensitive search/replace
  111. ---------------------------------------------------------------------}
  112. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  113. begin
  114. NotYetImplemented(' AnsiResemblesText');
  115. end;
  116. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  117. begin
  118. AnsiContainsText:=Pos(ASubText,AText)<>0;
  119. end;
  120. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  121. begin
  122. Result:=Copy(AText,1,Length(AsubText))=ASubText;
  123. end;
  124. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  125. begin
  126. result:=Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText))=asubtext;
  127. end;
  128. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  129. var iFrom, iTo: longint;
  130. begin
  131. iTo:=Pos(AFromText,AText);
  132. if iTo=0 then
  133. result:=AText
  134. else
  135. begin
  136. result:='';
  137. iFrom:=1;
  138. while (ito<>0) do
  139. begin
  140. result:=Result+Copy(AText,IFrom,Ito-IFrom+1)+AToText;
  141. ifrom:=ITo+Length(afromtext);
  142. ito:=Posex(Afromtext,atext,ifrom);
  143. end;
  144. if ifrom<=length(atext) then
  145. result:=result+copy(AText,ifrom, length(atext));
  146. end;
  147. end;
  148. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  149. var i : longint;
  150. begin
  151. result:=false;
  152. if high(AValues)=-1 Then exit;
  153. for i:=low(AValues) to High(Avalues) do
  154. if avalues[i]=atext Then
  155. result:=true;
  156. end;
  157. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  158. var i : longint;
  159. begin
  160. result:=-1;
  161. if high(AValues)=-1 Then exit;
  162. for i:=low(AValues) to High(Avalues) do
  163. if avalues[i]=atext Then
  164. exit(i); // make sure it is the first val.
  165. end;
  166. { ---------------------------------------------------------------------
  167. Case insensitive search/replace
  168. ---------------------------------------------------------------------}
  169. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  170. begin
  171. Result := Pos(ASubText,AText)<>0;
  172. end;
  173. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  174. begin
  175. Result := Pos(ASubText,AText)=1;
  176. end;
  177. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  178. begin
  179. Result := Pos(ASubText,AText)=(length(AText)-length(ASubText)+1);
  180. end;
  181. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  182. begin
  183. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  184. end;
  185. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  186. var
  187. counter: integer;
  188. begin
  189. counter := 0;
  190. {$ifdef INTERNLENGTH}
  191. while(counter < length(AValues)) do
  192. {$else}
  193. while(counter < high(AValues)+1) do
  194. {$endif}
  195. begin
  196. if(AText = AValues[counter]) then
  197. begin
  198. Result := true;
  199. exit;
  200. end;
  201. inc(counter);
  202. end;
  203. Result := false;
  204. end;
  205. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  206. var
  207. counter: integer;
  208. begin
  209. counter := 0;
  210. {$ifdef INTERNLENGTH}
  211. while(counter < length(AValues)) do
  212. {$else}
  213. while(counter < high(AValues)+1) do
  214. {$endif}
  215. begin
  216. if(AText = AValues[counter]) then
  217. begin
  218. Result := counter;
  219. exit;
  220. end;
  221. inc(counter);
  222. end;
  223. Result := -1;
  224. end;
  225. { ---------------------------------------------------------------------
  226. Playthingies
  227. ---------------------------------------------------------------------}
  228. Function DupeString(const AText: string; ACount: Integer): string;
  229. var i,l : integer;
  230. begin
  231. result:='';
  232. if aCount>=0 then
  233. begin
  234. l:=length(atext);
  235. SetLength(result,aCount*l);
  236. for i:=0 to ACount-1 do
  237. move(atext[1],Result[l*i+1],l);
  238. end;
  239. end;
  240. Function ReverseString(const AText: string): string;
  241. var c: char;
  242. i,j:longint;
  243. begin
  244. setlength(result,length(atext));
  245. i:=1; j:=length(atext);
  246. while (i<=j) do
  247. begin
  248. result[i]:=atext[j-i+1];
  249. inc(i);
  250. end;
  251. end;
  252. Function AnsiReverseString(const AText: AnsiString): AnsiString;
  253. begin
  254. NotYetImplemented(' AnsiReverseString');
  255. end;
  256. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  257. var i,j : longint;
  258. begin
  259. j:=length(ASubText);
  260. i:=length(AText);
  261. SetLength(Result,i-ALength+j);
  262. move (AText[1],result[1],AStart-1);
  263. move (ASubText[1],result[AStart],j);
  264. move (AText[AStart+ALength], Result[AStart+j],i-AStart-ALength+1);
  265. end;
  266. Function RandomFrom(const AValues: array of string): string; overload;
  267. begin
  268. if high(AValues)=-1 then exit('');
  269. result:=Avalues[random(High(AValues)+1)];
  270. end;
  271. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
  272. begin
  273. if avalue then result:=atrue else result:=afalse;
  274. end;
  275. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  276. begin
  277. if avalue then result:=atrue else result:='';
  278. end;
  279. { ---------------------------------------------------------------------
  280. VB emulations.
  281. ---------------------------------------------------------------------}
  282. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  283. begin
  284. Result:=Copy(AText,1,ACount);
  285. end;
  286. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  287. var j,l:integer;
  288. begin
  289. l:=length(atext);
  290. j:=ACount;
  291. if j>l then j:=l;
  292. Result:=Copy(AText,l-j+1,j);
  293. end;
  294. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  295. begin
  296. if (ACount=0) or (AStart>length(atext)) then
  297. exit('');
  298. Result:=Copy(AText,AStart,ACount);
  299. end;
  300. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  301. begin
  302. NotYetImplemented(' LeftBStr');
  303. end;
  304. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  305. begin
  306. NotYetImplemented(' RightBStr');
  307. end;
  308. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  309. begin
  310. NotYetImplemented(' MidBStr');
  311. end;
  312. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  313. begin
  314. Result := copy(AText,1,ACount);
  315. end;
  316. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  317. begin
  318. Result := copy(AText,length(AText)-ACount+1,ACount);
  319. end;
  320. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  321. begin
  322. NotYetImplemented(' AnsiMidStr');
  323. end;
  324. {$ifndef ver1_0}
  325. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  326. begin
  327. NotYetImplemented(' LeftStr');
  328. end;
  329. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  330. begin
  331. NotYetImplemented(' RightStr');
  332. end;
  333. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  334. begin
  335. NotYetImplemented(' MidStr');
  336. end;
  337. {$endif}
  338. { ---------------------------------------------------------------------
  339. Extended search and replace
  340. ---------------------------------------------------------------------}
  341. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  342. begin
  343. NotYetImplemented(' SearchBuf');
  344. end;
  345. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  346. begin
  347. NotYetImplemented(' SearchBuf');
  348. end;
  349. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  350. var i : pchar;
  351. begin
  352. if (offset<1) or (offset>length(s)) then exit(0);
  353. i:=strpos(@s[offset],@substr[1]);
  354. if i=nil then
  355. PosEx:=0
  356. else
  357. PosEx:=succ(i-pchar(s));
  358. end;
  359. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  360. begin
  361. posex:=posex(substr,s,1);
  362. end;
  363. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  364. var l : longint;
  365. begin
  366. if (offset<1) or (offset>length(s)) then exit(0);
  367. l:=length(s);
  368. {$ifndef useindexbyte}
  369. while (offset<=l) and (s[offset]<>c) do inc(offset);
  370. if offset>l then
  371. posex:=0
  372. else
  373. posex:=offset;
  374. {$else}
  375. posex:=offset+indexbyte(s[offset],l-offset+1);
  376. if posex=(offset-1) then
  377. posex:=0;
  378. {$endif}
  379. end;
  380. { ---------------------------------------------------------------------
  381. Soundex Functions.
  382. ---------------------------------------------------------------------}
  383. Const
  384. SScore : array[1..255] of Char =
  385. ('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
  386. '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
  387. '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
  388. '0','0','0','0','0','0', // 91..95
  389. '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
  390. '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
  391. '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
  392. '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
  393. '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
  394. '0','0','0','0','0'); // 251..255
  395. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  396. Var
  397. S,PS : Char;
  398. I,L : integer;
  399. begin
  400. Result:='';
  401. PS:=#0;
  402. If Length(AText)>0 then
  403. begin
  404. Result:=Upcase(AText[1]);
  405. I:=2;
  406. L:=Length(AText);
  407. While (I<=L) and (Length(Result)<ALength) do
  408. begin
  409. S:=SScore[Ord(AText[i])];
  410. If Not (S in ['0','i',PS]) then
  411. Result:=Result+S;
  412. If (S<>'i') then
  413. PS:=S;
  414. Inc(I);
  415. end;
  416. end;
  417. L:=Length(Result);
  418. If (L<ALength) then
  419. Result:=Result+StringOfChar('0',Alength-L);
  420. end;
  421. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  422. begin
  423. Result:=Soundex(AText,4);
  424. end;
  425. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  426. begin
  427. NotYetImplemented(' SoundexInt');
  428. end;
  429. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  430. begin
  431. NotYetImplemented(' SoundexInt');
  432. end;
  433. Function DecodeSoundexInt(AValue: Integer): string;
  434. begin
  435. NotYetImplemented(' DecodeSoundexInt');
  436. end;
  437. Function SoundexWord(const AText: string): Word;
  438. Var
  439. S : String;
  440. begin
  441. S:=SoundEx(Atext,4);
  442. Writeln('Soundex result : "',S,'"');
  443. Result:=Ord(S[1])-Ord('A');
  444. Result:=Result*26+StrToInt(S[2]);
  445. Result:=Result*7+StrToInt(S[3]);
  446. Result:=Result*7+StrToInt(S[4]);
  447. end;
  448. Function DecodeSoundexWord(AValue: Word): string;
  449. begin
  450. NotYetImplemented(' DecodeSoundexWord');
  451. end;
  452. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  453. begin
  454. NotYetImplemented(' SoundexSimilar');
  455. end;
  456. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  457. begin
  458. NotYetImplemented(' SoundexSimilar');
  459. end;
  460. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  461. begin
  462. NotYetImplemented(' SoundexCompare');
  463. end;
  464. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  465. begin
  466. NotYetImplemented(' SoundexCompare');
  467. end;
  468. Function SoundexProc(const AText, AOther: string): Boolean;
  469. begin
  470. NotYetImplemented(' SoundexProc');
  471. end;
  472. end.
  473. {
  474. $Log$
  475. Revision 1.7 2004-07-01 15:42:18 peter
  476. * fix 1.0.x compile
  477. Revision 1.6 2004/06/29 19:37:17 marco
  478. * updates from B. Tierens
  479. Revision 1.5 2004/05/17 07:33:01 marco
  480. * fixes from Luiz Am?rico
  481. Revision 1.4 2004/03/19 12:54:22 marco
  482. * more strutils small things
  483. Revision 1.3 2004/03/18 16:55:47 marco
  484. * more simple implementations done, based on copy() Largely untested
  485. }