content: package btools.util;
  
  public final class ByteArrayUnifier implements IByteArrayUnifier {
    private byte[][] byteArrayCache;
    private int[] crcCrosscheck;
    private int size;
  
    public ByteArrayUnifier(int size, boolean validateImmutability) {
      this.size = size;
      byteArrayCache = new byte[size][];
      if (validateImmutability) crcCrosscheck = new int[size];
    }
  
    /**
     * Unify a byte array in order to reuse instances when possible.
     * The byte arrays are assumed to be treated as immutable,
     * allowing the reuse
     *
     * @param ab the byte array to unify
     * @return the cached instance or the input instanced if not cached
     */
    public byte[] unify(byte[] ab) {
      return unify(ab, 0, ab.length);
    }
  
    public byte[] unify(byte[] ab, int offset, int len) {
      int crc = Crc32.crc(ab, offset, len);
      int idx = (crc & 0xfffffff) % size;
      byte[] abc = byteArrayCache[idx];
      if (abc != null && abc.length == len) {
        int i = 0;
        while (i < len) {
          if (ab[offset + i] != abc[i])
            break;
          i++;
        }
        if (i == len)
          return abc;
      }
      if (crcCrosscheck != null) {
        if (byteArrayCache[idx] != null) {
          byte[] abold = byteArrayCache[idx];
          int crcold = Crc32.crc(abold, 0, abold.length);
          if (crcold != crcCrosscheck[idx])
            throw new IllegalArgumentException("ByteArrayUnifier: immutablity validation failed!");
        }
        crcCrosscheck[idx] = crc;
      }
      byte[] nab = new byte[len];
      System.arraycopy(ab, offset, nab, 0, len);
      byteArrayCache[idx] = nab;
      return nab;
    }
  }
  