/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
// BEGIN android-note
// address length was changed from long to int for performance reasons.
// END android-note
package org.apache.harmony.luni.platform;
/**
* The platform address class is an unsafe virtualization of an OS memory block.
*
*/
public class PlatformAddress implements ICommonDataTypes, Comparable {
/**
* This final field defines the size of an address on this platform.
*/
static final int SIZEOF = Platform.getMemorySystem().getPointerSize();
/**
* NULL is the canonical address with address value zero.
*/
public static final PlatformAddress NULL = new PlatformAddress(0, 0);
public static final IMemorySpy memorySpy = new RuntimeMemorySpy();
static final IMemorySystem osMemory = Platform.getMemorySystem();
static final long UNKNOWN = -1;
final int osaddr;
final long size;
PlatformAddress(int address, long size) {
super();
osaddr = address;
this.size = size;
}
/**
* Sending auto free to an address means that, when this subsystem has
* allocated the memory, it will automatically be freed when this object is
* collected by the garbage collector if the memory has not already been
* freed explicitly.
*
*/
public final void autoFree() {
memorySpy.autoFree(this);
}
public PlatformAddress duplicate(){
return PlatformAddressFactory.on(osaddr, size);
}
public PlatformAddress offsetBytes(int offset) {
return PlatformAddressFactory.on(osaddr + offset, size - offset);
}
// BEGIN android-removed
// public PlatformAddress offsetBytes(long offset) {
// return PlatformAddressFactory.on(osaddr + offset, size - offset);
// }
// END android-removed
public final void moveTo(PlatformAddress dest, long numBytes) {
osMemory.memmove(dest.osaddr, osaddr, numBytes);
}
public final boolean equals(Object other) {
return (other instanceof PlatformAddress)
&& (((PlatformAddress) other).osaddr == osaddr);
}
public final int hashCode() {
return (int) osaddr;
}
public final boolean isNULL() {
return this == NULL;
}
public void free() {
// Memory spys can veto the basic free if they determine the memory was
// not allocated.
if (memorySpy.free(this)) {
osMemory.free(osaddr);
}
}
public final void setAddress(int offset, PlatformAddress address) {
osMemory.setAddress(osaddr + offset, address.osaddr);
}
public final PlatformAddress getAddress(int offset) {
int addr = getInt(offset);
return PlatformAddressFactory.on(addr);
}
public final void setByte(int offset, byte value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JBYTE);
osMemory.setByte(osaddr + offset, value);
}
public final void setByteArray(int offset, byte[] bytes, int bytesOffset,
int length) {
memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE);
osMemory.setByteArray(osaddr + offset, bytes, bytesOffset, length);
}
// BEGIN android-added
public final void setShortArray(int offset, short[] shorts,
int shortsOffset, int length, boolean swap) {
memorySpy.rangeCheck(this, offset, length * SIZEOF_JSHORT);
osMemory.setShortArray(osaddr + offset, shorts, shortsOffset, length,
swap);
}
public final void setIntArray(int offset, int[] ints,
int intsOffset, int length, boolean swap) {
memorySpy.rangeCheck(this, offset, length * SIZEOF_JINT);
osMemory.setIntArray(osaddr + offset, ints, intsOffset, length, swap);
}
// END android-added
public final byte getByte(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JBYTE);
return osMemory.getByte(osaddr + offset);
}
public final void getByteArray(int offset, byte[] bytes, int bytesOffset,
int length) {
memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE);
osMemory.getByteArray(osaddr + offset, bytes, bytesOffset, length);
}
public final void setShort(int offset, short value, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JSHORT);
osMemory.setShort(osaddr + offset, value, order);
}
public final void setShort(int offset, short value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JSHORT);
osMemory.setShort(osaddr + offset, value);
}
public final short getShort(int offset, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JSHORT);
return osMemory.getShort(osaddr + offset, order);
}
public final short getShort(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JSHORT);
return osMemory.getShort(osaddr + offset);
}
public final void setInt(int offset, int value, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JINT);
osMemory.setInt(osaddr + offset, value, order);
}
public final void setInt(int offset, int value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JINT);
osMemory.setInt(osaddr + offset, value);
}
public final int getInt(int offset, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JINT);
return osMemory.getInt(osaddr + offset, order);
}
public final int getInt(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JINT);
return osMemory.getInt(osaddr + offset);
}
public final void setLong(int offset, long value, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JLONG);
osMemory.setLong(osaddr + offset, value, order);
}
public final void setLong(int offset, long value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JLONG);
osMemory.setLong(osaddr + offset, value);
}
public final long getLong(int offset, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JLONG);
return osMemory.getLong(osaddr + offset, order);
}
public final long getLong(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JLONG);
return osMemory.getLong(osaddr + offset);
}
public final void setFloat(int offset, float value, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JFLOAT);
osMemory.setFloat(osaddr + offset, value, order);
}
public final void setFloat(int offset, float value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JFLOAT);
osMemory.setFloat(osaddr + offset, value);
}
public final float getFloat(int offset, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JFLOAT);
return osMemory.getFloat(osaddr + offset, order);
}
public final float getFloat(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JFLOAT);
return osMemory.getFloat(osaddr + offset);
}
public final void setDouble(int offset, double value, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JDOUBLE);
osMemory.setDouble(osaddr + offset, value, order);
}
public final void setDouble(int offset, double value) {
memorySpy.rangeCheck(this, offset, SIZEOF_JDOUBLE);
osMemory.setDouble(osaddr + offset, value);
}
public final double getDouble(int offset, Endianness order) {
memorySpy.rangeCheck(this, offset, SIZEOF_JDOUBLE);
return osMemory.getDouble(osaddr + offset, order);
}
public final double getDouble(int offset) {
memorySpy.rangeCheck(this, offset, SIZEOF_JDOUBLE);
return osMemory.getDouble(osaddr + offset);
}
// BEGIN android-added
public final int toInt() {
return osaddr;
}
// END android-added
public final long toLong() {
return osaddr;
}
public final String toString() {
return "PlatformAddress[" + osaddr + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
public final long getSize(){
return size;
}
public final int compareTo(Object other) {
if (other == null) {
throw new NullPointerException(); // per spec.
}
if (other instanceof PlatformAddress) {
int otherPA = ((PlatformAddress) other).osaddr;
if (osaddr == otherPA) {
return 0;
}
return osaddr < otherPA ? -1 : 1;
}
throw new ClassCastException(); // per spec.
}
}