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 }