/src/lib/storage/collection.e

http://github.com/tybor/Liberty · Specman e · 554 lines · 345 code · 42 blank · 167 comment · 3 complexity · 8ffe3a90398515a85cbf9b4fd7d50758 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. deferred class COLLECTION[E_]
  5. --
  6. -- Common abstract definition of a sequenceable collection of objects. Such a collection is traversable
  7. -- using a simple INTEGER index from `lower' to `upper' using `item'. All COLLECTIONs are resizable
  8. -- thanks to `add_last' / `remove_last', `add_first' / `remove_first' as well as `add' / `remove' .
  9. --
  10. -- This abstraction provides feature to view a COLLECTION as a stack (as an example by using `add_last',
  11. -- `last', and `remove_last'). One can also use a COLLECTION as a queue (as an example, by using
  12. -- `add_last', `first' and `remove_first'). See also class QUEUE and STACK.
  13. --
  14. -- The Liberty Eiffel standard library provides five implementations of COLLECTION: ARRAY, FAST_ARRAY,
  15. -- RING_ARRAY, LINKED_LIST and TWO_WAY_LINKED_LIST. Except for creations all implementations have
  16. -- exactly the same behavior. Switching from one implementation to another only change the memory used
  17. -- and the execution time (see header comment of ARRAY, FAST_ARRAY, RING_ARRAY, LINKED_LIST and
  18. -- TWO_WAY_LINKED_LIST for more details).
  19. --
  20. inherit
  21. STORABLE
  22. undefine out_in_tagged_out_memory
  23. redefine copy, is_equal
  24. end
  25. TRAVERSABLE[E_]
  26. redefine copy, is_equal
  27. end
  28. SEARCHABLE[E_]
  29. undefine out_in_tagged_out_memory
  30. redefine copy, is_equal
  31. end
  32. feature {ANY} -- Accessing:
  33. frozen infix "@" (i: INTEGER): E_
  34. -- The infix notation which is actually just a synonym for `item'.
  35. --
  36. -- See also `item'.
  37. require
  38. valid_index(i)
  39. do
  40. Result := item(i)
  41. ensure
  42. definition: Result = item(i)
  43. end
  44. feature {ANY} -- Writing:
  45. put (element: like item; i: INTEGER) assign item
  46. -- Make `element' the item at index `i'.
  47. --
  48. -- See also `lower', `upper', `valid_index', `item', `swap', `force'.
  49. require
  50. valid_index(i)
  51. deferred
  52. ensure
  53. item(i) = element
  54. count = old count
  55. end
  56. swap (i1, i2: INTEGER)
  57. -- Swap item at index `i1' with item at index `i2'.
  58. --
  59. -- See also `item', `put'.
  60. require
  61. valid_index(i1)
  62. valid_index(i2)
  63. local
  64. tmp: like item
  65. do
  66. tmp := item(i1)
  67. put(item(i2), i1)
  68. put(tmp, i2)
  69. ensure
  70. item(i1) = old item(i2)
  71. item(i2) = old item(i1)
  72. count = old count
  73. end
  74. set_all_with (v: like item)
  75. -- Set all items with value `v'.
  76. --
  77. -- See also `set_slice_with'.
  78. deferred
  79. ensure
  80. count = old count
  81. end
  82. set_slice_with (v: like item; lower_index, upper_index: INTEGER)
  83. -- Set all items in range [`lower_index' .. `upper_index'] with `v'.
  84. --
  85. -- See also `set_all_with'.
  86. require
  87. lower_index <= upper_index
  88. valid_index(lower_index)
  89. valid_index(upper_index)
  90. local
  91. i: INTEGER
  92. do
  93. from
  94. i := lower_index
  95. until
  96. i > upper_index
  97. loop
  98. put(v, i)
  99. i := i + 1
  100. end
  101. ensure
  102. count = old count
  103. end
  104. clear_all
  105. -- Set every item to its default value. The `count' is not affected.
  106. --
  107. -- See also `clear', `all_default'.
  108. local
  109. value: like item
  110. do
  111. set_all_with(value)
  112. ensure
  113. stable_upper: upper = old upper
  114. stable_lower: lower = old lower
  115. all_default
  116. end
  117. feature {ANY} -- Adding:
  118. add_first (element: like item)
  119. -- Add a new item in first position : `count' is increased by
  120. -- one and all other items are shifted right.
  121. --
  122. -- See also `add_last', `first', `last', `add'.
  123. deferred
  124. ensure
  125. first = element
  126. count = 1 + old count
  127. lower = old lower
  128. upper = 1 + old upper
  129. end
  130. add_last (element: like item)
  131. -- Add a new item at the end : `count' is increased by one.
  132. --
  133. -- See also `add_first', `last', `first', `add'.
  134. deferred
  135. ensure
  136. last = element
  137. count = 1 + old count
  138. lower = old lower
  139. upper = 1 + old upper
  140. end
  141. add (element: like item; index: INTEGER)
  142. -- Add a new `element' at rank `index' : `count' is increased
  143. -- by one and range [`index' .. `upper'] is shifted right by one position.
  144. --
  145. -- See also `add_first', `add_last', `append_collection'.
  146. require
  147. index.in_range(lower, upper + 1)
  148. deferred
  149. ensure
  150. item(index) = element
  151. count = 1 + old count
  152. upper = 1 + old upper
  153. end
  154. append_collection (other: COLLECTION[E_])
  155. -- Append `other' to Current.
  156. --
  157. -- See also `add_last', `add_first', `add'.
  158. obsolete "Use `append_traversable' instead."
  159. require
  160. other /= Void
  161. do
  162. append_traversable(other)
  163. ensure
  164. count = other.count + old count
  165. end
  166. append_traversable (other: TRAVERSABLE[E_])
  167. -- Append `other' to Current.
  168. --
  169. -- See also `add_last', `add_first', `add'.
  170. require
  171. other /= Void
  172. local
  173. i: INTEGER
  174. do
  175. from
  176. i := other.lower
  177. until
  178. i > other.upper
  179. loop
  180. add_last(other.item(i))
  181. i := i + 1
  182. end
  183. -- Note: AFAIK it could also be implemented with other.for_each(agent add_last). Paolo 2011-08-12
  184. -- Yes, but it MUST NOT. We are in the standard library and it must work without the GC so don't build useless
  185. -- objects. Cad 2015-06-03
  186. ensure
  187. count = other.count + old count
  188. end
  189. feature {ANY} -- Modification:
  190. force (element: E_; index: INTEGER)
  191. -- Make `element' the item at `index', enlarging the collection if
  192. -- necessary (new bounds except `index' are initialized with
  193. -- default values).
  194. --
  195. -- See also `put', `item', `swap'.
  196. require
  197. index >= lower
  198. deferred
  199. ensure
  200. upper = index.max(old upper)
  201. item(index) = element
  202. end
  203. copy (other: like Current)
  204. -- Reinitialize by copying all the items of `other'.
  205. deferred
  206. end
  207. from_collection (model: TRAVERSABLE[like item])
  208. -- Initialize the current object with the contents of `model'.
  209. require
  210. model /= Void
  211. useful_work: model /= Current
  212. deferred
  213. ensure
  214. count = model.count
  215. end
  216. feature {ANY} -- Removing:
  217. remove_first
  218. -- Remove the `first' element of the collection.
  219. --
  220. -- See also `remove_last', `remove', `remove_head'.
  221. require
  222. not is_empty
  223. deferred
  224. ensure
  225. count = old count - 1
  226. lower = old lower + 1 xor upper = old upper - 1
  227. end
  228. remove_head (n: INTEGER)
  229. -- Remove the `n' elements of the collection.
  230. --
  231. -- See also `remove_tail', `remove', `remove_first'.
  232. require
  233. n > 0 and n <= count
  234. deferred
  235. ensure
  236. count = old count - n
  237. lower = old lower + n xor upper = old upper - n
  238. end
  239. remove (index: INTEGER)
  240. -- Remove the item at position `index'. Followings items are shifted left by one position.
  241. --
  242. -- See also `remove_first', `remove_head', `remove_tail', `remove_last'.
  243. require
  244. valid_index(index)
  245. deferred
  246. ensure
  247. count = old count - 1
  248. upper = old upper - 1
  249. end
  250. remove_last
  251. -- Remove the `last' item.
  252. --
  253. -- See also `remove_first', `remove', `remove_tail'.
  254. require
  255. not is_empty
  256. deferred
  257. ensure
  258. count = old count - 1
  259. upper = old upper - 1
  260. end
  261. remove_tail (n: INTEGER)
  262. -- Remove the last `n' item(s).
  263. --
  264. -- See also `remove_head', `remove', `remove_last'.
  265. require
  266. n > 0 and n <= count
  267. deferred
  268. ensure
  269. count = old count - n
  270. upper = old upper - n
  271. end
  272. clear_count
  273. -- Discard all items (`is_empty' is True after that call). If possible, the actual implementation
  274. -- supposed to keep its internal storage area in order to refill `Current' in an efficient way.
  275. --
  276. -- See also `clear_count_and_capacity'.
  277. deferred
  278. ensure
  279. is_empty: count = 0
  280. end
  281. clear_count_and_capacity
  282. -- Discard all items (`is_empty' is True after that call). If possible, the actual implementation
  283. -- supposed to release its internal storage area for this memory to be used by other objects.
  284. --
  285. -- See also `clear_count'.
  286. deferred
  287. ensure
  288. is_empty: count = 0
  289. end
  290. feature {ANY} -- Looking and Searching:
  291. has (x: like item): BOOLEAN
  292. -- Look for `x' using `is_equal' for comparison.
  293. --
  294. -- See also `fast_has', `index_of', `fast_index_of'.
  295. do
  296. Result := valid_index(first_index_of(x))
  297. end
  298. fast_has (x: like item): BOOLEAN
  299. -- Look for `x' using basic `=' for comparison.
  300. --
  301. -- See also `has', `fast_index_of', `index_of'.
  302. do
  303. Result := valid_index(fast_first_index_of(x))
  304. end
  305. last_index_of (element: like item): INTEGER
  306. -- Using `is_equal' for comparison, gives the index of the last occurrence of `element' at or before
  307. -- `upper'. Search is done in reverse direction, which means from the `upper' down to the
  308. -- `lower' index . Answer `lower -1' when the search fail.
  309. --
  310. -- See also `fast_last_index_of', `reverse_index_of', `index_of'.
  311. do
  312. Result := reverse_index_of(element, upper)
  313. end
  314. fast_last_index_of (element: like item): INTEGER
  315. -- Using basic `=' for comparison, gives the index of the last occurrence of `element' at or before
  316. -- `upper'. Search is done in reverse direction, which means from the `upper' down to the
  317. -- `lower' index . Answer `lower -1' when the search fail.
  318. --
  319. -- See also `fast_reverse_index_of', `last_index_of'.
  320. do
  321. Result := fast_reverse_index_of(element, upper)
  322. end
  323. feature {ANY} -- Looking and comparison:
  324. fast_is_equal (other: like Current): BOOLEAN
  325. -- Do both collections have the same `lower', `upper', and items?
  326. -- The basic `=' is used for comparison of items.
  327. --
  328. -- See also `is_equal', `same_items'.
  329. deferred
  330. ensure
  331. Result implies lower = other.lower and upper = other.upper
  332. end
  333. is_equal (other: like Current): BOOLEAN
  334. -- Do both collections have the same `lower', `upper', and
  335. -- items?
  336. -- Feature `is_equal' is used for comparison of items.
  337. --
  338. -- See also `fast_is_equal', `same_items'.
  339. deferred
  340. ensure then
  341. Result implies lower = other.lower and upper = other.upper
  342. end
  343. is_equal_map (other: like Current): BOOLEAN
  344. -- Do both collections have the same `lower', `upper', and
  345. -- items?
  346. -- Feature `is_equal' is used for comparison of items.
  347. obsolete "Use `is_equal' instead."
  348. do
  349. Result := is_equal(other)
  350. end
  351. all_default: BOOLEAN
  352. -- Do all items have their type's default value?
  353. -- Note: for non Void items, the test is performed with the `is_default' predicate.
  354. --
  355. -- See also `clear_all'.
  356. deferred
  357. end
  358. same_items (other: COLLECTION[E_]): BOOLEAN
  359. -- Do both collections have the same items? The basic `=' is used
  360. -- for comparison of items and indices are not considered (for
  361. -- example this routine may yield True with `Current' indexed in
  362. -- range [1..2] and `other' indexed in range [2..3]).
  363. --
  364. -- See also `is_equal', `fast_is_equal'.
  365. require
  366. other /= Void
  367. local
  368. i, j: INTEGER
  369. do
  370. if count = other.count then
  371. from
  372. Result := True
  373. i := lower
  374. j := other.lower
  375. until
  376. not Result or else i > upper
  377. loop
  378. Result := item(i) = other.item(j)
  379. i := i + 1
  380. j := j + 1
  381. end
  382. end
  383. ensure
  384. Result implies count = other.count
  385. end
  386. occurrences (element: like item): INTEGER
  387. -- Number of occurrences of `element' using `is_equal' for comparison.
  388. --
  389. -- See also `fast_occurrences', `index_of'.
  390. deferred
  391. ensure
  392. Result >= 0
  393. end
  394. fast_occurrences (element: like item): INTEGER
  395. -- Number of occurrences of `element' using basic `=' for comparison.
  396. --
  397. -- See also `occurrences', `index_of'.
  398. deferred
  399. ensure
  400. Result >= 0
  401. end
  402. feature {ANY} -- Other features:
  403. replace_all (old_value, new_value: like item)
  404. -- Replace all occurrences of the element `old_value' by `new_value' using `is_equal' for comparison.
  405. --
  406. -- See also `fast_replace_all', `move'.
  407. deferred
  408. ensure
  409. count = old count
  410. not (create {SAFE_EQUAL[E_]}).test(old_value, new_value) implies occurrences(old_value) = 0
  411. end
  412. fast_replace_all (old_value, new_value: like item)
  413. -- Replace all occurrences of the element `old_value' by `new_value' using basic `=' for comparison.
  414. --
  415. -- See also `replace_all', `move'.
  416. deferred
  417. ensure
  418. count = old count
  419. old_value /= new_value implies fast_occurrences(old_value) = 0
  420. end
  421. move (lower_index, upper_index, distance: INTEGER)
  422. -- Move range `lower_index' .. `upper_index' by `distance' positions.
  423. -- Negative distance moves towards lower indices.
  424. -- Free places get default values.
  425. --
  426. -- See also `slice', `replace_all'.
  427. require
  428. lower_index <= upper_index
  429. valid_index(lower_index)
  430. valid_index(lower_index + distance)
  431. valid_index(upper_index)
  432. valid_index(upper_index + distance)
  433. local
  434. default_value: like item; i: INTEGER
  435. do
  436. if distance = 0 then
  437. elseif distance < 0 then
  438. from
  439. i := lower_index
  440. until
  441. i > upper_index
  442. loop
  443. put(item(i), i + distance)
  444. put(default_value, i)
  445. i := i + 1
  446. end
  447. else
  448. from
  449. i := upper_index
  450. until
  451. i < lower_index
  452. loop
  453. put(item(i), i + distance)
  454. put(default_value, i)
  455. i := i - 1
  456. end
  457. end
  458. ensure
  459. count = old count
  460. end
  461. slice (min, max: INTEGER): like Current
  462. -- New collection consisting of items at indexes in [`min'..`max'].
  463. -- Result has the same dynamic type as `Current'.
  464. -- The `lower' index of the `Result' is the same as `lower'.
  465. --
  466. -- See also `from_collection', `move', `replace_all'.
  467. require
  468. lower <= min
  469. max <= upper
  470. min <= max + 1
  471. deferred
  472. ensure
  473. same_dynamic_type(Result)
  474. Result.count = max - min + 1
  475. Result.lower = lower
  476. end
  477. reverse
  478. -- Reverse the order of the elements.
  479. deferred
  480. ensure
  481. count = old count
  482. end
  483. feature {} -- Implement manifest generic creation:
  484. manifest_semicolon_check: BOOLEAN False
  485. manifest_put (index: INTEGER; element: like item)
  486. require
  487. index >= 0
  488. deferred
  489. end
  490. invariant
  491. valid_bounds: lower <= upper + 1
  492. end -- class COLLECTION
  493. --
  494. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  495. --
  496. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  497. -- of this software and associated documentation files (the "Software"), to deal
  498. -- in the Software without restriction, including without limitation the rights
  499. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  500. -- copies of the Software, and to permit persons to whom the Software is
  501. -- furnished to do so, subject to the following conditions:
  502. --
  503. -- The above copyright notice and this permission notice shall be included in
  504. -- all copies or substantial portions of the Software.
  505. --
  506. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  507. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  508. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  509. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  510. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  511. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  512. -- THE SOFTWARE.