1 /*
2  * Copyright (C) 2011 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.hash;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import java.nio.charset.Charset;
22 
23 /**
24  * An abstract composition of multiple hash functions. {@linkplain #newHasher()} delegates to the
25  * {@code Hasher} objects of the delegate hash functions, and in the end, they are used by
26  * {@linkplain #makeHash(Hasher[])} that constructs the final {@code HashCode}.
27  *
28  * @author Dimitris Andreou
29  */
30 abstract class AbstractCompositeHashFunction extends AbstractStreamingHashFunction {
31   final HashFunction[] functions;
32 
AbstractCompositeHashFunction(HashFunction... functions)33   AbstractCompositeHashFunction(HashFunction... functions) {
34     for (HashFunction function : functions) {
35       checkNotNull(function);
36     }
37     this.functions = functions;
38   }
39 
40   /**
41    * Constructs a {@code HashCode} from the {@code Hasher} objects of the functions. Each of them
42    * has consumed the entire input and they are ready to output a {@code HashCode}. The order of
43    * the hashers are the same order as the functions given to the constructor.
44    */
45   // this could be cleaner if it passed HashCode[], but that would create yet another array...
makeHash(Hasher[] hashers)46   /* protected */ abstract HashCode makeHash(Hasher[] hashers);
47 
48   @Override
newHasher()49   public Hasher newHasher() {
50     final Hasher[] hashers = new Hasher[functions.length];
51     for (int i = 0; i < hashers.length; i++) {
52       hashers[i] = functions[i].newHasher();
53     }
54     return new Hasher() {
55       @Override public Hasher putByte(byte b) {
56         for (Hasher hasher : hashers) {
57           hasher.putByte(b);
58         }
59         return this;
60       }
61 
62       @Override public Hasher putBytes(byte[] bytes) {
63         for (Hasher hasher : hashers) {
64           hasher.putBytes(bytes);
65         }
66         return this;
67       }
68 
69       @Override public Hasher putBytes(byte[] bytes, int off, int len) {
70         for (Hasher hasher : hashers) {
71           hasher.putBytes(bytes, off, len);
72         }
73         return this;
74       }
75 
76       @Override public Hasher putShort(short s) {
77         for (Hasher hasher : hashers) {
78           hasher.putShort(s);
79         }
80         return this;
81       }
82 
83       @Override public Hasher putInt(int i) {
84         for (Hasher hasher : hashers) {
85           hasher.putInt(i);
86         }
87         return this;
88       }
89 
90       @Override public Hasher putLong(long l) {
91         for (Hasher hasher : hashers) {
92           hasher.putLong(l);
93         }
94         return this;
95       }
96 
97       @Override public Hasher putFloat(float f) {
98         for (Hasher hasher : hashers) {
99           hasher.putFloat(f);
100         }
101         return this;
102       }
103 
104       @Override public Hasher putDouble(double d) {
105         for (Hasher hasher : hashers) {
106           hasher.putDouble(d);
107         }
108         return this;
109       }
110 
111       @Override public Hasher putBoolean(boolean b) {
112         for (Hasher hasher : hashers) {
113           hasher.putBoolean(b);
114         }
115         return this;
116       }
117 
118       @Override public Hasher putChar(char c) {
119         for (Hasher hasher : hashers) {
120           hasher.putChar(c);
121         }
122         return this;
123       }
124 
125       /**
126        * @deprecated Use {@link Hasher#putUnencodedChars} instead.
127        */
128       @Deprecated
129       @Override public Hasher putString(CharSequence chars) {
130         return putUnencodedChars(chars);
131       }
132 
133       @Override public Hasher putUnencodedChars(CharSequence chars) {
134         for (Hasher hasher : hashers) {
135           hasher.putUnencodedChars(chars);
136         }
137         return this;
138       }
139 
140       @Override public Hasher putString(CharSequence chars, Charset charset) {
141         for (Hasher hasher : hashers) {
142           hasher.putString(chars, charset);
143         }
144         return this;
145       }
146 
147       @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
148         for (Hasher hasher : hashers) {
149           hasher.putObject(instance, funnel);
150         }
151         return this;
152       }
153 
154       @Override public HashCode hash() {
155         return makeHash(hashers);
156       }
157     };
158   }
159 
160   private static final long serialVersionUID = 0L;
161 }
162