strings.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1997 by Carl-Eric Codere,
  5. member of the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Unit Strings;
  13. {*********************************************************************}
  14. { Strings unit, 100% portable. }
  15. {- COMPILING INFORMATION ---------------------------------------------}
  16. { The only difference between this unit and the one supplied with }
  17. { Turbo Pascal 7.01, are that StrLen returns a longint, and the }
  18. { routines requiring a length now use longints instead of words. }
  19. { This should not influence the behaviour of your programs under }
  20. { Turbo Pascal. (it will even create better error checking for your }
  21. { programs). }
  22. {*********************************************************************}
  23. Interface
  24. {*********************************************************************}
  25. { Returns the number of Characters in Str,not counting the Null }
  26. { chracter. }
  27. {*********************************************************************}
  28. function StrLen(Str: PChar): longint;
  29. function StrEnd(Str: PChar): PChar;
  30. {*********************************************************************}
  31. { Description: Move count characters from source to dest. }
  32. { Do not forget to use StrLen(source)+1 as l parameter to also move }
  33. { the null character. }
  34. { Return value: Dest }
  35. { Remarks: Source and Dest may overlap. }
  36. {*********************************************************************}
  37. function StrMove(Dest,Source : Pchar;l : Longint) : pchar;
  38. function StrCopy(Dest, Source: PChar): PChar;
  39. {*********************************************************************}
  40. { Input: Source -> Source of the null-terminated string to copy. }
  41. { Dest -> Destination of null terminated string to copy. }
  42. { Return Value: Pointer to the end of the copied string of Dest. }
  43. { Output: Dest -> Pointer to the copied string. }
  44. {*********************************************************************}
  45. function StrECopy(Dest, Source: PChar): PChar;
  46. {*********************************************************************}
  47. { Copies at most MaxLen characters from Source to Dest. }
  48. { }
  49. { Remarks: According to the Turbo Pascal programmer's Reference }
  50. { this routine performs length checking. From the code of the }
  51. { original strings unit, this does not seem true... }
  52. { Furthermore, copying a null string gives two null characters in }
  53. { the destination according to the Turbo Pascal routine. }
  54. {*********************************************************************}
  55. function StrLCopy(Dest, Source: PChar; MaxLen: Longint): PChar;
  56. {*********************************************************************}
  57. { Input: Source -> Source of the pascal style string to copy. }
  58. { Dest -> Destination of null terminated string to copy. }
  59. { Return Value: Dest. (with noew copied string) }
  60. {*********************************************************************}
  61. function StrPCopy(Dest: PChar; Source: String): PChar;
  62. {*********************************************************************}
  63. { Description: Appends a copy of Source to then end of Dest and }
  64. { return Dest. }
  65. {*********************************************************************}
  66. function StrCat(Dest, Source: PChar): PChar;
  67. {*********************************************************************}
  68. { Description: Appends at most MaxLen - StrLen(Dest) characters from }
  69. { Source to the end of Dest, and returns Dest. }
  70. {*********************************************************************}
  71. function strlcat(dest,source : pchar;l : Longint) : pchar;
  72. {*********************************************************************}
  73. { Compares two strings. Does the ASCII value substraction of the }
  74. { first non matching characters }
  75. { Returns 0 if both strings are equal }
  76. { Returns < 0 if Str1 < Str2 }
  77. { Returns > 0 if Str1 > Str2 }
  78. {*********************************************************************}
  79. function StrComp(Str1, Str2: PChar): Integer;
  80. {*********************************************************************}
  81. { Compares two strings without case sensitivity. See StrComp for more}
  82. { information. }
  83. { Returns 0 if both strings are equal }
  84. { Returns < 0 if Str1 < Str2 }
  85. { Returns > 0 if Str1 > Str2 }
  86. {*********************************************************************}
  87. function StrIComp(Str1, Str2: PChar): Integer;
  88. {*********************************************************************}
  89. { Compares two strings up to a maximum of MaxLen characters. }
  90. { }
  91. { Returns 0 if both strings are equal }
  92. { Returns < 0 if Str1 < Str2 }
  93. { Returns > 0 if Str1 > Str2 }
  94. {*********************************************************************}
  95. function StrLComp(Str1, Str2: PChar; MaxLen: Longint): Integer;
  96. {*********************************************************************}
  97. { Compares two strings up to a maximum of MaxLen characters. }
  98. { The comparison is case insensitive. }
  99. { Returns 0 if both strings are equal }
  100. { Returns < 0 if Str1 < Str2 }
  101. { Returns > 0 if Str1 > Str2 }
  102. {*********************************************************************}
  103. function StrLIComp(Str1, Str2: PChar; MaxLen: Longint): Integer;
  104. {*********************************************************************}
  105. { Input: Str -> String to search. }
  106. { Ch -> Character to find in Str. }
  107. { Return Value: Pointer to first occurence of Ch in Str, nil if }
  108. { not found. }
  109. { Remark: The null terminator is considered being part of the string }
  110. {*********************************************************************}
  111. function StrScan(Str: PChar; Ch: Char): PChar;
  112. {*********************************************************************}
  113. { Input: Str -> String to search. }
  114. { Ch -> Character to find in Str. }
  115. { Return Value: Pointer to last occurence of Ch in Str, nil if }
  116. { not found. }
  117. { Remark: The null terminator is considered being part of the string }
  118. {*********************************************************************}
  119. function StrRScan(Str: PChar; Ch: Char): PChar;
  120. {*********************************************************************}
  121. { Input: Str1 -> String to search. }
  122. { Str2 -> String to match in Str1. }
  123. { Return Value: Pointer to first occurence of Str2 in Str1, nil if }
  124. { not found. }
  125. {*********************************************************************}
  126. function StrPos(Str1, Str2: PChar): PChar;
  127. {*********************************************************************}
  128. { Input: Str -> null terminated string to uppercase. }
  129. { Output:Str -> null terminated string in upper case characters. }
  130. { Return Value: null terminated string in upper case characters. }
  131. { Remarks: Case conversion is dependant on upcase routine. }
  132. {*********************************************************************}
  133. function StrUpper(Str: PChar): PChar;
  134. {*********************************************************************}
  135. { Input: Str -> null terminated string to lower case. }
  136. { Output:Str -> null terminated string in lower case characters. }
  137. { Return Value: null terminated string in lower case characters. }
  138. { Remarks: Only converts standard ASCII characters. }
  139. {*********************************************************************}
  140. function StrLower(Str: PChar): PChar;
  141. { StrPas converts Str to a Pascal style string. }
  142. function StrPas(Str: PChar): String;
  143. {*********************************************************************}
  144. { Input: Str -> String to duplicate. }
  145. { Return Value: Pointer to the new allocated string. nil if no }
  146. { string allocated. If Str = nil then return value }
  147. { will also be nil (in this case, no allocation }
  148. { occurs). The size allocated is of StrLen(Str)+1 }
  149. { bytes. }
  150. {*********************************************************************}
  151. function StrNew(P: PChar): PChar;
  152. { StrDispose disposes a string that was previously allocated }
  153. { with StrNew. If Str is NIL, StrDispose does nothing. }
  154. procedure StrDispose(P: PChar);
  155. Implementation
  156. function strlen(Str : pchar) : Longint;
  157. var
  158. counter : Longint;
  159. Begin
  160. counter := 0;
  161. while Str[counter] <> #0 do
  162. Inc(counter);
  163. strlen := counter;
  164. end;
  165. Function strpas(Str: pchar): string;
  166. { only 255 first characters are actually copied. }
  167. var
  168. counter : byte;
  169. lstr: string;
  170. Begin
  171. counter := 0;
  172. lstr := '';
  173. while (ord(Str[counter]) <> 0) and (counter < 255) do
  174. begin
  175. Inc(counter);
  176. lstr[counter] := char(Str[counter-1]);
  177. end;
  178. lstr[0] := char(counter);
  179. strpas := lstr;
  180. end;
  181. Function StrEnd(Str: PChar): PChar;
  182. var
  183. counter: Longint;
  184. begin
  185. counter := 0;
  186. while Str[counter] <> #0 do
  187. Inc(counter);
  188. StrEnd := @(Str[Counter]);
  189. end;
  190. Function StrCopy(Dest, Source:PChar): PChar;
  191. var
  192. counter : Longint;
  193. Begin
  194. counter := 0;
  195. while Source[counter] <> #0 do
  196. begin
  197. Dest[counter] := char(Source[counter]);
  198. Inc(counter);
  199. end;
  200. { terminate the string }
  201. Dest[counter] := #0;
  202. StrCopy := Dest;
  203. end;
  204. function StrCat(Dest,Source: PChar): PChar;
  205. var
  206. counter: Longint;
  207. PEnd: PChar;
  208. begin
  209. PEnd := StrEnd(Dest);
  210. counter := 0;
  211. while (Source[counter] <> #0) do
  212. begin
  213. PEnd[counter] := char(Source[counter]);
  214. Inc(counter);
  215. end;
  216. { terminate the string }
  217. PEnd[counter] := #0;
  218. StrCat := Dest;
  219. end;
  220. function StrUpper(Str: PChar): PChar;
  221. var
  222. counter: Longint;
  223. begin
  224. counter := 0;
  225. while (Str[counter] <> #0) do
  226. begin
  227. if Str[Counter] in [#97..#122,#128..#255] then
  228. Str[counter] := Upcase(Str[counter]);
  229. Inc(counter);
  230. end;
  231. StrUpper := Str;
  232. end;
  233. function StrLower(Str: PChar): PChar;
  234. var
  235. counter: Longint;
  236. begin
  237. counter := 0;
  238. while (Str[counter] <> #0) do
  239. begin
  240. if Str[counter] in [#65..#90] then
  241. Str[Counter] := chr(ord(Str[Counter]) + 32);
  242. Inc(counter);
  243. end;
  244. StrLower := Str;
  245. end;
  246. function StrPos(Str1,Str2: PChar): PChar;
  247. var
  248. count: Longint;
  249. oldindex: Longint;
  250. found: boolean;
  251. Str1Length: Longint;
  252. Str2Length: Longint;
  253. ll: Longint;
  254. Begin
  255. Str1Length := StrLen(Str1);
  256. Str2Length := StrLen(Str2);
  257. found := true;
  258. oldindex := 0;
  259. { If the search string is greater than the string to be searched }
  260. { it is certain that we will not find it. }
  261. { Furthermore looking for a null will simply give out a pointer, }
  262. { to the null character of str1 as in Borland Pascal. }
  263. if (Str2Length > Str1Length) or (Str2[0] = #0) then
  264. begin
  265. StrPos := nil;
  266. exit;
  267. end;
  268. Repeat
  269. { Find first matching character of Str2 in Str1 }
  270. { put index of this character in oldindex }
  271. for count:= oldindex to Str1Length-1 do
  272. begin
  273. if Str2[0] = Str1[count] then
  274. begin
  275. oldindex := count;
  276. break;
  277. end;
  278. { nothing found - exit routine }
  279. if count = Str1Length-1 then
  280. begin
  281. StrPos := nil;
  282. exit;
  283. end;
  284. end;
  285. found := true;
  286. { Compare the character strings }
  287. { and check if they match. }
  288. for ll := 0 to Str2Length-1 do
  289. begin
  290. { no match, stop iteration }
  291. if (Str2[ll] <> Str1[ll+oldindex]) then
  292. begin
  293. found := false;
  294. break;
  295. end;
  296. end;
  297. { Not found, the index will no point at next character }
  298. if not found then
  299. Inc(oldindex);
  300. { There was a match }
  301. if found then
  302. begin
  303. StrPos := @(Str1[oldindex]);
  304. exit;
  305. end;
  306. { If we have gone through the whole string to search }
  307. { then exit routine. }
  308. Until (Str1Length-oldindex) <= 0;
  309. StrPos := nil;
  310. end;
  311. function StrScan(Str: PChar; Ch: Char): PChar;
  312. Var
  313. count: Longint;
  314. Begin
  315. count := 0;
  316. { As in Borland Pascal , if looking for NULL return null }
  317. if ch = #0 then
  318. begin
  319. StrScan := @(Str[StrLen(Str)]);
  320. exit;
  321. end;
  322. { Find first matching character of Ch in Str }
  323. while Str[count] <> #0 do
  324. begin
  325. if Ch = Str[count] then
  326. begin
  327. StrScan := @(Str[count]);
  328. exit;
  329. end;
  330. Inc(count);
  331. end;
  332. { nothing found. }
  333. StrScan := nil;
  334. end;
  335. function StrRScan(Str: PChar; Ch: Char): PChar;
  336. Var
  337. count: Longint;
  338. index: Longint;
  339. Begin
  340. count := Strlen(Str);
  341. { As in Borland Pascal , if looking for NULL return null }
  342. if ch = #0 then
  343. begin
  344. StrRScan := @(Str[count]);
  345. exit;
  346. end;
  347. Dec(count);
  348. for index := count downto 0 do
  349. begin
  350. if Ch = Str[index] then
  351. begin
  352. StrRScan := @(Str[index]);
  353. exit;
  354. end;
  355. end;
  356. { nothing found. }
  357. StrRScan := nil;
  358. end;
  359. function StrNew(p:PChar): PChar;
  360. var
  361. len : Longint;
  362. tmp : pchar;
  363. begin
  364. strnew:=nil;
  365. if (p=nil) or (p^=#0) then
  366. exit;
  367. len:=strlen(p)+1;
  368. getmem(tmp,len);
  369. if tmp<>nil then
  370. strmove(tmp,p,len);
  371. StrNew := tmp;
  372. end;
  373. Function StrECopy(Dest, Source: PChar): PChar;
  374. { Equivalent to the following: }
  375. { strcopy(Dest,Source); }
  376. { StrECopy := StrEnd(Dest); }
  377. var
  378. counter : Longint;
  379. Begin
  380. counter := 0;
  381. while Source[counter] <> #0 do
  382. begin
  383. Dest[counter] := char(Source[counter]);
  384. Inc(counter);
  385. end;
  386. { terminate the string }
  387. Dest[counter] := #0;
  388. StrECopy:=@(Dest[counter]);
  389. end;
  390. Function StrPCopy(Dest: PChar; Source: String):PChar;
  391. var
  392. counter : byte;
  393. Begin
  394. counter := 0;
  395. { if empty pascal string }
  396. { then setup and exit now }
  397. if Source = '' then
  398. Begin
  399. Dest[0] := #0;
  400. StrPCopy := Dest;
  401. exit;
  402. end;
  403. for counter:=1 to length(Source) do
  404. begin
  405. Dest[counter-1] := Source[counter];
  406. end;
  407. { terminate the string }
  408. Dest[counter] := #0;
  409. StrPCopy:=Dest;
  410. end;
  411. procedure strdispose(p : pchar);
  412. begin
  413. if p<>nil then
  414. freemem(p,strlen(p)+1);
  415. end;
  416. function strmove(dest,source : pchar;l : Longint) : pchar;
  417. begin
  418. move(source^,dest^,l);
  419. strmove:=dest;
  420. end;
  421. function strlcat(dest,source : pchar;l : Longint) : pchar;
  422. var
  423. destend : pchar;
  424. begin
  425. destend:=strend(dest);
  426. l:=l-(destend-dest);
  427. strlcat:=strlcopy(destend,source,l);
  428. end;
  429. Function StrLCopy(Dest,Source: PChar; MaxLen: Longint): PChar;
  430. var
  431. counter: Longint;
  432. Begin
  433. counter := 0;
  434. { To be compatible with BP, on a null string, put two nulls }
  435. If Source[0] = #0 then
  436. Begin
  437. Dest[0]:=Source[0];
  438. Inc(counter);
  439. end;
  440. while (Source[counter] <> #0) and (counter < MaxLen) do
  441. Begin
  442. Dest[counter] := char(Source[counter]);
  443. Inc(counter);
  444. end;
  445. { terminate the string }
  446. Dest[counter] := #0;
  447. StrLCopy := Dest;
  448. end;
  449. function StrComp(Str1, Str2 : PChar): Integer;
  450. var
  451. counter: Longint;
  452. Begin
  453. counter := 0;
  454. While str1[counter] = str2[counter] do
  455. Begin
  456. if (str2[counter] = #0) or (str1[counter] = #0) then
  457. break;
  458. Inc(counter);
  459. end;
  460. StrComp := ord(str1[counter]) - ord(str2[counter]);
  461. end;
  462. function StrIComp(Str1, Str2 : PChar): Integer;
  463. var
  464. counter: Longint;
  465. c1, c2: char;
  466. Begin
  467. counter := 0;
  468. c1 := upcase(str1[counter]);
  469. c2 := upcase(str2[counter]);
  470. While c1 = c2 do
  471. Begin
  472. if (c1 = #0) or (c2 = #0) then break;
  473. Inc(counter);
  474. c1 := upcase(str1[counter]);
  475. c2 := upcase(str2[counter]);
  476. end;
  477. StrIComp := ord(c1) - ord(c2);
  478. end;
  479. function StrLComp(Str1, Str2 : PChar; MaxLen: Longint): Integer;
  480. var
  481. counter: Longint;
  482. c1, c2: char;
  483. Begin
  484. counter := 0;
  485. if MaxLen = 0 then
  486. begin
  487. StrLComp := 0;
  488. exit;
  489. end;
  490. Repeat
  491. if (c1 = #0) or (c2 = #0) then break;
  492. c1 := str1[counter];
  493. c2 := str2[counter];
  494. Inc(counter);
  495. Until (c1 <> c2) or (counter >= MaxLen);
  496. StrLComp := ord(c1) - ord(c2);
  497. end;
  498. function StrLIComp(Str1, Str2 : PChar; MaxLen: Longint): Integer;
  499. var
  500. counter: Longint;
  501. c1, c2: char;
  502. Begin
  503. counter := 0;
  504. if MaxLen = 0 then
  505. begin
  506. StrLIComp := 0;
  507. exit;
  508. end;
  509. Repeat
  510. if (c1 = #0) or (c2 = #0) then break;
  511. c1 := upcase(str1[counter]);
  512. c2 := upcase(str2[counter]);
  513. Inc(counter);
  514. Until (c1 <> c2) or (counter >= MaxLen);
  515. StrLIComp := ord(c1) - ord(c2);
  516. end;
  517. end.
  518. {
  519. $Log$
  520. Revision 1.2 1998-07-01 14:29:42 carl
  521. * strpas bugfix
  522. Revision 1.1.1.1 1998/03/25 11:18:46 root
  523. * Restored version
  524. Revision 1.4 1998/01/26 12:02:01 michael
  525. + Added log at the end
  526. Working file: rtl/template/strings.pp
  527. description:
  528. ----------------------------
  529. revision 1.3
  530. date: 1998/01/05 00:41:57; author: carl; state: Exp; lines: +4 -4
  531. * Esthetic (spelling mistake) fix
  532. ----------------------------
  533. revision 1.2
  534. date: 1997/12/01 12:45:49; author: michael; state: Exp; lines: +14 -1
  535. + added copyright reference in header.
  536. ----------------------------
  537. revision 1.1
  538. date: 1997/11/27 08:33:49; author: michael; state: Exp;
  539. Initial revision
  540. ----------------------------
  541. revision 1.1.1.1
  542. date: 1997/11/27 08:33:49; author: michael; state: Exp; lines: +0 -0
  543. FPC RTL CVS start
  544. =============================================================================
  545. }