/*******************************************************************************
* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import java.util.Arrays;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed;
import org.eclipse.core.runtime.CoreException;
public final class FloatingPointValue implements IValue {
private final char[] fFixedValue;
private FloatingPointValue(char[] fixedValue) {
fFixedValue = fixedValue;
}
public static FloatingPointValue create(char[] fixedValue) {
return new FloatingPointValue(fixedValue);
}
public static FloatingPointValue create(double value) {
return new FloatingPointValue(toCharArray(value));
}
@Override
public Long numericalValue() {
return null; // not a Long
}
@Override
public Number numberValue() {
return parseDouble(fFixedValue);
}
private static Double parseDouble(char[] value) {
double result = 0.0;
int i = 0;
int len = value.length;
while (i < len && value[i] >= '0' && value[i] <= '9') {
int digit = value[i] - '0';
result = result * 10 + digit;
++i;
}
if (i < len && value[i] == '.') {
++i;
}
double div = 10.0;
while (i < len && value[i] >= '0' && value[i] <= '9') {
int digit = value[i] - '0';
result += digit / div;
div *= 10.0;
++i;
}
if (i < len && (value[i] == 'e' || value[i] == 'E')) {
++i;
}
boolean exponentIsPositive = true;
if (i < len && (value[i] == '+' || value[i] == '-')) {
exponentIsPositive = (value[i] == '+');
++i;
}
int exponent = 0;
while (i < len && value[i] >= '0' && value[i] <= '9') {
int digit = value[i] - '0';
exponent = exponent * 10 + digit;
++i;
}
if (i < len && (value[i] == 'l' || value[i] == 'L' || value[i] == 'f' || value[i] == 'F')) {
++i;
}
if (i == len) {
if (!exponentIsPositive) {
exponent *= -1;
}
return result * Math.pow(10, exponent);
}
return null;
}
@Override
public int numberOfSubValues() {
return 1;
}
@Override
public ICPPEvaluation getSubValue(int index) {
if (index == 0) {
return getEvaluation();
}
return EvalFixed.INCOMPLETE;
}
@Override
public ICPPEvaluation[] getAllSubValues() {
return new ICPPEvaluation[]{ getEvaluation() };
}
@Override
public ICPPEvaluation getEvaluation() {
return null;
}
@Override
public char[] getSignature() {
return fFixedValue;
}
@Override
public int hashCode() {
return CharArrayUtils.hash(getSignature());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof FloatingPointValue)) {
return false;
}
final FloatingPointValue rhs = (FloatingPointValue) obj;
if (fFixedValue != null)
return CharArrayUtils.equals(fFixedValue, rhs.fFixedValue);
return CharArrayUtils.equals(getSignature(), rhs.getSignature());
}
@Deprecated
@Override
public char[] getInternalExpression() {
return CharArrayUtils.EMPTY_CHAR_ARRAY;
}
@Deprecated
@Override
public IBinding[] getUnknownBindings() {
return IBinding.EMPTY_BINDING_ARRAY;
}
@Override
public void setSubValue(int position, ICPPEvaluation newValue) {
}
private static char[] toCharArray(double value) {
StringBuilder buf= new StringBuilder();
buf.append(value);
return CharArrayUtils.extractChars(buf);
}
@Override
public String toString() {
return new String(getSignature());
}
@Override
public IValue clone() {
char[] newFixedValue = Arrays.copyOf(fFixedValue, fFixedValue.length);
return new FloatingPointValue(newFixedValue);
}
@Override
public void marshal(ITypeMarshalBuffer buf) throws CoreException {
buf.putShort(ITypeMarshalBuffer.FLOATING_POINT_VALUE);
buf.putCharArray(fFixedValue);
}
public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException {
return new FloatingPointValue(buf.getCharArray());
}
}