/src/lib/storage/collection/ring_array.e
Specman e | 902 lines | 762 code | 57 blank | 83 comment | 67 complexity | 1d2cac95c4c5bd4d22388fe491d8132c MD5 | raw file
1-- This file is part of a Liberty Eiffel library. 2-- See the full copyright at the end. 3-- 4class RING_ARRAY[E_] 5 -- 6 -- The main purpose of the RING_ARRAY implementation is to allow efficient manipulation of the queue 7 -- concept (i.e. using for example `add_last' / `first' / `remove_first'). Actually, the RING_ARRAY 8 -- implementation provides very good performance for all of the following features: `add_last', `last', 9 -- `remove_last', `add_first', `first', `remove_first'. 10 -- Furthermore, the RING_ARRAY implementation also has a common point with traditional ARRAY: the `lower' 11 -- bound can be any arbitrary value, even a negative one. 12 -- As ARRAY or FAST_ARRAY, the RING_ARRAY uses only one chunk of memory, the `storage' area which is a 13 -- NATIVE_ARRAY. This internal `storage' area is used in a circular way (no left- or right-alignment), 14 -- hence the very good performances for using it as a queue. Finally, if you have to perform many insertions 15 -- in the middle of your COLLECTION, do not expect good performance with a RING_ARRAY, but consider 16 -- LINKED_LIST or TWO_WAY_LINKED_LIST. 17 -- 18 19inherit 20 COLLECTION[E_] 21 redefine default_create 22 end 23 24insert 25 ARRAYED_COLLECTION[E_] 26 redefine first, to_external, default_create 27 end 28 NATIVE_ARRAY_COLLECTOR[E_] 29 undefine out_in_tagged_out_memory 30 redefine default_create 31 end 32 33create {ANY} 34 make, with_capacity, from_collection, manifest_creation, default_create 35 36feature {} 37 default_create 38 do 39 make(0, -1) 40 end 41 42feature {ANY} 43 lower: INTEGER 44 -- Lower index bound 45 46feature {ANY} -- Creation and Modification: 47 make (min_index, max_index: INTEGER) 48 -- Prepare the array to hold values for indexes in range 49 -- [`min_index' .. `max_index']. Set all values to default. 50 -- When `max_index' = `min_index' - 1, the array `is_empty'. 51 require 52 valid_bounds: min_index <= max_index + 1 53 local 54 needed: INTEGER 55 do 56 lower := min_index 57 upper := max_index 58 needed := max_index - min_index + 1 59 storage_lower := 0 60 if needed > 0 then 61 if capacity < needed then 62 storage := storage.calloc(needed) 63 capacity := needed 64 else 65 clear_all 66 end 67 end 68 next_generation 69 ensure 70 left_aligned: storage_lower = 0 71 lower_set: lower = min_index 72 upper_set: upper = max_index 73 items_set: all_default 74 end 75 76 with_capacity (needed_capacity, low: INTEGER) 77 -- Create an empty array with `capacity' initialized 78 -- at least to `needed_capacity' and `lower' set to `low'. 79 require 80 needed_capacity >= 0 81 do 82 if capacity < needed_capacity then 83 storage := storage.calloc(needed_capacity) 84 capacity := needed_capacity 85 end 86 lower := low 87 upper := low - 1 88 storage_lower := 0 89 next_generation 90 ensure 91 left_aligned: storage_lower = 0 92 empty: is_empty 93 big_enough: needed_capacity <= capacity 94 lower_set: lower = low 95 end 96 97feature {ANY} -- Modification: 98 resize (min_index, max_index: INTEGER) 99 -- Resize to bounds `min_index' and `max_index'. Do not lose any 100 -- item whose index is in both [`lower' .. `upper'] and 101 -- [`min_index' .. `max_index']. New positions if any are 102 -- initialized with the appropriate default value. 103 require 104 min_index <= max_index + 1 105 local 106 bubble, old_wrap, needed, inter_max, inter_min: INTEGER 107 do 108 needed := max_index - min_index + 1 109 if needed > 0 then 110 bubble := needed - capacity 111 if needed > capacity then 112 old_wrap := wrap_point 113 if capacity = 0 then 114 storage := storage.calloc(needed) 115 else 116 storage := storage.realloc(capacity, needed) 117 end 118 capacity := needed 119 end 120 inter_max := max_index.min(upper) 121 inter_min := min_index.max(lower) 122 if inter_max >= inter_min then 123 if old_wrap.in_range(inter_min, inter_max) then 124 if bubble > 0 then 125 -- A bubble was created inside the data. Update upper to acknowledge this (preconditions 126 -- will fail if we don't) 127 upper := upper + bubble 128 squeeze_bubble(inter_min, inter_max + bubble, old_wrap, bubble) 129 -- Upper is written below, no need to re-adjust 130 end 131 end 132 storage_lower := storage_lower - lower + min_index 133 if storage_lower < 0 then 134 storage_lower := storage_lower + capacity 135 elseif storage_lower >= capacity then 136 storage_lower := storage_lower - capacity 137 end 138 lower := min_index 139 upper := max_index 140 if inter_min > lower then 141 clear_slice(lower, inter_min - 1) 142 end 143 if inter_max < upper then 144 clear_slice(inter_max + 1, upper) 145 end 146 else 147 lower := min_index 148 upper := max_index 149 clear_all 150 end 151 else 152 lower := min_index 153 upper := max_index 154 end 155 next_generation 156 ensure 157 lower = min_index 158 upper = max_index 159 end 160 161 reindex (new_lower: INTEGER) 162 -- Change indexing to take in account the expected `new_lower' 163 -- index. The `upper' index is translated accordingly. 164 do 165 upper := upper + new_lower - lower 166 lower := new_lower 167 ensure 168 lower = new_lower 169 count = old count 170 end 171 172feature {ANY} -- Implementation of deferred: 173 count: INTEGER 174 do 175 Result := upper - lower + 1 176 end 177 178 is_empty: BOOLEAN 179 do 180 Result := upper < lower -- *** Is there a better implementation ? *** Dom march 30th 2006 *** 181 end 182 183 subarray (min, max: INTEGER): like Current 184 do 185 Result := slice(min, max) 186 Result.reindex(min) 187 ensure then 188 Result.lower = min 189 end 190 191 item (i: INTEGER): E_ 192 do 193 Result := storage.item(storage_index(i)) 194 end 195 196 put (element: like item; i: INTEGER) 197 do 198 storage.put(element, storage_index(i)) 199 next_generation 200 end 201 202 force (element: like item; index: INTEGER) 203 require else 204 True 205 do 206 if upper < index then 207 if index = upper + 1 then 208 add_last(element) 209 else 210 resize(lower, index) 211 put(element, index) 212 end 213 elseif index < lower then 214 if index = lower - 1 then 215 add_first(element) 216 reindex(lower - 1) 217 else 218 resize(index, upper) 219 put(element, index) 220 end 221 else 222 put(element, index) 223 end 224 ensure then 225 lower = index.min(old lower) 226 end 227 228 copy (other: like Current) 229 local 230 needed_capacity, o_s_u: INTEGER 231 do 232 storage_lower := 0 233 lower := other.lower 234 upper := other.upper 235 needed_capacity := upper - lower + 1 236 if capacity < needed_capacity then 237 storage := storage.calloc(needed_capacity) 238 capacity := needed_capacity 239 end 240 if needed_capacity > 0 then 241 o_s_u := other.storage_upper 242 if o_s_u >= other.storage_lower then 243 storage.slice_copy(0, other.storage, other.storage_lower, o_s_u) 244 else 245 storage.slice_copy(0, other.storage, other.storage_lower, other.capacity - 1) 246 storage.slice_copy(other.capacity - other.storage_lower, other.storage, 0, o_s_u) 247 end 248 end 249 next_generation 250 end 251 252 set_all_with (v: like item) 253 local 254 s_u: INTEGER 255 do 256 if is_empty then 257 else 258 s_u := storage_upper 259 if storage_lower <= s_u then 260 storage.set_slice_with(v, storage_lower, s_u) 261 else 262 storage.set_all_with(v, s_u) 263 storage.set_slice_with(v, storage_lower, capacity - 1) 264 end 265 end 266 next_generation 267 end 268 269 remove_first 270 do 271 lower := lower + 1 272 storage_lower := storage_lower + 1 273 if storage_lower = capacity then 274 storage_lower := 0 275 end 276 next_generation 277 ensure then 278 upper = old upper 279 end 280 281 remove_head (n: INTEGER) 282 local 283 i: INTEGER 284 do 285 from 286 i := n 287 until 288 i = 0 289 loop 290 remove_first 291 i := i - 1 292 end 293 next_generation 294 ensure then 295 upper = old upper 296 end 297 298 remove (index: INTEGER) 299 do 300 if index /= upper then 301 if index /= lower then 302 squeeze_bubble(lower, upper, index, 1) 303 else 304 storage_lower := storage_lower + 1 305 if storage_lower = capacity then 306 storage_lower := 0 307 end 308 end 309 end 310 upper := upper - 1 311 next_generation 312 end 313 314 clear_count 315 do 316 upper := lower - 1 317 next_generation 318 ensure then 319 capacity = old capacity 320 end 321 322 clear_count_and_capacity 323 local 324 null_storage: like storage 325 do 326 upper := lower - 1 327 storage := null_storage 328 capacity := 0 329 next_generation 330 ensure then 331 capacity = 0 332 end 333 334 add_first (element: like item) 335 do 336 make_space_for_one 337 upper := upper + 1 338 storage_lower := storage_lower - 1 339 if storage_lower < 0 then 340 storage_lower := storage_lower + capacity 341 end 342 storage.put(element, storage_lower) 343 next_generation 344 end 345 346 add_last (element: like item) 347 do 348 make_space_for_one 349 upper := upper + 1 350 put(element, upper) 351 end 352 353 from_collection (model: TRAVERSABLE[like item]) 354 local 355 i, up: INTEGER 356 do 357 from 358 with_capacity(model.count, model.lower) 359 i := model.lower 360 up := model.upper 361 until 362 i > up 363 loop 364 add_last(model.item(i)) 365 i := i + 1 366 end 367 next_generation 368 ensure then 369 lower = model.lower 370 upper = model.upper 371 end 372 373 all_default: BOOLEAN 374 local 375 s_u: INTEGER 376 do 377 if is_empty then 378 Result := True 379 else 380 s_u := storage_upper 381 if storage_lower <= s_u then 382 Result := storage.slice_default(storage_lower, s_u) 383 else 384 Result := storage.all_default(s_u) and then storage.slice_default(storage_lower, capacity - 1) 385 end 386 end 387 end 388 389 occurrences (element: like item): INTEGER 390 local 391 s_u: INTEGER 392 do 393 if is_empty then 394 else 395 s_u := storage_upper 396 if storage_lower <= s_u then 397 Result := storage.slice_occurrences(element, storage_lower, s_u) 398 else 399 Result := storage.occurrences(element, s_u) + storage.slice_occurrences(element, storage_lower, capacity - 1) 400 end 401 end 402 end 403 404 fast_occurrences (element: like item): INTEGER 405 local 406 s_u: INTEGER 407 do 408 if is_empty then 409 else 410 s_u := storage_upper 411 if storage_lower <= s_u then 412 Result := storage.slice_fast_occurrences(element, storage_lower, s_u) 413 else 414 Result := storage.fast_occurrences(element, s_u) + storage.slice_fast_occurrences(element, storage_lower, capacity - 1) 415 end 416 end 417 end 418 419 first_index_of (element: like item): INTEGER 420 local 421 s_u: INTEGER 422 do 423 if is_empty then 424 Result := upper + 1 425 else 426 s_u := storage_upper 427 if storage_lower <= s_u then 428 Result := storage.index_of(element, storage_lower, s_u) + lower - storage_lower 429 else 430 Result := storage.index_of(element, storage_lower, capacity - 1) 431 if Result = capacity then 432 Result := storage.first_index_of(element, s_u) + upper - s_u 433 else 434 Result := Result + lower - storage_lower 435 end 436 end 437 end 438 end 439 440 index_of (element: like item; start_index: INTEGER): INTEGER 441 local 442 s_start_index, s_u: INTEGER 443 do 444 if is_empty then 445 Result := upper + 1 446 else 447 s_u := storage_upper 448 s_start_index := storage_index(start_index) 449 if s_start_index <= s_u then 450 Result := storage.index_of(element, s_start_index, s_u) + lower - storage_lower 451 else 452 Result := storage.index_of(element, s_start_index, capacity - 1) 453 if Result = capacity then 454 Result := storage.first_index_of(element, s_u) + upper - s_u 455 else 456 Result := Result + lower - storage_lower 457 end 458 end 459 end 460 end 461 462 reverse_index_of (element: like item; start_index: INTEGER): INTEGER 463 local 464 safe_equal: SAFE_EQUAL[E_] 465 do 466 from 467 Result := start_index 468 until 469 Result < lower or else safe_equal.test(item(Result), element) 470 loop 471 Result := Result - 1 472 end 473 end 474 475 fast_first_index_of (element: like item): INTEGER 476 local 477 s_u: INTEGER 478 do 479 if is_empty then 480 Result := upper + 1 481 else 482 s_u := storage_upper 483 if storage_lower <= s_u then 484 Result := storage.fast_index_of(element, storage_lower, s_u) + lower - storage_lower 485 else 486 Result := storage.fast_index_of(element, storage_lower, capacity - 1) 487 if Result = capacity then 488 Result := storage.fast_first_index_of(element, s_u) + upper - s_u 489 else 490 Result := Result + lower - storage_lower 491 end 492 end 493 end 494 end 495 496 fast_index_of (element: like item; start_index: INTEGER): INTEGER 497 local 498 s_start_index, s_u: INTEGER 499 do 500 if is_empty then 501 Result := upper + 1 502 else 503 s_u := storage_upper 504 s_start_index := storage_index(start_index) 505 if s_start_index <= s_u then 506 Result := storage.fast_index_of(element, s_start_index, s_u) + lower - storage_lower 507 else 508 Result := storage.fast_index_of(element, s_start_index, capacity - 1) 509 if Result = capacity then 510 Result := storage.fast_first_index_of(element, s_u) + upper - s_u 511 else 512 Result := Result + lower - storage_lower 513 end 514 end 515 end 516 end 517 518 fast_reverse_index_of (element: like item; start_index: INTEGER): INTEGER 519 do 520 from 521 Result := start_index 522 until 523 Result < lower or else item(Result) = element 524 loop 525 Result := Result - 1 526 end 527 end 528 529 fast_is_equal (other: like Current): BOOLEAN 530 local 531 wp, owp: INTEGER 532 do 533 if Current = other then 534 Result := True 535 elseif lower = other.lower and then upper = other.upper then 536 wp := wrap_point 537 owp := other.wrap_point 538 if wp < owp then 539 Result := other.slices_are_equal(Current, owp, wp) 540 else 541 Result := slices_are_equal(other, wp, owp) 542 end 543 end 544 end 545 546 is_equal (other: like Current): BOOLEAN 547 local 548 wp, owp: INTEGER 549 do 550 if Current = other then 551 Result := True 552 elseif lower = other.lower and then upper = other.upper then 553 wp := wrap_point 554 owp := other.wrap_point 555 if wp < owp then 556 Result := other.slices_are_equal_map(Current, owp, wp) 557 else 558 Result := slices_are_equal_map(other, wp, owp) 559 end 560 end 561 end 562 563 slice (min, max: INTEGER): like Current 564 local 565 storage_min, storage_max: INTEGER 566 do 567 create Result.make(lower, lower + max - min) 568 if max >= min then 569 storage_min := storage_index(min) 570 storage_max := storage_index(max) 571 if storage_max >= storage_min then 572 Result.storage.slice_copy(0, storage, storage_min, storage_max) 573 else 574 Result.storage.slice_copy(0, storage, storage_min, capacity - 1) 575 Result.storage.slice_copy(capacity - storage_min, storage, 0, storage_max) 576 end 577 end 578 end 579 580 new_iterator: ITERATOR[E_] 581 do 582 create {ITERATOR_ON_TRAVERSABLE[E_]} Result.make(Current) 583 end 584 585 first: like item 586 do 587 Result := storage.item(storage_lower) 588 end 589 590feature {} 591 make_space_for_one 592 -- Make sure `storage' is big enough to hold at least one 593 -- more element. 594 local 595 old_capacity, s_u, wp: INTEGER 596 do 597 if capacity < count + 1 then 598 if capacity = 0 then 599 capacity := 16 600 storage := storage.calloc(capacity) 601 else 602 wp := wrap_point 603 s_u := storage_upper 604 old_capacity := capacity 605 capacity := 2 * capacity 606 storage := storage.realloc(old_capacity, capacity) 607 if s_u < storage_lower then 608 -- A bubble was created inside the data. Update upper to acknowledge this (preconditions 609 -- will fail if we don't) 610 upper := upper + capacity - old_capacity 611 squeeze_bubble(lower, upper, wp, capacity - old_capacity) 612 -- Update upper 613 upper := upper - capacity + old_capacity 614 end 615 end 616 end 617 next_generation 618 end 619 620 clear_slice (min, max: INTEGER) 621 require 622 valid_index(min) 623 valid_index(max) 624 local 625 s_min, s_max: INTEGER 626 do 627 if max >= min then 628 s_min := storage_index(min) 629 s_max := storage_index(max) 630 if s_max >= s_min then 631 storage.clear(s_min, s_max) 632 else 633 storage.clear(s_min, capacity - 1) 634 storage.clear(0, s_max) 635 end 636 end 637 next_generation 638 end 639 640 squeeze_bubble (min, max, pos, length: INTEGER) 641 require 642 valid_index(min) 643 valid_index(max) 644 pos.in_range(min + 1, max - length) 645 length > 0 646 do 647 if pos - min <= max - pos - length then 648 move(min, pos - 1, length) 649 storage_lower := storage_lower + length 650 if storage_lower >= capacity then 651 storage_lower := storage_lower - capacity 652 end 653 else 654 move(pos + length, max, -length) 655 end 656 next_generation 657 end 658 659 unwrap 660 local 661 bottom, top, free, old_bound, overlap: INTEGER; tmp: like storage 662 do 663 if is_wrapped then 664 bottom := wrap_point - lower 665 top := upper - wrap_point + 1 666 free := capacity - count 667 if free >= bottom then 668 old_bound := upper 669 upper := upper + bottom 670 move(lower, old_bound, bottom) 671 storage_lower := 0 672 upper := old_bound 673 elseif free >= top then 674 old_bound := lower 675 lower := lower - top 676 storage_lower := storage_lower - top 677 move(old_bound, upper, -top) 678 lower := old_bound 679 elseif bottom <= top then 680 overlap := bottom - free 681 tmp := tmp.calloc(overlap) 682 tmp.slice_copy(0, storage, storage_lower, storage_lower + overlap - 1) 683 old_bound := upper 684 lower := lower + overlap 685 storage_lower := storage_lower + overlap 686 upper := upper + bottom 687 move(lower, old_bound, bottom) 688 upper := old_bound 689 storage.slice_copy(0, tmp, 0, overlap - 1) 690 lower := lower - overlap 691 storage_lower := 0 692 else 693 overlap := top - free 694 tmp := tmp.calloc(overlap) 695 tmp.slice_copy(0, storage, storage_upper - overlap + 1, storage_upper) 696 old_bound := lower 697 lower := lower - top 698 storage_lower := storage_lower - top 699 upper := upper - overlap 700 move(old_bound, upper, -top) 701 lower := old_bound 702 storage.slice_copy(storage_upper + 1, tmp, 0, overlap - 1) 703 upper := upper + overlap 704 end 705 end 706 next_generation 707 ensure 708 not is_wrapped 709 is_equal(old twin) 710 end 711 712feature {ANY} 713 to_external: POINTER 714 -- Gives C access into the internal `storage' of the ARRAY. 715 -- Result is pointing the element at index `lower'. 716 -- 717 -- NOTE: do not free/realloc the Result. Any operation that changes 718 -- `lower' or `upper' can make this pointer useless (because the 719 -- array has wrapped or its beginning in the storage has moved), 720 -- and operations that change `capacity' can make it invalid 721 -- (because new memory has been allocated and the old memory has 722 -- been freed) 723 do 724 unwrap 725 Result := storage.to_pointer + storage_lower * storage.element_sizeof 726 ensure then 727 not is_wrapped 728 end 729 730 is_wrapped: BOOLEAN 731 do 732 Result := storage_lower + count > capacity 733 ensure 734 Result = (not is_empty and then storage_lower > storage_upper) 735 end 736 737feature {RING_ARRAY} 738 storage_lower: INTEGER 739 -- Index of `first' in `storage' 740 -- This would always be 0 for regular arrays. 741 742 storage_upper: INTEGER 743 -- Index of `last' in `storage' 744 require 745 not is_empty 746 do 747 Result := storage_index(upper) 748 ensure 749 in_storage(Result) 750 end 751 752 storage_index (i: INTEGER): INTEGER 753 -- Index in `storage' corresponding to index `i' in `Current' 754 require 755 valid_index(i) 756 do 757 Result := i - lower + storage_lower 758 if Result >= capacity then 759 Result := Result - capacity 760 end 761 ensure 762 in_storage(Result) 763 end 764 765 in_storage (index: INTEGER): BOOLEAN 766 do 767 Result := index.in_range(0, capacity - 1) 768 ensure 769 Result = (0 <= index and index < capacity) 770 end 771 772 wrap_point: INTEGER 773 -- Index in Current (seen as a COLLECTION) such that for any 774 -- `valid_index'es i and j, if i < wrap_point and j >= 775 -- wrap_point then storage_index(i) > storage_index(j) 776 -- 777 -- This can happen because of the circular nature of the 778 -- array. `wrap_point' is not a `valid_index' if and only if 779 -- there is no such point (i.e. the array doesn't wrap). 780 do 781 Result := capacity + lower - storage_lower 782 ensure 783 capacity > 0 implies Result > lower 784 valid_index(Result) = is_wrapped 785 end 786 787 slices_are_equal (other: like Current; wp, owp: INTEGER): BOOLEAN 788 require 789 wp >= owp 790 lower = other.lower 791 upper = other.upper 792 local 793 oswp: INTEGER 794 do 795 if owp > upper then 796 Result := storage.slice_fast_memcmp(storage_lower, other.storage, other.storage_lower, other.storage_upper) 797 elseif wp > upper or else wp = owp then 798 Result := storage.slice_fast_memcmp(storage_lower, other.storage, other.storage_lower, other.capacity - 1) and then storage.slice_fast_memcmp(storage_index(owp), other.storage, 0, other.storage_upper) 799 else 800 oswp := other.storage_index(wp) 801 Result := storage.slice_fast_memcmp(storage_lower, other.storage, other.storage_lower, other.capacity - 1) and then storage.slice_fast_memcmp(storage_index(owp), other.storage, 0, oswp - 1) and then storage.slice_fast_memcmp(0, other.storage, oswp, other.storage_upper) 802 end 803 end 804 805 slices_are_equal_map (other: like Current; wp, owp: INTEGER): BOOLEAN 806 require 807 wp >= owp 808 lower = other.lower 809 upper = other.upper 810 local 811 oswp: INTEGER 812 do 813 if owp > upper then 814 Result := storage.slice_memcmp(storage_lower, other.storage, other.storage_lower, other.storage_upper) 815 elseif wp > upper or else wp = owp then 816 Result := storage.slice_memcmp(storage_lower, other.storage, other.storage_lower, other.capacity - 1) and then storage.slice_memcmp(storage_index(owp), other.storage, 0, other.storage_upper) 817 else 818 oswp := other.storage_index(wp) 819 Result := storage.slice_memcmp(storage_lower, other.storage, other.storage_lower, other.capacity - 1) and then storage.slice_memcmp(storage_index(owp), other.storage, 0, oswp - 1) and then storage.slice_memcmp(0, other.storage, oswp, other.storage_upper) 820 end 821 end 822 823feature {} -- Garbage collector tuning (very low-level): 824 mark_native_arrays 825 -- For performance reasons, the unused area of `storage' is always left as it is when 826 -- some elements are removed. No time is lost to clean the released area with a Void 827 -- or a 0 value. (Look for example the `remove_last' implementation.) 828 -- Thus, the unused area of `storage' may contains references of actually unreachable 829 -- objects. The following `mark_native_arrays' actually replace the 830 -- default behavior (the call is automatic) in order to mark only reachable objects. 831 local 832 i: INTEGER 833 do 834 if not is_empty then 835 if is_wrapped then 836 from 837 i := capacity - 1 838 until 839 i < storage_lower 840 loop 841 mark_item(storage, i) 842 i := i - 1 843 end 844 from 845 i := storage_upper 846 until 847 i < 0 848 loop 849 mark_item(storage, i) 850 i := i - 1 851 end 852 else 853 from 854 i := storage_upper 855 until 856 i < storage_lower 857 loop 858 mark_item(storage, i) 859 i := i - 1 860 end 861 end 862 end 863 end 864 865feature {} -- Implement manifest generic creation (very low-level): 866 manifest_make (needed_capacity: INTEGER; initial_lower: INTEGER) 867 -- Manifest creation of a RING_ARRAY `lower' set to `initial_lower'. 868 do 869 make(initial_lower, initial_lower + needed_capacity - 1) 870 end 871 872 manifest_put (index: INTEGER; element: like item) 873 do 874 storage.put(element, index) 875 ensure 876 item(index + lower) = element 877 end 878 879invariant 880 is_empty or in_storage(storage_lower) 881 882end -- class RING_ARRAY 883-- 884-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file. 885-- 886-- Permission is hereby granted, free of charge, to any person obtaining a copy 887-- of this software and associated documentation files (the "Software"), to deal 888-- in the Software without restriction, including without limitation the rights 889-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 890-- copies of the Software, and to permit persons to whom the Software is 891-- furnished to do so, subject to the following conditions: 892-- 893-- The above copyright notice and this permission notice shall be included in 894-- all copies or substantial portions of the Software. 895-- 896-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 897-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 898-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 899-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 900-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 901-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 902-- THE SOFTWARE.