• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
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.android.mediaframeworktest.unit;
18 
19 import android.util.Log;
20 
21 import java.lang.reflect.Array;
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24 import java.util.Arrays;
25 
26 public class ByteArrayHelpers {
27 
28     private static final String TAG = "ByteArrayHelpers";
29     private static boolean VERBOSE = false;
30 
31     /**
32      * Convert an array of byte primitives to a {@code byte[]} using native endian order.
33      *
34      * <p>This function is a pass-through; it's here only to provide overloads for
35      * every single type of primitive arrays.
36      *
37      * @param array array of primitives
38      * @return array
39      */
toByteArray(byte[] array)40     public static byte[] toByteArray(byte[] array) {
41         return array;
42     }
43 
44     /**
45      * Convert an array of shorts to a {@code byte[]} using native endian order.
46      *
47      * @param array array of shorts
48      * @return array converted into byte array using native endian order
49      */
toByteArray(short[] array)50     public static byte[] toByteArray(short[] array) {
51         return toByteArray(array, Short.SIZE);
52     }
53 
54     /**
55      * Convert an array of chars to a {@code byte[]} using native endian order.
56      *
57      * @param array array of chars
58      * @return array converted into byte array using native endian order
59      */
toByteArray(char[] array)60     public static byte[] toByteArray(char[] array) {
61         return toByteArray(array, Character.SIZE);
62     }
63     /**
64      * Convert an array of ints to a {@code byte[]} using native endian order.
65      *
66      * @param array array of ints
67      * @return array converted into byte array using native endian order
68      */
toByteArray(int[] array)69     public static byte[] toByteArray(int[] array) {
70         return toByteArray(array, Integer.SIZE);
71     }
72     /**
73      * Convert an array of longs to a {@code byte[]} using native endian order.
74      *
75      * @param array array of longs
76      * @return array converted into byte array using native endian order
77      */
toByteArray(long[] array)78     public static byte[] toByteArray(long[] array) {
79         return toByteArray(array, Long.SIZE);
80     }
81     /**
82      * Convert an array of floats to a {@code byte[]} using native endian order.
83      *
84      * @param array array of floats
85      * @return array converted into byte array using native endian order
86      */
toByteArray(float[] array)87     public static byte[] toByteArray(float[] array) {
88         return toByteArray(array, Float.SIZE);
89     }
90     /**
91      * Convert an array of doubles to a {@code byte[]} using native endian order.
92      *
93      * @param array array of doubles
94      * @return array converted into byte array using native endian order
95      */
toByteArray(double[] array)96     public static byte[] toByteArray(double[] array) {
97         return toByteArray(array, Double.SIZE);
98     }
99 
100     /**
101      * Convert an array of primitives to a {@code byte[]} using native endian order.
102      *
103      * <p>Arguments other than arrays are not supported. The array component must be primitive,
104      * the wrapper class is not allowed (e.g. {@code int[]} is ok, but {@code Integer[]} is not.</p>
105      *
106      * @param array array of primitives
107      * @return array converted into byte array using native endian order
108      *
109      * @throws IllegalArgumentException if {@code array} was not an array of primitives
110      */
toByteArray(T array)111     public static <T> byte[] toByteArray(T array) {
112         @SuppressWarnings("unchecked")
113         Class<T> klass = (Class<T>) array.getClass();
114 
115         if (!klass.isArray()) {
116             throw new IllegalArgumentException("array class must be an array");
117         }
118 
119         Class<?> componentClass = klass.getComponentType();
120 
121         if (!componentClass.isPrimitive()) {
122             throw new IllegalArgumentException("array's component must be a primitive");
123         }
124 
125         int sizeInBits;
126         if (klass == int.class) {
127             sizeInBits = Integer.SIZE;
128         } else if (klass == float.class) {
129             sizeInBits = Float.SIZE;
130         } else if (klass == double.class) {
131             sizeInBits = Double.SIZE;
132         } else if (klass == short.class) {
133             sizeInBits = Short.SIZE;
134         } else if (klass == char.class) {
135             sizeInBits = Character.SIZE;
136         } else if (klass == long.class) {
137             sizeInBits = Long.SIZE;
138         } else if (klass == byte.class) {
139             sizeInBits = Byte.SIZE;
140         } else {
141             throw new AssertionError();
142         }
143 
144         return toByteArray(array, sizeInBits);
145     }
146 
147     /**
148      * Convert a variadic list of {@code Number}s into a byte array using native endian order.
149      *
150      * <p>Each {@link Number} must be an instance of a primitive wrapper class
151      * (e.g. {@link Integer} is OK, since it wraps {@code int}, but {@code BigInteger} is not.</p>
152      *
153      * @param numbers variadic list of numeric values
154      * @return array converted into byte array using native endian order
155      *
156      * @throws IllegalArgumentException
157      *          if {@code numbers} contained a class that wasn't a primitive wrapper
158      */
toByteArray(Number... numbers)159     public static byte[] toByteArray(Number... numbers) {
160         if (numbers.length == 0) {
161             throw new IllegalArgumentException("too few numbers");
162         }
163 
164         if (VERBOSE) Log.v(TAG, "toByteArray - input: " + Arrays.toString(numbers));
165 
166         // Have a large enough capacity to fit in every number as a double
167         ByteBuffer byteBuffer = ByteBuffer.allocate(numbers.length * (Double.SIZE / Byte.SIZE))
168                 .order(ByteOrder.nativeOrder());
169 
170         for (int i = 0; i < numbers.length; ++i) {
171             Number value = numbers[i];
172             Class<? extends Number> klass = value.getClass();
173 
174             if (VERBOSE) Log.v(TAG, "toByteArray - number " + i + ", class " + klass);
175 
176             if (klass == Integer.class) {
177                 byteBuffer.putInt((Integer)value);
178             } else if (klass == Float.class) {
179                 byteBuffer.putFloat((Float)value);
180             } else if (klass == Double.class) {
181                 byteBuffer.putDouble((Double)value);
182             } else if (klass == Short.class) {
183                 byteBuffer.putShort((Short)value);
184             } else if (klass == Long.class) {
185                 byteBuffer.putLong((Long)value);
186             } else if (klass == Byte.class) {
187                 byteBuffer.put((Byte)value);
188             } else {
189                 throw new IllegalArgumentException(
190                         "number class invalid; must be wrapper around primitive class");
191             }
192         }
193 
194         if (VERBOSE) Log.v(TAG, "toByteArray - end of loop");
195 
196         // Each number written is at least 1 byte, so the position should be at least length
197         if (numbers.length != 0 && byteBuffer.position() < numbers.length) {
198             throw new AssertionError(String.format(
199                     "Had %d numbers, but byte buffer position was only %d",
200                     numbers.length, byteBuffer.position()));
201         }
202 
203         byteBuffer.flip();
204 
205         byte[] bytes = new byte[byteBuffer.limit()];
206         byteBuffer.get(bytes);
207 
208         if (VERBOSE) Log.v(TAG, "toByteArray - output: " + Arrays.toString(bytes));
209 
210         return bytes;
211     }
212 
toByteArray(T array, int sizeOfTBits)213     private static <T> byte[] toByteArray(T array, int sizeOfTBits) {
214         @SuppressWarnings("unchecked")
215         Class<T> klass = (Class<T>) array.getClass();
216 
217         if (!klass.isArray()) {
218             throw new IllegalArgumentException("array class must be an array");
219         }
220 
221         int sizeOfT = sizeOfTBits / Byte.SIZE;
222         int byteLength = Array.getLength(array) * sizeOfT;
223 
224         if (klass == byte[].class) {
225             // Always return a copy
226             return Arrays.copyOf((byte[])array, byteLength);
227         }
228 
229         ByteBuffer byteBuffer = ByteBuffer.allocate(byteLength).order(ByteOrder.nativeOrder());
230 
231         if (klass == int[].class) {
232             byteBuffer.asIntBuffer().put((int[])array);
233         } else if (klass == float[].class) {
234             byteBuffer.asFloatBuffer().put((float[])array);
235         } else if (klass == double[].class) {
236             byteBuffer.asDoubleBuffer().put((double[])array);
237         } else if (klass == short[].class) {
238             byteBuffer.asShortBuffer().put((short[])array);
239         } else if (klass == char[].class) {
240             byteBuffer.asCharBuffer().put((char[])array);
241         } else if (klass == long[].class) {
242             byteBuffer.asLongBuffer().put((long[])array);
243         } else {
244             throw new IllegalArgumentException("array class invalid; must be a primitive array");
245         }
246 
247         return byteBuffer.array();
248     }
249 
ByteArrayHelpers()250     private ByteArrayHelpers() {
251         throw new AssertionError();
252     }
253 }
254