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