/src/lib/storage/map.e

http://github.com/tybor/Liberty · Specman e · 540 lines · 397 code · 38 blank · 105 comment · 17 complexity · 014a6f6a7093df1ba847199e2cbb9e7b 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 MAP[V_, K_]
  5. --
  6. -- Read-only associative memory. Values of type `V_' are stored using Keys of type `K_'.
  7. --
  8. -- See also DICTIONARY
  9. --
  10. inherit
  11. TRAVERSABLE[V_]
  12. rename
  13. new_iterator as new_iterator_on_items,
  14. for_each as for_each_item,
  15. do_all as do_all_items,
  16. for_all as for_all_items,
  17. exists as exists_item,
  18. aggregate as aggregate_items
  19. undefine
  20. copy
  21. redefine
  22. is_equal, out_in_tagged_out_memory
  23. end
  24. feature {ANY} -- Counting:
  25. is_empty: BOOLEAN
  26. -- Is it empty?
  27. do
  28. Result := count = 0
  29. end
  30. feature {ANY} -- Basic access:
  31. has (k: K_): BOOLEAN
  32. -- Is there a value currently associated with key `k'?
  33. --
  34. -- See also `fast_has', `at'.
  35. require
  36. k /= Void
  37. deferred
  38. end
  39. at (k: K_): V_
  40. -- Return the value associated to key `k'.
  41. --
  42. -- See also `fast_at', `reference_at', `has'.
  43. require
  44. has(k)
  45. deferred
  46. end
  47. frozen infix "@" (k: K_): V_
  48. -- The infix notation which is actually a synonym for `at'.
  49. require
  50. has(k)
  51. do
  52. Result := at(k)
  53. ensure
  54. definition: Result = at(k)
  55. end
  56. reference_at (k: K_): V_
  57. -- Return Void or the value associated with key `k'. Actually, this feature is useful only
  58. -- when the type of values (the type V_) is a reference type, to avoid using `has' just
  59. -- followed by `at' to get the corresponding value with the very best performances.
  60. --
  61. -- See also `fast_reference_at', `at', `has'.
  62. require
  63. k /= Void
  64. values_are_not_expanded: Result = Void
  65. deferred
  66. ensure
  67. has(k) implies Result = at(k)
  68. end
  69. fast_has (k: K_): BOOLEAN
  70. -- Is there a value currently associated with key `k'?
  71. -- Using basic `=' for comparison.
  72. --
  73. -- See also `has', `at', `fast_at'.
  74. require
  75. k /= Void
  76. deferred
  77. end
  78. fast_at (k: K_): V_
  79. -- Return the value associated to key `k' using basic `=' for comparison.
  80. --
  81. -- See also `at', `reference_at', `fast_reference_at'.
  82. require
  83. fast_has(k)
  84. deferred
  85. end
  86. fast_reference_at (k: K_): V_
  87. -- Same work as `reference_at', but basic `=' is used for comparison.
  88. --
  89. -- See also `reference_at', `at', `has'.
  90. require
  91. k /= Void
  92. values_are_reference: Result = Void
  93. deferred
  94. ensure
  95. fast_has(k) implies Result = fast_at(k)
  96. end
  97. feature {ANY} -- Looking and searching some value:
  98. occurrences (v: V_): INTEGER
  99. -- Number of occurrences using `is_equal' for comparison.
  100. --
  101. -- See also `fast_occurrences', `fast_has', `has'.
  102. local
  103. i: INTEGER; safe_equal: SAFE_EQUAL[V_]
  104. do
  105. from
  106. i := lower
  107. until
  108. i > upper
  109. loop
  110. if safe_equal.test(v, item(i)) then
  111. Result := Result + 1
  112. end
  113. i := i + 1
  114. end
  115. ensure
  116. Result >= 0
  117. end
  118. fast_occurrences (v: V_): INTEGER
  119. -- Number of occurrences using basic `=' for comparison.
  120. --
  121. -- See also `occurrences', `fast_has', `has'.
  122. local
  123. i: INTEGER
  124. do
  125. from
  126. i := lower
  127. until
  128. i > upper
  129. loop
  130. if v = item(i) then
  131. Result := Result + 1
  132. end
  133. i := i + 1
  134. end
  135. ensure
  136. Result >= 0
  137. end
  138. key_at (v: V_): K_
  139. -- Retrieve the key used for value `v' using `is_equal' for comparison.
  140. --
  141. -- See also `fast_key_at', `at'.
  142. require
  143. occurrences(v) = 1
  144. local
  145. i: INTEGER; safe_equal: SAFE_EQUAL[V_]
  146. do
  147. from
  148. i := lower
  149. until
  150. safe_equal.test(v, item(i))
  151. loop
  152. i := i + 1
  153. end
  154. Result := key(i)
  155. ensure
  156. (create {SAFE_EQUAL[V_]}).test(at(Result), v)
  157. end
  158. fast_key_at (v: V_): K_
  159. -- Retrieve the key used for value `v' using `=' for comparison.
  160. --
  161. -- See also `key_at', `at'.
  162. require
  163. fast_occurrences(v) = 1
  164. local
  165. i: INTEGER
  166. do
  167. from
  168. i := lower
  169. until
  170. v = item(i)
  171. loop
  172. i := i + 1
  173. end
  174. Result := key(i)
  175. ensure
  176. at(Result) = v
  177. end
  178. feature {ANY} -- To provide iterating facilities:
  179. lower: INTEGER 1
  180. upper: INTEGER
  181. do
  182. Result := count
  183. ensure
  184. count = Result - lower + 1
  185. end
  186. item (index: INTEGER): V_
  187. deferred
  188. ensure
  189. Result = at(key(index))
  190. end
  191. key (index: INTEGER): K_
  192. require
  193. valid_index(index)
  194. deferred
  195. ensure
  196. at(Result) = item(index)
  197. end
  198. first: V_
  199. do
  200. Result := item(lower)
  201. end
  202. last: V_
  203. do
  204. Result := item(upper)
  205. end
  206. new_iterator_on_items: ITERATOR[V_]
  207. deferred
  208. ensure then
  209. Result /= Void
  210. end
  211. new_iterator_on_keys: ITERATOR[K_]
  212. deferred
  213. ensure
  214. Result /= Void
  215. end
  216. new_iterator: ITERATOR[TUPLE[V_, K_]]
  217. deferred
  218. ensure
  219. Result /= Void
  220. end
  221. key_map_in (buffer: COLLECTION[K_])
  222. -- Append in `buffer', all available keys (this may be useful to
  223. -- speed up the traversal).
  224. --
  225. -- See also `item_map_in'.
  226. require
  227. buffer /= Void
  228. do
  229. buffer.append_traversable(keys)
  230. ensure
  231. buffer.count = count + old buffer.count
  232. end
  233. item_map_in (buffer: COLLECTION[V_])
  234. -- Append in `buffer', all available items (this may be useful to
  235. -- speed up the traversal).
  236. --
  237. -- See also `key_map_in'.
  238. require
  239. buffer /= Void
  240. do
  241. buffer.append_traversable(items)
  242. ensure
  243. buffer.count = count + old buffer.count
  244. end
  245. keys: TRAVERSABLE[K_]
  246. -- An iterable of this map keys
  247. do
  248. if keys_memory = Void then
  249. create keys_memory.from_map(Current)
  250. end
  251. Result := keys_memory
  252. ensure
  253. Result.count = count
  254. end
  255. items: TRAVERSABLE[V_]
  256. -- An iterable of this map values
  257. -- Usually returns Current because MAP is TRAVERSABLE.
  258. do
  259. Result := Current
  260. ensure
  261. Result.count = count
  262. end
  263. feature {ANY}
  264. fast_is_equal (other: like Current): BOOLEAN
  265. -- Do both dictionaries have the same set of associations?
  266. -- Keys are compared with `is_equal' and values are compared
  267. -- with the basic = operator.
  268. --
  269. -- See also `is_equal'.
  270. local
  271. i: INTEGER; k: K_
  272. do
  273. if Current = other then
  274. Result := True
  275. elseif count = other.count then
  276. from
  277. Result := True
  278. i := 1
  279. until
  280. not Result or else i > count
  281. loop
  282. k := key(i)
  283. if other.has(k) then
  284. if other.at(k) /= item(i) then
  285. Result := False
  286. else
  287. i := i + 1
  288. end
  289. else
  290. Result := False
  291. end
  292. end
  293. end
  294. ensure
  295. Result implies count = other.count
  296. end
  297. is_equal (other: like Current): BOOLEAN
  298. -- Do both dictionaries have the same set of associations?
  299. -- Both keys and values are compared with `is_equal'.
  300. --
  301. -- See also `fast_is_equal'.
  302. local
  303. i: INTEGER; k: K_; safe_equal: SAFE_EQUAL[V_]
  304. do
  305. if Current = other then
  306. Result := True
  307. elseif count = other.count then
  308. from
  309. Result := True
  310. i := 1
  311. until
  312. not Result or else i > count
  313. loop
  314. k := key(i)
  315. if other.has(k) then
  316. if not safe_equal.test(other.at(k), item(i)) then
  317. Result := False
  318. else
  319. i := i + 1
  320. end
  321. else
  322. Result := False
  323. end
  324. end
  325. end
  326. end
  327. is_equal_map (other: like Current): BOOLEAN
  328. -- Do both collections have the same `lower', `upper', and
  329. -- items?
  330. -- Feature `is_equal' is used for comparison of items.
  331. obsolete "Use `is_equal' instead."
  332. do
  333. Result := is_equal(other)
  334. end
  335. feature {ANY} -- Display support:
  336. out_in_tagged_out_memory
  337. local
  338. i: INTEGER; k: like key; v: like item
  339. do
  340. tagged_out_memory.extend('{')
  341. tagged_out_memory.append(generating_type)
  342. tagged_out_memory.append(once ":[")
  343. from
  344. i := lower
  345. until
  346. i > upper
  347. loop
  348. k := key(i)
  349. if k = Void then
  350. tagged_out_memory.append(once "Void")
  351. else
  352. k.out_in_tagged_out_memory
  353. end
  354. tagged_out_memory.extend('=')
  355. v := item(i)
  356. if v = Void then
  357. tagged_out_memory.append(once "Void")
  358. else
  359. v.out_in_tagged_out_memory
  360. end
  361. if i < upper then
  362. tagged_out_memory.extend(' ')
  363. end
  364. i := i + 1
  365. end
  366. tagged_out_memory.append(once "]}")
  367. end
  368. feature {ANY} -- Agents based features:
  369. for_each (action: PROCEDURE[TUPLE[V_, K_]])
  370. -- Apply `action' to every [V_, K_] associations of `Current'.
  371. --
  372. -- See also `for_all', `exist'.
  373. require
  374. action /= Void
  375. local
  376. i: INTEGER; v: V_; k: K_
  377. do
  378. from
  379. i := lower
  380. until
  381. i > upper
  382. loop
  383. v := item(i)
  384. k := key(i)
  385. action.call([v, k])
  386. i := i + 1
  387. end
  388. end
  389. frozen do_all (action: ROUTINE[TUPLE[V_, K_]])
  390. -- Apply `action' to every [V_, K_] associations of `Current'.
  391. --
  392. -- See also `for_all', `exist'.
  393. obsolete "This feature is not secure because it accepts a FUNCTION, the result of which is lost. Plese use `for_each` instead."
  394. require
  395. action /= Void
  396. local
  397. p: PROCEDURE[TUPLE[V_, K_]]
  398. do
  399. if p ?:= action then
  400. p ::= action
  401. else
  402. p := agent (v: V_; k: K_) do action.call([v, k]) end (?, ?)
  403. end
  404. for_each(p)
  405. end
  406. for_all (test: PREDICATE[TUPLE[V_, K_]]): BOOLEAN
  407. -- Do all [V_, K_] associations satisfy `test'?
  408. --
  409. -- See also `for_each', `exist'.
  410. require
  411. test /= Void
  412. local
  413. i: INTEGER; v: V_; k: K_
  414. do
  415. from
  416. Result := True
  417. i := lower
  418. until
  419. not Result or else i > upper
  420. loop
  421. v := item(i)
  422. k := key(i)
  423. Result := test.item([v, k])
  424. i := i + 1
  425. end
  426. end
  427. exists (test: PREDICATE[TUPLE[V_, K_]]): BOOLEAN
  428. -- Does at least one [V_, K_] association satisfy `test'?
  429. --
  430. -- See also `for_all', `for_each'.
  431. require
  432. test /= Void
  433. local
  434. i: INTEGER; v: V_; k: K_
  435. do
  436. from
  437. i := lower
  438. until
  439. Result or else i > upper
  440. loop
  441. v := item(i)
  442. k := key(i)
  443. Result := test.item([v, k])
  444. i := i + 1
  445. end
  446. end
  447. aggregate (action: FUNCTION[TUPLE[V_, V_, K_], V_]; initial: V_): V_
  448. -- Aggregate all the elements starting from the initial value.
  449. --
  450. -- See also `for_each', `for_all', `exists'.
  451. require
  452. action /= Void
  453. local
  454. i: INTEGER; v: V_; k: K_
  455. do
  456. from
  457. Result := initial
  458. i := lower
  459. until
  460. i > upper
  461. loop
  462. v := item(i)
  463. k := key(i)
  464. Result := action.item([Result, v, k])
  465. i := i + 1
  466. end
  467. end
  468. feature {ANY} -- Other features:
  469. internal_key (k: K_): K_
  470. -- Retrieve the internal key object which correspond to the existing
  471. -- entry `k' (the one memorized into the `Current' dictionary).
  472. --
  473. -- See also `has', `fast_has'.
  474. require
  475. has(k)
  476. deferred
  477. ensure
  478. Result.is_equal(k)
  479. end
  480. feature {}
  481. keys_memory: DICTIONARY_KEY_TRAVERSER[V_, K_]
  482. end -- class MAP
  483. --
  484. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  485. --
  486. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  487. -- of this software and associated documentation files (the "Software"), to deal
  488. -- in the Software without restriction, including without limitation the rights
  489. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  490. -- copies of the Software, and to permit persons to whom the Software is
  491. -- furnished to do so, subject to the following conditions:
  492. --
  493. -- The above copyright notice and this permission notice shall be included in
  494. -- all copies or substantial portions of the Software.
  495. --
  496. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  497. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  498. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  499. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  500. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  501. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  502. -- THE SOFTWARE.