| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |