All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.codec.digest.XXHash32 Maven / Gradle / Ivy

Go to download

The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.

There is a newer version: 20041127.091804
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.codec.digest;

import static java.lang.Integer.rotateLeft;

import java.util.zip.Checksum;

/**
 * Implementation of the xxhash32 hash algorithm.
 *
 * 

Copied from Commons Compress 1.14 * https://git-wip-us.apache.org/repos/asf?p=commons-compress.git;a=blob;f=src/main/java/org/apache/commons/compress/compressors/lz4/XXHash32.java;h=a406ffc197449be594d46f0d2712b2d4786a1e68;hb=HEAD

*

NotThreadSafe

* @see xxHash * @since 1.11 */ public class XXHash32 implements Checksum { private static final int BUF_SIZE = 16; private static final int ROTATE_BITS = 13; private static final int PRIME1 = (int) 2654435761l; private static final int PRIME2 = (int) 2246822519l; private static final int PRIME3 = (int) 3266489917l; private static final int PRIME4 = 668265263; private static final int PRIME5 = 374761393; private final byte[] oneByte = new byte[1]; private final int[] state = new int[4]; // Note: the code used to use ByteBuffer but the manual method is 50% faster // See: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/2f56fb5c private final byte[] buffer = new byte[BUF_SIZE]; private final int seed; private int totalLen; private int pos; /** * Creates an XXHash32 instance with a seed of 0. */ public XXHash32() { this(0); } /** * Creates an XXHash32 instance. * @param seed the seed to use */ public XXHash32(final int seed) { this.seed = seed; initializeState(); } @Override public void reset() { initializeState(); totalLen = 0; pos = 0; } @Override public void update(final int b) { oneByte[0] = (byte) (b & 0xff); update(oneByte, 0, 1); } @Override public void update(final byte[] b, int off, final int len) { if (len <= 0) { return; } totalLen += len; final int end = off + len; if (pos + len < BUF_SIZE) { System.arraycopy(b, off, buffer, pos, len); pos += len; return; } if (pos > 0) { final int size = BUF_SIZE - pos; System.arraycopy(b, off, buffer, pos, size); process(buffer, 0); off += size; } final int limit = end - BUF_SIZE; while (off <= limit) { process(b, off); off += BUF_SIZE; } if (off < end) { pos = end - off; System.arraycopy(b, off, buffer, 0, pos); } } @Override public long getValue() { int hash; if (totalLen > BUF_SIZE) { hash = rotateLeft(state[0], 1) + rotateLeft(state[1], 7) + rotateLeft(state[2], 12) + rotateLeft(state[3], 18); } else { hash = state[2] + PRIME5; } hash += totalLen; int idx = 0; final int limit = pos - 4; for (; idx <= limit; idx += 4) { hash = rotateLeft(hash + getInt(buffer, idx) * PRIME3, 17) * PRIME4; } while (idx < pos) { hash = rotateLeft(hash + (buffer[idx++] & 0xff) * PRIME5, 11) * PRIME1; } hash ^= hash >>> 15; hash *= PRIME2; hash ^= hash >>> 13; hash *= PRIME3; hash ^= hash >>> 16; return hash & 0xffffffffl; } private static int getInt(final byte[] buffer, final int idx) { return (int) (fromLittleEndian(buffer, idx, 4) & 0xffffffffl); } private void initializeState() { state[0] = seed + PRIME1 + PRIME2; state[1] = seed + PRIME2; state[2] = seed; state[3] = seed - PRIME1; } private void process(final byte[] b, final int offset) { // local shadows for performance int s0 = state[0]; int s1 = state[1]; int s2 = state[2]; int s3 = state[3]; s0 = rotateLeft(s0 + getInt(b, offset) * PRIME2, ROTATE_BITS) * PRIME1; s1 = rotateLeft(s1 + getInt(b, offset + 4) * PRIME2, ROTATE_BITS) * PRIME1; s2 = rotateLeft(s2 + getInt(b, offset + 8) * PRIME2, ROTATE_BITS) * PRIME1; s3 = rotateLeft(s3 + getInt(b, offset + 12) * PRIME2, ROTATE_BITS) * PRIME1; state[0] = s0; state[1] = s1; state[2] = s2; state[3] = s3; pos = 0; } /** * Reads the given byte array as a little endian long. * @param bytes the byte array to convert * @param off the offset into the array that starts the value * @param length the number of bytes representing the value * @return the number read * @throws IllegalArgumentException if len is bigger than eight */ private static long fromLittleEndian(final byte[] bytes, final int off, final int length) { if (length > 8) { throw new IllegalArgumentException("can't read more than eight bytes into a long value"); } long l = 0; for (int i = 0; i < length; i++) { l |= (bytes[off + i] & 0xffl) << (8 * i); } return l; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy