ByteBufferReader.java revision fa04a81daf829e6e5c099c9a249b8dd8dd112102
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.Wifi
15 */
16
17package com.android.server.wifi;
18
19import com.android.internal.annotations.VisibleForTesting;
20
21import java.nio.BufferUnderflowException;
22import java.nio.ByteBuffer;
23import java.nio.ByteOrder;
24import java.nio.charset.Charset;
25
26/**
27 * Utility class for reading generic data (e.g. various length integer, string) from ByteBuffer.
28 */
29public class ByteBufferReader {
30    @VisibleForTesting
31    public static final int MINIMUM_INTEGER_SIZE = Byte.BYTES;
32
33    @VisibleForTesting
34    public static final int MAXIMUM_INTEGER_SIZE = Long.BYTES;
35
36    /**
37     * Read an integer value from a buffer.
38     *
39     * @param payload The buffer to read from
40     * @param byteOrder Byte order of the buffer
41     * @param size The number of bytes to read from the buffer
42     * @return The integer value
43     * @throws BufferUnderflowException
44     * @throws IllegalArgumentException
45     */
46    public static long readInteger(ByteBuffer payload, ByteOrder byteOrder, int size) {
47        if (size < MINIMUM_INTEGER_SIZE || size > MAXIMUM_INTEGER_SIZE) {
48            throw new IllegalArgumentException("Invalid size " + size);
49        }
50
51        // Read the necessary bytes.
52        byte[] octets = new byte[size];
53        payload.get(octets);
54
55        // Format the value based on byte order.
56        long value = 0;
57        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
58            for (int n = octets.length - 1; n >= 0; n--) {
59                value = (value << Byte.SIZE) | (octets[n] & 0xFF);
60            }
61        } else {
62            for (byte octet : octets) {
63                value = (value << Byte.SIZE) | (octet & 0xFF);
64            }
65        }
66        return value;
67    }
68
69    /**
70     * Read a string from a buffer. An empty String will be returned for a String with 0 length.
71     *
72     * @param payload The buffer to read from
73     * @param length Number of bytes to read from the buffer
74     * @param charset The character set of the string
75     * @return {@link String}
76     * @throws BufferUnderflowException
77     * @throws NegativeArraySizeException
78     */
79    public static String readString(ByteBuffer payload, int length, Charset charset) {
80        byte[] octets = new byte[length];
81        payload.get(octets);
82        return new String(octets, charset);
83    }
84
85    /**
86     * Read a string from a buffer where the string value is preceded by the length of the string
87     * (1 byte) in the buffer.
88     *
89     * @param payload The buffer to read from
90     * @param charset The character set of the string
91     * @return {@link String}
92     * @throws BufferUnderflowException
93     */
94    public static String readStringWithByteLength(ByteBuffer payload, Charset charset) {
95        int length = payload.get() & 0xFF;
96        return readString(payload, length, charset);
97    }
98}
99