View Javadoc
1   //******************************************************************************
2   //
3   // File:    Packing.java
4   // Package: edu.rit.util
5   // Unit:    Class edu.rit.util.Packing
6   //
7   // This Java source file is copyright (C) 2012 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.util;
41  
42  /**
43   * Class Packing provides static methods for packing and unpacking arrays of
44   * bytes into and out of integers, long integers, and arrays thereof.
45   * <P>
46   * <I>Note:</I> The operations in class Packing are not multiple thread safe.
47   *
48   * @author Alan Kaminsky
49   * @version 26-Mar-2012
50   */
51  public class Packing {
52  
53  // Prevent construction.
54      private Packing() {
55      }
56  
57  // Exported operations.
58      /**
59       * Pack bytes from the given array into an integer in little-endian order.
60       *
61       * @param src Source array of bytes to pack.
62       * @param srcPos Index of first byte to pack.
63       * @return Elements <code>src[srcPos]</code> through <code>src[srcPos+3]</code>
64       * packed into an integer in little-endian order.
65       * @exception NullPointerException (unchecked exception) Thrown if
66       * <code>src</code> is null.
67       * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
68       * packing would cause accessing array elements out of bounds.
69       */
70      public static int packIntLittleEndian(byte[] src,
71              int srcPos) {
72          if (srcPos + 4 > src.length) {
73              throw new IndexOutOfBoundsException();
74          }
75          int rv = 0;
76          for (int i = 0; i <= 3; ++i) {
77              rv |= (src[srcPos + i] & 0xFF) << (i * 8);
78          }
79          return rv;
80      }
81  
82      /**
83       * Pack bytes from the given array into an integer in big-endian order.
84       *
85       * @param src Source array of bytes to pack.
86       * @param srcPos Index of first byte to pack.
87       * @return Elements <code>src[srcPos]</code> through <code>src[srcPos+3]</code>
88       * packed into an integer in big-endian order.
89       * @exception NullPointerException (unchecked exception) Thrown if
90       * <code>src</code> is null.
91       * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
92       * packing would cause accessing array elements out of bounds.
93       */
94      public static int packIntBigEndian(byte[] src,
95              int srcPos) {
96          if (srcPos + 4 > src.length) {
97              throw new IndexOutOfBoundsException();
98          }
99          int rv = 0;
100         for (int i = 0; i <= 3; ++i) {
101             rv |= (src[srcPos + i] & 0xFF) << ((3 - i) * 8);
102         }
103         return rv;
104     }
105 
106     /**
107      * Pack bytes from the given array into the given array of integers in
108      * little-endian order. Elements <code>src[srcPos]</code> through
109      * <code>src[srcPos+4*len-1]</code> are packed into <code>dst[dstPos]</code> through
110      * <code>dst[dstPos+len-1]</code>.
111      *
112      * @param src Source array of bytes to pack.
113      * @param srcPos Index of first byte to pack.
114      * @param dst Destination array of packed integers.
115      * @param dstPos Index of first packed integer.
116      * @param len Number of integers (not bytes!) to pack.
117      * @exception NullPointerException (unchecked exception) Thrown if
118      * <code>src</code> is null. Thrown if
119      * <code>dst</code> is null.
120      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
121      * packing would cause accessing array elements out of bounds; in this case
122      * <code>dst</code> is not altered.
123      */
124     public static void packIntLittleEndian(byte[] src,
125             int srcPos,
126             int[] dst,
127             int dstPos,
128             int len) {
129         if (srcPos + 4 * len > src.length) {
130             throw new IndexOutOfBoundsException();
131         }
132         if (dstPos + len > dst.length) {
133             throw new IndexOutOfBoundsException();
134         }
135         for (int i = 0; i < len; ++i) {
136             dst[dstPos + i] = packIntLittleEndian(src, srcPos + 4 * i);
137         }
138     }
139 
140     /**
141      * Pack bytes from the given array into the given array of integers in
142      * big-endian order. Elements <code>src[srcPos]</code> through
143      * <code>src[srcPos+4*len-1]</code> are packed into <code>dst[dstPos]</code> through
144      * <code>dst[dstPos+len-1]</code>.
145      *
146      * @param src Source array of bytes to pack.
147      * @param srcPos Index of first byte to pack.
148      * @param dst Destination array of packed integers.
149      * @param dstPos Index of first packed integer.
150      * @param len Number of integers (not bytes!) to pack.
151      * @exception NullPointerException (unchecked exception) Thrown if
152      * <code>src</code> is null. Thrown if
153      * <code>dst</code> is null.
154      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
155      * packing would cause accessing array elements out of bounds; in this case
156      * <code>dst</code> is not altered.
157      */
158     public static void packIntBigEndian(byte[] src,
159             int srcPos,
160             int[] dst,
161             int dstPos,
162             int len) {
163         if (srcPos + 4 * len > src.length) {
164             throw new IndexOutOfBoundsException();
165         }
166         if (dstPos + len > dst.length) {
167             throw new IndexOutOfBoundsException();
168         }
169         for (int i = 0; i < len; ++i) {
170             dst[dstPos + i] = packIntBigEndian(src, srcPos + 4 * i);
171         }
172     }
173 
174     /**
175      * Pack bytes from the given array into a long integer in little-endian
176      * order.
177      *
178      * @param src Source array of bytes to pack.
179      * @param srcPos Index of first byte to pack.
180      * @return Elements <code>src[srcPos]</code> through <code>src[srcPos+7]</code>
181      * packed into a long integer in little-endian order.
182      * @exception NullPointerException (unchecked exception) Thrown if
183      * <code>src</code> is null.
184      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
185      * packing would cause accessing array elements out of bounds.
186      */
187     public static long packLongLittleEndian(byte[] src,
188             int srcPos) {
189         if (srcPos + 8 > src.length) {
190             throw new IndexOutOfBoundsException();
191         }
192         long rv = 0L;
193         for (int i = 0; i <= 7; ++i) {
194             rv |= (src[srcPos + i] & 0xFFL) << (i * 8);
195         }
196         return rv;
197     }
198 
199     /**
200      * Pack bytes from the given array into a long integer in big-endian order.
201      *
202      * @param src Source array of bytes to pack.
203      * @param srcPos Index of first byte to pack.
204      * @return Elements <code>src[srcPos]</code> through <code>src[srcPos+7]</code>
205      * packed into a long integer in big-endian order.
206      * @exception NullPointerException (unchecked exception) Thrown if
207      * <code>src</code> is null.
208      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
209      * packing would cause accessing array elements out of bounds.
210      */
211     public static long packLongBigEndian(byte[] src,
212             int srcPos) {
213         if (srcPos + 8 > src.length) {
214             throw new IndexOutOfBoundsException();
215         }
216         long rv = 0L;
217         for (int i = 0; i <= 7; ++i) {
218             rv |= (src[srcPos + i] & 0xFFL) << ((7 - i) * 8);
219         }
220         return rv;
221     }
222 
223     /**
224      * Pack bytes from the given array into the given array of long integers in
225      * little-endian order. Elements <code>src[srcPos]</code> through
226      * <code>src[srcPos+8*len-1]</code> are packed into <code>dst[dstPos]</code> through
227      * <code>dst[dstPos+len-1]</code>.
228      *
229      * @param src Source array of bytes to pack.
230      * @param srcPos Index of first byte to pack.
231      * @param dst Destination array of packed long integers.
232      * @param dstPos Index of first packed long integer.
233      * @param len Number of long integers (not bytes!) to pack.
234      * @exception NullPointerException (unchecked exception) Thrown if
235      * <code>src</code> is null. Thrown if
236      * <code>dst</code> is null.
237      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
238      * packing would cause accessing array elements out of bounds; in this case
239      * <code>dst</code> is not altered.
240      */
241     public static void packLongLittleEndian(byte[] src,
242             int srcPos,
243             long[] dst,
244             int dstPos,
245             int len) {
246         if (srcPos + 8 * len > src.length) {
247             throw new IndexOutOfBoundsException();
248         }
249         if (dstPos + len > dst.length) {
250             throw new IndexOutOfBoundsException();
251         }
252         for (int i = 0; i < len; ++i) {
253             dst[dstPos + i] = packLongLittleEndian(src, srcPos + 8 * i);
254         }
255     }
256 
257     /**
258      * Pack bytes from the given array into the given array of long integers in
259      * big-endian order. Elements <code>src[srcPos]</code> through
260      * <code>src[srcPos+8*len-1]</code> are packed into <code>dst[dstPos]</code> through
261      * <code>dst[dstPos+len-1]</code>.
262      *
263      * @param src Source array of bytes to pack.
264      * @param srcPos Index of first byte to pack.
265      * @param dst Destination array of packed long integers.
266      * @param dstPos Index of first packed long integer.
267      * @param len Number of long integers (not bytes!) to pack.
268      * @exception NullPointerException (unchecked exception) Thrown if
269      * <code>src</code> is null. Thrown if
270      * <code>dst</code> is null.
271      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
272      * packing would cause accessing array elements out of bounds; in this case
273      * <code>dst</code> is not altered.
274      */
275     public static void packLongBigEndian(byte[] src,
276             int srcPos,
277             long[] dst,
278             int dstPos,
279             int len) {
280         if (srcPos + 8 * len > src.length) {
281             throw new IndexOutOfBoundsException();
282         }
283         if (dstPos + len > dst.length) {
284             throw new IndexOutOfBoundsException();
285         }
286         for (int i = 0; i < len; ++i) {
287             dst[dstPos + i] = packLongBigEndian(src, srcPos + 8 * i);
288         }
289     }
290 
291     /**
292      * Unpack the given integer into the given array of bytes in little-endian
293      * order. The integer is unpacked into elements <code>dst[dstPos]</code> through
294      * <code>dst[dstPos+3]</code>.
295      *
296      * @param src Source integer to unpack.
297      * @param dst Destination array to receive unpacked bytes.
298      * @param dstPos Index of first unpacked byte.
299      * @exception NullPointerException (unchecked exception) Thrown if
300      * <code>dst</code> is null.
301      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
302      * unpacking would cause accessing array elements out of bounds; in this
303      * case <code>dst</code> is not altered.
304      */
305     public static void unpackIntLittleEndian(int src,
306             byte[] dst,
307             int dstPos) {
308         if (dstPos + 4 > dst.length) {
309             throw new IndexOutOfBoundsException();
310         }
311         for (int i = 0; i <= 3; ++i) {
312             dst[dstPos + i] = (byte) (src >> (i * 8));
313         }
314     }
315 
316     /**
317      * Unpack the given integer into the given array of bytes in big-endian
318      * order. The integer is unpacked into elements <code>dst[dstPos]</code> through
319      * <code>dst[dstPos+3]</code>.
320      *
321      * @param src Source integer to unpack.
322      * @param dst Destination array to receive unpacked bytes.
323      * @param dstPos Index of first unpacked byte.
324      * @exception NullPointerException (unchecked exception) Thrown if
325      * <code>dst</code> is null.
326      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
327      * unpacking would cause accessing array elements out of bounds; in this
328      * case <code>dst</code> is not altered.
329      */
330     public static void unpackIntBigEndian(int src,
331             byte[] dst,
332             int dstPos) {
333         if (dstPos + 4 > dst.length) {
334             throw new IndexOutOfBoundsException();
335         }
336         for (int i = 0; i <= 3; ++i) {
337             dst[dstPos + i] = (byte) (src >> ((3 - i) * 8));
338         }
339     }
340 
341     /**
342      * Unpack integers from the given array into the given array of bytes in
343      * little-endian order. Elements <code>src[srcPos]</code> through
344      * <code>src[srcPos+len-1]</code> are unpacked into <code>dst[dstPos]</code> through
345      * <code>dst[dstPos+4*len-1]</code>.
346      *
347      * @param src Source array of integers to unpack.
348      * @param srcPos Index of first integer to unpack.
349      * @param dst Destination array to receive unpacked bytes.
350      * @param dstPos Index of first unpacked byte.
351      * @param len Number of integers (not bytes!) to unpack.
352      * @exception NullPointerException (unchecked exception) Thrown if
353      * <code>src</code> is null. Thrown if
354      * <code>dst</code> is null.
355      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
356      * unpacking would cause accessing array elements out of bounds; in this
357      * case <code>dst</code> is not altered.
358      */
359     public static void unpackIntLittleEndian(int[] src,
360             int srcPos,
361             byte[] dst,
362             int dstPos,
363             int len) {
364         if (srcPos + len > src.length) {
365             throw new IndexOutOfBoundsException();
366         }
367         if (dstPos + 4 * len > dst.length) {
368             throw new IndexOutOfBoundsException();
369         }
370         for (int i = 0; i < len; ++i) {
371             unpackIntLittleEndian(src[srcPos + i], dst, dstPos + 4 * i);
372         }
373     }
374 
375     /**
376      * Unpack integers from the given array into the given array of bytes in
377      * big-endian order. Elements <code>src[srcPos]</code> through
378      * <code>src[srcPos+len-1]</code> are unpacked into <code>dst[dstPos]</code> through
379      * <code>dst[dstPos+4*len-1]</code>.
380      *
381      * @param src Source array of integers to unpack.
382      * @param srcPos Index of first integer to unpack.
383      * @param dst Destination array to receive unpacked bytes.
384      * @param dstPos Index of first unpacked byte.
385      * @param len Number of integers (not bytes!) to unpack.
386      * @exception NullPointerException (unchecked exception) Thrown if
387      * <code>src</code> is null. Thrown if
388      * <code>dst</code> is null.
389      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
390      * unpacking would cause accessing array elements out of bounds; in this
391      * case <code>dst</code> is not altered.
392      */
393     public static void unpackIntBigEndian(int[] src,
394             int srcPos,
395             byte[] dst,
396             int dstPos,
397             int len) {
398         if (srcPos + len > src.length) {
399             throw new IndexOutOfBoundsException();
400         }
401         if (dstPos + 4 * len > dst.length) {
402             throw new IndexOutOfBoundsException();
403         }
404         for (int i = 0; i < len; ++i) {
405             unpackIntBigEndian(src[srcPos + i], dst, dstPos + 4 * i);
406         }
407     }
408 
409     /**
410      * Unpack the given long integer into the given array of bytes in
411      * little-endian order. The long integer is unpacked into elements
412      * <code>dst[dstPos]</code> through <code>dst[dstPos+7]</code>.
413      *
414      * @param src Source long integer to unpack.
415      * @param dst Destination array to receive unpacked bytes.
416      * @param dstPos Index of first unpacked byte.
417      * @exception NullPointerException (unchecked exception) Thrown if
418      * <code>dst</code> is null.
419      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
420      * unpacking would cause accessing array elements out of bounds; in this
421      * case <code>dst</code> is not altered.
422      */
423     public static void unpackLongLittleEndian(long src,
424             byte[] dst,
425             int dstPos) {
426         if (dstPos + 8 > dst.length) {
427             throw new IndexOutOfBoundsException();
428         }
429         for (int i = 0; i <= 7; ++i) {
430             dst[dstPos + i] = (byte) (src >> (i * 8));
431         }
432     }
433 
434     /**
435      * Unpack the given long integer into the given array of bytes in big-endian
436      * order. The long integer is unpacked into elements <code>dst[dstPos]</code>
437      * through <code>dst[dstPos+3]</code>.
438      *
439      * @param src Source long integer to unpack.
440      * @param dst Destination array to receive unpacked bytes.
441      * @param dstPos Index of first unpacked byte.
442      * @exception NullPointerException (unchecked exception) Thrown if
443      * <code>dst</code> is null.
444      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
445      * unpacking would cause accessing array elements out of bounds; in this
446      * case <code>dst</code> is not altered.
447      */
448     public static void unpackLongBigEndian(long src,
449             byte[] dst,
450             int dstPos) {
451         if (dstPos + 8 > dst.length) {
452             throw new IndexOutOfBoundsException();
453         }
454         for (int i = 0; i <= 7; ++i) {
455             dst[dstPos + i] = (byte) (src >> ((7 - i) * 8));
456         }
457     }
458 
459     /**
460      * Unpack long integers from the given array into the given array of bytes
461      * in little-endian order. Elements <code>src[srcPos]</code> through
462      * <code>src[srcPos+len-1]</code> are unpacked into <code>dst[dstPos]</code> through
463      * <code>dst[dstPos+8*len-1]</code>.
464      *
465      * @param src Source array of long integers to unpack.
466      * @param srcPos Index of first long integer to unpack.
467      * @param dst Destination array to receive unpacked bytes.
468      * @param dstPos Index of first unpacked byte.
469      * @param len Number of integers (not bytes!) to unpack.
470      * @exception NullPointerException (unchecked exception) Thrown if
471      * <code>src</code> is null. Thrown if
472      * <code>dst</code> is null.
473      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
474      * unpacking would cause accessing array elements out of bounds; in this
475      * case <code>dst</code> is not altered.
476      */
477     public static void unpackLongLittleEndian(long[] src,
478             int srcPos,
479             byte[] dst,
480             int dstPos,
481             int len) {
482         if (srcPos + len > src.length) {
483             throw new IndexOutOfBoundsException();
484         }
485         if (dstPos + 8 * len > dst.length) {
486             throw new IndexOutOfBoundsException();
487         }
488         for (int i = 0; i < len; ++i) {
489             unpackLongLittleEndian(src[srcPos + i], dst, dstPos + 8 * i);
490         }
491     }
492 
493     /**
494      * Unpack long integers from the given array into the given array of bytes
495      * in big-endian order. Elements <code>src[srcPos]</code> through
496      * <code>src[srcPos+len-1]</code> are unpacked into <code>dst[dstPos]</code> through
497      * <code>dst[dstPos+8*len-1]</code>.
498      *
499      * @param src Source array of long integers to unpack.
500      * @param srcPos Index of first long integer to unpack.
501      * @param dst Destination array to receive unpacked bytes.
502      * @param dstPos Index of first unpacked byte.
503      * @param len Number of integers (not bytes!) to unpack.
504      * @exception NullPointerException (unchecked exception) Thrown if
505      * <code>src</code> is null. Thrown if
506      * <code>dst</code> is null.
507      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
508      * unpacking would cause accessing array elements out of bounds; in this
509      * case <code>dst</code> is not altered.
510      */
511     public static void unpackLongBigEndian(long[] src,
512             int srcPos,
513             byte[] dst,
514             int dstPos,
515             int len) {
516         if (srcPos + len > src.length) {
517             throw new IndexOutOfBoundsException();
518         }
519         if (dstPos + 8 * len > dst.length) {
520             throw new IndexOutOfBoundsException();
521         }
522         for (int i = 0; i < len; ++i) {
523             unpackLongBigEndian(src[srcPos + i], dst, dstPos + 8 * i);
524         }
525     }
526 
527 }