/*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableType;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.core.runtime.CoreException;
/**
* Built-in c++ type.
*/
public class CPPBasicType implements ICPPBasicType, ISerializableType {
public static final CPPBasicType BOOLEAN = new CPPBasicType(Kind.eBoolean, 0, null);
private final Kind fKind;
private final int fModifiers;
private IASTExpression fExpression;
public CPPBasicType(Kind kind, int qualifiers, IASTExpression expression) {
if (kind == Kind.eUnspecified) {
if ((qualifiers & (IS_COMPLEX | IS_IMAGINARY)) != 0) {
fKind= Kind.eFloat;
} else if ((qualifiers & (IS_LONG | IS_SHORT | IS_SIGNED | IS_UNSIGNED | IS_LONG_LONG)) != 0) {
fKind= Kind.eInt;
} else {
fKind= Kind.eUnspecified;
}
} else {
fKind= kind;
}
fModifiers= qualifiers;
fExpression= expression;
}
public CPPBasicType(Kind kind, int qualifiers) {
this(kind, qualifiers, null);
}
public CPPBasicType(ICPPASTSimpleDeclSpecifier sds) {
this(getKind(sds), getModifiers(sds), null);
}
private static int getModifiers(ICPPASTSimpleDeclSpecifier sds) {
return
(sds.isLong() ? IBasicType.IS_LONG : 0) |
(sds.isShort() ? IBasicType.IS_SHORT : 0) |
(sds.isSigned() ? IBasicType.IS_SIGNED: 0) |
(sds.isUnsigned() ? IBasicType.IS_UNSIGNED : 0) |
(sds.isLongLong() ? IBasicType.IS_LONG_LONG : 0) |
(sds.isComplex() ? IBasicType.IS_COMPLEX : 0) |
(sds.isImaginary() ? IBasicType.IS_IMAGINARY : 0);
}
private static Kind getKind(ICPPASTSimpleDeclSpecifier sds) {
return getKind(sds.getType());
}
static Kind getKind(final int simpleDeclSpecType) {
switch (simpleDeclSpecType) {
case IASTSimpleDeclSpecifier.t_bool:
return Kind.eBoolean;
case IASTSimpleDeclSpecifier.t_char:
return Kind.eChar;
case IASTSimpleDeclSpecifier.t_wchar_t:
return Kind.eWChar;
case IASTSimpleDeclSpecifier.t_char16_t:
return Kind.eChar16;
case IASTSimpleDeclSpecifier.t_char32_t:
return Kind.eChar32;
case IASTSimpleDeclSpecifier.t_double:
return Kind.eDouble;
case IASTSimpleDeclSpecifier.t_float:
return Kind.eFloat;
case IASTSimpleDeclSpecifier.t_int:
return Kind.eInt;
case IASTSimpleDeclSpecifier.t_void:
return Kind.eVoid;
default:
return Kind.eUnspecified;
}
}
public boolean isSameType(IType object) {
if (object == this)
return true;
if (object instanceof ITypedef)
return object.isSameType(this);
if (!(object instanceof ICPPBasicType))
return false;
ICPPBasicType t = (ICPPBasicType) object;
if (fKind != t.getKind())
return false;
if (fKind == Kind.eInt) {
//signed int and int are equivalent
return (fModifiers & ~IS_SIGNED) == (t.getModifiers() & ~IS_SIGNED);
}
return fModifiers == t.getModifiers();
}
public Kind getKind() {
return fKind;
}
public boolean isSigned() {
return (fModifiers & IS_SIGNED) != 0;
}
public boolean isUnsigned() {
return (fModifiers & IS_UNSIGNED) != 0;
}
public boolean isShort() {
return (fModifiers & IS_SHORT) != 0;
}
public boolean isLong() {
return (fModifiers & IS_LONG) != 0;
}
public boolean isLongLong() {
return (fModifiers & IS_LONG_LONG) != 0;
}
public boolean isComplex() {
return (fModifiers & IS_COMPLEX) != 0;
}
public boolean isImaginary() {
return (fModifiers & IS_IMAGINARY) != 0;
}
@Override
public Object clone() {
IType t = null;
try {
t = (IType) super.clone();
} catch (CloneNotSupportedException e) {
//not going to happen
}
return t;
}
public void setFromExpression(IASTExpression val) {
fExpression = val;
}
/**
* Returns the expression the type was created for, or <code>null</code>.
*/
public IASTExpression getCreatedFromExpression() {
return fExpression;
}
public int getModifiers() {
return fModifiers;
}
@Override
public String toString() {
return ASTTypeUtil.getType(this);
}
public void marshal(ITypeMarshalBuffer buffer) throws CoreException {
final int kind= getKind().ordinal();
final int shiftedKind= kind * ITypeMarshalBuffer.FLAG1;
final int modifiers= getModifiers();
if (shiftedKind < ITypeMarshalBuffer.FLAG4 && modifiers == 0) {
buffer.putByte((byte) (ITypeMarshalBuffer.BASIC_TYPE | shiftedKind));
} else {
buffer.putByte((byte) (ITypeMarshalBuffer.BASIC_TYPE | ITypeMarshalBuffer.FLAG4));
buffer.putByte((byte) kind);
buffer.putByte((byte) modifiers);
}
}
public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
final boolean dense= (firstByte & ITypeMarshalBuffer.FLAG4) == 0;
int modifiers= 0;
int kind;
if (dense) {
kind= (firstByte & (ITypeMarshalBuffer.FLAG4-1))/ITypeMarshalBuffer.FLAG1;
} else {
kind= buffer.getByte();
modifiers= buffer.getByte();
}
return new CPPBasicType(Kind.values()[kind], modifiers);
}
@Deprecated
public int getQualifierBits() {
return getModifiers();
}
@Deprecated
public int getType() {
switch (fKind) {
case eBoolean:
return t_bool;
case eChar:
case eChar16:
case eChar32:
return t_char;
case eWChar:
return t_wchar_t;
case eDouble:
return t_double;
case eFloat:
return t_float;
case eInt:
return t_int;
case eVoid:
return t_void;
case eUnspecified:
return t_unspecified;
}
return t_unspecified;
}
/**
* @deprecated types don't have values
*/
@Deprecated
public IASTExpression getValue() {
return fExpression;
}
}