/*******************************************************************************
* Copyright (c) 2009 Red Hat, Inc.
* 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:
* Red Hat Incorporated - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.cdt.libhover;
import java.io.Serializable;
import java.util.ArrayList;
public class TypedefInfo implements Serializable {
private static final long serialVersionUID = 1L;
private String[] templates = new String[0];
private String typedefName;
private String transformedType;
private ArrayList<TypedefInfo> children = null;
public TypedefInfo(String typedefName, String transformedType) {
this.typedefName = typedefName;
this.transformedType = transformedType;
}
public String getTypedefName() {
return typedefName;
}
public void setTypedefName(String name) {
typedefName = name;
}
private String[] getTemplateArgs(String str) {
ArrayList<String> list = new ArrayList<>();
int index = 0;
int lastIndex = 0;
int templateCounter = 0;
while (index < str.length()) {
char ch = str.charAt(index);
if (ch == '<') {
if (templateCounter == 0)
lastIndex = index + 1;
templateCounter++;
} else if (ch == '>') {
templateCounter--;
} else if (ch == ',' && templateCounter == 1) {
// FIXME: do we have to strip out all blanks here?
list.add(str.substring(lastIndex, index).trim());
lastIndex = index + 1;
}
++index;
}
String[] args = new String[list.size()];
return list.toArray(args);
}
public String getTransformedType(String className) {
int index = className.indexOf('<');
if (index > 0) {
TypedefInfo e = this;
// Search the children list in case the given class name
// matches a specific template case.
ArrayList<TypedefInfo> children = getChildren();
for (int x = 0; x < children.size(); ++x) {
TypedefInfo child = children.get(x);
if (className.matches(child.getTypedefName())) {
e = child;
break;
}
}
String[] templates = e.getTemplates();
String transformedName = e.transformedType;
// Check if there are any template arguments to replace. If not,
// we can just return the transformed type we have.
if (templates.length <= 0)
return transformedName;
String[] args = getTemplateArgs(className);
String[] templateArgs = getTemplateArgs(e.getTypedefName());
int j = 0;
// For every argument that doesn't match up, it must be a template
// parameter so we'll replace the template parameter name with the
// supplied parameter. We have to query the template parameter list
// for the names to replace because for partial specific templates
// those names will have been replaced with regex sequences designed to
// help us identify when the specific template has matched. For example,
// <char, _Tp> will be stored as <char,[a-zA-Z0-9_]*> and if we have
// <char,char> we will replace _Tp with char in the transformed type.
for (int i = 0; i < args.length; ++i) {
if (!args[i].equals(templateArgs[i])) {
transformedName = transformedName.replaceAll(templates[j], args[i]);
++j;
}
}
return transformedName;
} else {
// There is no template specified.
return transformedType;
}
}
public void addTypedef(TypedefInfo typedef) {
if (children == null) {
children = new ArrayList<>();
}
children.add(typedef);
}
public ArrayList<TypedefInfo> getChildren() {
return children;
}
public void copyTemplates(String[] newTemplates) {
templates = new String[newTemplates.length];
for (int i = 0; i < templates.length; ++i) {
templates[i] = newTemplates[i];
}
}
public String[] getTemplates() {
return templates;
}
}