/src/lib/string/string.e

http://github.com/tybor/Liberty · Specman e · 1040 lines · 809 code · 60 blank · 171 comment · 46 complexity · 43c542c8b99e5dcd8def1b6e3267f30d MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class STRING
  5. --
  6. -- Resizable character STRINGs indexed from `1' to `count'.
  7. --
  8. inherit
  9. NATIVELY_STORED_STRING
  10. create {ANY}
  11. with_capacity, make, copy, make_empty, make_filled, from_external, from_external_copy,
  12. from_external_sized, from_external_sized_copy, make_from_string
  13. feature {ANY} -- Creation / Modification:
  14. make, with_capacity (needed_capacity: INTEGER)
  15. -- Initialize the string to have at least `needed_capacity' characters of storage.
  16. require
  17. non_negative_size: needed_capacity >= 0
  18. do
  19. storage_lower := 0
  20. if needed_capacity > 0 then
  21. ensure_capacity(needed_capacity)
  22. end
  23. count := 0
  24. next_generation
  25. ensure
  26. needed_capacity <= capacity
  27. empty_string: count = 0
  28. end
  29. make_empty
  30. -- Create an empty string.
  31. do
  32. make(0)
  33. end
  34. make_filled (c: CHARACTER; n: INTEGER)
  35. -- Initialize string with `n' copies of `c'.
  36. require
  37. valid_count: n >= 0
  38. do
  39. make(n)
  40. count := n
  41. fill_with(c)
  42. next_generation
  43. ensure
  44. count_set: count = n
  45. filled: occurrences(c) = count
  46. end
  47. make_from_string (model: ABSTRACT_STRING)
  48. -- Initialize from the characters of `model'.
  49. require
  50. model /= Void
  51. local
  52. c: INTEGER
  53. do
  54. storage_lower := 0
  55. c := model.count
  56. count := c
  57. if c > 0 then
  58. ensure_capacity(c)
  59. slice_copy(0, model, model.lower, model.upper)
  60. end
  61. next_generation
  62. ensure
  63. count = model.count
  64. end
  65. feature {ANY}
  66. hash_code: INTEGER
  67. do
  68. Result := computed_hash_code
  69. end
  70. feature {ANY} -- Modification:
  71. resize (new_count: INTEGER)
  72. -- Resize Current. When `new_count' is greater than
  73. -- `count', new positions are initialized with the
  74. -- default value of type CHARACTER ('%U').
  75. require
  76. new_count >= 0
  77. do
  78. if new_count <= count then
  79. elseif capacity < new_count + storage_lower then
  80. ensure_capacity(new_count + storage_lower)
  81. else
  82. storage.clear(count + storage_lower, new_count + storage_lower - 1)
  83. end
  84. count := new_count
  85. ensure
  86. count = new_count
  87. capacity >= old capacity
  88. end
  89. clear_count, wipe_out
  90. -- Discard all characters so that `is_empty' is True after that call.
  91. -- The internal `capacity' is not changed by this call (i.e. the internal `storage' memory
  92. -- neither released nor shrunk).
  93. --
  94. -- See also `clear_count_and_capacity'.
  95. do
  96. storage_lower := 0
  97. count := 0
  98. ensure
  99. is_empty: count = 0
  100. capacity = old capacity
  101. storage_lower = 0
  102. end
  103. clear_count_and_capacity
  104. -- Discard all characters (`is_empty' is True after that call). The internal `capacity' may also be
  105. -- reduced after this call.
  106. --
  107. -- See also `clear_count'.
  108. local
  109. null_storage: like storage
  110. do
  111. count := 0
  112. capacity := 0
  113. storage_lower := 0
  114. storage := null_storage
  115. ensure
  116. is_empty: count = 0
  117. capacity = 0
  118. storage_lower = 0
  119. storage.is_null
  120. end
  121. copy (other: like Current)
  122. -- Copy `other' onto Current.
  123. --
  124. -- See also `copy_substring'.
  125. local
  126. c: INTEGER
  127. do
  128. if other /= Current then
  129. storage_lower := 0
  130. c := other.count
  131. if c > 0 then
  132. ensure_capacity(c)
  133. storage.copy_slice_from(other.storage, other.storage_lower, other.storage_lower + c - 1)
  134. end
  135. count := c
  136. end
  137. ensure then
  138. count = other.count
  139. end
  140. copy_substring (s: ABSTRACT_STRING; start_index, end_index: INTEGER)
  141. -- Copy the substring from `s' from `start_index' to `end_index'
  142. -- to Current.
  143. --
  144. -- See also `copy'.
  145. require
  146. string_not_void: s /= Void
  147. valid_start_index: 1 <= start_index
  148. valid_end_index: end_index <= s.count
  149. meaningful_interval: start_index <= end_index + 1
  150. local
  151. c: INTEGER
  152. do
  153. c := end_index - start_index + 1
  154. if c > 0 then
  155. ensure_capacity(c)
  156. slice_copy(0, s, start_index, end_index)
  157. end
  158. count := c
  159. end
  160. fill_with (c: CHARACTER)
  161. -- Replace every character with `c'.
  162. do
  163. storage_lower := 0
  164. storage.set_all_with(c, count - 1)
  165. ensure
  166. occurrences(c) = count
  167. end
  168. replace_all (old_character, new_character: like item)
  169. -- Replace all occurrences of the element `old_character' by `new_character'.
  170. do
  171. storage.fast_replace_all(old_character, new_character, count + storage_lower - 1)
  172. ensure
  173. count = old count
  174. old_character /= new_character implies occurrences(old_character) = 0
  175. end
  176. append, append_string (s: ABSTRACT_STRING)
  177. -- Append a copy of 's' to `Current'.
  178. --
  179. -- See also `add_last', `add_first', `prepend', '+'.
  180. require
  181. s_not_void: s /= Void
  182. local
  183. needed_capacity: INTEGER
  184. do
  185. -- Note: pre-computing needed capacity may be costly for ROPEs. Consider moving it into the NATIVELY_STORED_STRING-specific part of the feature.
  186. needed_capacity := count + s.count + storage_lower
  187. ensure_capacity(needed_capacity)
  188. slice_copy(upper, s, s.lower, s.upper)
  189. count := needed_capacity - storage_lower
  190. end
  191. append_substring (s: ABSTRACT_STRING; start_index, end_index: INTEGER)
  192. -- Append the substring from `s' from `start_index' to `end_index'
  193. -- to Current.
  194. require
  195. string_not_void: s /= Void
  196. valid_start_index: 1 <= start_index
  197. valid_end_index: end_index <= s.count
  198. meaningful_interval: start_index <= end_index + 1
  199. local
  200. needed_capacity: INTEGER
  201. do
  202. needed_capacity := count + storage_lower + end_index - start_index + 1
  203. ensure_capacity(needed_capacity)
  204. slice_copy(upper, s, start_index, end_index)
  205. count := needed_capacity
  206. end
  207. prepend (other: ABSTRACT_STRING)
  208. -- Prepend `other' to `Current'.
  209. --
  210. -- See also `append'.
  211. require
  212. other /= Void
  213. local
  214. d, i, j: INTEGER
  215. do
  216. if other = Current then --| **** TODO -- this fixes TEST_ALG09 using a quick and dirty special case :-(
  217. ensure_capacity(count * 2 + storage_lower)
  218. slice_copy(count, Current, lower, upper)
  219. count := count * 2
  220. else
  221. i := count
  222. j := other.count
  223. d := storage_lower - j
  224. if d < 0 then
  225. -- the string to be prepended is bigger than the unused space available in the buffer before the beginning of the string.
  226. ensure_capacity(i + j)
  227. end
  228. if i = 0 or else d = 0 then
  229. storage_lower := 0
  230. elseif d > 0 then
  231. storage_lower := d
  232. else
  233. storage.move(storage_lower, storage_lower + i - 1, -d)
  234. storage_lower := 0
  235. end
  236. slice_copy(0, other, other.lower, other.upper)
  237. count := i + j
  238. end
  239. ensure
  240. (old other.twin + old twin).is_equal(Current)
  241. end
  242. insert_string (s: ABSTRACT_STRING; i: INTEGER)
  243. -- Insert `s' at index `i', shifting characters from index `i'
  244. -- to `count' rightwards.
  245. require
  246. string_not_void: s /= Void
  247. valid_insertion_index: lower <= i and i <= upper + 1
  248. local
  249. j, k, dk: INTEGER
  250. do
  251. j := count
  252. k := s.count
  253. count := j + k
  254. dk := k - storage_lower
  255. if dk <= 0 then
  256. storage.move(storage_lower, i - lower + storage_lower, -k)
  257. storage_lower := -dk
  258. slice_copy(i - lower, s, s.lower, s.upper)
  259. else
  260. ensure_capacity(count)
  261. if storage_lower > 0 then
  262. storage.move(storage_lower, i + storage_lower - lower, -storage_lower)
  263. end
  264. if i <= j then
  265. storage.move(i + storage_lower - lower, j + storage_lower - lower, dk)
  266. end
  267. storage_lower := 0
  268. slice_copy(i - lower, s, s.lower, s.upper)
  269. end
  270. end
  271. replace_substring (s: ABSTRACT_STRING; start_index, end_index: INTEGER)
  272. -- Replace the substring from `start_index' to `end_index',
  273. -- inclusive, with `s'.
  274. require
  275. string_not_void: s /= Void
  276. valid_start_index: lower <= start_index
  277. valid_end_index: end_index <= upper
  278. meaningful_interval: start_index <= end_index + 1
  279. local
  280. remove_len, insert_len, difference, old_upper: INTEGER
  281. do
  282. remove_len := end_index - start_index + 1
  283. insert_len := s.count
  284. difference := insert_len - remove_len
  285. if difference > 0 then
  286. if storage_lower >= difference then
  287. storage.move(storage_lower, start_index, -difference)
  288. storage_lower := storage_lower - difference
  289. else
  290. old_upper := upper
  291. ensure_capacity(count + difference)
  292. if end_index < old_upper then
  293. -- something to move?
  294. storage.move(storage_lower + end_index + 1 - lower, storage_lower + old_upper - lower, difference)
  295. end
  296. end
  297. elseif difference < 0 then
  298. if end_index < upper then
  299. -- something to move?
  300. storage.move(storage_lower + end_index + 1 - lower, storage_lower + upper - lower, difference)
  301. end
  302. end
  303. count := count + difference
  304. slice_copy(start_index - lower, s, s.lower, s.upper)
  305. end
  306. put (c: CHARACTER; i: INTEGER)
  307. -- Put `c' at index `i'.
  308. --
  309. -- See also `item', `lower', `upper', `swap'.
  310. require
  311. valid_index: valid_index(i)
  312. do
  313. storage.put(c, storage_lower + i - lower)
  314. ensure
  315. item(i) = c
  316. end
  317. swap (i1, i2: INTEGER)
  318. -- Swap two characters.
  319. --
  320. -- See also `item', `put'.
  321. require
  322. valid_index(i1)
  323. valid_index(i2)
  324. local
  325. tmp: CHARACTER
  326. do
  327. tmp := item(i1)
  328. put(item(i2), i1)
  329. put(tmp, i2)
  330. ensure
  331. item(i1) = old item(i2)
  332. item(i2) = old item(i1)
  333. end
  334. insert_character (c: CHARACTER; i: INTEGER)
  335. -- Inserts `c' at index `i', shifting characters from
  336. -- position 'i' to `count' rightwards.
  337. require
  338. valid_insertion_index: lower <= i and i <= upper + 1
  339. do
  340. if storage_lower > 0 and then i <= upper then
  341. if i > lower then
  342. storage.move(storage_lower, storage_lower + i - lower, -1)
  343. end
  344. storage_lower := storage_lower - 1
  345. else
  346. ensure_capacity(count + storage_lower + 1)
  347. if i <= upper then
  348. storage.move(storage_lower - lower + i, storage_lower - lower + upper, 1)
  349. end
  350. end
  351. storage.put(c, storage_lower + i - lower)
  352. count := count + 1
  353. ensure
  354. item(i) = c
  355. count = old count + 1
  356. end
  357. shrink (min_index, max_index: INTEGER)
  358. -- Keep only the slice [`min_index' .. `max_index'] or nothing
  359. -- when the slice is empty.
  360. require
  361. lower <= min_index
  362. max_index <= upper
  363. min_index <= max_index + 1
  364. do
  365. if max_index < min_index then
  366. count := 0
  367. elseif min_index = 1 then
  368. count := max_index
  369. else
  370. storage_lower := storage_lower + min_index - lower
  371. count := max_index - min_index + 1
  372. end
  373. ensure
  374. count = max_index - min_index + 1
  375. end
  376. remove (i: INTEGER)
  377. -- Remove character at position `i'.
  378. --
  379. -- See also `remove_head', `remove_between', `remove_suffix', `remove_prefix'.
  380. require
  381. valid_removal_index: valid_index(i)
  382. do
  383. remove_between(i, i)
  384. ensure
  385. count = old count - 1
  386. end
  387. add_first, precede (c: CHARACTER)
  388. -- Add `c' at first position.
  389. --
  390. -- See also `add_last'.
  391. do
  392. insert_character(c, lower)
  393. ensure
  394. count = 1 + old count
  395. item(lower) = c
  396. end
  397. add_last, append_character, extend (c: CHARACTER)
  398. -- Append `c' to string.
  399. --
  400. -- See also `add_first'.
  401. do
  402. insert_character(c, upper + 1)
  403. ensure
  404. count = 1 + old count
  405. item(upper) = c
  406. end
  407. to_lower
  408. -- Convert all characters to lower case.
  409. --
  410. -- See also `to_upper', `as_lower', `as_upper'.
  411. local
  412. i: INTEGER
  413. do
  414. from
  415. i := 1
  416. until
  417. i > count
  418. loop
  419. put(item(i).to_lower, i)
  420. i := i + 1
  421. end
  422. end
  423. to_upper
  424. -- Convert all characters to upper case.
  425. --
  426. -- See also `to_lower', `as_upper', `as_lower'.
  427. local
  428. i: INTEGER
  429. do
  430. from
  431. i := 1
  432. until
  433. i > count
  434. loop
  435. put(item(i).to_upper, i)
  436. i := i + 1
  437. end
  438. end
  439. keep_head (n: INTEGER)
  440. -- Remove all characters except for the first `n'.
  441. -- Do nothing if `n' >= `count'.
  442. --
  443. -- See also `keep_tail', `remove_head', `remove_tail'.
  444. require
  445. n_non_negative: n >= 0
  446. do
  447. if n < count then
  448. remove_tail(count - n)
  449. end
  450. ensure
  451. count = n.min(old count)
  452. end
  453. keep_tail (n: INTEGER)
  454. -- Remove all characters except for the last `n'.
  455. -- Do nothing if `n' >= `count'.
  456. --
  457. -- See also `keep_head', `remove_tail', `remove_head'.
  458. require
  459. n_non_negative: n >= 0
  460. do
  461. if n < count then
  462. remove_head(count - n)
  463. end
  464. ensure
  465. count = n.min(old count)
  466. end
  467. remove_first
  468. -- Remove the `first' item.
  469. --
  470. -- See also `remove_head', `remove_last', `remove'.
  471. require
  472. not is_empty
  473. do
  474. storage_lower := storage_lower + 1
  475. count := count - 1
  476. ensure
  477. count = old count - 1
  478. end
  479. remove_head (n: INTEGER)
  480. -- Remove `n' first characters. If `n' >= `count', remove all.
  481. --
  482. -- See also `remove_tail', `remove', `remove_the_first'.
  483. require
  484. n_non_negative: n >= 0
  485. do
  486. if n >= count then
  487. storage_lower := 0
  488. count := 0
  489. else
  490. storage_lower := storage_lower + n
  491. count := count - n
  492. end
  493. ensure
  494. count = (old count - n).max(0)
  495. end
  496. remove_last
  497. -- Remove the `last' item.
  498. --
  499. -- See also `remove_tail', `remove_first', `remove'.
  500. require
  501. not is_empty
  502. do
  503. count := count - 1
  504. ensure
  505. count = old count - 1
  506. end
  507. remove_tail (n: INTEGER)
  508. -- Remove `n' last characters. If `n' >= `count', remove all.
  509. --
  510. -- See also `remove_head', `remove', `remove_the_last'.
  511. require
  512. n_non_negative: n >= 0
  513. do
  514. if n >= count then
  515. storage_lower := 0
  516. count := 0
  517. else
  518. count := count - n
  519. end
  520. ensure
  521. count = (old count - n).max(0)
  522. end
  523. remove_substring, remove_between (start_index, end_index: INTEGER)
  524. -- Remove all characters from `strt_index' to `end_index' inclusive.
  525. require
  526. valid_start_index: 1 <= start_index
  527. valid_end_index: end_index <= count
  528. meaningful_interval: start_index <= end_index + 1
  529. local
  530. i, len: INTEGER
  531. do
  532. len := end_index - start_index + 1
  533. if len > 0 then
  534. from
  535. i := end_index + 1
  536. until
  537. i > count
  538. loop
  539. put(item(i), i - len)
  540. i := i + 1
  541. end
  542. count := count - len
  543. end
  544. ensure
  545. count = old count - (end_index - start_index + 1)
  546. end
  547. remove_suffix (s: ABSTRACT_STRING)
  548. -- Remove the suffix `s' of current string.
  549. --
  550. -- See also `remove_prefix', `remove_tail', `remove'.
  551. require
  552. has_suffix(s)
  553. do
  554. remove_tail(s.count)
  555. ensure
  556. (old Current.twin).is_equal(Current + old s.twin)
  557. end
  558. remove_prefix (s: ABSTRACT_STRING)
  559. -- Remove the prefix `s' of current string.
  560. --
  561. -- See also `remove_suffix', `remove_head', `remove'.
  562. require
  563. has_prefix(s)
  564. do
  565. remove_head(s.count)
  566. ensure
  567. (old s.twin + Current).is_equal(old Current.twin)
  568. end
  569. left_adjust
  570. -- Remove leading blanks.
  571. --
  572. -- See also `remove_head', `first'.
  573. local
  574. i: INTEGER
  575. do
  576. from
  577. i := 1
  578. until
  579. i > count or else not item(i).is_separator -- i.e. not a blank like ' '
  580. loop
  581. i := i + 1
  582. end
  583. remove_head(i - 1)
  584. ensure
  585. stripped: is_empty or else not first.is_separator
  586. end
  587. right_adjust
  588. -- Remove trailing blanks.
  589. --
  590. -- See also `remove_tail', `last'.
  591. do
  592. from
  593. until
  594. count = 0 or else not item(count).is_separator
  595. loop
  596. count := count - 1
  597. end
  598. ensure
  599. stripped: is_empty or else not last.is_separator
  600. end
  601. feature {ANY} -- Other features:
  602. substring (start_index, end_index: INTEGER): like Current
  603. local
  604. new_count: INTEGER
  605. new_store: like storage
  606. do
  607. new_count := end_index - start_index + 1
  608. new_store := new_store.calloc(new_count + 1)
  609. new_store.slice_copy(0, storage, storage_lower + start_index - lower, storage_lower + end_index - lower)
  610. Result := standard_twin
  611. Result.from_external_sized(new_store.to_external, new_count)
  612. end
  613. extend_multiple (c: CHARACTER; n: INTEGER)
  614. -- Extend Current with `n' times character `c'.
  615. require
  616. n >= 0
  617. local
  618. i: INTEGER
  619. do
  620. from
  621. i := n
  622. until
  623. i = 0
  624. loop
  625. add_last(c)
  626. i := i - 1
  627. end
  628. ensure
  629. count = n + old count
  630. end
  631. precede_multiple (c: CHARACTER; n: INTEGER)
  632. -- Prepend `n' times character `c' to Current.
  633. local
  634. old_upper, new_storage_lower: INTEGER
  635. do
  636. -- Note: This command once had this precondition: "require n >= 0" As you
  637. -- can see this implementation does not actually need it. In fact this
  638. -- command will not fail if n is negative. Perhaps it is a vestigial
  639. -- precondition when there were no NATURAL type. When n is not positive
  640. -- this command does not make any change. Paolo
  641. -- 2011-09-04
  642. if n > 0 then
  643. old_upper := upper
  644. if old_upper < lower then
  645. check count = 0 end
  646. storage_lower := 0
  647. extend_multiple(c, n)
  648. else
  649. if n > storage_lower then
  650. new_storage_lower := 0
  651. count := count + storage_lower
  652. extend_multiple('%U', n - storage_lower)
  653. else
  654. new_storage_lower := storage_lower - n
  655. count := count + n
  656. end
  657. storage.move(storage_lower, storage_lower + old_upper - lower, n)
  658. storage.set_slice_with(c, new_storage_lower, new_storage_lower + n - 1)
  659. storage_lower:= new_storage_lower
  660. next_generation
  661. end
  662. end
  663. ensure
  664. count = n.max(0) + old count
  665. not_changed_when_n_is_not_positive: n < 1 implies Current ~ old twin
  666. end
  667. extend_to_count (c: CHARACTER; needed_count: INTEGER)
  668. -- Extend Current with `c' until `needed_count' is reached.
  669. -- Do nothing if `needed_count' is already greater or equal
  670. -- to `count'.
  671. require
  672. needed_count >= 0
  673. local
  674. needed: INTEGER
  675. do
  676. from
  677. needed := needed_count - count
  678. until
  679. needed <= 0
  680. loop
  681. add_last(c)
  682. needed := needed - 1
  683. end
  684. ensure
  685. count >= needed_count
  686. end
  687. precede_to_count (c: CHARACTER; needed_count: INTEGER)
  688. -- Prepend `c' to Current until `needed_count' is reached.
  689. -- Do nothing if `needed_count' is already greater or equal
  690. -- to `count'.
  691. require
  692. needed_count >= 0
  693. local
  694. needed: INTEGER
  695. do
  696. from
  697. needed := needed_count - count
  698. until
  699. needed <= 0
  700. loop
  701. add_first(c)
  702. needed := needed - 1
  703. end
  704. ensure
  705. count >= needed_count
  706. end
  707. reverse
  708. -- Reverse the string.
  709. local
  710. i1, i2: INTEGER
  711. do
  712. from
  713. i1 := 1
  714. i2 := count
  715. until
  716. i1 >= i2
  717. loop
  718. swap(i1, i2)
  719. i1 := i1 + 1
  720. i2 := i2 - 1
  721. end
  722. end
  723. remove_all_occurrences (ch: CHARACTER)
  724. -- Remove all occurrences of `ch'.
  725. --
  726. -- See also `occurrences', `remove'.
  727. local
  728. i, j: INTEGER
  729. do
  730. from
  731. i := 1
  732. j := 1
  733. until
  734. i > count
  735. loop
  736. if item(i) /= ch then
  737. put(item(i), j)
  738. j := j + 1
  739. end
  740. i := i + 1
  741. end
  742. count := j - 1
  743. ensure
  744. count = old count - old occurrences(ch)
  745. end
  746. feature {ANY} -- Testing and Conversion:
  747. to_hexadecimal
  748. -- Convert Current bit sequence into the corresponding
  749. -- hexadecimal notation.
  750. require
  751. is_bit
  752. local
  753. i, k, new_count: INTEGER; value: INTEGER
  754. do
  755. from
  756. i := 1
  757. k := count #\\ 4
  758. if k > 0 then
  759. new_count := 1
  760. end
  761. until
  762. k = 0
  763. loop
  764. value := value * 2 + item(i).value
  765. i := i + 1
  766. k := k - 1
  767. end
  768. if new_count > 0 then
  769. put(value.hexadecimal_digit, new_count)
  770. end
  771. from
  772. until
  773. i > count
  774. loop
  775. from
  776. value := item(i).value
  777. i := i + 1
  778. k := 3
  779. until
  780. k = 0
  781. loop
  782. value := value * 2 + item(i).value
  783. i := i + 1
  784. k := k - 1
  785. end
  786. new_count := new_count + 1
  787. put(value.hexadecimal_digit, new_count)
  788. end
  789. count := new_count
  790. end
  791. feature {ANY} -- Other features:
  792. extend_unless (ch: CHARACTER)
  793. -- Extend `Current' (using `extend') with `ch' unless `ch'
  794. -- already the `last' character.
  795. do
  796. if count = 0 or else item(count) /= ch then
  797. add_last(ch)
  798. end
  799. ensure
  800. last = ch
  801. count >= old count
  802. end
  803. intern: FIXED_STRING
  804. -- A shared version of this string.
  805. local
  806. strings: FAST_ARRAY[FIXED_STRING]
  807. i: INTEGER
  808. do
  809. strings := interned.reference_at(hash_code)
  810. if strings = Void then
  811. create strings.with_capacity(4)
  812. interned.add(strings, hash_code)
  813. end
  814. from
  815. i := strings.lower
  816. until
  817. Result /= Void or else i > strings.upper
  818. loop
  819. if strings.item(i).same_as(Current) then
  820. Result := strings.item(i)
  821. end
  822. i := i + 1
  823. end
  824. if Result = Void then
  825. create Result.make_from_string(Current)
  826. Result.do_intern(strings)
  827. end
  828. end
  829. feature {ANY} -- Interfacing with C string:
  830. to_external: POINTER
  831. -- Gives C access to the internal `storage' (may be dangerous).
  832. -- To be compatible with C, a null character is added at the end
  833. -- of the internal `storage'. This extra null character is not
  834. -- part of the Eiffel STRING.
  835. do
  836. if count + storage_lower = capacity then
  837. add_last('%U')
  838. count := count - 1
  839. elseif storage.item(count + storage_lower) /= '%U' then
  840. storage.put('%U', count + storage_lower)
  841. end
  842. Result := storage.to_pointer + storage_lower
  843. end
  844. from_external (p: POINTER)
  845. -- Internal `storage' is set using `p' (may be dangerous because
  846. -- the external C string `p' is not duplicated). Assume `p' has a
  847. -- null character at the end in order to compute the Eiffel
  848. -- `count'. This extra null character is not part of the Eiffel
  849. -- STRING. Also consider `from_external_copy' to choose the most
  850. -- appropriate.
  851. require
  852. p.is_not_null
  853. do
  854. storage_lower := 0
  855. from
  856. storage := storage.from_pointer(p)
  857. count := 0
  858. until
  859. storage.item(count) = '%U'
  860. loop
  861. count := count + 1
  862. end
  863. capacity := count + 1
  864. if storage_signature_count > 0 then
  865. has_storage_signature := False
  866. end
  867. next_generation
  868. ensure
  869. capacity = count + 1
  870. p = to_external
  871. end
  872. from_external_copy (p: POINTER)
  873. -- Internal `storage' is set using a copy of `p'. Assume `p' has a
  874. -- null character at the end in order to compute the Eiffel
  875. -- `count'. This extra null character is not part of the Eiffel
  876. -- STRING. Also consider `from_external' to choose the most
  877. -- appropriate.
  878. require
  879. p.is_not_null
  880. local
  881. s: like storage; i: INTEGER
  882. do
  883. storage_lower := 0
  884. from
  885. s := s.from_pointer(p)
  886. count := 0
  887. until
  888. s.item(i) = '%U'
  889. loop
  890. add_last(s.item(i))
  891. i := i + 1
  892. end
  893. next_generation
  894. end
  895. from_external_sized (p: POINTER; size: INTEGER)
  896. -- Internal `storage' is set using `p' (may be dangerous because
  897. -- the external C string `p' is not duplicated). The 'count' of
  898. -- characters of the string is set to 'size'.
  899. -- Also consider `from_external_sized_copy' to choose the most
  900. -- appropriate.
  901. require
  902. p.is_not_null
  903. size >= 0
  904. do
  905. storage_lower := 0
  906. storage := storage.from_pointer(p)
  907. count := size
  908. capacity := size
  909. if storage_signature_count > 0 then
  910. has_storage_signature := False
  911. end
  912. next_generation
  913. ensure
  914. count = size
  915. capacity = size
  916. p = storage.to_pointer -- caution: to_external will add a trailing null
  917. end
  918. from_external_sized_copy (p: POINTER; size: INTEGER)
  919. -- Internal `storage' is set using a copy of `p'.
  920. -- 'size' characters are copied, setting then 'count' to 'size'.
  921. -- Also consider `from_external' to choose the most appropriate.
  922. require
  923. p.is_not_null
  924. size >= 0
  925. local
  926. s: like storage
  927. do
  928. storage_lower := 0
  929. from
  930. ensure_capacity(size)
  931. s := s.from_pointer(p)
  932. count := 0
  933. until
  934. count = size
  935. loop
  936. storage.put(s.item(count), count)
  937. count := count + 1
  938. end
  939. next_generation
  940. ensure
  941. count = size
  942. end
  943. feature {RECYCLING_POOL, STRING_RECYCLING_POOL}
  944. recycle
  945. do
  946. clear_count
  947. end
  948. feature {}
  949. slice_copy (at: INTEGER; source: ABSTRACT_STRING; start_index, end_index: INTEGER)
  950. do
  951. if end_index >= start_index then
  952. source.copy_slice_to_native(start_index, end_index, storage, at + storage_lower)
  953. end
  954. end
  955. invariant
  956. 0 <= count
  957. count <= capacity
  958. capacity > 0 implies storage.is_not_null
  959. storage_lower >= 0
  960. end -- class STRING
  961. --
  962. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  963. --
  964. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  965. -- of this software and associated documentation files (the "Software"), to deal
  966. -- in the Software without restriction, including without limitation the rights
  967. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  968. -- copies of the Software, and to permit persons to whom the Software is
  969. -- furnished to do so, subject to the following conditions:
  970. --
  971. -- The above copyright notice and this permission notice shall be included in
  972. -- all copies or substantial portions of the Software.
  973. --
  974. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  975. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  976. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  977. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  978. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  979. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  980. -- THE SOFTWARE.