/**
* Copyright 2013, Landz and its contributors. All rights reserved.
*
* 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 z.znr.invoke.linux.x64;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import java.lang.reflect.Modifier;
import java.util.*;
/**
*
*/
class AsmBuilder {
private final String classNamePath;
private final ClassVisitor classVisitor;
private final AsmClassLoader classLoader;
private final ObjectNameGenerator genericObjectId = new InferringObjectNameGenerator();
private final Map<Object, ObjectField> genericObjects = new IdentityHashMap<Object, ObjectField>();
private final List<ObjectField> objectFields = new ArrayList<ObjectField>();
AsmBuilder(String classNamePath, ClassVisitor classVisitor, AsmClassLoader classLoader) {
this.classNamePath = classNamePath;
this.classVisitor = classVisitor;
this.classLoader = classLoader;
}
public String getClassNamePath() {
return classNamePath;
}
ClassVisitor getClassVisitor() {
return classVisitor;
}
public AsmClassLoader getClassLoader() {
return classLoader;
}
private static interface ObjectNameGenerator {
String generateName(Class cls);
}
private static final class SimpleObjectNameGenerator implements ObjectNameGenerator {
private final String baseName;
private int value;
SimpleObjectNameGenerator(String baseName) {
this.baseName = baseName;
this.value = 0;
}
public String generateName(Class klass) {
return baseName + "_" + ++value;
}
}
private static final class InferringObjectNameGenerator implements ObjectNameGenerator {
private final Map<Class, Long> classCount = new IdentityHashMap<>();
public String generateName(Class klass) {
Long count = classCount.get(klass);
classCount.put(klass, count = count != null ? count + 1 : 1);
return klass.getName().replace('.', '_') + '_' + count;
}
}
<T> ObjectField addField(Map<T, ObjectField> map, T value, Class klass, ObjectNameGenerator objectNameGenerator) {
ObjectField field = new ObjectField(objectNameGenerator.generateName(klass), value, klass);
objectFields.add(field);
map.put(value, field);
return field;
}
<T> ObjectField getField(Map<T, ObjectField> map, T value, Class klass, ObjectNameGenerator objectNameGenerator) {
ObjectField field = map.get(value);
return field != null ? field : addField(map, value, klass, objectNameGenerator);
}
private static Class publicClass(Class klass) {
for (Class c = klass; c != null; c = c.getSuperclass()) {
if (Modifier.isPublic(c.getModifiers())) {
return c;
}
}
throw new RuntimeException("no public ancestor of " + klass);
}
String getObjectFieldName(Object obj, Class klass) {
return getObjectField(obj, klass).name;
}
String getObjectFieldName(Object obj) {
return getObjectField(obj).name;
}
ObjectField getObjectField(Object obj, Class klass) {
return getField(genericObjects, obj, klass, genericObjectId);
}
ObjectField getObjectField(Object obj) {
return getField(genericObjects, obj, publicClass(obj.getClass()), genericObjectId);
}
public static final class ObjectField {
public final String name;
public final Object value;
public final Class klass;
public ObjectField(String fieldName, Object fieldValue, Class fieldClass) {
this.name = fieldName;
this.value = fieldValue;
this.klass = fieldClass;
}
}
ObjectField[] getObjectFieldArray() {
return objectFields.toArray(new ObjectField[objectFields.size()]);
}
Map<String, Object> getObjectFieldMap() {
Map<String, Object> m = new HashMap<>();
for (ObjectField f : objectFields) {
m.put(f.name, f.value);
}
return m;
}
}