/*******************************************************************************
* Copyright (c) 2008, 2013 Wind River Systems, Inc. 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ObjectMap;
/**
* Maps template parameters to values.
*/
public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
public static final CPPTemplateParameterMap EMPTY = new CPPTemplateParameterMap(0);
private final ObjectMap fMap;
/**
* Constructs an empty parameter map.
*/
public CPPTemplateParameterMap(int initialSize) {
fMap= new ObjectMap(initialSize);
}
public CPPTemplateParameterMap(CPPTemplateParameterMap other) {
fMap= (ObjectMap) other.fMap.clone();
}
/**
* Returns whether the map contains the given parameter
*/
public boolean contains(ICPPTemplateParameter templateParameter) {
return fMap.containsKey(templateParameter.getParameterID());
}
/**
* Adds the mapping.
*/
public void put(ICPPTemplateParameter param, ICPPTemplateArgument value) {
fMap.put(param.getParameterID(), value);
}
/**
* Adds the mapping.
*/
public void put(int parameterID, ICPPTemplateArgument value) {
fMap.put(parameterID, value);
}
/**
* Adds the mapping.
*/
public void put(ICPPTemplateParameter param, ICPPTemplateArgument[] packExpansion) {
fMap.put(param.getParameterID(), packExpansion);
}
/**
* Adds the mapping.
*/
public void put(int parameterID, ICPPTemplateArgument[] packExpansion) {
fMap.put(parameterID, packExpansion);
}
/**
* Returns the value for the given parameter.
*/
@Override
public ICPPTemplateArgument getArgument(ICPPTemplateParameter param) {
if (param == null)
return null;
return getArgument(param.getParameterID());
}
/**
* Returns the value for the template parameter with the given id.
* @see ICPPTemplateParameter#getParameterID()
*/
@Override
public ICPPTemplateArgument getArgument(int paramID) {
final Object object = fMap.get(paramID);
if (object instanceof ICPPTemplateArgument) {
return (ICPPTemplateArgument) object;
}
return null;
}
/**
* Returns the values for the given template parameter pack.
*/
@Override
public ICPPTemplateArgument[] getPackExpansion(ICPPTemplateParameter tpar) {
return getPackExpansion(tpar.getParameterID());
}
/**
* Returns the values for the template parameter pack with the given id.
* @see ICPPTemplateParameter#getParameterID()
*/
@Override
public ICPPTemplateArgument[] getPackExpansion(int paramID) {
final Object object = fMap.get(paramID);
if (object instanceof ICPPTemplateArgument[]) {
return (ICPPTemplateArgument[]) object;
}
return null;
}
@Override
public ICPPTemplateArgument getArgument(ICPPTemplateParameter tpar, int packOffset) {
return getArgument(tpar.getParameterID(), packOffset);
}
/**
* Returns the argument at the given position
*/
public ICPPTemplateArgument getArgument(int paramID, int packOffset) {
final Object object = fMap.get(paramID);
if (object instanceof ICPPTemplateArgument)
return (ICPPTemplateArgument) object;
if (object instanceof ICPPTemplateArgument[]) {
ICPPTemplateArgument[] args = (ICPPTemplateArgument[]) object;
if (packOffset < args.length && packOffset >= 0)
return args[packOffset];
}
return null;
}
/**
* Returns the argument at the given position
*/
public boolean putPackElement(Integer paramID, int packOffset, ICPPTemplateArgument arg, int packSize) {
ICPPTemplateArgument[] args;
final Object object = fMap.get(paramID);
if (object instanceof ICPPTemplateArgument[]) {
args = (ICPPTemplateArgument[]) object;
if (packSize != args.length)
return false;
} else if (object == null) {
args= new ICPPTemplateArgument[packSize];
fMap.put(paramID, args);
} else {
return false;
}
args[packOffset]= arg;
return true;
}
/**
* Puts all mappings from the supplied map into this map.
*/
public void putAll(ICPPTemplateParameterMap map) {
if (map instanceof CPPTemplateParameterMap) {
final ObjectMap omap= ((CPPTemplateParameterMap) map).fMap;
for (int i = 0; i < omap.size(); i++) {
fMap.put(omap.keyAt(i), omap.getAt(i));
}
} else {
assert false;
}
}
public boolean addDeducedArgs(CPPTemplateParameterMap deducedMap) {
Integer[] keys= deducedMap.getAllParameterPositions();
for (Integer key : keys) {
Object explicit= fMap.get(key);
Object deduced= deducedMap.fMap.get(key);
if (explicit == null) {
if (deduced instanceof ICPPTemplateArgument[]) {
for (ICPPTemplateArgument arg : (ICPPTemplateArgument[]) deduced) {
if (arg == null)
return false;
}
}
fMap.put(key, deduced);
} else if (explicit instanceof ICPPTemplateArgument[] && deduced instanceof ICPPTemplateArgument[]) {
ICPPTemplateArgument[] explicitPack= (ICPPTemplateArgument[]) explicit;
ICPPTemplateArgument[] deducedPack= (ICPPTemplateArgument[]) deduced;
if (deducedPack.length < explicitPack.length)
return false;
System.arraycopy(explicitPack, 0, deducedPack, 0, explicitPack.length);
for (ICPPTemplateArgument arg : deducedPack) {
if (arg == null)
return false;
}
fMap.put(key, deducedPack);
} else {
return false;
}
}
return true;
}
/**
* Returns the array of template parameter positions, for which a mapping exists.
*/
@Override
public Integer[] getAllParameterPositions() {
return fMap.keyArray(Integer.class);
}
/**
* For debugging purposes, only.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{"); //$NON-NLS-1$
for (int i = 0; i < fMap.size(); i++) {
Integer key = (Integer) fMap.keyAt(i);
if (key != null) {
if (sb.length() > 1) {
sb.append(", "); //$NON-NLS-1$
}
final Object obj = fMap.getAt(i);
if (obj instanceof ICPPTemplateArgument) {
appendArg(sb, key, (ICPPTemplateArgument) obj);
} else if (obj instanceof ICPPTemplateArgument[]) {
for (ICPPTemplateArgument arg : (ICPPTemplateArgument[]) obj) {
appendArg(sb, key, arg);
}
}
}
}
sb.append("}"); //$NON-NLS-1$
return sb.toString();
}
private void appendArg(StringBuilder sb, Integer key, ICPPTemplateArgument value) {
sb.append('#');
sb.append(key >> 16);
sb.append(',');
sb.append(key & 0xffff);
sb.append(": "); //$NON-NLS-1$
sb.append(ASTTypeUtil.getArgumentString(value, true));
}
}