Logo Search packages:      
Sourcecode: libjna-java version File versions  Download package

int com::sun::jna::Structure::calculateSize ( boolean  force  )  [inline, package, inherited]

Calculate the amount of native memory required for this structure. May return CALCULATE_SIZE if the size can not yet be determined (usually due to fields in the derived class not yet being initialized).

If the force parameter is true will throw an IllegalStateException if the size can not be determined.

Exceptions:
IllegalStateException an array field is not initialized
IllegalArgumentException when an unsupported field type is encountered

Reimplemented in com::sun::jna::Union.

Definition at line 747 of file Structure.java.

References com::sun::jna::NativeMappedConverter::defaultValue(), com::sun::jna::Structure::getField(), com::sun::jna::TypeMapper::getFromNativeConverter(), com::sun::jna::Structure::getNativeAlignment(), com::sun::jna::Structure::getNativeSize(), com::sun::jna::TypeMapper::getToNativeConverter(), com::sun::jna::NativeMappedConverter::nativeType, com::sun::jna::Structure::newInstance(), and com::sun::jna::ToNativeConverter::toNative().

Referenced by com::sun::jna::Structure::allocateMemory().

                                     {
        // TODO: maybe cache this information on a per-class basis
        // so that we don't have to re-analyze this static information each
        // time a struct is allocated.

        structAlignment = 1;
        int calculatedSize = 0;
        Field[] fields = getClass().getFields();
        if (REVERSE_FIELDS) {
            for (int i=0;i < fields.length/2;i++) {
                int idx = fields.length-1-i;
                Field tmp = fields[i];
                fields[i] = fields[idx];
                fields[idx] = tmp;
            }
        }
        for (int i=0; i<fields.length; i++) {
            Field field = fields[i];
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers))
                continue;

            Class type = field.getType();
            StructField structField = new StructField();
            structField.isVolatile = Modifier.isVolatile(modifiers);
            structField.field = field;
            if (Modifier.isFinal(modifiers)) {
                field.setAccessible(true);
            }
            structField.name = field.getName();
            structField.type = type;

            // Check for illegal field types
            if (Callback.class.isAssignableFrom(type) && !type.isInterface()) {
                throw new IllegalArgumentException("Structure Callback field '"
                                                   + field.getName()
                                                   + "' must be an interface");
            }
            if (type.isArray()
                && Structure.class.equals(type.getComponentType())) {
                String msg = "Nested Structure arrays must use a "
                    + "derived Structure type so that the size of "
                    + "the elements can be determined";
                throw new IllegalArgumentException(msg);
            }

            int fieldAlignment = 1;
            if (!Modifier.isPublic(field.getModifiers()))
                continue;

            Object value = getField(structField);
            if (value == null) {
                if (Structure.class.isAssignableFrom(type)
                    && !(ByReference.class.isAssignableFrom(type))) {
                    try {
                        value = newInstance(type);
                        setField(structField, value);
                    }
                    catch(IllegalArgumentException e) {
                        String msg = "Can't determine size of nested structure: "
                            + e.getMessage();
                        throw new IllegalArgumentException(msg);
                    }
                }
                else if (type.isArray()) {
                    // can't calculate size yet, defer until later
                    if (force) {
                        throw new IllegalStateException("Array fields must be initialized");
                    }
                    return CALCULATE_SIZE;
                }
            }
            Class nativeType = type;
            if (NativeMapped.class.isAssignableFrom(type)) {
                NativeMappedConverter tc = NativeMappedConverter.getInstance(type);
                value = tc.defaultValue();
                nativeType = tc.nativeType();
                structField.writeConverter = tc;
                structField.readConverter = tc;
                structField.context = new StructureReadContext(this, field);
                setField(structField, value);
            }
            else if (typeMapper != null) {
                ToNativeConverter writeConverter = typeMapper.getToNativeConverter(type);
                FromNativeConverter readConverter = typeMapper.getFromNativeConverter(type);
                if (writeConverter != null && readConverter != null) {
                    value = writeConverter.toNative(value,
                                                    new StructureWriteContext(this, structField.field));
                    nativeType = value != null ? value.getClass() : Pointer.class;
                    structField.writeConverter = writeConverter;
                    structField.readConverter = readConverter;
                    structField.context = new StructureReadContext(this, field);
                }
                else if (writeConverter != null || readConverter != null) {
                    String msg = "Structures require bidirectional type conversion for " + type;
                    throw new IllegalArgumentException(msg);
                }
            }
            structField.size = getNativeSize(nativeType, value);
            fieldAlignment = getNativeAlignment(nativeType, value, i==0);

            // Align fields as appropriate
            structAlignment = Math.max(structAlignment, fieldAlignment);
            if ((calculatedSize % fieldAlignment) != 0) {
                calculatedSize += fieldAlignment - (calculatedSize % fieldAlignment);
            }
            structField.offset = calculatedSize;
            calculatedSize += structField.size;

            // Save the field in our list
            structFields.put(structField.name, structField);
        }

        if (calculatedSize > 0) {
            return calculateAlignedSize(calculatedSize);
        }

        throw new IllegalArgumentException("Structure " + getClass()
                                           + " has unknown size (ensure "
                                           + "all fields are public)");
    }


Generated by  Doxygen 1.6.0   Back to index