]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/java/net/tinyos/message/Message.java
Added getSerialPacket() and setSerialPacket() methods to the Message class so we...
[tinyos-2.x.git] / support / sdk / java / net / tinyos / message / Message.java
index 0ebb5080f9c712a2526166cfdb16f5490b81747d..a5fdd4495a6d801fe4ae531b9e4d69ca6b154004 100644 (file)
@@ -49,540 +49,641 @@ package net.tinyos.message;
 
 public class Message implements Cloneable {
 
-    /**
-     * The maximum number of characters read from an 8-bit array field
-     * being converted into a Java String.
-     */
-    public static final int MAX_CONVERTED_STRING_LENGTH = 512;
-
-    /** 
-     * The underlying byte array storing the data for this message. 
-     * This is private to enforce access to the data through the accessor
-     * methods in this class, which do bounds checking and manage the
-     * base_offset for embedded messages.
-     */
-    private byte[] data;
-
-    /** 
-     * The base offset into the data. This allows the message data to
-     * exist at some non-zero offset into the actual data.
-     */
-    protected int base_offset;
-
-    /**
-     * The actual length of the message data. Must be less than or
-     * equal to (data.length - base_offset).
-     */
-    protected int data_length;
-
-    /**
-     * The AM type corresponding to this object. Set to -1 if no AM type
-     * is known.
-     */
-    protected int am_type;
-
-    /** Limit no-arg instantiation. */
-    protected Message() {
-    }
-
-    /**
-     * Construct a new message of the given size.
-     * @param data_length The size of the message to create.
-     */
-    public Message(int data_length) {
-       init(data_length);
-    }
-    public void init(int data_length) {
-       init(new byte[data_length]);
-    }
-
-    /**
-     * Construct a new message of the given size and base offset.
-     * Allocates a new byte array of size data_length+base_offset.
-     * @param data_length The size of the message to create.
-     * @param base_offset The base offset into the newly created message.
-     */
-    public Message(int data_length, int base_offset) {
-      init(data_length, base_offset);
-    }
-    protected void init(int data_length, int base_offset) {
-      init(new byte[data_length+base_offset], base_offset);
-    }
-
-    /**
-     * Construct a message using data as the storage.
-     * The length of data determines the length of this message.
-     * @param data the storage for this message
-     */
-    public Message(byte[] data) {
-       init(data);
-    }
-    protected void init(byte[] data) {
-       init(data, 0);
-    }
-
-    /**
-     * Construct a message using data as the storage.
-     * Use the given base_offset as the base offset into the 
-     * data array. The data length will be (data.length - base_offset).
-     * @param data the storage for this message
-     * @param base_offset the base offset into the data array
-     */
-    public Message(byte[] data, int base_offset) {
-       init(data, base_offset);
-    }
-    protected void init(byte[] data, int base_offset) {
-       init(data, base_offset, data.length - base_offset);
-    }
-
-    /**
-     * Construct a message using data as the storage.
-     * Use the given base_offset as the base offset into the 
-     * data array, and the specified data length.
-     * @param data the storage for this message
-     * @param base_offset the base offset into the data array
-     * @param data_length the length of the message data
-     */
-    public Message(byte[] data, int base_offset, int data_length) {
-       init(data, base_offset, data_length);
-    }
-    protected void init(byte[] data, int base_offset, int data_length) {
-       this.data = data;
-       this.base_offset = base_offset;
-       this.data_length = data_length;
-       if (base_offset + data_length > data.length) throw new ArrayIndexOutOfBoundsException("Cannot create Message with base_offset "+base_offset+", data_length "+data_length+" and data array size "+data.length);
-    }
-
-    /**
-     * Construct an embedded message within the given 'msg'.
-     * Use the given base_offset as the base offset into the 
-     * data array, and the specified data length.
-     * @param msg the message to embed this message into
-     * @param base_offset the base offset into the data array
-     * @param data_length the length of the message data
-     */
-    public Message(Message msg, int base_offset, int data_length) {
-       init(msg, base_offset, data_length);
-    }
-    protected void init(Message msg, int base_offset, int data_length) {
-       init(msg.dataGet(), msg.base_offset+base_offset, data_length);
-    }
-
-    private Message cloneself() {
-       Message copy;
-
-       try {
-           copy = (Message)super.clone();
-       }
-       catch (CloneNotSupportedException e) {
-           System.err.println("Message: WARNING: CloneNotSupportedException in cloneself(): "+e);
-           System.err.println("Message: This is a bug - please contact dgay@intel-research.net");
-           copy = null;
-           System.exit(2);
-       }
-       return copy;
-    }
-
-    /**
-     * Clone this Message, including making a copy of its data
-     */
-    public Object clone() {
-       Message copy = cloneself();
-       copy.init((byte[])data.clone(), base_offset, data_length);
-       copy.am_type = this.am_type;
-       return copy;
-    }
-
-    /**
-     * Clone this Message, but give it a new unitialised data array of size
-     * size
-     * @param size size of the new data array
-     */
-    public Message clone(int size) {
-       Message copy = cloneself();
-       copy.init(new byte[size], 0, size);
-       copy.am_type = this.am_type;
-       return copy;
-    }
-
-    /**
-     * Copy new data for this message from 'data'. 
-     * Copies min(data.length, this.data_length) bytes.
-     * @param data the array containing the data to be copied
-     * @exception ArrayIndexOutOfBoundsException if any of
-     * data[0..getData().length - 1] are invalid
-     */
-    public void dataSet(byte[] data) {
-       dataSet(data, 0, this.base_offset, Math.min(this.data_length, data.length));
-    }
-
-    /**
-     * Copy new data for this message from offsetFrom in data to
-     * offsetTo in this message. Copies a total of length bytes
-     * @param data the array containing the data to be copied
-     * @param offsetFrom the offset in data to start copying from
-     * @param offsetTo the offset at which to start copying data into
-     * this message.
-     * @param length bytes are copied.
-     * @exception ArrayIndexOutOfBoundsException if any of
-     * the source or target indices are invalid
-     */
-    public void dataSet(byte[] data, int offsetFrom, int offsetTo, int length) {
-      System.arraycopy(data, offsetFrom, this.data, offsetTo+base_offset, length);
-    }
-
-    /**
-     * Copy new data for this message from the raw data in msg to
-     * offsetTo in this message. Copies a total of msg.dataLength() bytes
-     * @param msg the message containing the data to be copied
-     * @param offsetTo the offset at which to start copying data into
-     * this message.
-     * @exception ArrayIndexOutOfBoundsException if any of
-     * the target indices are invalid
-     */
-    public void dataSet(Message msg, int offsetTo) {
-      System.arraycopy(msg.dataGet(), msg.baseOffset(),
-                      this.data, offsetTo+base_offset,
-                      msg.dataLength());
-    }
-
-    /**
-     * Return the raw byte array representing the data of this message.
-     * Note that only indices in the range
-     * (this.baseOffset(), this.baseOffset()+this.dataLength()) are
-     * valid. 
-     */
-    public byte[] dataGet() {
-       return data;
-    }
-
-    /**
-     * Return the base offset into the data array for this message.
-     */
-    public int baseOffset() {
-        return base_offset;
-    }
-
-    /**
-     * Return the length of the data (in bytes) contained in this message.
-     */
-    public int dataLength() {
-        return data_length;
-    }
-
-    /**
-     * Return the active message type of this message (-1 if unknown)
-     */
-    public int amType() {
-       return am_type;
-    }
-
-    /**
-     * Set the active message type of this message
-     */
-    public void amTypeSet(int type) {
-      this.am_type = type;
-    }
-
-    // Check that length bits from offset are in bounds
-    private void checkBounds(int offset, int length) {
-       if (offset < 0 || length <= 0 || offset + length > (data_length * 8))
-         throw new ArrayIndexOutOfBoundsException("Message.checkBounds: bad offset ("+offset+") or length ("+length+"), for data_length "+data_length+ " in class " + this.getClass());
-    }
-
-    // Check that value is valid for a bitfield of length length
-    private void checkValue(int length, long value) {
-       if (length != 64 && (value < 0 || value >= 1L << length))
-           throw new IllegalArgumentException("Message.checkValue: bad length ("+length+" or value ("+value+")");
-    }
-
-    // Unsigned byte read
-    private int ubyte(int offset) {
-       int val = data[base_offset+offset];
-
-       if (val < 0) return val + 256;
-       else return val;
-    }
-
-    // ASSUMES: little endian bits & bytes for the methods without BE, and
-    //   big endian bits & bytes for the methods with BE
-
-    /**
-     * Read the length bit unsigned little-endian int at offset
-     * @param offset bit offset where the unsigned int starts
-     * @param length bit length of the unsigned int
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     */
-    protected long getUIntElement(int offset, int length) {
-       checkBounds(offset, length);
-
-       int byteOffset = offset >> 3;
-       int bitOffset = offset & 7;
-       int shift = 0;
-       long val = 0;
-
-       // all in one byte case
-       if (length + bitOffset <= 8)
-           return (ubyte(byteOffset) >> bitOffset) & ((1 << length) - 1);
-
-       // get some high order bits
-       if (bitOffset > 0) {
-           val = ubyte(byteOffset) >> bitOffset;
-           byteOffset++;
-           shift += 8 - bitOffset;
-           length -= 8 - bitOffset;
-       }
-
-       while (length >= 8) {
-           val |= (long)ubyte(byteOffset++) << shift;
-           shift += 8;
-           length -= 8;
-       }
-
-       // data from last byte
-       if (length > 0)
-           val |= (long)(ubyte(byteOffset) & ((1 << length) - 1)) << shift;
-
-       return val;
-    }
-
-    /**
-     * Set the length bit unsigned little-endian int at offset to val
-     * @param offset bit offset where the unsigned int starts
-     * @param length bit length of the unsigned int
-     * @param val value to set the bit field to
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     * @exception IllegalArgumentException if val is an out-of-range value
-     * for this bitfield
-     */
-    protected void setUIntElement(int offset, int length, long val) {
-       checkBounds(offset, length);
-       //checkValue(length, val);
-
-       int byteOffset = offset >> 3;
-       int bitOffset = offset & 7;
-       int shift = 0;
-
-       // all in one byte case
-       if (length + bitOffset <= 8) {
-           data[base_offset+byteOffset] = (byte)
-               ((ubyte(byteOffset) & ~(((1 << length) - 1) << bitOffset))
-                | val << bitOffset);
-           return;
-       }
-
-       // set some high order bits
-       if (bitOffset > 0) {
-           data[base_offset+byteOffset] = (byte)
-               ((ubyte(byteOffset) & ((1 << bitOffset) - 1)) | val << bitOffset);
-           byteOffset++;
-           shift += 8 - bitOffset;
-           length -= 8 - bitOffset;
-       }
-
-       while (length >= 8) {
-           data[base_offset+(byteOffset++)] = (byte)(val >> shift);
-           shift += 8;
-           length -= 8;
-       }
-
-       // data for last byte
-       if (length > 0)
-           data[base_offset+byteOffset] = (byte)
-               ((ubyte(byteOffset) & ~((1 << length) - 1)) | val >> shift);
-    }
-
-    /**
-     * Read the length bit signed little-endian int at offset
-     * @param offset bit offset where the signed int starts
-     * @param length bit length of the signed int
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     */
-    protected long getSIntElement(int offset, int length)
-       throws ArrayIndexOutOfBoundsException {
-       long val = getUIntElement(offset, length);
-
-       if (length == 64)
-           return val;
-
-       if ((val & 1L << (length - 1)) != 0)
-           return val - (1L << length);
-
-       return val;
-    }
-
-    /**
-     * Set the length bit signed little-endian int at offset to val
-     * @param offset bit offset where the signed int starts
-     * @param length bit length of the signed int
-     * @param value value to set the bit field to
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     * @exception IllegalArgumentException if val is an out-of-range value
-     * for this bitfield
-     */ 
-   protected void setSIntElement(int offset, int length, long value)
-       throws ArrayIndexOutOfBoundsException {
-       if (length != 64 && value >= 1L << (length - 1))
-           throw new IllegalArgumentException();
-
-       if (length != 64 && value < 0)
-           value += 1L << length;
-
-       setUIntElement(offset, length, value);
-    }
-
-    /**
-     * Read the length bit unsigned big-endian int at offset
-     * @param offset bit offset where the unsigned int starts. Note that
-     *   these are big-endian bit offsets: bit 0 is the MSB, bit 7 the LSB.
-     * @param length bit length of the unsigned int
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     */
-    protected long getUIntBEElement(int offset, int length) {
-       checkBounds(offset, length);
-
-       int byteOffset = offset >> 3;
-       int bitOffset = offset & 7;
-       long val = 0;
-
-       // All in one byte case
-       if (length + bitOffset <= 8)
-           return (ubyte(byteOffset) >> (8 - bitOffset - length)) &
-               ((1 << length) - 1);
-
-       // get some high order bits
-       if (bitOffset > 0) {
-           length -= 8 - bitOffset;
-           val = (long)(ubyte(byteOffset) & ((1 << (8 - bitOffset)) - 1)) << length;
-           byteOffset++;
-       }
-
-       while (length >= 8) {
-           length -= 8;
-           val |= (long)ubyte(byteOffset++) << length;
-       }
-
-       // data from last byte
-       if (length > 0)
-           val |= ubyte(byteOffset) >> (8 - length);
-
-       return val;
-    }
-
-    /**
-     * Set the length bit unsigned big-endian int at offset to val
-     * @param offset bit offset where the unsigned int starts. Note that
-     *   these are big-endian bit offsets: bit 0 is the MSB, bit 7 the LSB.
-     * @param length bit length of the unsigned int
-     * @param val value to set the bit field to
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     * @exception IllegalArgumentException if val is an out-of-range value
-     * for this bitfield
-     */
-    protected void setUIntBEElement(int offset, int length, long val) {
-       checkBounds(offset, length);
-       //checkValue(length, val);
-
-       int byteOffset = offset >> 3;
-       int bitOffset = offset & 7;
-       int shift = 0;
-
-       // all in one byte case
-       if (length + bitOffset <= 8) {
-           int mask = ((1 << length) - 1) << (8 - bitOffset - length);
-
-           data[base_offset+byteOffset] = (byte)
-               ((ubyte(byteOffset) & ~mask)
-                | val << (8 - bitOffset - length));
-           return;
-       }
-
-       // set some high order bits
-       if (bitOffset > 0) {
-           int mask = (1 << (8 - bitOffset)) - 1;
-
-           length -= 8 - bitOffset;
-           data[base_offset+byteOffset] = (byte)
-               (ubyte(byteOffset) & ~mask | val >> length);
-           byteOffset++;
-       }
-
-       while (length >= 8) {
-           length -= 8;
-           data[base_offset+(byteOffset++)] = (byte)(val >> length);
-       }
-
-       // data for last byte
-       if (length > 0) {
-           int mask = (1 << (8 - length)) - 1;
-
-           data[base_offset+byteOffset] = (byte)
-               ((ubyte(byteOffset) & mask) | val << (8 - length));
-       }
-    }
-
-    /**
-     * Read the length bit signed big-endian int at offset
-     * @param offset bit offset where the signed int starts
-     * @param length bit length of the signed int
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     */
-    protected long getSIntBEElement(int offset, int length)
-       throws ArrayIndexOutOfBoundsException {
-       long val = getUIntBEElement(offset, length);
-
-       if (length == 64)
-           return val;
-
-       if ((val & 1L << (length - 1)) != 0)
-           return val - (1L << length);
-
-       return val;
-    }
-
-    /**
-     * Set the length bit signed big-endian int at offset to val
-     * @param offset bit offset where the signed int starts
-     * @param length bit length of the signed int
-     * @param value value to set the bit field to
-     * @exception ArrayIndexOutOfBoundsException for invalid offset, length
-     * @exception IllegalArgumentException if val is an out-of-range value
-     * for this bitfield
-     */ 
-   protected void setSIntBEElement(int offset, int length, long value)
-       throws ArrayIndexOutOfBoundsException {
-       if (length != 64 && value >= 1L << (length - 1))
-           throw new IllegalArgumentException();
-
-       if (length != 64 && value < 0)
-           value += 1L << length;
-
-       setUIntBEElement(offset, length, value);
-    }
-
-    /**
-     * Read the 32 bit IEEE float at offset
-     * @param offset bit offset where the float starts
-     * @param length is ignored
-     * @exception ArrayIndexOutOfBoundsException for invalid offset
-     */
-    protected float getFloatElement(int offset, int length)
-       throws ArrayIndexOutOfBoundsException {
-
-       return Float.intBitsToFloat((int)getUIntElement(offset, 32));
-    }
-
-    /**
-     * Set the 32 bit IEEE float at offset to value
-     * @param offset bit offset where the float starts
-     * @param length is ignored
-     * @param value value to store in bitfield
-     * @exception ArrayIndexOutOfBoundsException for invalid offset
-     */
-    protected void setFloatElement(int offset, int length, float value)
-       throws ArrayIndexOutOfBoundsException {
-
-       // using SInt because floatToRawIntBits might return a negative value
-       setSIntElement(offset, 32, Float.floatToRawIntBits(value));
-    }
+  /**
+   * The maximum number of characters read from an 8-bit array field being
+   * converted into a Java String.
+   */
+  public static final int MAX_CONVERTED_STRING_LENGTH = 512;
+
+  /**
+   * The underlying byte array storing the data for this message. This is
+   * private to enforce access to the data through the accessor methods in this
+   * class, which do bounds checking and manage the base_offset for embedded
+   * messages.
+   */
+  private byte[] data;
+
+  /**
+   * The base offset into the data. This allows the message data to exist at
+   * some non-zero offset into the actual data.
+   */
+  protected int base_offset;
+
+  /**
+   * The actual length of the message data. Must be less than or equal to
+   * (data.length - base_offset).
+   */
+  protected int data_length;
+
+  /**
+   * The AM type corresponding to this object. Set to -1 if no AM type is known.
+   */
+  protected int am_type;
+
+  /** The serial packet this message originated from */
+  private SerialPacket serialPacket;
+  
+  /** Limit no-arg instantiation. */
+  protected Message() {
+  }
+
+  /**
+   * Construct a new message of the given size.
+   * 
+   * @param data_length
+   *          The size of the message to create.
+   */
+  public Message(int data_length) {
+    init(data_length);
+  }
+
+  public void init(int data_length) {
+    init(new byte[data_length]);
+  }
+
+  /**
+   * Construct a new message of the given size and base offset. Allocates a new
+   * byte array of size data_length+base_offset.
+   * 
+   * @param data_length
+   *          The size of the message to create.
+   * @param base_offset
+   *          The base offset into the newly created message.
+   */
+  public Message(int data_length, int base_offset) {
+    init(data_length, base_offset);
+  }
+
+  protected void init(int data_length, int base_offset) {
+    init(new byte[data_length + base_offset], base_offset);
+  }
+
+  /**
+   * Construct a message using data as the storage. The length of data
+   * determines the length of this message.
+   * 
+   * @param data
+   *          the storage for this message
+   */
+  public Message(byte[] data) {
+    init(data);
+  }
+
+  protected void init(byte[] data) {
+    init(data, 0);
+  }
+
+  /**
+   * Construct a message using data as the storage. Use the given base_offset as
+   * the base offset into the data array. The data length will be (data.length -
+   * base_offset).
+   * 
+   * @param data
+   *          the storage for this message
+   * @param base_offset
+   *          the base offset into the data array
+   */
+  public Message(byte[] data, int base_offset) {
+    init(data, base_offset);
+  }
+
+  protected void init(byte[] data, int base_offset) {
+    init(data, base_offset, data.length - base_offset);
+  }
+
+  /**
+   * Construct a message using data as the storage. Use the given base_offset as
+   * the base offset into the data array, and the specified data length.
+   * 
+   * @param data
+   *          the storage for this message
+   * @param base_offset
+   *          the base offset into the data array
+   * @param data_length
+   *          the length of the message data
+   */
+  public Message(byte[] data, int base_offset, int data_length) {
+    init(data, base_offset, data_length);
+  }
+
+  protected void init(byte[] data, int base_offset, int data_length) {
+    this.data = data;
+    this.base_offset = base_offset;
+    this.data_length = data_length;
+    if (base_offset + data_length > data.length)
+      throw new ArrayIndexOutOfBoundsException(
+          "Cannot create Message with base_offset " + base_offset
+              + ", data_length " + data_length + " and data array size "
+              + data.length);
+  }
+
+  /**
+   * Construct an embedded message within the given 'msg'. Use the given
+   * base_offset as the base offset into the data array, and the specified data
+   * length.
+   * 
+   * @param msg
+   *          the message to embed this message into
+   * @param base_offset
+   *          the base offset into the data array
+   * @param data_length
+   *          the length of the message data
+   */
+  public Message(Message msg, int base_offset, int data_length) {
+    init(msg, base_offset, data_length);
+  }
+
+  protected void init(Message msg, int base_offset, int data_length) {
+    init(msg.dataGet(), msg.base_offset + base_offset, data_length);
+  }
+
+  private Message cloneself() {
+    Message copy;
+
+    try {
+      copy = (Message) super.clone();
+    } catch (CloneNotSupportedException e) {
+      System.err
+          .println("Message: WARNING: CloneNotSupportedException in cloneself(): "
+              + e);
+      System.err
+          .println("Message: This is a bug - please contact dgay@intel-research.net");
+      copy = null;
+      System.exit(2);
+    }
+    return copy;
+  }
+
+  /**
+   * Clone this Message, including making a copy of its data
+   */
+  public Object clone() {
+    Message copy = cloneself();
+    copy.init((byte[]) data.clone(), base_offset, data_length);
+    copy.am_type = this.am_type;
+    return copy;
+  }
+
+  /**
+   * Clone this Message, but give it a new unitialised data array of size size
+   * 
+   * @param size
+   *          size of the new data array
+   */
+  public Message clone(int size) {
+    Message copy = cloneself();
+    copy.init(new byte[size], 0, size);
+    copy.am_type = this.am_type;
+    return copy;
+  }
+
+  /**
+   * Copy new data for this message from 'data'. Copies min(data.length,
+   * this.data_length) bytes.
+   * 
+   * @param data
+   *          the array containing the data to be copied
+   * @exception ArrayIndexOutOfBoundsException
+   *              if any of data[0..getData().length - 1] are invalid
+   */
+  public void dataSet(byte[] data) {
+    dataSet(data, 0, this.base_offset, Math.min(this.data_length, data.length));
+  }
+
+  /**
+   * Copy new data for this message from offsetFrom in data to offsetTo in this
+   * message. Copies a total of length bytes
+   * 
+   * @param data
+   *          the array containing the data to be copied
+   * @param offsetFrom
+   *          the offset in data to start copying from
+   * @param offsetTo
+   *          the offset at which to start copying data into this message.
+   * @param length
+   *          bytes are copied.
+   * @exception ArrayIndexOutOfBoundsException
+   *              if any of the source or target indices are invalid
+   */
+  public void dataSet(byte[] data, int offsetFrom, int offsetTo, int length) {
+    System.arraycopy(data, offsetFrom, this.data, offsetTo + base_offset,
+        length);
+  }
+
+  /**
+   * Copy new data for this message from the raw data in msg to offsetTo in this
+   * message. Copies a total of msg.dataLength() bytes
+   * 
+   * @param msg
+   *          the message containing the data to be copied
+   * @param offsetTo
+   *          the offset at which to start copying data into this message.
+   * @exception ArrayIndexOutOfBoundsException
+   *              if any of the target indices are invalid
+   */
+  public void dataSet(Message msg, int offsetTo) {
+    System.arraycopy(msg.dataGet(), msg.baseOffset(), this.data, offsetTo
+        + base_offset, msg.dataLength());
+  }
+
+  /**
+   * Return the raw byte array representing the data of this message. Note that
+   * only indices in the range (this.baseOffset(),
+   * this.baseOffset()+this.dataLength()) are valid.
+   */
+  public byte[] dataGet() {
+    return data;
+  }
+
+  /**
+   * Return the base offset into the data array for this message.
+   */
+  public int baseOffset() {
+    return base_offset;
+  }
+
+  /**
+   * Return the length of the data (in bytes) contained in this message.
+   */
+  public int dataLength() {
+    return data_length;
+  }
+
+  /**
+   * Return the active message type of this message (-1 if unknown)
+   */
+  public int amType() {
+    return am_type;
+  }
+
+  /**
+   * Set the active message type of this message
+   */
+  public void amTypeSet(int type) {
+    this.am_type = type;
+  }
+
+  // Check that length bits from offset are in bounds
+  private void checkBounds(int offset, int length) {
+    if (offset < 0 || length <= 0 || offset + length > (data_length * 8))
+      throw new ArrayIndexOutOfBoundsException(
+          "Message.checkBounds: bad offset (" + offset + ") or length ("
+              + length + "), for data_length " + data_length + " in class "
+              + this.getClass());
+  }
+
+  // Check that value is valid for a bitfield of length length
+  private void checkValue(int length, long value) {
+    if (length != 64 && (value < 0 || value >= 1L << length))
+      throw new IllegalArgumentException("Message.checkValue: bad length ("
+          + length + " or value (" + value + ")");
+  }
+
+  // Unsigned byte read
+  private int ubyte(int offset) {
+    int val = data[base_offset + offset];
+
+    if (val < 0)
+      return val + 256;
+    else
+      return val;
+  }
+
+  // ASSUMES: little endian bits & bytes for the methods without BE, and
+  // big endian bits & bytes for the methods with BE
+
+  /**
+   * Read the length bit unsigned little-endian int at offset
+   * 
+   * @param offset
+   *          bit offset where the unsigned int starts
+   * @param length
+   *          bit length of the unsigned int
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   */
+  protected long getUIntElement(int offset, int length) {
+    checkBounds(offset, length);
+
+    int byteOffset = offset >> 3;
+    int bitOffset = offset & 7;
+    int shift = 0;
+    long val = 0;
+
+    // all in one byte case
+    if (length + bitOffset <= 8)
+      return (ubyte(byteOffset) >> bitOffset) & ((1 << length) - 1);
+
+    // get some high order bits
+    if (bitOffset > 0) {
+      val = ubyte(byteOffset) >> bitOffset;
+      byteOffset++;
+      shift += 8 - bitOffset;
+      length -= 8 - bitOffset;
+    }
+
+    while (length >= 8) {
+      val |= (long) ubyte(byteOffset++) << shift;
+      shift += 8;
+      length -= 8;
+    }
+
+    // data from last byte
+    if (length > 0)
+      val |= (long) (ubyte(byteOffset) & ((1 << length) - 1)) << shift;
+
+    return val;
+  }
+
+  /**
+   * Set the length bit unsigned little-endian int at offset to val
+   * 
+   * @param offset
+   *          bit offset where the unsigned int starts
+   * @param length
+   *          bit length of the unsigned int
+   * @param val
+   *          value to set the bit field to
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   * @exception IllegalArgumentException
+   *              if val is an out-of-range value for this bitfield
+   */
+  protected void setUIntElement(int offset, int length, long val) {
+    checkBounds(offset, length);
+    // checkValue(length, val);
+
+    int byteOffset = offset >> 3;
+    int bitOffset = offset & 7;
+    int shift = 0;
+
+    // all in one byte case
+    if (length + bitOffset <= 8) {
+      data[base_offset + byteOffset] = (byte) ((ubyte(byteOffset) & ~(((1 << length) - 1) << bitOffset)) | val << bitOffset);
+      return;
+    }
+
+    // set some high order bits
+    if (bitOffset > 0) {
+      data[base_offset + byteOffset] = (byte) ((ubyte(byteOffset) & ((1 << bitOffset) - 1)) | val << bitOffset);
+      byteOffset++;
+      shift += 8 - bitOffset;
+      length -= 8 - bitOffset;
+    }
+
+    while (length >= 8) {
+      data[base_offset + (byteOffset++)] = (byte) (val >> shift);
+      shift += 8;
+      length -= 8;
+    }
+
+    // data for last byte
+    if (length > 0)
+      data[base_offset + byteOffset] = (byte) ((ubyte(byteOffset) & ~((1 << length) - 1)) | val >> shift);
+  }
+
+  /**
+   * Read the length bit signed little-endian int at offset
+   * 
+   * @param offset
+   *          bit offset where the signed int starts
+   * @param length
+   *          bit length of the signed int
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   */
+  protected long getSIntElement(int offset, int length)
+      throws ArrayIndexOutOfBoundsException {
+    long val = getUIntElement(offset, length);
+
+    if (length == 64)
+      return val;
+
+    if ((val & 1L << (length - 1)) != 0)
+      return val - (1L << length);
+
+    return val;
+  }
+
+  /**
+   * Set the length bit signed little-endian int at offset to val
+   * 
+   * @param offset
+   *          bit offset where the signed int starts
+   * @param length
+   *          bit length of the signed int
+   * @param value
+   *          value to set the bit field to
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   * @exception IllegalArgumentException
+   *              if val is an out-of-range value for this bitfield
+   */
+  protected void setSIntElement(int offset, int length, long value)
+      throws ArrayIndexOutOfBoundsException {
+    if (length != 64 && value >= 1L << (length - 1))
+      throw new IllegalArgumentException();
+
+    if (length != 64 && value < 0)
+      value += 1L << length;
+
+    setUIntElement(offset, length, value);
+  }
+
+  /**
+   * Read the length bit unsigned big-endian int at offset
+   * 
+   * @param offset
+   *          bit offset where the unsigned int starts. Note that these are
+   *          big-endian bit offsets: bit 0 is the MSB, bit 7 the LSB.
+   * @param length
+   *          bit length of the unsigned int
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   */
+  protected long getUIntBEElement(int offset, int length) {
+    checkBounds(offset, length);
+
+    int byteOffset = offset >> 3;
+    int bitOffset = offset & 7;
+    long val = 0;
+
+    // All in one byte case
+    if (length + bitOffset <= 8)
+      return (ubyte(byteOffset) >> (8 - bitOffset - length))
+          & ((1 << length) - 1);
+
+    // get some high order bits
+    if (bitOffset > 0) {
+      length -= 8 - bitOffset;
+      val = (long) (ubyte(byteOffset) & ((1 << (8 - bitOffset)) - 1)) << length;
+      byteOffset++;
+    }
+
+    while (length >= 8) {
+      length -= 8;
+      val |= (long) ubyte(byteOffset++) << length;
+    }
+
+    // data from last byte
+    if (length > 0)
+      val |= ubyte(byteOffset) >> (8 - length);
+
+    return val;
+  }
+
+  /**
+   * Set the length bit unsigned big-endian int at offset to val
+   * 
+   * @param offset
+   *          bit offset where the unsigned int starts. Note that these are
+   *          big-endian bit offsets: bit 0 is the MSB, bit 7 the LSB.
+   * @param length
+   *          bit length of the unsigned int
+   * @param val
+   *          value to set the bit field to
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   * @exception IllegalArgumentException
+   *              if val is an out-of-range value for this bitfield
+   */
+  protected void setUIntBEElement(int offset, int length, long val) {
+    checkBounds(offset, length);
+    // checkValue(length, val);
+
+    int byteOffset = offset >> 3;
+    int bitOffset = offset & 7;
+    int shift = 0;
+
+    // all in one byte case
+    if (length + bitOffset <= 8) {
+      int mask = ((1 << length) - 1) << (8 - bitOffset - length);
+
+      data[base_offset + byteOffset] = (byte) ((ubyte(byteOffset) & ~mask) | val << (8 - bitOffset - length));
+      return;
+    }
+
+    // set some high order bits
+    if (bitOffset > 0) {
+      int mask = (1 << (8 - bitOffset)) - 1;
+
+      length -= 8 - bitOffset;
+      data[base_offset + byteOffset] = (byte) (ubyte(byteOffset) & ~mask | val >> length);
+      byteOffset++;
+    }
+
+    while (length >= 8) {
+      length -= 8;
+      data[base_offset + (byteOffset++)] = (byte) (val >> length);
+    }
+
+    // data for last byte
+    if (length > 0) {
+      int mask = (1 << (8 - length)) - 1;
+
+      data[base_offset + byteOffset] = (byte) ((ubyte(byteOffset) & mask) | val << (8 - length));
+    }
+  }
+
+  /**
+   * Read the length bit signed big-endian int at offset
+   * 
+   * @param offset
+   *          bit offset where the signed int starts
+   * @param length
+   *          bit length of the signed int
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   */
+  protected long getSIntBEElement(int offset, int length)
+      throws ArrayIndexOutOfBoundsException {
+    long val = getUIntBEElement(offset, length);
+
+    if (length == 64)
+      return val;
+
+    if ((val & 1L << (length - 1)) != 0)
+      return val - (1L << length);
+
+    return val;
+  }
+
+  /**
+   * Set the length bit signed big-endian int at offset to val
+   * 
+   * @param offset
+   *          bit offset where the signed int starts
+   * @param length
+   *          bit length of the signed int
+   * @param value
+   *          value to set the bit field to
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset, length
+   * @exception IllegalArgumentException
+   *              if val is an out-of-range value for this bitfield
+   */
+  protected void setSIntBEElement(int offset, int length, long value)
+      throws ArrayIndexOutOfBoundsException {
+    if (length != 64 && value >= 1L << (length - 1))
+      throw new IllegalArgumentException();
+
+    if (length != 64 && value < 0)
+      value += 1L << length;
+
+    setUIntBEElement(offset, length, value);
+  }
+
+  /**
+   * Read the 32 bit IEEE float at offset
+   * 
+   * @param offset
+   *          bit offset where the float starts
+   * @param length
+   *          is ignored
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset
+   */
+  protected float getFloatElement(int offset, int length)
+      throws ArrayIndexOutOfBoundsException {
+
+    return Float.intBitsToFloat((int) getUIntElement(offset, 32));
+  }
+
+  /**
+   * Set the 32 bit IEEE float at offset to value
+   * 
+   * @param offset
+   *          bit offset where the float starts
+   * @param length
+   *          is ignored
+   * @param value
+   *          value to store in bitfield
+   * @exception ArrayIndexOutOfBoundsException
+   *              for invalid offset
+   */
+  protected void setFloatElement(int offset, int length, float value)
+      throws ArrayIndexOutOfBoundsException {
+
+    // using SInt because floatToRawIntBits might return a negative value
+    setSIntElement(offset, 32, Float.floatToRawIntBits(value));
+  }
+
+  /**
+   * 
+   * @return the SerialPacket this message originated from, if it was set
+   *     externally
+   */
+  public SerialPacket getSerialPacket() {
+    return serialPacket;
+  }
+
+  /**
+   * 
+   * @param mySerialPacket the SerialPacket this message originated from
+   */
+  protected void setSerialPacket(SerialPacket mySerialPacket) {
+    serialPacket = mySerialPacket;
+  }
+  
+  
 }