From 71baf5a7af874151db54927b5299dbf5e3cac440 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sun, 25 Sep 2011 18:20:11 +0200 Subject: [PATCH] Small improvements to Local Index Activity. Made search faster --- .../src/gnu/trove/impl/hash/TIntLongHash.java | 341 +++++ .../gnu/trove/iterator/TIntLongIterator.java | 115 ++ .../src/gnu/trove/map/TIntLongMap.java | 303 ++++ .../gnu/trove/map/hash/TIntLongHashMap.java | 1293 +++++++++++++++++ .../trove/procedure/TIntLongProcedure.java | 42 + .../binary/BinaryMapPoiReaderAdapter.java | 73 +- OsmAnd/res/values/strings.xml | 2 + .../plus/activities/LocalIndexesActivity.java | 155 +- 8 files changed, 2254 insertions(+), 70 deletions(-) create mode 100644 DataExtractionOSM/src/gnu/trove/impl/hash/TIntLongHash.java create mode 100644 DataExtractionOSM/src/gnu/trove/iterator/TIntLongIterator.java create mode 100644 DataExtractionOSM/src/gnu/trove/map/TIntLongMap.java create mode 100644 DataExtractionOSM/src/gnu/trove/map/hash/TIntLongHashMap.java create mode 100644 DataExtractionOSM/src/gnu/trove/procedure/TIntLongProcedure.java diff --git a/DataExtractionOSM/src/gnu/trove/impl/hash/TIntLongHash.java b/DataExtractionOSM/src/gnu/trove/impl/hash/TIntLongHash.java new file mode 100644 index 0000000000..f0e01e4d44 --- /dev/null +++ b/DataExtractionOSM/src/gnu/trove/impl/hash/TIntLongHash.java @@ -0,0 +1,341 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2001, Eric D. Friedman All Rights Reserved. +// Copyright (c) 2009, Rob Eden All Rights Reserved. +// Copyright (c) 2009, Jeff Randall All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/////////////////////////////////////////////////////////////////////////////// + +package gnu.trove.impl.hash; + +import gnu.trove.procedure.*; +import gnu.trove.impl.HashFunctions; + +import java.io.ObjectOutput; +import java.io.ObjectInput; +import java.io.IOException; + + +////////////////////////////////////////////////// +// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // +////////////////////////////////////////////////// + + +/** + * An open addressed hashing implementation for int/long primitive entries. + * + * Created: Sun Nov 4 08:56:06 2001 + * + * @author Eric D. Friedman + * @author Rob Eden + * @author Jeff Randall + * @version $Id: _K__V_Hash.template,v 1.1.2.6 2009/11/07 03:36:44 robeden Exp $ + */ +abstract public class TIntLongHash extends TPrimitiveHash { + + /** the set of ints */ + public transient int[] _set; + + + /** + * key that represents null + * + * NOTE: should not be modified after the Hash is created, but is + * not final because of Externalization + * + */ + protected int no_entry_key; + + + /** + * value that represents null + * + * NOTE: should not be modified after the Hash is created, but is + * not final because of Externalization + * + */ + protected long no_entry_value; + + + /** + * Creates a new T#E#Hash instance with the default + * capacity and load factor. + */ + public TIntLongHash() { + super(); + no_entry_key = ( int ) 0; + no_entry_value = ( long ) 0; + } + + + /** + * Creates a new T#E#Hash instance whose capacity + * is the next highest prime above initialCapacity + 1 + * unless that value is already prime. + * + * @param initialCapacity an int value + */ + public TIntLongHash( int initialCapacity ) { + super( initialCapacity ); + no_entry_key = ( int ) 0; + no_entry_value = ( long ) 0; + } + + + /** + * Creates a new TIntLongHash instance with a prime + * value at or near the specified capacity and load factor. + * + * @param initialCapacity used to find a prime capacity for the table. + * @param loadFactor used to calculate the threshold over which + * rehashing takes place. + */ + public TIntLongHash( int initialCapacity, float loadFactor ) { + super(initialCapacity, loadFactor); + no_entry_key = ( int ) 0; + no_entry_value = ( long ) 0; + } + + + /** + * Creates a new TIntLongHash instance with a prime + * value at or near the specified capacity and load factor. + * + * @param initialCapacity used to find a prime capacity for the table. + * @param loadFactor used to calculate the threshold over which + * rehashing takes place. + * @param no_entry_value value that represents null + */ + public TIntLongHash( int initialCapacity, float loadFactor, + int no_entry_key, long no_entry_value ) { + super(initialCapacity, loadFactor); + this.no_entry_key = no_entry_key; + this.no_entry_value = no_entry_value; + } + + + /** + * Returns the value that is used to represent null as a key. The default + * value is generally zero, but can be changed during construction + * of the collection. + * + * @return the value that represents null + */ + public int getNoEntryKey() { + return no_entry_key; + } + + + /** + * Returns the value that is used to represent null. The default + * value is generally zero, but can be changed during construction + * of the collection. + * + * @return the value that represents null + */ + public long getNoEntryValue() { + return no_entry_value; + } + + + /** + * initializes the hashtable to a prime capacity which is at least + * initialCapacity + 1. + * + * @param initialCapacity an int value + * @return the actual capacity chosen + */ + protected int setUp( int initialCapacity ) { + int capacity; + + capacity = super.setUp( initialCapacity ); + _set = new int[capacity]; + return capacity; + } + + + /** + * Searches the set for val + * + * @param val an int value + * @return a boolean value + */ + public boolean contains( int val ) { + return index(val) >= 0; + } + + + /** + * Executes procedure for each key in the map. + * + * @param procedure a TIntProcedure value + * @return false if the loop over the set terminated because + * the procedure returned false for some value. + */ + public boolean forEach( TIntProcedure procedure ) { + byte[] states = _states; + int[] set = _set; + for ( int i = set.length; i-- > 0; ) { + if ( states[i] == FULL && ! procedure.execute( set[i] ) ) { + return false; + } + } + return true; + } + + + /** + * Releases the element currently stored at index. + * + * @param index an int value + */ + protected void removeAt( int index ) { + _set[index] = no_entry_key; + super.removeAt( index ); + } + + + /** + * Locates the index of val. + * + * @param key an int value + * @return the index of val or -1 if it isn't in the set. + */ + protected int index( int key ) { + int hash, probe, index, length; + + final byte[] states = _states; + final int[] set = _set; + length = states.length; + hash = HashFunctions.hash( key ) & 0x7fffffff; + index = hash % length; + + if ( states[index] != FREE && + ( states[index] == REMOVED || set[index] != key ) ) { + // see Knuth, p. 529 + probe = 1 + ( hash % ( length - 2 ) ); + + do { + index -= probe; + if ( index < 0 ) { + index += length; + } + } while ( states[index] != FREE && + ( states[index] == REMOVED || set[index] != key ) ); + } + + return states[index] == FREE ? -1 : index; + } + + + /** + * Locates the index at which val can be inserted. if + * there is already a value equal()ing val in the set, + * returns that value as a negative integer. + * + * @param key an int value + * @return an int value + */ + protected int insertionIndex( int key ) { + int hash, probe, index, length; + + final byte[] states = _states; + final int[] set = _set; + length = states.length; + hash = HashFunctions.hash( key ) & 0x7fffffff; + index = hash % length; + + if ( states[index] == FREE ) { + return index; // empty, all done + } else if ( states[index] == FULL && set[index] == key ) { + return -index -1; // already stored + } else { // already FULL or REMOVED, must probe + // compute the double hash + probe = 1 + ( hash % ( length - 2 ) ); + + // if the slot we landed on is FULL (but not removed), probe + // until we find an empty slot, a REMOVED slot, or an element + // equal to the one we are trying to insert. + // finding an empty slot means that the value is not present + // and that we should use that slot as the insertion point; + // finding a REMOVED slot means that we need to keep searching, + // however we want to remember the offset of that REMOVED slot + // so we can reuse it in case a "new" insertion (i.e. not an update) + // is possible. + // finding a matching value means that we've found that our desired + // key is already in the table + + if ( states[index] != REMOVED ) { + // starting at the natural offset, probe until we find an + // offset that isn't full. + do { + index -= probe; + if (index < 0) { + index += length; + } + } while ( states[index] == FULL && set[index] != key ); + } + + // if the index we found was removed: continue probing until we + // locate a free location or an element which equal()s the + // one we have. + if ( states[index] == REMOVED) { + int firstRemoved = index; + while ( states[index] != FREE && + ( states[index] == REMOVED || set[index] != key ) ) { + index -= probe; + if (index < 0) { + index += length; + } + } + return states[index] == FULL ? -index -1 : firstRemoved; + } + // if it's full, the key is already stored + return states[index] == FULL ? -index -1 : index; + } + } + + + /** {@inheritDoc} */ + public void writeExternal( ObjectOutput out ) throws IOException { + // VERSION + out.writeByte( 0 ); + + // SUPER + super.writeExternal( out ); + + // NO_ENTRY_KEY + out.writeInt( no_entry_key ); + + // NO_ENTRY_VALUE + out.writeLong( no_entry_value ); + } + + + /** {@inheritDoc} */ + public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException { + // VERSION + in.readByte(); + + // SUPER + super.readExternal( in ); + + // NO_ENTRY_KEY + no_entry_key = in.readInt(); + + // NO_ENTRY_VALUE + no_entry_value = in.readLong(); + } +} // TIntLongHash diff --git a/DataExtractionOSM/src/gnu/trove/iterator/TIntLongIterator.java b/DataExtractionOSM/src/gnu/trove/iterator/TIntLongIterator.java new file mode 100644 index 0000000000..7342734de8 --- /dev/null +++ b/DataExtractionOSM/src/gnu/trove/iterator/TIntLongIterator.java @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2001, Eric D. Friedman All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/////////////////////////////////////////////////////////////////////////////// + +package gnu.trove.iterator; + +////////////////////////////////////////////////// +// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // +////////////////////////////////////////////////// + + +/** + * Iterator for maps of type int and long. + * + *

The iterator semantics for Trove's primitive maps is slightly different + * from those defined in java.util.Iterator, but still well within + * the scope of the pattern, as defined by Gamma, et al.

+ * + *

This iterator does not implicitly advance to the next entry when + * the value at the current position is retrieved. Rather, you must explicitly + * ask the iterator to advance() and then retrieve either the key(), + * the value() or both. This is done so that you have the option, but not + * the obligation, to retrieve keys and/or values as your application requires, and + * without introducing wrapper objects that would carry both. As the iteration is + * stateful, access to the key/value parts of the current map entry happens in + * constant time.

+ * + *

In practice, the iterator is akin to a "search finger" that you move from + * position to position. Read or write operations affect the current entry only and + * do not assume responsibility for moving the finger.

+ * + *

Here are some sample scenarios for this class of iterator:

+ * + *
+ * // accessing keys/values through an iterator:
+ * for ( TIntLongIterator it = map.iterator(); it.hasNext(); ) {
+ *   it.advance();
+ *   if ( satisfiesCondition( it.key() ) {
+ *     doSomethingWithValue( it.value() );
+ *   }
+ * }
+ * 
+ * + *
+ * // modifying values in-place through iteration:
+ * for ( TIntLongIterator it = map.iterator(); it.hasNext(); ) {
+ *   it.advance();
+ *   if ( satisfiesCondition( it.key() ) {
+ *     it.setValue( newValueForKey( it.key() ) );
+ *   }
+ * }
+ * 
+ * + *
+ * // deleting entries during iteration:
+ * for ( TIntLongIterator it = map.iterator(); it.hasNext(); ) {
+ *   it.advance();
+ *   if ( satisfiesCondition( it.key() ) {
+ *     it.remove();
+ *   }
+ * }
+ * 
+ * + *
+ * // faster iteration by avoiding hasNext():
+ * TIntLongIterator iterator = map.iterator();
+ * for ( int i = map.size(); i-- > 0; ) {
+ *   iterator.advance();
+ *   doSomethingWithKeyAndValue( iterator.key(), iterator.value() );
+ * }
+ * 
+ */ +public interface TIntLongIterator extends TAdvancingIterator { + /** + * Provides access to the key of the mapping at the iterator's position. + * Note that you must advance() the iterator at least once + * before invoking this method. + * + * @return the key of the entry at the iterator's current position. + */ + public int key(); + + /** + * Provides access to the value of the mapping at the iterator's position. + * Note that you must advance() the iterator at least once + * before invoking this method. + * + * @return the value of the entry at the iterator's current position. + */ + public long value(); + + /** + * Replace the value of the mapping at the iterator's position with the + * specified value. Note that you must advance() the iterator at + * least once before invoking this method. + * + * @param val the value to set in the current entry + * @return the old value of the entry. + */ + public long setValue( long val ); +} diff --git a/DataExtractionOSM/src/gnu/trove/map/TIntLongMap.java b/DataExtractionOSM/src/gnu/trove/map/TIntLongMap.java new file mode 100644 index 0000000000..a114709715 --- /dev/null +++ b/DataExtractionOSM/src/gnu/trove/map/TIntLongMap.java @@ -0,0 +1,303 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009, Rob Eden All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/////////////////////////////////////////////////////////////////////////////// + +package gnu.trove.map; + + +////////////////////////////////////////////////// +// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // +////////////////////////////////////////////////// + +import gnu.trove.function.*; +import gnu.trove.iterator.*; +import gnu.trove.procedure.*; +import gnu.trove.set.*; +import gnu.trove.TLongCollection; + +import java.util.Map; +import java.io.Serializable; + + +/** + * Interface for a primitive map of int keys and long values. + */ +public interface TIntLongMap extends Serializable { + + /** + * Returns the value that will be returned from {@link #get} or {@link #put} if no + * entry exists for a given key. The default value is generally zero, but can be + * changed during construction of the collection. + * + * @return the value that represents a null key in this collection. + */ + public int getNoEntryKey(); + + + /** + * Returns the value that will be returned from {@link #get} or {@link #put} if no + * entry exists for a given key. The default value is generally zero, but can be + * changed during construction of the collection. + * + * @return the value that represents a null value in this collection. + */ + public long getNoEntryValue(); + + + /** + * Inserts a key/value pair into the map. + * + * @param key an int value + * @param value an long value + * + * @return the previous value associated with key, or the "no entry" value + * if none was found (see {@link #getNoEntryValue}). + */ + public long put( int key, long value ); + + + /** + * Inserts a key/value pair into the map if the specified key is not already + * associated with a value. + * + * @param key an int value + * @param value an long value + * + * @return the previous value associated with key, or the "no entry" value + * if none was found (see {@link #getNoEntryValue}). + */ + public long putIfAbsent( int key, long value ); + + + /** + * Put all the entries from the given Map into this map. + * + * @param map The Map from which entries will be obtained to put into this map. + */ + public void putAll( Map map ); + + + /** + * Put all the entries from the given map into this map. + * + * @param map The map from which entries will be obtained to put into this map. + */ + public void putAll( TIntLongMap map ); + + + /** + * Retrieves the value for key + * + * @param key an int value + * + * @return the previous value associated with key, or the "no entry" value + * if none was found (see {@link #getNoEntryValue}). + */ + public long get( int key ); + + + /** + * Empties the map. + */ + public void clear(); + + + /** + * Returns true if this map contains no key-value mappings. + * + * @return true if this map contains no key-value mappings + */ + public boolean isEmpty(); + + + /** + * Deletes a key/value pair from the map. + * + * @param key an int value + * + * @return the previous value associated with key, or the "no entry" value + * if none was found (see {@link #getNoEntryValue}). + */ + public long remove( int key ); + + + /** + * Returns an int value that is the number of elements in the map. + * + * @return an int value that is the number of elements in the map. + */ + public int size(); + + + /** + * Returns the keys of the map as a TIntSet + * + * @return the keys of the map as a TIntSet + */ + public TIntSet keySet(); + + + /** + * Returns the keys of the map as an array of int values. + * + * @return the keys of the map as an array of int values. + */ + public int[] keys(); + + + /** + * Returns the keys of the map. + * + * @param array the array into which the elements of the list are to be stored, + * if it is big enough; otherwise, a new array of the same type is + * allocated for this purpose. + * @return the keys of the map as an array. + */ + public int[] keys( int[] array ); + + + /** + * Returns the values of the map as a TLongCollection + * + * @return the values of the map as a TLongCollection + */ + public TLongCollection valueCollection(); + + + /** + * Returns the values of the map as an array of #e# values. + * + * @return the values of the map as an array of #e# values. + */ + public long[] values(); + + + /** + * Returns the values of the map using an existing array. + * + * @param array the array into which the elements of the list are to be stored, + * if it is big enough; otherwise, a new array of the same type is + * allocated for this purpose. + * @return the values of the map as an array of #e# values. + */ + public long[] values( long[] array ); + + + /** + * Checks for the presence of val in the values of the map. + * + * @param val an long value + * @return a boolean value + */ + public boolean containsValue( long val ); + + + /** + * Checks for the present of key in the keys of the map. + * + * @param key an int value + * @return a boolean value + */ + public boolean containsKey( int key ); + + + /** + * @return a TIntLongIterator with access to this map's keys and values + */ + public TIntLongIterator iterator(); + + + /** + * Executes procedure for each key in the map. + * + * @param procedure a TIntProcedure value + * @return false if the loop over the keys terminated because + * the procedure returned false for some key. + */ + public boolean forEachKey( TIntProcedure procedure ); + + + /** + * Executes procedure for each value in the map. + * + * @param procedure a T#F#Procedure value + * @return false if the loop over the values terminated because + * the procedure returned false for some value. + */ + public boolean forEachValue( TLongProcedure procedure ); + + + /** + * Executes procedure for each key/value entry in the + * map. + * + * @param procedure a TOIntLongProcedure value + * @return false if the loop over the entries terminated because + * the procedure returned false for some entry. + */ + public boolean forEachEntry( TIntLongProcedure procedure ); + + + /** + * Transform the values in this map using function. + * + * @param function a TLongFunction value + */ + public void transformValues( TLongFunction function ); + + + /** + * Retains only those entries in the map for which the procedure + * returns a true value. + * + * @param procedure determines which entries to keep + * @return true if the map was modified. + */ + public boolean retainEntries( TIntLongProcedure procedure ); + + + /** + * Increments the primitive value mapped to key by 1 + * + * @param key the key of the value to increment + * @return true if a mapping was found and modified. + */ + public boolean increment( int key ); + + + /** + * Adjusts the primitive value mapped to key. + * + * @param key the key of the value to increment + * @param amount the amount to adjust the value by. + * @return true if a mapping was found and modified. + */ + public boolean adjustValue( int key, long amount ); + + + /** + * Adjusts the primitive value mapped to the key if the key is present in the map. + * Otherwise, the initial_value is put in the map. + * + * @param key the key of the value to increment + * @param adjust_amount the amount to adjust the value by + * @param put_amount the value put into the map if the key is not initial present + * + * @return the value present in the map after the adjustment or put operation + */ + public long adjustOrPutValue( int key, long adjust_amount, long put_amount ); +} diff --git a/DataExtractionOSM/src/gnu/trove/map/hash/TIntLongHashMap.java b/DataExtractionOSM/src/gnu/trove/map/hash/TIntLongHashMap.java new file mode 100644 index 0000000000..22b01c8ae2 --- /dev/null +++ b/DataExtractionOSM/src/gnu/trove/map/hash/TIntLongHashMap.java @@ -0,0 +1,1293 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2001, Eric D. Friedman All Rights Reserved. +// Copyright (c) 2009, Rob Eden All Rights Reserved. +// Copyright (c) 2009, Jeff Randall All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/////////////////////////////////////////////////////////////////////////////// + +package gnu.trove.map.hash; + + +////////////////////////////////////////////////// +// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // +////////////////////////////////////////////////// + +import gnu.trove.map.TIntLongMap; +import gnu.trove.function.TLongFunction; +import gnu.trove.procedure.*; +import gnu.trove.set.*; +import gnu.trove.iterator.*; +import gnu.trove.impl.hash.*; +import gnu.trove.impl.HashFunctions; +import gnu.trove.*; + +import java.io.*; +import java.util.*; + +/** + * An open addressed Map implementation for int keys and long values. + * + * @author Eric D. Friedman + * @author Rob Eden + * @author Jeff Randall + * @version $Id: _K__V_HashMap.template,v 1.1.2.16 2010/03/02 04:09:50 robeden Exp $ + */ +public class TIntLongHashMap extends TIntLongHash implements TIntLongMap, Externalizable { + static final long serialVersionUID = 1L; + + /** the values of the map */ + protected transient long[] _values; + + + /** + * Creates a new TIntLongHashMap instance with the default + * capacity and load factor. + */ + public TIntLongHashMap() { + super(); + } + + + /** + * Creates a new TIntLongHashMap instance with a prime + * capacity equal to or greater than initialCapacity and + * with the default load factor. + * + * @param initialCapacity an int value + */ + public TIntLongHashMap( int initialCapacity ) { + super( initialCapacity ); + } + + + /** + * Creates a new TIntLongHashMap instance with a prime + * capacity equal to or greater than initialCapacity and + * with the specified load factor. + * + * @param initialCapacity an int value + * @param loadFactor a float value + */ + public TIntLongHashMap( int initialCapacity, float loadFactor ) { + super( initialCapacity, loadFactor ); + } + + + /** + * Creates a new TIntLongHashMap instance with a prime + * capacity equal to or greater than initialCapacity and + * with the specified load factor. + * + * @param initialCapacity an int value + * @param loadFactor a float value + * @param noEntryKey a int value that represents + * null for the Key set. + * @param noEntryValue a long value that represents + * null for the Value set. + */ + public TIntLongHashMap( int initialCapacity, float loadFactor, + int noEntryKey, long noEntryValue ) { + super( initialCapacity, loadFactor, noEntryKey, noEntryValue ); + } + + + /** + * Creates a new TIntLongHashMap instance containing + * all of the entries in the map passed in. + * + * @param keys a int array containing the keys for the matching values. + * @param values a long array containing the values. + */ + public TIntLongHashMap( int[] keys, long[] values ) { + super( Math.max( keys.length, values.length ) ); + + int size = Math.min( keys.length, values.length ); + for ( int i = 0; i < size; i++ ) { + this.put( keys[i], values[i] ); + } + } + + + /** + * Creates a new TIntLongHashMap instance containing + * all of the entries in the map passed in. + * + * @param map a TIntLongMap that will be duplicated. + */ + public TIntLongHashMap( TIntLongMap map ) { + super( map.size() ); + if ( map instanceof TIntLongHashMap ) { + TIntLongHashMap hashmap = ( TIntLongHashMap ) map; + this._loadFactor = hashmap._loadFactor; + this.no_entry_key = hashmap.no_entry_key; + this.no_entry_value = hashmap.no_entry_value; + //noinspection RedundantCast + if ( this.no_entry_key != ( int ) 0 ) { + Arrays.fill( _set, this.no_entry_key ); + } + //noinspection RedundantCast + if ( this.no_entry_value != ( long ) 0 ) { + Arrays.fill( _values, this.no_entry_value ); + } + setUp( (int) Math.ceil( DEFAULT_CAPACITY / _loadFactor ) ); + } + putAll( map ); + } + + + /** + * initializes the hashtable to a prime capacity which is at least + * initialCapacity + 1. + * + * @param initialCapacity an int value + * @return the actual capacity chosen + */ + protected int setUp( int initialCapacity ) { + int capacity; + + capacity = super.setUp( initialCapacity ); + _values = new long[capacity]; + return capacity; + } + + + /** + * rehashes the map to the new capacity. + * + * @param newCapacity an int value + */ + /** {@inheritDoc} */ + protected void rehash( int newCapacity ) { + int oldCapacity = _set.length; + + int oldKeys[] = _set; + long oldVals[] = _values; + byte oldStates[] = _states; + + _set = new int[newCapacity]; + _values = new long[newCapacity]; + _states = new byte[newCapacity]; + + for ( int i = oldCapacity; i-- > 0; ) { + if( oldStates[i] == FULL ) { + int o = oldKeys[i]; + int index = insertionIndex( o ); + _set[index] = o; + _values[index] = oldVals[i]; + _states[index] = FULL; + } + } + } + + + /** {@inheritDoc} */ + public long put( int key, long value ) { + int index = insertionIndex( key ); + return doPut( key, value, index ); + } + + + /** {@inheritDoc} */ + public long putIfAbsent( int key, long value ) { + int index = insertionIndex( key ); + if (index < 0) + return _values[-index - 1]; + return doPut( key, value, index ); + } + + + private long doPut( int key, long value, int index ) { + byte previousState; + long previous = no_entry_value; + boolean isNewMapping = true; + if ( index < 0 ) { + index = -index -1; + previous = _values[index]; + isNewMapping = false; + } + previousState = _states[index]; + _set[index] = key; + _states[index] = FULL; + _values[index] = value; + if (isNewMapping) { + postInsertHook( previousState == FREE ); + } + + return previous; + } + + + /** {@inheritDoc} */ + public void putAll( Map map ) { + ensureCapacity( map.size() ); + // could optimize this for cases when map instanceof THashMap + for ( Map.Entry entry : map.entrySet() ) { + this.put( entry.getKey().intValue(), entry.getValue().longValue() ); + } + } + + + /** {@inheritDoc} */ + public void putAll( TIntLongMap map ) { + ensureCapacity( map.size() ); + TIntLongIterator iter = map.iterator(); + while ( iter.hasNext() ) { + iter.advance(); + this.put( iter.key(), iter.value() ); + } + } + + + /** {@inheritDoc} */ + public long get( int key ) { + int index = index( key ); + return index < 0 ? no_entry_value : _values[index]; + } + + + /** {@inheritDoc} */ + public void clear() { + super.clear(); + Arrays.fill( _set, 0, _set.length, no_entry_key ); + Arrays.fill( _values, 0, _values.length, no_entry_value ); + Arrays.fill( _states, 0, _states.length, FREE ); + } + + + /** {@inheritDoc} */ + public boolean isEmpty() { + return 0 == _size; + } + + + /** {@inheritDoc} */ + public long remove( int key ) { + long prev = no_entry_value; + int index = index( key ); + if ( index >= 0 ) { + prev = _values[index]; + removeAt( index ); // clear key,state; adjust size + } + return prev; + } + + + /** {@inheritDoc} */ + protected void removeAt( int index ) { + _values[index] = no_entry_value; + super.removeAt( index ); // clear key, state; adjust size + } + + + /** {@inheritDoc} */ + public TIntSet keySet() { + return new TKeyView(); + } + + + /** {@inheritDoc} */ + public int[] keys() { + int[] keys = new int[size()]; + int[] k = _set; + byte[] states = _states; + + for ( int i = k.length, j = 0; i-- > 0; ) { + if ( states[i] == FULL ) { + keys[j++] = k[i]; + } + } + return keys; + } + + + /** {@inheritDoc} */ + public int[] keys( int[] array ) { + int size = size(); + if ( array.length < size ) { + array = new int[size]; + } + + int[] keys = _set; + byte[] states = _states; + + for ( int i = keys.length, j = 0; i-- > 0; ) { + if ( states[i] == FULL ) { + array[j++] = keys[i]; + } + } + return array; + } + + + /** {@inheritDoc} */ + public TLongCollection valueCollection() { + return new TValueView(); + } + + + /** {@inheritDoc} */ + public long[] values() { + long[] vals = new long[size()]; + long[] v = _values; + byte[] states = _states; + + for ( int i = v.length, j = 0; i-- > 0; ) { + if ( states[i] == FULL ) { + vals[j++] = v[i]; + } + } + return vals; + } + + + /** {@inheritDoc} */ + public long[] values( long[] array ) { + int size = size(); + if ( array.length < size ) { + array = new long[size]; + } + + long[] v = _values; + byte[] states = _states; + + for ( int i = v.length, j = 0; i-- > 0; ) { + if ( states[i] == FULL ) { + array[j++] = v[i]; + } + } + return array; + } + + + /** {@inheritDoc} */ + public boolean containsValue( long val ) { + byte[] states = _states; + long[] vals = _values; + + for ( int i = vals.length; i-- > 0; ) { + if ( states[i] == FULL && val == vals[i] ) { + return true; + } + } + return false; + } + + + /** {@inheritDoc} */ + public boolean containsKey( int key ) { + return contains( key ); + } + + + /** {@inheritDoc} */ + public TIntLongIterator iterator() { + return new TIntLongHashIterator( this ); + } + + + /** {@inheritDoc} */ + public boolean forEachKey( TIntProcedure procedure ) { + return forEach( procedure ); + } + + + /** {@inheritDoc} */ + public boolean forEachValue( TLongProcedure procedure ) { + byte[] states = _states; + long[] values = _values; + for ( int i = values.length; i-- > 0; ) { + if ( states[i] == FULL && ! procedure.execute( values[i] ) ) { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean forEachEntry( TIntLongProcedure procedure ) { + byte[] states = _states; + int[] keys = _set; + long[] values = _values; + for ( int i = keys.length; i-- > 0; ) { + if ( states[i] == FULL && ! procedure.execute( keys[i], values[i] ) ) { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public void transformValues( TLongFunction function ) { + byte[] states = _states; + long[] values = _values; + for ( int i = values.length; i-- > 0; ) { + if ( states[i] == FULL ) { + values[i] = function.execute( values[i] ); + } + } + } + + + /** {@inheritDoc} */ + public boolean retainEntries( TIntLongProcedure procedure ) { + boolean modified = false; + byte[] states = _states; + int[] keys = _set; + long[] values = _values; + + + // Temporarily disable compaction. This is a fix for bug #1738760 + tempDisableAutoCompaction(); + try { + for ( int i = keys.length; i-- > 0; ) { + if ( states[i] == FULL && ! procedure.execute( keys[i], values[i] ) ) { + removeAt( i ); + modified = true; + } + } + } + finally { + reenableAutoCompaction( true ); + } + + return modified; + } + + + /** {@inheritDoc} */ + public boolean increment( int key ) { + return adjustValue( key, ( long ) 1 ); + } + + + /** {@inheritDoc} */ + public boolean adjustValue( int key, long amount ) { + int index = index( key ); + if (index < 0) { + return false; + } else { + _values[index] += amount; + return true; + } + } + + + /** {@inheritDoc} */ + public long adjustOrPutValue( int key, long adjust_amount, long put_amount ) { + int index = insertionIndex( key ); + final boolean isNewMapping; + final long newValue; + if ( index < 0 ) { + index = -index -1; + newValue = ( _values[index] += adjust_amount ); + isNewMapping = false; + } else { + newValue = ( _values[index] = put_amount ); + isNewMapping = true; + } + + byte previousState = _states[index]; + _set[index] = key; + _states[index] = FULL; + + if ( isNewMapping ) { + postInsertHook(previousState == FREE); + } + + return newValue; + } + + + /** a view onto the keys of the map. */ + protected class TKeyView implements TIntSet { + + /** {@inheritDoc} */ + public TIntIterator iterator() { + return new TIntLongKeyHashIterator( TIntLongHashMap.this ); + } + + + /** {@inheritDoc} */ + public int getNoEntryValue() { + return no_entry_key; + } + + + /** {@inheritDoc} */ + public int size() { + return _size; + } + + + /** {@inheritDoc} */ + public boolean isEmpty() { + return 0 == _size; + } + + + /** {@inheritDoc} */ + public boolean contains( int entry ) { + return TIntLongHashMap.this.contains( entry ); + } + + + /** {@inheritDoc} */ + public int[] toArray() { + return TIntLongHashMap.this.keys(); + } + + + /** {@inheritDoc} */ + public int[] toArray( int[] dest ) { + return TIntLongHashMap.this.keys( dest ); + } + + + /** + * Unsupported when operating upon a Key Set view of a TIntLongMap + *

+ * {@inheritDoc} + */ + public boolean add( int entry ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + public boolean remove( int entry ) { + return no_entry_value != TIntLongHashMap.this.remove( entry ); + } + + + /** {@inheritDoc} */ + public boolean containsAll( Collection collection ) { + for ( Object element : collection ) { + if ( element instanceof Integer ) { + int ele = ( ( Integer ) element ).intValue(); + if ( ! TIntLongHashMap.this.containsKey( ele ) ) { + return false; + } + } else { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean containsAll( TIntCollection collection ) { + TIntIterator iter = collection.iterator(); + while ( iter.hasNext() ) { + if ( ! TIntLongHashMap.this.containsKey( iter.next() ) ) { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean containsAll( int[] array ) { + for ( int element : array ) { + if ( ! TIntLongHashMap.this.contains( element ) ) { + return false; + } + } + return true; + } + + + /** + * Unsupported when operating upon a Key Set view of a TIntLongMap + *

+ * {@inheritDoc} + */ + public boolean addAll( Collection collection ) { + throw new UnsupportedOperationException(); + } + + + /** + * Unsupported when operating upon a Key Set view of a TIntLongMap + *

+ * {@inheritDoc} + */ + public boolean addAll( TIntCollection collection ) { + throw new UnsupportedOperationException(); + } + + + /** + * Unsupported when operating upon a Key Set view of a TIntLongMap + *

+ * {@inheritDoc} + */ + public boolean addAll( int[] array ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + @SuppressWarnings({"SuspiciousMethodCalls"}) + public boolean retainAll( Collection collection ) { + boolean modified = false; + TIntIterator iter = iterator(); + while ( iter.hasNext() ) { + if ( ! collection.contains( Integer.valueOf ( iter.next() ) ) ) { + iter.remove(); + modified = true; + } + } + return modified; + } + + + /** {@inheritDoc} */ + public boolean retainAll( TIntCollection collection ) { + if ( this == collection ) { + return false; + } + boolean modified = false; + TIntIterator iter = iterator(); + while ( iter.hasNext() ) { + if ( ! collection.contains( iter.next() ) ) { + iter.remove(); + modified = true; + } + } + return modified; + } + + + /** {@inheritDoc} */ + public boolean retainAll( int[] array ) { + boolean changed = false; + Arrays.sort( array ); + int[] set = _set; + byte[] states = _states; + + for ( int i = set.length; i-- > 0; ) { + if ( states[i] == FULL && ( Arrays.binarySearch( array, set[i] ) < 0) ) { + removeAt( i ); + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( Collection collection ) { + boolean changed = false; + for ( Object element : collection ) { + if ( element instanceof Integer ) { + int c = ( ( Integer ) element ).intValue(); + if ( remove( c ) ) { + changed = true; + } + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( TIntCollection collection ) { + if ( this == collection ) { + clear(); + return true; + } + boolean changed = false; + TIntIterator iter = collection.iterator(); + while ( iter.hasNext() ) { + int element = iter.next(); + if ( remove( element ) ) { + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( int[] array ) { + boolean changed = false; + for ( int i = array.length; i-- > 0; ) { + if ( remove( array[i] ) ) { + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public void clear() { + TIntLongHashMap.this.clear(); + } + + + /** {@inheritDoc} */ + public boolean forEach( TIntProcedure procedure ) { + return TIntLongHashMap.this.forEachKey( procedure ); + } + + + @Override + public boolean equals( Object other ) { + if (! (other instanceof TIntSet)) { + return false; + } + final TIntSet that = ( TIntSet ) other; + if ( that.size() != this.size() ) { + return false; + } + for ( int i = _states.length; i-- > 0; ) { + if ( _states[i] == FULL ) { + if ( ! that.contains( _set[i] ) ) { + return false; + } + } + } + return true; + } + + + @Override + public int hashCode() { + int hashcode = 0; + for ( int i = _states.length; i-- > 0; ) { + if ( _states[i] == FULL ) { + hashcode += HashFunctions.hash( _set[i] ); + } + } + return hashcode; + } + + + @Override + public String toString() { + final StringBuilder buf = new StringBuilder( "{" ); + forEachKey( new TIntProcedure() { + private boolean first = true; + + + public boolean execute( int key ) { + if ( first ) { + first = false; + } else { + buf.append( ", " ); + } + + buf.append( key ); + return true; + } + } ); + buf.append( "}" ); + return buf.toString(); + } + } + + + /** a view onto the values of the map. */ + protected class TValueView implements TLongCollection { + + /** {@inheritDoc} */ + public TLongIterator iterator() { + return new TIntLongValueHashIterator( TIntLongHashMap.this ); + } + + + /** {@inheritDoc} */ + public long getNoEntryValue() { + return no_entry_value; + } + + + /** {@inheritDoc} */ + public int size() { + return _size; + } + + + /** {@inheritDoc} */ + public boolean isEmpty() { + return 0 == _size; + } + + + /** {@inheritDoc} */ + public boolean contains( long entry ) { + return TIntLongHashMap.this.containsValue( entry ); + } + + + /** {@inheritDoc} */ + public long[] toArray() { + return TIntLongHashMap.this.values(); + } + + + /** {@inheritDoc} */ + public long[] toArray( long[] dest ) { + return TIntLongHashMap.this.values( dest ); + } + + + + public boolean add( long entry ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + public boolean remove( long entry ) { + long[] values = _values; + int[] set = _set; + + for ( int i = values.length; i-- > 0; ) { + if ( ( set[i] != FREE && set[i] != REMOVED ) && entry == values[i] ) { + removeAt( i ); + return true; + } + } + return false; + } + + + /** {@inheritDoc} */ + public boolean containsAll( Collection collection ) { + for ( Object element : collection ) { + if ( element instanceof Long ) { + long ele = ( ( Long ) element ).longValue(); + if ( ! TIntLongHashMap.this.containsValue( ele ) ) { + return false; + } + } else { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean containsAll( TLongCollection collection ) { + TLongIterator iter = collection.iterator(); + while ( iter.hasNext() ) { + if ( ! TIntLongHashMap.this.containsValue( iter.next() ) ) { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean containsAll( long[] array ) { + for ( long element : array ) { + if ( ! TIntLongHashMap.this.containsValue( element ) ) { + return false; + } + } + return true; + } + + + /** {@inheritDoc} */ + public boolean addAll( Collection collection ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + public boolean addAll( TLongCollection collection ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + public boolean addAll( long[] array ) { + throw new UnsupportedOperationException(); + } + + + /** {@inheritDoc} */ + @SuppressWarnings({"SuspiciousMethodCalls"}) + public boolean retainAll( Collection collection ) { + boolean modified = false; + TLongIterator iter = iterator(); + while ( iter.hasNext() ) { + if ( ! collection.contains( Long.valueOf ( iter.next() ) ) ) { + iter.remove(); + modified = true; + } + } + return modified; + } + + + /** {@inheritDoc} */ + public boolean retainAll( TLongCollection collection ) { + if ( this == collection ) { + return false; + } + boolean modified = false; + TLongIterator iter = iterator(); + while ( iter.hasNext() ) { + if ( ! collection.contains( iter.next() ) ) { + iter.remove(); + modified = true; + } + } + return modified; + } + + + /** {@inheritDoc} */ + public boolean retainAll( long[] array ) { + boolean changed = false; + Arrays.sort( array ); + long[] values = _values; + byte[] states = _states; + + for ( int i = values.length; i-- > 0; ) { + if ( states[i] == FULL && ( Arrays.binarySearch( array, values[i] ) < 0) ) { + removeAt( i ); + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( Collection collection ) { + boolean changed = false; + for ( Object element : collection ) { + if ( element instanceof Long ) { + long c = ( ( Long ) element ).longValue(); + if ( remove( c ) ) { + changed = true; + } + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( TLongCollection collection ) { + if ( this == collection ) { + clear(); + return true; + } + boolean changed = false; + TLongIterator iter = collection.iterator(); + while ( iter.hasNext() ) { + long element = iter.next(); + if ( remove( element ) ) { + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public boolean removeAll( long[] array ) { + boolean changed = false; + for ( int i = array.length; i-- > 0; ) { + if ( remove( array[i] ) ) { + changed = true; + } + } + return changed; + } + + + /** {@inheritDoc} */ + public void clear() { + TIntLongHashMap.this.clear(); + } + + + /** {@inheritDoc} */ + public boolean forEach( TLongProcedure procedure ) { + return TIntLongHashMap.this.forEachValue( procedure ); + } + + + /** {@inheritDoc} */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder( "{" ); + forEachValue( new TLongProcedure() { + private boolean first = true; + + public boolean execute( long value ) { + if ( first ) { + first = false; + } else { + buf.append( ", " ); + } + + buf.append( value ); + return true; + } + } ); + buf.append( "}" ); + return buf.toString(); + } + } + + + class TIntLongKeyHashIterator extends THashPrimitiveIterator implements TIntIterator { + + /** + * Creates an iterator over the specified map + * + * @param hash the TPrimitiveHash we will be iterating over. + */ + TIntLongKeyHashIterator( TPrimitiveHash hash ) { + super( hash ); + } + + /** {@inheritDoc} */ + public int next() { + moveToNextIndex(); + return _set[_index]; + } + + /** @{inheritDoc} */ + public void remove() { + if ( _expectedSize != _hash.size() ) { + throw new ConcurrentModificationException(); + } + + // Disable auto compaction during the remove. This is a workaround for bug 1642768. + try { + _hash.tempDisableAutoCompaction(); + TIntLongHashMap.this.removeAt( _index ); + } + finally { + _hash.reenableAutoCompaction( false ); + } + + _expectedSize--; + } + } + + + + class TIntLongValueHashIterator extends THashPrimitiveIterator implements TLongIterator { + + /** + * Creates an iterator over the specified map + * + * @param hash the TPrimitiveHash we will be iterating over. + */ + TIntLongValueHashIterator( TPrimitiveHash hash ) { + super( hash ); + } + + /** {@inheritDoc} */ + public long next() { + moveToNextIndex(); + return _values[_index]; + } + + /** @{inheritDoc} */ + public void remove() { + if ( _expectedSize != _hash.size() ) { + throw new ConcurrentModificationException(); + } + + // Disable auto compaction during the remove. This is a workaround for bug 1642768. + try { + _hash.tempDisableAutoCompaction(); + TIntLongHashMap.this.removeAt( _index ); + } + finally { + _hash.reenableAutoCompaction( false ); + } + + _expectedSize--; + } + } + + + class TIntLongHashIterator extends THashPrimitiveIterator implements TIntLongIterator { + + /** + * Creates an iterator over the specified map + * + * @param map the TIntLongHashMap we will be iterating over. + */ + TIntLongHashIterator( TIntLongHashMap map ) { + super( map ); + } + + /** {@inheritDoc} */ + public void advance() { + moveToNextIndex(); + } + + /** {@inheritDoc} */ + public int key() { + return _set[_index]; + } + + /** {@inheritDoc} */ + public long value() { + return _values[_index]; + } + + /** {@inheritDoc} */ + public long setValue( long val ) { + long old = value(); + _values[_index] = val; + return old; + } + + /** @{inheritDoc} */ + public void remove() { + if ( _expectedSize != _hash.size() ) { + throw new ConcurrentModificationException(); + } + // Disable auto compaction during the remove. This is a workaround for bug 1642768. + try { + _hash.tempDisableAutoCompaction(); + TIntLongHashMap.this.removeAt( _index ); + } + finally { + _hash.reenableAutoCompaction( false ); + } + _expectedSize--; + } + } + + + /** {@inheritDoc} */ + @Override + public boolean equals( Object other ) { + if ( ! ( other instanceof TIntLongMap ) ) { + return false; + } + TIntLongMap that = ( TIntLongMap ) other; + if ( that.size() != this.size() ) { + return false; + } + long[] values = _values; + byte[] states = _states; + long this_no_entry_value = getNoEntryValue(); + long that_no_entry_value = that.getNoEntryValue(); + for ( int i = values.length; i-- > 0; ) { + if ( states[i] == FULL ) { + int key = _set[i]; + long that_value = that.get( key ); + long this_value = values[i]; + if ( ( this_value != that_value ) && + ( this_value != this_no_entry_value ) && + ( that_value != that_no_entry_value ) ) { + return false; + } + } + } + return true; + } + + + /** {@inheritDoc} */ + @Override + public int hashCode() { + int hashcode = 0; + byte[] states = _states; + for ( int i = _values.length; i-- > 0; ) { + if ( states[i] == FULL ) { + hashcode += HashFunctions.hash( _set[i] ) ^ + HashFunctions.hash( _values[i] ); + } + } + return hashcode; + } + + + /** {@inheritDoc} */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder( "{" ); + forEachEntry( new TIntLongProcedure() { + private boolean first = true; + public boolean execute( int key, long value ) { + if ( first ) first = false; + else buf.append( ", " ); + + buf.append(key); + buf.append("="); + buf.append(value); + return true; + } + }); + buf.append( "}" ); + return buf.toString(); + } + + + /** {@inheritDoc} */ + public void writeExternal(ObjectOutput out) throws IOException { + // VERSION + out.writeByte( 0 ); + + // SUPER + super.writeExternal( out ); + + // NUMBER OF ENTRIES + out.writeInt( _size ); + + // ENTRIES + for ( int i = _states.length; i-- > 0; ) { + if ( _states[i] == FULL ) { + out.writeInt( _set[i] ); + out.writeLong( _values[i] ); + } + } + } + + + /** {@inheritDoc} */ + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + // VERSION + in.readByte(); + + // SUPER + super.readExternal( in ); + + // NUMBER OF ENTRIES + int size = in.readInt(); + setUp( size ); + + // ENTRIES + while (size-- > 0) { + int key = in.readInt(); + long val = in.readLong(); + put(key, val); + } + } +} // TIntLongHashMap diff --git a/DataExtractionOSM/src/gnu/trove/procedure/TIntLongProcedure.java b/DataExtractionOSM/src/gnu/trove/procedure/TIntLongProcedure.java new file mode 100644 index 0000000000..45b3bb043e --- /dev/null +++ b/DataExtractionOSM/src/gnu/trove/procedure/TIntLongProcedure.java @@ -0,0 +1,42 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2001, Eric D. Friedman All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/////////////////////////////////////////////////////////////////////////////// + +package gnu.trove.procedure; + +////////////////////////////////////////////////// +// THIS IS A GENERATED CLASS. DO NOT HAND EDIT! // +////////////////////////////////////////////////// + + +/** + * Interface for procedures that take two parameters of type int and long. + */ +public interface TIntLongProcedure { + + /** + * Executes this procedure. A false return value indicates that + * the application executing this procedure should not invoke this + * procedure again. + * + * @param a a int value + * @param b a long value + * @return true if additional invocations of the procedure are + * allowed. + */ + public boolean execute( int a, long b ); +} diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java index 9a8aa56c89..0846799264 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -1,13 +1,17 @@ package net.osmand.binary; -import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntLongHashMap; import gnu.trove.set.hash.TLongHashSet; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.apache.commons.logging.Log; + import net.osmand.Algoritms; +import net.osmand.LogUtil; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; import net.osmand.data.Amenity; import net.osmand.data.AmenityType; @@ -19,6 +23,7 @@ import com.google.protobuf.CodedInputStreamRAF; import com.google.protobuf.WireFormat; public class BinaryMapPoiReaderAdapter { + private static final Log LOG = LogUtil.getLog(BinaryMapPoiReaderAdapter.class); public static final int SHIFT_BITS_CATEGORY = 7; private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ; @@ -154,7 +159,8 @@ public class BinaryMapPoiReaderAdapter { protected void searchPoiIndex(int left31, int right31, int top31, int bottom31, SearchRequest req, PoiRegion region) throws IOException { int indexOffset = codedIS.getTotalBytesRead(); - TIntArrayList offsets = new TIntArrayList(); + long time = System.currentTimeMillis(); + TIntLongHashMap offsetsMap = new TIntLongHashMap(); while(true){ if(req.isInterrupted()){ return; @@ -167,21 +173,24 @@ public class BinaryMapPoiReaderAdapter { case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER : int length = readInt(); int oldLimit = codedIS.pushLimit(length); - readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsets, req, region); + readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsetsMap, req, region); codedIS.popLimit(oldLimit); break; case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER : - offsets.sort(); + int[] offsets = offsetsMap.keys(); + Arrays.sort(offsets); TLongHashSet skipTiles = null; - List temporaryList = new ArrayList(); int zoomToSkip = 31; if(req.zoom != -1){ skipTiles = new TLongHashSet(); zoomToSkip = req.zoom + ZOOM_TO_SKIP_FILTER; } + List temporaryList = new ArrayList(); + LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) + + "ms. Found " + offsets.length +" subtress"); - for (int j = 0; j < offsets.size(); j++) { - codedIS.seek(offsets.get(j) + indexOffset); + for (int j = 0; j < offsets.length; j++) { + codedIS.seek(offsets[j] + indexOffset); int len = readInt(); int oldLim = codedIS.pushLimit(len); @@ -190,15 +199,29 @@ public class BinaryMapPoiReaderAdapter { readPoiData(left31, right31, top31, bottom31, req, req.getSearchResults(), region, skipTiles, zoomToSkip); } else { - temporaryList.clear(); - readPoiData(left31, right31, top31, bottom31, req, temporaryList, region, skipTiles, zoomToSkip); - for(Amenity a : temporaryList){ - int x = (int) MapUtils.getTileNumberX(zoomToSkip, a.getLocation().getLongitude()); - int y = (int) MapUtils.getTileNumberY(zoomToSkip, a.getLocation().getLatitude()); - long val = (((long) x) << zoomToSkip) | y; - if(!skipTiles.contains(val)){ - skipTiles.add(val); - req.getSearchResults().add(a); + long box = offsetsMap.get(offsets[j]); + int z = (int) (box & 31); + boolean skipBox = false; + if (z >= zoomToSkip) { + int yt = (int) ((box >> 5) & ((1 << z) - 1)); + int xt = (int) (box >> (5 + z)); + long val = ((((long) xt) >> (z - zoomToSkip)) << zoomToSkip) | (((long) yt) >> (z - zoomToSkip)); + skipBox = skipTiles.contains(val); + } + + if(skipBox){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } else { + temporaryList.clear(); + readPoiData(left31, right31, top31, bottom31, req, temporaryList, region, skipTiles, zoomToSkip); + for (Amenity a : temporaryList) { + int x = (int) MapUtils.getTileNumberX(zoomToSkip, a.getLocation().getLongitude()); + int y = (int) MapUtils.getTileNumberY(zoomToSkip, a.getLocation().getLatitude()); + long val = (((long) x) << zoomToSkip) | y; + if (!skipTiles.contains(val)) { + skipTiles.add(val); + req.getSearchResults().add(a); + } } } } @@ -370,7 +393,7 @@ public class BinaryMapPoiReaderAdapter { } private void readBoxField(int left31, int right31, int top31, int bottom31, - int px, int py, int pzoom, TIntArrayList offsets, SearchRequest req, PoiRegion region) throws IOException { + int px, int py, int pzoom, TIntLongHashMap offsetsMap, SearchRequest req, PoiRegion region) throws IOException { req.numberOfReadSubtrees++; boolean checkBox = true; int zoom = pzoom; @@ -409,7 +432,7 @@ public class BinaryMapPoiReaderAdapter { } break; - case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: + case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: { int x = dx + (px << (zoom - pzoom)); int y = dy + (py << (zoom - pzoom)); if(checkBox){ @@ -427,13 +450,15 @@ public class BinaryMapPoiReaderAdapter { } int length = readInt(); int oldLimit = codedIS.pushLimit(length); - readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsets, req, region); + readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsetsMap, req, region); codedIS.popLimit(oldLimit); - break; - - case OsmandOdb.OsmAndPoiBox.SHIFTTODATA_FIELD_NUMBER: - offsets.add(readInt()); - break; + } break; + case OsmandOdb.OsmAndPoiBox.SHIFTTODATA_FIELD_NUMBER: { + int x = dx + (px << (zoom - pzoom)); + int y = dy + (py << (zoom - pzoom)); + long l = ((((x << zoom) | y) << 5) | zoom); + offsetsMap.put(readInt(), l); + } break; default: skipUnknownField(t); break; diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 187ff89eb2..843737e8cb 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,7 @@ + Rename + Show on map Online Nominatim Never Choose auto follow settings diff --git a/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java b/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java index 43fa2c4420..78ff08c17a 100644 --- a/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java @@ -59,6 +59,7 @@ public class LocalIndexesActivity extends ExpandableListActivity { private boolean selectionMode = false; private Set selectedItems = new LinkedHashSet(); + private OsmandSettings settings; protected static int DELETE_OPERATION = 1; protected static int BACKUP_OPERATION = 2; @@ -66,6 +67,8 @@ public class LocalIndexesActivity extends ExpandableListActivity { MessageFormat formatMb = new MessageFormat("{0, number,##.#} MB", Locale.US); MessageFormat formatGb = new MessageFormat("{0, number,#.##} GB", Locale.US); + + @SuppressWarnings("unchecked") @Override @@ -74,6 +77,7 @@ public class LocalIndexesActivity extends ExpandableListActivity { // requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.local_index); + settings = OsmandSettings.getOsmandSettings(this); descriptionLoader = new LoadLocalIndexDescriptionTask(); listAdapter = new LocalIndexesAdapter(); Object indexes = getLastNonConfigurationInstance(); @@ -100,22 +104,82 @@ public class LocalIndexesActivity extends ExpandableListActivity { int child = ExpandableListView.getPackedPositionChild(packedPos); if (child >= 0 && group >= 0) { final LocalIndexInfo point = (LocalIndexInfo) listAdapter.getChild(group, child); - if (point != null && point.getGpxFile() != null) { - WptPt loc = point.getGpxFile().findPointToShow(); - if (loc != null) { - OsmandSettings.getOsmandSettings(LocalIndexesActivity.this).setMapLocationToShow(loc.lat, - loc.lon); - } - ((OsmandApplication) getApplication()).setGpxFileToDisplay(point.getGpxFile()); - MapActivity.launchMapActivityMoveToTop(LocalIndexesActivity.this); - } + showContextMenu(point); } - } + } }); setListAdapter(listAdapter); updateDescriptionTextWithSize(); } + + private void showContextMenu(final LocalIndexInfo info) { + Builder builder = new AlertDialog.Builder(this); + final List menu = new ArrayList(); + if(info.getGpxFile() != null && info.getType() == LocalIndexType.GPX_DATA){ + menu.add(R.string.show_gpx_route); + menu.add(R.string.local_index_mi_upload_gpx); + } + if(info.getType() == LocalIndexType.MAP_DATA || info.getType() == LocalIndexType.POI_DATA){ + if(!info.isBackupedData()){ + menu.add(R.string.local_index_mi_backup); + } + } + if(info.isBackupedData()){ + menu.add(R.string.local_index_mi_restore); + } + menu.add(R.string.local_index_mi_rename); + menu.add(R.string.local_index_mi_delete); + if (!menu.isEmpty()) { + String[] values = new String[menu.size()]; + for (int i = 0; i < values.length; i++) { + values[i] = getString(menu.get(i)); + } + builder.setItems(values, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int resId = menu.get(which); + if (resId == R.string.show_gpx_route) { + if (info != null && info.getGpxFile() != null) { + WptPt loc = info.getGpxFile().findPointToShow(); + if (loc != null) { + OsmandSettings.getOsmandSettings(LocalIndexesActivity.this).setMapLocationToShow(loc.lat, loc.lon); + } + ((OsmandApplication) getApplication()).setGpxFileToDisplay(info.getGpxFile()); + MapActivity.launchMapActivityMoveToTop(LocalIndexesActivity.this); + } + } else if (resId == R.string.local_index_mi_rename) { + // TODO + } else if (resId == R.string.local_index_mi_restore) { + boolean successfull = move(new File(info.getPathToData()), getFileToRestore(info)); + if(successfull){ + info.setBackupedData(false); + reloadIndexes(); + } + listAdapter.move(new LocalIndexInfo[] {info}, true); + } else if (resId == R.string.local_index_mi_delete) { + File f = new File(info.getPathToData()); + boolean successfull = Algoritms.removeAllFiles(f); + if(successfull){ + listAdapter.delete(new LocalIndexInfo[] {info}); + reloadIndexes(); + } + } else if (resId == R.string.local_index_mi_backup) { + boolean successfull = move(new File(info.getPathToData()), getFileToBackup(info)); + if(successfull){ + info.setBackupedData(true); + reloadIndexes(); + } + listAdapter.move(new LocalIndexInfo[] {info}, false); + } else if (resId == R.string.local_index_mi_upload_gpx) { + // TODO + } + } + }); + + } + builder.show(); + } public class LoadLocalIndexTask extends AsyncTask> { @@ -165,50 +229,49 @@ public class LocalIndexesActivity extends ExpandableListActivity { } + private File getFileToRestore(LocalIndexInfo i){ + if(i.isBackupedData()){ + File parent = new File(i.getPathToData()).getParentFile(); + if(i.getType() == LocalIndexType.GPX_DATA){ + parent = settings.extendOsmandPath(ResourceManager.GPX_PATH); + } else if(i.getType() == LocalIndexType.MAP_DATA){ + parent = settings.extendOsmandPath(ResourceManager.MAPS_PATH); + } else if(i.getType() == LocalIndexType.POI_DATA){ + parent = settings.extendOsmandPath(ResourceManager.POI_PATH); + } else if(i.getType() == LocalIndexType.TILES_DATA){ + parent = settings.extendOsmandPath(ResourceManager.TILES_PATH); + } else if(i.getType() == LocalIndexType.VOICE_DATA){ + parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH); + } else if(i.getType() == LocalIndexType.TTS_VOICE_DATA){ + parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH); + } + return new File(parent, i.getFileName()); + } + return new File(i.getPathToData()); + } + + private File getFileToBackup(LocalIndexInfo i) { + if(!i.isBackupedData()){ + return new File(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), i.getFileName()); + } + return new File(i.getPathToData()); + } + + private boolean move(File from, File to){ + if(!to.getParentFile().exists()){ + to.getParentFile().mkdirs(); + } + return from.renameTo(to); + } + public class LocalIndexOperationTask extends AsyncTask { private final int operation; - private OsmandSettings settings; public LocalIndexOperationTask(int operation){ this.operation = operation; - settings = ((OsmandApplication) getApplication()).getSettings(); } - public File getFileToRestore(LocalIndexInfo i){ - if(i.isBackupedData()){ - File parent = new File(i.getPathToData()).getParentFile(); - if(i.getType() == LocalIndexType.GPX_DATA){ - parent = settings.extendOsmandPath(ResourceManager.GPX_PATH); - } else if(i.getType() == LocalIndexType.MAP_DATA){ - parent = settings.extendOsmandPath(ResourceManager.MAPS_PATH); - } else if(i.getType() == LocalIndexType.POI_DATA){ - parent = settings.extendOsmandPath(ResourceManager.POI_PATH); - } else if(i.getType() == LocalIndexType.TILES_DATA){ - parent = settings.extendOsmandPath(ResourceManager.TILES_PATH); - } else if(i.getType() == LocalIndexType.VOICE_DATA){ - parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH); - } else if(i.getType() == LocalIndexType.TTS_VOICE_DATA){ - parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH); - } - return new File(parent, i.getFileName()); - } - return new File(i.getPathToData()); - } - - private File getFileToBackup(LocalIndexInfo i) { - if(!i.isBackupedData()){ - return new File(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), i.getFileName()); - } - return new File(i.getPathToData()); - } - - private boolean move(File from, File to){ - if(!to.getParentFile().exists()){ - to.getParentFile().mkdirs(); - } - return from.renameTo(to); - } @Override protected String doInBackground(LocalIndexInfo... params) {