HashSupport.java 6.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/*******************************************************************************
 * 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);
        }
    }
}