/src/wrappers/common/library/c_array.e

http://github.com/tybor/Liberty · Specman e · 773 lines · 501 code · 68 blank · 204 comment · 26 complexity · f13aaa683b4048563f1c78f737cbe859 MD5 · raw file

  1. note
  2. description:
  3. "."
  4. copyright:
  5. "[
  6. Copyright (C) 2006-2017: Paolo Redaelli
  7. This library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Lesser General Public License
  9. as published by the Free Software Foundation; either version 2.1 of
  10. the License, or (at your option) any later version.
  11. This library is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18. 02110-1301 USA
  19. ]"
  20. deferred class C_ARRAY[ITEM_ -> C_STRUCT]
  21. -- An array of wrapped item which is also a wrapper to a C array
  22. -- of pointers of item's struct. For example a C_ARRAY[GTK_BUTTON]
  23. -- wraps a GtkButton** array.
  24. inherit
  25. WRAPPER_COLLECTION[ITEM_]
  26. insert
  27. EXCEPTIONS
  28. -- creation with_capacity, from_collection, from_external_array
  29. undefine copy, fill_tagged_out_memory, is_equal, out_in_tagged_out_memory
  30. end
  31. feature {} -- Creation
  32. from_external_array (an_array: POINTER; a_length: INTEGER)
  33. require
  34. array_not_null: an_array.is_not_null
  35. positive_length: a_length > 0
  36. do
  37. upper := a_length - 1
  38. capacity := a_length
  39. storage := storage.from_pointer(an_array)
  40. end
  41. with_capacity (a_capacity: INTEGER)
  42. require
  43. positive_capacity: a_capacity > 0
  44. do
  45. capacity := a_capacity
  46. upper := -1
  47. storage := storage.calloc(a_capacity)
  48. end
  49. feature {ANY}
  50. item (i: INTEGER_32): ITEM_
  51. local
  52. ptr: POINTER
  53. do
  54. ptr := storage.item(i)
  55. if ptr.is_not_null then
  56. Result := wrapper(ptr)
  57. end
  58. end
  59. first: ITEM_
  60. do
  61. Result := item(lower)
  62. end
  63. last: ITEM_
  64. do
  65. Result := item(upper)
  66. end
  67. feature {ANY} -- Writing:
  68. put (element: like item; i: INTEGER)
  69. do
  70. if element /= Void then
  71. storage.put(element.handle, i)
  72. else
  73. storage.put(default_pointer, i)
  74. end
  75. end
  76. set_all_with (v: like item)
  77. local
  78. i: INTEGER
  79. do
  80. from
  81. i := lower
  82. until
  83. i > upper
  84. loop
  85. put(v, i)
  86. i := i + 1
  87. end
  88. end
  89. feature {ANY} -- Adding:
  90. add_first (element: like item)
  91. -- Performance: O(count), not counting the eventual reallocation.
  92. local
  93. i, j: INTEGER
  94. do
  95. if count = capacity then
  96. capacity := capacity * 2
  97. storage := storage.realloc(count, capacity)
  98. end
  99. from
  100. i := upper
  101. j := i + 1
  102. until
  103. i = lower
  104. loop
  105. storage.put(storage.item(i), j)
  106. j := i
  107. i := i - 1
  108. end
  109. storage.put(null_or(element), lower)
  110. upper := upper + 1
  111. end
  112. add_last (element: like item)
  113. -- Performance: O(1), not counting the eventual reallocation.
  114. do
  115. if count = capacity then
  116. capacity := capacity * 2
  117. storage := storage.realloc(count, capacity)
  118. end
  119. check
  120. count = upper + 1
  121. end
  122. -- because the next put command relies on this assumption.
  123. storage.put(null_or(element), count)
  124. upper := upper + 1
  125. end
  126. add (element: like item; index: INTEGER)
  127. -- Performance: O(count-index), not counting the eventual reallocation
  128. local
  129. i, j: INTEGER
  130. do
  131. -- Add a new `element' at rank `index' : `count' is increased by one
  132. -- and range [`index' .. `upper'] is shifted right by one position.
  133. if count = capacity then
  134. capacity := capacity * 2
  135. storage := storage.realloc(count, capacity)
  136. end
  137. from
  138. i := upper
  139. j := upper + 1
  140. until
  141. i < index
  142. loop
  143. storage.put(storage.item(i), j)
  144. j := i
  145. i := i - 1
  146. end
  147. storage.put(null_or(element), index)
  148. upper := upper + 1
  149. end
  150. feature {ANY} -- Modification:
  151. copy (other: like Current)
  152. local
  153. i: INTEGER
  154. do
  155. if other /= Void then
  156. capacity := other.capacity
  157. upper := other.upper
  158. storage := storage.calloc(other.capacity)
  159. from
  160. i := lower
  161. until
  162. i > upper
  163. loop
  164. put(other.item(i), i)
  165. i := i + 1
  166. end
  167. end
  168. end
  169. force (element: ITEM_; index: INTEGER)
  170. do
  171. -- Make `element' the item at `index', enlarging the collection if
  172. -- necessary (new bounds except `index' are initialized with default
  173. -- values).
  174. if index > upper then
  175. upper := index
  176. if index > capacity then
  177. debug
  178. print(once "C_ARRAY.force: storage enlarged using realloc%N")
  179. end
  180. storage := storage.realloc(count, index)
  181. end
  182. end
  183. put(element, index)
  184. end
  185. from_collection (model: COLLECTION[like item])
  186. local
  187. i: ITERATOR[like item]
  188. do
  189. -- FIXME: signature should be model: TRAVERSABLE, once SE2.3 is out
  190. with_capacity(model.count)
  191. from
  192. i := model.new_iterator
  193. i.start
  194. until
  195. i.is_off
  196. loop
  197. add_last(i.item)
  198. i.next
  199. end
  200. end
  201. feature {ANY} -- Removing:
  202. remove_first
  203. -- Performance: O(count)
  204. local
  205. i, j: INTEGER
  206. do
  207. -- Remove the `first' element of the collection.
  208. from
  209. i := lower
  210. j := lower + 1
  211. until
  212. j > upper
  213. loop
  214. storage.put(storage.item(j), i)
  215. i := j
  216. j := j + 1
  217. end
  218. upper := upper - 1
  219. end
  220. remove_head (n: INTEGER)
  221. -- Performance: O(upper-n)
  222. local
  223. i, j: INTEGER
  224. do
  225. -- Remove the `n' elements of the collection.
  226. from
  227. i := lower
  228. j := lower + n
  229. until
  230. j > upper
  231. loop
  232. storage.put(storage.item(j), i)
  233. i := i + 1
  234. j := j + 1
  235. end
  236. upper := upper - n
  237. end
  238. remove (index: INTEGER)
  239. -- Performance: O(count)
  240. local
  241. i, j: INTEGER
  242. do
  243. -- Remove the item at position `index'. Followings items are shifted
  244. -- left by one position.
  245. from
  246. i := index
  247. j := index + 1
  248. until
  249. j >= upper
  250. loop
  251. storage.put(storage.item(j), i)
  252. i := j
  253. j := j + 1
  254. end
  255. upper := upper - 1
  256. end
  257. remove_last
  258. -- Performance: O(1)
  259. do
  260. -- Remove the `last' item.
  261. storage.put(default_pointer, upper)
  262. upper := upper - 1
  263. end
  264. remove_tail (n: INTEGER)
  265. -- Performance: O(n)
  266. local
  267. i, j: INTEGER
  268. do
  269. -- Remove the last `n' item(s).
  270. -- 0 1 2 3 4 5 6 7 8 9 (0,9 c=10)
  271. -- 0 1 2 3 4 5 6 x x x (n=3)
  272. from
  273. i := upper - n + 1
  274. until
  275. i > upper
  276. loop
  277. storage.put(default_pointer, i)
  278. i := i + 1
  279. end
  280. upper := upper - n
  281. end
  282. clear_count
  283. local
  284. i: INTEGER
  285. do
  286. -- Discard all items (`is_empty' is True after that call). If
  287. -- possible, the actual implementation is supposed to keep
  288. -- its internal storage area in order to refill `Current' in
  289. -- an efficient way.
  290. from
  291. i := lower
  292. until
  293. i > upper
  294. loop
  295. storage.put(default_pointer, i)
  296. i := i + 1
  297. end
  298. upper := lower
  299. end
  300. clear_count_and_capacity
  301. -- Instead of releasing the memory, it is reallocated with
  302. -- with 2 elements.
  303. do
  304. -- Discard all items (`is_empty' is True after that call). If possible,
  305. -- the actual implementation is supposed to release its internal
  306. -- storage area for this memory to be used by other objects.
  307. storage := storage.realloc(count, 2)
  308. upper := lower
  309. end
  310. feature {ANY} -- Looking and Searching:
  311. first_index_of (element: like item): INTEGER
  312. do
  313. Result := index_of(element, lower)
  314. end
  315. index_of (element: like item; start_index: INTEGER): INTEGER
  316. do
  317. -- Using `is_equal' for comparison, gives the index of the
  318. -- first occurrence of `element' at or after
  319. -- `start_index'. Answer `upper + 1' when `element' when the
  320. -- search fail.
  321. if element = Void then
  322. from
  323. Result := lower -- start_index
  324. until
  325. item(Result) = Void or else Result > upper
  326. loop
  327. Result := Result + 1
  328. end
  329. else
  330. from
  331. Result := lower -- start_index
  332. until
  333. item(Result).is_equal(element) or else Result > upper
  334. loop
  335. Result := Result + 1
  336. end
  337. end
  338. end
  339. reverse_index_of (element: like item; start_index: INTEGER): INTEGER
  340. do
  341. -- Using `is_equal' for comparison, gives the index of the
  342. -- first occurrence of `element' at or before
  343. -- `start_index'. Search is done in reverse direction, which
  344. -- means from the `start_index' down to the `lower'
  345. -- index. Answer `lower -1' when the search fail.
  346. if element = Void then
  347. from
  348. Result := start_index
  349. until
  350. item(Result) = Void or else Result < lower
  351. loop
  352. Result := Result - 1
  353. end
  354. else
  355. from
  356. Result := start_index
  357. until
  358. item(Result).is_equal(element) or else Result < lower
  359. loop
  360. Result := Result - 1
  361. end
  362. end
  363. end
  364. fast_first_index_of (element: like item): INTEGER
  365. -- Note: comparison is done using the address of the wrapped
  366. -- structure.
  367. do
  368. Result := fast_index_of(element, lower)
  369. end
  370. fast_index_of (element: like item; start_index: INTEGER): INTEGER
  371. -- Note: comparison is done using the address of the wrapped
  372. -- structure.
  373. local
  374. element_ptr: POINTER
  375. do
  376. -- Using basic `=' for comparison, gives the index of the
  377. -- first occurrence of `element' at or after
  378. -- `start_index'. Answer `upper + 1' when `element' when the
  379. -- search fail.
  380. element_ptr := null_or(element)
  381. from
  382. Result := lower
  383. until
  384. storage.item(Result) = element_ptr or else Result > upper
  385. loop
  386. Result := Result + 1
  387. end
  388. end
  389. fast_reverse_index_of (element: like item; start_index: INTEGER): INTEGER
  390. -- Note: comparison is done using the address of the wrapped
  391. -- structure
  392. local
  393. element_ptr: POINTER
  394. do
  395. -- Using basic `=' comparison, gives the index of the first
  396. -- occurrence of `element' at or before `start_index'. Search
  397. -- is done in reverse direction, which means from the
  398. -- `start_index' down to the `lower' index . Answer `lower
  399. -- -1' when the search fail.
  400. element_ptr := null_or(element)
  401. -- from Result:=start_index
  402. from
  403. Result := lower
  404. until
  405. storage.item(Result) = element_ptr or else Result > upper
  406. loop
  407. Result := Result - 1
  408. end
  409. end
  410. feature {ANY} -- Looking and comparison:
  411. is_equal (other: like Current): BOOLEAN
  412. -- Do both collections have the same `lower', `upper', and items?
  413. -- The basic `=' is used for comparison of items.
  414. -- Complexity: O(count)
  415. local
  416. i: INTEGER
  417. do
  418. if other = Void then
  419. Result := False
  420. elseif lower /= other.lower or upper /= other.upper then
  421. Result := False
  422. else
  423. from
  424. i := lower
  425. until
  426. Result = True or else i > upper
  427. loop
  428. Result := Current.storage.item(i) = other.storage.item(i)
  429. i := i + 1
  430. end
  431. end
  432. end
  433. all_default: BOOLEAN
  434. -- Do all items have their type's default value? Note: for
  435. -- non Void items, the test is performed with the
  436. -- `is_default' predicate.
  437. -- See also `clear_all'.
  438. local
  439. i: INTEGER
  440. do
  441. from
  442. i := lower
  443. until
  444. Result = False or else i > upper
  445. loop
  446. Result := storage.item(i).is_null
  447. i := i + 1
  448. end
  449. end
  450. occurrences (element: like item): INTEGER
  451. local
  452. i: ITERATOR[ITEM_]
  453. do
  454. -- Number of occurrences of `element' using `is_equal' for comparison.
  455. if element /= Void then
  456. from
  457. i := new_iterator
  458. i.start
  459. until
  460. i.is_off
  461. loop
  462. if element.is_equal(i.item) then
  463. Result := Result + 1
  464. end
  465. i.next
  466. end
  467. else
  468. from
  469. i := new_iterator
  470. i.start
  471. until
  472. i.is_off
  473. loop
  474. if i.item = Void then
  475. Result := Result + 1
  476. end
  477. i.next
  478. end
  479. end
  480. end
  481. fast_occurrences (element: like item): INTEGER
  482. -- Number of occurrences of `element' using basic its handle
  483. -- (or default_pointer) for comparison.
  484. local
  485. ep: POINTER; i: INTEGER
  486. do
  487. ep := null_or(element)
  488. from
  489. i := lower
  490. until
  491. i > upper
  492. loop
  493. if storage.item(i) = ep then
  494. Result := Result + 1
  495. end
  496. i := i + 1
  497. end
  498. end
  499. feature {ANY}
  500. -- Agents based features:
  501. -- for_each (action: ROUTINE[TUPLE[ITEM_]])
  502. -- do
  503. -- -- Apply `action' to every item of `Current'.
  504. -- --
  505. -- -- See also `for_all', `exists'.
  506. -- require
  507. -- action /= Void
  508. -- local
  509. -- i: INTEGER
  510. -- do
  511. -- from
  512. -- i := lower
  513. -- until
  514. -- i > upper
  515. -- loop
  516. -- action.call([item(i)])
  517. -- i := i + 1
  518. -- end
  519. -- end
  520. -- for_all (test: PREDICATE[TUPLE[ITEM_]]): BOOLEAN
  521. -- do
  522. -- -- Do all items satisfy `test'?
  523. -- --
  524. -- -- See also `for_each', `exists'.
  525. -- require
  526. -- test /= Void
  527. -- local
  528. -- i: INTEGER
  529. -- do
  530. -- from
  531. -- Result := True
  532. -- i := lower
  533. -- until
  534. -- not Result or else i > upper
  535. -- loop
  536. -- Result := test.item([item(i)])
  537. -- i := i + 1
  538. -- end
  539. -- end
  540. -- exists (test: PREDICATE[TUPLE[ITEM_]]): BOOLEAN
  541. -- do
  542. -- -- Does at least one item satisfy `test'?
  543. -- --
  544. -- -- See also `for_each', `for_all'.
  545. -- require
  546. -- test /= Void
  547. -- local
  548. -- i: INTEGER
  549. -- do
  550. -- from
  551. -- i := lower
  552. -- until
  553. -- Result or else i > upper
  554. -- loop
  555. -- Result := test.item([item(i)])
  556. -- i := i + 1
  557. -- end
  558. -- end
  559. feature {ANY} -- Other features:
  560. replace_all (old_value, new_value: like item)
  561. obsolete "Unimplemented!"
  562. do
  563. -- -- Replace all occurrences of the element `old_value' by `new_value' using `is_equal' for comparison.
  564. -- --
  565. -- -- See also `fast_replace_all', `move'.
  566. -- deferred
  567. -- ensure
  568. -- count = old count
  569. -- not (create {SAFE_EQUAL[ITEM_]}).test(old_value, new_value) implies occurrences(old_value) = 0
  570. end
  571. fast_replace_all (old_value, new_value: like item)
  572. obsolete "Unimplemented!"
  573. do
  574. -- -- Replace all occurrences of the element `old_value' by `new_value' using basic `=' for comparison.
  575. -- --
  576. -- -- See also `replace_all', `move'.
  577. -- deferred
  578. -- ensure
  579. -- count = old count
  580. -- old_value /= new_value implies fast_occurrences(old_value) = 0
  581. end
  582. -- move (lower_index, upper_index, distance: INTEGER)
  583. -- do
  584. -- -- Move range `lower_index' .. `upper_index' by `distance' positions.
  585. -- -- Negative distance moves towards lower indices.
  586. -- -- Free places get default values.
  587. -- --
  588. -- -- See also `slice', `replace_all'.
  589. -- require
  590. -- lower_index <= upper_index
  591. -- valid_index(lower_index)
  592. -- valid_index(lower_index + distance)
  593. -- valid_index(upper_index)
  594. -- valid_index(upper_index + distance)
  595. -- local
  596. -- default_value: like item; i: INTEGER
  597. -- do
  598. -- if distance = 0 then
  599. -- elseif distance < 0 then
  600. -- from
  601. -- i := lower_index
  602. -- until
  603. -- i > upper_index
  604. -- loop
  605. -- put(item(i), i + distance)
  606. -- put(default_value, i)
  607. -- i := i + 1
  608. -- end
  609. -- else
  610. -- from
  611. -- i := upper_index
  612. -- until
  613. -- i < lower_index
  614. -- loop
  615. -- put(item(i), i + distance)
  616. -- put(default_value, i)
  617. -- i := i - 1
  618. -- end
  619. -- end
  620. -- ensure
  621. -- count = old count
  622. -- end
  623. slice (min, max: INTEGER): like Current
  624. obsolete "Unimplemented!"
  625. do
  626. -- -- New collection consisting of items at indexes in [`min'..`max'].
  627. -- -- Result has the same dynamic type as `Current'.
  628. -- -- The `lower' index of the `Result' is the same as `lower'.
  629. -- --
  630. -- -- See also `from_collection', `move', `replace_all'.
  631. -- require
  632. -- lower <= min
  633. -- max <= upper
  634. -- min <= max + 1
  635. -- deferred
  636. -- ensure
  637. -- same_dynamic_type(Result)
  638. -- Result.count = max - min + 1
  639. -- Result.lower = lower
  640. end
  641. reverse
  642. obsolete "Unimplemented!"
  643. do
  644. -- -- Reverse the order of the elements.
  645. -- deferred
  646. -- ensure
  647. -- count = old count
  648. end
  649. feature {ANY} -- struct_size: INTEGER
  650. count: INTEGER
  651. do
  652. Result := upper - lower + 1
  653. end
  654. upper: INTEGER
  655. lower: INTEGER 0
  656. is_empty: BOOLEAN
  657. do
  658. Result := upper = -1 or else storage.is_null
  659. end
  660. new_iterator: ITERATOR[ITEM_]
  661. do
  662. create {ITERATOR_ON_C_ARRAY[ITEM_]} Result.from_array(Current)
  663. end
  664. as_c_array: NATIVE_ARRAY[POINTER]
  665. do
  666. Result := storage
  667. end
  668. feature {C_ARRAY, WRAPPER_HANDLER} -- Implementation
  669. storage: NATIVE_ARRAY[POINTER]
  670. capacity: INTEGER
  671. feature {} -- Implement manifest generic creation (very low-level):
  672. manifest_make (needed_capacity: INTEGER)
  673. -- Manifest creation of a LLVM_TYPE_ARRAY
  674. require
  675. needed_capacity > 0
  676. do
  677. with_capacity(needed_capacity)
  678. upper := needed_capacity - 1
  679. end
  680. manifest_put (index: INTEGER_32; element: ITEM_)
  681. do
  682. put(element, index)
  683. end
  684. feature {ANY} -- TODO: unimplemented
  685. clear_all
  686. do
  687. not_yet_implemented
  688. end
  689. fast_has (an_item: ITEM_): BOOLEAN
  690. do
  691. not_yet_implemented
  692. end
  693. has (an_item: ITEM_): BOOLEAN
  694. do
  695. not_yet_implemented
  696. end
  697. swap (i1, i2: INTEGER)
  698. do
  699. not_yet_implemented
  700. end
  701. append_collection (another: COLLECTION[ITEM_])
  702. do
  703. not_yet_implemented
  704. end
  705. end -- class C_ARRAY