/src/lib/storage/low_level/native_array.e

http://github.com/tybor/Liberty · Specman e · 842 lines · 664 code · 51 blank · 127 comment · 32 complexity · ad3fadb4ed622917203ceafc7a480f9f MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. expanded class NATIVE_ARRAY[E_]
  5. --
  6. -- This class gives access to the lowest level for arrays. As any low level array, you can
  7. -- get high performances with NATIVE_ARRAYs, but you loose most valid bounds checks (as
  8. -- you can do in plain C code for example).
  9. --
  10. -- Note: this class is the basic support for most of our high-level arrays-like classes: STRING,
  11. -- ARRAY, FAST_ARRAY as well as MUTABLE_BIG_INTEGER. Each class using some attribute of some
  12. -- NATIVE_ARRAY type needs an attribute named `capacity' with value set to the size of the
  13. -- actual NATIVE_ARRAY. Value has to be adjusted after each calloc/realloc/create_from.
  14. --
  15. insert
  16. SAFE_EQUAL[E_]
  17. create {ANY}
  18. default_create, manifest_creation
  19. feature {ANY} -- Basic features:
  20. element_sizeof: INTEGER
  21. -- The size in number of bytes for type `E_'.
  22. external "built_in"
  23. end
  24. calloc (nb_elements: INTEGER): like Current
  25. -- Allocate a new array of `nb_elements' of type `E_'.
  26. -- The new array is initialized with default values.
  27. require
  28. nb_elements > 0
  29. external "built_in"
  30. ensure
  31. Result.is_not_null
  32. Result.all_default(nb_elements - 1)
  33. end
  34. item (index: INTEGER): E_
  35. -- To read an `item'.
  36. -- Assume that `calloc' is already done and that `index' is the range [0 .. `nb_elements'-1].
  37. require
  38. index >= 0
  39. external "built_in"
  40. end
  41. put (element: E_; index: INTEGER)
  42. -- To write an item.
  43. -- Assume that `calloc' is already done and that `index'
  44. -- is the range [0 .. `nb_elements'-1].
  45. require
  46. index >= 0
  47. external "built_in"
  48. ensure
  49. item(index) = element
  50. end
  51. feature {ANY}
  52. realloc (old_nb_elts, new_nb_elts: INTEGER): like Current
  53. -- Assume Current is a valid NATIVE_ARRAY in range
  54. -- [0 .. `old_nb_elts'-1]. Allocate a bigger new array in
  55. -- range [0 .. `new_nb_elts'-1].
  56. -- Old range is copied in the new allocated array.
  57. -- New items are initialized with default values.
  58. require
  59. is_not_null
  60. old_nb_elts > 0
  61. old_nb_elts < new_nb_elts
  62. do
  63. Result := calloc(new_nb_elts)
  64. Result.copy_from(Current, old_nb_elts - 1)
  65. ensure
  66. Result.is_not_null
  67. end
  68. feature {ANY} -- Comparison:
  69. memcmp (other: like Current; capacity: INTEGER): BOOLEAN
  70. -- True if all elements in range [0 .. `capacity'-1] are identical using `is_equal'.
  71. -- Assume Current and `other' are big enough.
  72. -- See also `fast_memcmp'.
  73. require
  74. capacity > 0 implies other.is_not_null
  75. local
  76. i: INTEGER
  77. do
  78. from
  79. i := capacity - 1
  80. until
  81. i < 0 or else not safe_equal(item(i), other.item(i))
  82. loop
  83. i := i - 1
  84. end
  85. Result := i < 0
  86. end
  87. slice_memcmp (at: INTEGER; other: like Current; other_lower, other_upper: INTEGER): BOOLEAN
  88. -- True if all elements in range [0 .. `other_upper' - `other_lower'] are identical
  89. -- to the elements in range [`other_lower' .. `other_upper'] of `other' using
  90. -- `is_equal'. Assume `Current' and `other' are big enough.
  91. -- See also `slice_fast_memcmp'.
  92. require
  93. at >= 0
  94. other_lower >= 0
  95. other_upper >= other_lower - 1
  96. other_upper >= other_lower implies other.is_not_null
  97. local
  98. i: INTEGER
  99. do
  100. from
  101. i := other_upper - other_lower
  102. until
  103. i < 0 or else not safe_equal(item(at + i), other.item(other_lower + i))
  104. loop
  105. i := i - 1
  106. end
  107. Result := i < 0
  108. end
  109. fast_memcmp (other: like Current; capacity: INTEGER): BOOLEAN
  110. -- Same jobs as `memcmp' but uses infix "=" instead of `is_equal'.
  111. require
  112. capacity > 0 implies other.is_not_null
  113. local
  114. i: INTEGER
  115. do
  116. from
  117. i := capacity - 1
  118. until
  119. i < 0 or else item(i) /= other.item(i)
  120. loop
  121. i := i - 1
  122. end
  123. Result := i < 0
  124. end
  125. slice_fast_memcmp (at: INTEGER; other: like Current; other_lower, other_upper: INTEGER): BOOLEAN
  126. -- Same jobs as `slice_memcmp' but uses infix "=" instead of `is_equal'.
  127. require
  128. at >= 0
  129. other_lower >= 0
  130. other_upper >= other_lower - 1
  131. other_upper >= other_lower implies other.is_not_null
  132. local
  133. i: INTEGER
  134. do
  135. from
  136. i := other_upper - other_lower
  137. until
  138. i < 0 or else item(at + i) /= other.item(other_lower + i)
  139. loop
  140. i := i - 1
  141. end
  142. Result := i < 0
  143. end
  144. deep_memcmp (other: like Current; capacity: INTEGER): BOOLEAN
  145. -- Same jobs as `memcmp' but uses `is_deep_equal' instead of `is_equal'.
  146. require
  147. capacity > 0 implies other.is_not_null
  148. local
  149. i: INTEGER; e1, e2: like item
  150. do
  151. from
  152. i := capacity - 1
  153. Result := True
  154. until
  155. not Result or else i < 0
  156. loop
  157. e1 := item(i)
  158. e2 := other.item(i)
  159. if e1 = e2 then
  160. elseif e1 /= Void then
  161. if e2 /= Void then
  162. Result := e1.is_deep_equal(e2)
  163. else
  164. Result := False
  165. end
  166. else
  167. Result := False
  168. end
  169. i := i - 1
  170. end
  171. end
  172. slice_deep_memcmp (at: INTEGER; other: like Current; other_lower, other_upper: INTEGER): BOOLEAN
  173. -- Same jobs as `slice_memcmp' but uses `is_deep_equal' instead of `is_equal'.
  174. require
  175. at >= 0
  176. other_lower >= 0
  177. other_upper >= other_lower - 1
  178. other_upper >= other_lower implies other.is_not_null
  179. local
  180. i: INTEGER; e1, e2: like item
  181. do
  182. from
  183. i := other_upper - other_lower
  184. Result := True
  185. until
  186. not Result or else i < 0
  187. loop
  188. e1 := item(i)
  189. e2 := other.item(i)
  190. if e1 = e2 then
  191. elseif e1 /= Void then
  192. if e2 /= Void then
  193. Result := e1.is_deep_equal(e2)
  194. else
  195. Result := False
  196. end
  197. else
  198. Result := False
  199. end
  200. i := i - 1
  201. end
  202. end
  203. feature {ANY} -- Searching:
  204. first_index_of (element: like item; upper: INTEGER): INTEGER
  205. -- Using `is_equal' for comparison, gives the index of the first occurrence of `element' at or after
  206. -- `0'. Answer `upper + 1' when the search fail.
  207. -- See also `fast_index_of', `reverse_index_of'.
  208. require
  209. upper >= 0
  210. do
  211. from
  212. check
  213. Result = 0
  214. end
  215. until
  216. Result > upper or else safe_equal(element, item(Result))
  217. loop
  218. Result := Result + 1
  219. end
  220. ensure
  221. Result.in_range(0, upper + 1)
  222. Result <= upper implies safe_equal(element, item(Result))
  223. end
  224. index_of (element: like item; start_index, upper: INTEGER): INTEGER
  225. -- Using `is_equal' for comparison, gives the index of the first occurrence of `element' at or after
  226. -- `start_index'. Answer `upper + 1' when the search fail.
  227. -- See also `fast_index_of', `reverse_index_of'.
  228. require
  229. start_index >= 0
  230. start_index <= upper
  231. do
  232. from
  233. Result := start_index
  234. until
  235. Result > upper or else safe_equal(element, item(Result))
  236. loop
  237. Result := Result + 1
  238. end
  239. ensure
  240. Result.in_range(start_index, upper + 1)
  241. Result <= upper implies safe_equal(element, item(Result))
  242. end
  243. reverse_index_of (element: like item; upper: INTEGER): INTEGER
  244. -- Using `is_equal' for comparison, gives the index of the first occurrence of `element' at or before
  245. -- `upper'. Search is done in reverse direction, which means from `upper' down to the
  246. -- `0'. Answer `-1' when the search fail.
  247. -- See also `fast_reverse_index_of', `index_of'.
  248. require
  249. upper >= -1
  250. do
  251. from
  252. Result := upper
  253. until
  254. Result < 0 or else safe_equal(element, item(Result))
  255. loop
  256. Result := Result - 1
  257. end
  258. ensure
  259. Result.in_range(-1, upper)
  260. Result > 0 implies safe_equal(element, item(Result))
  261. end
  262. fast_index_of (element: like item; start_index, upper: INTEGER): INTEGER
  263. -- Using basic `=' for comparison, gives the index of the first occurrence of `element' at or after
  264. -- `start_index'. Answer `upper + 1' when the search fail.
  265. -- See also `index_of', `reverse_index_of'.
  266. require
  267. start_index >= 0
  268. start_index <= upper + 1
  269. do
  270. from
  271. Result := start_index
  272. until
  273. Result > upper or else element = item(Result)
  274. loop
  275. Result := Result + 1
  276. end
  277. ensure
  278. Result.in_range(start_index, upper + 1)
  279. Result <= upper implies element = item(Result)
  280. end
  281. fast_reverse_index_of (element: like item; upper: INTEGER): INTEGER
  282. -- Using basic `=' for comparison, gives the index of the first occurrence of `element' at or before
  283. -- `upper'. Search is done in reverse direction, which means from `upper' down to the
  284. -- `0'. Answer `-1' when the search fail.
  285. -- See also `reverse_index_of', `index_of'.
  286. require
  287. upper >= -1
  288. do
  289. from
  290. Result := upper
  291. until
  292. Result < 0 or else element = item(Result)
  293. loop
  294. Result := Result - 1
  295. end
  296. ensure
  297. Result.in_range(-1, upper)
  298. Result > 0 implies element = item(Result)
  299. end
  300. fast_first_index_of (element: like item; upper: INTEGER): INTEGER
  301. -- Using basic `=' for comparison, gives the index of the first occurrence of `element' at or after
  302. -- `0'. Answer `upper + 1' when the search fail.
  303. -- See also `fast_index_of', `reverse_index_of'.
  304. require
  305. upper >= 0
  306. do
  307. from
  308. check
  309. Result = 0
  310. end
  311. until
  312. Result > upper or else element = item(Result)
  313. loop
  314. Result := Result + 1
  315. end
  316. ensure
  317. Result.in_range(0, upper + 1)
  318. Result <= upper implies element = item(Result)
  319. end
  320. has (element: like item; upper: INTEGER): BOOLEAN
  321. -- Look for `element' using `is_equal' for comparison.
  322. -- Also consider `fast_has' to choose the most appropriate.
  323. require
  324. upper >= -1
  325. local
  326. i: INTEGER
  327. do
  328. from
  329. i := upper
  330. until
  331. Result or else i < 0
  332. loop
  333. Result := safe_equal(element, item(i))
  334. i := i - 1
  335. end
  336. end
  337. slice_has (element: like item; lower, upper: INTEGER): BOOLEAN
  338. -- Look for `element' using `is_equal' for comparison.
  339. -- Also consider `slice_fast_has' to choose the most appropriate.
  340. require
  341. lower >= 0
  342. upper >= lower - 1
  343. local
  344. i: INTEGER
  345. do
  346. from
  347. i := lower
  348. until
  349. Result or else i > upper
  350. loop
  351. Result := safe_equal(element, item(i))
  352. i := i + 1
  353. end
  354. end
  355. fast_has (element: like item; upper: INTEGER): BOOLEAN
  356. -- Look for `element' using basic `=' for comparison.
  357. -- Also consider `has' to choose the most appropriate.
  358. require
  359. upper >= -1
  360. local
  361. i: INTEGER
  362. do
  363. from
  364. i := upper
  365. until
  366. i < 0 or else element = item(i)
  367. loop
  368. i := i - 1
  369. end
  370. Result := i >= 0
  371. end
  372. slice_fast_has (element: like item; lower, upper: INTEGER): BOOLEAN
  373. -- Look for `element' using `is_equal' for comparison.
  374. -- Also consider `slice_fast_has' to choose the most appropriate.
  375. require
  376. lower >= 0
  377. upper >= lower - 1
  378. local
  379. i: INTEGER
  380. do
  381. from
  382. i := lower
  383. until
  384. Result or else i > upper
  385. loop
  386. Result := element = item(i)
  387. i := i + 1
  388. end
  389. end
  390. feature {ANY} -- Removing:
  391. remove_first (upper: INTEGER)
  392. -- Assume `upper' is a valid index.
  393. -- Move range [1 .. `upper'] by 1 position left.
  394. require
  395. upper >= 0
  396. local
  397. i: INTEGER
  398. do
  399. from
  400. until
  401. i = upper
  402. loop
  403. put(item(i + 1), i)
  404. i := i + 1
  405. end
  406. end
  407. remove (index, upper: INTEGER)
  408. -- Assume `upper' is a valid index.
  409. -- Move range [`index' + 1 .. `upper'] by 1 position left.
  410. require
  411. index >= 0
  412. index <= upper
  413. local
  414. i: INTEGER
  415. do
  416. from
  417. i := index
  418. until
  419. i = upper
  420. loop
  421. put(item(i + 1), i)
  422. i := i + 1
  423. end
  424. end
  425. feature {ANY} -- Replacing:
  426. replace_all (old_value, new_value: like item; upper: INTEGER)
  427. -- Replace all occurrences of the element `old_value' by `new_value' using `is_equal' for comparison.
  428. -- See also `fast_replace_all' to choose the appropriate one.
  429. require
  430. upper >= -1
  431. local
  432. i: INTEGER
  433. do
  434. from
  435. i := upper
  436. until
  437. i < 0
  438. loop
  439. if safe_equal(old_value, item(i)) then
  440. put(new_value, i)
  441. end
  442. i := i - 1
  443. end
  444. end
  445. fast_replace_all (old_value, new_value: like item; upper: INTEGER)
  446. -- Replace all occurrences of the element `old_value' by `new_value'
  447. -- using basic `=' for comparison.
  448. -- See also `replace_all' to choose the appropriate one.
  449. require
  450. upper >= -1
  451. local
  452. i: INTEGER
  453. do
  454. from
  455. i := upper
  456. until
  457. i < 0
  458. loop
  459. if old_value = item(i) then
  460. put(new_value, i)
  461. end
  462. i := i - 1
  463. end
  464. end
  465. feature {ANY} -- Adding:
  466. copy_at (at: INTEGER; src: like Current; src_capacity: INTEGER)
  467. -- Copy range [0 .. `src_capacity - 1'] of `src' to range [`at' .. `at + src_capacity - 1'] of `Current'.
  468. -- No subscript checking.
  469. require
  470. at >= 0
  471. src_capacity >= 0
  472. local
  473. at_idx, src_idx: INTEGER
  474. do
  475. from
  476. src_idx := src_capacity - 1
  477. at_idx := at + src_idx
  478. until
  479. src_idx < 0
  480. loop
  481. put(src.item(src_idx), at_idx)
  482. src_idx := src_idx - 1
  483. at_idx := at_idx - 1
  484. end
  485. end
  486. slice_copy (at: INTEGER; src: like Current; src_min, src_max: INTEGER)
  487. -- Copy range [`src_min' .. `src_max'] of `src' to range [`at' .. `at + src_max - src_min'] of `Current'.
  488. -- No subscript checking.
  489. --*** NATIVE_ARRAY[CHARACTER/INTEGER_8] are modified byte per byte. Efficiency should be improved here.
  490. require
  491. at >= 0
  492. src_max >= src_min - 1
  493. useful_work: src /= Current or at /= src_min
  494. external "built_in"
  495. end
  496. feature {ANY} -- Other:
  497. set_all_with (v: like item; upper: INTEGER)
  498. -- Set all elements in range [0 .. `upper'] with value `v'.
  499. require
  500. upper >= -1
  501. do
  502. set_slice_with(v, 0, upper)
  503. end
  504. set_slice_with (v: like item; lower, upper: INTEGER)
  505. -- Set all elements in range [`lower' .. `upper'] with value `v'.
  506. require
  507. lower >= 0
  508. upper >= lower - 1
  509. local
  510. i: INTEGER
  511. do
  512. from
  513. i := lower
  514. until
  515. i > upper
  516. loop
  517. put(v, i)
  518. i := i + 1
  519. end
  520. end
  521. clear_all (upper: INTEGER)
  522. -- Set all elements in range [0 .. `upper'] with the default value.
  523. require
  524. upper >= -1
  525. local
  526. v: E_; i: INTEGER
  527. do
  528. from
  529. i := upper
  530. until
  531. i < 0
  532. loop
  533. put(v, i)
  534. i := i - 1
  535. end
  536. ensure
  537. all_default(upper)
  538. end
  539. clear (lower, upper: INTEGER)
  540. -- Set all elements in range [`lower' .. `upper'] with the default value.
  541. require
  542. lower >= 0
  543. upper >= lower - 1
  544. local
  545. v: E_; i: INTEGER
  546. do
  547. from
  548. i := lower
  549. until
  550. i > upper
  551. loop
  552. put(v, i)
  553. i := i + 1
  554. end
  555. end
  556. copy_from (model: like Current; upper: INTEGER)
  557. -- Assume `upper' is a valid index both in Current and `model'.
  558. require
  559. upper >= -1
  560. do
  561. copy_slice_from(model, 0, upper)
  562. end
  563. copy_slice_from (model: like Current; lower, upper: INTEGER)
  564. -- Assume `upper' is a valid index both in Current and `model'.
  565. require
  566. lower >= 0
  567. upper >= lower - 1
  568. useful_work: model /= Current or else lower > 0
  569. do
  570. slice_copy(0, model, lower, upper)
  571. end
  572. deep_twin_from (capacity: INTEGER): like Current
  573. -- To implement `deep_twin'. Allocate a new array of `capacity' initialized with `deep_twin'.
  574. -- Assume `capacity' is valid both in `Current' and `model'.
  575. require
  576. capacity >= 0
  577. local
  578. i: INTEGER; element: like item
  579. do
  580. if capacity > 0 then
  581. from
  582. Result := calloc(capacity)
  583. i := capacity - 1
  584. until
  585. i < 0
  586. loop
  587. element := item(i)
  588. if element /= Void then
  589. element := element.deep_twin
  590. end
  591. Result.put(element, i)
  592. i := i - 1
  593. end
  594. end
  595. end
  596. move (lower, upper, offset: INTEGER)
  597. -- Move range [`lower' .. `upper'] by `offset' positions.
  598. -- Freed positions are not initialized to default values.
  599. require
  600. lower >= 0
  601. upper >= lower
  602. lower + offset >= 0
  603. local
  604. i: INTEGER
  605. do
  606. if offset = 0 then
  607. elseif offset < 0 then
  608. from
  609. i := lower
  610. until
  611. i > upper
  612. loop
  613. put(item(i), i + offset)
  614. i := i + 1
  615. end
  616. else
  617. from
  618. i := upper
  619. until
  620. i < lower
  621. loop
  622. put(item(i), i + offset)
  623. i := i - 1
  624. end
  625. end
  626. end
  627. occurrences (element: like item; upper: INTEGER): INTEGER
  628. -- Number of occurrences of `element' in range [0 .. `upper'] using `is_equal' for comparison.
  629. -- See also `fast_occurrences' to chose the appropriate one.
  630. require
  631. upper >= -1
  632. local
  633. i: INTEGER
  634. do
  635. from
  636. i := upper
  637. until
  638. i < 0
  639. loop
  640. if safe_equal(element, item(i)) then
  641. Result := Result + 1
  642. end
  643. i := i - 1
  644. end
  645. end
  646. slice_occurrences (element: like item; lower, upper: INTEGER): INTEGER
  647. -- Number of occurrences of `element' in range [`lower' .. `upper'] using `is_equal' for comparison.
  648. -- See also `slice_fast_occurrences' to chose the appropriate one.
  649. require
  650. lower >= 0
  651. upper >= lower - 1
  652. local
  653. i: INTEGER
  654. do
  655. from
  656. i := lower
  657. until
  658. i > upper
  659. loop
  660. if safe_equal(element, item(i)) then
  661. Result := Result + 1
  662. end
  663. i := i + 1
  664. end
  665. end
  666. fast_occurrences (element: like item; upper: INTEGER): INTEGER
  667. -- Number of occurrences of `element' in range [0 .. `upper'] using basic "=" for comparison.
  668. -- See also `occurrences' to chose the appropriate one.
  669. require
  670. upper >= -1
  671. local
  672. i: INTEGER
  673. do
  674. from
  675. i := upper
  676. until
  677. i < 0
  678. loop
  679. if element = item(i) then
  680. Result := Result + 1
  681. end
  682. i := i - 1
  683. end
  684. end
  685. slice_fast_occurrences (element: like item; lower, upper: INTEGER): INTEGER
  686. -- Number of occurrences of `element' in range [`lower' .. `upper']
  687. -- using basic "=" for comparison.
  688. -- See also `slice_occurrences' to chose the appropriate one.
  689. require
  690. lower >= 0
  691. upper >= lower - 1
  692. local
  693. i: INTEGER
  694. do
  695. from
  696. i := lower
  697. until
  698. i > upper
  699. loop
  700. if element = item(i) then
  701. Result := Result + 1
  702. end
  703. i := i + 1
  704. end
  705. end
  706. all_default (upper: INTEGER): BOOLEAN
  707. -- Do all items in range [0 .. `upper'] have their type's default value?
  708. -- Note: for non Void items, the test is performed with the `is_default' predicate.
  709. require
  710. upper >= -1
  711. do
  712. Result := slice_default(0, upper)
  713. end
  714. slice_default (lower, upper: INTEGER): BOOLEAN
  715. -- Do all items in range [`lower' .. `upper'] have their type's default value?
  716. -- Note: for non Void items, the test is performed with the `is_default' predicate.
  717. require
  718. lower >= 0
  719. upper >= lower - 1
  720. local
  721. i: INTEGER; v: like item
  722. do
  723. from
  724. Result := True
  725. i := lower
  726. until
  727. i > upper or else not Result
  728. loop
  729. v := item(i)
  730. if v /= Void then
  731. Result := v.is_default
  732. end
  733. i := i + 1
  734. end
  735. end
  736. feature {ANY} -- Interfacing with other languages:
  737. to_external: POINTER
  738. -- Gives access to the C pointer on the area of storage.
  739. do
  740. Result := to_pointer
  741. end
  742. from_pointer (pointer: POINTER): like Current
  743. -- Convert `pointer' into Current type.
  744. external "built_in"
  745. end
  746. is_not_null: BOOLEAN
  747. do
  748. Result := to_pointer.is_not_null
  749. end
  750. is_null: BOOLEAN
  751. do
  752. Result := to_pointer.is_null
  753. end
  754. feature {} -- Implement manifest generic creation.
  755. manifest_make (needed_capacity: INTEGER)
  756. -- Manifest creation (see also `calloc' and `realloc' for creation).
  757. do
  758. check
  759. -- Automatic usage of `calloc'.
  760. False
  761. end
  762. end
  763. manifest_put (index: INTEGER; element: like item)
  764. do
  765. check
  766. -- Automatic usage of `put'.
  767. False
  768. end
  769. end
  770. manifest_semicolon_check: BOOLEAN False
  771. end -- class NATIVE_ARRAY
  772. --
  773. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  774. --
  775. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  776. -- of this software and associated documentation files (the "Software"), to deal
  777. -- in the Software without restriction, including without limitation the rights
  778. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  779. -- copies of the Software, and to permit persons to whom the Software is
  780. -- furnished to do so, subject to the following conditions:
  781. --
  782. -- The above copyright notice and this permission notice shall be included in
  783. -- all copies or substantial portions of the Software.
  784. --
  785. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  786. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  787. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  788. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  789. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  790. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  791. -- THE SOFTWARE.