All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jna.Union Maven / Gradle / Ivy

There is a newer version: 1.50.0
Show newest version
/* Copyright (c) 2007-2012 Timothy Wall, All Rights Reserved
 *
 * The contents of this file is dual-licensed under 2
 * alternative Open Source/Free licenses: LGPL 2.1 or later and
 * Apache License 2.0. (starting with JNA version 4.0.0).
 *
 * You can freely decide which license you want to apply to
 * the project.
 *
 * You may obtain a copy of the LGPL License at:
 *
 * http://www.gnu.org/licenses/licenses.html
 *
 * A copy is also included in the downloadable source code package
 * containing JNA, in file "LGPL2.1".
 *
 * You may obtain a copy of the Apache License at:
 *
 * http://www.apache.org/licenses/
 *
 * A copy is also included in the downloadable source code package
 * containing JNA, in file "AL2.0".
 */
package com.sun.jna;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/** Represents a native union.  When writing to native memory, the field
 * corresponding to the type passed to {@link #setType} will be written
 * to native memory.  Upon reading from native memory, Structure, String,
 * or WString fields will not be initialized unless they are
 * the current field as identified by a call to {@link #setType}.  The current
 * field is always unset by default to avoid accidentally attempting to read
 * a field that is not valid.  In the case of a String, for instance, an
 * invalid pointer may result in a memory fault when attempting to initialize
 * the String.
 */
public abstract class Union extends Structure {
    private StructField activeField;

    /** Create a Union whose size and alignment will be calculated
     * automatically.
     */
    protected Union() { }
    /** Create a Union of the given size, using default alignment. */
    protected Union(Pointer p) {
        super(p);
    }
    /** Create a Union of the given size and alignment type. */
    protected Union(Pointer p, int alignType) {
        super(p, alignType);
    }
    /** Create a Union of the given size and alignment type. */
    protected Union(TypeMapper mapper) {
        super(mapper);
    }
    /** Create a Union of the given size and alignment type. */
    protected Union(Pointer p, int alignType, TypeMapper mapper) {
        super(p, alignType, mapper);
    }

    /** Unions do not need a field order, so automatically provide a value to
     * satisfy checking in the Structure superclass.
     */
    @Override
    protected List getFieldOrder() {
        List flist = getFieldList();
        List list = new ArrayList(flist.size());
        for (Field f : flist) {
            list.add(f.getName());
        }
        return list;
    }

    /** Indicates by type which field will be used to write to native memory.
     * If there are multiple fields of the same type, use {@link
     * #setType(String)} instead with the field name.
     * @param type desired active type for the union
     * @throws IllegalArgumentException if the type does not correspond to
     * any declared union field.
     */
    public void setType(Class type) {
        ensureAllocated();
        for (StructField f : fields().values()) {
            if (f.type == type) {
                activeField = f;
                return;
            }
        }
        throw new IllegalArgumentException("No field of type " + type + " in " + this);
    }

    /**
     * Indicates which field will be used to write to native memory.
     * @param fieldName desired field to use for the active union type
     * @throws IllegalArgumentException if the name does not correspond to
     * any declared union field.
     */
    public void setType(String fieldName) {
        ensureAllocated();
        StructField f = fields().get(fieldName);
        if (f != null) {
            activeField = f;
        }
        else {
            throw new IllegalArgumentException("No field named " + fieldName
                                               + " in " + this);
        }
    }

    /** Force a read of the given field from native memory.
     * @return the new field value, after updating
     * @throws IllegalArgumentException if no field exists with the given name
     */
    @Override
    public Object readField(String fieldName) {
        ensureAllocated();
        setType(fieldName);
        return super.readField(fieldName);
    }

    /** Write the given field value to native memory.
     * The given field will become the active one.
     * @throws IllegalArgumentException if no field exists with the given name
     */
    @Override
    public void writeField(String fieldName) {
        ensureAllocated();
        setType(fieldName);
        super.writeField(fieldName);
    }

    /** Write the given field value to the field and native memory.
     * The given field will become the active one.
     * @throws IllegalArgumentException if no field exists with the given name
     */
    @Override
    public void writeField(String fieldName, Object value) {
        ensureAllocated();
        setType(fieldName);
        super.writeField(fieldName, value);
    }

    /** Reads the Structure field of the given type from memory, sets it as
     * the active type and returns it.  Convenience method for
     * 

     * Union u;
     * Class type;
     * u.setType(type);
     * u.read();
     * value = u.field;
     * 
* @param type class type of the Structure field to read * @return the Structure field with the given type */ public Object getTypedValue(Class type) { ensureAllocated(); for (StructField f : fields().values()) { if (f.type == type) { activeField = f; read(); return getFieldValue(activeField.field); } } throw new IllegalArgumentException("No field of type " + type + " in " + this); } /** Set the active type and its value. Convenience method for *

     * Union u;
     * Class type;
     * u.setType(type);
     * u.field = value;
     * 
* @param object instance of a class which is part of the union * @return this Union object */ public Object setTypedValue(Object object) { StructField f = findField(object.getClass()); if (f != null) { activeField = f; setFieldValue(f.field, object); return this; } throw new IllegalArgumentException("No field of type " + object.getClass() + " in " + this); } /** Returns the field in this union with the same type as type, * if any, null otherwise. * @param type type to search for * @return StructField of matching type */ private StructField findField(Class type) { ensureAllocated(); for (StructField f : fields().values()) { if (f.type.isAssignableFrom(type)) { return f; } } return null; } /** Only the currently selected field will be written. */ @Override protected void writeField(StructField field) { if (field == activeField) { super.writeField(field); } } /** Avoid reading pointer-based fields and structures unless explicitly * selected. Structures may contain pointer-based fields which can * crash the VM if not properly initialized. */ @Override protected Object readField(StructField field) { if (field == activeField || (!Structure.class.isAssignableFrom(field.type) && !String.class.isAssignableFrom(field.type) && !WString.class.isAssignableFrom(field.type))) { return super.readField(field); } // Field not accessible // TODO: read by-value structures, to the extent possible; need a // "read cautiously" method to "read" to indicate we want to avoid // pointer-based fields return null; } /** All fields are considered the "first" element. */ @Override protected int getNativeAlignment(Class type, Object value, boolean isFirstElement) { return super.getNativeAlignment(type, value, true); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy