Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.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.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2008 JRuby project Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
  
  
  package org.jruby.ext.ffi;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import org.jruby.Ruby;
  import static org.jruby.runtime.Visibility.*;

Defines the memory layout for a native structure.
  
  @JRubyClass(name=., parent="Object")
  public final class StructLayout extends Type {
      static final Storage nullStorage = new NullStorage();
    
    
The name to use to register this class in the JRuby runtime
  
      static final String CLASS_NAME = "StructLayout";
  
      private final Member[] identityLookupTable;

    
The name:offset map for this struct
  
      private final Map<IRubyObjectMembermemberMap;
    
    
The ordered list of field names (as symbols)
  
      private final List<IRubyObjectfieldNames;

    
The ordered list of fields
  
      private final List<Fieldfields;

    
The ordered list of fields
  
      private final Collection<Membermembers;

    
The number of cacheable fields in this struct
  
      private final int cacheableFieldCount;

    
The number of reference fields in this struct
  
      private final int referenceFieldCount;
  
      private final boolean isUnion;

    
Registers the StructLayout class in the JRuby runtime.

Parameters:
runtime The JRuby runtime to register the new class in.
Returns:
The new class
  
      public static RubyClass createStructLayoutClass(Ruby runtimeRubyModule module) {
          RubyClass layoutClass = runtime.defineClassUnder(module.getClass("Type"),
                  .module);
          layoutClass.defineAnnotatedMethods(StructLayout.class);
         layoutClass.defineAnnotatedConstants(StructLayout.class);
 
         RubyClass arrayClass = runtime.defineClassUnder("ArrayProxy"runtime.getObject(),
                 .layoutClass);
         arrayClass.includeModule(runtime.getEnumerable());
         arrayClass.defineAnnotatedMethods(ArrayProxy.class);
 
         RubyClass charArrayClass = runtime.defineClassUnder("CharArrayProxy"arrayClass,
                 .layoutClass);
         charArrayClass.defineAnnotatedMethods(CharArrayProxy.class);
 
         RubyClass fieldClass = runtime.defineClassUnder("Field"runtime.getObject(),
                 .layoutClass);
         fieldClass.defineAnnotatedMethods(Field.class);
 
         RubyClass numberFieldClass = runtime.defineClassUnder("Number"fieldClass,
                 .layoutClass);
         numberFieldClass.defineAnnotatedMethods(NumberField.class);
 
         RubyClass enumFieldClass = runtime.defineClassUnder("Enum"fieldClass,
                 .layoutClass);
         enumFieldClass.defineAnnotatedMethods(EnumField.class);
 
         RubyClass stringFieldClass = runtime.defineClassUnder("String"fieldClass,
                 .layoutClass);
         stringFieldClass.defineAnnotatedMethods(StringField.class);
 
         RubyClass pointerFieldClass = runtime.defineClassUnder("Pointer"fieldClass,
                 .layoutClass);
         pointerFieldClass.defineAnnotatedMethods(PointerField.class);
 
         RubyClass functionFieldClass = runtime.defineClassUnder("Function"fieldClass,
                 .layoutClass);
         functionFieldClass.defineAnnotatedMethods(FunctionField.class);
 
         RubyClass innerStructFieldClass = runtime.defineClassUnder("InnerStruct"fieldClass,
                 .layoutClass);
         innerStructFieldClass.defineAnnotatedMethods(InnerStructField.class);
 
         RubyClass arrayFieldClass = runtime.defineClassUnder("Array"fieldClass,
                 .layoutClass);
         arrayFieldClass.defineAnnotatedMethods(ArrayField.class);
 
         RubyClass variableLengthArrayProxyClass = runtime.defineClassUnder("VariableLengthArrayProxy"runtime.getObject(),
                 .layoutClass);
         variableLengthArrayProxyClass.defineAnnotatedMethods(VariableLengthArrayProxy.class);
 
         RubyClass mappedFieldClass = runtime.defineClassUnder("Mapped"fieldClass,
                 .layoutClass);
         mappedFieldClass.defineAnnotatedMethods(MappedField.class);
 
 
         return layoutClass;
     }
    
    
    
Creates a new StructLayout instance.

Parameters:
runtime The runtime for the StructLayout.
fields The fields map for this struct.
size the total size of the struct.
alignment The minimum alignment required when allocating memory.
 
     private StructLayout(Ruby runtimeRubyClass klassCollection<IRubyObjectfieldsint sizeint alignment) {
         super(runtimeklass.sizealignment);
 
         int cfCount = 0, refCount = 0;
         List<FieldfieldList = new ArrayList<Field>(fields.size());
         List<IRubyObjectnames = new ArrayList<IRubyObject>(fields.size());
         List<MembermemberList = new ArrayList<Member>(fields.size());
         Map<IRubyObjectMembermemberStringMap = new HashMap<IRubyObjectMember>(fields.size());
         Member[] memberSymbolLookupTable = new Member[Util.roundUpToPowerOfTwo(fields.size() * 8)];
         int offset = 0;
         
         int index = 0;
         for (IRubyObject obj : fields) {
             
             if (!(obj instanceof Field)) {
                 throw runtime.newTypeError(objruntime.getModule("FFI").getClass("StructLayout").getClass("Field"));
             }
 
             Field f = (Fieldobj;
             if (!(f.name instanceof RubySymbol)) {
                 throw runtime.newTypeError("fields list contains field with invalid name");
             }
             if (f.type.getNativeSize() < 1 && index < (fields.size() - 1)) {
                 throw runtime.newTypeError("sizeof field == 0");
             }
 
             names.add(f.name);
             fieldList.add(f);
 
             Member m = new Member(findexf.isCacheable() ? cfCount++ : -1, f.isValueReferenceNeeded() ? refCount++ : -1);
             for (int idx = symbolIndex(f.namememberSymbolLookupTable.length); ; idx = nextIndex(idxmemberSymbolLookupTable.length)) {
                 if (memberSymbolLookupTable[idx] == null) {
                     memberSymbolLookupTable[idx] = m;
                     break;
                 }
             }
 
             // Allow fields to be accessed as ['name'] as well as [:name] for legacy code
             memberStringMap.put(f.namem);
             memberStringMap.put(f.name.asString(), m);
             memberList.add(m);
             offset = Math.max(offsetf.offset);
             index++;
         }
 
 
         this. = cfCount;
         this. = refCount;
 
         // Create the ordered list of field names from the map
         this. = Collections.unmodifiableList(new ArrayList<IRubyObject>(names));
         this. = Collections.unmodifiableList(fieldList);
         this. = Collections.unmodifiableMap(memberStringMap);
         this. = memberSymbolLookupTable;
         this. = Collections.unmodifiableList(memberList);
         this. = offset == 0 && memberList.size() > 1;
     }
     
     @JRubyMethod(name = "new", meta = true, required = 3, optional = 1)
     public static final IRubyObject newStructLayout(ThreadContext contextIRubyObject klass
             IRubyObject[] args) {
 
         IRubyObject rbFields = args[0], size = args[1], alignment = args[2];
 
         if (!(rbFields instanceof RubyArray)) {
             throw context.runtime.newTypeError(rbFieldscontext.runtime.getArray());
         }
 
         List<IRubyObjectfields = Arrays.asList(((RubyArrayrbFields).toJavaArrayMaybeUnsafe());
 
         return new StructLayout(context.runtime, (RubyClassklassfields,
                 RubyNumeric.num2int(size), RubyNumeric.num2int(alignment));
     }

    
Gets the value of the struct member corresponding to name.

Parameters:
ptr The address of the structure in memory.
name The name of the member.
Returns:
A ruby value for the native value of the struct member.
 
     @JRubyMethod(name = "get", required = 2)
     public IRubyObject get(ThreadContext contextIRubyObject ptrIRubyObject name) {
         return getValue(contextnameptr);
     }
    
    
Sets the native value of the struct member corresponding to name.

Parameters:
ptr The address of the structure in memory.
name The name of the member.
Returns:
A ruby value for the native value of the struct member.
 
     @JRubyMethod(name = "put", required = 3)
     public IRubyObject put(ThreadContext contextIRubyObject ptrIRubyObject nameIRubyObject value) {
         putValue(contextnameptrvalue);
 
         return value;
     }
    
    
Gets a ruby array of the names of all members of this struct.

Returns:
a RubyArray containing the names of all members.
 
     @JRubyMethod(name = "members")
     public IRubyObject members(ThreadContext context) {
         RubyArray mbrs = RubyArray.newArray(context.runtime.size());
         for (IRubyObject name : ) {
             mbrs.append(name);
         }
         return mbrs;
     }

    
Gets a ruby array of the offsets of all members of this struct.

Returns:
a RubyArray containing the offsets of all members.
 
     @JRubyMethod(name = "offsets")
     public IRubyObject offsets(ThreadContext context) {
         Ruby runtime = context.runtime;
         RubyArray offsets = RubyArray.newArray(runtime);
 
         for (IRubyObject name : ) {
             RubyArray offset = RubyArray.newArray(runtime);
             // Assemble a [ :name, offset ] array
             offset.append(name);
             offset.append(runtime.newFixnum(getMember(runtimename).));
             offsets.append(offset);
         }
 
         return offsets;
     }
 
     @JRubyMethod(name = "offset_of")
     public IRubyObject offset_of(ThreadContext contextIRubyObject fieldName) {
         return getField(context.runtimefieldName).offset(context);
     }
     
     @JRubyMethod(name = "[]")
     public IRubyObject aref(ThreadContext contextIRubyObject fieldName) {
         return getField(context.runtimefieldName);
     }
 
     @JRubyMethod
     public IRubyObject fields(ThreadContext context) {
         return RubyArray.newArray(context.runtime);
     }
 
     final IRubyObject getValue(ThreadContext contextIRubyObject nameStorage cacheIRubyObject ptr) {
         if (!(ptr instanceof AbstractMemory)) {
             throw context.runtime.newTypeError(ptrcontext.runtime.getFFI().);
         }
 
         return getMember(context.runtimename).get(contextcache, (AbstractMemoryptr);
     }
 
     final void putValue(ThreadContext contextIRubyObject nameStorage cacheIRubyObject ptrIRubyObject value) {
         if (!(ptr instanceof AbstractMemory)) {
             throw context.runtime.newTypeError(ptrcontext.runtime.getFFI().);
         }
 
         getMember(context.runtimename).put(contextcache, (AbstractMemoryptrvalue);
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == oreturn true;
         if (o == null || getClass() != o.getClass()) return false;
         if (!super.equals(o)) return false;
 
         StructLayout that = (StructLayouto;
 
         if ( != null ? !.equals(that.fields) : that.fields != nullreturn false;
 
         return true;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + ( != null ? .hashCode() : 0);
         return result;
     }
 
     private static int symbolIndex(IRubyObject nameint length) {
         return System.identityHashCode(name) & (length - 1);
     }
 
     private static int nextIndex(int idxint length) {
         return (idx + 1) & (length - 1);
     }

    
Returns a StructLayout.Member descriptor for a struct field.

Parameters:
name The name of the struct field.
Returns:
A Member descriptor.
 
     final Member getMember(Ruby runtimeIRubyObject name) {
         Member m;
         int idx = symbolIndex(name.);
         while ((m = [idx]) != null) {
             if (m.name == name) {
                 return m;
             }
             idx = nextIndex(idx.);
         }
 
         Member f = .get(name);
         if (f != null) {
             return f;
         }
 
         throw runtime.newArgumentError("Unknown field: " + name);
     }

    
Returns a StructLayout.Field descriptor for a struct field.

Parameters:
name The name of the struct field.
Returns:
A Member descriptor.
 
     final Field getField(Ruby runtimeIRubyObject name) {
         return getMember(runtimename).;
     }
 
     public final int getSize() {
         return getNativeSize();
     }
 
     final int getReferenceFieldCount() {
         return ;
     }
 
     final int getReferenceFieldIndex(Member member) {
         return member.referenceIndex;
     }
 
     final int getCacheableFieldCount() {
         return ;
     }
 
     final int getCacheableFieldIndex(Member member) {
         return member.cacheIndex;
     }
 
     public final int getFieldCount() {
         return .size();
     }
 
     public final java.util.Collection<FieldgetFields() {
         return ;
     }
 
     public final java.util.Collection<MembergetMembers() {
         return ;
     }
 
     public final boolean isUnion() {
         return ;
     }

    
A struct member. This defines the offset within a chunk of memory to use when reading/writing the member, as well as how to convert between the native representation of the member and the JRuby representation.
 
     public static final class Member {
         final FieldIO io;
 
         final Field field;

        
The Type of this member.
 
         final Type type;

        
The offset within the memory area of this member
 
         final int offset;

        
The index of this member within the struct field cache
 
         final int cacheIndex;

        
The index of this member within the struct field reference arra
 
         final int referenceIndex;

        
The index of this member within the struct
 
         final int index;
 
         final IRubyObject name;

        
Initializes a new Member instance
 
         protected Member(Field fint indexint cacheIndexint referenceIndex) {
             this. = f;
             this. = f.io;
             this. = f.type;
             this. = f.offset;
             this. = index;
             this. = cacheIndex;
             this. = referenceIndex;
             this. = f.name;
         }
 
         final long getOffset(IRubyObject ptr) {
             return ;
         }
 
         final int getIndex() {
             return ;
         }
 
         @Override
         public boolean equals(Object obj) {
             return obj instanceof Member && ((Memberobj). ==  && .equals(((Memberobj).);
         }
 
         @Override
         public int hashCode() {
             return 53 * 5 + (int) (this. ^ (this. >>> 32)) + 37 * .hashCode();
         }
        
        
Writes a ruby value to the native struct member as the appropriate native value.

Parameters:
runtime The ruby runtime
cache The value cache
ptr The struct memory area.
value The ruby value to write to the native struct member.
 
         public final void put(ThreadContext contextStorage cacheAbstractMemory ptrIRubyObject value) {
             .put(contextcachethisptrvalue);
         }

        
Reads a ruby value from the struct member.

Parameters:
cache The cache used to store
ptr The struct memory area.
Returns:
A ruby object equivalent to the native member value.
 
         public final IRubyObject get(ThreadContext contextStorage cacheAbstractMemory ptr) {
             return .get(contextcachethisptr);
         }
 
         public final int offset() {
             return ;
         }
 
         public final Type type() {
             return ;
         }
     }
 
     interface FieldIO {
        
Writes a ruby value to the native struct member as the appropriate native value.

Parameters:
runtime The ruby runtime
cache The value cache
ptr The struct memory area.
value The ruby value to write to the native struct member.
 
         public abstract void put(ThreadContext contextStorage cacheMember mAbstractMemory ptrIRubyObject value);

        
Reads a ruby value from the struct member.

Parameters:
cache The cache used to store
ptr The struct memory area.
Returns:
A ruby object equivalent to the native member value.
 
         public abstract IRubyObject get(ThreadContext contextStorage cacheMember mAbstractMemory ptr);

        
Gets the cacheable status of this Struct member

Returns:
true if this member type is cacheable
 
         public abstract boolean isCacheable();

        
Checks if a reference to the ruby object assigned to this field needs to be stored

Returns:
true if this member type requires the ruby value to be stored.
 
         public abstract boolean isValueReferenceNeeded();
     }
 
     static final class DefaultFieldIO implements FieldIO {
         public static final FieldIO INSTANCE = new DefaultFieldIO();
 
         public IRubyObject get(ThreadContext contextStorage cacheMember mAbstractMemory ptr) {
             return m.field.callMethod(context"get"ptr);
         }
 
         public void put(ThreadContext contextStorage cacheMember mAbstractMemory ptrIRubyObject value) {
             m.field.callMethod(context"put"new IRubyObject[] { ptrvalue });
         }
 
         public final boolean isCacheable() {
             return false;
         }
 
         public final boolean isValueReferenceNeeded() {
             return false;
         }
     }
 
     private static final class FieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new Field(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new FieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Field", parent="Object")
     public static class Field extends RubyObject {

        
The basic ops to read/write this field
 
         private FieldIO io;

        
The name of this field
 
         private IRubyObject name;

        
The Type of this field.
 
         private Type type;

        
The offset within the memory area of this member
 
         private int offset;
 
 
         Field(Ruby runtimeRubyClass klass) {
             this(runtimeklass.);
         }
 
         Field(Ruby runtimeRubyClass klassFieldIO io) {
             this(runtimeklass, (Typeruntime.getModule("FFI").getClass("Type").getConstant("VOID"),
                     -1, io);
             
         }
         
         Field(Ruby runtimeRubyClass klassType typeint offsetFieldIO io) {
             super(runtimeklass);
             this. = runtime.getNil();
             this. = type;
             this. = offset;
             this. = io;
         }
 
         void init(IRubyObject nameIRubyObject typeIRubyObject offset) {
             this. = name;
             this. = checkType(type);
             this. = RubyNumeric.num2int(offset);
         }
 
         void init(IRubyObject nameIRubyObject typeIRubyObject offsetFieldIO io) {
             init(nametypeoffset);
             this. = io;
         }
 
         void init(IRubyObject[] argsFieldIO io) {
             init(args[0], args[2], args[1], io);
         }
 
         @JRubyMethod(name="initialize", visibility = , required = 3, optional = 1)
         public IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
             
             init(args[0], args[2], args[1]);
 
             return this;
         }
 
         final Type checkType(IRubyObject type) {
             if (!(type instanceof Type)) {
                 throw getRuntime().newTypeError(typegetRuntime().getModule("FFI").getClass("Type"));
             }
             return (Typetype;
         }
 
         public final int offset() {
             return this.;
         }
 
         public final Type ffiType() {
             return ;
         }
 
         @Override
         public boolean equals(Object obj) {
             return obj instanceof Field && ((Fieldobj). ==  && ((Fieldobj)..equals();
         }
 
         @Override
         public int hashCode() {
             return 53 * 5 + (int) (this. ^ (this. >>> 32)) ^ .hashCode();
         }

        
Gets the cacheable status of this Struct member

Returns:
true if this member type is cacheable
 
         public final boolean isCacheable() {
             return .isCacheable();
         }

        
Checks if a reference to the ruby object assigned to this field needs to be stored

Returns:
true if this member type requires the ruby value to be stored.
 
         public final boolean isValueReferenceNeeded() {
             return .isValueReferenceNeeded();
         }
 
         final FieldIO getFieldIO() {
             return ;
         }
 
         static ByteOrder getByteOrderOption(ThreadContext contextIRubyObject[] args) {
 
             ByteOrder order = ByteOrder.nativeOrder();
 
             if (args.length > 3 && args[3] instanceof RubyHash) {
                 RubyHash options = (RubyHashargs[3];
                 IRubyObject byte_order = options.fastARef(RubySymbol.newSymbol(context.runtime"byte_order"));
                 if (byte_order instanceof RubySymbol || byte_order instanceof RubyString) {
                     String orderName = byte_order.asJavaString();
                     if ("network".equals(orderName) || "big".equals(orderName)) {
                         order = .;
                     
                     } else if ("little".equals(orderName)) {
                         order = .;
                     }
                 }
             }
             
             return order;
         }
 
         @JRubyMethod
         public final IRubyObject size(ThreadContext context) {
             return context.runtime.newFixnum(.getNativeSize());
         }
 
         @JRubyMethod
         public final IRubyObject alignment(ThreadContext context) {
             return context.runtime.newFixnum(.getNativeAlignment());
         }
 
         @JRubyMethod
         public final IRubyObject offset(ThreadContext context) {
             return context.runtime.newFixnum();
         }
 
         @JRubyMethod(name = { "type""ffi_type" })
         public final IRubyObject type(ThreadContext context) {
             return ;
         }
 
         @JRubyMethod
         public final IRubyObject name(ThreadContext context) {
             return ;
         }
     }
 
     private static final class NumberFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new NumberField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new NumberFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Number", parent="FFI::StructLayout::Field")
     public static final class NumberField extends Field {
 
         public NumberField(Ruby runtimeRubyClass klass) {
             super(runtimeklass);
         }
 
         @Override
         public final IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
 
             init(argsnew NumberFieldIO(checkType(args[2]), getByteOrderOption(contextargs)));
 
             return this;
         }
     }
 
     private static final class EnumFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new EnumField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new EnumFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Enum", parent="FFI::StructLayout::Field")
     public static final class EnumField extends Field {
         public EnumField(Ruby runtimeRubyClass klass) {
             super(runtimeklass);
         }
 
         @Override
         public final IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
 
             init(argsnew EnumFieldIO(getByteOrderOption(contextargs)));
 
             return this;
         }
     }
 
     private static final class StringFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new StringField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new StringFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::String", parent="FFI::StructLayout::Field")
     static final class StringField extends Field {
         public StringField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
     }
 
     private static final class PointerFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new PointerField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new PointerFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Pointer", parent="FFI::StructLayout::Field")
     public static final class PointerField extends Field {
         public PointerField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
     }
 
     private static final class FunctionFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new FunctionField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new FunctionFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Function", parent="FFI::StructLayout::Field")
     public static final class FunctionField extends Field {
 
         public FunctionField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
 
         @Override
         @JRubyMethod(name="initialize", visibility = , required = 3, optional = 1)
         public final IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
             
             IRubyObject type = args[2];
 
             if (!(type instanceof CallbackInfo)) {
                 throw context.runtime.newTypeError(typecontext.runtime.getModule("FFI").getClass("Type").getClass("Function"));
             }
             init(args.);
 
             return this;
         }
     }
 
     private static final class InnerStructFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new InnerStructField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new InnerStructFieldAllocator();
     }
     
     @JRubyClass(name="FFI::StructLayout::InnerStruct", parent="FFI::StructLayout::Field")
     public static final class InnerStructField extends Field {
 
         public InnerStructField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
         
         @Override
         @JRubyMethod(name="initialize", visibility = , required = 3, optional = 1)
         public IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
 
             IRubyObject type = args[2];
 
             if (!(type instanceof StructByValue)) {
                 throw context.runtime.newTypeError(type,
                         context.runtime.getModule("FFI").getClass("Type").getClass("Struct"));
             }
             init(argsnew InnerStructFieldIO((StructByValuetype));
 
             return this;
         }
     }
 
     private static final class ArrayFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new ArrayField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new ArrayFieldAllocator();
     }
     
     @JRubyClass(name="FFI::StructLayout::Array", parent="FFI::StructLayout::Field")
     public static final class ArrayField extends Field {
 
         public ArrayField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
 
         @Override
         @JRubyMethod(name="initialize", visibility = , required = 3, optional = 1)
         public final IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
 
             IRubyObject type = args[2];
             if (!(type instanceof Type.Array)) {
                 throw context.runtime.newTypeError(type,
                         context.runtime.getModule("FFI").getClass("Type").getClass("Array"));
             }
             init(argsnew ArrayFieldIO((Type.Arraytype));
 
             return this;
         }
     }
 
     private static final class MappedFieldAllocator implements ObjectAllocator {
         public final IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new MappedField(runtimeklass);
         }
         private static final ObjectAllocator INSTANCE = new MappedFieldAllocator();
     }
 
     @JRubyClass(name="FFI::StructLayout::Mapped", parent="FFI::StructLayout::Field")
     public static final class MappedField extends Field {
 
         public MappedField(Ruby runtimeRubyClass klass) {
             super(runtimeklass.);
         }
 
         @JRubyMethod(required = 4)
         public IRubyObject initialize(ThreadContext contextIRubyObject[] args) {
             if (!(args[2] instanceof MappedType)) {
                 throw context.runtime.newTypeError(args[2],
                         context.runtime.getModule("FFI").getClass("Type").getClass("Mapped"));
             }
 
             if (!(args[3] instanceof Field)) {
                 throw context.runtime.newTypeError(args[3],
                         context.runtime.getModule("FFI").getClass("StructLayout").getClass("Field"));
             }
 
             init(args[0], args[2], args[1], new MappedFieldIO((MappedTypeargs[2], ((Fieldargs[3]).getFieldIO()));
 
             return this;
         }
     }
 
 
     public static interface Storage {
         IRubyObject getCachedValue(Member member);
         void putCachedValue(Member memberIRubyObject value);
         void putReference(Member memberObject value);
     }
 
     static class NullStorage implements Storage {
         public IRubyObject getCachedValue(Member member) { return null; }
         public void putCachedValue(Member memberIRubyObject value) { }
         public void putReference(Member memberObject value) { }
     }
     
     @JRubyClass(name="FFI::StructLayout::ArrayProxy", parent="Object")
     public static class ArrayProxy extends RubyObject {
         protected final AbstractMemory ptr;
         final MemoryOp aio;
         protected final Type.Array arrayType;
         private final boolean cacheable;
         private IRubyObject[] valueCache;
 
         ArrayProxy(Ruby runtimeIRubyObject ptrlong offsetType.Array typeMemoryOp aio) {
             this(runtimeruntime.getModule("FFI").getClass().getClass("ArrayProxy"),
                     ptroffsettypeaio);
         }
 
         ArrayProxy(Ruby runtimeRubyClass klassIRubyObject ptrlong offsetType.Array typeMemoryOp aio) {
             super(runtimeklass);
             this. = ((AbstractMemoryptr).slice(runtimeoffsettype.getNativeSize());
             this. = type;
             this. = aio;
             this. = type.getComponentType() instanceof Type.Array 
                     || type.getComponentType() instanceof StructByValue;
         }
 
         private final long getOffset(IRubyObject index) {
             return getOffset(Util.int32Value(index));
         }
 
         private final long getOffset(int index) {
             if (index < 0 || index >= .length()) {
                 throw getRuntime().newIndexError("index " + index + " out of bounds");
             }
 
             return (long) (index * .getComponentType().getNativeSize());
         }
 
         private IRubyObject get(ThreadContext contextint index) {
             IRubyObject obj;
             
             if ( != null && (obj = [index]) != null) {
                 return obj;
             }
             putCachedValue(indexobj = .get(contextgetOffset(index)));
             
             return obj;
         }
         
         public final void putCachedValue(int idxIRubyObject value) {
             if () {
                 if ( == null) {
                      = new IRubyObject[.length()];
                 }
                 [idx] = value;
             }
         }
 
         @JRubyMethod(name = "[]")
         public IRubyObject get(ThreadContext contextIRubyObject index) {
             return get(context, Util.int32Value(index));
         }
 
         @JRubyMethod(name = "[]=")
         public IRubyObject put(ThreadContext contextIRubyObject indexIRubyObject value) {
             int idx = Util.int32Value(index);
             
             putCachedValue(idxvalue);
            
            .put(contextgetOffset(idx), value);
            
            return value;
        }
        @JRubyMethod(name = { "to_a""to_ary" })
        public IRubyObject get(ThreadContext context) {
            
            IRubyObject[] elems = new IRubyObject[.length()];
            for (int i = 0; i < elems.length; ++i) {
                elems[i] = get(contexti);
            }
            return RubyArray.newArrayNoCopy(context.runtimeelems);
        }
        @JRubyMethod(name = { "to_ptr" })
        public IRubyObject to_ptr(ThreadContext context) {
            return ;
        }
        @JRubyMethod(name = { "size" })
        public IRubyObject size(ThreadContext context) {
            return .length(context);
        }

        
Needed for Enumerable implementation
        @JRubyMethod(name = "each")
        public IRubyObject each(ThreadContext contextBlock block) {
            if (!block.isGiven()) {
                throw context.runtime.newLocalJumpErrorNoBlock();
            }
            for (int i = 0; i < .length(); ++i) {
                block.yield(contextget(contexti));
            }
            return this;
        }
        
    }
    @JRubyClass(name="FFI::StructLayout::CharArrayProxy", parent="FFI::StructLayout::ArrayProxy")
    public static final class CharArrayProxy extends ArrayProxy {
        CharArrayProxy(Ruby runtimeIRubyObject ptrlong offsetType.Array typeMemoryOp aio) {
            super(runtimeruntime.getModule("FFI").getClass("StructLayout").getClass("CharArrayProxy"),
                    ptroffsettypeaio);
        }
        @JRubyMethod(name = { "to_s" })
        public IRubyObject to_s(ThreadContext context) {
            return MemoryUtil.getTaintedString(context.runtime.getMemoryIO(), 0, .length());
        }
    }
    @JRubyClass(name="FFI::StructLayout::VariableLengthArrayProxy", parent="Object")
    public static class VariableLengthArrayProxy extends RubyObject {
        protected final AbstractMemory ptr;
        final MemoryOp aio;
        private final Type componentType;
        VariableLengthArrayProxy(Ruby runtimeIRubyObject ptrlong offsetType.Array typeMemoryOp aio) {