Fnv.java

package com.alibaba.fastjson2.util;

import static com.alibaba.fastjson2.JSONFactory.MIXED_HASH_ALGORITHM;

// fnv1a 64
public class Fnv {
    public static final long MAGIC_HASH_CODE = 0xcbf29ce484222325L;
    public static final long MAGIC_PRIME = 0x100000001b3L;

    public static long hashCode64LCase(String name) {
        if (MIXED_HASH_ALGORITHM) {
            boolean ascii = true;
            long nameValue = 0;

            int scoreCount = 0;
            for (int i = 0; i < name.length(); ++i) {
                char ch = name.charAt(i);
                if (ch > 0xFF || (i == 0 && ch == 0)) {
                    ascii = false;
                    break;
                }

                if (ch == '-' || ch == '_') {
                    scoreCount++;
                }
            }

            if (ascii && (name.length() - scoreCount) <= 8) {
                for (int i = name.length() - 1, j = 0; i >= 0; --i) {
                    char ch = name.charAt(i);
                    if (ch == '-' || ch == '_') {
                        continue;
                    }
                    if (ch >= 'A' && ch <= 'Z') {
                        ch = (char) (ch + 32);
                    }

                    if (j == 0) {
                        nameValue = (byte) ch;
                    } else {
                        nameValue <<= 8;
                        nameValue += ch;
                    }
                    j++;
                }

                if (nameValue != 0) {
                    return nameValue;
                }
            }
        }

        long hashCode = MAGIC_HASH_CODE;
        for (int i = 0; i < name.length(); ++i) {
            char ch = name.charAt(i);

            if (ch == '-' || ch == '_') {
                continue;
            }
            if (ch >= 'A' && ch <= 'Z') {
                ch = (char) (ch + 32);
            }

            hashCode ^= ch;
            hashCode *= MAGIC_PRIME;
        }
        return hashCode;
    }

    public static long hashCode64(String name) {
        if (MIXED_HASH_ALGORITHM && name.length() <= 8) {
            boolean ascii = true;
            long nameValue = 0;

            for (int i = 0; i < name.length(); ++i) {
                char ch = name.charAt(i);
                if (ch > 0xFF || (i == 0 && ch == 0)) {
                    ascii = false;
                    break;
                }
            }

            if (ascii) {
                for (int i = name.length() - 1; i >= 0; --i) {
                    char ch = name.charAt(i);
                    if (i == name.length() - 1) {
                        nameValue = (byte) ch;
                    } else {
                        nameValue <<= 8;
                        nameValue += ch;
                    }
                }

                if (nameValue != 0) {
                    return nameValue;
                }
            }
        }

        long hashCode = MAGIC_HASH_CODE;
        for (int i = 0; i < name.length(); ++i) {
            char ch = name.charAt(i);
            hashCode ^= ch;
            hashCode *= MAGIC_PRIME;
        }
        return hashCode;
    }

    public static long hashCode64(byte... name) {
        if (MIXED_HASH_ALGORITHM && name.length > 0 && name.length <= 8 && name[0] != 0) {
            long nameValue = 0;
            switch (name.length) {
                case 1:
                    nameValue = name[0];
                    break;
                case 2:
                    nameValue
                            = ((name[1]) << 8)
                            + (name[0] & 0xFF);
                    break;
                case 3:
                    nameValue
                            = ((name[2]) << 16)
                            + ((name[1] & 0xFF) << 8)
                            + (name[0] & 0xFF);
                    break;
                case 4:
                    nameValue
                            = (name[3] << 24)
                            + ((name[2] & 0xFF) << 16)
                            + ((name[1] & 0xFF) << 8)
                            + (name[0] & 0xFF);
                    break;
                case 5:
                    nameValue
                            = (((long) name[4]) << 32)
                            + ((name[3] & 0xFFL) << 24)
                            + ((name[2] & 0xFFL) << 16)
                            + ((name[0] & 0xFFL) << 8)
                            + (name[0] & 0xFFL);
                    break;
                case 6:
                    nameValue
                            = (((long) name[5]) << 40)
                            + ((name[4] & 0xFFL) << 32)
                            + ((name[3] & 0xFFL) << 24)
                            + ((name[2] & 0xFFL) << 16)
                            + ((name[1] & 0xFFL) << 8)
                            + (name[0] & 0xFFL);
                    break;
                case 7:
                    nameValue
                            = (((long) name[6]) << 48)
                            + ((name[5] & 0xFFL) << 40)
                            + ((name[4] & 0xFFL) << 32)
                            + ((name[3] & 0xFFL) << 24)
                            + ((name[2] & 0xFFL) << 16)
                            + ((name[1] & 0xFFL) << 8)
                            + (name[0] & 0xFFL);
                    break;
                case 8:
                    nameValue
                            = (((long) name[7]) << 56)
                            + ((name[6] & 0xFFL) << 48)
                            + ((name[5] & 0xFFL) << 40)
                            + ((name[4] & 0xFFL) << 32)
                            + ((name[3] & 0xFFL) << 24)
                            + ((name[2] & 0xFFL) << 16)
                            + ((name[1] & 0xFFL) << 8)
                            + (name[0] & 0xFFL);
                    break;
                default:
                    break;
            }

            if (nameValue != 0) {
                return nameValue;
            }
        }

        long hashCode = MAGIC_HASH_CODE;
        for (int i = 0; i < name.length; ++i) {
            char ch = (char) name[i];
            hashCode ^= ch;
            hashCode *= MAGIC_PRIME;
        }
        return hashCode;
    }
}