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 }