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 component contains encoders and decoders for various formats such as Base16, Base32, Base64, digest, and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities. This is a port for GWT, which enables program, to use Apache Commons Codec also in the frontend compiled by the gwt compiler to java-script.

There is a newer version: 1.17.1-0
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 com.google.gwt.core.shared.GwtIncompatible;

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 */ @GwtIncompatible("incompatible class") 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; /** Set to true when the state array has been updated since the last reset. */ private boolean stateUpdated; /** * 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; stateUpdated = false; } @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; // Check if the unprocessed bytes and new bytes can fill a block of 16. // Make this overflow safe in the event that len is Integer.MAX_VALUE. // Equivalent to: (pos + len < BUF_SIZE) if (pos + len - BUF_SIZE < 0) { System.arraycopy(b, off, buffer, pos, len); pos += len; return; } // Process left-over bytes with new bytes 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; } // Handle left-over bytes if (off < end) { pos = end - off; System.arraycopy(b, off, buffer, 0, pos); } else { pos = 0; } } @Override public long getValue() { int hash; if (stateUpdated) { // Hash with the state hash = rotateLeft(state[0], 1) + rotateLeft(state[1], 7) + rotateLeft(state[2], 12) + rotateLeft(state[3], 18); } else { // Hash using the original seed from position 2 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; } /** * Gets the little-endian int from 4 bytes starting at the specified index. * * @param buffer The data * @param idx The index * @return The little-endian int */ private static int getInt(final byte[] buffer, final int idx) { return ((buffer[idx ] & 0xff) ) | ((buffer[idx + 1] & 0xff) << 8) | ((buffer[idx + 2] & 0xff) << 16) | ((buffer[idx + 3] & 0xff) << 24); } 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; stateUpdated = true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy