Package jnr.ffi.provider.jffi

Source Code of jnr.ffi.provider.jffi.Types

package jnr.ffi.provider.jffi;

import jnr.ffi.Address;
import jnr.ffi.NativeType;
import jnr.ffi.Pointer;
import jnr.ffi.Type;
import jnr.ffi.annotations.TypeDefinition;

import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.nio.Buffer;
import java.util.*;

import static jnr.ffi.provider.jffi.AsmUtil.isDelegate;

/**
*
*/
class Types {
    private static Reference<Map<Class, Map<Collection<Annotation>, Type>>> typeCacheReference;

    static Type getType(jnr.ffi.Runtime runtime, Class javaType, Collection<Annotation> annotations) {
        Map<Class, Map<Collection<Annotation>, Type>> cache = typeCacheReference != null ? typeCacheReference.get() : null;
        Map<Collection<Annotation>, Type> aliasCache = cache != null ? cache.get(javaType) : null;
        Type type = aliasCache != null ? aliasCache.get(annotations) : null;
       
        return type != null ? type : lookupAndCacheType(runtime, javaType, annotations);
    }
   
    @SuppressWarnings("unchecked")
    private static synchronized Type lookupAndCacheType(jnr.ffi.Runtime runtime, Class javaType, Collection<Annotation> annotations) {
        Map<Class, Map<Collection<Annotation>, Type>> cache = typeCacheReference != null ? typeCacheReference.get() : null;
        Map<Collection<Annotation>, Type> aliasCache = cache != null ? cache.get(javaType) : null;
        Type type = aliasCache != null ? aliasCache.get(annotations) : null;
        if (type != null) {
            return type;
        }
        cache = new HashMap<Class, Map<Collection<Annotation>, Type>>(cache != null ? cache : Collections.EMPTY_MAP);
       
        aliasCache = new HashMap<Collection<Annotation>, Type>(aliasCache != null ? aliasCache : Collections.EMPTY_MAP);
        aliasCache.put(annotations, type = lookupType(runtime, javaType, annotations));
        cache.put(javaType, Collections.unmodifiableMap(aliasCache));

        typeCacheReference = new SoftReference<Map<Class, Map<Collection<Annotation>, Type>>>(Collections.unmodifiableMap(new IdentityHashMap<Class, Map<Collection<Annotation>, Type>>(cache)));
       
        return type;
    }
   
    private static Type lookupAliasedType(jnr.ffi.Runtime runtime, Collection<Annotation> annotations) {
        for (Annotation a : annotations) {
            TypeDefinition typedef = a.annotationType().getAnnotation(TypeDefinition.class);
            if (typedef != null) {
                return runtime.findType(typedef.alias());
            }
        }

        return null;
    }

    static Type lookupType(jnr.ffi.Runtime runtime, Class type, Collection<Annotation> annotations) {
        Type aliasedType = lookupAliasedType(runtime, annotations);
        if (aliasedType != null) {
            return aliasedType;

        } else if (Void.class.isAssignableFrom(type) || void.class == type) {
            return runtime.findType(NativeType.VOID);

        } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) {
            return runtime.findType(NativeType.SINT);

        } else if (Byte.class.isAssignableFrom(type) || byte.class == type) {
            return runtime.findType(NativeType.SCHAR);

        } else if (Short.class.isAssignableFrom(type) || short.class == type) {
            return runtime.findType(NativeType.SSHORT);

        } else if (Integer.class.isAssignableFrom(type) || int.class == type) {
            return runtime.findType(NativeType.SINT);

        } else if (Long.class.isAssignableFrom(type) || long.class == type) {
            return runtime.findType(NativeType.SLONG);

        } else if (Float.class.isAssignableFrom(type) || float.class == type) {
            return runtime.findType(NativeType.FLOAT);

        } else if (Double.class.isAssignableFrom(type) || double.class == type) {
            return runtime.findType(NativeType.DOUBLE);

        } else if (Pointer.class.isAssignableFrom(type)) {
            return runtime.findType(NativeType.ADDRESS);

        } else if (Address.class.isAssignableFrom(type)) {
            return runtime.findType(NativeType.ADDRESS);

        } else if (Buffer.class.isAssignableFrom(type)) {
            return runtime.findType(NativeType.ADDRESS);

        } else if (CharSequence.class.isAssignableFrom(type)) {
            return runtime.findType(NativeType.ADDRESS);

        } else if (type.isArray()) {
            return runtime.findType(NativeType.ADDRESS);

        } else if (isDelegate(type)) {
            return runtime.findType(NativeType.ADDRESS);

        } else {
            throw new IllegalArgumentException("unsupported type: " + type);
        }
    }

}
TOP

Related Classes of jnr.ffi.provider.jffi.Types

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.