strutils.pp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  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. { ---------------------------------------------------------------------
  102. Other functions, based on RxStrUtils.
  103. ---------------------------------------------------------------------}
  104. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  105. function DelSpace(const S: string): string;
  106. function DelChars(const S: string; Chr: Char): string;
  107. function DelSpace1(const S: string): string;
  108. function Tab2Space(const S: string; Numb: Byte): string;
  109. function NPos(const C: string; S: string; N: Integer): Integer;
  110. function AddChar(C: Char; const S: string; N: Integer): string;
  111. function AddCharR(C: Char; const S: string; N: Integer): string;
  112. function PadLeft(const S: string; N: Integer): string;
  113. function PadRight(const S: string; N: Integer): string;
  114. function PadCenter(const S: string; Len: Integer): string;
  115. function Copy2Symb(const S: string; Symb: Char): string;
  116. function Copy2SymbDel(var S: string; Symb: Char): string;
  117. function Copy2Space(const S: string): string;
  118. function Copy2SpaceDel(var S: string): string;
  119. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  120. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  121. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  122. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  123. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  124. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  125. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  126. function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  127. function FindPart(const HelpWilds, InputStr: string): Integer;
  128. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  129. function XorString(const Key, Src: ShortString): ShortString;
  130. function XorEncode(const Key, Source: string): string;
  131. function XorDecode(const Key, Source: string): string;
  132. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  133. function Numb2USA(const S: string): string;
  134. function Hex2Dec(const S: string): Longint;
  135. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  136. function Numb2Dec(S: string; Base: Byte): Longint;
  137. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  138. function IntToRoman(Value: Longint): string;
  139. function RomanToInt(const S: string): Longint;
  140. const
  141. DigitChars = ['0'..'9'];
  142. Brackets = ['(',')','[',']','{','}'];
  143. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  144. implementation
  145. { ---------------------------------------------------------------------
  146. Auxiliary functions
  147. ---------------------------------------------------------------------}
  148. Procedure NotYetImplemented (FN : String);
  149. begin
  150. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  151. end;
  152. { ---------------------------------------------------------------------
  153. Case sensitive search/replace
  154. ---------------------------------------------------------------------}
  155. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  156. begin
  157. NotYetImplemented(' AnsiResemblesText');
  158. end;
  159. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  160. begin
  161. AnsiContainsText:=Pos(ASubText,AText)<>0;
  162. end;
  163. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  164. begin
  165. Result:=Copy(AText,1,Length(AsubText))=ASubText;
  166. end;
  167. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  168. begin
  169. result:=Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText))=asubtext;
  170. end;
  171. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  172. var iFrom, iTo: longint;
  173. begin
  174. iTo:=Pos(AFromText,AText);
  175. if iTo=0 then
  176. result:=AText
  177. else
  178. begin
  179. result:='';
  180. iFrom:=1;
  181. while (ito<>0) do
  182. begin
  183. result:=Result+Copy(AText,IFrom,Ito-IFrom+1)+AToText;
  184. ifrom:=ITo+Length(afromtext);
  185. ito:=Posex(Afromtext,atext,ifrom);
  186. end;
  187. if ifrom<=length(atext) then
  188. result:=result+copy(AText,ifrom, length(atext));
  189. end;
  190. end;
  191. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  192. var i : longint;
  193. begin
  194. result:=false;
  195. if high(AValues)=-1 Then exit;
  196. for i:=low(AValues) to High(Avalues) do
  197. if avalues[i]=atext Then
  198. result:=true;
  199. end;
  200. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  201. var i : longint;
  202. begin
  203. result:=-1;
  204. if high(AValues)=-1 Then exit;
  205. for i:=low(AValues) to High(Avalues) do
  206. if avalues[i]=atext Then
  207. exit(i); // make sure it is the first val.
  208. end;
  209. { ---------------------------------------------------------------------
  210. Case insensitive search/replace
  211. ---------------------------------------------------------------------}
  212. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  213. begin
  214. Result := Pos(ASubText,AText)<>0;
  215. end;
  216. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  217. begin
  218. Result := Pos(ASubText,AText)=1;
  219. end;
  220. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  221. begin
  222. Result := Pos(ASubText,AText)=(length(AText)-length(ASubText)+1);
  223. end;
  224. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  225. begin
  226. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  227. end;
  228. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  229. var
  230. counter: integer;
  231. begin
  232. counter := 0;
  233. {$ifdef INTERNLENGTH}
  234. while(counter < length(AValues)) do
  235. {$else}
  236. while(counter < high(AValues)+1) do
  237. {$endif}
  238. begin
  239. if(AText = AValues[counter]) then
  240. begin
  241. Result := true;
  242. exit;
  243. end;
  244. inc(counter);
  245. end;
  246. Result := false;
  247. end;
  248. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  249. var
  250. counter: integer;
  251. begin
  252. counter := 0;
  253. {$ifdef INTERNLENGTH}
  254. while(counter < length(AValues)) do
  255. {$else}
  256. while(counter < high(AValues)+1) do
  257. {$endif}
  258. begin
  259. if(AText = AValues[counter]) then
  260. begin
  261. Result := counter;
  262. exit;
  263. end;
  264. inc(counter);
  265. end;
  266. Result := -1;
  267. end;
  268. { ---------------------------------------------------------------------
  269. Playthingies
  270. ---------------------------------------------------------------------}
  271. Function DupeString(const AText: string; ACount: Integer): string;
  272. var i,l : integer;
  273. begin
  274. result:='';
  275. if aCount>=0 then
  276. begin
  277. l:=length(atext);
  278. SetLength(result,aCount*l);
  279. for i:=0 to ACount-1 do
  280. move(atext[1],Result[l*i+1],l);
  281. end;
  282. end;
  283. Function ReverseString(const AText: string): string;
  284. var c: char;
  285. i,j:longint;
  286. begin
  287. setlength(result,length(atext));
  288. i:=1; j:=length(atext);
  289. while (i<=j) do
  290. begin
  291. result[i]:=atext[j-i+1];
  292. inc(i);
  293. end;
  294. end;
  295. Function AnsiReverseString(const AText: AnsiString): AnsiString;
  296. begin
  297. NotYetImplemented(' AnsiReverseString');
  298. end;
  299. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  300. var i,j : longint;
  301. begin
  302. j:=length(ASubText);
  303. i:=length(AText);
  304. SetLength(Result,i-ALength+j);
  305. move (AText[1],result[1],AStart-1);
  306. move (ASubText[1],result[AStart],j);
  307. move (AText[AStart+ALength], Result[AStart+j],i-AStart-ALength+1);
  308. end;
  309. Function RandomFrom(const AValues: array of string): string; overload;
  310. begin
  311. if high(AValues)=-1 then exit('');
  312. result:=Avalues[random(High(AValues)+1)];
  313. end;
  314. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
  315. begin
  316. if avalue then result:=atrue else result:=afalse;
  317. end;
  318. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  319. begin
  320. if avalue then result:=atrue else result:='';
  321. end;
  322. { ---------------------------------------------------------------------
  323. VB emulations.
  324. ---------------------------------------------------------------------}
  325. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  326. begin
  327. Result:=Copy(AText,1,ACount);
  328. end;
  329. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  330. var j,l:integer;
  331. begin
  332. l:=length(atext);
  333. j:=ACount;
  334. if j>l then j:=l;
  335. Result:=Copy(AText,l-j+1,j);
  336. end;
  337. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  338. begin
  339. if (ACount=0) or (AStart>length(atext)) then
  340. exit('');
  341. Result:=Copy(AText,AStart,ACount);
  342. end;
  343. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  344. begin
  345. NotYetImplemented(' LeftBStr');
  346. end;
  347. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  348. begin
  349. NotYetImplemented(' RightBStr');
  350. end;
  351. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  352. begin
  353. NotYetImplemented(' MidBStr');
  354. end;
  355. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  356. begin
  357. Result := copy(AText,1,ACount);
  358. end;
  359. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  360. begin
  361. Result := copy(AText,length(AText)-ACount+1,ACount);
  362. end;
  363. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  364. begin
  365. NotYetImplemented(' AnsiMidStr');
  366. end;
  367. {$ifndef ver1_0}
  368. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  369. begin
  370. NotYetImplemented(' LeftStr');
  371. end;
  372. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  373. begin
  374. NotYetImplemented(' RightStr');
  375. end;
  376. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  377. begin
  378. NotYetImplemented(' MidStr');
  379. end;
  380. {$endif}
  381. { ---------------------------------------------------------------------
  382. Extended search and replace
  383. ---------------------------------------------------------------------}
  384. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  385. begin
  386. NotYetImplemented(' SearchBuf');
  387. end;
  388. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  389. begin
  390. NotYetImplemented(' SearchBuf');
  391. end;
  392. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  393. var i : pchar;
  394. begin
  395. if (offset<1) or (offset>length(s)) then exit(0);
  396. i:=strpos(@s[offset],@substr[1]);
  397. if i=nil then
  398. PosEx:=0
  399. else
  400. PosEx:=succ(i-pchar(s));
  401. end;
  402. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  403. begin
  404. posex:=posex(substr,s,1);
  405. end;
  406. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  407. var l : longint;
  408. begin
  409. if (offset<1) or (offset>length(s)) then exit(0);
  410. l:=length(s);
  411. {$ifndef useindexbyte}
  412. while (offset<=l) and (s[offset]<>c) do inc(offset);
  413. if offset>l then
  414. posex:=0
  415. else
  416. posex:=offset;
  417. {$else}
  418. posex:=offset+indexbyte(s[offset],l-offset+1);
  419. if posex=(offset-1) then
  420. posex:=0;
  421. {$endif}
  422. end;
  423. { ---------------------------------------------------------------------
  424. Soundex Functions.
  425. ---------------------------------------------------------------------}
  426. Const
  427. SScore : array[1..255] of Char =
  428. ('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
  429. '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
  430. '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
  431. '0','0','0','0','0','0', // 91..95
  432. '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
  433. '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
  434. '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
  435. '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
  436. '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
  437. '0','0','0','0','0'); // 251..255
  438. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  439. Var
  440. S,PS : Char;
  441. I,L : integer;
  442. begin
  443. Result:='';
  444. PS:=#0;
  445. If Length(AText)>0 then
  446. begin
  447. Result:=Upcase(AText[1]);
  448. I:=2;
  449. L:=Length(AText);
  450. While (I<=L) and (Length(Result)<ALength) do
  451. begin
  452. S:=SScore[Ord(AText[i])];
  453. If Not (S in ['0','i',PS]) then
  454. Result:=Result+S;
  455. If (S<>'i') then
  456. PS:=S;
  457. Inc(I);
  458. end;
  459. end;
  460. L:=Length(Result);
  461. If (L<ALength) then
  462. Result:=Result+StringOfChar('0',Alength-L);
  463. end;
  464. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  465. begin
  466. Result:=Soundex(AText,4);
  467. end;
  468. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  469. begin
  470. NotYetImplemented(' SoundexInt');
  471. end;
  472. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  473. begin
  474. NotYetImplemented(' SoundexInt');
  475. end;
  476. Function DecodeSoundexInt(AValue: Integer): string;
  477. begin
  478. NotYetImplemented(' DecodeSoundexInt');
  479. end;
  480. Function SoundexWord(const AText: string): Word;
  481. Var
  482. S : String;
  483. begin
  484. S:=SoundEx(Atext,4);
  485. Writeln('Soundex result : "',S,'"');
  486. Result:=Ord(S[1])-Ord('A');
  487. Result:=Result*26+StrToInt(S[2]);
  488. Result:=Result*7+StrToInt(S[3]);
  489. Result:=Result*7+StrToInt(S[4]);
  490. end;
  491. Function DecodeSoundexWord(AValue: Word): string;
  492. begin
  493. NotYetImplemented(' DecodeSoundexWord');
  494. end;
  495. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  496. begin
  497. NotYetImplemented(' SoundexSimilar');
  498. end;
  499. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  500. begin
  501. NotYetImplemented(' SoundexSimilar');
  502. end;
  503. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  504. begin
  505. NotYetImplemented(' SoundexCompare');
  506. end;
  507. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  508. begin
  509. NotYetImplemented(' SoundexCompare');
  510. end;
  511. Function SoundexProc(const AText, AOther: string): Boolean;
  512. begin
  513. NotYetImplemented(' SoundexProc');
  514. end;
  515. { ---------------------------------------------------------------------
  516. RxStrUtils-like functions.
  517. ---------------------------------------------------------------------}
  518. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  519. var
  520. i,l: Integer;
  521. begin
  522. l:=Length(S);
  523. i:=1;
  524. Result:=True;
  525. while Result and (i<=l) do
  526. begin
  527. Result:=Not (S[i] in EmptyChars);
  528. Inc(i);
  529. end;
  530. end;
  531. function DelSpace(const S: String): string;
  532. begin
  533. Result:=DelChars(S,' ');
  534. end;
  535. function DelChars(const S: string; Chr: Char): string;
  536. var
  537. I,J: Integer;
  538. begin
  539. Result:=S;
  540. I:=Length(Result);
  541. While I>0 do
  542. begin
  543. if Result[I]=Chr then
  544. begin
  545. J:=I-1;
  546. While (J>0) and (Result[J]=Chr) do
  547. Dec(j);
  548. Delete(Result,J+1,I-J);
  549. I:=J+1;
  550. end;
  551. dec(I);
  552. end;
  553. end;
  554. function DelSpace1(const S: string): string;
  555. var
  556. i: Integer;
  557. begin
  558. Result:=S;
  559. for i:=Length(Result) downto 2 do
  560. if (Result[i]=' ') and (Result[I-1]=' ') then
  561. Delete(Result,I,1);
  562. end;
  563. function Tab2Space(const S: string; Numb: Byte): string;
  564. var
  565. I: Integer;
  566. begin
  567. I:=1;
  568. Result:=S;
  569. while I <= Length(Result) do
  570. if Result[I]<>Chr(9) then
  571. inc(I)
  572. else
  573. begin
  574. Result[I]:=' ';
  575. If (Numb>1) then
  576. Insert(StringOfChar('0',Numb-1),Result,I);
  577. Inc(I,Numb);
  578. end;
  579. end;
  580. function NPos(const C: string; S: string; N: Integer): Integer;
  581. var
  582. i,p,k: Integer;
  583. begin
  584. Result:=0;
  585. if N<1 then
  586. Exit;
  587. k:=0;
  588. i:=1;
  589. Repeat
  590. p:=pos(C,S);
  591. Inc(k,p);
  592. if p>0 then
  593. delete(S,1,p);
  594. Inc(i);
  595. Until (i>n) or (p=0);
  596. If (P>0) then
  597. Result:=K;
  598. end;
  599. function AddChar(C: Char; const S: string; N: Integer): string;
  600. Var
  601. l : Integer;
  602. begin
  603. Result:=S;
  604. l:=Length(Result);
  605. if l<N then
  606. Result:=StringOfChar(C,N-l)+Result;
  607. end;
  608. function AddCharR(C: Char; const S: string; N: Integer): string;
  609. Var
  610. l : Integer;
  611. begin
  612. Result:=S;
  613. l:=Length(Result);
  614. if l<N then
  615. Result:=Result+StringOfChar(C,N-l);
  616. end;
  617. function PadRight(const S: string; N: Integer): string;
  618. begin
  619. Result:=AddCharR(' ',S,N);
  620. end;
  621. function PadLeft(const S: string; N: Integer): string;
  622. begin
  623. Result:=AddChar(' ',S,N);
  624. end;
  625. function Copy2Symb(const S: string; Symb: Char): string;
  626. var
  627. p: Integer;
  628. begin
  629. p:=Pos(Symb,S);
  630. if p=0 then
  631. p:=Length(S)+1;
  632. Result:=Copy(S,1,p-1);
  633. end;
  634. function Copy2SymbDel(var S: string; Symb: Char): string;
  635. begin
  636. Result:=Copy2Symb(S,Symb);
  637. S:=TrimRight(Copy(S,Length(Result)+1,Length(S)));
  638. end;
  639. function Copy2Space(const S: string): string;
  640. begin
  641. Result:=Copy2Symb(S,' ');
  642. end;
  643. function Copy2SpaceDel(var S: string): string;
  644. begin
  645. Result:=Copy2SymbDel(S,' ');
  646. end;
  647. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  648. var
  649. l : Integer;
  650. P,PE : PChar;
  651. begin
  652. Result:=AnsiLowerCase(S);
  653. P:=PChar(Result);
  654. PE:=P+Length(Result);
  655. while (P<PE) do
  656. begin
  657. while (P<PE) and (P^ in WordDelims) do
  658. inc(P);
  659. if (P<PE) then
  660. P^:=UpCase(P^);
  661. while (P<PE) and not (P^ in WordDelims) do
  662. inc(P);
  663. end;
  664. end;
  665. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  666. var
  667. P,PE : PChar;
  668. begin
  669. Result:=0;
  670. P:=Pchar(S);
  671. PE:=P+Length(S);
  672. while (P<PE) do
  673. begin
  674. while (P<PE) and (P^ in WordDelims) do
  675. Inc(P);
  676. if (P<PE) then
  677. inc(Result);
  678. while (P<PE) and not (P^ in WordDelims) do
  679. inc(P);
  680. end;
  681. end;
  682. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  683. var
  684. PS,P,PE : PChar;
  685. Count: Integer;
  686. begin
  687. Result:=0;
  688. Count:=0;
  689. PS:=PChar(S);
  690. PE:=PS+Length(S);
  691. P:=PS;
  692. while (P<PE) and (Count<>N) do
  693. begin
  694. while (P<PE) and (P^ in WordDelims) do
  695. inc(P);
  696. if (P<PE) then
  697. inc(Count);
  698. if (Count<>N) then
  699. while (P<PE) and not (P^ in WordDelims) do
  700. inc(P)
  701. else
  702. Result:=(P-PS)+1;
  703. end;
  704. end;
  705. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  706. var
  707. i: Integer;
  708. begin
  709. Result:=ExtractWordPos(N,S,WordDelims,i);
  710. end;
  711. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  712. var
  713. i,j,l: Integer;
  714. begin
  715. j:=0;
  716. i:=WordPosition(N, S, WordDelims);
  717. Pos:=i;
  718. if (i<>0) then
  719. begin
  720. j:=i;
  721. l:=Length(S);
  722. while (j<=L) and not (S[j] in WordDelims) do
  723. inc(j);
  724. end;
  725. SetLength(Result,j-i);
  726. If ((j-i)>0) then
  727. Move(S[i],Result[1],j-i);
  728. end;
  729. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  730. var
  731. w,i,l,len: Integer;
  732. begin
  733. w:=0;
  734. i:=1;
  735. l:=0;
  736. len:=Length(S);
  737. SetLength(Result, 0);
  738. while (i<=len) and (w<>N) do
  739. begin
  740. if s[i] in Delims then
  741. inc(w)
  742. else
  743. begin
  744. if (N-1)=w then
  745. begin
  746. inc(l);
  747. SetLength(Result,l);
  748. Result[Len]:=S[i];
  749. end;
  750. end;
  751. inc(i);
  752. end;
  753. end;
  754. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  755. var
  756. i,l: Integer;
  757. begin
  758. i:=Pos;
  759. l:=Length(S);
  760. while (i<=l) and not (S[i] in Delims) do
  761. inc(i);
  762. Result:=Copy(S,Pos,i-Pos);
  763. if (i<=l) and (S[i] in Delims) then
  764. inc(i);
  765. Pos:=i;
  766. end;
  767. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  768. var
  769. i,Count : Integer;
  770. begin
  771. Result:=False;
  772. Count:=WordCount(S, WordDelims);
  773. I:=1;
  774. While (Not Result) and (I<=Count) do
  775. Result:=ExtractWord(i,S,WordDelims)=W;
  776. end;
  777. function Numb2USA(const S: string): string;
  778. var
  779. i, NA: Integer;
  780. begin
  781. i:=Length(S);
  782. Result:=S;
  783. NA:=0;
  784. while (i > 0) do begin
  785. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  786. begin
  787. insert(',', Result, i);
  788. inc(NA);
  789. end;
  790. Dec(i);
  791. end;
  792. end;
  793. function PadCenter(const S: string; Len: Integer): string;
  794. begin
  795. if Length(S)<Len then
  796. begin
  797. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  798. Result:=Result+StringOfChar(' ',Len-Length(Result));
  799. end
  800. else
  801. Result:=S;
  802. end;
  803. function Hex2Dec(const S: string): Longint;
  804. var
  805. HexStr: string;
  806. begin
  807. if Pos('$',S)=0 then
  808. HexStr:='$'+ S
  809. else
  810. HexStr:=S;
  811. Result:=StrTointDef(HexStr,0);
  812. end;
  813. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  814. var
  815. C: Integer;
  816. Number: Longint;
  817. begin
  818. if N=0 then
  819. Result:='0'
  820. else
  821. begin
  822. Number:=N;
  823. Result:='';
  824. while Number>0 do
  825. begin
  826. C:=Number mod Base;
  827. if C>9 then
  828. C:=C+55
  829. else
  830. C:=C+48;
  831. Result:=Chr(C)+Result;
  832. Number:=Number div Base;
  833. end;
  834. end;
  835. if (Result<>'') then
  836. Result:=AddChar('0',Result,Len);
  837. end;
  838. function Numb2Dec(S: string; Base: Byte): Longint;
  839. var
  840. i, P: Longint;
  841. begin
  842. i:=Length(S);
  843. Result:=0;
  844. S:=UpperCase(S);
  845. P:=1;
  846. while (i>=1) do
  847. begin
  848. if (S[i]>'@') then
  849. Result:=Result+(Ord(S[i])-55)*P
  850. else
  851. Result:=Result+(Ord(S[i])-48)*P;
  852. Dec(i);
  853. P:=P*Base;
  854. end;
  855. end;
  856. function RomanToint(const S: string): Longint;
  857. const
  858. RomanChars = ['C','D','i','L','M','V','X'];
  859. RomanValues : array['C'..'X'] of Word
  860. = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
  861. var
  862. index, Next: Char;
  863. i,l: Integer;
  864. Negative: Boolean;
  865. begin
  866. Result:=0;
  867. i:=0;
  868. Negative:=(Length(S)>0) and (S[1]='-');
  869. if Negative then
  870. inc(i);
  871. l:=Length(S);
  872. while (i<l) do
  873. begin
  874. inc(i);
  875. index:=UpCase(S[i]);
  876. if index in RomanChars then
  877. begin
  878. if Succ(i)<=l then
  879. Next:=UpCase(S[i+1])
  880. else
  881. Next:=#0;
  882. if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
  883. begin
  884. inc(Result, RomanValues[Next]);
  885. Dec(Result, RomanValues[index]);
  886. inc(i);
  887. end
  888. else
  889. inc(Result, RomanValues[index]);
  890. end
  891. else
  892. begin
  893. Result:=0;
  894. Exit;
  895. end;
  896. end;
  897. if Negative then
  898. Result:=-Result;
  899. end;
  900. function intToRoman(Value: Longint): string;
  901. const
  902. Arabics : Array[1..13] of Integer
  903. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  904. Romans : Array[1..13] of String
  905. = ('i','iV','V','iX','X','XL','L','XC','C','CD','D','CM','M');
  906. var
  907. i: Integer;
  908. begin
  909. for i:=13 downto 1 do
  910. while (Value >= Arabics[i]) do
  911. begin
  912. Value:=Value-Arabics[i];
  913. Result:=Result+Romans[i];
  914. end;
  915. end;
  916. function intToBin(Value: Longint; Digits, Spaces: Integer): string;
  917. begin
  918. Result:='';
  919. if (Digits>32) then
  920. Digits:=32;
  921. while (Digits>0) do
  922. begin
  923. if (Digits mod Spaces)=0 then
  924. Result:=Result+' ';
  925. Dec(Digits);
  926. Result:=Result+intToStr((Value shr Digits) and 1);
  927. end;
  928. end;
  929. function FindPart(const HelpWilds, inputStr: string): Integer;
  930. var
  931. i, J: Integer;
  932. Diff: Integer;
  933. begin
  934. Result:=0;
  935. i:=Pos('?',HelpWilds);
  936. if (i=0) then
  937. Result:=Pos(HelpWilds, inputStr)
  938. else
  939. begin
  940. Diff:=Length(inputStr) - Length(HelpWilds);
  941. for i:=0 to Diff do
  942. begin
  943. for J:=1 to Length(HelpWilds) do
  944. if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
  945. begin
  946. if (J=Length(HelpWilds)) then
  947. begin
  948. Result:=i+1;
  949. Exit;
  950. end;
  951. end
  952. else
  953. Break;
  954. end;
  955. end;
  956. end;
  957. function isWild(inputStr, Wilds: string; ignoreCase: Boolean): Boolean;
  958. function SearchNext(var Wilds: string): Integer;
  959. begin
  960. Result:=Pos('*', Wilds);
  961. if Result>0 then
  962. Wilds:=Copy(Wilds,1,Result - 1);
  963. end;
  964. var
  965. CWild, CinputWord: Integer; { counter for positions }
  966. i, LenHelpWilds: Integer;
  967. MaxinputWord, MaxWilds: Integer; { Length of inputStr and Wilds }
  968. HelpWilds: string;
  969. begin
  970. if Wilds = inputStr then begin
  971. Result:=True;
  972. Exit;
  973. end;
  974. repeat { delete '**', because '**' = '*' }
  975. i:=Pos('**', Wilds);
  976. if i > 0 then
  977. Wilds:=Copy(Wilds, 1, i - 1) + '*' + Copy(Wilds, i + 2, Maxint);
  978. until i = 0;
  979. if Wilds = '*' then begin { for fast end, if Wilds only '*' }
  980. Result:=True;
  981. Exit;
  982. end;
  983. MaxinputWord:=Length(inputStr);
  984. MaxWilds:=Length(Wilds);
  985. if ignoreCase then begin { upcase all letters }
  986. inputStr:=AnsiUpperCase(inputStr);
  987. Wilds:=AnsiUpperCase(Wilds);
  988. end;
  989. if (MaxWilds = 0) or (MaxinputWord = 0) then begin
  990. Result:=False;
  991. Exit;
  992. end;
  993. CinputWord:=1;
  994. CWild:=1;
  995. Result:=True;
  996. repeat
  997. if inputStr[CinputWord] = Wilds[CWild] then begin { equal letters }
  998. { goto next letter }
  999. inc(CWild);
  1000. inc(CinputWord);
  1001. Continue;
  1002. end;
  1003. if Wilds[CWild] = '?' then begin { equal to '?' }
  1004. { goto next letter }
  1005. inc(CWild);
  1006. inc(CinputWord);
  1007. Continue;
  1008. end;
  1009. if Wilds[CWild] = '*' then begin { handling of '*' }
  1010. HelpWilds:=Copy(Wilds, CWild + 1, MaxWilds);
  1011. i:=SearchNext(HelpWilds);
  1012. LenHelpWilds:=Length(HelpWilds);
  1013. if i = 0 then begin
  1014. { no '*' in the rest, compare the ends }
  1015. if HelpWilds = '' then Exit; { '*' is the last letter }
  1016. { check the rest for equal Length and no '?' }
  1017. for i:=0 to LenHelpWilds - 1 do begin
  1018. if (HelpWilds[LenHelpWilds - i] <> inputStr[MaxinputWord - i]) and
  1019. (HelpWilds[LenHelpWilds - i]<> '?') then
  1020. begin
  1021. Result:=False;
  1022. Exit;
  1023. end;
  1024. end;
  1025. Exit;
  1026. end;
  1027. { handle all to the next '*' }
  1028. inc(CWild, 1 + LenHelpWilds);
  1029. i:=FindPart(HelpWilds, Copy(inputStr, CinputWord, Maxint));
  1030. if i= 0 then begin
  1031. Result:=False;
  1032. Exit;
  1033. end;
  1034. CinputWord:=i + LenHelpWilds;
  1035. Continue;
  1036. end;
  1037. Result:=False;
  1038. Exit;
  1039. until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
  1040. { no completed evaluation }
  1041. if CinputWord <= MaxinputWord then Result:=False;
  1042. if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then Result:=False;
  1043. end;
  1044. function XorString(const Key, Src: ShortString): ShortString;
  1045. var
  1046. i: Integer;
  1047. begin
  1048. Result:=Src;
  1049. if Length(Key) > 0 then
  1050. for i:=1 to Length(Src) do
  1051. Result[i]:=Chr(Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
  1052. end;
  1053. function XorEncode(const Key, Source: string): string;
  1054. var
  1055. i: Integer;
  1056. C: Byte;
  1057. begin
  1058. Result:='';
  1059. for i:=1 to Length(Source) do
  1060. begin
  1061. if Length(Key) > 0 then
  1062. C:=Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Byte(Source[i])
  1063. else
  1064. C:=Byte(Source[i]);
  1065. Result:=Result+AnsiLowerCase(intToHex(C, 2));
  1066. end;
  1067. end;
  1068. function XorDecode(const Key, Source: string): string;
  1069. var
  1070. i: Integer;
  1071. C: Char;
  1072. begin
  1073. Result:='';
  1074. for i:=0 to Length(Source) div 2 - 1 do
  1075. begin
  1076. C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
  1077. if Length(Key) > 0 then
  1078. C:=Chr(Byte(Key[1 + (i mod Length(Key))]) xor Byte(C));
  1079. Result:=Result + C;
  1080. end;
  1081. end;
  1082. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  1083. var
  1084. i: Integer;
  1085. S: string;
  1086. begin
  1087. i:=1;
  1088. Result:='';
  1089. while (Result='') and (i<=ParamCount) do
  1090. begin
  1091. S:=ParamStr(i);
  1092. if (SwitchChars=[]) or ((S[1] in SwitchChars) and (Length(S) > 1)) and
  1093. (AnsiCompareText(Copy(S,2,Length(S)-1),Switch)=0) then
  1094. begin
  1095. inc(i);
  1096. if i<=ParamCount then
  1097. Result:=ParamStr(i);
  1098. end;
  1099. inc(i);
  1100. end;
  1101. end;
  1102. end.
  1103. {
  1104. $Log$
  1105. Revision 1.8 2004-07-13 18:42:39 michael
  1106. + Added some RxStrUtils functions for Rx compatibility
  1107. Revision 1.7 2004/07/01 15:42:18 peter
  1108. * fix 1.0.x compile
  1109. Revision 1.6 2004/06/29 19:37:17 marco
  1110. * updates from B. Tierens
  1111. Revision 1.5 2004/05/17 07:33:01 marco
  1112. * fixes from Luiz Am?rico
  1113. Revision 1.4 2004/03/19 12:54:22 marco
  1114. * more strutils small things
  1115. Revision 1.3 2004/03/18 16:55:47 marco
  1116. * more simple implementations done, based on copy() Largely untested
  1117. }