blob: 1f9bb96410bb46ce04b79179b1091101ea008f5f [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed 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.
*/
package com.android.ahat.heapdump;
import java.util.Objects;
/**
* A Java instance or primitive value from a parsed heap dump.
* Note: To save memory, a null Value is used to represent a null Java
* instance from the heap dump.
*/
public abstract class Value {
Value() { }
/**
* Constructs a Value for an AhatInstance.
* Note: returns null for null <code>value</code>.
*
* @param value the AhatInstance to make into a value
* @return the constructed value.
*/
public static Value pack(AhatInstance value) {
return value == null ? null : new InstanceValue(value);
}
/**
* Constructs a Value for a boolean.
*
* @param value the boolean to make into a value
* @return the constructed value.
*/
public static Value pack(boolean value) {
return new BooleanValue(value);
}
/**
* Constructs a Value for a char.
*
* @param value the char to make into a value
* @return the constructed value.
*/
public static Value pack(char value) {
return new CharValue(value);
}
/**
* Constructs a Value for a float.
*
* @param value the float to make into a value
* @return the constructed value.
*/
public static Value pack(float value) {
return new FloatValue(value);
}
/**
* Constructs a Value for a double.
*
* @param value the double to make into a value
* @return the constructed value.
*/
public static Value pack(double value) {
return new DoubleValue(value);
}
/**
* Constructs a Value for a byte.
*
* @param value the byte to make into a value
* @return the constructed value.
*/
public static Value pack(byte value) {
return new ByteValue(value);
}
/**
* Constructs a Value for a short.
*
* @param value the short to make into a value
* @return the constructed value.
*/
public static Value pack(short value) {
return new ShortValue(value);
}
/**
* Constructs a Value for a int.
*
* @param value the int to make into a value
* @return the constructed value.
*/
public static Value pack(int value) {
return new IntValue(value);
}
/**
* Constructs a Value for a long.
*
* @param value the long to make into a value
* @return the constructed value.
*/
public static Value pack(long value) {
return new LongValue(value);
}
/**
* Returns the type of the given value.
*
* @param value the value to get the type of
* @return the value's type
*/
public static Type getType(Value value) {
return value == null ? Type.OBJECT : value.getType();
}
/**
* Return the type of the given value.
*/
abstract Type getType();
/**
* Returns true if the Value is an AhatInstance rather than a primitive
* value.
*
* @return true if the value is an AhatInstance
*/
public boolean isAhatInstance() {
return false;
}
/**
* Returns the Value as an AhatInstance if it is one.
* Returns null if the Value represents a Java primitive value.
*
* @return the AhatInstance packed into this value
*/
public AhatInstance asAhatInstance() {
return null;
}
/**
* Returns true if the Value is an int.
*
* @return true if the value is an int.
*/
public boolean isInteger() {
return false;
}
/**
* Returns the Value as an int if it is one.
* Returns null if the Value does not represent an int.
*
* @return the int packed into this value
*/
public Integer asInteger() {
return null;
}
/**
* Returns true if the Value is an long.
*
* @return true if the value is an long.
*/
public boolean isLong() {
return false;
}
/**
* Returns the Value as an long if it is one.
* Returns null if the Value does not represent an long.
*
* @return the long packed into this value
*/
public Long asLong() {
return null;
}
/**
* Returns the Value as an byte if it is one.
* Returns null if the Value does not represent an byte.
*
* @return the byte packed into this value
*/
public Byte asByte() {
return null;
}
/**
* Returns the Value as an char if it is one.
* Returns null if the Value does not represent an char.
*
* @return the char packed into this value
*/
public Character asChar() {
return null;
}
@Override
public abstract String toString();
Value getBaseline() {
return this;
}
/**
* Returns the baseline of the given value for the purposes of diff.
* This method can be used to handle the case when the Value is null.
*
* @param value the value to get the baseline of
* @return the baseline of the value
* @see Diffable#getBaseline
*/
public static Value getBaseline(Value value) {
return value == null ? null : value.getBaseline();
}
@Override
public abstract int hashCode();
@Override
public abstract boolean equals(Object other);
private static class BooleanValue extends Value {
private boolean mBool;
BooleanValue(boolean bool) {
mBool = bool;
}
@Override
Type getType() {
return Type.BOOLEAN;
}
@Override
public String toString() {
return Boolean.toString(mBool);
}
@Override public int hashCode() {
return Objects.hash(mBool);
}
@Override public boolean equals(Object other) {
if (other instanceof BooleanValue) {
BooleanValue value = (BooleanValue)other;
return mBool == value.mBool;
}
return false;
}
}
private static class ByteValue extends Value {
private byte mByte;
ByteValue(byte b) {
mByte = b;
}
@Override
public Byte asByte() {
return mByte;
}
@Override
Type getType() {
return Type.BYTE;
}
@Override
public String toString() {
return Byte.toString(mByte);
}
@Override public int hashCode() {
return Objects.hash(mByte);
}
@Override public boolean equals(Object other) {
if (other instanceof ByteValue) {
ByteValue value = (ByteValue)other;
return mByte == value.mByte;
}
return false;
}
}
private static class CharValue extends Value {
private char mChar;
CharValue(char c) {
mChar = c;
}
@Override
public Character asChar() {
return mChar;
}
@Override
Type getType() {
return Type.CHAR;
}
@Override
public String toString() {
return Character.toString(mChar);
}
@Override public int hashCode() {
return Objects.hash(mChar);
}
@Override public boolean equals(Object other) {
if (other instanceof CharValue) {
CharValue value = (CharValue)other;
return mChar == value.mChar;
}
return false;
}
}
private static class DoubleValue extends Value {
private double mDouble;
DoubleValue(double d) {
mDouble = d;
}
@Override
Type getType() {
return Type.DOUBLE;
}
@Override
public String toString() {
return Double.toString(mDouble);
}
@Override public int hashCode() {
return Objects.hash(mDouble);
}
@Override public boolean equals(Object other) {
if (other instanceof DoubleValue) {
DoubleValue value = (DoubleValue)other;
return mDouble == value.mDouble;
}
return false;
}
}
private static class FloatValue extends Value {
private float mFloat;
FloatValue(float f) {
mFloat = f;
}
@Override
Type getType() {
return Type.FLOAT;
}
@Override
public String toString() {
return Float.toString(mFloat);
}
@Override public int hashCode() {
return Objects.hash(mFloat);
}
@Override public boolean equals(Object other) {
if (other instanceof FloatValue) {
FloatValue value = (FloatValue)other;
return mFloat == value.mFloat;
}
return false;
}
}
private static class InstanceValue extends Value {
private AhatInstance mInstance;
InstanceValue(AhatInstance inst) {
assert(inst != null);
mInstance = inst;
}
@Override
public boolean isAhatInstance() {
return true;
}
@Override
public AhatInstance asAhatInstance() {
return mInstance;
}
@Override
Type getType() {
return Type.OBJECT;
}
@Override
public String toString() {
return mInstance.toString();
}
@Override
Value getBaseline() {
return InstanceValue.pack(mInstance.getBaseline());
}
@Override public int hashCode() {
return Objects.hash(mInstance);
}
@Override public boolean equals(Object other) {
if (other instanceof InstanceValue) {
InstanceValue value = (InstanceValue)other;
return mInstance.equals(value.mInstance);
}
return false;
}
}
private static class IntValue extends Value {
private int mInt;
IntValue(int i) {
mInt = i;
}
@Override
public boolean isInteger() {
return true;
}
@Override
public Integer asInteger() {
return mInt;
}
@Override
Type getType() {
return Type.INT;
}
@Override
public String toString() {
return Integer.toString(mInt);
}
@Override public int hashCode() {
return Objects.hash(mInt);
}
@Override public boolean equals(Object other) {
if (other instanceof IntValue) {
IntValue value = (IntValue)other;
return mInt == value.mInt;
}
return false;
}
}
private static class LongValue extends Value {
private long mLong;
LongValue(long l) {
mLong = l;
}
@Override
public boolean isLong() {
return true;
}
@Override
public Long asLong() {
return mLong;
}
@Override
Type getType() {
return Type.LONG;
}
@Override
public String toString() {
return Long.toString(mLong);
}
@Override public int hashCode() {
return Objects.hash(mLong);
}
@Override public boolean equals(Object other) {
if (other instanceof LongValue) {
LongValue value = (LongValue)other;
return mLong == value.mLong;
}
return false;
}
}
private static class ShortValue extends Value {
private short mShort;
ShortValue(short s) {
mShort = s;
}
@Override
Type getType() {
return Type.SHORT;
}
@Override
public String toString() {
return Short.toString(mShort);
}
@Override public int hashCode() {
return Objects.hash(mShort);
}
@Override public boolean equals(Object other) {
if (other instanceof ShortValue) {
ShortValue value = (ShortValue)other;
return mShort == value.mShort;
}
return false;
}
}
}