diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.78.0/tests/expected/d/40000-HashMap.d')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.78.0/tests/expected/d/40000-HashMap.d | 1111 |
1 files changed, 0 insertions, 1111 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/tests/expected/d/40000-HashMap.d b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/tests/expected/d/40000-HashMap.d deleted file mode 100644 index e90087c4..00000000 --- a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/tests/expected/d/40000-HashMap.d +++ /dev/null @@ -1,1111 +0,0 @@ -/******************************************************************************* - - @file HashMap.d - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for damages - of any kind arising from the use of this software. - - Permission is hereby granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and/or - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment within documentation of - said product would be appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 3. This notice may not be removed or altered from any distribution - of the source. - - 4. Derivative works are permitted, but they must carry this notice - in full and credit the original source. - - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - Written by Doug Lea with assistance from members of JCP JSR-166 - Expert Group and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain - - @version Initial version, July 2004 - @author Doug Lea; ported/modified by Kris - -*******************************************************************************/ - -module mango.cache.HashMap; - -/****************************************************************************** - -******************************************************************************/ - -extern (C) -{ -int memcmp(char *, char *, uint); -} - - -/** - * A hash table supporting full concurrency of retrievals and - * adjustable expected concurrency for updates. This class obeys the - * same functional specification as {@link java.util.Hashtable}, and - * includes versions of methods corresponding to each method of - * <tt>Hashtable</tt>. However, even though all operations are - * thread-safe, retrieval operations do <em>not</em> entail locking, - * and there is <em>not</em> any support for locking the entire table - * in a way that prevents all access. This class is fully - * interoperable with <tt>Hashtable</tt> in programs that rely on its - * thread safety but not on its synchronization details. - * - * <p> Retrieval operations (including <tt>get</tt>) generally do not - * block, so may overlap with update operations (including - * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results - * of the most recently <em>completed</em> update operations holding - * upon their onset. For aggregate operations such as <tt>putAll</tt> - * and <tt>clear</tt>, concurrent retrievals may reflect insertion or - * removal of only some entries. Similarly, Iterators and - * Enumerations return elements reflecting the state of the hash table - * at some point at or since the creation of the iterator/enumeration. - * They do <em>not</em> throw - * {@link ConcurrentModificationException}. However, iterators are - * designed to be used by only one thread at a time. - * - * <p> The allowed concurrency among update operations is guided by - * the optional <tt>concurrencyLevel</tt> constructor argument - * (default 16), which is used as a hint for internal sizing. The - * table is internally partitioned to try to permit the indicated - * number of concurrent updates without contention. Because placement - * in hash tables is essentially random, the actual concurrency will - * vary. Ideally, you should choose a value to accommodate as many - * threads as will ever concurrently modify the table. Using a - * significantly higher value than you need can waste space and time, - * and a significantly lower value can lead to thread contention. But - * overestimates and underestimates within an order of magnitude do - * not usually have much noticeable impact. A value of one is - * appropriate when it is known that only one thread will modify and - * all others will only read. Also, resizing this or any other kind of - * hash table is a relatively slow operation, so, when possible, it is - * a good idea to provide estimates of expected table sizes in - * constructors. - * - * <p>This class and its views and iterators implement all of the - * <em>optional</em> methods of the {@link Map} and {@link Iterator} - * interfaces. - * - * <p> Like {@link java.util.Hashtable} but unlike {@link - * java.util.HashMap}, this class does NOT allow <tt>null</tt> to be - * used as a key or value. - * - * <p>This class is a member of the - * <a href="{@docRoot}/../guide/collections/index.html"> - * Java Collections Framework</a>. - * - * @since 1.5 - * @author Doug Lea - * @param <K> the type of keys maintained by this map - * @param <V> the type of mapped values - */ - -class HashMap -{ - alias void[] K; - alias Object V; - alias jhash hash; // jhash, fnv, or walter - - /* - * The basic strategy is to subdivide the table among Segments, - * each of which itself is a concurrently readable hash table. - */ - - /* ---------------- Constants -------------- */ - - /** - * The default initial number of table slots for this table. - * Used when not otherwise specified in constructor. - */ - private const uint DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly - * specified by either of the constructors with arguments. MUST - * be a power of two <= 1<<30 to ensure that entries are indexible - * using ints. - */ - private const uint MAXIMUM_CAPACITY = 1 << 30; - - /** - * The default load factor for this table. Used when not - * otherwise specified in constructor. - */ - private const float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The default number of concurrency control segments. - **/ - private const uint DEFAULT_SEGMENTS = 16; - - /** - * The maximum number of segments to allow; used to bound - * constructor arguments. - */ - private const uint MAX_SEGMENTS = 1 << 16; // slightly conservative - - - /* ---------------- Fields -------------- */ - - /** - * Mask value for indexing into segments. The upper bits of a - * key's hash code are used to choose the segment. - **/ - private final int segmentMask; - - /** - * Shift value for indexing within segments. - **/ - private final int segmentShift; - - /** - * The segments, each of which is a specialized hash table - */ - private final Segment[] segments; - - - /* ---------------- Small Utilities -------------- */ - - /** - * Returns a hash code for non-null Object x. - * Uses the same hash code spreader as most other java.util hash tables. - * @param x the object serving as a key - * @return the hash code - */ - private static final uint walter(K x) - { - uint h = typeid(char[]).getHash(&x); - - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Returns a hash code for non-null Object x. - * uses the FNV hash function - * @param x the object serving as a key - * @return the hash code - */ - private static final uint fnv(K x) - { - uint hash = 2_166_136_261; - - foreach (ubyte c; cast(ubyte[])x) - { - hash ^= c; - hash *= 16_777_619; - } - return hash; - } - - - - /** - * hash() -- hash a variable-length key into a 32-bit value - * k : the key (the unaligned variable-length array of bytes) - * len : the length of the key, counting by bytes - * level : can be any 4-byte value - * Returns a 32-bit value. Every bit of the key affects every bit of - * the return value. Every 1-bit and 2-bit delta achieves avalanche. - * About 36+6len instructions. - * - * The best hash table sizes are powers of 2. There is no need to do - * mod a prime (mod is sooo slow!). If you need less than 32 bits, - * use a bitmask. For example, if you need only 10 bits, do - * h = (h & hashmask(10)); - * In which case, the hash table should have hashsize(10) elements. - * - * If you are hashing n strings (ub1 **)k, do it like this: - * for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); - * - * By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this - * code any way you wish, private, educational, or commercial. It's free. - * - * See http://burlteburtle.net/bob/hash/evahash.html - * Use for hash table lookup, or anything where one collision in 2^32 is - * acceptable. Do NOT use for cryptographic purposes. - */ - - static final uint jhash(K x) - { - ubyte *k; - uint a, - b, - c, - len; - - len = x.length; - k = cast(ubyte *)x; - a = b = 0x9e3779b9; - - // the previous hash value - c = 0; - - // handle most of the key - while (len >= 12) - { - a += *cast(uint *)(k + 0); - b += *cast(uint *)(k + 4); - c += *cast(uint *)(k + 8); - - a -= b; a -= c; a ^= (c >> 13); - b -= c; b -= a; b ^= (a << 8); - c -= a; c -= b; c ^= (b >> 13); - a -= b; a -= c; a ^= (c >> 12); - b -= c; b -= a; b ^= (a << 16); - c -= a; c -= b; c ^= (b >> 5); - a -= b; a -= c; a ^= (c >> 3); - b -= c; b -= a; b ^= (a << 10); - c -= a; c -= b; c ^= (b >> 15); - k += 12; len -= 12; - } - - // handle the last 11 bytes - c += x.length; - switch (len) - { - case 11: c += (cast(uint)k[10] << 24); - - case 10: c += (cast(uint)k[9] << 16); - - case 9: c += (cast(uint)k[8] << 8); - - case 8: b += (cast(uint)k[7] << 24); - - case 7: b += (cast(uint)k[6] << 16); - - case 6: b += (cast(uint)k[5] << 8); - - case 5: b += k[4]; - - case 4: a += (cast(uint)k[3] << 24); - - case 3: a += (cast(uint)k[2] << 16); - - case 2: a += (cast(uint)k[1] << 8); - - case 1: a += k[0]; - - default: - } - - a -= b; a -= c; a ^= (c >> 13); - b -= c; b -= a; b ^= (a << 8); - c -= a; c -= b; c ^= (b >> 13); - a -= b; a -= c; a ^= (c >> 12); - b -= c; b -= a; b ^= (a << 16); - c -= a; c -= b; c ^= (b >> 5); - a -= b; a -= c; a ^= (c >> 3); - b -= c; b -= a; b ^= (a << 10); - c -= a; c -= b; c ^= (b >> 15); - - return c; - } - - - /** - * Returns the segment that should be used for key with given hash - * @param hash the hash code for the key - * @return the segment - */ - private final Segment segmentFor(uint hash) - { - return segments[(hash >>> segmentShift) & segmentMask]; - } - - /* ---------------- Inner Classes -------------- */ - - /** - * ConcurrentHashMap list entry. Note that this is never exported - * out as a user-visible Map.Entry. - * - * Because the value field is volatile, not final, it is legal wrt - * the Java Memory Model for an unsynchronized reader to see null - * instead of initial value when read via a data race. Although a - * reordering leading to this is not likely to ever actually - * occur, the Segment.readValueUnderLock method is used as a - * backup in case a null (pre-initialized) value is ever seen in - * an unsynchronized access method. - */ - private static class HashEntry - { - final K key; - final uint hash; - final V value; - final HashEntry next; - - this(K key, uint hash, HashEntry next, V value) - { - this.key = key; - this.hash = hash; - this.next = next; - this.value = value; - } - } - - /** - * Segments are specialized versions of hash tables. This - * subclasses from ReentrantLock opportunistically, just to - * simplify some locking and avoid separate construction. - **/ - static class Segment - { - /* - * Segments maintain a table of entry lists that are ALWAYS - * kept in a consistent state, so can be read without locking. - * Next fields of nodes are immutable (final). All list - * additions are performed at the front of each bin. This - * makes it easy to check changes, and also fast to traverse. - * When nodes would otherwise be changed, new nodes are - * created to replace them. This works well for hash tables - * since the bin lists tend to be short. (The average length - * is less than two for the default load factor threshold.) - * - * Read operations can thus proceed without locking, but rely - * on selected uses of volatiles to ensure that completed - * write operations performed by other threads are - * noticed. For most purposes, the "count" field, tracking the - * number of elements, serves as that volatile variable - * ensuring visibility. This is convenient because this field - * needs to be read in many read operations anyway: - * - * - All (unsynchronized) read operations must first read the - * "count" field, and should not look at table entries if - * it is 0. - * - * - All (synchronized) write operations should write to - * the "count" field after structurally changing any bin. - * The operations must not take any action that could even - * momentarily cause a concurrent read operation to see - * inconsistent data. This is made easier by the nature of - * the read operations in Map. For example, no operation - * can reveal that the table has grown but the threshold - * has not yet been updated, so there are no atomicity - * requirements for this with respect to reads. - * - * As a guide, all critical volatile reads and writes to the - * count field are marked in code comments. - */ - - /** - * The number of elements in this segment's region. - **/ - int count; - - /** - * The table is rehashed when its size exceeds this threshold. - * (The value of this field is always (int)(capacity * - * loadFactor).) - */ - int threshold; - - /** - * The per-segment table. Declared as a raw type, casted - * to HashEntry<K,V> on each use. - */ - HashEntry[] table; - - /** - * The load factor for the hash table. Even though this value - * is same for all segments, it is replicated to avoid needing - * links to outer object. - * @serial - */ - final float loadFactor; - - this(int initialCapacity, float lf) - { - loadFactor = lf; - setTable(new HashEntry[initialCapacity]); - } - - /** - * Set table to new HashEntry array. - * Call only while holding lock or in constructor. - **/ - private final void setTable(HashEntry[] newTable) - { - threshold = cast(int)(newTable.length * loadFactor); - volatile table = newTable; - } - - /** - * Return properly casted first entry of bin for given hash - */ - private final HashEntry getFirst(uint hash) - { - HashEntry[] tab; - - volatile tab = table; - return tab[hash & (tab.length - 1)]; - } - - /** - * Return true if the two keys match - */ - private static final bool matchKey(K a, K b) - { - if (a.length == b.length) - return cast(bool)(memcmp(cast(char *)a, cast(char *)b, a.length) == 0); - - return false; - } - - /* Specialized implementations of map methods */ - - final V get(K key, uint hash) - { - int c; - - // read-volatile - volatile c = count; - if (c) - { - HashEntry e = getFirst(hash); - - while (e) - { - if (hash == e.hash && matchKey(key, e.key)) - { - V v; - - volatile v = e.value; - if (v) - return v; - - synchronized (this) - return e.value; - } - e = e.next; - } - } - return null; - } - - - final bool containsKey(K key, uint hash) - { - int c; - - // read-volatile - volatile c = count; - if (c) - { - HashEntry e = getFirst(hash); - - while (e) - { - if (e.hash == hash && matchKey(key, e.key)) - return true; - - e = e.next; - } - } - return false; - } - - - - final synchronized V replace(K key, uint hash, V newValue) - { - HashEntry e = getFirst(hash); - - while (e && (e.hash != hash || !matchKey(key, e.key))) - e = e.next; - - V oldValue = null; - - if (e) - volatile - { - oldValue = e.value; - e.value = newValue; - } - return oldValue; - } - - - final synchronized V put(K key, uint hash, V value, bool onlyIfAbsent) - { - int c; - - volatile c = count; - if (c++ > threshold) - rehash(); - - HashEntry[] tab; - - volatile tab = table; - uint index = hash & (tab.length - 1); - HashEntry first = tab[index]; - HashEntry e = first; - - while (e && (e.hash != hash || !matchKey(key, e.key))) - e = e.next; - - V oldValue; - - if (e) - { - volatile oldValue = e.value; - if (!onlyIfAbsent) - volatile e.value = value; - } - else - { - oldValue = null; - tab[index] = new HashEntry(key, hash, first, value); - - // write-volatile - volatile count = c; - } - return oldValue; - } - - - private final void rehash() - { - HashEntry[] oldTable; - - volatile oldTable = table; - int oldCapacity = oldTable.length; - - if (oldCapacity >= MAXIMUM_CAPACITY) - return; - - /* - * Reclassify nodes in each list to new Map. Because we are - * using power-of-two expansion, the elements from each bin - * must either stay at same index, or move with a power of two - * offset. We eliminate unnecessary node creation by catching - * cases where old nodes can be reused because their next - * fields won't change. Statistically, at the default - * threshold, only about one-sixth of them need cloning when - * a table doubles. The nodes they replace will be garbage - * collectable as soon as they are no longer referenced by any - * reader thread that may be in the midst of traversing table - * right now. - */ - - HashEntry[] newTable = new HashEntry[oldCapacity << 1]; - - threshold = cast(int)(newTable.length * loadFactor); - int sizeMask = newTable.length - 1; - - for (int i = 0; i < oldCapacity; ++i) - { - // We need to guarantee that any existing reads of old Map can - // proceed. So we cannot yet null out each bin. - HashEntry e = oldTable[i]; - - if (e) - { - HashEntry next = e.next; - uint idx = e.hash & sizeMask; - - // Single node on list - if (next is null) - newTable[idx] = e; - else - { - // Reuse trailing consecutive sequence at same slot - HashEntry lastRun = e; - int lastIdx = idx; - - for (HashEntry last = next; last; last = last.next) - { - uint k = last.hash & sizeMask; - - if (k != lastIdx) - { - lastIdx = k; - lastRun = last; - } - } - newTable[lastIdx] = lastRun; - - // Clone all remaining nodes - for (HashEntry p = e; p !is lastRun; p = p.next) - { - uint k = p.hash & sizeMask; - HashEntry n = newTable[k]; - - newTable[k] = new HashEntry(p.key, p.hash, n, p.value); - } - } - } - } - volatile table = newTable; - } - - /** - * Remove; match on key only if value null, else match both. - */ - final synchronized V remove(K key, uint hash, V value) - { - int c; - HashEntry[] tab; - - volatile c = count - 1; - volatile tab = table; - - uint index = hash & (tab.length - 1); - HashEntry first = tab[index]; - HashEntry e = first; - - while (e && (e.hash != hash || !matchKey(key, e.key))) - e = e.next; - - V oldValue = null; - - if (e) - { - V v; - - volatile v = e.value; - if (value is null || value == v) - { - oldValue = v; - - // All entries following removed node can stay - // in list, but all preceding ones need to be - // cloned. - HashEntry newFirst = e.next; - - for (HashEntry p = first; p !is e; p = p.next) - newFirst = new HashEntry(p.key, p.hash, newFirst, p.value); - tab[index] = newFirst; - - // write-volatile - volatile count = c; - } - } - return oldValue; - } - - - final synchronized void clear() - { - if (count) - { - HashEntry[] tab; - - volatile tab = table; - - for (int i = 0; i < tab.length; i++) - tab[i] = null; - - // write-volatile - volatile count = 0; - } - } - } - - - - /* ---------------- Public operations -------------- */ - - /** - * Creates a new, empty map with the specified initial - * capacity and the specified load factor. - * - * @param initialCapacity the initial capacity. The implementation - * performs internal sizing to accommodate this many elements. - * @param loadFactor the load factor threshold, used to control resizing. - * @param concurrencyLevel the estimated number of concurrently - * updating threads. The implementation performs internal sizing - * to try to accommodate this many threads. - * @throws IllegalArgumentException if the initial capacity is - * negative or the load factor or concurrencyLevel are - * nonpositive. - */ - public this(uint initialCapacity, float loadFactor, uint concurrencyLevel) - { - assert(loadFactor > 0); - - if (concurrencyLevel > MAX_SEGMENTS) - concurrencyLevel = MAX_SEGMENTS; - - // Find power-of-two sizes best matching arguments - int sshift = 0; - int ssize = 1; - - while (ssize < concurrencyLevel) - { - ++sshift; - ssize <<= 1; - } - - segmentShift = 32 - sshift; - segmentMask = ssize - 1; - this.segments = new Segment[ssize]; - - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - - int c = initialCapacity / ssize; - - if (c * ssize < initialCapacity) - ++c; - - int cap = 1; - - while (cap < c) - cap <<= 1; - - for (int i = 0; i < this.segments.length; ++i) - this.segments[i] = new Segment(cap, loadFactor); - } - - /** - * Creates a new, empty map with the specified initial - * capacity, and with default load factor and concurrencyLevel. - * - * @param initialCapacity The implementation performs internal - * sizing to accommodate this many elements. - * @throws IllegalArgumentException if the initial capacity of - * elements is negative. - */ - public this(uint initialCapacity) - { - this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); - } - - /** - * Creates a new, empty map with a default initial capacity, - * load factor, and concurrencyLevel. - */ - public this() - { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); - } - - /** - * Returns the value to which the specified key is mapped in this table. - * - * @param key a key in the table. - * @return the value to which the key is mapped in this table; - * <tt>null</tt> if the key is not mapped to any value in - * this table. - * @throws NullPointerException if the key is - * <tt>null</tt>. - */ - public V get(K key) - { - uint hash = hash(key); // throws NullPointerException if key null - - return segmentFor(hash).get(key, hash); - } - - /** - * Tests if the specified object is a key in this table. - * - * @param key possible key. - * @return <tt>true</tt> if and only if the specified object - * is a key in this table, as determined by the - * <tt>equals</tt> method; <tt>false</tt> otherwise. - * @throws NullPointerException if the key is - * <tt>null</tt>. - */ - public bool containsKey(K key) - { - uint hash = hash(key); // throws NullPointerException if key null - - return segmentFor(hash).containsKey(key, hash); - } - - /** - * Maps the specified <tt>key</tt> to the specified - * <tt>value</tt> in this table. Neither the key nor the - * value can be <tt>null</tt>. - * - * <p> The value can be retrieved by calling the <tt>get</tt> method - * with a key that is equal to the original key. - * - * @param key the table key. - * @param value the value. - * @return the previous value of the specified key in this table, - * or <tt>null</tt> if it did not have one. - * @throws NullPointerException if the key or value is - * <tt>null</tt>. - */ - public V put(K key, V value) - { - assert(value); - - uint hash = hash(key); - - return segmentFor(hash).put(key, hash, value, false); - } - - /** - * If the specified key is not already associated - * with a value, associate it with the given value. - * This is equivalent to - * <pre> - * if (!map.containsKey(key)) - * return map.put(key, value); - * else - * return map.get(key); - * </pre> - * Except that the action is performed atomically. - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or <tt>null</tt> - * if there was no mapping for key. - * @throws NullPointerException if the specified key or value is - * <tt>null</tt>. - */ - public V putIfAbsent(K key, V value) - { - assert(value); - - uint hash = hash(key); - - return segmentFor(hash).put(key, hash, value, true); - } - - - /** - * Removes the key (and its corresponding value) from this - * table. This method does nothing if the key is not in the table. - * - * @param key the key that needs to be removed. - * @return the value to which the key had been mapped in this table, - * or <tt>null</tt> if the key did not have a mapping. - * @throws NullPointerException if the key is - * <tt>null</tt>. - */ - public V remove(K key) - { - uint hash = hash(key); - - return segmentFor(hash).remove(key, hash, null); - } - - /** - * Remove entry for key only if currently mapped to given value. - * Acts as - * <pre> - * if (map.get(key).equals(value)) { - * map.remove(key); - * return true; - * } else return false; - * </pre> - * except that the action is performed atomically. - * @param key key with which the specified value is associated. - * @param value value associated with the specified key. - * @return true if the value was removed - * @throws NullPointerException if the specified key is - * <tt>null</tt>. - */ - public bool remove(K key, V value) - { - uint hash = hash(key); - - return cast(bool)(segmentFor(hash).remove(key, hash, value) !is null); - } - - - /** - * Replace entry for key only if currently mapped to some value. - * Acts as - * <pre> - * if ((map.containsKey(key)) { - * return map.put(key, value); - * } else return null; - * </pre> - * except that the action is performed atomically. - * @param key key with which the specified value is associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or <tt>null</tt> - * if there was no mapping for key. - * @throws NullPointerException if the specified key or value is - * <tt>null</tt>. - */ - public V replace(K key, V value) - { - assert(value); - - uint hash = hash(key); - - return segmentFor(hash).replace(key, hash, value); - } - - - /** - * Removes all mappings from this map. - */ - public void clear() - { - for (int i = 0; i < segments.length; ++i) - segments[i].clear(); - } - - - /** - * Returns an enumeration of the keys in this table. - * - * @return an enumeration of the keys in this table. - * @see #keySet - */ - public KeyIterator keys() - { - return new KeyIterator(this); - } - - /** - * Returns an enumeration of the values in this table. - * - * @return an enumeration of the values in this table. - * @see #values - */ - public ValueIterator elements() - { - return new ValueIterator(this); - } - - /********************************************************************** - - Iterate over all keys in hashmap - - **********************************************************************/ - - int opApply(int delegate(inout char[]) dg) - { - int result = 0; - KeyIterator iterator = keys(); - - while (iterator.hasNext) - { - char[] ca = cast(char[])iterator.next; - - if ((result = dg(ca)) != 0) - break; - } - return result; - } - - /********************************************************************** - - Iterate over all keys in hashmap - - **********************************************************************/ - - int opApply(int delegate(inout char[], inout Object) dg) - { - int result = 0; - KeyIterator iterator = keys(); - - while (iterator.hasNext) - { - HashEntry he = iterator.nextElement; - char[] ca = cast(char[])he.key; - - if ((result = dg(ca, he.value)) != 0) - break; - } - return result; - } - - - /* ---------------- Iterator Support -------------- */ - - abstract static class HashIterator - { - int nextSegmentIndex; - int nextTableIndex; - HashEntry[] currentTable; - HashEntry nextEntry; - HashEntry lastReturned; - HashMap map; - - this(HashMap map) - { - this.map = map; - nextSegmentIndex = map.segments.length - 1; - nextTableIndex = -1; - advance(); - } - - final void advance() - { - if (nextEntry !is null && (nextEntry = nextEntry.next) !is null) - return; - - while (nextTableIndex >= 0) - { - if ((nextEntry = currentTable[nextTableIndex--]) !is null) - return; - } - - while (nextSegmentIndex >= 0) - { - Segment seg = map.segments[nextSegmentIndex--]; - - volatile if (seg.count) - { - currentTable = seg.table; - for (int j = currentTable.length - 1; j >= 0; --j) - { - if ((nextEntry = currentTable[j]) !is null) - { - nextTableIndex = j - 1; - return; - } - } - } - } - } - - public bool hasNext() - { - return cast(bool)(nextEntry !is null); - } - - HashEntry nextElement() - { - if (nextEntry is null) - throw new Exception("no such element in HashMap"); - - lastReturned = nextEntry; - advance(); - return lastReturned; - } - } - - static class KeyIterator : HashIterator - { - this(HashMap map) { - super(map); - } - public K next() - { - return super.nextElement().key; - } - } - - static class ValueIterator : HashIterator - { - this(HashMap map) { - super(map); - } - public V next() - { - volatile return super.nextElement().value; - } - } -} |