/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;

public class Main {
    public static void main(String[] args) {
        ByteBuffer buf = ByteBuffer.allocateDirect(16);
        System.out.println("Direct byte buffer has array: " + buf.hasArray());

        intFloatTest();
        basicShortTest();
        primTest();
    }

    /*
     * Create a buffer and fiddle with it.
     */
    public static void basicShortTest() {
        ByteBuffer directBuf = ByteBuffer.allocateDirect(64);
        //ByteBuffer directBuf = ByteBuffer.allocateDirect(65);

        ShortBuffer shortBuf = directBuf.asShortBuffer();

        short[] myShorts = {
            1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
            1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015,
            1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
            1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031
        };

        ((Buffer) shortBuf).position(0);
        shortBuf.put(myShorts, 0, 32);      // should work
        ((Buffer) shortBuf).position(0);
        shortBuf.put(myShorts, 16, 16);     // should work
        shortBuf.put(myShorts, 16, 16);     // advance to end

        try {
            shortBuf.put(myShorts, 0, 1);     // should fail
            System.out.println("ERROR: out-of-bounds put succeeded\n");
        } catch (BufferOverflowException boe) {
            System.out.println("Got expected buffer overflow exception");
        }

        try {
            ((Buffer) shortBuf).position(0);
            shortBuf.put(myShorts, 0, 33);     // should fail
            System.out.println("ERROR: out-of-bounds put succeeded\n");
        } catch (IndexOutOfBoundsException ioobe) {
            System.out.println("Got expected out-of-bounds exception");
        }

        try {
            ((Buffer) shortBuf).position(16);
            shortBuf.put(myShorts, 0, 17);     // should fail
            System.out.println("ERROR: out-of-bounds put succeeded\n");
        } catch (BufferOverflowException boe) {
            System.out.println("Got expected buffer overflow exception");
        }
    }

    /*
     * Try this with either floats or ints; ints fail with
     * BufferOverflowException, floats work.
     *
     * From http://code.google.com/p/android/issues/detail?id=1585 .
     */
    public static void intFloatTest() {
        ByteBuffer direct = ByteBuffer.allocateDirect(100);
        direct.order(ByteOrder.nativeOrder());
        IntBuffer int1 = direct.asIntBuffer();
        int data[] = new int[25];
        //FloatBuffer int1 = direct.asFloatBuffer();
        //float data[] = new float[25];
        ((Buffer) int1).clear();
        int1.put(data);
        ((Buffer) int1).position(0);

        ((Buffer) int1).clear();
        int1.put (data);
        ((Buffer) int1).position(0);
    }

    /*
     * Exercise all "view buffer" classes, in both byte orders.
     */
    public static void primTest() {
        ByteBuffer directBuf = ByteBuffer.allocateDirect(36);
        directBuf.order(ByteOrder.BIG_ENDIAN);
        storeValues(directBuf);

        for (int i = 0; i < 36; i++) {
            directBuf.put(i, (byte) 0xcc);
        }

        directBuf.order(ByteOrder.LITTLE_ENDIAN);
        storeValues(directBuf);
    }

    static void storeValues(ByteBuffer directBuf) {
        ((Buffer) directBuf).position(0);
        ShortBuffer shortBuf = directBuf.asShortBuffer();
        CharBuffer charBuf = directBuf.asCharBuffer();
        IntBuffer intBuf = directBuf.asIntBuffer();
        FloatBuffer floatBuf = directBuf.asFloatBuffer();
        LongBuffer longBuf = directBuf.asLongBuffer();
        DoubleBuffer doubleBuf = directBuf.asDoubleBuffer();

        final byte byteValue = -5;
        final short shortValue = -1234;
        final char charValue = 49200;
        final int intValue = 0x12345678;
        final float floatValue = 3.14159f;
        final long longValue = 0x1122334455667788L;
        final double doubleValue = Double.MIN_VALUE;

        if (directBuf.put(1, byteValue).get(1) != byteValue) {
            throw new RuntimeException("byte get/store failed");
        }
        if (shortBuf.put(1, shortValue).get(1) != shortValue) {
            throw new RuntimeException("short get/store failed");
        }
        if (charBuf.put(2, charValue).get(2) != charValue) {
            throw new RuntimeException("char get/store failed");
        }
        if (intBuf.put(2, intValue).get(2) != intValue) {
            throw new RuntimeException("int get/store failed");
        }
        if (floatBuf.put(3, floatValue).get(3) != floatValue) {
            throw new RuntimeException("float get/store failed");
        }
        if (longBuf.put(2, longValue).get(2) != longValue) {
            throw new RuntimeException("long get/store failed");
        }
        if (doubleBuf.put(3, doubleValue).get(3) != doubleValue) {
            throw new RuntimeException("double get/store failed");
        }

        ((Buffer) directBuf).position(0);
        char[] outBuf = new char[directBuf.limit() * 2];
        for (int i = 0; i < directBuf.limit(); i++) {
            byte b = directBuf.get();
            outBuf[i*2] = hexChar((byte) ((b >> 4) & 0x0f));
            outBuf[i*2+1] = hexChar((byte) (b & 0x0f));
        }
        System.out.println(new String(outBuf));
    }

    static char hexChar(byte b) {
        if (b < 10) {
            return (char) ('0' + b);
        } else {
            return (char) ('a' + b - 10);
        }
    }
}
