1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.collection.TreeMap; 13 14 import hunt.collection.AbstractCollection; 15 import hunt.collection.AbstractMap; 16 import hunt.collection.AbstractSet; 17 import hunt.collection.Collection; 18 import hunt.collection.Iterator; 19 import hunt.collection.Map; 20 import hunt.collection.NavigableMap; 21 import hunt.collection.NavigableSet; 22 import hunt.collection.Set; 23 import hunt.collection.SortedMap; 24 import hunt.collection.SortedSet; 25 26 import hunt.Exceptions; 27 import hunt.Functions; 28 import hunt.Object; 29 import hunt.util.Comparator; 30 import hunt.util.Spliterator; 31 32 import std.algorithm; 33 import std.conv; 34 import std.exception; 35 import std.math; 36 import std.range; 37 import std.traits; 38 39 40 version (HUNT_DEBUG) import hunt.logging.ConsoleLogger; 41 42 // Red-black mechanics 43 44 private enum bool RED = false; 45 private enum bool BLACK = true; 46 47 48 /** 49 * A Red-Black tree based {@link NavigableMap} implementation. 50 * The map is sorted according to the {@linkplain Comparable natural 51 * ordering} of its keys, or by a {@link Comparator} provided at map 52 * creation time, depending on which constructor is used. 53 * 54 * <p>This implementation provides guaranteed log(n) time cost for the 55 * {@code containsKey}, {@code get}, {@code put} and {@code remove} 56 * operations. Algorithms are adaptations of those in Cormen, Leiserson, and 57 * Rivest's <em>Introduction to Algorithms</em>. 58 * 59 * <p>Note that the ordering maintained by a tree map, like any sorted map, and 60 * whether or not an explicit comparator is provided, must be <em>consistent 61 * with {@code equals}</em> if this sorted map is to correctly implement the 62 * {@code Map} interface. (See {@code Comparable} or {@code Comparator} for a 63 * precise definition of <em>consistent with equals</em>.) This is so because 64 * the {@code Map} interface is defined in terms of the {@code equals} 65 * operation, but a sorted map performs all key comparisons using its {@code 66 * compareTo} (or {@code compare}) method, so two keys that are deemed equal by 67 * this method are, from the standpoint of the sorted map, equal. The behavior 68 * of a sorted map <em>is</em> well-defined even if its ordering is 69 * inconsistent with {@code equals}; it just fails to obey the general contract 70 * of the {@code Map} interface. 71 * 72 * <p><strong>Note that this implementation is not synchronized.</strong> 73 * If multiple threads access a map concurrently, and at least one of the 74 * threads modifies the map structurally, it <em>must</em> be synchronized 75 * externally. (A structural modification is any operation that adds or 76 * deletes one or more mappings; merely changing the value associated 77 * with an existing key is not a structural modification.) This is 78 * typically accomplished by synchronizing on some object that naturally 79 * encapsulates the map. 80 * If no such object exists, the map should be "wrapped" using the 81 * {@link Collections#synchronizedSortedMap Collections.synchronizedSortedMap} 82 * method. This is best done at creation time, to prevent accidental 83 * unsynchronized access to the map: <pre> 84 * SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));</pre> 85 * 86 * <p>The iterators returned by the {@code iterator} method of the collections 87 * returned by all of this class's "collection view methods" are 88 * <em>fail-fast</em>: if the map is structurally modified at any time after 89 * the iterator is created, in any way except through the iterator's own 90 * {@code remove} method, the iterator will throw a {@link 91 * ConcurrentModificationException}. Thus, in the face of concurrent 92 * modification, the iterator fails quickly and cleanly, rather than risking 93 * arbitrary, non-deterministic behavior at an undetermined time in the future. 94 * 95 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 96 * as it is, generally speaking, impossible to make any hard guarantees in the 97 * presence of unsynchronized concurrent modification. Fail-fast iterators 98 * throw {@code ConcurrentModificationException} on a best-effort basis. 99 * Therefore, it would be wrong to write a program that depended on this 100 * exception for its correctness: <em>the fail-fast behavior of iterators 101 * should be used only to detect bugs.</em> 102 * 103 * <p>All {@code MapEntry} pairs returned by methods in this class 104 * and its views represent snapshots of mappings at the time they were 105 * produced. They do <strong>not</strong> support the {@code Entry.setValue} 106 * method. (Note however that it is possible to change mappings in the 107 * associated map using {@code put}.) 108 * 109 * <p>This class is a member of the 110 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 111 * Java Collections Framework</a>. 112 * 113 * @param !K the type of keys maintained by this map 114 * @param !V the type of mapped values 115 * 116 * @author Josh Bloch and Doug Lea 117 * @see Map 118 * @see HashMap 119 * @see Hashtable 120 * @see Comparable 121 * @see Comparator 122 * @see Collection 123 * @since 1.2 124 */ 125 126 class TreeMap(K,V) : AbstractMap!(K,V), NavigableMap!(K,V) { //, Cloneable, java.io.Serializable 127 128 /** 129 * The comparator used to maintain order in this tree map, or 130 * null if it uses the natural ordering of its keys. 131 * 132 * @serial 133 */ 134 private Comparator!K _comparator; 135 136 private TreeMapEntry!(K,V) root; 137 138 /** 139 * The number of entries in the tree 140 */ 141 // private int _size = 0; 142 143 /** 144 * The number of structural modifications to the tree. 145 */ 146 private int modCount = 0; 147 148 /** 149 * Constructs a new, empty tree map, using the natural ordering of its 150 * keys. All keys inserted into the map must implement the {@link 151 * Comparable} interface. Furthermore, all such keys must be 152 * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw 153 * a {@code ClassCastException} for any keys {@code k1} and 154 * {@code k2} in the map. If the user attempts to put a key into the 155 * map that violates this constraint (for example, the user attempts to 156 * put a string key into a map whose keys are integers), the 157 * {@code put(Object key, Object value)} call will throw a 158 * {@code ClassCastException}. 159 */ 160 this() { 161 _comparator = null; 162 } 163 164 /** 165 * Constructs a new, empty tree map, ordered according to the given 166 * comparator. All keys inserted into the map must be <em>mutually 167 * comparable</em> by the given comparator: {@code comparator.compare(k1, 168 * k2)} must not throw a {@code ClassCastException} for any keys 169 * {@code k1} and {@code k2} in the map. If the user attempts to put 170 * a key into the map that violates this constraint, the {@code put(Object 171 * key, Object value)} call will throw a 172 * {@code ClassCastException}. 173 * 174 * @param comparator the comparator that will be used to order this map. 175 * If {@code null}, the {@linkplain Comparable natural 176 * ordering} of the keys will be used. 177 */ 178 this(Comparator!K comparator) { 179 this._comparator = comparator; 180 } 181 182 /** 183 * Constructs a new tree map containing the same mappings as the given 184 * map, ordered according to the <em>natural ordering</em> of its keys. 185 * All keys inserted into the new map must implement the {@link 186 * Comparable} interface. Furthermore, all such keys must be 187 * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw 188 * a {@code ClassCastException} for any keys {@code k1} and 189 * {@code k2} in the map. This method runs in n*log(n) time. 190 * 191 * @param m the map whose mappings are to be placed in this map 192 * @throws ClassCastException if the keys in m are not {@link Comparable}, 193 * or are not mutually comparable 194 * @throws NullPointerException if the specified map is null 195 */ 196 this(Map!(K, V) m) { 197 _comparator = null; 198 putAll(m); 199 } 200 201 /** 202 * Constructs a new tree map containing the same mappings and 203 * using the same ordering as the specified sorted map. This 204 * method runs in linear time. 205 * 206 * @param m the sorted map whose mappings are to be placed in this map, 207 * and whose comparator is to be used to sort this map 208 * @throws NullPointerException if the specified map is null 209 */ 210 // this(SortedMap!(K, V) m) { 211 // _comparator = m.comparator(); 212 // try { 213 // buildFromSorted(m.size(), m.entrySet().iterator(), null, null); 214 // } catch (IOException cannotHappen) { 215 // } catch (ClassNotFoundException cannotHappen) { 216 // } 217 // } 218 219 220 // Query Operations 221 222 /** 223 * Returns the number of key-value mappings in this map. 224 * 225 * @return the number of key-value mappings in this map 226 */ 227 // override int size() { 228 // return _size; 229 // } 230 231 /** 232 * Returns {@code true} if this map contains a mapping for the specified 233 * key. 234 * 235 * @param key key whose presence in this map is to be tested 236 * @return {@code true} if this map contains a mapping for the 237 * specified key 238 * @throws ClassCastException if the specified key cannot be compared 239 * with the keys currently in the map 240 * @throws NullPointerException if the specified key is null 241 * and this map uses natural ordering, or its comparator 242 * does not permit null keys 243 */ 244 override bool containsKey(K key) { 245 return getEntry(key) !is null; 246 } 247 248 /** 249 * Returns {@code true} if this map maps one or more keys to the 250 * specified value. More formally, returns {@code true} if and only if 251 * this map contains at least one mapping to a value {@code v} such 252 * that {@code (value is null ? v is null : value.equals(v))}. This 253 * operation will probably require time linear in the map size for 254 * most implementations. 255 * 256 * @param value value whose presence in this map is to be tested 257 * @return {@code true} if a mapping to {@code value} exists; 258 * {@code false} otherwise 259 * @since 1.2 260 */ 261 override bool containsValue(V value) { 262 for (TreeMapEntry!(K,V) e = getFirstEntry(); e !is null; e = successor(e)) 263 if (valEquals(value, e.value)) 264 return true; 265 return false; 266 } 267 268 /** 269 * Returns the value to which the specified key is mapped, 270 * or {@code null} if this map contains no mapping for the key. 271 * 272 * <p>More formally, if this map contains a mapping from a key 273 * {@code k} to a value {@code v} such that {@code key} compares 274 * equal to {@code k} according to the map's ordering, then this 275 * method returns {@code v}; otherwise it returns {@code null}. 276 * (There can be at most one such mapping.) 277 * 278 * <p>A return value of {@code null} does not <em>necessarily</em> 279 * indicate that the map contains no mapping for the key; it's also 280 * possible that the map explicitly maps the key to {@code null}. 281 * The {@link #containsKey containsKey} operation may be used to 282 * distinguish these two cases. 283 * 284 * @throws ClassCastException if the specified key cannot be compared 285 * with the keys currently in the map 286 * @throws NullPointerException if the specified key is null 287 * and this map uses natural ordering, or its comparator 288 * does not permit null keys 289 */ 290 override V get(K key) { 291 TreeMapEntry!(K,V) p = getEntry(key); 292 return (p is null ? null : p.value); 293 } 294 295 Comparator!K comparator() { 296 return _comparator; 297 } 298 299 /** 300 * @throws NoSuchElementException {@inheritDoc} 301 */ 302 K firstKey() { 303 return key(getFirstEntry()); 304 } 305 306 /** 307 * @throws NoSuchElementException {@inheritDoc} 308 */ 309 K lastKey() { 310 return key(getLastEntry()); 311 } 312 313 /** 314 * Copies all of the mappings from the specified map to this map. 315 * These mappings replace any mappings that this map had for any 316 * of the keys currently in the specified map. 317 * 318 * @param map mappings to be stored in this map 319 * @throws ClassCastException if the class of a key or value in 320 * the specified map prevents it from being stored in this map 321 * @throws NullPointerException if the specified map is null or 322 * the specified map contains a null key and this map does not 323 * permit null keys 324 */ 325 override void putAll(Map!(K, V) map) { 326 int mapSize = map.size(); 327 SortedMap!(K, V) sortedMap = cast(SortedMap!(K, V)) map; 328 if (_size==0 && mapSize !is 0 && sortedMap !is null) { 329 Comparator!K c = sortedMap.comparator(); 330 if (c == _comparator) { 331 ++modCount; 332 implementationMissing(false); 333 // try { 334 // buildFromSorted(mapSize, map, //.entrySet().iterator(), 335 // null, null); 336 // } catch (IOException cannotHappen) { 337 // } 338 // catch (ClassNotFoundException cannotHappen) { 339 // } 340 return; 341 } 342 } 343 super.putAll(map); 344 } 345 346 /** 347 * Returns this map's entry for the given key, or {@code null} if the map 348 * does not contain an entry for the key. 349 * 350 * @return this map's entry for the given key, or {@code null} if the map 351 * does not contain an entry for the key 352 * @throws ClassCastException if the specified key cannot be compared 353 * with the keys currently in the map 354 * @throws NullPointerException if the specified key is null 355 * and this map uses natural ordering, or its comparator 356 * does not permit null keys 357 */ 358 final TreeMapEntry!(K,V) getEntry(K key) { 359 // Offload comparator-based version for sake of performance 360 if (_comparator !is null) 361 return getEntryUsingComparator(key); 362 static if(is(T == class)) 363 { 364 if (key is null) 365 throw new NullPointerException(); 366 } 367 K k = key; 368 TreeMapEntry!(K,V) p = root; 369 while (p !is null) { 370 // static if(isNumeric!(K)) 371 // int cp = std.math.cmp(cast(float)k, cast(float)p.key); 372 // else 373 // int cp = std.algorithm.cmp(k, p.key); 374 int cp = compare(k, p.key); 375 376 if (cp < 0) 377 p = p.left; 378 else if (cp > 0) 379 p = p.right; 380 else 381 return p; 382 } 383 return null; 384 } 385 386 /** 387 * Version of getEntry using comparator. Split off from getEntry 388 * for performance. (This is not worth doing for most methods, 389 * that are less dependent on comparator performance, but is 390 * worthwhile here.) 391 */ 392 final TreeMapEntry!(K,V) getEntryUsingComparator(K key) { 393 K k = key; 394 Comparator!K cpr = _comparator; 395 if (cpr !is null) { 396 TreeMapEntry!(K,V) p = root; 397 while (p !is null) { 398 int cmp = cpr.compare(k, p.key); 399 if (cmp < 0) 400 p = p.left; 401 else if (cmp > 0) 402 p = p.right; 403 else 404 return p; 405 } 406 } 407 return null; 408 } 409 410 /** 411 * Gets the entry corresponding to the specified key; if no such entry 412 * exists, returns the entry for the least key greater than the specified 413 * key; if no such entry exists (i.e., the greatest key in the Tree is less 414 * than the specified key), returns {@code null}. 415 */ 416 final TreeMapEntry!(K,V) getCeilingEntry(K key) { 417 TreeMapEntry!(K,V) p = root; 418 while (p !is null) { 419 int cmp = compare(key, p.key); 420 if (cmp < 0) { 421 if (p.left !is null) 422 p = p.left; 423 else 424 return p; 425 } else if (cmp > 0) { 426 if (p.right !is null) { 427 p = p.right; 428 } else { 429 TreeMapEntry!(K,V) parent = p.parent; 430 TreeMapEntry!(K,V) ch = p; 431 while (parent !is null && ch == parent.right) { 432 ch = parent; 433 parent = parent.parent; 434 } 435 return parent; 436 } 437 } else 438 return p; 439 } 440 return null; 441 } 442 443 /** 444 * Gets the entry corresponding to the specified key; if no such entry 445 * exists, returns the entry for the greatest key less than the specified 446 * key; if no such entry exists, returns {@code null}. 447 */ 448 final TreeMapEntry!(K,V) getFloorEntry(K key) { 449 TreeMapEntry!(K,V) p = root; 450 while (p !is null) { 451 int cmp = compare(key, p.key); 452 if (cmp > 0) { 453 if (p.right !is null) 454 p = p.right; 455 else 456 return p; 457 } else if (cmp < 0) { 458 if (p.left !is null) { 459 p = p.left; 460 } else { 461 TreeMapEntry!(K,V) parent = p.parent; 462 TreeMapEntry!(K,V) ch = p; 463 while (parent !is null && ch == parent.left) { 464 ch = parent; 465 parent = parent.parent; 466 } 467 return parent; 468 } 469 } else 470 return p; 471 472 } 473 return null; 474 } 475 476 /** 477 * Gets the entry for the least key greater than the specified 478 * key; if no such entry exists, returns the entry for the least 479 * key greater than the specified key; if no such entry exists 480 * returns {@code null}. 481 */ 482 final TreeMapEntry!(K,V) getHigherEntry(K key) { 483 TreeMapEntry!(K,V) p = root; 484 while (p !is null) { 485 int cmp = compare(key, p.key); 486 if (cmp < 0) { 487 if (p.left !is null) 488 p = p.left; 489 else 490 return p; 491 } else { 492 if (p.right !is null) { 493 p = p.right; 494 } else { 495 TreeMapEntry!(K,V) parent = p.parent; 496 TreeMapEntry!(K,V) ch = p; 497 while (parent !is null && ch == parent.right) { 498 ch = parent; 499 parent = parent.parent; 500 } 501 return parent; 502 } 503 } 504 } 505 return null; 506 } 507 508 /** 509 * Returns the entry for the greatest key less than the specified key; if 510 * no such entry exists (i.e., the least key in the Tree is greater than 511 * the specified key), returns {@code null}. 512 */ 513 final TreeMapEntry!(K,V) getLowerEntry(K key) { 514 TreeMapEntry!(K,V) p = root; 515 while (p !is null) { 516 int cmp = compare(key, p.key); 517 if (cmp > 0) { 518 if (p.right !is null) 519 p = p.right; 520 else 521 return p; 522 } else { 523 if (p.left !is null) { 524 p = p.left; 525 } else { 526 TreeMapEntry!(K,V) parent = p.parent; 527 TreeMapEntry!(K,V) ch = p; 528 while (parent !is null && ch == parent.left) { 529 ch = parent; 530 parent = parent.parent; 531 } 532 return parent; 533 } 534 } 535 } 536 return null; 537 } 538 539 /** 540 * Associates the specified value with the specified key in this map. 541 * If the map previously contained a mapping for the key, the old 542 * value is replaced. 543 * 544 * @param key key with which the specified value is to be associated 545 * @param value value to be associated with the specified key 546 * 547 * @return the previous value associated with {@code key}, or 548 * {@code null} if there was no mapping for {@code key}. 549 * (A {@code null} return can also indicate that the map 550 * previously associated {@code null} with {@code key}.) 551 * @throws ClassCastException if the specified key cannot be compared 552 * with the keys currently in the map 553 * @throws NullPointerException if the specified key is null 554 * and this map uses natural ordering, or its comparator 555 * does not permit null keys 556 */ 557 override V put(K key, V value) { 558 TreeMapEntry!(K,V) t = root; 559 if (t is null) { 560 // compare(key, key); // type (and possibly null) check 561 562 root = new TreeMapEntry!(K,V)(key, value, null); 563 _size = 1; 564 modCount++; 565 return null; 566 } 567 int _cmp; 568 TreeMapEntry!(K,V) parent; 569 // split comparator and comparable paths 570 Comparator!K cpr = _comparator; 571 if (cpr !is null) { 572 do { 573 parent = t; 574 _cmp = cpr.compare(key, t.key); 575 if (_cmp < 0) 576 t = t.left; 577 else if (_cmp > 0) 578 t = t.right; 579 else 580 return t.setValue(value); 581 } while (t !is null); 582 } 583 else { 584 // if (key is null) 585 // throw new NullPointerException(); 586 // Comparable!K k = cast(Comparable!K) key; 587 K k = key; 588 do { 589 parent = t; 590 // _cmp = k.compareTo(t.key); 591 592 // static if(isNumeric!(K)) 593 // _cmp = std.math.cmp(cast(float)k, cast(float)t.key); 594 // else 595 // _cmp = std.algorithm.cmp(k, t.key); 596 _cmp = compare(k, t.key); 597 598 if (_cmp < 0) 599 t = t.left; 600 else if (_cmp > 0) 601 t = t.right; 602 else 603 return t.setValue(value); 604 } while (t !is null); 605 } 606 TreeMapEntry!(K,V) e = new TreeMapEntry!(K,V)(key, value, parent); 607 if (_cmp < 0) 608 parent.left = e; 609 else 610 parent.right = e; 611 fixAfterInsertion(e); 612 _size++; 613 modCount++; 614 return null; 615 } 616 617 /** 618 * Removes the mapping for this key from this TreeMap if present. 619 * 620 * @param key key for which mapping should be removed 621 * @return the previous value associated with {@code key}, or 622 * {@code null} if there was no mapping for {@code key}. 623 * (A {@code null} return can also indicate that the map 624 * previously associated {@code null} with {@code key}.) 625 * @throws ClassCastException if the specified key cannot be compared 626 * with the keys currently in the map 627 * @throws NullPointerException if the specified key is null 628 * and this map uses natural ordering, or its comparator 629 * does not permit null keys 630 */ 631 override V remove(K key) { 632 TreeMapEntry!(K,V) p = getEntry(key); 633 if (p is null) 634 return null; 635 636 V oldValue = p.value; 637 deleteEntry(p); 638 return oldValue; 639 } 640 641 /** 642 * Removes all of the mappings from this map. 643 * The map will be empty after this call returns. 644 */ 645 override void clear() { 646 modCount++; 647 _size = 0; 648 root = null; 649 } 650 651 /** 652 * Returns a shallow copy of this {@code TreeMap} instance. (The keys and 653 * values themselves are not cloned.) 654 * 655 * @return a shallow copy of this map 656 */ 657 // Object clone() { 658 // TreeMap<?,?> clone; 659 // try { 660 // clone = (TreeMap<?,?>) super.clone(); 661 // } catch (CloneNotSupportedException e) { 662 // throw new InternalError(e); 663 // } 664 665 // // Put clone into "virgin" state (except for comparator) 666 // clone.root = null; 667 // clone.size = 0; 668 // clone.modCount = 0; 669 // clone.entrySet = null; 670 // clone._navigableKeySet = null; 671 // clone._descendingMap = null; 672 673 // // Initialize clone with our mappings 674 // try { 675 // clone.buildFromSorted(size, entrySet().iterator(), null, null); 676 // } catch (java.io.IOException cannotHappen) { 677 // } catch (ClassNotFoundException cannotHappen) { 678 // } 679 680 // return clone; 681 // } 682 683 // NavigableMap API methods 684 685 /** 686 * @since 1.6 687 */ 688 MapEntry!(K,V) firstEntry() { 689 return exportEntry!(K,V)(getFirstEntry()); 690 } 691 692 /** 693 * @since 1.6 694 */ 695 MapEntry!(K,V) lastEntry() { 696 return exportEntry!(K,V)(getLastEntry()); 697 } 698 699 /** 700 * @since 1.6 701 */ 702 MapEntry!(K,V) pollFirstEntry() { 703 TreeMapEntry!(K,V) p = getFirstEntry(); 704 MapEntry!(K,V) result = exportEntry!(K,V)(p); 705 if (p !is null) 706 deleteEntry(p); 707 return result; 708 } 709 710 /** 711 * @since 1.6 712 */ 713 MapEntry!(K,V) pollLastEntry() { 714 TreeMapEntry!(K,V) p = getLastEntry(); 715 MapEntry!(K,V) result = exportEntry!(K,V)(p); 716 if (p !is null) 717 deleteEntry(p); 718 return result; 719 } 720 721 /** 722 * @throws ClassCastException {@inheritDoc} 723 * @throws NullPointerException if the specified key is null 724 * and this map uses natural ordering, or its comparator 725 * does not permit null keys 726 * @since 1.6 727 */ 728 MapEntry!(K,V) lowerEntry(K key) { 729 return exportEntry!(K,V)(getLowerEntry(key)); 730 } 731 732 /** 733 * @throws ClassCastException {@inheritDoc} 734 * @throws NullPointerException if the specified key is null 735 * and this map uses natural ordering, or its comparator 736 * does not permit null keys 737 * @since 1.6 738 */ 739 K lowerKey(K key) { 740 return keyOrNull(getLowerEntry(key)); 741 } 742 743 /** 744 * @throws ClassCastException {@inheritDoc} 745 * @throws NullPointerException if the specified key is null 746 * and this map uses natural ordering, or its comparator 747 * does not permit null keys 748 * @since 1.6 749 */ 750 MapEntry!(K,V) floorEntry(K key) { 751 return exportEntry!(K,V)(getFloorEntry(key)); 752 } 753 754 /** 755 * @throws ClassCastException {@inheritDoc} 756 * @throws NullPointerException if the specified key is null 757 * and this map uses natural ordering, or its comparator 758 * does not permit null keys 759 * @since 1.6 760 */ 761 K floorKey(K key) { 762 return keyOrNull(getFloorEntry(key)); 763 } 764 765 /** 766 * @throws ClassCastException {@inheritDoc} 767 * @throws NullPointerException if the specified key is null 768 * and this map uses natural ordering, or its comparator 769 * does not permit null keys 770 * @since 1.6 771 */ 772 MapEntry!(K,V) ceilingEntry(K key) { 773 return exportEntry!(K,V)(getCeilingEntry(key)); 774 } 775 776 /** 777 * @throws ClassCastException {@inheritDoc} 778 * @throws NullPointerException if the specified key is null 779 * and this map uses natural ordering, or its comparator 780 * does not permit null keys 781 * @since 1.6 782 */ 783 K ceilingKey(K key) { 784 return keyOrNull(getCeilingEntry(key)); 785 } 786 787 /** 788 * @throws ClassCastException {@inheritDoc} 789 * @throws NullPointerException if the specified key is null 790 * and this map uses natural ordering, or its comparator 791 * does not permit null keys 792 * @since 1.6 793 */ 794 MapEntry!(K,V) higherEntry(K key) { 795 return exportEntry!(K,V)(getHigherEntry(key)); 796 } 797 798 /** 799 * @throws ClassCastException {@inheritDoc} 800 * @throws NullPointerException if the specified key is null 801 * and this map uses natural ordering, or its comparator 802 * does not permit null keys 803 * @since 1.6 804 */ 805 K higherKey(K key) { 806 return keyOrNull(getHigherEntry(key)); 807 } 808 809 // Views 810 811 /** 812 * Fields initialized to contain an instance of the entry set view 813 * the first time this view is requested. Views are stateless, so 814 * there's no reason to create more than one. 815 */ 816 // private EntrySet _entrySet; 817 // private KeySet!(K,V) _navigableKeySet; 818 private NavigableMap!(K,V) _descendingMap; 819 820 /** 821 * Returns a {@link Set} view of the keys contained in this map. 822 * 823 * <p>The set's iterator returns the keys in ascending order. 824 * The set's spliterator is 825 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 826 * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} 827 * and {@link Spliterator#ORDERED} with an encounter order that is ascending 828 * key order. The spliterator's comparator (see 829 * {@link java.util.Spliterator#getComparator()}) is {@code null} if 830 * the tree map's comparator (see {@link #comparator()}) is {@code null}. 831 * Otherwise, the spliterator's comparator is the same as or imposes the 832 * same total ordering as the tree map's comparator. 833 * 834 * <p>The set is backed by the map, so changes to the map are 835 * reflected in the set, and vice-versa. If the map is modified 836 * while an iteration over the set is in progress (except through 837 * the iterator's own {@code remove} operation), the results of 838 * the iteration are undefined. The set supports element removal, 839 * which removes the corresponding mapping from the map, via the 840 * {@code Iterator.remove}, {@code Set.remove}, 841 * {@code removeAll}, {@code retainAll}, and {@code clear} 842 * operations. It does not support the {@code add} or {@code addAll} 843 * operations. 844 */ 845 // Set!K keySet() { 846 // return navigableKeySet(); 847 // } 848 849 /** 850 * @since 1.6 851 */ 852 // NavigableSet!K navigableKeySet() { 853 // KeySet!(K, V) nks = _navigableKeySet; 854 // return (nks !is null) ? nks : (_navigableKeySet = new KeySet!(K, V)(this)); 855 // } 856 857 /** 858 * @since 1.6 859 */ 860 // NavigableSet!K descendingKeySet() { 861 // return descendingMap().navigableKeySet(); 862 // } 863 864 /** 865 * Returns a {@link Collection} view of the values contained in this map. 866 * 867 * <p>The collection's iterator returns the values in ascending order 868 * of the corresponding keys. The collection's spliterator is 869 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 870 * <em>fail-fast</em>, and additionally reports {@link Spliterator#ORDERED} 871 * with an encounter order that is ascending order of the corresponding 872 * keys. 873 * 874 * <p>The collection is backed by the map, so changes to the map are 875 * reflected in the collection, and vice-versa. If the map is 876 * modified while an iteration over the collection is in progress 877 * (except through the iterator's own {@code remove} operation), 878 * the results of the iteration are undefined. The collection 879 * supports element removal, which removes the corresponding 880 * mapping from the map, via the {@code Iterator.remove}, 881 * {@code Collection.remove}, {@code removeAll}, 882 * {@code retainAll} and {@code clear} operations. It does not 883 * support the {@code add} or {@code addAll} operations. 884 */ 885 // Collection!V values() { 886 // Collection!V vs = values; 887 // if (vs is null) { 888 // vs = new Values(); 889 // values = vs; 890 // } 891 // return vs; 892 // } 893 894 /** 895 * Returns a {@link Set} view of the mappings contained in this map. 896 * 897 * <p>The set's iterator returns the entries in ascending key order. The 898 * sets's spliterator is 899 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 900 * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} and 901 * {@link Spliterator#ORDERED} with an encounter order that is ascending key 902 * order. 903 * 904 * <p>The set is backed by the map, so changes to the map are 905 * reflected in the set, and vice-versa. If the map is modified 906 * while an iteration over the set is in progress (except through 907 * the iterator's own {@code remove} operation, or through the 908 * {@code setValue} operation on a map entry returned by the 909 * iterator) the results of the iteration are undefined. The set 910 * supports element removal, which removes the corresponding 911 * mapping from the map, via the {@code Iterator.remove}, 912 * {@code Set.remove}, {@code removeAll}, {@code retainAll} and 913 * {@code clear} operations. It does not support the 914 * {@code add} or {@code addAll} operations. 915 */ 916 // Set!(MapEntry!(K,V)) entrySet() { 917 // EntrySet es = _entrySet; 918 // return (es !is null) ? es : (_entrySet = new EntrySet()); 919 // } 920 921 /** 922 * @since 1.6 923 */ 924 // NavigableMap!(K, V) descendingMap() { 925 // NavigableMap!(K, V) km = _descendingMap; 926 // return (km !is null) ? km : 927 // (_descendingMap = new DescendingSubMap!(K, V)(this, 928 // true, K.init, true, 929 // true, K.init, true)); 930 // } 931 932 /** 933 * @throws ClassCastException {@inheritDoc} 934 * @throws NullPointerException if {@code fromKey} or {@code toKey} is 935 * null and this map uses natural ordering, or its comparator 936 * does not permit null keys 937 * @throws IllegalArgumentException {@inheritDoc} 938 * @since 1.6 939 */ 940 NavigableMap!(K,V) subMap(K fromKey, bool fromInclusive, 941 K toKey, bool toInclusive) { 942 return new AscendingSubMap!(K, V)(this, 943 false, fromKey, fromInclusive, 944 false, toKey, toInclusive); 945 } 946 947 /** 948 * @throws ClassCastException {@inheritDoc} 949 * @throws NullPointerException if {@code toKey} is null 950 * and this map uses natural ordering, or its comparator 951 * does not permit null keys 952 * @throws IllegalArgumentException {@inheritDoc} 953 * @since 1.6 954 */ 955 NavigableMap!(K,V) headMap(K toKey, bool inclusive) { 956 return new AscendingSubMap!(K, V)(this, 957 true, K.init, true, 958 false, toKey, inclusive); 959 } 960 961 /** 962 * @throws ClassCastException {@inheritDoc} 963 * @throws NullPointerException if {@code fromKey} is null 964 * and this map uses natural ordering, or its comparator 965 * does not permit null keys 966 * @throws IllegalArgumentException {@inheritDoc} 967 * @since 1.6 968 */ 969 NavigableMap!(K,V) tailMap(K fromKey, bool inclusive) { 970 return new AscendingSubMap!(K, V)(this, 971 false, fromKey, inclusive, 972 true, K.init, true); 973 } 974 975 /** 976 * @throws ClassCastException {@inheritDoc} 977 * @throws NullPointerException if {@code fromKey} or {@code toKey} is 978 * null and this map uses natural ordering, or its comparator 979 * does not permit null keys 980 * @throws IllegalArgumentException {@inheritDoc} 981 */ 982 SortedMap!(K,V) subMap(K fromKey, K toKey) { 983 return subMap(fromKey, true, toKey, false); 984 } 985 986 /** 987 * @throws ClassCastException {@inheritDoc} 988 * @throws NullPointerException if {@code toKey} is null 989 * and this map uses natural ordering, or its comparator 990 * does not permit null keys 991 * @throws IllegalArgumentException {@inheritDoc} 992 */ 993 SortedMap!(K,V) headMap(K toKey) { 994 return headMap(toKey, false); 995 } 996 997 /** 998 * @throws ClassCastException {@inheritDoc} 999 * @throws NullPointerException if {@code fromKey} is null 1000 * and this map uses natural ordering, or its comparator 1001 * does not permit null keys 1002 * @throws IllegalArgumentException {@inheritDoc} 1003 */ 1004 SortedMap!(K,V) tailMap(K fromKey) { 1005 return tailMap(fromKey, true); 1006 } 1007 1008 override 1009 bool replace(K key, V oldValue, V newValue) { 1010 TreeMapEntry!(K,V) p = getEntry(key); 1011 if (p !is null && oldValue == p.value) { 1012 p.value = newValue; 1013 return true; 1014 } 1015 return false; 1016 } 1017 1018 override 1019 V replace(K key, V value) { 1020 TreeMapEntry!(K,V) p = getEntry(key); 1021 if (p !is null) { 1022 V oldValue = p.value; 1023 p.value = value; 1024 return oldValue; 1025 } 1026 return null; 1027 } 1028 1029 // override 1030 // void replaceAll(BiFunction<K, V, ? : V> function) { 1031 // Objects.requireNonNull(function); 1032 // int expectedModCount = modCount; 1033 1034 // for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1035 // e.value = function.apply(e.key, e.value); 1036 1037 // if (expectedModCount !is modCount) { 1038 // throw new ConcurrentModificationException(); 1039 // } 1040 // } 1041 // } 1042 1043 1044 // View class support 1045 1046 override int opApply(scope int delegate(ref K, ref V) dg) { 1047 if(dg is null) 1048 throw new NullPointerException(); 1049 1050 int result = 0; 1051 int expectedModCount = modCount; 1052 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1053 result = dg(e.key, e.value); 1054 if(result != 0) return result; 1055 } 1056 1057 if (expectedModCount !is modCount) 1058 throw new ConcurrentModificationException(); 1059 1060 return result; 1061 } 1062 1063 1064 override int opApply(scope int delegate(MapEntry!(K, V) entry) dg) { 1065 if(dg is null) 1066 throw new NullPointerException(); 1067 1068 int result = 0; 1069 int expectedModCount = modCount; 1070 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1071 result = dg(e); 1072 if(result != 0) return result; 1073 } 1074 1075 if (expectedModCount !is modCount) 1076 throw new ConcurrentModificationException(); 1077 1078 return result; 1079 } 1080 1081 override InputRange!K byKey() 1082 { 1083 return new KeyInputRange(); 1084 // throw new NotImplementedException(); 1085 } 1086 1087 override InputRange!V byValue() 1088 { 1089 return new ValueInputRange(); 1090 // throw new NotImplementedException(); 1091 } 1092 1093 1094 // class Values : AbstractCollection!V { 1095 // Iterator!V iterator() { 1096 // return new ValueIterator(getFirstEntry()); 1097 // } 1098 1099 // override int size() { 1100 // return this.outer.size(); 1101 // } 1102 1103 // override bool contains(V o) { 1104 // return this.outer.containsValue(o); 1105 // } 1106 1107 // bool remove(V o) { 1108 // for (TreeMapEntry!(K,V) e = getFirstEntry(); e !is null; e = successor(e)) { 1109 // if (valEquals(e.getValue(), o)) { 1110 // deleteEntry(e); 1111 // return true; 1112 // } 1113 // } 1114 // return false; 1115 // } 1116 1117 // override void clear() { 1118 // this.outer.clear(); 1119 // } 1120 1121 // // Spliterator!V spliterator() { 1122 // // return new ValueSpliterator!(K,V)(TreeMap.this, null, null, 0, -1, 0); 1123 // // } 1124 // } 1125 1126 // class EntrySet : AbstractSet!(MapEntry!(K,V)) { 1127 1128 // Iterator!(MapEntry!(K,V)) iterator() { 1129 // return new EntryIterator(getFirstEntry()); 1130 // } 1131 1132 // override bool contains(MapEntry!(K,V) entry) { 1133 // // if (!(o instanceof MapEntry)) 1134 // // return false; 1135 // // MapEntry<?,?> entry = (MapEntry<?,?>) o; 1136 // V value = entry.getValue(); 1137 // TreeMapEntry!(K,V) p = getEntry(entry.getKey()); 1138 // return p !is null && valEquals(p.getValue(), value); 1139 // } 1140 1141 // bool remove(MapEntry!(K,V) entry) { 1142 // // if (!(o instanceof MapEntry)) 1143 // // return false; 1144 // // MapEntry<?,?> entry = (MapEntry<?,?>) o; 1145 // V value = entry.getValue(); 1146 // TreeMapEntry!(K,V) p = getEntry(entry.getKey()); 1147 // if (p !is null && valEquals(p.getValue(), value)) { 1148 // deleteEntry(p); 1149 // return true; 1150 // } 1151 // return false; 1152 // } 1153 1154 // override int size() { 1155 // return this.outer.size(); 1156 // } 1157 1158 // override void clear() { 1159 // this.outer.clear(); 1160 // } 1161 1162 // // Spliterator!(MapEntry!(K,V)) spliterator() { 1163 // // return new EntrySpliterator!(K,V)(this.outer, null, null, 0, -1, 0); 1164 // // } 1165 // } 1166 1167 /* 1168 * Unlike Values and EntrySet, the KeySet class is static, 1169 * delegating to a NavigableMap to allow use by SubMaps, which 1170 * outweighs the ugliness of needing type-tests for the following 1171 * Iterator methods that are defined appropriately in main versus 1172 * submap classes. 1173 */ 1174 1175 // Iterator!K keyIterator() { 1176 // return new KeyIterator(getFirstEntry()); 1177 // } 1178 1179 // Iterator!K descendingKeyIterator() { 1180 // return new DescendingKeyIterator(getLastEntry()); 1181 // } 1182 1183 // static final class KeySet(E, V) : AbstractSet!E , NavigableSet!E { 1184 // private NavigableMap!(E, V) m; 1185 1186 // this(NavigableMap!(E, V) map) { m = map; } 1187 1188 // Iterator!E iterator() { 1189 // TreeMap!(E, V) mm = cast(TreeMap!(E, V))m; 1190 // if (mm !is null) 1191 // return mm.keyIterator(); 1192 // else 1193 // return (cast(TreeMap.NavigableSubMap!(E, V))m).keyIterator(); 1194 // } 1195 1196 // Iterator!E descendingIterator() { 1197 // TreeMap!(E, V) mm = cast(TreeMap!(E, V))m; 1198 // if (mm !is null) 1199 // return mm.descendingKeyIterator(); 1200 // else 1201 // return (cast(TreeMap.NavigableSubMap!(E, V))m).descendingKeyIterator(); 1202 // } 1203 1204 // override int size() { return m.size(); } 1205 // override bool isEmpty() { return m.isEmpty(); } 1206 // override bool contains(K o) { return m.containsKey(o); } 1207 // override void clear() { m.clear(); } 1208 // E lower(E e) { return m.lowerKey(e); } 1209 // E floor(E e) { return m.floorKey(e); } 1210 // E ceiling(E e) { return m.ceilingKey(e); } 1211 // E higher(E e) { return m.higherKey(e); } 1212 // E first() { return m.firstKey(); } 1213 // E last() { return m.lastKey(); } 1214 // // Comparator!E comparator() { return m.comparator(); } 1215 // E pollFirst() { 1216 // MapEntry!(E, V) e = m.pollFirstEntry(); 1217 // return (e is null) ? E.init : e.getKey(); 1218 // } 1219 // E pollLast() { 1220 // MapEntry!(E, V) e = m.pollLastEntry(); 1221 // return (e is null) ? E.init : e.getKey(); 1222 // } 1223 // bool remove(E o) { 1224 // int oldSize = size(); 1225 // m.remove(o); 1226 // return size() !is oldSize; 1227 // } 1228 // NavigableSet!E subSet(E fromElement, bool fromInclusive, 1229 // E toElement, bool toInclusive) { 1230 // return new KeySet!(E, V)(m.subMap(fromElement, fromInclusive, 1231 // toElement, toInclusive)); 1232 // } 1233 // NavigableSet!E headSet(E toElement, bool inclusive) { 1234 // return new KeySet!(E, V)(m.headMap(toElement, inclusive)); 1235 // } 1236 // NavigableSet!E tailSet(E fromElement, bool inclusive) { 1237 // return new KeySet!(E, V)(m.tailMap(fromElement, inclusive)); 1238 // } 1239 // SortedSet!E subSet(E fromElement, E toElement) { 1240 // return subSet(fromElement, true, toElement, false); 1241 // } 1242 // SortedSet!E headSet(E toElement) { 1243 // return headSet(toElement, false); 1244 // } 1245 // SortedSet!E tailSet(E fromElement) { 1246 // return tailSet(fromElement, true); 1247 // } 1248 // NavigableSet!E descendingSet() { 1249 // return new KeySet!(E, V)(m.descendingMap()); 1250 // } 1251 1252 // // Spliterator!E spliterator() { 1253 // // return keySpliteratorFor(m); 1254 // // } 1255 // } 1256 1257 /** 1258 * Base class for TreeMap Iterators 1259 */ 1260 1261 mixin template TreeMapIterator() { 1262 TreeMapEntry!(K,V) next; 1263 TreeMapEntry!(K,V) lastReturned; 1264 int expectedModCount; 1265 1266 this() { 1267 expectedModCount = modCount; 1268 lastReturned = null; 1269 next = getFirstEntry(); 1270 } 1271 1272 final bool empty() { 1273 return next is null; 1274 } 1275 1276 final void popFront() { 1277 TreeMapEntry!(K,V) e = next; 1278 if (e is null) 1279 throw new NoSuchElementException(); 1280 if (modCount !is expectedModCount) 1281 throw new ConcurrentModificationException(); 1282 next = successor(e); 1283 lastReturned = e; 1284 // return e; 1285 } 1286 1287 // final TreeMapEntry!(K,V) prevEntry() { 1288 // TreeMapEntry!(K,V) e = next; 1289 // if (e is null) 1290 // throw new NoSuchElementException(); 1291 // if (modCount !is expectedModCount) 1292 // throw new ConcurrentModificationException(); 1293 // next = predecessor(e); 1294 // lastReturned = e; 1295 // return e; 1296 // } 1297 } 1298 1299 final class KeyInputRange : InputRange!K { 1300 mixin TreeMapIterator; 1301 1302 final K front() @property { return next.key; } 1303 1304 // https://forum.dlang.org/thread/amzthhonuozlobghqqgk@forum.dlang.org?page=1 1305 // https://issues.dlang.org/show_bug.cgi?id=18036 1306 final K moveFront() @property { throw new NotSupportedException(); } 1307 1308 int opApply(scope int delegate(K) dg) { 1309 if(dg is null) 1310 throw new NullPointerException(); 1311 1312 int result = 0; 1313 int expectedModCount = modCount; 1314 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1315 result = dg(e.key); 1316 if(result != 0) return result; 1317 } 1318 1319 if (expectedModCount !is modCount) 1320 throw new ConcurrentModificationException(); 1321 1322 return result; 1323 } 1324 1325 int opApply(scope int delegate(size_t, K) dg) { 1326 if(dg is null) 1327 throw new NullPointerException(); 1328 1329 int result = 0; 1330 int mc = modCount; 1331 size_t index = 0; 1332 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1333 result = dg(index++, e.key); 1334 if(result != 0) return result; 1335 } 1336 1337 if(modCount != mc) 1338 throw new ConcurrentModificationException(); 1339 1340 return result; 1341 } 1342 } 1343 1344 final class ValueInputRange : InputRange!V { 1345 mixin TreeMapIterator; 1346 1347 final V front() @property { return next.value; } 1348 1349 final V moveFront() @property { throw new NotSupportedException(); } 1350 1351 int opApply(scope int delegate(V) dg) { 1352 if(dg is null) 1353 throw new NullPointerException(); 1354 1355 int result = 0; 1356 int mc = modCount; 1357 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1358 result = dg(e.value); 1359 if(result != 0) return result; 1360 } 1361 1362 if(modCount != mc) 1363 throw new ConcurrentModificationException(); 1364 1365 return result; 1366 } 1367 1368 int opApply(scope int delegate(size_t, V) dg) { 1369 if(dg is null) 1370 throw new NullPointerException(); 1371 1372 int result = 0; 1373 int mc = modCount; 1374 size_t index = 0; 1375 for (TreeMapEntry!(K, V) e = getFirstEntry(); e !is null; e = successor(e)) { 1376 result = dg(index++, e.value); 1377 if(result != 0) return result; 1378 } 1379 1380 if(modCount != mc) 1381 throw new ConcurrentModificationException(); 1382 1383 return result; 1384 } 1385 } 1386 1387 // abstract class PrivateEntryIterator(T) : Iterator!T { 1388 // TreeMapEntry!(K,V) next; 1389 // TreeMapEntry!(K,V) lastReturned; 1390 // int expectedModCount; 1391 1392 // this(TreeMapEntry!(K,V) first) { 1393 // expectedModCount = modCount; 1394 // lastReturned = null; 1395 // next = first; 1396 // } 1397 1398 // final bool hasNext() { 1399 // return next !is null; 1400 // } 1401 1402 // final TreeMapEntry!(K,V) nextEntry() { 1403 // TreeMapEntry!(K,V) e = next; 1404 // if (e is null) 1405 // throw new NoSuchElementException(); 1406 // if (modCount !is expectedModCount) 1407 // throw new ConcurrentModificationException(); 1408 // next = successor(e); 1409 // lastReturned = e; 1410 // return e; 1411 // } 1412 1413 // final TreeMapEntry!(K,V) prevEntry() { 1414 // TreeMapEntry!(K,V) e = next; 1415 // if (e is null) 1416 // throw new NoSuchElementException(); 1417 // if (modCount !is expectedModCount) 1418 // throw new ConcurrentModificationException(); 1419 // next = predecessor(e); 1420 // lastReturned = e; 1421 // return e; 1422 // } 1423 1424 // void remove() { 1425 // if (lastReturned is null) 1426 // throw new IllegalStateException(); 1427 // if (modCount !is expectedModCount) 1428 // throw new ConcurrentModificationException(); 1429 // // deleted entries are replaced by their successors 1430 // if (lastReturned.left !is null && lastReturned.right !is null) 1431 // next = lastReturned; 1432 // deleteEntry(lastReturned); 1433 // expectedModCount = modCount; 1434 // lastReturned = null; 1435 // } 1436 // } 1437 1438 // final class EntryIterator : PrivateEntryIterator!(MapEntry!(K,V)) { 1439 // this(TreeMapEntry!(K,V) first) { 1440 // super(first); 1441 // } 1442 // MapEntry!(K,V) next() { 1443 // return nextEntry(); 1444 // } 1445 // } 1446 1447 // final class ValueIterator : PrivateEntryIterator!V { 1448 // this(TreeMapEntry!(K,V) first) { 1449 // super(first); 1450 // } 1451 // V next() { 1452 // return nextEntry().value; 1453 // } 1454 // } 1455 1456 // final class KeyIterator : PrivateEntryIterator!K { 1457 // this(TreeMapEntry!(K,V) first) { 1458 // super(first); 1459 // } 1460 // K next() { 1461 // return nextEntry().key; 1462 // } 1463 // } 1464 1465 // final class DescendingKeyIterator : PrivateEntryIterator!K { 1466 // this(TreeMapEntry!(K,V) first) { 1467 // super(first); 1468 // } 1469 // K next() { 1470 // return prevEntry().key; 1471 // } 1472 1473 // override void remove() { 1474 // if (lastReturned is null) 1475 // throw new IllegalStateException(); 1476 // if (modCount !is expectedModCount) 1477 // throw new ConcurrentModificationException(); 1478 // deleteEntry(lastReturned); 1479 // lastReturned = null; 1480 // expectedModCount = modCount; 1481 // } 1482 // } 1483 1484 /** 1485 * Compares two keys using the correct comparison method for this TreeMap. 1486 */ 1487 // final private int compare(K k1, K k2) { 1488 // if(k1 == k2) return 0; 1489 // else if(k1 > k2) return 1; 1490 // else return -1; 1491 // } 1492 1493 1494 // SubMaps 1495 1496 /** 1497 * Dummy value serving as unmatchable fence key for unbounded 1498 * SubMapIterators 1499 */ 1500 private __gshared Object UNBOUNDED; 1501 1502 shared static this() 1503 { 1504 UNBOUNDED = new Object(); 1505 } 1506 1507 /** 1508 * This class exists solely for the sake of serialization 1509 * compatibility with previous releases of TreeMap that did not 1510 * support NavigableMap. It translates an old-version SubMap into 1511 * a new-version AscendingSubMap. This class is never otherwise 1512 * used. 1513 * 1514 * @serial include 1515 */ 1516 private class SubMap : AbstractMap!(K,V), SortedMap!(K,V) { 1517 1518 private bool fromStart = false, toEnd = false; 1519 private K fromKey, toKey; 1520 // private Object readResolve() { 1521 // return new AscendingSubMap<>(TreeMap.this, 1522 // fromStart, fromKey, true, 1523 // toEnd, toKey, false); 1524 // } 1525 Set!(MapEntry!(K,V)) entrySet() { throw new InternalError(); } 1526 K lastKey() { throw new InternalError(); } 1527 K firstKey() { throw new InternalError(); } 1528 SortedMap!(K,V) subMap(K fromKey, K toKey) { throw new InternalError(); } 1529 SortedMap!(K,V) headMap(K toKey) { throw new InternalError(); } 1530 SortedMap!(K,V) tailMap(K fromKey) { throw new InternalError(); } 1531 Comparator!K comparator() { throw new InternalError(); } 1532 1533 1534 override bool opEquals(IObject o) { 1535 return opEquals(cast(Object) o); 1536 } 1537 1538 override bool opEquals(Object o) { 1539 return super.opEquals(o); 1540 } 1541 1542 override size_t toHash() @trusted nothrow { 1543 return super.toHash(); 1544 } 1545 1546 override string toString() { 1547 return super.toString(); 1548 } 1549 1550 override K[] keySet() { 1551 return super.keySet(); 1552 } 1553 1554 override V[] values() { 1555 return super.values; 1556 } 1557 } 1558 1559 1560 /** 1561 * Returns the first Entry in the TreeMap (according to the TreeMap's 1562 * key-sort function). Returns null if the TreeMap is empty. 1563 */ 1564 final TreeMapEntry!(K,V) getFirstEntry() { 1565 TreeMapEntry!(K,V) p = root; 1566 if (p !is null) 1567 while (p.left !is null) 1568 p = p.left; 1569 return p; 1570 } 1571 1572 /** 1573 * Returns the last Entry in the TreeMap (according to the TreeMap's 1574 * key-sort function). Returns null if the TreeMap is empty. 1575 */ 1576 final TreeMapEntry!(K,V) getLastEntry() { 1577 TreeMapEntry!(K,V) p = root; 1578 if (p !is null) 1579 while (p.right !is null) 1580 p = p.right; 1581 return p; 1582 } 1583 1584 1585 1586 /** 1587 * Balancing operations. 1588 * 1589 * Implementations of rebalancings during insertion and deletion are 1590 * slightly different than the CLR version. Rather than using dummy 1591 * nilnodes, we use a set of accessors that deal properly with null. They 1592 * are used to avoid messiness surrounding nullness checks in the main 1593 * algorithms. 1594 */ 1595 1596 private static bool colorOf(K,V)(TreeMapEntry!(K,V) p) { 1597 return (p is null ? BLACK : p.color); 1598 } 1599 1600 private static TreeMapEntry!(K,V) parentOf(K,V)(TreeMapEntry!(K,V) p) { 1601 return (p is null ? null: p.parent); 1602 } 1603 1604 private static void setColor(K,V)(TreeMapEntry!(K,V) p, bool c) { 1605 if (p !is null) 1606 p.color = c; 1607 } 1608 1609 private static TreeMapEntry!(K,V) leftOf(K,V)(TreeMapEntry!(K,V) p) { 1610 return (p is null) ? null: p.left; 1611 } 1612 1613 private static TreeMapEntry!(K,V) rightOf(K,V)(TreeMapEntry!(K,V) p) { 1614 return (p is null) ? null: p.right; 1615 } 1616 1617 /** From CLR */ 1618 private void rotateLeft(TreeMapEntry!(K,V) p) { 1619 if (p !is null) { 1620 TreeMapEntry!(K,V) r = p.right; 1621 p.right = r.left; 1622 if (r.left !is null) 1623 r.left.parent = p; 1624 r.parent = p.parent; 1625 if (p.parent is null) 1626 root = r; 1627 else if (p.parent.left == p) 1628 p.parent.left = r; 1629 else 1630 p.parent.right = r; 1631 r.left = p; 1632 p.parent = r; 1633 } 1634 } 1635 1636 /** From CLR */ 1637 private void rotateRight(TreeMapEntry!(K,V) p) { 1638 if (p !is null) { 1639 TreeMapEntry!(K,V) l = p.left; 1640 p.left = l.right; 1641 if (l.right !is null) l.right.parent = p; 1642 l.parent = p.parent; 1643 if (p.parent is null) 1644 root = l; 1645 else if (p.parent.right == p) 1646 p.parent.right = l; 1647 else p.parent.left = l; 1648 l.right = p; 1649 p.parent = l; 1650 } 1651 } 1652 1653 /** From CLR */ 1654 private void fixAfterInsertion(TreeMapEntry!(K,V) x) { 1655 x.color = RED; 1656 1657 while (x !is null && x !is root && x.parent.color == RED) { 1658 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { 1659 TreeMapEntry!(K,V) y = rightOf(parentOf(parentOf(x))); 1660 if (colorOf(y) == RED) { 1661 setColor(parentOf(x), BLACK); 1662 setColor(y, BLACK); 1663 setColor(parentOf(parentOf(x)), RED); 1664 x = parentOf(parentOf(x)); 1665 } else { 1666 if (x == rightOf(parentOf(x))) { 1667 x = parentOf(x); 1668 rotateLeft(x); 1669 } 1670 setColor(parentOf(x), BLACK); 1671 setColor(parentOf(parentOf(x)), RED); 1672 rotateRight(parentOf(parentOf(x))); 1673 } 1674 } else { 1675 TreeMapEntry!(K,V) y = leftOf(parentOf(parentOf(x))); 1676 if (colorOf(y) == RED) { 1677 setColor(parentOf(x), BLACK); 1678 setColor(y, BLACK); 1679 setColor(parentOf(parentOf(x)), RED); 1680 x = parentOf(parentOf(x)); 1681 } else { 1682 if (x == leftOf(parentOf(x))) { 1683 x = parentOf(x); 1684 rotateRight(x); 1685 } 1686 setColor(parentOf(x), BLACK); 1687 setColor(parentOf(parentOf(x)), RED); 1688 rotateLeft(parentOf(parentOf(x))); 1689 } 1690 } 1691 } 1692 root.color = BLACK; 1693 } 1694 1695 /** 1696 * Delete node p, and then rebalance the tree. 1697 */ 1698 private void deleteEntry(TreeMapEntry!(K,V) p) { 1699 modCount++; 1700 _size--; 1701 1702 // If strictly internal, copy successor's element to p and then make p 1703 // point to successor. 1704 if (p.left !is null && p.right !is null) { 1705 TreeMapEntry!(K,V) s = successor(p); 1706 p.key = s.key; 1707 p.value = s.value; 1708 p = s; 1709 } // p has 2 children 1710 1711 // Start fixup at replacement node, if it exists. 1712 TreeMapEntry!(K,V) replacement = (p.left !is null ? p.left : p.right); 1713 1714 if (replacement !is null) { 1715 // Link replacement to parent 1716 replacement.parent = p.parent; 1717 if (p.parent is null) 1718 root = replacement; 1719 else if (p == p.parent.left) 1720 p.parent.left = replacement; 1721 else 1722 p.parent.right = replacement; 1723 1724 // Null out links so they are OK to use by fixAfterDeletion. 1725 p.left = p.right = p.parent = null; 1726 1727 // Fix replacement 1728 if (p.color == BLACK) 1729 fixAfterDeletion(replacement); 1730 } else if (p.parent is null) { // return if we are the only node. 1731 root = null; 1732 } else { // No children. Use self as phantom replacement and unlink. 1733 if (p.color == BLACK) 1734 fixAfterDeletion(p); 1735 1736 if (p.parent !is null) { 1737 if (p == p.parent.left) 1738 p.parent.left = null; 1739 else if (p == p.parent.right) 1740 p.parent.right = null; 1741 p.parent = null; 1742 } 1743 } 1744 } 1745 1746 /** From CLR */ 1747 private void fixAfterDeletion(TreeMapEntry!(K,V) x) { 1748 while (x !is root && colorOf(x) == BLACK) { 1749 if (x == leftOf(parentOf(x))) { 1750 TreeMapEntry!(K,V) sib = rightOf(parentOf(x)); 1751 1752 if (colorOf(sib) == RED) { 1753 setColor(sib, BLACK); 1754 setColor(parentOf(x), RED); 1755 rotateLeft(parentOf(x)); 1756 sib = rightOf(parentOf(x)); 1757 } 1758 1759 if (colorOf(leftOf(sib)) == BLACK && 1760 colorOf(rightOf(sib)) == BLACK) { 1761 setColor(sib, RED); 1762 x = parentOf(x); 1763 } else { 1764 if (colorOf(rightOf(sib)) == BLACK) { 1765 setColor(leftOf(sib), BLACK); 1766 setColor(sib, RED); 1767 rotateRight(sib); 1768 sib = rightOf(parentOf(x)); 1769 } 1770 setColor(sib, colorOf(parentOf(x))); 1771 setColor(parentOf(x), BLACK); 1772 setColor(rightOf(sib), BLACK); 1773 rotateLeft(parentOf(x)); 1774 x = root; 1775 } 1776 } else { // symmetric 1777 TreeMapEntry!(K,V) sib = leftOf(parentOf(x)); 1778 1779 if (colorOf(sib) == RED) { 1780 setColor(sib, BLACK); 1781 setColor(parentOf(x), RED); 1782 rotateRight(parentOf(x)); 1783 sib = leftOf(parentOf(x)); 1784 } 1785 1786 if (colorOf(rightOf(sib)) == BLACK && 1787 colorOf(leftOf(sib)) == BLACK) { 1788 setColor(sib, RED); 1789 x = parentOf(x); 1790 } else { 1791 if (colorOf(leftOf(sib)) == BLACK) { 1792 setColor(rightOf(sib), BLACK); 1793 setColor(sib, RED); 1794 rotateLeft(sib); 1795 sib = leftOf(parentOf(x)); 1796 } 1797 setColor(sib, colorOf(parentOf(x))); 1798 setColor(parentOf(x), BLACK); 1799 setColor(leftOf(sib), BLACK); 1800 rotateRight(parentOf(x)); 1801 x = root; 1802 } 1803 } 1804 } 1805 1806 setColor(x, BLACK); 1807 } 1808 1809 // private static final long serialVersionUID = 919286545866124006L; 1810 1811 /** 1812 * Save the state of the {@code TreeMap} instance to a stream (i.e., 1813 * serialize it). 1814 * 1815 * @serialData The <em>size</em> of the TreeMap (the number of key-value 1816 * mappings) is emitted (int), followed by the key (Object) 1817 * and value (Object) for each key-value mapping represented 1818 * by the TreeMap. The key-value mappings are emitted in 1819 * key-order (as determined by the TreeMap's Comparator, 1820 * or by the keys' natural ordering if the TreeMap has no 1821 * Comparator). 1822 */ 1823 // private void writeObject(java.io.ObjectOutputStream s) 1824 // throws java.io.IOException { 1825 // // Write out the Comparator and any hidden stuff 1826 // s.defaultWriteObject(); 1827 1828 // // Write out size (number of Mappings) 1829 // s.writeInt(size); 1830 1831 // // Write out keys and values (alternating) 1832 // for (Iterator!(MapEntry!(K,V)) i = entrySet().iterator(); i.hasNext(); ) { 1833 // MapEntry!(K,V) e = i.next(); 1834 // s.writeObject(e.getKey()); 1835 // s.writeObject(e.getValue()); 1836 // } 1837 // } 1838 1839 /** 1840 * Reconstitute the {@code TreeMap} instance from a stream (i.e., 1841 * deserialize it). 1842 */ 1843 // private void readObject(final java.io.ObjectInputStream s) 1844 // throws java.io.IOException, ClassNotFoundException { 1845 // // Read in the Comparator and any hidden stuff 1846 // s.defaultReadObject(); 1847 1848 // // Read in size 1849 // int size = s.readInt(); 1850 1851 // buildFromSorted(size, null, s, null); 1852 // } 1853 1854 /** Intended to be called only from TreeSet.readObject */ 1855 // void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal) { 1856 // buildFromSorted(size, null, s, defaultVal); 1857 // } 1858 1859 /** Intended to be called only from TreeSet.addAll */ 1860 // void addAllForTreeSet(SortedSet!K set, V defaultVal) { 1861 // try { 1862 // buildFromSorted(set.size(), set.iterator(), null, defaultVal); 1863 // } catch (IOException cannotHappen) { 1864 // } catch (ClassNotFoundException cannotHappen) { 1865 // } 1866 // } 1867 1868 1869 /** 1870 * Linear time tree building algorithm from sorted data. Can accept keys 1871 * and/or values from iterator or stream. This leads to too many 1872 * parameters, but seems better than alternatives. The four formats 1873 * that this method accepts are: 1874 * 1875 * 1) An iterator of Map.Entries. (it !is null, defaultVal is null). 1876 * 2) An iterator of keys. (it !is null, defaultVal !is null). 1877 * 3) A stream of alternating serialized keys and values. 1878 * (it is null, defaultVal is null). 1879 * 4) A stream of serialized keys. (it is null, defaultVal !is null). 1880 * 1881 * It is assumed that the comparator of the TreeMap is already set prior 1882 * to calling this method. 1883 * 1884 * @param size the number of keys (or key-value pairs) to be read from 1885 * the iterator or stream 1886 * @param it If non-null, new entries are created from entries 1887 * or keys read from this iterator. 1888 * @param str If non-null, new entries are created from keys and 1889 * possibly values read from this stream in serialized form. 1890 * Exactly one of it and str should be non-null. 1891 * @param defaultVal if non-null, this default value is used for 1892 * each value in the map. If null, each value is read from 1893 * iterator or stream, as described above. 1894 * @throws java.io.IOException propagated from stream reads. This cannot 1895 * occur if str is null. 1896 * @throws ClassNotFoundException propagated from readObject. 1897 * This cannot occur if str is null. 1898 */ 1899 // private void buildFromSorted(int size, Iterator<?> it, 1900 // // java.io.ObjectInputStream str, 1901 // V defaultVal) { 1902 // this._size = size; 1903 // root = buildFromSorted(0, 0, size-1, computeRedLevel(size), 1904 // it, defaultVal); 1905 // } 1906 1907 /** 1908 * Recursive "helper method" that does the real work of the 1909 * previous method. Identically named parameters have 1910 * identical definitions. Additional parameters are documented below. 1911 * It is assumed that the comparator and size fields of the TreeMap are 1912 * already set prior to calling this method. (It ignores both fields.) 1913 * 1914 * @param level the current level of tree. Initial call should be 0. 1915 * @param lo the first element index of this subtree. Initial should be 0. 1916 * @param hi the last element index of this subtree. Initial should be 1917 * size-1. 1918 * @param redLevel the level at which nodes should be red. 1919 * Must be equal to computeRedLevel for tree of this size. 1920 */ 1921 // private final TreeMapEntry!(K,V) buildFromSorted(int level, int lo, int hi, 1922 // int redLevel, 1923 // Iterator<?> it, 1924 // // java.io.ObjectInputStream str, 1925 // V defaultVal) { 1926 // /* 1927 // * Strategy: The root is the middlemost element. To get to it, we 1928 // * have to first recursively construct the entire left subtree, 1929 // * so as to grab all of its elements. We can then proceed with right 1930 // * subtree. 1931 // * 1932 // * The lo and hi arguments are the minimum and maximum 1933 // * indices to pull out of the iterator or stream for current subtree. 1934 // * They are not actually indexed, we just proceed sequentially, 1935 // * ensuring that items are extracted in corresponding order. 1936 // */ 1937 1938 // if (hi < lo) return null; 1939 1940 // int mid = (lo + hi) >>> 1; 1941 1942 // TreeMapEntry!(K,V) left = null; 1943 // if (lo < mid) 1944 // left = buildFromSorted(level+1, lo, mid - 1, redLevel, 1945 // it, str, defaultVal); 1946 1947 // // extract key and/or value from iterator or stream 1948 // K key; 1949 // V value; 1950 // if (it !is null) { 1951 // if (defaultVal is null) { 1952 // MapEntry<?,?> entry = (MapEntry<?,?>)it.next(); 1953 // key = (K)entry.getKey(); 1954 // value = (V)entry.getValue(); 1955 // } else { 1956 // key = (K)it.next(); 1957 // value = defaultVal; 1958 // } 1959 // } else { // use stream 1960 // key = (K) str.readObject(); 1961 // value = (defaultVal !is null ? defaultVal : (V) str.readObject()); 1962 // } 1963 1964 // TreeMapEntry!(K,V) middle = new Entry<>(key, value, null); 1965 1966 // // color nodes in non-full bottommost level red 1967 // if (level == redLevel) 1968 // middle.color = RED; 1969 1970 // if (left !is null) { 1971 // middle.left = left; 1972 // left.parent = middle; 1973 // } 1974 1975 // if (mid < hi) { 1976 // TreeMapEntry!(K,V) right = buildFromSorted(level+1, mid+1, hi, redLevel, 1977 // it, str, defaultVal); 1978 // middle.right = right; 1979 // right.parent = middle; 1980 // } 1981 1982 // return middle; 1983 // } 1984 1985 /** 1986 * Find the level down to which to assign all nodes BLACK. This is the 1987 * last `full' level of the complete binary tree produced by 1988 * buildTree. The remaining nodes are colored RED. (This makes a `nice' 1989 * set of color assignments wrt future insertions.) This level number is 1990 * computed by finding the number of splits needed to reach the zeroeth 1991 * node. (The answer is ~lg(N), but in any case must be computed by same 1992 * quick O(lg(N)) loop.) 1993 */ 1994 private static int computeRedLevel(int sz) { 1995 int level = 0; 1996 for (int m = sz - 1; m >= 0; m = m / 2 - 1) 1997 level++; 1998 return level; 1999 } 2000 2001 /** 2002 * Currently, we support Spliterator-based versions only for the 2003 * full map, in either plain of descending form, otherwise relying 2004 * on defaults because size estimation for submaps would dominate 2005 * costs. The type tests needed to check these for key views are 2006 * not very nice but avoid disrupting existing class 2007 * structures. Callers must use plain default spliterators if this 2008 * returns null. 2009 */ 2010 // static !K Spliterator!K keySpliteratorFor(NavigableMap<K,?> m) { 2011 // if (m instanceof TreeMap) { 2012 // TreeMap<K,Object> t = 2013 // (TreeMap<K,Object>) m; 2014 // return t.keySpliterator(); 2015 // } 2016 // if (m instanceof DescendingSubMap) { 2017 // DescendingSubMap<K,?> dm = 2018 // (DescendingSubMap<K,?>) m; 2019 // TreeMap<K,?> tm = dm.m; 2020 // if (dm == tm.descendingMap) { 2021 // TreeMap<K,Object> t = 2022 // (TreeMap<K,Object>) tm; 2023 // return t.descendingKeySpliterator(); 2024 // } 2025 // } 2026 // NavigableSubMap<K,?> sm = 2027 // (NavigableSubMap<K,?>) m; 2028 // return sm.keySpliterator(); 2029 // } 2030 2031 // final Spliterator!K keySpliterator() { 2032 // return new KeySpliterator!(K,V)(this, null, null, 0, -1, 0); 2033 // } 2034 2035 // final Spliterator!K descendingKeySpliterator() { 2036 // return new DescendingKeySpliterator!(K,V)(this, null, null, 0, -2, 0); 2037 // } 2038 2039 /** 2040 * Base class for spliterators. Iteration starts at a given 2041 * origin and continues up to but not including a given fence (or 2042 * null for end). At top-level, for ascending cases, the first 2043 * split uses the root as left-fence/right-origin. From there, 2044 * right-hand splits replace the current fence with its left 2045 * child, also serving as origin for the split-off spliterator. 2046 * Left-hands are symmetric. Descending versions place the origin 2047 * at the end and invert ascending split rules. This base class 2048 * is non-commital about directionality, or whether the top-level 2049 * spliterator covers the whole tree. This means that the actual 2050 * split mechanics are located in subclasses. Some of the subclass 2051 * trySplit methods are identical (except for return types), but 2052 * not nicely factorable. 2053 * 2054 * Currently, subclass versions exist only for the full map 2055 * (including descending keys via its descendingMap). Others are 2056 * possible but currently not worthwhile because submaps require 2057 * O(n) computations to determine size, which substantially limits 2058 * potential speed-ups of using custom Spliterators versus default 2059 * mechanics. 2060 * 2061 * To boostrap initialization, external constructors use 2062 * negative size estimates: -1 for ascend, -2 for descend. 2063 */ 2064 // static class TreeMapSpliterator!(K,V) { 2065 // final TreeMap!(K,V) tree; 2066 // TreeMapEntry!(K,V) current; // traverser; initially first node in range 2067 // TreeMapEntry!(K,V) fence; // one past last, or null 2068 // int side; // 0: top, -1: is a left split, +1: right 2069 // int est; // size estimate (exact only for top-level) 2070 // int expectedModCount; // for CME checks 2071 2072 // TreeMapSpliterator(TreeMap!(K,V) tree, 2073 // TreeMapEntry!(K,V) origin, TreeMapEntry!(K,V) fence, 2074 // int side, int est, int expectedModCount) { 2075 // this.tree = tree; 2076 // this.current = origin; 2077 // this.fence = fence; 2078 // this.side = side; 2079 // this.est = est; 2080 // this.expectedModCount = expectedModCount; 2081 // } 2082 2083 // final int getEstimate() { // force initialization 2084 // int s; TreeMap!(K,V) t; 2085 // if ((s = est) < 0) { 2086 // if ((t = tree) !is null) { 2087 // current = (s == -1) ? t.getFirstEntry() : t.getLastEntry(); 2088 // s = est = t.size; 2089 // expectedModCount = t.modCount; 2090 // } 2091 // else 2092 // s = est = 0; 2093 // } 2094 // return s; 2095 // } 2096 2097 // final long estimateSize() { 2098 // return (long)getEstimate(); 2099 // } 2100 // } 2101 2102 // static final class KeySpliterator!(K,V) 2103 // : TreeMapSpliterator!(K,V) 2104 // , Spliterator!K { 2105 // KeySpliterator(TreeMap!(K,V) tree, 2106 // TreeMapEntry!(K,V) origin, TreeMapEntry!(K,V) fence, 2107 // int side, int est, int expectedModCount) { 2108 // super(tree, origin, fence, side, est, expectedModCount); 2109 // } 2110 2111 // KeySpliterator!(K,V) trySplit() { 2112 // if (est < 0) 2113 // getEstimate(); // force initialization 2114 // int d = side; 2115 // TreeMapEntry!(K,V) e = current, f = fence, 2116 // s = ((e is null || e == f) ? null : // empty 2117 // (d == 0) ? tree.root : // was top 2118 // (d > 0) ? e.right : // was right 2119 // (d < 0 && f !is null) ? f.left : // was left 2120 // null); 2121 // if (s !is null && s !is e && s !is f && 2122 // tree.compare(e.key, s.key) < 0) { // e not already past s 2123 // side = 1; 2124 // return new KeySpliterator<> 2125 // (tree, e, current = s, -1, est >>>= 1, expectedModCount); 2126 // } 2127 // return null; 2128 // } 2129 2130 // void forEachRemaining(Consumer!K action) { 2131 // if (action is null) 2132 // throw new NullPointerException(); 2133 // if (est < 0) 2134 // getEstimate(); // force initialization 2135 // TreeMapEntry!(K,V) f = fence, e, p, pl; 2136 // if ((e = current) !is null && e !is f) { 2137 // current = f; // exhaust 2138 // do { 2139 // action.accept(e.key); 2140 // if ((p = e.right) !is null) { 2141 // while ((pl = p.left) !is null) 2142 // p = pl; 2143 // } 2144 // else { 2145 // while ((p = e.parent) !is null && e == p.right) 2146 // e = p; 2147 // } 2148 // } while ((e = p) !is null && e !is f); 2149 // if (tree.modCount !is expectedModCount) 2150 // throw new ConcurrentModificationException(); 2151 // } 2152 // } 2153 2154 // bool tryAdvance(Consumer!K action) { 2155 // TreeMapEntry!(K,V) e; 2156 // if (action is null) 2157 // throw new NullPointerException(); 2158 // if (est < 0) 2159 // getEstimate(); // force initialization 2160 // if ((e = current) is null || e == fence) 2161 // return false; 2162 // current = successor(e); 2163 // action.accept(e.key); 2164 // if (tree.modCount !is expectedModCount) 2165 // throw new ConcurrentModificationException(); 2166 // return true; 2167 // } 2168 2169 // int characteristics() { 2170 // return (side == 0 ? Spliterator.SIZED : 0) | 2171 // Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED; 2172 // } 2173 2174 // final Comparator!K getComparator() { 2175 // return tree.comparator; 2176 // } 2177 2178 // } 2179 2180 // static final class DescendingKeySpliterator!(K,V) 2181 // : TreeMapSpliterator!(K,V) 2182 // , Spliterator!K { 2183 // DescendingKeySpliterator(TreeMap!(K,V) tree, 2184 // TreeMapEntry!(K,V) origin, TreeMapEntry!(K,V) fence, 2185 // int side, int est, int expectedModCount) { 2186 // super(tree, origin, fence, side, est, expectedModCount); 2187 // } 2188 2189 // DescendingKeySpliterator!(K,V) trySplit() { 2190 // if (est < 0) 2191 // getEstimate(); // force initialization 2192 // int d = side; 2193 // TreeMapEntry!(K,V) e = current, f = fence, 2194 // s = ((e is null || e == f) ? null : // empty 2195 // (d == 0) ? tree.root : // was top 2196 // (d < 0) ? e.left : // was left 2197 // (d > 0 && f !is null) ? f.right : // was right 2198 // null); 2199 // if (s !is null && s !is e && s !is f && 2200 // tree.compare(e.key, s.key) > 0) { // e not already past s 2201 // side = 1; 2202 // return new DescendingKeySpliterator<> 2203 // (tree, e, current = s, -1, est >>>= 1, expectedModCount); 2204 // } 2205 // return null; 2206 // } 2207 2208 // void forEachRemaining(Consumer!K action) { 2209 // if (action is null) 2210 // throw new NullPointerException(); 2211 // if (est < 0) 2212 // getEstimate(); // force initialization 2213 // TreeMapEntry!(K,V) f = fence, e, p, pr; 2214 // if ((e = current) !is null && e !is f) { 2215 // current = f; // exhaust 2216 // do { 2217 // action.accept(e.key); 2218 // if ((p = e.left) !is null) { 2219 // while ((pr = p.right) !is null) 2220 // p = pr; 2221 // } 2222 // else { 2223 // while ((p = e.parent) !is null && e == p.left) 2224 // e = p; 2225 // } 2226 // } while ((e = p) !is null && e !is f); 2227 // if (tree.modCount !is expectedModCount) 2228 // throw new ConcurrentModificationException(); 2229 // } 2230 // } 2231 2232 // bool tryAdvance(Consumer!K action) { 2233 // TreeMapEntry!(K,V) e; 2234 // if (action is null) 2235 // throw new NullPointerException(); 2236 // if (est < 0) 2237 // getEstimate(); // force initialization 2238 // if ((e = current) is null || e == fence) 2239 // return false; 2240 // current = predecessor(e); 2241 // action.accept(e.key); 2242 // if (tree.modCount !is expectedModCount) 2243 // throw new ConcurrentModificationException(); 2244 // return true; 2245 // } 2246 2247 // int characteristics() { 2248 // return (side == 0 ? Spliterator.SIZED : 0) | 2249 // Spliterator.DISTINCT | Spliterator.ORDERED; 2250 // } 2251 // } 2252 2253 // static final class ValueSpliterator!(K,V) 2254 // : TreeMapSpliterator!(K,V) 2255 // , Spliterator!V { 2256 // ValueSpliterator(TreeMap!(K,V) tree, 2257 // TreeMapEntry!(K,V) origin, TreeMapEntry!(K,V) fence, 2258 // int side, int est, int expectedModCount) { 2259 // super(tree, origin, fence, side, est, expectedModCount); 2260 // } 2261 2262 // ValueSpliterator!(K,V) trySplit() { 2263 // if (est < 0) 2264 // getEstimate(); // force initialization 2265 // int d = side; 2266 // TreeMapEntry!(K,V) e = current, f = fence, 2267 // s = ((e is null || e == f) ? null : // empty 2268 // (d == 0) ? tree.root : // was top 2269 // (d > 0) ? e.right : // was right 2270 // (d < 0 && f !is null) ? f.left : // was left 2271 // null); 2272 // if (s !is null && s !is e && s !is f && 2273 // tree.compare(e.key, s.key) < 0) { // e not already past s 2274 // side = 1; 2275 // return new ValueSpliterator<> 2276 // (tree, e, current = s, -1, est >>>= 1, expectedModCount); 2277 // } 2278 // return null; 2279 // } 2280 2281 // void forEachRemaining(Consumer<V> action) { 2282 // if (action is null) 2283 // throw new NullPointerException(); 2284 // if (est < 0) 2285 // getEstimate(); // force initialization 2286 // TreeMapEntry!(K,V) f = fence, e, p, pl; 2287 // if ((e = current) !is null && e !is f) { 2288 // current = f; // exhaust 2289 // do { 2290 // action.accept(e.value); 2291 // if ((p = e.right) !is null) { 2292 // while ((pl = p.left) !is null) 2293 // p = pl; 2294 // } 2295 // else { 2296 // while ((p = e.parent) !is null && e == p.right) 2297 // e = p; 2298 // } 2299 // } while ((e = p) !is null && e !is f); 2300 // if (tree.modCount !is expectedModCount) 2301 // throw new ConcurrentModificationException(); 2302 // } 2303 // } 2304 2305 // bool tryAdvance(Consumer<V> action) { 2306 // TreeMapEntry!(K,V) e; 2307 // if (action is null) 2308 // throw new NullPointerException(); 2309 // if (est < 0) 2310 // getEstimate(); // force initialization 2311 // if ((e = current) is null || e == fence) 2312 // return false; 2313 // current = successor(e); 2314 // action.accept(e.value); 2315 // if (tree.modCount !is expectedModCount) 2316 // throw new ConcurrentModificationException(); 2317 // return true; 2318 // } 2319 2320 // int characteristics() { 2321 // return (side == 0 ? Spliterator.SIZED : 0) | Spliterator.ORDERED; 2322 // } 2323 // } 2324 2325 // static final class EntrySpliterator!(K,V) 2326 // : TreeMapSpliterator!(K,V) 2327 // , Spliterator!(MapEntry!(K,V)) { 2328 // EntrySpliterator(TreeMap!(K,V) tree, 2329 // TreeMapEntry!(K,V) origin, TreeMapEntry!(K,V) fence, 2330 // int side, int est, int expectedModCount) { 2331 // super(tree, origin, fence, side, est, expectedModCount); 2332 // } 2333 2334 // EntrySpliterator!(K,V) trySplit() { 2335 // if (est < 0) 2336 // getEstimate(); // force initialization 2337 // int d = side; 2338 // TreeMapEntry!(K,V) e = current, f = fence, 2339 // s = ((e is null || e == f) ? null : // empty 2340 // (d == 0) ? tree.root : // was top 2341 // (d > 0) ? e.right : // was right 2342 // (d < 0 && f !is null) ? f.left : // was left 2343 // null); 2344 // if (s !is null && s !is e && s !is f && 2345 // tree.compare(e.key, s.key) < 0) { // e not already past s 2346 // side = 1; 2347 // return new EntrySpliterator<> 2348 // (tree, e, current = s, -1, est >>>= 1, expectedModCount); 2349 // } 2350 // return null; 2351 // } 2352 2353 // void forEachRemaining(Consumer<MapEntry!(K, V)> action) { 2354 // if (action is null) 2355 // throw new NullPointerException(); 2356 // if (est < 0) 2357 // getEstimate(); // force initialization 2358 // TreeMapEntry!(K,V) f = fence, e, p, pl; 2359 // if ((e = current) !is null && e !is f) { 2360 // current = f; // exhaust 2361 // do { 2362 // action.accept(e); 2363 // if ((p = e.right) !is null) { 2364 // while ((pl = p.left) !is null) 2365 // p = pl; 2366 // } 2367 // else { 2368 // while ((p = e.parent) !is null && e == p.right) 2369 // e = p; 2370 // } 2371 // } while ((e = p) !is null && e !is f); 2372 // if (tree.modCount !is expectedModCount) 2373 // throw new ConcurrentModificationException(); 2374 // } 2375 // } 2376 2377 // bool tryAdvance(Consumer<MapEntry!(K,V)> action) { 2378 // TreeMapEntry!(K,V) e; 2379 // if (action is null) 2380 // throw new NullPointerException(); 2381 // if (est < 0) 2382 // getEstimate(); // force initialization 2383 // if ((e = current) is null || e == fence) 2384 // return false; 2385 // current = successor(e); 2386 // action.accept(e); 2387 // if (tree.modCount !is expectedModCount) 2388 // throw new ConcurrentModificationException(); 2389 // return true; 2390 // } 2391 2392 // int characteristics() { 2393 // return (side == 0 ? Spliterator.SIZED : 0) | 2394 // Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED; 2395 // } 2396 2397 // override 2398 // Comparator<MapEntry!(K, V)> getComparator() { 2399 // // Adapt or create a key-based comparator 2400 // if (tree.comparator !is null) { 2401 // return MapEntry.comparingByKey(tree.comparator); 2402 // } 2403 // else { 2404 // return (Comparator<MapEntry!(K, V)> & Serializable) (e1, e2) -> { 2405 // 2406 // Comparable!K k1 = (Comparable!K) e1.getKey(); 2407 // return k1.compareTo(e2.getKey()); 2408 // }; 2409 // } 2410 // } 2411 // } 2412 2413 override bool opEquals(IObject o) { 2414 return opEquals(cast(Object) o); 2415 } 2416 2417 override bool opEquals(Object o) { 2418 return super.opEquals(o); 2419 } 2420 2421 override size_t toHash() @trusted nothrow { 2422 return super.toHash(); 2423 } 2424 2425 override string toString() { 2426 return super.toString(); 2427 } 2428 } 2429 2430 2431 /** 2432 * Node in the Tree. Doubles as a means to pass key-value pairs back to 2433 * user (see MapEntry). 2434 */ 2435 2436 static final class TreeMapEntry(K,V) : MapEntry!(K,V) { 2437 K key; 2438 V value; 2439 TreeMapEntry!(K,V) left; 2440 TreeMapEntry!(K,V) right; 2441 TreeMapEntry!(K,V) parent; 2442 bool color = BLACK; 2443 2444 /** 2445 * Make a new cell with given key, value, and parent, and with 2446 * {@code null} child links, and BLACK color. 2447 */ 2448 this(K key, V value, TreeMapEntry!(K,V) parent) { 2449 this.key = key; 2450 this.value = value; 2451 this.parent = parent; 2452 } 2453 2454 /** 2455 * Returns the key. 2456 * 2457 * @return the key 2458 */ 2459 K getKey() { 2460 return key; 2461 } 2462 2463 /** 2464 * Returns the value associated with the key. 2465 * 2466 * @return the value associated with the key 2467 */ 2468 V getValue() { 2469 return value; 2470 } 2471 2472 /** 2473 * Replaces the value currently associated with the key with the given 2474 * value. 2475 * 2476 * @return the value associated with the key before this method was 2477 * called 2478 */ 2479 V setValue(V value) { 2480 V oldValue = this.value; 2481 this.value = value; 2482 return oldValue; 2483 } 2484 2485 bool opEquals(IObject o) { 2486 return opEquals(cast(Object) o); 2487 } 2488 2489 override bool opEquals(Object o) { 2490 MapEntry!(K, V) e = cast(MapEntry!(K, V))o; 2491 if (e is null) 2492 return false; 2493 2494 return key == e.getKey() && value == e.getValue(); 2495 } 2496 2497 override size_t toHash() @trusted nothrow { 2498 // int keyHash = (key is null ? 0 : key.hashCode()); 2499 // int valueHash = (value is null ? 0 : value.hashCode()); 2500 // return keyHash ^ valueHash; 2501 static if(is(K == class)) { 2502 size_t kHash = 0; 2503 if(key !is null) kHash = key.toHash(); 2504 } 2505 else { 2506 size_t kHash = hashOf(key); 2507 } 2508 2509 static if(is(V == class)) { 2510 size_t vHash = 0; 2511 if(value !is null) vHash = value.toHash(); 2512 } 2513 else { 2514 size_t vHash = hashOf(value); 2515 } 2516 2517 return kHash ^ vHash; 2518 } 2519 2520 override string toString() { 2521 return key.to!string() ~ "=" ~ value.to!string(); 2522 } 2523 } 2524 2525 2526 /** 2527 * @serial include 2528 */ 2529 abstract static class NavigableSubMap(K,V) : AbstractMap!(K,V) , NavigableMap!(K,V) { 2530 /** 2531 * The backing map. 2532 */ 2533 protected TreeMap!(K,V) m; 2534 2535 /** 2536 * Endpoints are represented as triples (fromStart, lo, 2537 * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is 2538 * true, then the low (absolute) bound is the start of the 2539 * backing map, and the other values are ignored. Otherwise, 2540 * if loInclusive is true, lo is the inclusive bound, else lo 2541 * is the exclusive bound. Similarly for the upper bound. 2542 */ 2543 K lo, hi; 2544 bool fromStart, toEnd; 2545 bool loInclusive, hiInclusive; 2546 2547 int sizeModCount = 0; 2548 2549 this(TreeMap!(K,V) m, 2550 bool fromStart, K lo, bool loInclusive, 2551 bool toEnd, K hi, bool hiInclusive) { 2552 if (!fromStart && !toEnd) { 2553 if (compare(lo, hi) > 0) 2554 throw new IllegalArgumentException("fromKey > toKey"); 2555 } else { 2556 // if (!fromStart) // type check 2557 // compare(lo, lo); 2558 // if (!toEnd) 2559 // compare(hi, hi); 2560 } 2561 2562 this.m = m; 2563 this.fromStart = fromStart; 2564 this.lo = lo; 2565 this.loInclusive = loInclusive; 2566 this.toEnd = toEnd; 2567 this.hi = hi; 2568 this.hiInclusive = hiInclusive; 2569 2570 this._size = -1; 2571 // if(fromStart && toEnd) 2572 // this._size = m.size(); 2573 // else 2574 // updateSize(); 2575 } 2576 2577 // internal utilities 2578 2579 final bool tooLow(K key) { 2580 if (!fromStart) { 2581 int c = compare(key, lo); 2582 if (c < 0 || (c == 0 && !loInclusive)) 2583 return true; 2584 } 2585 return false; 2586 } 2587 2588 final bool tooHigh(K key) { 2589 if (!toEnd) { 2590 int c = compare(key, hi); 2591 if (c > 0 || (c == 0 && !hiInclusive)) 2592 return true; 2593 } 2594 return false; 2595 } 2596 2597 final bool inRange(K key) { 2598 return !tooLow(key) && !tooHigh(key); 2599 } 2600 2601 final bool inClosedRange(K key) { 2602 return (fromStart || compare(key, lo) >= 0) 2603 && (toEnd || compare(hi, key) >= 0); 2604 } 2605 2606 final bool inRange(K key, bool inclusive) { 2607 return inclusive ? inRange(key) : inClosedRange(key); 2608 } 2609 2610 /* 2611 * Absolute versions of relation operations. 2612 * Subclasses map to these using like-named "sub" 2613 * versions that invert senses for descending maps 2614 */ 2615 2616 final TreeMapEntry!(K,V) absLowest() { 2617 TreeMapEntry!(K,V) e = 2618 (fromStart ? m.getFirstEntry() : 2619 (loInclusive ? m.getCeilingEntry(lo) : 2620 m.getHigherEntry(lo))); 2621 return (e is null || tooHigh(e.key)) ? null : e; 2622 } 2623 2624 final TreeMapEntry!(K,V) absHighest() { 2625 TreeMapEntry!(K,V) e = 2626 (toEnd ? m.getLastEntry() : 2627 (hiInclusive ? m.getFloorEntry(hi) : 2628 m.getLowerEntry(hi))); 2629 return (e is null || tooLow(e.key)) ? null : e; 2630 } 2631 2632 final TreeMapEntry!(K,V) absCeiling(K key) { 2633 if (tooLow(key)) 2634 return absLowest(); 2635 TreeMapEntry!(K,V) e = m.getCeilingEntry(key); 2636 return (e is null || tooHigh(e.key)) ? null : e; 2637 } 2638 2639 final TreeMapEntry!(K,V) absHigher(K key) { 2640 if (tooLow(key)) 2641 return absLowest(); 2642 TreeMapEntry!(K,V) e = m.getHigherEntry(key); 2643 return (e is null || tooHigh(e.key)) ? null : e; 2644 } 2645 2646 final TreeMapEntry!(K,V) absFloor(K key) { 2647 if (tooHigh(key)) 2648 return absHighest(); 2649 TreeMapEntry!(K,V) e = m.getFloorEntry(key); 2650 return (e is null || tooLow(e.key)) ? null : e; 2651 } 2652 2653 final TreeMapEntry!(K,V) absLower(K key) { 2654 if (tooHigh(key)) 2655 return absHighest(); 2656 TreeMapEntry!(K,V) e = m.getLowerEntry(key); 2657 return (e is null || tooLow(e.key)) ? null : e; 2658 } 2659 2660 /** Returns the absolute high fence for ascending traversal */ 2661 final TreeMapEntry!(K,V) absHighFence() { 2662 return (toEnd ? null : (hiInclusive ? 2663 m.getHigherEntry(hi) : 2664 m.getCeilingEntry(hi))); 2665 } 2666 2667 /** Return the absolute low fence for descending traversal */ 2668 final TreeMapEntry!(K,V) absLowFence() { 2669 return (fromStart ? null : (loInclusive ? 2670 m.getLowerEntry(lo) : 2671 m.getFloorEntry(lo))); 2672 } 2673 2674 // Abstract methods defined in ascending vs descending classes 2675 // These relay to the appropriate absolute versions 2676 2677 abstract TreeMapEntry!(K,V) subLowest(); 2678 abstract TreeMapEntry!(K,V) subHighest(); 2679 abstract TreeMapEntry!(K,V) subCeiling(K key); 2680 abstract TreeMapEntry!(K,V) subHigher(K key); 2681 abstract TreeMapEntry!(K,V) subFloor(K key); 2682 abstract TreeMapEntry!(K,V) subLower(K key); 2683 2684 /** Returns ascending iterator from the perspective of this submap */ 2685 // abstract Iterator!K keyIterator(); 2686 2687 // abstract Spliterator!K keySpliterator(); 2688 2689 /** Returns descending iterator from the perspective of this submap */ 2690 // abstract Iterator!K descendingKeyIterator(); 2691 2692 2693 // methods 2694 override bool opEquals(IObject o) { 2695 return opEquals(cast(Object) o); 2696 } 2697 2698 override bool opEquals(Object o) { 2699 return super.opEquals(o); 2700 } 2701 2702 override size_t toHash() @trusted nothrow { 2703 return super.toHash(); 2704 } 2705 2706 override string toString() { 2707 return super.toString(); 2708 } 2709 2710 override bool isEmpty() { 2711 if(fromStart && toEnd) 2712 return m.isEmpty(); 2713 else { 2714 TreeMapEntry!(K,V) n = absLowest(); 2715 return n is null || tooHigh(n.key); 2716 } 2717 } 2718 2719 override int size() { 2720 if(fromStart && toEnd) 2721 return m.size(); 2722 if(_size == -1 || sizeModCount != m.modCount) 2723 updateSize(); 2724 return _size; 2725 } 2726 2727 private void updateSize() { 2728 int s = 0; 2729 foreach(item; this) { 2730 s++; 2731 } 2732 _size = s; 2733 } 2734 2735 final override bool containsKey(K key) { 2736 return inRange(key) && m.containsKey(key); 2737 } 2738 2739 final override V put(K key, V value) { 2740 if (!inRange(key)) 2741 throw new IllegalArgumentException("key out of range"); 2742 // _size++; 2743 return m.put(key, value); 2744 } 2745 2746 final override V get(K key) { 2747 return !inRange(key) ? null : m.get(key); 2748 } 2749 2750 final override V remove(K key) { 2751 // _size--; 2752 return !inRange(key) ? null : m.remove(key); 2753 } 2754 2755 final MapEntry!(K,V) ceilingEntry(K key) { 2756 return exportEntry!(K,V)(subCeiling(key)); 2757 } 2758 2759 final K ceilingKey(K key) { 2760 return keyOrNull(subCeiling(key)); 2761 } 2762 2763 final MapEntry!(K,V) higherEntry(K key) { 2764 return exportEntry!(K,V)(subHigher(key)); 2765 } 2766 2767 final K higherKey(K key) { 2768 return keyOrNull(subHigher(key)); 2769 } 2770 2771 final MapEntry!(K,V) floorEntry(K key) { 2772 return exportEntry!(K,V)(subFloor(key)); 2773 } 2774 2775 final K floorKey(K key) { 2776 return keyOrNull(subFloor(key)); 2777 } 2778 2779 final MapEntry!(K,V) lowerEntry(K key) { 2780 return exportEntry!(K,V)(subLower(key)); 2781 } 2782 2783 final K lowerKey(K key) { 2784 return keyOrNull(subLower(key)); 2785 } 2786 2787 final K firstKey() { 2788 return key(subLowest()); 2789 } 2790 2791 final K lastKey() { 2792 return key(subHighest()); 2793 } 2794 2795 final MapEntry!(K,V) firstEntry() { 2796 return exportEntry!(K,V)(subLowest()); 2797 } 2798 2799 final MapEntry!(K,V) lastEntry() { 2800 return exportEntry!(K,V)(subHighest()); 2801 } 2802 2803 final MapEntry!(K,V) pollFirstEntry() { 2804 TreeMapEntry!(K,V) e = subLowest(); 2805 MapEntry!(K,V) result = exportEntry!(K,V)(e); 2806 if (e !is null) 2807 m.deleteEntry(e); 2808 return result; 2809 } 2810 2811 final MapEntry!(K,V) pollLastEntry() { 2812 TreeMapEntry!(K,V) e = subHighest(); 2813 MapEntry!(K,V) result = exportEntry!(K,V)(e); 2814 if (e !is null) 2815 m.deleteEntry(e); 2816 return result; 2817 } 2818 2819 // Views 2820 // NavigableMap!(K,V) descendingMapView; 2821 // EntrySetView entrySetView; 2822 // KeySet!(K, V) navigableKeySetView; 2823 2824 // final NavigableSet!K navigableKeySet() { 2825 // KeySet!(K, V) nksv = navigableKeySetView; 2826 // return (nksv !is null) ? nksv : 2827 // (navigableKeySetView = new TreeMap.KeySet!(K, V)(this)); 2828 // } 2829 2830 // final Set!K keySet() { 2831 // return navigableKeySet(); 2832 // } 2833 2834 // NavigableSet!K descendingKeySet() { 2835 // return descendingMap().navigableKeySet(); 2836 // } 2837 2838 alias subMap = NavigableMap!(K,V).subMap; 2839 alias headMap = NavigableMap!(K,V).headMap; 2840 alias tailMap = NavigableMap!(K,V).tailMap; 2841 2842 final SortedMap!(K,V) subMap(K fromKey, K toKey) { 2843 return subMap(fromKey, true, toKey, false); 2844 } 2845 2846 final SortedMap!(K,V) headMap(K toKey) { 2847 return headMap(toKey, false); 2848 } 2849 2850 final SortedMap!(K,V) tailMap(K fromKey) { 2851 return tailMap(fromKey, true); 2852 } 2853 2854 // View classes 2855 2856 // abstract class EntrySetView : AbstractSet!(MapEntry!(K,V)) { 2857 // private int _size = -1, sizeModCount; 2858 2859 // override int size() { 2860 // if (fromStart && toEnd) 2861 // return m.size(); 2862 // // if (_size == -1 || sizeModCount !is m.modCount) { 2863 // // sizeModCount = m.modCount; 2864 // // _size = 0; 2865 // // Iterator!K i = iterator(); 2866 // // while (i.hasNext()) { 2867 // // _size++; 2868 // // i.next(); 2869 // // } 2870 // // } 2871 // implementationMissing(); 2872 // return _size; 2873 // } 2874 2875 // override bool isEmpty() { 2876 // TreeMapEntry!(K,V) n = absLowest(); 2877 // return n is null || tooHigh(n.key); 2878 // } 2879 2880 // override bool contains(MapEntry!(K,V) entry) { 2881 // // MapEntry!(K,V) entry = cast(MapEntry!(K,V)) o; 2882 // // if (!(o instanceof MapEntry)) 2883 // // return false; 2884 // K key = entry.getKey(); 2885 // if (!inRange(key)) 2886 // return false; 2887 // TreeMapEntry!(K,V) node = m.getEntry(key); 2888 // return node !is null && 2889 // valEquals(node.getValue(), entry.getValue()); 2890 // } 2891 2892 // bool remove(MapEntry!(K,V) entry) { 2893 // // if (!(o instanceof MapEntry)) 2894 // // return false; 2895 // // MapEntry<?,?> entry = (MapEntry<?,?>) o; 2896 // K key = entry.getKey(); 2897 // if (!inRange(key)) 2898 // return false; 2899 // TreeMapEntry!(K,V) node = m.getEntry(key); 2900 // if (node !is null && valEquals(node.getValue(), 2901 // entry.getValue())) { 2902 // m.deleteEntry(node); 2903 // return true; 2904 // } 2905 // return false; 2906 // } 2907 // } 2908 2909 2910 /** 2911 * Iterators for SubMaps 2912 */ 2913 2914 // see also: SubMapIterator 2915 mixin template SubMapInputRange() { 2916 TreeMapEntry!(K,V) lastReturned; 2917 TreeMapEntry!(K,V) next; 2918 K fenceKey; 2919 int expectedModCount; 2920 2921 this(TreeMapEntry!(K,V) first, 2922 TreeMapEntry!(K,V) fence) { 2923 expectedModCount = m.modCount; 2924 lastReturned = null; 2925 next = first; 2926 fenceKey = fence is null ? K.init : fence.key; 2927 } 2928 2929 final bool empty() { 2930 return next is null || next.key == fenceKey; 2931 } 2932 2933 final void popFront() { 2934 TreeMapEntry!(K,V) e = next; 2935 if (e is null || e.key == fenceKey) { 2936 throw new NoSuchElementException(); 2937 } 2938 2939 next = successor(e); 2940 lastReturned = e; 2941 // return e; 2942 } 2943 } 2944 2945 final class KeyInputRange : InputRange!K { 2946 mixin SubMapInputRange; 2947 2948 final K front() @property { return next.key; } 2949 2950 final K moveFront() @property { throw new NotSupportedException(); } 2951 2952 int opApply(scope int delegate(K) dg) { 2953 if(dg is null) 2954 throw new NullPointerException(); 2955 2956 int result = 0; 2957 while(!empty()) { 2958 result = dg(next.key); 2959 // popFront(); 2960 if(result != 0) return result; 2961 next = successor(next); 2962 } 2963 2964 if (m.modCount != expectedModCount) 2965 throw new ConcurrentModificationException(); 2966 return result; 2967 } 2968 2969 int opApply(scope int delegate(size_t, K) dg) { 2970 if(dg is null) 2971 throw new NullPointerException(); 2972 2973 int result = 0; 2974 size_t index = 0; 2975 while(!empty()) { 2976 result = dg(index++, next.key); 2977 if(result != 0) return result; 2978 next = successor(next); 2979 } 2980 2981 if (m.modCount != expectedModCount) 2982 throw new ConcurrentModificationException(); 2983 2984 return result; 2985 } 2986 } 2987 2988 final class ValueInputRange : InputRange!V { 2989 mixin SubMapInputRange; 2990 2991 final V front() @property { return next.value; } 2992 2993 final V moveFront() @property { throw new NotSupportedException(); } 2994 2995 int opApply(scope int delegate(V) dg) { 2996 if(dg is null) 2997 throw new NullPointerException(); 2998 2999 int result = 0; 3000 while(!empty()) { 3001 result = dg(next.value); 3002 if(result != 0) return result; 3003 next = successor(next); 3004 } 3005 3006 if (m.modCount != expectedModCount) 3007 throw new ConcurrentModificationException(); 3008 return result; 3009 } 3010 3011 int opApply(scope int delegate(size_t, V) dg) { 3012 if(dg is null) 3013 throw new NullPointerException(); 3014 3015 int result = 0; 3016 size_t index = 0; 3017 while(!empty()) { 3018 result = dg(index++, next.value); 3019 if(result != 0) return result; 3020 next = successor(next); 3021 } 3022 3023 if (m.modCount != expectedModCount) 3024 throw new ConcurrentModificationException(); 3025 3026 return result; 3027 } 3028 } 3029 3030 3031 abstract class SubMapIterator(T) : Iterator!T { 3032 TreeMapEntry!(K,V) lastReturned; 3033 TreeMapEntry!(K,V) next; 3034 K fenceKey; 3035 int expectedModCount; 3036 3037 this(TreeMapEntry!(K,V) first, 3038 TreeMapEntry!(K,V) fence) { 3039 expectedModCount = m.modCount; 3040 lastReturned = null; 3041 next = first; 3042 fenceKey = fence is null ? K.init : fence.key; 3043 } 3044 3045 final bool hasNext() { 3046 return next !is null && next.key !is fenceKey; 3047 } 3048 3049 final TreeMapEntry!(K,V) nextEntry() { 3050 TreeMapEntry!(K,V) e = next; 3051 if (e is null || e.key == fenceKey) 3052 throw new NoSuchElementException(); 3053 if (m.modCount !is expectedModCount) 3054 throw new ConcurrentModificationException(); 3055 next = successor(e); 3056 lastReturned = e; 3057 return e; 3058 } 3059 3060 final TreeMapEntry!(K,V) prevEntry() { 3061 TreeMapEntry!(K,V) e = next; 3062 if (e is null || e.key == fenceKey) 3063 throw new NoSuchElementException(); 3064 if (m.modCount !is expectedModCount) 3065 throw new ConcurrentModificationException(); 3066 next = predecessor(e); 3067 lastReturned = e; 3068 return e; 3069 } 3070 3071 final void removeAscending() { 3072 if (lastReturned is null) 3073 throw new IllegalStateException(); 3074 if (m.modCount !is expectedModCount) 3075 throw new ConcurrentModificationException(); 3076 // deleted entries are replaced by their successors 3077 if (lastReturned.left !is null && lastReturned.right !is null) 3078 next = lastReturned; 3079 m.deleteEntry(lastReturned); 3080 lastReturned = null; 3081 expectedModCount = m.modCount; 3082 } 3083 3084 final void removeDescending() { 3085 if (lastReturned is null) 3086 throw new IllegalStateException(); 3087 if (m.modCount !is expectedModCount) 3088 throw new ConcurrentModificationException(); 3089 m.deleteEntry(lastReturned); 3090 lastReturned = null; 3091 expectedModCount = m.modCount; 3092 } 3093 3094 } 3095 3096 final class SubMapEntryIterator : SubMapIterator!(MapEntry!(K,V)) { 3097 this(TreeMapEntry!(K,V) first, 3098 TreeMapEntry!(K,V) fence) { 3099 super(first, fence); 3100 } 3101 MapEntry!(K,V) next() { 3102 return nextEntry(); 3103 } 3104 void remove() { 3105 removeAscending(); 3106 } 3107 } 3108 3109 final class DescendingSubMapEntryIterator : SubMapIterator!(MapEntry!(K,V)) { 3110 this(TreeMapEntry!(K,V) last, TreeMapEntry!(K,V) fence) { 3111 super(last, fence); 3112 } 3113 3114 MapEntry!(K,V) next() { 3115 return prevEntry(); 3116 } 3117 void remove() { 3118 removeDescending(); 3119 } 3120 } 3121 3122 // Implement minimal Spliterator as KeySpliterator backup 3123 final class SubMapKeyIterator : SubMapIterator!K { // , Spliterator!K 3124 this(TreeMapEntry!(K,V) first, 3125 TreeMapEntry!(K,V) fence) { 3126 super(first, fence); 3127 } 3128 K next() { 3129 return nextEntry().key; 3130 } 3131 void remove() { 3132 removeAscending(); 3133 } 3134 Spliterator!K trySplit() { 3135 return null; 3136 } 3137 void forEachRemaining(Consumer!K action) { 3138 while (hasNext()) 3139 action(next()); 3140 } 3141 bool tryAdvance(Consumer!K action) { 3142 if (hasNext()) { 3143 action(next()); 3144 return true; 3145 } 3146 return false; 3147 } 3148 long estimateSize() { 3149 return long.max; 3150 } 3151 int characteristics() { 3152 return SpliteratorCharacteristic.DISTINCT | SpliteratorCharacteristic.ORDERED | 3153 SpliteratorCharacteristic.SORTED; 3154 } 3155 final Comparator!K getComparator() { 3156 return this.outer.comparator(); 3157 } 3158 } 3159 3160 final class DescendingSubMapKeyIterator : SubMapIterator!K { // , Spliterator!K 3161 this(TreeMapEntry!(K,V) last, 3162 TreeMapEntry!(K,V) fence) { 3163 super(last, fence); 3164 } 3165 K next() { 3166 return prevEntry().key; 3167 } 3168 void remove() { 3169 removeDescending(); 3170 } 3171 Spliterator!K trySplit() { 3172 return null; 3173 } 3174 void forEachRemaining(Consumer!K action) { 3175 while (hasNext()) 3176 action(next()); 3177 } 3178 bool tryAdvance(Consumer!K action) { 3179 if (hasNext()) { 3180 action(next()); 3181 return true; 3182 } 3183 return false; 3184 } 3185 long estimateSize() { 3186 return long.max; 3187 } 3188 // int characteristics() { 3189 // return Spliterator.DISTINCT | Spliterator.ORDERED; 3190 // } 3191 } 3192 3193 3194 } 3195 3196 /** 3197 * @serial include 3198 */ 3199 final class AscendingSubMap(K,V) : NavigableSubMap!(K,V) { 3200 // private static final long serialVersionUID = 912986545866124060L; 3201 3202 this(TreeMap!(K,V) m, 3203 bool fromStart, K lo, bool loInclusive, 3204 bool toEnd, K hi, bool hiInclusive) { 3205 super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); 3206 } 3207 3208 Comparator!K comparator() { 3209 return m.comparator(); 3210 } 3211 3212 NavigableMap!(K,V) subMap(K fromKey, bool fromInclusive, 3213 K toKey, bool toInclusive) { 3214 if (!inRange(fromKey, fromInclusive)) 3215 throw new IllegalArgumentException("fromKey out of range"); 3216 if (!inRange(toKey, toInclusive)) 3217 throw new IllegalArgumentException("toKey out of range"); 3218 return new AscendingSubMap!(K,V)(m, 3219 false, fromKey, fromInclusive, 3220 false, toKey, toInclusive); 3221 } 3222 3223 NavigableMap!(K,V) headMap(K toKey, bool inclusive) { 3224 if (!inRange(toKey, inclusive)) 3225 throw new IllegalArgumentException("toKey out of range"); 3226 return new AscendingSubMap!(K,V)(m, 3227 fromStart, lo, loInclusive, 3228 false, toKey, inclusive); 3229 } 3230 3231 NavigableMap!(K,V) tailMap(K fromKey, bool inclusive) { 3232 if (!inRange(fromKey, inclusive)) 3233 throw new IllegalArgumentException("fromKey out of range"); 3234 return new AscendingSubMap!(K,V)(m, 3235 false, fromKey, inclusive, 3236 toEnd, hi, hiInclusive); 3237 } 3238 3239 // NavigableMap!(K,V) descendingMap() { 3240 // NavigableMap!(K,V) mv = descendingMapView; 3241 // return (mv !is null) ? mv : 3242 // (descendingMapView = 3243 // new DescendingSubMap!(K,V)(m, 3244 // fromStart, lo, loInclusive, 3245 // toEnd, hi, hiInclusive)); 3246 // } 3247 3248 override InputRange!K byKey() { 3249 return new KeyInputRange(absLowest(), absHighFence()); 3250 } 3251 3252 override InputRange!V byValue() { 3253 return new ValueInputRange(absLowest(), absHighFence()); 3254 } 3255 // override Iterator!K keyIterator() { 3256 // return new SubMapKeyIterator(absLowest(), absHighFence()); 3257 // } 3258 3259 // Spliterator!K keySpliterator() { 3260 // return new SubMapKeyIterator(absLowest(), absHighFence()); 3261 // } 3262 3263 // override Iterator!K descendingKeyIterator() { 3264 // return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 3265 // } 3266 3267 3268 override int opApply(scope int delegate(ref K, ref V) dg) { 3269 if(dg is null) 3270 throw new NullPointerException(); 3271 3272 int result = 0; 3273 Iterator!(MapEntry!(K,V)) iterator = new SubMapEntryIterator(absLowest(), absHighFence()); 3274 while(iterator.hasNext()) { 3275 TreeMapEntry!(K,V) e = cast(TreeMapEntry!(K,V)) iterator.next(); 3276 result = dg(e.key, e.value); 3277 if(result != 0) return result; 3278 } 3279 3280 return result; 3281 } 3282 3283 override int opApply(scope int delegate(MapEntry!(K, V) entry) dg) { 3284 if(dg is null) 3285 throw new NullPointerException(); 3286 3287 int result = 0; 3288 Iterator!(MapEntry!(K,V)) iterator = new SubMapEntryIterator(absLowest(), absHighFence()); 3289 while(iterator.hasNext()) { 3290 result = dg(iterator.next()); 3291 if(result != 0) return result; 3292 } 3293 3294 return result; 3295 } 3296 3297 // final class AscendingEntrySetView : EntrySetView { 3298 // Iterator!(MapEntry!(K,V)) iterator() { 3299 // return new SubMapEntryIterator(absLowest(), absHighFence()); 3300 // } 3301 // } 3302 3303 // Set!(MapEntry!(K,V)) entrySet() { 3304 // EntrySetView es = entrySetView; 3305 // return (es !is null) ? es : (entrySetView = new AscendingEntrySetView()); 3306 // } 3307 3308 override TreeMapEntry!(K,V) subLowest() { return absLowest(); } 3309 override TreeMapEntry!(K,V) subHighest() { return absHighest(); } 3310 override TreeMapEntry!(K,V) subCeiling(K key) { return absCeiling(key); } 3311 override TreeMapEntry!(K,V) subHigher(K key) { return absHigher(key); } 3312 override TreeMapEntry!(K,V) subFloor(K key) { return absFloor(key); } 3313 override TreeMapEntry!(K,V) subLower(K key) { return absLower(key); } 3314 } 3315 3316 /** 3317 * @serial include 3318 */ 3319 final class DescendingSubMap(K,V) : NavigableSubMap!(K,V) { 3320 // private static final long serialVersionUID = 912986545866120460L; 3321 this(TreeMap!(K,V) m, 3322 bool fromStart, K lo, bool loInclusive, 3323 bool toEnd, K hi, bool hiInclusive) { 3324 super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); 3325 3326 // reverseComparator = Collections.reverseOrder(m._comparator); 3327 } 3328 3329 private Comparator!K reverseComparator; 3330 3331 Comparator!K comparator() { 3332 implementationMissing(); 3333 return reverseComparator; 3334 } 3335 3336 NavigableMap!(K,V) subMap(K fromKey, bool fromInclusive, 3337 K toKey, bool toInclusive) { 3338 if (!inRange(fromKey, fromInclusive)) 3339 throw new IllegalArgumentException("fromKey out of range"); 3340 if (!inRange(toKey, toInclusive)) 3341 throw new IllegalArgumentException("toKey out of range"); 3342 return new DescendingSubMap!(K,V)(m, 3343 false, toKey, toInclusive, 3344 false, fromKey, fromInclusive); 3345 } 3346 3347 NavigableMap!(K,V) headMap(K toKey, bool inclusive) { 3348 if (!inRange(toKey, inclusive)) 3349 throw new IllegalArgumentException("toKey out of range"); 3350 return new DescendingSubMap!(K,V)(m, 3351 false, toKey, inclusive, 3352 toEnd, hi, hiInclusive); 3353 } 3354 3355 NavigableMap!(K,V) tailMap(K fromKey, bool inclusive) { 3356 if (!inRange(fromKey, inclusive)) 3357 throw new IllegalArgumentException("fromKey out of range"); 3358 return new DescendingSubMap!(K,V)(m, 3359 fromStart, lo, loInclusive, 3360 false, fromKey, inclusive); 3361 } 3362 3363 // NavigableMap!(K,V) descendingMap() { 3364 // NavigableMap!(K,V) mv = descendingMapView; 3365 // return (mv !is null) ? mv : 3366 // (descendingMapView = 3367 // new AscendingSubMap!(K,V)(m, 3368 // fromStart, lo, loInclusive, 3369 // toEnd, hi, hiInclusive)); 3370 // } 3371 3372 // override Iterator!K keyIterator() { 3373 // return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 3374 // } 3375 3376 // override Spliterator!K keySpliterator() { 3377 // return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 3378 // } 3379 3380 // override Iterator!K descendingKeyIterator() { 3381 // return new SubMapKeyIterator(absLowest(), absHighFence()); 3382 // } 3383 3384 // final class DescendingEntrySetView : EntrySetView { 3385 // Iterator!(MapEntry!(K,V)) iterator() { 3386 // return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); 3387 // } 3388 // } 3389 3390 // Set!(MapEntry!(K,V)) entrySet() { 3391 // EntrySetView es = entrySetView; 3392 // return (es !is null) ? es : (entrySetView = new DescendingEntrySetView()); 3393 // } 3394 3395 override TreeMapEntry!(K,V) subLowest() { return absHighest(); } 3396 override TreeMapEntry!(K,V) subHighest() { return absLowest(); } 3397 override TreeMapEntry!(K,V) subCeiling(K key) { return absFloor(key); } 3398 override TreeMapEntry!(K,V) subHigher(K key) { return absLower(key); } 3399 override TreeMapEntry!(K,V) subFloor(K key) { return absCeiling(key); } 3400 override TreeMapEntry!(K,V) subLower(K key) { return absHigher(key); } 3401 } 3402 3403 3404 // Little utilities 3405 3406 /** 3407 * Returns the successor of the specified Entry, or null if no such. 3408 */ 3409 private TreeMapEntry!(K,V) successor(K,V)(TreeMapEntry!(K,V) t) { 3410 if (t is null) 3411 return null; 3412 else if (t.right !is null) { 3413 TreeMapEntry!(K,V) p = t.right; 3414 while (p.left !is null) 3415 p = p.left; 3416 return p; 3417 } else { 3418 TreeMapEntry!(K,V) p = t.parent; 3419 TreeMapEntry!(K,V) ch = t; 3420 while (p !is null && ch == p.right) { 3421 ch = p; 3422 p = p.parent; 3423 } 3424 return p; 3425 } 3426 } 3427 3428 /** 3429 * Returns the predecessor of the specified Entry, or null if no such. 3430 */ 3431 private TreeMapEntry!(K,V) predecessor(K,V)(TreeMapEntry!(K,V) t) { 3432 if (t is null) 3433 return null; 3434 else if (t.left !is null) { 3435 TreeMapEntry!(K,V) p = t.left; 3436 while (p.right !is null) 3437 p = p.right; 3438 return p; 3439 } else { 3440 TreeMapEntry!(K,V) p = t.parent; 3441 TreeMapEntry!(K,V) ch = t; 3442 while (p !is null && ch == p.left) { 3443 ch = p; 3444 p = p.parent; 3445 } 3446 return p; 3447 } 3448 } 3449 3450 3451 /** 3452 * Test two values for equality. Differs from o1.equals(o2) only in 3453 * that it copes with {@code null} o1 properly. 3454 */ 3455 private bool valEquals(V)(V o1, V o2) { 3456 // return (o1 is null ? o2 is null : o1.equals(o2)); 3457 return o1 == o2; 3458 } 3459 3460 /** 3461 * Return SimpleImmutableEntry for entry, or null if null 3462 */ 3463 private MapEntry!(K,V) exportEntry(K,V)(TreeMapEntry!(K,V) e) { 3464 return (e is null) ? null : 3465 new SimpleImmutableEntry!(K,V)(e); 3466 } 3467 3468 /** 3469 * Return key for entry, or null if null 3470 */ 3471 private K keyOrNull(K,V)(TreeMapEntry!(K,V) e) { 3472 return (e is null) ? K.init : e.key; 3473 } 3474 3475 /** 3476 * Returns the key corresponding to the specified Entry. 3477 * @throws NoSuchElementException if the Entry is null 3478 */ 3479 private K key(K, V)(TreeMapEntry!(K,V) e) { 3480 if (e is null) 3481 throw new NoSuchElementException(); 3482 return e.key; 3483 }