View Javadoc
1   package org.sim0mq.message.util;
2   
3   import java.nio.ByteOrder;
4   
5   /**
6    * Method to help with Little Endian / Big Endian conversions for the Sim0MQ messages. All Sim0MQ messages are encoded Big
7    * Endian over the wire.
8    * <p>
9    * Copyright (c) 2016-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
10   * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>.
11   * </p>
12   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
13   * initial version Dec 15, 2016 <br>
14   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
15   */
16  public final class EndianUtil
17  {
18      /** do we want to send the messages in big endian? */
19      private static boolean defaultBigEndian = true;
20  
21      /** is the platform big endian? */
22      private static final boolean PLATFORM_BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
23  
24      /**
25       * Utility class - do not instantiate.
26       */
27      private EndianUtil()
28      {
29          //
30      }
31  
32      /**
33       * Decode a short.
34       * @param message the ZeroMQ byte array to decode
35       * @param pointer the first byte to consider
36       * @return the short value
37       */
38      public static short decodeShort(final byte[] message, final int pointer)
39      {
40          if (defaultBigEndian)
41          {
42              return (short) (((message[pointer] & 0xff) << 8) | ((message[pointer + 1] & 0xff)));
43          }
44          else
45          {
46              return (short) (((message[pointer + 1] & 0xff) << 8) | ((message[pointer] & 0xff)));
47          }
48      }
49  
50      /**
51       * Decode a int.
52       * @param message the ZeroMQ byte array to decode
53       * @param pointer the first byte to consider
54       * @return the integer value
55       */
56      public static int decodeInt(final byte[] message, final int pointer)
57      {
58          if (defaultBigEndian)
59          {
60              return (((message[pointer] & 0xff) << 24) | ((message[pointer + 1] & 0xff) << 16)
61                      | ((message[pointer + 2] & 0xff) << 8) | ((message[pointer + 3] & 0xff)));
62          }
63          else
64          {
65              return (((message[pointer + 3] & 0xff) << 24) | ((message[pointer + 2] & 0xff) << 16)
66                      | ((message[pointer + 1] & 0xff) << 8) | ((message[pointer] & 0xff)));
67          }
68      }
69  
70      /**
71       * Decode a long.
72       * @param message the ZeroMQ byte array to decode
73       * @param pointer the first byte to consider
74       * @return the long value
75       */
76      public static long decodeLong(final byte[] message, final int pointer)
77      {
78          if (defaultBigEndian)
79          {
80              return ((((long) message[pointer]) << 56) | (((long) message[pointer + 1] & 0xff) << 48)
81                      | (((long) message[pointer + 2] & 0xff) << 40) | (((long) message[pointer + 3] & 0xff) << 32)
82                      | (((long) message[pointer + 4] & 0xff) << 24) | (((long) message[pointer + 5] & 0xff) << 16)
83                      | (((long) message[pointer + 6] & 0xff) << 8) | (((long) message[pointer + 7] & 0xff)));
84          }
85          else
86          {
87              return ((((long) message[pointer + 7]) << 56) | (((long) message[pointer + 6] & 0xff) << 48)
88                      | (((long) message[pointer + 5] & 0xff) << 40) | (((long) message[pointer + 4] & 0xff) << 32)
89                      | (((long) message[pointer + 3] & 0xff) << 24) | (((long) message[pointer + 2] & 0xff) << 16)
90                      | (((long) message[pointer + 1] & 0xff) << 8) | (((long) message[pointer] & 0xff)));
91          }
92      }
93  
94      /**
95       * Decode a float.
96       * @param message the ZeroMQ byte array to decode
97       * @param pointer the first byte to consider
98       * @return the float value
99       */
100     public static float decodeFloat(final byte[] message, final int pointer)
101     {
102         int bits = decodeInt(message, pointer);
103         return Float.intBitsToFloat(bits);
104     }
105 
106     /**
107      * Decode a double.
108      * @param message the ZeroMQ byte array to decode
109      * @param pointer the first byte to consider
110      * @return the double value
111      */
112     public static double decodeDouble(final byte[] message, final int pointer)
113     {
114         long bits = decodeLong(message, pointer);
115         return Double.longBitsToDouble(bits);
116     }
117 
118     /**
119      * Decode a char (16 bits).
120      * @param message the ZeroMQ byte array to decode
121      * @param pointer the first byte to consider
122      * @return the short value
123      */
124     public static char decodeChar(final byte[] message, final int pointer)
125     {
126         return (char) decodeShort(message, pointer);
127     }
128 
129     /**
130      * Decode a String including the length int from the message byte array.
131      * @param message the message byte array
132      * @param pointer the start position in the array
133      * @return the Java String at position pointer
134      */
135     public static String decodeUTF8String(final byte[] message, final int pointer)
136     {
137         int len = decodeInt(message, pointer);
138         char[] c = new char[len];
139         for (int i = 0; i < len; i++)
140         {
141             c[i] = (char) message[pointer + i + 4];
142         }
143         return String.copyValueOf(c);
144     }
145 
146     /**
147      * Decode a String including the length int from the message byte array.
148      * @param message the message byte array
149      * @param pointer the start position in the array
150      * @return the Java String at position pointer
151      */
152     public static String decodeUTF16String(final byte[] message, final int pointer)
153     {
154         int len = decodeInt(message, pointer);
155         char[] c = new char[len];
156         for (int i = 0; i < len; i++)
157         {
158             c[i] = decodeChar(message, pointer + 2 * i + 4);
159         }
160         return String.copyValueOf(c);
161     }
162 
163     /**
164      * Encode a short into a message buffer.
165      * @param v the variable to encode
166      * @param message the message buffer to encode the variable into
167      * @param pointer the pointer to start writing
168      * @return the new pointer after writing
169      */
170     public static int encodeShort(final short v, final byte[] message, final int pointer)
171     {
172         int p = pointer;
173         if (defaultBigEndian)
174         {
175             message[p++] = (byte) (v >> 8);
176             message[p++] = (byte) (v);
177         }
178         else
179         {
180             message[p++] = (byte) (v);
181             message[p++] = (byte) (v >> 8);
182         }
183         return p;
184     }
185 
186     /**
187      * Encode a char (16 bits) into a message buffer.
188      * @param v the variable to encode
189      * @param message the message buffer to encode the variable into
190      * @param pointer the pointer to start writing
191      * @return the new pointer after writing
192      */
193     public static int encodeChar(final char v, final byte[] message, final int pointer)
194     {
195         return encodeShort((short) v, message, pointer);
196     }
197 
198     /**
199      * Encode a int into a message buffer.
200      * @param v the variable to encode
201      * @param message the message buffer to encode the variable into
202      * @param pointer the pointer to start writing
203      * @return the new pointer after writing
204      */
205     public static int encodeInt(final int v, final byte[] message, final int pointer)
206     {
207         int p = pointer;
208         if (defaultBigEndian)
209         {
210             message[p++] = (byte) ((v >> 24) & 0xFF);
211             message[p++] = (byte) ((v >> 16) & 0xFF);
212             message[p++] = (byte) ((v >> 8) & 0xFF);
213             message[p++] = (byte) (v & 0xFF);
214         }
215         else
216         {
217             message[p++] = (byte) (v & 0xFF);
218             message[p++] = (byte) ((v >> 8) & 0xFF);
219             message[p++] = (byte) ((v >> 16) & 0xFF);
220             message[p++] = (byte) ((v >> 24) & 0xFF);
221         }
222         return p;
223     }
224 
225     /**
226      * Encode a long into a message buffer.
227      * @param v the variable to encode
228      * @param message the message buffer to encode the variable into
229      * @param pointer the pointer to start writing
230      * @return the new pointer after writing
231      */
232     public static int encodeLong(final long v, final byte[] message, final int pointer)
233     {
234         int p = pointer;
235         if (defaultBigEndian)
236         {
237             message[p++] = (byte) ((v >> 56) & 0xFF);
238             message[p++] = (byte) ((v >> 48) & 0xFF);
239             message[p++] = (byte) ((v >> 40) & 0xFF);
240             message[p++] = (byte) ((v >> 32) & 0xFF);
241             message[p++] = (byte) ((v >> 24) & 0xFF);
242             message[p++] = (byte) ((v >> 16) & 0xFF);
243             message[p++] = (byte) ((v >> 8) & 0xFF);
244             message[p++] = (byte) (v & 0xFF);
245         }
246         else
247         {
248             message[p++] = (byte) (v & 0xFF);
249             message[p++] = (byte) ((v >> 8) & 0xFF);
250             message[p++] = (byte) ((v >> 16) & 0xFF);
251             message[p++] = (byte) ((v >> 24) & 0xFF);
252             message[p++] = (byte) ((v >> 32) & 0xFF);
253             message[p++] = (byte) ((v >> 40) & 0xFF);
254             message[p++] = (byte) ((v >> 48) & 0xFF);
255             message[p++] = (byte) ((v >> 56) & 0xFF);
256         }
257         return p;
258     }
259 
260     /**
261      * Encode a float into a message buffer.
262      * @param v the variable to encode
263      * @param message the message buffer to encode the variable into
264      * @param pointer the pointer to start writing
265      * @return the new pointer after writing
266      */
267     public static int encodeFloat(final float v, final byte[] message, final int pointer)
268     {
269         int vint = Float.floatToIntBits(v);
270         return encodeInt(vint, message, pointer);
271     }
272 
273     /**
274      * Encode a double into a message buffer.
275      * @param v the variable to encode
276      * @param message the message buffer to encode the variable into
277      * @param pointer the pointer to start writing
278      * @return the new pointer after writing
279      */
280     public static int encodeDouble(final double v, final byte[] message, final int pointer)
281     {
282         long vlong = Double.doubleToLongBits(v);
283         return encodeLong(vlong, message, pointer);
284     }
285 
286     /**
287      * Return a long encoded as a byte array.
288      * @param v the long variable to encode
289      * @return the byte array.
290      */
291     public static byte[] longToByteArray(final long v)
292     {
293         byte[] message = new byte[8];
294         int pointer = 0;
295         encodeLong(v, message, pointer);
296         return message;
297     }
298 
299     /**
300      * Return an int encoded as a byte array.
301      * @param v the int variable to encode
302      * @return the byte array.
303      */
304     public static byte[] intToByteArray(final int v)
305     {
306         byte[] message = new byte[4];
307         int pointer = 0;
308         encodeInt(v, message, pointer);
309         return message;
310     }
311 
312     /**
313      * Return a double encoded as a byte array.
314      * @param v the double variable to encode
315      * @return the byte array.
316      */
317     public static byte[] doubleToByteArray(final double v)
318     {
319         byte[] message = new byte[8];
320         int pointer = 0;
321         encodeDouble(v, message, pointer);
322         return message;
323     }
324 
325     /**
326      * Return a float encoded as a byte array.
327      * @param v the float variable to encode
328      * @return the byte array.
329      */
330     public static byte[] floatToByteArray(final float v)
331     {
332         byte[] message = new byte[4];
333         int pointer = 0;
334         encodeFloat(v, message, pointer);
335         return message;
336     }
337 
338     /**
339      * @return defaultBigEndian
340      */
341     public static boolean isDefaultBigEndian()
342     {
343         return defaultBigEndian;
344     }
345 
346     /**
347      * @param defaultBigEndian set defaultBigEndian
348      */
349     public static void setDefaultBigEndian(final boolean defaultBigEndian)
350     {
351         EndianUtil.defaultBigEndian = defaultBigEndian;
352     }
353 
354     /**
355      * @return platformbigendian
356      */
357     public static boolean isPlatformBigEndian()
358     {
359         return PLATFORM_BIG_ENDIAN;
360     }
361 
362 }