blob: a1d884ec7f04eaf9db6713525c0e0432df7616cc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2016 Intel Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Intel Corporation - Initial API and implementation
* Mark Mitchell, CodeSourcery - Bug 136896: View variables in binary format
* Mathias Kunter - Bug 370462: View variables in octal format
*******************************************************************************/
package org.eclipse.cdt.utils;
import java.io.Serializable;
import java.math.BigInteger;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.internal.core.Messages;
public class Addr32 implements IAddress, Serializable {
private static final long MAX_ADDR = 0xffffffffL;
public static final Addr32 ZERO = new Addr32(0);
public static final Addr32 MAX = new Addr32(MAX_ADDR);
public static final BigInteger MAX_OFFSET = BigInteger.valueOf(MAX_ADDR);
private static final int BYTES_NUM = 4;
private static final int DIGITS_NUM = BYTES_NUM * 2;
private static final int CHARS_NUM = DIGITS_NUM + 2;
private static final int OCTAL_DIGITS_NUM = (BYTES_NUM * 8 + 2) / 3;
private static final int OCTAL_CHARS_NUM = OCTAL_DIGITS_NUM + 1;
private static final int BINARY_DIGITS_NUM = BYTES_NUM * 8;
private static final int BINARY_CHARS_NUM = BINARY_DIGITS_NUM + 2;
private final long address;
/*
* addrBytes should be 4 bytes length
*/
public Addr32(byte[] addrBytes) {
if (addrBytes.length != 4)
throw (new NumberFormatException("Invalid address array")); //$NON-NLS-1$
/* We should mask out sign bits to have correct value */
this.address = ((((long) addrBytes[0]) << 24) & 0xFF000000L) + ((((long) addrBytes[1]) << 16) & 0x00FF0000L)
+ ((((long) addrBytes[2]) << 8) & 0x0000FF00L) + (addrBytes[3] & 0x000000FFL);
}
public Addr32(long rawaddress) {
this(rawaddress, true);
}
public Addr32(long rawaddress, boolean truncate) {
if (rawaddress > MAX_ADDR || rawaddress < 0) {
if (truncate) {
rawaddress &= MAX_ADDR; // truncate
} else {
throw (new NumberFormatException(Messages.Addr_valueOutOfRange));
}
}
this.address = rawaddress;
}
public Addr32(String addr) {
this(addr, true);
}
public Addr32(String addr, boolean truncate) {
this(Long.decode(addr).longValue(), truncate);
}
public Addr32(String addr, int radix) {
this(addr, radix, true);
}
public Addr32(String addr, int radix, boolean truncate) {
this(Long.parseLong(addr, radix), truncate);
}
@Override
public IAddress add(BigInteger offset) {
return new Addr32(this.address + offset.longValue());
}
@Override
public IAddress add(long offset) {
return new Addr32(this.address + offset);
}
@Override
public BigInteger getMaxOffset() {
return MAX_OFFSET;
}
@Override
public BigInteger getValue() {
return BigInteger.valueOf(address);
}
@Override
public BigInteger distanceTo(IAddress other) {
return other.getValue().subtract(getValue());
}
@Override
public int compareTo(Object other) {
if (!(other instanceof IAddress)) {
throw new IllegalArgumentException();
}
return getValue().compareTo(((IAddress) other).getValue());
}
@Override
public boolean isMax() {
return address == MAX.address;
}
@Override
public boolean isZero() {
return address == ZERO.address;
}
@Override
public String toString() {
return toString(10);
}
@Override
public String toString(int radix) {
return Long.toString(address, radix);
}
@Override
public boolean equals(Object x) {
if (x == this)
return true;
if (!(x instanceof IAddress))
return false;
return getValue().equals(((IAddress) x).getValue());
}
@Override
public int hashCode() {
return (int) (address ^ (address >> 32));
}
@Override
public String toHexAddressString() {
String addressString = Long.toString(address, 16);
StringBuilder sb = new StringBuilder(CHARS_NUM);
int count = DIGITS_NUM - addressString.length();
sb.append("0x"); //$NON-NLS-1$
for (int i = 0; i < count; ++i) {
sb.append('0');
}
sb.append(addressString);
return sb.toString();
}
/**
* @since 5.4
*/
public String toOctalAddressString() {
String addressString = Long.toString(address, 8);
StringBuilder sb = new StringBuilder(OCTAL_CHARS_NUM);
int count = OCTAL_DIGITS_NUM - addressString.length();
sb.append("0"); //$NON-NLS-1$
for (int i = 0; i < count; ++i) {
sb.append('0');
}
sb.append(addressString);
return sb.toString();
}
@Override
public String toBinaryAddressString() {
String addressString = Long.toString(address, 2);
StringBuilder sb = new StringBuilder(BINARY_CHARS_NUM);
int count = BINARY_DIGITS_NUM - addressString.length();
sb.append("0b"); //$NON-NLS-1$
for (int i = 0; i < count; ++i) {
sb.append('0');
}
sb.append(addressString);
return sb.toString();
}
@Override
public int getCharsNum() {
return CHARS_NUM;
}
@Override
public int getSize() {
return BYTES_NUM;
}
}