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

com.google.common.hash.MessageDigestHashFunction Maven / Gradle / Ivy

Go to download

Guava is a suite of core and expanded libraries that include utility classes, google's collections, io classes, and much much more. Guava has only one code dependency - javax.annotation, per the JSR-305 spec.

There is a newer version: 17.0
Show newest version
/*
 * Copyright (C) 2011 The Guava Authors
 *
 * 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.google.common.hash;

import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.primitives.Chars;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * {@link HashFunction} adapter for {@link MessageDigest}s.
 *
 * @author Kevin Bourrillion
 * @author Dimitris Andreou
 */
final class MessageDigestHashFunction extends AbstractStreamingHashFunction {
  private final String algorithmName;
  private final int bits;

  MessageDigestHashFunction(String algorithmName) {
    this.algorithmName = algorithmName;
    this.bits = getMessageDigest(algorithmName).getDigestLength() * 8;
  }

  public int bits() {
    return bits;
  }

  private static MessageDigest getMessageDigest(String algorithmName) {
    try {
      return MessageDigest.getInstance(algorithmName);
    } catch (NoSuchAlgorithmException e) {
      throw new AssertionError(e);
    }
  }

  public Hasher newHasher() {
    return new MessageDigestHasher(getMessageDigest(algorithmName));
  }

  private static class MessageDigestHasher implements Hasher {
    private final MessageDigest digest;
    private final ByteBuffer scratch; // lazy convenience
    private boolean done;

    private MessageDigestHasher(MessageDigest digest) {
      this.digest = digest;
      this.scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
    }

    public Hasher putByte(byte b) {
      checkNotDone();
      digest.update(b);
      return this;
    }

    public Hasher putBytes(byte[] bytes) {
      checkNotDone();
      digest.update(bytes);
      return this;
    }

    public Hasher putBytes(byte[] bytes, int off, int len) {
      checkNotDone();
      checkPositionIndexes(off, off + len, bytes.length);
      digest.update(bytes, off, len);
      return this;
    }

    public Hasher putShort(short s) {
      checkNotDone();
      scratch.putShort(s);
      digest.update(scratch.array(), 0, Shorts.BYTES);
      scratch.clear();
      return this;
    }

    public Hasher putInt(int i) {
      checkNotDone();
      scratch.putInt(i);
      digest.update(scratch.array(), 0, Ints.BYTES);
      scratch.clear();
      return this;
    }

    public Hasher putLong(long l) {
      checkNotDone();
      scratch.putLong(l);
      digest.update(scratch.array(), 0, Longs.BYTES);
      scratch.clear();
      return this;
    }

    public Hasher putFloat(float f) {
      checkNotDone();
      scratch.putFloat(f);
      digest.update(scratch.array(), 0, 4);
      scratch.clear();
      return this;
    }

    public Hasher putDouble(double d) {
      checkNotDone();
      scratch.putDouble(d);
      digest.update(scratch.array(), 0, 8);
      scratch.clear();
      return this;
    }

    public Hasher putBoolean(boolean b) {
      return putByte(b ? (byte) 1 : (byte) 0);
    }

    public Hasher putChar(char c) {
      checkNotDone();
      scratch.putChar(c);
      digest.update(scratch.array(), 0, Chars.BYTES);
      scratch.clear();
      return this;
    }

    public Hasher putString(CharSequence charSequence) {
      for (int i = 0; i < charSequence.length(); i++) {
        putChar(charSequence.charAt(i));
      }
      return this;
    }

    public Hasher putString(CharSequence charSequence, Charset charset) {
      ByteBuffer buf = charset.encode(CharBuffer.wrap(charSequence));
      if (buf.hasArray()) {
        return putBytes(
            buf.array(), buf.arrayOffset() + buf.position(), buf.limit() + buf.arrayOffset());
      } else {
        byte[] tmp = new byte[buf.remaining()];
        buf.get(tmp);
        return putBytes(tmp);
      }
    }

    public  Hasher putObject(T instance, Funnel funnel) {
      checkNotDone();
      funnel.funnel(instance, this);
      return this;
    }

    private void checkNotDone() {
      checkState(!done, "Cannot use Hasher after calling #hash() on it");
    }

    public HashCode hash() {
      done = true;
      return HashCodes.fromBytesNoCopy(digest.digest());
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy