package net.i2p.data;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.IOException;
import java.io.InputStream;
/**
* Defines the hash as defined by the I2P data structure spec.
* A hash is the SHA-256 of some data, taking up 32 bytes.
*
* @author jrandom
*/
public class Hash extends SimpleDataStructure {
private volatile String _base64ed;
private int _cachedHashCode;
public final static int HASH_LENGTH = 32;
public final static Hash FAKE_HASH = new Hash(new byte[HASH_LENGTH]);
private static final int CACHE_SIZE = 2048;
private static final SDSCache<Hash> _cache = new SDSCache<Hash>(Hash.class, HASH_LENGTH, CACHE_SIZE);
/**
* Pull from cache or return new
*
* WARNING - If the SDS is found in the cache, the passed-in
* byte array will be returned to the SimpleByteCache for reuse.
* Do NOT save a reference to the passed-in data, or use or modify it,
* after this call.
*
* Ignore this warning and you WILL corrupt the cache or other data structures.
*
* @throws IllegalArgumentException if data is not the correct number of bytes
* @since 0.8.3
*/
public static Hash create(byte[] data) {
return _cache.get(data);
}
/**
* Pull from cache or return new
* @throws ArrayIndexOutOfBoundsException if not enough bytes
* @since 0.8.3
*/
public static Hash create(byte[] data, int off) {
return _cache.get(data, off);
}
/**
* Pull from cache or return new
* @since 0.8.3
*/
public static Hash create(InputStream in) throws IOException {
return _cache.get(in);
}
public Hash() {
super();
}
/** @throws IllegalArgumentException if data is not 32 bytes (null is ok) */
public Hash(byte data[]) {
super();
setData(data);
}
public int length() {
return HASH_LENGTH;
}
/** @throws IllegalArgumentException if data is not 32 bytes (null is ok) */
@Override
public void setData(byte[] data) {
super.setData(data);
_base64ed = null;
_cachedHashCode = super.hashCode();
}
@Override
public void readBytes(InputStream in) throws DataFormatException, IOException {
super.readBytes(in);
_base64ed = null;
_cachedHashCode = super.hashCode();
}
/** a Hash is a hash, so just use the first 4 bytes for speed */
@Override
public int hashCode() {
return _cachedHashCode;
}
@Override
public String toBase64() {
if (_base64ed == null) {
_base64ed = super.toBase64();
}
return _base64ed;
}
/**
* For convenience.
* @return "{52 chars}.b32.i2p" or null if data not set.
* @since 0.9.25
*/
public String toBase32() {
if (_data == null)
return null;
return Base32.encode(_data) + ".b32.i2p";
}
/**
* @since 0.9.17
*/
public static void clearCache() {
_cache.clear();
}
}