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

us.ihmc.idl.CDR Maven / Gradle / Ivy

/**
 * Copyright 2024 Florida Institute for Human and Machine Cognition (IHMC)
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package us.ihmc.idl;

import java.nio.ByteBuffer;

import org.apache.commons.lang3.NotImplementedException;

import us.ihmc.pubsub.common.SerializedPayload;

/**
 * Helper class to serialize and deserialize IDL messages.
 * 
 * It should not be necessary to use this class directly. Use the IDLGenerator to create the neccessary java files to serialize and deserialize messages
 * 
 * @author Jesper Smith
 *
 */
public class CDR
{
   private static final int encapsulation_size = 4;
   public static final int UNSIGNED_SHORT_MAX = 0xFFFF;
   public static final long UNSIGNED_INT_MAX = 0xFFFFFFFFL;

   private SerializedPayload payload;
   private ByteBuffer buf;
   private static short options = 0x0;

   public static int alignment(int current_alignment, int dataSize)
   {
      return (dataSize - (current_alignment % dataSize)) & (dataSize - 1);
   }

   public void serialize(SerializedPayload payload)
   {
      writeEncapsulation(payload);

      buf = payload.getData();
      this.payload = payload;

   }

   public static void writeEncapsulation(SerializedPayload payload)
   {
      ByteBuffer buf = payload.getData();
      //Write encapsulation
      buf.put((byte) 0x0);
      buf.put((byte) payload.getEncapsulation());
      buf.putShort(options);
   }

   public void deserialize(SerializedPayload payload)
   {
      readEncapsulation(payload);
      buf = payload.getData();
      this.payload = payload;
   }
   
   public static void readEncapsulation(SerializedPayload payload)
   {
      ByteBuffer buf = payload.getData();
      /* int dummy = */ buf.get();
      short encapsulation = buf.get();
      payload.setEncapsulation(encapsulation);
      /* this.options = */ buf.getShort();
   }

   public void finishSerialize()
   {
      buf.flip();
      payload.setLength(buf.limit());
   }

   public void finishDeserialize()
   {
   }
   
   public static int getTypeSize(int elementTypeSize)
   {
      return elementTypeSize + encapsulation_size;
   }

   /**
    * Signed short
    */
   public short read_type_1()
   {
      align(2);
      return buf.getShort();
   }

   public void write_type_1(short val)
   {
      align(2);
      buf.putShort(val);
   }

   /**
    * Signed int
    */
   public int read_type_2()
   {
      align(4);
      return buf.getInt();
   }

   public void write_type_2(int val)
   {
      align(4);
      buf.putInt(val);
   }

   /**
    * Unsigned short
    */
   public int read_type_3()
   {
      return Short.toUnsignedInt(read_type_1());
   }

   public void write_type_3(int val)
   {
      if (val < 0)
         throw new ArithmeticException("(CDR.java:134): int " + val + " cannot be cast to unsigned short. cannot be negative");
      else if (val > UNSIGNED_SHORT_MAX)
         throw new ArithmeticException("(CDR.java:134): int " + val + " cannot be cast to unsigned short. UNSIGNED_SHORT_MAX = " + UNSIGNED_SHORT_MAX);

      write_type_1((short) val);
   }

   /**
    * Unsigned int
    */
   public long read_type_4()
   {
      return Integer.toUnsignedLong(read_type_2());
   }

   public void write_type_4(long val)
   {
      if (val < 0)
         throw new ArithmeticException("(CDR.java:134): long " + val + " cannot be cast to unsigned int. cannot be negative");
      else if (val > UNSIGNED_INT_MAX)
         throw new ArithmeticException("(CDR.java:134): long " + val + " cannot be cast to unsigned int. UNSIGNED_INT_MAX = " + UNSIGNED_INT_MAX);

      write_type_2((int) val);
   }

   /**
    * Float
    */
   public float read_type_5()
   {
      align(4);
      return buf.getFloat();
   }

   public void write_type_5(float val)
   {
      align(4);
      buf.putFloat(val);
   }

   /**
    * Double
    */
   public double read_type_6()
   {
      align(8);
      return buf.getDouble();
   }

   public void write_type_6(double val)
   {
      align(8);
      buf.putDouble(val);
   }

   /**
    * Boolean
    */
   public boolean read_type_7()
   {
      int val = read_type_9();
      return val != (byte) 0;
   }

   public void write_type_7(boolean val)
   {
      write_type_9(val ? (byte) 1 : (byte) 0);
   }

   /**
    * Char
    */
   public char read_type_8()
   {
      return (char) (buf.get() & 0xFF);
   }

   public void write_type_8(char val)
   {
      buf.put((byte) val);
   }

   /**
    * Octet
    */
   public byte read_type_9()
   {
      return buf.get();
   }

   public void write_type_9(byte val)
   {
      buf.put(val);
   }

   /**
    * Union
    */
   public Object read_type_b()
   {
      throw new NotImplementedException("Union types are not implemented yet");
   }

   public void write_type_b(Object object)
   {
      throw new NotImplementedException("Union types are not implemented yet");
   }

   /**
    * Enum
    */

   public int read_type_c()
   {
      return read_type_2();
   }

   public void write_type_c(int val)
   {
      write_type_2(val);
   }

   /**
    * String
    */
   public void read_type_d(StringBuilder res)
   {
      int length = read_type_2() - 1;
      res.setLength(length);
      for (int i = 0; i < length; i++)
      {
         res.setCharAt(i, (char) buf.get());
      }
      buf.get();
   }

   public void write_type_d(StringBuilder str)
   {
      write_type_2(str.length() + 1);
      for (int i = 0; i < str.length(); i++)
      {
         buf.put((byte) str.charAt(i));
      }
      buf.put((byte) 0);
   }

   /**
    * Sequence
    */
   public void read_type_e(IDLSequence seq)
   {
      int length = read_type_2();
      seq.resetQuick();

      if (seq instanceof IDLSequence.Byte byteSeq) // faster copy
      {
         byteSeq.getBuffer().put(0, buf, buf.position(), length);
         byteSeq.getBuffer().position(length);
         buf.position(buf.position() + length);
      }
      else
      {
         for (int i = 0; i < length; i++)
         {
            seq.readElement(i, this);
         }
      }
   }

   public void write_type_e(IDLSequence seq)
   {
      int length = seq.size();
      write_type_2(length);

      if (seq instanceof IDLSequence.Byte byteSeq) // faster copy
      {
         buf.put(buf.position(), byteSeq.getBuffer(), 0, length);
         buf.position(buf.position() + length);
      }
      else
      {
         for (int i = 0; i < length; i++)
         {
            seq.writeElement(i, this);
         }
      }
   }

   /** 
    * Array
    */
   public void read_type_f()
   {

   }

   /**
    * Signed long, 64 bit
    */
   public long read_type_11()
   {
      align(8);
      return buf.getLong();
   }

   public void write_type_11(long val)
   {
      align(8);
      buf.putLong(val);
   }

   /**
    * Unsigned long, 64bit
    */
   public long read_type_12()
   {
      return read_type_11();
   }

   public void write_type_12(long val)
   {
      write_type_11(val);
   }

   /**
    * Long doubles (16 bytes, unsupported)
    */
   public double read_type_13()
   {
      throw new NotImplementedException("Java does not support 16 byte Double values");
   }

   public void write_type_13(double val)
   {
      throw new NotImplementedException("Java does not support 16 byte Double values");
   }

   /**
    * Wide char (32 bits)
    */
   public char read_type_14()
   {
      return (char) read_type_2();
   }

   public void write_type_14(char val)
   {
      write_type_2((int) val);
   }

   /**
    * Wide string
    */
   public void read_type_15(StringBuilder res)
   {
      int length = read_type_2();
      res.setLength(length);
      for (int i = 0; i < length; i++)
      {
         res.setCharAt(i, buf.getChar());
      }
   }

   public void write_type_15(StringBuilder str)
   {
      write_type_2(str.length());
      for (int i = 0; i < str.length(); i++)
      {
         buf.putChar(str.charAt(i));
      }
   }

   public int align(int byteBoundary)
   {
      int position = buf.position() - encapsulation_size;
      int adv = (position % byteBoundary);

      if (adv != 0)
      {
         buf.position(position + encapsulation_size + (byteBoundary - adv));
      }

      return adv;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy