blob: 34a203c39832f006b07b855964134b0199120928 [file] [log] [blame]
/*******************************************************************************
* Copyright 2014 Trevor Robinson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.scurrilous.circe;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Iterator;
/**
* Flags indicating the support available for some set of hash algorithm.
*/
public enum HashSupport {
/**
* Indicates that the hash algorithm is available in hardware-accelerated
* native code as an {@link IncrementalIntHash} or
* {@link IncrementalLongHash}, depending on which of {@link #INT_SIZED} or
* {@link #LONG_SIZED} is set.
*/
HARDWARE_INCREMENTAL(10),
/**
* Indicates that the hash algorithm is available in hardware-accelerated
* native code.
*/
HARDWARE(20),
/**
* Indicates that the hash algorithm is available in native code as a
* {@link IncrementalIntHash} or {@link IncrementalLongHash}, depending on
* which of {@link #INT_SIZED} or {@link #LONG_SIZED} is set.
*/
NATIVE_INCREMENTAL(30),
/**
* Indicates that the hash algorithm is available in native code.
*/
NATIVE(40),
/**
* Indicates that the incremental hash algorithm supports unsafe memory
* access via {@link IncrementalIntHash#resume(int, long, long)} or
* {@link IncrementalLongHash#resume(long, long, long)}, depending on which
* of {@link #INT_SIZED} or {@link #LONG_SIZED} is set.
*/
UNSAFE_INCREMENTAL(50),
/**
* Indicates that the stateful hash algorithm unsafe memory access via
* {@link StatefulHash#update(long, long)}. If {@link #INT_SIZED} is also
* set, the function returned by {@link StatefulIntHash#asStateless()} also
* supports {@link StatelessIntHash#calculate(long, long)}. Similarly, if
* {@link #LONG_SIZED} is also set, the function returned by
* {@link StatefulLongHash#asStateless()} also supports
* {@link StatelessLongHash#calculate(long, long)}.
*/
UNSAFE(60),
/**
* Indicates that the hash algorithm is available as a
* {@link IncrementalIntHash} or {@link IncrementalLongHash}, depending on
* which of {@link #INT_SIZED} or {@link #LONG_SIZED} is set.
*/
STATELESS_INCREMENTAL(70),
/**
* Indicates that the hash algorithm is available as an incremental stateful
* hash function, for which {@link StatefulHash#supportsIncremental()}
* returns {@code true}. This flag is implied by
* {@link #STATELESS_INCREMENTAL}.
*/
INCREMENTAL(80),
/**
* Indicates that the hash algorithm is available as a
* {@link StatefulIntHash} and {@link StatelessIntHash}.
*/
INT_SIZED(90),
/**
* Indicates that the hash algorithm is available as a
* {@link StatefulLongHash} and {@link StatelessLongHash}.
*/
LONG_SIZED(90),
/**
* Indicates that the hash algorithm is available as a {@link StatefulHash}.
* If this flag is not set, the algorithm is not supported at all.
*/
STATEFUL(100);
/**
* The minimum priority value, indicating the highest priority. All flags
* have a priority value greater than this.
*/
public static final int MIN_PRIORITY = 0;
/**
* The maximum priority value, indicating the lowest priority. All flags
* have a priority value less than this.
*/
public static final int MAX_PRIORITY = 110;
private final int priority;
private HashSupport(int priority) {
this.priority = priority;
}
/**
* Returns the relative priority of a hash algorithm support flag, which is
* an indicator of its performance and flexibility. Lower values indicate
* higher priority.
*
* @return the priority of this flag (currently between 10 and 90)
*/
public int getPriority() {
return priority;
}
/**
* Returns the {@linkplain #getPriority() priority} of the highest-priority
* hash algorithm support flag in the given set of flags. If the set is
* empty, {@link #MAX_PRIORITY} is returned.
*
* @param set a set of hash algorithm support flags
* @return the highest priority (lowest value) in the set, or
* {@link #MAX_PRIORITY} if empty
*/
public static int getMaxPriority(EnumSet<HashSupport> set) {
if (set.isEmpty())
return MAX_PRIORITY;
return set.iterator().next().getPriority();
}
/**
* Compares the given sets of hash algorithm support flags for priority
* order. The set with the highest priority flag without a flag of matching
* priority in the other set has higher priority.
*
* @param set1 the first set to be compared
* @param set2 the second set to be compared
* @return a negative integer, zero, or a positive integer if the first set
* has priority higher than, equal to, or lower than the second
*/
public static int compare(EnumSet<HashSupport> set1, EnumSet<HashSupport> set2) {
// assumes iterators return flags in priority order
final Iterator<HashSupport> i1 = set1.iterator();
final Iterator<HashSupport> i2 = set2.iterator();
int floor = MIN_PRIORITY;
while (i1.hasNext() || i2.hasNext()) {
int p1, p2;
do {
p1 = i1.hasNext() ? i1.next().getPriority() : MAX_PRIORITY;
} while (p1 == floor);
do {
p2 = i2.hasNext() ? i2.next().getPriority() : MAX_PRIORITY;
} while (p2 == floor);
if (p1 < p2)
return -1;
if (p1 > p2)
return 1;
floor = p1;
}
return 0;
}
/**
* {@link Comparator} for {@link EnumSet EnumSets} for hash support flags.
*/
static final class SetComparator implements Comparator<EnumSet<HashSupport>> {
@Override
public int compare(EnumSet<HashSupport> o1, EnumSet<HashSupport> o2) {
return HashSupport.compare(o1, o2);
}
}
}