View Javadoc
1   /*
2    * Copyright (C) 2008 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.primitives;
16  
17  import static com.google.common.base.Preconditions.checkArgument;
18  import static com.google.common.base.Preconditions.checkElementIndex;
19  import static com.google.common.base.Preconditions.checkNotNull;
20  import static com.google.common.base.Preconditions.checkPositionIndexes;
21  
22  import com.google.common.annotations.GwtCompatible;
23  import java.io.Serializable;
24  import java.util.AbstractList;
25  import java.util.Arrays;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.List;
29  import java.util.RandomAccess;
30  import javax.annotation.Nullable;
31  
32  /**
33   * Static utility methods pertaining to {@code byte} primitives, that are not already found in
34   * either {@link Byte} or {@link Arrays}, <i>and interpret bytes as neither signed nor unsigned</i>.
35   * The methods which specifically treat bytes as signed or unsigned are found in {@link SignedBytes}
36   * and {@link UnsignedBytes}.
37   *
38   * <p>See the Guava User Guide article on
39   * <a href="https://github.com/google/guava/wiki/PrimitivesExplained">primitive utilities</a>.
40   *
41   * @author Kevin Bourrillion
42   * @since 1.0
43   */
44  // TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
45  // javadoc?
46  @GwtCompatible
47  public final class Bytes {
48    private Bytes() {}
49  
50    /**
51     * Returns a hash code for {@code value}; equal to the result of invoking
52     * {@code ((Byte) value).hashCode()}.
53     *
54     * <p><b>Java 8 users:</b> use {@link Byte#hashCode(byte)} instead.
55     *
56     * @param value a primitive {@code byte} value
57     * @return a hash code for the value
58     */
59    public static int hashCode(byte value) {
60      return value;
61    }
62  
63    /**
64     * Returns {@code true} if {@code target} is present as an element anywhere in {@code array}.
65     *
66     * @param array an array of {@code byte} values, possibly empty
67     * @param target a primitive {@code byte} value
68     * @return {@code true} if {@code array[i] == target} for some value of {@code
69     *     i}
70     */
71    public static boolean contains(byte[] array, byte target) {
72      for (byte value : array) {
73        if (value == target) {
74          return true;
75        }
76      }
77      return false;
78    }
79  
80    /**
81     * Returns the index of the first appearance of the value {@code target} in {@code array}.
82     *
83     * @param array an array of {@code byte} values, possibly empty
84     * @param target a primitive {@code byte} value
85     * @return the least index {@code i} for which {@code array[i] == target}, or {@code -1} if no
86     *     such index exists.
87     */
88    public static int indexOf(byte[] array, byte target) {
89      return indexOf(array, target, 0, array.length);
90    }
91  
92    // TODO(kevinb): consider making this public
93    private static int indexOf(byte[] array, byte target, int start, int end) {
94      for (int i = start; i < end; i++) {
95        if (array[i] == target) {
96          return i;
97        }
98      }
99      return -1;
100   }
101 
102   /**
103    * Returns the start position of the first occurrence of the specified {@code
104    * target} within {@code array}, or {@code -1} if there is no such occurrence.
105    *
106    * <p>More formally, returns the lowest index {@code i} such that
107    * {@code Arrays.copyOfRange(array, i, i + target.length)} contains exactly the same elements as
108    * {@code target}.
109    *
110    * @param array the array to search for the sequence {@code target}
111    * @param target the array to search for as a sub-sequence of {@code array}
112    */
113   public static int indexOf(byte[] array, byte[] target) {
114     checkNotNull(array, "array");
115     checkNotNull(target, "target");
116     if (target.length == 0) {
117       return 0;
118     }
119 
120     outer:
121     for (int i = 0; i < array.length - target.length + 1; i++) {
122       for (int j = 0; j < target.length; j++) {
123         if (array[i + j] != target[j]) {
124           continue outer;
125         }
126       }
127       return i;
128     }
129     return -1;
130   }
131 
132   /**
133    * Returns the index of the last appearance of the value {@code target} in {@code array}.
134    *
135    * @param array an array of {@code byte} values, possibly empty
136    * @param target a primitive {@code byte} value
137    * @return the greatest index {@code i} for which {@code array[i] == target}, or {@code -1} if no
138    *     such index exists.
139    */
140   public static int lastIndexOf(byte[] array, byte target) {
141     return lastIndexOf(array, target, 0, array.length);
142   }
143 
144   // TODO(kevinb): consider making this public
145   private static int lastIndexOf(byte[] array, byte target, int start, int end) {
146     for (int i = end - 1; i >= start; i--) {
147       if (array[i] == target) {
148         return i;
149       }
150     }
151     return -1;
152   }
153 
154   /**
155    * Returns the values from each provided array combined into a single array. For example,
156    * {@code concat(new byte[] {a, b}, new byte[] {}, new byte[] {c}} returns the array {@code {a, b,
157    * c}}.
158    *
159    * @param arrays zero or more {@code byte} arrays
160    * @return a single array containing all the values from the source arrays, in order
161    */
162   public static byte[] concat(byte[]... arrays) {
163     int length = 0;
164     for (byte[] array : arrays) {
165       length += array.length;
166     }
167     byte[] result = new byte[length];
168     int pos = 0;
169     for (byte[] array : arrays) {
170       System.arraycopy(array, 0, result, pos, array.length);
171       pos += array.length;
172     }
173     return result;
174   }
175 
176   /**
177    * Returns an array containing the same values as {@code array}, but guaranteed to be of a
178    * specified minimum length. If {@code array} already has a length of at least {@code minLength},
179    * it is returned directly. Otherwise, a new array of size {@code minLength + padding} is
180    * returned, containing the values of {@code array}, and zeroes in the remaining places.
181    *
182    * @param array the source array
183    * @param minLength the minimum length the returned array must guarantee
184    * @param padding an extra amount to "grow" the array by if growth is necessary
185    * @throws IllegalArgumentException if {@code minLength} or {@code padding} is negative
186    * @return an array containing the values of {@code array}, with guaranteed minimum length
187    *     {@code minLength}
188    */
189   public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
190     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
191     checkArgument(padding >= 0, "Invalid padding: %s", padding);
192     return (array.length < minLength) ? Arrays.copyOf(array, minLength + padding) : array;
193   }
194 
195   /**
196    * Returns an array containing each value of {@code collection}, converted to a {@code byte} value
197    * in the manner of {@link Number#byteValue}.
198    *
199    * <p>Elements are copied from the argument collection as if by {@code
200    * collection.toArray()}. Calling this method is as thread-safe as calling that method.
201    *
202    * @param collection a collection of {@code Number} instances
203    * @return an array containing the same values as {@code collection}, in the same order, converted
204    *     to primitives
205    * @throws NullPointerException if {@code collection} or any of its elements is null
206    * @since 1.0 (parameter was {@code Collection<Byte>} before 12.0)
207    */
208   public static byte[] toArray(Collection<? extends Number> collection) {
209     if (collection instanceof ByteArrayAsList) {
210       return ((ByteArrayAsList) collection).toByteArray();
211     }
212 
213     Object[] boxedArray = collection.toArray();
214     int len = boxedArray.length;
215     byte[] array = new byte[len];
216     for (int i = 0; i < len; i++) {
217       // checkNotNull for GWT (do not optimize)
218       array[i] = ((Number) checkNotNull(boxedArray[i])).byteValue();
219     }
220     return array;
221   }
222 
223   /**
224    * Returns a fixed-size list backed by the specified array, similar to
225    * {@link Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)}, but any
226    * attempt to set a value to {@code null} will result in a {@link NullPointerException}.
227    *
228    * <p>The returned list maintains the values, but not the identities, of {@code Byte} objects
229    * written to or read from it. For example, whether {@code list.get(0) == list.get(0)} is true for
230    * the returned list is unspecified.
231    *
232    * @param backingArray the array to back the list
233    * @return a list view of the array
234    */
235   public static List<Byte> asList(byte... backingArray) {
236     if (backingArray.length == 0) {
237       return Collections.emptyList();
238     }
239     return new ByteArrayAsList(backingArray);
240   }
241 
242   @GwtCompatible
243   private static class ByteArrayAsList extends AbstractList<Byte>
244       implements RandomAccess, Serializable {
245     final byte[] array;
246     final int start;
247     final int end;
248 
249     ByteArrayAsList(byte[] array) {
250       this(array, 0, array.length);
251     }
252 
253     ByteArrayAsList(byte[] array, int start, int end) {
254       this.array = array;
255       this.start = start;
256       this.end = end;
257     }
258 
259     @Override
260     public int size() {
261       return end - start;
262     }
263 
264     @Override
265     public boolean isEmpty() {
266       return false;
267     }
268 
269     @Override
270     public Byte get(int index) {
271       checkElementIndex(index, size());
272       return array[start + index];
273     }
274 
275     @Override
276     public boolean contains(Object target) {
277       // Overridden to prevent a ton of boxing
278       return (target instanceof Byte) && Bytes.indexOf(array, (Byte) target, start, end) != -1;
279     }
280 
281     @Override
282     public int indexOf(Object target) {
283       // Overridden to prevent a ton of boxing
284       if (target instanceof Byte) {
285         int i = Bytes.indexOf(array, (Byte) target, start, end);
286         if (i >= 0) {
287           return i - start;
288         }
289       }
290       return -1;
291     }
292 
293     @Override
294     public int lastIndexOf(Object target) {
295       // Overridden to prevent a ton of boxing
296       if (target instanceof Byte) {
297         int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
298         if (i >= 0) {
299           return i - start;
300         }
301       }
302       return -1;
303     }
304 
305     @Override
306     public Byte set(int index, Byte element) {
307       checkElementIndex(index, size());
308       byte oldValue = array[start + index];
309       // checkNotNull for GWT (do not optimize)
310       array[start + index] = checkNotNull(element);
311       return oldValue;
312     }
313 
314     @Override
315     public List<Byte> subList(int fromIndex, int toIndex) {
316       int size = size();
317       checkPositionIndexes(fromIndex, toIndex, size);
318       if (fromIndex == toIndex) {
319         return Collections.emptyList();
320       }
321       return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
322     }
323 
324     @Override
325     public boolean equals(@Nullable Object object) {
326       if (object == this) {
327         return true;
328       }
329       if (object instanceof ByteArrayAsList) {
330         ByteArrayAsList that = (ByteArrayAsList) object;
331         int size = size();
332         if (that.size() != size) {
333           return false;
334         }
335         for (int i = 0; i < size; i++) {
336           if (array[start + i] != that.array[that.start + i]) {
337             return false;
338           }
339         }
340         return true;
341       }
342       return super.equals(object);
343     }
344 
345     @Override
346     public int hashCode() {
347       int result = 1;
348       for (int i = start; i < end; i++) {
349         result = 31 * result + Bytes.hashCode(array[i]);
350       }
351       return result;
352     }
353 
354     @Override
355     public String toString() {
356       StringBuilder builder = new StringBuilder(size() * 5);
357       builder.append('[').append(array[start]);
358       for (int i = start + 1; i < end; i++) {
359         builder.append(", ").append(array[i]);
360       }
361       return builder.append(']').toString();
362     }
363 
364     byte[] toByteArray() {
365       return Arrays.copyOfRange(array, start, end);
366     }
367 
368     private static final long serialVersionUID = 0;
369   }
370 
371   /**
372    * Reverses the elements of {@code array}. This is equivalent to {@code
373    * Collections.reverse(Bytes.asList(array))}, but is likely to be more efficient.
374    *
375    * @since 23.1
376    */
377   public static void reverse(byte[] array) {
378     checkNotNull(array);
379     reverse(array, 0, array.length);
380   }
381 
382   /**
383    * Reverses the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
384    * exclusive. This is equivalent to {@code
385    * Collections.reverse(Bytes.asList(array).subList(fromIndex, toIndex))}, but is likely to be more
386    * efficient.
387    *
388    * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
389    *     {@code toIndex > fromIndex}
390    * @since 23.1
391    */
392   public static void reverse(byte[] array, int fromIndex, int toIndex) {
393     checkNotNull(array);
394     checkPositionIndexes(fromIndex, toIndex, array.length);
395     for (int i = fromIndex, j = toIndex - 1; i < j; i++, j--) {
396       byte tmp = array[i];
397       array[i] = array[j];
398       array[j] = tmp;
399     }
400   }
401 }