• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.google.android.exoplayer2.util;
17 
18 import androidx.annotation.Nullable;
19 import com.google.android.exoplayer2.C;
20 import java.nio.ByteBuffer;
21 import java.nio.charset.Charset;
22 
23 /**
24  * Wraps a byte array, providing a set of methods for parsing data from it. Numerical values are
25  * parsed with the assumption that their constituent bytes are in big endian order.
26  */
27 public final class ParsableByteArray {
28 
29   public byte[] data;
30 
31   private int position;
32   private int limit;
33 
34   /** Creates a new instance that initially has no backing data. */
ParsableByteArray()35   public ParsableByteArray() {
36     data = Util.EMPTY_BYTE_ARRAY;
37   }
38 
39   /**
40    * Creates a new instance with {@code limit} bytes and sets the limit.
41    *
42    * @param limit The limit to set.
43    */
ParsableByteArray(int limit)44   public ParsableByteArray(int limit) {
45     this.data = new byte[limit];
46     this.limit = limit;
47   }
48 
49   /**
50    * Creates a new instance wrapping {@code data}, and sets the limit to {@code data.length}.
51    *
52    * @param data The array to wrap.
53    */
ParsableByteArray(byte[] data)54   public ParsableByteArray(byte[] data) {
55     this.data = data;
56     limit = data.length;
57   }
58 
59   /**
60    * Creates a new instance that wraps an existing array.
61    *
62    * @param data The data to wrap.
63    * @param limit The limit to set.
64    */
ParsableByteArray(byte[] data, int limit)65   public ParsableByteArray(byte[] data, int limit) {
66     this.data = data;
67     this.limit = limit;
68   }
69 
70   /** Sets the position and limit to zero. */
reset()71   public void reset() {
72     position = 0;
73     limit = 0;
74   }
75 
76   /**
77    * Resets the position to zero and the limit to the specified value. If the limit exceeds the
78    * capacity, {@code data} is replaced with a new array of sufficient size.
79    *
80    * @param limit The limit to set.
81    */
reset(int limit)82   public void reset(int limit) {
83     reset(capacity() < limit ? new byte[limit] : data, limit);
84   }
85 
86   /**
87    * Updates the instance to wrap {@code data}, and resets the position to zero and the limit to
88    * {@code data.length}.
89    *
90    * @param data The array to wrap.
91    */
92   public void reset(byte[] data) {
93     reset(data, data.length);
94   }
95 
96   /**
97    * Updates the instance to wrap {@code data}, and resets the position to zero.
98    *
99    * @param data The array to wrap.
100    * @param limit The limit to set.
101    */
102   public void reset(byte[] data, int limit) {
103     this.data = data;
104     this.limit = limit;
105     position = 0;
106   }
107 
108   /**
109    * Returns the number of bytes yet to be read.
110    */
111   public int bytesLeft() {
112     return limit - position;
113   }
114 
115   /**
116    * Returns the limit.
117    */
118   public int limit() {
119     return limit;
120   }
121 
122   /**
123    * Sets the limit.
124    *
125    * @param limit The limit to set.
126    */
127   public void setLimit(int limit) {
128     Assertions.checkArgument(limit >= 0 && limit <= data.length);
129     this.limit = limit;
130   }
131 
132   /**
133    * Returns the current offset in the array, in bytes.
134    */
getPosition()135   public int getPosition() {
136     return position;
137   }
138 
139   /**
140    * Returns the capacity of the array, which may be larger than the limit.
141    */
capacity()142   public int capacity() {
143     return data.length;
144   }
145 
146   /**
147    * Sets the reading offset in the array.
148    *
149    * @param position Byte offset in the array from which to read.
150    * @throws IllegalArgumentException Thrown if the new position is neither in nor at the end of the
151    *     array.
152    */
setPosition(int position)153   public void setPosition(int position) {
154     // It is fine for position to be at the end of the array.
155     Assertions.checkArgument(position >= 0 && position <= limit);
156     this.position = position;
157   }
158 
159   /**
160    * Moves the reading offset by {@code bytes}.
161    *
162    * @param bytes The number of bytes to skip.
163    * @throws IllegalArgumentException Thrown if the new position is neither in nor at the end of the
164    *     array.
165    */
skipBytes(int bytes)166   public void skipBytes(int bytes) {
167     setPosition(position + bytes);
168   }
169 
170   /**
171    * Reads the next {@code length} bytes into {@code bitArray}, and resets the position of
172    * {@code bitArray} to zero.
173    *
174    * @param bitArray The {@link ParsableBitArray} into which the bytes should be read.
175    * @param length The number of bytes to write.
176    */
readBytes(ParsableBitArray bitArray, int length)177   public void readBytes(ParsableBitArray bitArray, int length) {
178     readBytes(bitArray.data, 0, length);
179     bitArray.setPosition(0);
180   }
181 
182   /**
183    * Reads the next {@code length} bytes into {@code buffer} at {@code offset}.
184    *
185    * @see System#arraycopy(Object, int, Object, int, int)
186    * @param buffer The array into which the read data should be written.
187    * @param offset The offset in {@code buffer} at which the read data should be written.
188    * @param length The number of bytes to read.
189    */
readBytes(byte[] buffer, int offset, int length)190   public void readBytes(byte[] buffer, int offset, int length) {
191     System.arraycopy(data, position, buffer, offset, length);
192     position += length;
193   }
194 
195   /**
196    * Reads the next {@code length} bytes into {@code buffer}.
197    *
198    * @see ByteBuffer#put(byte[], int, int)
199    * @param buffer The {@link ByteBuffer} into which the read data should be written.
200    * @param length The number of bytes to read.
201    */
readBytes(ByteBuffer buffer, int length)202   public void readBytes(ByteBuffer buffer, int length) {
203     buffer.put(data, position, length);
204     position += length;
205   }
206 
207   /**
208    * Peeks at the next byte as an unsigned value.
209    */
peekUnsignedByte()210   public int peekUnsignedByte() {
211     return (data[position] & 0xFF);
212   }
213 
214   /**
215    * Peeks at the next char.
216    */
peekChar()217   public char peekChar() {
218     return (char) ((data[position] & 0xFF) << 8
219         | (data[position + 1] & 0xFF));
220   }
221 
222   /**
223    * Reads the next byte as an unsigned value.
224    */
readUnsignedByte()225   public int readUnsignedByte() {
226     return (data[position++] & 0xFF);
227   }
228 
229   /**
230    * Reads the next two bytes as an unsigned value.
231    */
readUnsignedShort()232   public int readUnsignedShort() {
233     return (data[position++] & 0xFF) << 8
234         | (data[position++] & 0xFF);
235   }
236 
237   /**
238    * Reads the next two bytes as an unsigned value.
239    */
readLittleEndianUnsignedShort()240   public int readLittleEndianUnsignedShort() {
241     return (data[position++] & 0xFF) | (data[position++] & 0xFF) << 8;
242   }
243 
244   /**
245    * Reads the next two bytes as a signed value.
246    */
readShort()247   public short readShort() {
248     return (short) ((data[position++] & 0xFF) << 8
249         | (data[position++] & 0xFF));
250   }
251 
252   /**
253    * Reads the next two bytes as a signed value.
254    */
readLittleEndianShort()255   public short readLittleEndianShort() {
256     return (short) ((data[position++] & 0xFF) | (data[position++] & 0xFF) << 8);
257   }
258 
259   /**
260    * Reads the next three bytes as an unsigned value.
261    */
readUnsignedInt24()262   public int readUnsignedInt24() {
263     return (data[position++] & 0xFF) << 16
264         | (data[position++] & 0xFF) << 8
265         | (data[position++] & 0xFF);
266   }
267 
268   /**
269    * Reads the next three bytes as a signed value.
270    */
readInt24()271   public int readInt24() {
272     return ((data[position++] & 0xFF) << 24) >> 8
273         | (data[position++] & 0xFF) << 8
274         | (data[position++] & 0xFF);
275   }
276 
277   /**
278    * Reads the next three bytes as a signed value in little endian order.
279    */
readLittleEndianInt24()280   public int readLittleEndianInt24() {
281     return (data[position++] & 0xFF)
282         | (data[position++] & 0xFF) << 8
283         | (data[position++] & 0xFF) << 16;
284   }
285 
286   /**
287    * Reads the next three bytes as an unsigned value in little endian order.
288    */
readLittleEndianUnsignedInt24()289   public int readLittleEndianUnsignedInt24() {
290     return (data[position++] & 0xFF)
291         | (data[position++] & 0xFF) << 8
292         | (data[position++] & 0xFF) << 16;
293   }
294 
295   /**
296    * Reads the next four bytes as an unsigned value.
297    */
readUnsignedInt()298   public long readUnsignedInt() {
299     return (data[position++] & 0xFFL) << 24
300         | (data[position++] & 0xFFL) << 16
301         | (data[position++] & 0xFFL) << 8
302         | (data[position++] & 0xFFL);
303   }
304 
305   /**
306    * Reads the next four bytes as an unsigned value in little endian order.
307    */
readLittleEndianUnsignedInt()308   public long readLittleEndianUnsignedInt() {
309     return (data[position++] & 0xFFL)
310         | (data[position++] & 0xFFL) << 8
311         | (data[position++] & 0xFFL) << 16
312         | (data[position++] & 0xFFL) << 24;
313   }
314 
315   /**
316    * Reads the next four bytes as a signed value
317    */
readInt()318   public int readInt() {
319     return (data[position++] & 0xFF) << 24
320         | (data[position++] & 0xFF) << 16
321         | (data[position++] & 0xFF) << 8
322         | (data[position++] & 0xFF);
323   }
324 
325   /**
326    * Reads the next four bytes as a signed value in little endian order.
327    */
readLittleEndianInt()328   public int readLittleEndianInt() {
329     return (data[position++] & 0xFF)
330         | (data[position++] & 0xFF) << 8
331         | (data[position++] & 0xFF) << 16
332         | (data[position++] & 0xFF) << 24;
333   }
334 
335   /**
336    * Reads the next eight bytes as a signed value.
337    */
readLong()338   public long readLong() {
339     return (data[position++] & 0xFFL) << 56
340         | (data[position++] & 0xFFL) << 48
341         | (data[position++] & 0xFFL) << 40
342         | (data[position++] & 0xFFL) << 32
343         | (data[position++] & 0xFFL) << 24
344         | (data[position++] & 0xFFL) << 16
345         | (data[position++] & 0xFFL) << 8
346         | (data[position++] & 0xFFL);
347   }
348 
349   /**
350    * Reads the next eight bytes as a signed value in little endian order.
351    */
readLittleEndianLong()352   public long readLittleEndianLong() {
353     return (data[position++] & 0xFFL)
354         | (data[position++] & 0xFFL) << 8
355         | (data[position++] & 0xFFL) << 16
356         | (data[position++] & 0xFFL) << 24
357         | (data[position++] & 0xFFL) << 32
358         | (data[position++] & 0xFFL) << 40
359         | (data[position++] & 0xFFL) << 48
360         | (data[position++] & 0xFFL) << 56;
361   }
362 
363   /**
364    * Reads the next four bytes, returning the integer portion of the fixed point 16.16 integer.
365    */
readUnsignedFixedPoint1616()366   public int readUnsignedFixedPoint1616() {
367     int result = (data[position++] & 0xFF) << 8
368         | (data[position++] & 0xFF);
369     position += 2; // Skip the non-integer portion.
370     return result;
371   }
372 
373   /**
374    * Reads a Synchsafe integer.
375    * <p>
376    * Synchsafe integers keep the highest bit of every byte zeroed. A 32 bit synchsafe integer can
377    * store 28 bits of information.
378    *
379    * @return The parsed value.
380    */
readSynchSafeInt()381   public int readSynchSafeInt() {
382     int b1 = readUnsignedByte();
383     int b2 = readUnsignedByte();
384     int b3 = readUnsignedByte();
385     int b4 = readUnsignedByte();
386     return (b1 << 21) | (b2 << 14) | (b3 << 7) | b4;
387   }
388 
389   /**
390    * Reads the next four bytes as an unsigned integer into an integer, if the top bit is a zero.
391    *
392    * @throws IllegalStateException Thrown if the top bit of the input data is set.
393    */
readUnsignedIntToInt()394   public int readUnsignedIntToInt() {
395     int result = readInt();
396     if (result < 0) {
397       throw new IllegalStateException("Top bit not zero: " + result);
398     }
399     return result;
400   }
401 
402   /**
403    * Reads the next four bytes as a little endian unsigned integer into an integer, if the top bit
404    * is a zero.
405    *
406    * @throws IllegalStateException Thrown if the top bit of the input data is set.
407    */
readLittleEndianUnsignedIntToInt()408   public int readLittleEndianUnsignedIntToInt() {
409     int result = readLittleEndianInt();
410     if (result < 0) {
411       throw new IllegalStateException("Top bit not zero: " + result);
412     }
413     return result;
414   }
415 
416   /**
417    * Reads the next eight bytes as an unsigned long into a long, if the top bit is a zero.
418    *
419    * @throws IllegalStateException Thrown if the top bit of the input data is set.
420    */
readUnsignedLongToLong()421   public long readUnsignedLongToLong() {
422     long result = readLong();
423     if (result < 0) {
424       throw new IllegalStateException("Top bit not zero: " + result);
425     }
426     return result;
427   }
428 
429   /**
430    * Reads the next four bytes as a 32-bit floating point value.
431    */
readFloat()432   public float readFloat() {
433     return Float.intBitsToFloat(readInt());
434   }
435 
436   /**
437    * Reads the next eight bytes as a 64-bit floating point value.
438    */
readDouble()439   public double readDouble() {
440     return Double.longBitsToDouble(readLong());
441   }
442 
443   /**
444    * Reads the next {@code length} bytes as UTF-8 characters.
445    *
446    * @param length The number of bytes to read.
447    * @return The string encoded by the bytes.
448    */
readString(int length)449   public String readString(int length) {
450     return readString(length, Charset.forName(C.UTF8_NAME));
451   }
452 
453   /**
454    * Reads the next {@code length} bytes as characters in the specified {@link Charset}.
455    *
456    * @param length The number of bytes to read.
457    * @param charset The character set of the encoded characters.
458    * @return The string encoded by the bytes in the specified character set.
459    */
readString(int length, Charset charset)460   public String readString(int length, Charset charset) {
461     String result = new String(data, position, length, charset);
462     position += length;
463     return result;
464   }
465 
466   /**
467    * Reads the next {@code length} bytes as UTF-8 characters. A terminating NUL byte is discarded,
468    * if present.
469    *
470    * @param length The number of bytes to read.
471    * @return The string, not including any terminating NUL byte.
472    */
readNullTerminatedString(int length)473   public String readNullTerminatedString(int length) {
474     if (length == 0) {
475       return "";
476     }
477     int stringLength = length;
478     int lastIndex = position + length - 1;
479     if (lastIndex < limit && data[lastIndex] == 0) {
480       stringLength--;
481     }
482     String result = Util.fromUtf8Bytes(data, position, stringLength);
483     position += length;
484     return result;
485   }
486 
487   /**
488    * Reads up to the next NUL byte (or the limit) as UTF-8 characters.
489    *
490    * @return The string not including any terminating NUL byte, or null if the end of the data has
491    *     already been reached.
492    */
493   @Nullable
readNullTerminatedString()494   public String readNullTerminatedString() {
495     if (bytesLeft() == 0) {
496       return null;
497     }
498     int stringLimit = position;
499     while (stringLimit < limit && data[stringLimit] != 0) {
500       stringLimit++;
501     }
502     String string = Util.fromUtf8Bytes(data, position, stringLimit - position);
503     position = stringLimit;
504     if (position < limit) {
505       position++;
506     }
507     return string;
508   }
509 
510   /**
511    * Reads a line of text.
512    *
513    * <p>A line is considered to be terminated by any one of a carriage return ('\r'), a line feed
514    * ('\n'), or a carriage return followed immediately by a line feed ('\r\n'). The system's default
515    * charset (UTF-8) is used. This method discards leading UTF-8 byte order marks, if present.
516    *
517    * @return The line not including any line-termination characters, or null if the end of the data
518    *     has already been reached.
519    */
520   @Nullable
readLine()521   public String readLine() {
522     if (bytesLeft() == 0) {
523       return null;
524     }
525     int lineLimit = position;
526     while (lineLimit < limit && !Util.isLinebreak(data[lineLimit])) {
527       lineLimit++;
528     }
529     if (lineLimit - position >= 3 && data[position] == (byte) 0xEF
530         && data[position + 1] == (byte) 0xBB && data[position + 2] == (byte) 0xBF) {
531       // There's a UTF-8 byte order mark at the start of the line. Discard it.
532       position += 3;
533     }
534     String line = Util.fromUtf8Bytes(data, position, lineLimit - position);
535     position = lineLimit;
536     if (position == limit) {
537       return line;
538     }
539     if (data[position] == '\r') {
540       position++;
541       if (position == limit) {
542         return line;
543       }
544     }
545     if (data[position] == '\n') {
546       position++;
547     }
548     return line;
549   }
550 
551   /**
552    * Reads a long value encoded by UTF-8 encoding
553    *
554    * @throws NumberFormatException if there is a problem with decoding
555    * @return Decoded long value
556    */
readUtf8EncodedLong()557   public long readUtf8EncodedLong() {
558     int length = 0;
559     long value = data[position];
560     // find the high most 0 bit
561     for (int j = 7; j >= 0; j--) {
562       if ((value & (1 << j)) == 0) {
563         if (j < 6) {
564           value &= (1 << j) - 1;
565           length = 7 - j;
566         } else if (j == 7) {
567           length = 1;
568         }
569         break;
570       }
571     }
572     if (length == 0) {
573       throw new NumberFormatException("Invalid UTF-8 sequence first byte: " + value);
574     }
575     for (int i = 1; i < length; i++) {
576       int x = data[position + i];
577       if ((x & 0xC0) != 0x80) { // if the high most 0 bit not 7th
578         throw new NumberFormatException("Invalid UTF-8 sequence continuation byte: " + value);
579       }
580       value = (value << 6) | (x & 0x3F);
581     }
582     position += length;
583     return value;
584   }
585 
586 }
587