17dd252788645e940eada959bdde927426e2531c9Paul Duffin/*
27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2011 The Guava Authors
37dd252788645e940eada959bdde927426e2531c9Paul Duffin *
47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License.
67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at
77dd252788645e940eada959bdde927426e2531c9Paul Duffin *
87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
97dd252788645e940eada959bdde927426e2531c9Paul Duffin *
107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software
117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and
147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License.
157dd252788645e940eada959bdde927426e2531c9Paul Duffin */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.hash;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
207dd252788645e940eada959bdde927426e2531c9Paul Duffin
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.charset.Charset;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An abstract composition of multiple hash functions. {@linkplain #newHasher()} delegates to the
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Hasher} objects of the delegate hash functions, and in the end, they are used by
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@linkplain #makeHash(Hasher[])} that constructs the final {@code HashCode}.
277dd252788645e940eada959bdde927426e2531c9Paul Duffin *
287dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Dimitris Andreou
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertabstract class AbstractCompositeHashFunction extends AbstractStreamingHashFunction {
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final HashFunction[] functions;
327dd252788645e940eada959bdde927426e2531c9Paul Duffin
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  AbstractCompositeHashFunction(HashFunction... functions) {
347dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (HashFunction function : functions) {
357dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkNotNull(function);
367dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.functions = functions;
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
397dd252788645e940eada959bdde927426e2531c9Paul Duffin
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Constructs a {@code HashCode} from the {@code Hasher} objects of the functions. Each of them
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * has consumed the entire input and they are ready to output a {@code HashCode}. The order of
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the hashers are the same order as the functions given to the constructor.
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // this could be cleaner if it passed HashCode[], but that would create yet another array...
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /* protected */ abstract HashCode makeHash(Hasher[] hashers);
477dd252788645e940eada959bdde927426e2531c9Paul Duffin
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Hasher newHasher() {
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Hasher[] hashers = new Hasher[functions.length];
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < hashers.length; i++) {
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      hashers[i] = functions[i].newHasher();
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new Hasher() {
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putByte(byte b) {
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putByte(b);
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putBytes(byte[] bytes) {
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBytes(bytes);
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putBytes(byte[] bytes, int off, int len) {
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBytes(bytes, off, len);
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putShort(short s) {
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putShort(s);
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putInt(int i) {
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putInt(i);
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putLong(long l) {
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putLong(l);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putFloat(float f) {
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putFloat(f);
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putDouble(double d) {
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putDouble(d);
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putBoolean(boolean b) {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBoolean(b);
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putChar(char c) {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putChar(c);
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putUnencodedChars(CharSequence chars) {
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin          hasher.putUnencodedChars(chars);
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Hasher putString(CharSequence chars, Charset charset) {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putString(chars, charset);
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putObject(instance, funnel);
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public HashCode hash() {
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return makeHash(hashers);
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1517dd252788645e940eada959bdde927426e2531c9Paul Duffin
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final long serialVersionUID = 0L;
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
154