/*
 * Copyright 2003-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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;
    }
}
