Translating FlagDefinition(s)

Flags are mapped to a Java wrapper, so that we're ensure typing during calls. Flags are just a special type of Enums where different binary values are used to specify a flag or type. The translation scheme is:

Let's take an enum PuppyFlags {Smart, Friendly, Fluffy}. The translation will produce a PuppyFlags java class, with the following structure.

Example 5-2. Flag Wrapper

import java.util.Hashtable;

final public class PuppyFlags {
  int value_;

  public PuppyFlags(int value) {
    value_ = value;
  }

  public int getValue() {
    return value_;
  }

  public int hashCode() {
    return value_;
  }

  public boolean equals(Object other) {
    return (other instanceof PuppyFlags)
      && (((PuppyFlags) other).value_ == value_);
  }

  static private Hashtable theInternedExtras = null;
  static private PuppyFlags theSacrificialOne = new PuppyFlags(0);
  static public synchronized PuppyFlags intern(int value) {
    if (value < theInterned.length)
      return theInterned[value];
    theSacrificialOne.value_ = value;
    if (theInternedExtras == null)
      theInternedExtras = new Hashtable();
    PuppyFlags already  = (PuppyFlags) theInternedExtras.get(theSacrificialOne);
    if (already == null) {
      already = new PuppyFlags(value);
      theInternedExtras.put(already, already);
    }
    return already;
  }
  static private PuppyFlags[] theInterned = {
    new PuppyFlags(0),
    new PuppyFlags(1),
    new PuppyFlags(2),
    new PuppyFlags(3),
    new PuppyFlags(4),
    new PuppyFlags(5),
    new PuppyFlags(6),
    new PuppyFlags(7)
  };
  public final static int _Smart = 1 << 0;
  public final static PuppyFlags Smart = PuppyFlags.intern(1 << 0);
  public final static int _Friendly = 1 << 1;
  public final static PuppyFlags Friendly = PuppyFlags.intern(1 << 1);
  public final static int _Fluffy = 1 << 2;
  public final static PuppyFlags Fluffy = PuppyFlags.intern(1 << 2);
}

A C function setPuppyFlags(PuppyFlags v) would be translated to a method setPuppyFlags(PuppyFlags v). This java method is generated to automatically unwrap the PuppyFlags Java object, and then pass the integer constant to the native code. Using the "PuppyFlags" wrapper is quite easy, either through the static instances which wrap the int values, or through the integer value, with the constructor and accessor (it might be useful in switch() blocks, for instance).

Every flag type comes with a means to intern elements of that type. Interning is the process by which, for a given integer value, only one corresponding object will ever be created, allowing for memory efficiency and the ability to compare objects using the == operator and having that be equivalent to using the Object.equals() method. The interning mechanism is set up so that a flag type may gain new elements dynamically. This isn't needed by every flag type, but there are some which do require this behavior. In particular, if a flag type has more than 8 bits, then not all of the possible values are created as wrapped objects initially. Only the first 256, plus the ones representing each of the other possible one-bit-on values, are created when the class gets initialized. All the rest are only created and interned on demand.

This translation closely mimics the one found in the CORBA IDL/Java mapping.