/*
 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.management.counter.perf;

import sun.management.counter.*;
import java.nio.*;
import java.io.UnsupportedEncodingException;

class PerfDataEntry {
    private class EntryFieldOffset {
        private final static int SIZEOF_BYTE = 1;
        private final static int SIZEOF_INT  = 4;
        private final static int SIZEOF_LONG = 8;

        private final static int ENTRY_LENGTH_SIZE    = SIZEOF_INT;
        private final static int NAME_OFFSET_SIZE     = SIZEOF_INT;
        private final static int VECTOR_LENGTH_SIZE   = SIZEOF_INT;
        private final static int DATA_TYPE_SIZE       = SIZEOF_BYTE;
        private final static int FLAGS_SIZE           = SIZEOF_BYTE;
        private final static int DATA_UNIT_SIZE       = SIZEOF_BYTE;
        private final static int DATA_VAR_SIZE        = SIZEOF_BYTE;
        private final static int DATA_OFFSET_SIZE     = SIZEOF_INT;

        final static int ENTRY_LENGTH  = 0;
        final static int NAME_OFFSET   = ENTRY_LENGTH + ENTRY_LENGTH_SIZE;
        final static int VECTOR_LENGTH = NAME_OFFSET + NAME_OFFSET_SIZE;;
        final static int DATA_TYPE     = VECTOR_LENGTH + VECTOR_LENGTH_SIZE;
        final static int FLAGS         = DATA_TYPE + DATA_TYPE_SIZE;
        final static int DATA_UNIT     = FLAGS + FLAGS_SIZE;
        final static int DATA_VAR      = DATA_UNIT + DATA_UNIT_SIZE;
        final static int DATA_OFFSET   = DATA_VAR + DATA_VAR_SIZE;
    }

    private String       name;
    private int          entryStart;
    private int          entryLength;
    private int          vectorLength;
    private PerfDataType dataType;
    private int          flags;
    private Units        unit;
    private Variability  variability;
    private int          dataOffset;
    private int          dataSize;
    private ByteBuffer   data;

    PerfDataEntry(ByteBuffer b) {
        entryStart = b.position();
        entryLength = b.getInt();

        // check for valid entry length
        if (entryLength <= 0 || entryLength > b.limit()) {
            throw new InstrumentationException("Invalid entry length: " +
                                               " entryLength = " + entryLength);
        }
        // check if last entry occurs before the eof.
        if ((entryStart + entryLength) > b.limit()) {
            throw new InstrumentationException("Entry extends beyond end of buffer: " +
                                               " entryStart = " + entryStart +
                                               " entryLength = " + entryLength +
                                               " buffer limit = " + b.limit());
        }

        b.position(entryStart + EntryFieldOffset.NAME_OFFSET);
        int nameOffset = b.getInt();

        if ((entryStart + nameOffset) > b.limit()) {
            throw new InstrumentationException("Invalid name offset: " +
                                               " entryStart = " + entryStart +
                                               " nameOffset = " + nameOffset +
                                               " buffer limit = " + b.limit());
        }


        b.position(entryStart + EntryFieldOffset.VECTOR_LENGTH);
        vectorLength = b.getInt();

        b.position(entryStart + EntryFieldOffset.DATA_TYPE);
        dataType = PerfDataType.toPerfDataType(b.get());

        b.position(entryStart + EntryFieldOffset.FLAGS);
        flags = b.get();

        b.position(entryStart + EntryFieldOffset.DATA_UNIT);
        unit = Units.toUnits(b.get());

        b.position(entryStart + EntryFieldOffset.DATA_VAR);
        variability = Variability.toVariability(b.get());

        b.position(entryStart + EntryFieldOffset.DATA_OFFSET);
        dataOffset = b.getInt();

        // read in the perfData item name, casting bytes to chars. skip the
        // null terminator
        b.position(entryStart + nameOffset);
        // calculate the length of the name
        int nameLength = 0;
        byte c;
        for (; (c = b.get()) != (byte)0; nameLength++);

        byte[] symbolBytes = new byte[nameLength];
        b.position(entryStart + nameOffset);
        for (int i = 0; i < nameLength; i++) {
            symbolBytes[i] = b.get();
        }

        // convert name into a String
        try {
            name = new String(symbolBytes, "UTF-8");
        }
        catch (UnsupportedEncodingException e) {
            // should not reach here
            // "UTF-8" is always a known encoding
            throw new InternalError(e.getMessage());
        }

        if (variability == Variability.INVALID) {
            throw new InstrumentationException("Invalid variability attribute:" +
                                               " name = " + name);
        }
        if (unit == Units.INVALID) {
            throw new InstrumentationException("Invalid units attribute: " +
                                               " name = " + name);
        }

        if (vectorLength > 0) {
            dataSize = vectorLength * dataType.size();
        } else {
            dataSize = dataType.size();
        }

        // check if data beyond the eof.
        if ((entryStart + dataOffset + dataSize) > b.limit()) {
            throw new InstrumentationException("Data extends beyond end of buffer: " +
                                               " entryStart = " + entryStart +
                                               " dataOffset = " + dataOffset+
                                               " dataSize = " + dataSize +
                                               " buffer limit = " + b.limit());
        }
        // Construct a ByteBuffer for the data
        b.position(entryStart + dataOffset);
        data = b.slice();
        data.order(b.order());
        data.limit(dataSize);
    }


    public int size() {
        return entryLength;
    }

    public String name() {
        return name;
    }

    public PerfDataType type() {
        return dataType;
    }

    public Units units() {
        return unit;
    }

    public int flags() {
        return flags;
    }

    /**
     * Returns the number of elements in the data.
     */
    public int vectorLength() {
        return vectorLength;
    }

    public Variability variability() {
        return variability;
    }

    public ByteBuffer byteData() {
        data.position(0);
        assert data.remaining() == vectorLength();
        return data.duplicate();
    }

    public LongBuffer longData() {
        LongBuffer lb = data.asLongBuffer();
        return lb;
    }
}
