/* * Copyright (c) 2007, 2012, 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. * * 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 com.sun.max.tele.data; import java.nio.*; import com.sun.max.lang.*; import com.sun.max.tele.util.*; import com.sun.max.unsafe.*; import com.sun.max.vm.type.*; /** * An adapter for reading/writing bytes and other primitive data kinds from/to a source/destination * that can be identified by an {@link Address}. Subclasses implement only the most basic * read/write operations. */ public abstract class DataAccessAdapter implements DataAccess { private static final int BOOLEAN_SIZE = 1; private static final int FLOAT_SIZE = 4; private static final int DOUBLE_SIZE = 8; private final WordWidth wordWidth; public final ByteOrder byteOrder; protected DataAccessAdapter(WordWidth wordWidth, ByteOrder byteOrder) { this.wordWidth = wordWidth; this.byteOrder = byteOrder; } public void readFully(Address address, ByteBuffer buffer) { DataIO.Static.readFully(this, address, buffer); } public byte[] readFully(Address address, int length) { return DataIO.Static.readFully(this, address, length); } public void readFully(Address address, byte[] buffer) { DataIO.Static.readFully(this, address, ByteBuffer.wrap(buffer)); } public byte readByte(Address address, Offset offset) { return readByte(address.plus(offset)); } public byte readByte(Address address, int offset) { return readByte(address.plus(offset)); } public byte getByte(Address address, int displacement, int index) { return readByte(address.plus(displacement).plus(index * Bytes.SIZE)); } public boolean readBoolean(Address address) { return readByte(address) != (byte) 0; } public boolean readBoolean(Address address, Offset offset) { return readBoolean(address.plus(offset)); } public boolean readBoolean(Address address, int offset) { return readBoolean(address.plus(offset)); } public boolean getBoolean(Address address, int displacement, int index) { return readBoolean(address.plus(displacement).plus(index * BOOLEAN_SIZE)); } public short readShort(Address address, Offset offset) { return readShort(address.plus(offset)); } public short readShort(Address address, int offset) { return readShort(address.plus(offset)); } public short getShort(Address address, int displacement, int index) { return readShort(address.plus(displacement).plus(index * Shorts.SIZE)); } public char readChar(Address address) { return UnsafeCast.asChar(readShort(address)); } public char readChar(Address address, Offset offset) { return readChar(address.plus(offset)); } public char readChar(Address address, int offset) { return readChar(address.plus(offset)); } public char getChar(Address address, int displacement, int index) { return readChar(address.plus(displacement).plus(index * Chars.SIZE)); } public int readInt(Address address, Offset offset) { return readInt(address.plus(offset)); } public int readInt(Address address, int offset) { return readInt(address.plus(offset)); } public int getInt(Address address, int displacement, int index) { return readInt(address.plus(displacement).plus(index * Ints.SIZE)); } public float readFloat(Address address) { return Float.intBitsToFloat(readInt(address)); } public float readFloat(Address address, Offset offset) { return readFloat(address.plus(offset)); } public float readFloat(Address address, int offset) { return readFloat(address.plus(offset)); } public float getFloat(Address address, int displacement, int index) { return readFloat(address.plus(displacement).plus(index * FLOAT_SIZE)); } public long readLong(Address address, Offset offset) { return readLong(address.plus(offset)); } public long readLong(Address address, int offset) { return readLong(address.plus(offset)); } public long getLong(Address address, int displacement, int index) { return readLong(address.plus(displacement).plus(index * Longs.SIZE)); } public double readDouble(Address address) { return Double.longBitsToDouble(readLong(address)); } public double readDouble(Address address, Offset offset) { return readDouble(address.plus(offset)); } public double readDouble(Address address, int offset) { return readDouble(address.plus(offset)); } public double getDouble(Address address, int displacement, int index) { return readDouble(address.plus(displacement).plus(index * DOUBLE_SIZE)); } public Word readWord(Address address) { switch (wordWidth) { case BITS_32: return Offset.fromInt(readInt(address)); case BITS_64: return Offset.fromLong(readLong(address)); default: throw TeleError.unexpected(); } } public Word readWord(Address address, Offset offset) { return readWord(address.plus(offset)); } public Word readWord(Address address, int offset) { return readWord(address.plus(offset)); } public Word getWord(Address address, int displacement, int index) { return readWord(address.plus(displacement).plus(index * wordWidth.numberOfBytes)); } public void writeBuffer(Address address, ByteBuffer buffer) { final int length = buffer.capacity(); final int bytesWritten = write(buffer, 0, length, address); if (bytesWritten < 0) { throw new DataIOError(address); } if (bytesWritten != length) { throw new DataIOError(address, (length - bytesWritten) + " of " + length + " bytes unwritten"); } } public void writeBytes(Address address, byte[] bytes) { writeBuffer(address, ByteBuffer.wrap(bytes)); } public void writeByte(Address address, Offset offset, byte value) { writeByte(address.plus(offset), value); } public void writeByte(Address address, int offset, byte value) { writeByte(address.plus(offset), value); } public void setByte(Address address, int displacement, int index, byte value) { writeByte(address.plus(displacement).plus(index * Bytes.SIZE), value); } public void writeBoolean(Address address, boolean value) { writeByte(address, value ? (byte) 1 : (byte) 0); } public void writeBoolean(Address address, Offset offset, boolean value) { writeBoolean(address.plus(offset), value); } public void writeBoolean(Address address, int offset, boolean value) { writeBoolean(address.plus(offset), value); } public void setBoolean(Address address, int displacement, int index, boolean value) { writeBoolean(address.plus(displacement).plus(index * BOOLEAN_SIZE), value); } public void writeShort(Address address, Offset offset, short value) { writeShort(address.plus(offset), value); } public void writeShort(Address address, int offset, short value) { writeShort(address.plus(offset), value); } public void setShort(Address address, int displacement, int index, short value) { writeShort(address.plus(displacement).plus(index * Shorts.SIZE), value); } public void writeChar(Address address, char value) { writeShort(address, UnsafeCast.asShort(value)); } public void writeChar(Address address, Offset offset, char value) { writeChar(address.plus(offset), value); } public void writeChar(Address address, int offset, char value) { writeChar(address.plus(offset), value); } public void setChar(Address address, int displacement, int index, char value) { writeChar(address.plus(displacement).plus(index * Chars.SIZE), value); } public void writeInt(Address address, Offset offset, int value) { writeInt(address.plus(offset), value); } public void writeInt(Address address, int offset, int value) { writeInt(address.plus(offset), value); } public void setInt(Address address, int displacement, int index, int value) { writeInt(address.plus(displacement).plus(index * Ints.SIZE), value); } public void writeFloat(Address address, float value) { writeInt(address, Float.floatToRawIntBits(value)); } public void writeFloat(Address address, Offset offset, float value) { writeFloat(address.plus(offset), value); } public void writeFloat(Address address, int offset, float value) { writeFloat(address.plus(offset), value); } public void setFloat(Address address, int displacement, int index, float value) { writeFloat(address.plus(displacement).plus(index * FLOAT_SIZE), value); } public void writeLong(Address address, Offset offset, long value) { writeLong(address.plus(offset), value); } public void writeLong(Address address, int offset, long value) { writeLong(address.plus(offset), value); } public void setLong(Address address, int displacement, int index, long value) { writeLong(address.plus(displacement).plus(index * Longs.SIZE), value); } public void writeDouble(Address address, double value) { writeLong(address, Double.doubleToRawLongBits(value)); } public void writeDouble(Address address, Offset offset, double value) { writeDouble(address.plus(offset), value); } public void writeDouble(Address address, int offset, double value) { writeDouble(address.plus(offset), value); } public void setDouble(Address address, int displacement, int index, double value) { writeDouble(address.plus(displacement).plus(index * DOUBLE_SIZE), value); } public void writeWord(Address address, Word value) { switch (wordWidth) { case BITS_32: writeInt(address, value.asOffset().toInt()); break; case BITS_64: writeLong(address, value.asOffset().toLong()); break; default: throw TeleError.unexpected(); } } public void writeWord(Address address, Offset offset, Word value) { writeWord(address.plus(offset), value); } public void writeWord(Address address, int offset, Word value) { writeWord(address.plus(offset), value); } public void setWord(Address address, int displacement, int index, Word value) { writeWord(address.plus(displacement).plus(index * wordWidth.numberOfBytes), value); } // Checkstyle: stop public synchronized void copyElements(Address address, int displacement, int srcIndex, Object dst, int dstIndex, int length) { Kind kind = Kind.fromJava(dst.getClass().getComponentType()); int size = length * kind.width.numberOfBytes; ByteBuffer byteBuffer = ByteBuffer.allocate(size); Static.readFully(this, address.plus(displacement + srcIndex * kind.width.numberOfBytes), byteBuffer); byteBuffer.order(byteOrder); byteBuffer.position(0); switch (kind.asEnum) { case BOOLEAN: { boolean[] arr = (boolean[]) dst; for (int i = 0; i < length; ++i) { arr[dstIndex + i] = byteBuffer.get(i) != 0; } break; } case BYTE: byteBuffer.get((byte[]) dst, dstIndex, length); break; case CHAR: byteBuffer.asCharBuffer().get((char[]) dst, dstIndex, length); break; case SHORT: byteBuffer.asShortBuffer().get((short[]) dst, dstIndex, length); break; case INT: byteBuffer.asIntBuffer().get((int[]) dst, dstIndex, length); break; case FLOAT: byteBuffer.asFloatBuffer().get((float[]) dst, dstIndex, length); break; case LONG: byteBuffer.asLongBuffer().get((long[]) dst, dstIndex, length); break; case DOUBLE: byteBuffer.asDoubleBuffer().get((double[]) dst, dstIndex, length); break; case WORD: { if (wordWidth == WordWidth.BITS_32) { IntBuffer intBuffer = byteBuffer.asIntBuffer(); Word[] arr = (Word[]) dst; for (int i = 0; i < length; ++i) { WordArray.set(arr, dstIndex + i, Offset.fromInt(intBuffer.get())); } } else if (wordWidth == WordWidth.BITS_64) { LongBuffer longBuffer = byteBuffer.asLongBuffer(); Word[] arr = (Word[]) dst; for (int i = 0; i < length; ++i) { WordArray.set(arr, dstIndex + i, Offset.fromLong(longBuffer.get())); } } else { throw TeleError.unexpected(); } break; } default: throw TeleError.unexpected("invalid type"); } } // Checkstyle: resume }