1 /*-------------------------------------------------------------------------- 2 * Copyright 2011 Taro L. Saito 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 *--------------------------------------------------------------------------*/ 16 //-------------------------------------- 17 // snappy-java Project 18 // 19 // Snappy.java 20 // Since: 2011/03/29 21 // 22 // $URL$ 23 // $Author$ 24 //-------------------------------------- 25 package org.xerial.snappy; 26 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.UnsupportedEncodingException; 30 import java.net.URL; 31 import java.nio.ByteBuffer; 32 import java.nio.charset.Charset; 33 import java.util.Properties; 34 35 /** 36 * Snappy API for data compression/decompression 37 * <p/> 38 * Note: if the native libraries cannot be loaded, an ExceptionInInitializerError 39 * will be thrown at first use of this class. 40 * 41 * @author Taro L. Saito 42 */ 43 public class Snappy 44 { 45 static { 46 try { 47 impl = SnappyLoader.loadSnappyApi(); 48 } 49 catch (Exception e) { 50 throw new ExceptionInInitializerError(e); 51 } 52 } 53 54 /** 55 * An instance of SnappyNative 56 */ 57 private static SnappyNative impl; 58 59 /** 60 * Clean up a temporary file (native lib) generated by snappy-java. 61 * General users do not need to call this method, since the native library extracted in snappy-java 62 * is deleted upon JVM termination (vie deleteOnExit()). 63 * This method is useful when using a J2EE container, which will restart servlet containers multiple times without 64 * restarting JVM. 65 */ cleanUp()66 public static void cleanUp() 67 { 68 SnappyLoader.cleanUpExtractedNativeLib(); 69 SnappyLoader.setSnappyApi(null); 70 } 71 72 /** 73 * Copy bytes from source to destination 74 * 75 * @param src pointer to the source array 76 * @param offset byte offset in the source array 77 * @param byteLength the number of bytes to copy 78 * @param dest pointer to the destination array 79 * @param dest_offset byte offset in the destination array 80 * @throws IOException 81 */ arrayCopy(Object src, int offset, int byteLength, Object dest, int dest_offset)82 public static void arrayCopy(Object src, int offset, int byteLength, Object dest, int dest_offset) 83 throws IOException 84 { 85 impl.arrayCopy(src, offset, byteLength, dest, dest_offset); 86 } 87 88 /** 89 * High-level API for compressing the input byte array. This method performs 90 * array copy to generate the result. If you want to reduce the memory copy 91 * cost, use {@link #compress(byte[], int, int, byte[], int)} or 92 * {@link #compress(ByteBuffer, ByteBuffer)}. 93 * 94 * @param input the input data 95 * @return the compressed byte array 96 * @throws IOException 97 */ compress(byte[] input)98 public static byte[] compress(byte[] input) 99 throws IOException 100 { 101 return rawCompress(input, input.length); 102 } 103 104 /** 105 * Compress the input buffer content in [inputOffset, 106 * ...inputOffset+inputLength) then output to the specified output buffer. 107 * 108 * @param input 109 * @param inputOffset 110 * @param inputLength 111 * @param output 112 * @param outputOffset 113 * @return byte size of the compressed data 114 * @throws IOException when failed to access the input/output buffer 115 */ compress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)116 public static int compress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) 117 throws IOException 118 { 119 return rawCompress(input, inputOffset, inputLength, output, outputOffset); 120 } 121 122 /** 123 * Compress the content in the given input buffer. After the compression, 124 * you can retrieve the compressed data from the output buffer [pos() ... 125 * limit()) (compressed data size = limit() - pos() = remaining()) 126 * 127 * @param uncompressed buffer[pos() ... limit()) containing the input data 128 * @param compressed output of the compressed data. Uses range [pos()..]. 129 * @return byte size of the compressed data. 130 * @throws SnappyError when the input is not a direct buffer 131 */ compress(ByteBuffer uncompressed, ByteBuffer compressed)132 public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) 133 throws IOException 134 { 135 136 if (!uncompressed.isDirect()) { 137 throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer"); 138 } 139 if (!compressed.isDirect()) { 140 throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "destination is not a direct buffer"); 141 } 142 143 // input: uncompressed[pos(), limit()) 144 // output: compressed 145 int uPos = uncompressed.position(); 146 int uLen = uncompressed.remaining(); 147 int compressedSize = impl.rawCompress(uncompressed, uPos, uLen, compressed, 148 compressed.position()); 149 150 // pos limit 151 // [ ......BBBBBBB.........] 152 compressed.limit(compressed.position() + compressedSize); 153 154 return compressedSize; 155 } 156 157 /** 158 * Compress the input char array 159 * 160 * @param input 161 * @return the compressed data 162 */ compress(char[] input)163 public static byte[] compress(char[] input) 164 throws IOException 165 { 166 return rawCompress(input, input.length * 2); // char uses 2 bytes 167 } 168 169 /** 170 * Compress the input double array 171 * 172 * @param input 173 * @return the compressed data 174 */ compress(double[] input)175 public static byte[] compress(double[] input) 176 throws IOException 177 { 178 return rawCompress(input, input.length * 8); // double uses 8 bytes 179 } 180 181 /** 182 * Compress the input float array 183 * 184 * @param input 185 * @return the compressed data 186 */ compress(float[] input)187 public static byte[] compress(float[] input) 188 throws IOException 189 { 190 return rawCompress(input, input.length * 4); // float uses 4 bytes 191 } 192 193 /** 194 * Compress the input int array 195 * 196 * @param input 197 * @return the compressed data 198 */ compress(int[] input)199 public static byte[] compress(int[] input) 200 throws IOException 201 { 202 return rawCompress(input, input.length * 4); // int uses 4 bytes 203 } 204 205 /** 206 * Compress the input long array 207 * 208 * @param input 209 * @return the compressed data 210 */ compress(long[] input)211 public static byte[] compress(long[] input) 212 throws IOException 213 { 214 return rawCompress(input, input.length * 8); // long uses 8 bytes 215 } 216 217 /** 218 * Compress the input short array 219 * 220 * @param input 221 * @return the compressed data 222 */ compress(short[] input)223 public static byte[] compress(short[] input) 224 throws IOException 225 { 226 return rawCompress(input, input.length * 2); // short uses 2 bytes 227 } 228 229 /** 230 * Compress the input String 231 * 232 * @param s 233 * @return the compressed data 234 * @throws IOException 235 */ compress(String s)236 public static byte[] compress(String s) 237 throws IOException 238 { 239 try { 240 return compress(s, "UTF-8"); 241 } 242 catch (UnsupportedEncodingException e) { 243 throw new IllegalStateException("UTF-8 encoder is not found"); 244 } 245 } 246 247 /** 248 * Compress the input string using the given encoding 249 * 250 * @param s 251 * @param encoding 252 * @return the compressed data 253 * @throws UnsupportedEncodingException 254 * @throws IOException 255 */ compress(String s, String encoding)256 public static byte[] compress(String s, String encoding) 257 throws UnsupportedEncodingException, IOException 258 { 259 byte[] data = s.getBytes(encoding); 260 return compress(data); 261 } 262 263 /** 264 * Compress the input string using the given encoding 265 * 266 * @param s 267 * @param encoding 268 * @return the compressed data 269 * @throws UnsupportedEncodingException 270 * @throws IOException 271 */ compress(String s, Charset encoding)272 public static byte[] compress(String s, Charset encoding) 273 throws IOException 274 { 275 byte[] data = s.getBytes(encoding); 276 return compress(data); 277 } 278 279 /** 280 * Get the native library version of the snappy 281 * 282 * @return native library version 283 */ getNativeLibraryVersion()284 public static String getNativeLibraryVersion() 285 { 286 URL versionFile = SnappyLoader.class.getResource("/org/xerial/snappy/VERSION"); 287 288 String version = "unknown"; 289 try { 290 if (versionFile != null) { 291 InputStream in = null; 292 try { 293 Properties versionData = new Properties(); 294 in = versionFile.openStream(); 295 versionData.load(in); 296 version = versionData.getProperty("version", version); 297 if (version.equals("unknown")) { 298 version = versionData.getProperty("SNAPPY_VERSION", version); 299 } 300 version = version.trim().replaceAll("[^0-9\\.]", ""); 301 } 302 finally { 303 if(in != null) { 304 in.close(); 305 } 306 } 307 } 308 } 309 catch (IOException e) { 310 e.printStackTrace(); 311 } 312 return version; 313 } 314 315 /** 316 * Returns true iff the contents of compressed buffer [offset, 317 * offset+length) can be uncompressed successfully. Does not return the 318 * uncompressed data. Takes time proportional to the input length, but is 319 * usually at least a factor of four faster than actual decompression. 320 */ isValidCompressedBuffer(byte[] input, int offset, int length)321 public static boolean isValidCompressedBuffer(byte[] input, int offset, int length) 322 throws IOException 323 { 324 if (input == null) { 325 throw new NullPointerException("input is null"); 326 } 327 return impl.isValidCompressedBuffer(input, offset, length); 328 } 329 330 /** 331 * Returns true iff the contents of compressed buffer [offset, 332 * offset+length) can be uncompressed successfully. Does not return the 333 * uncompressed data. Takes time proportional to the input length, but is 334 * usually at least a factor of four faster than actual decompression. 335 */ isValidCompressedBuffer(byte[] input)336 public static boolean isValidCompressedBuffer(byte[] input) 337 throws IOException 338 { 339 return isValidCompressedBuffer(input, 0, input.length); 340 } 341 342 /** 343 * Returns true iff the contents of compressed buffer [pos() ... limit()) 344 * can be uncompressed successfully. Does not return the uncompressed data. 345 * Takes time proportional to the input length, but is usually at least a 346 * factor of four faster than actual decompression. 347 */ isValidCompressedBuffer(ByteBuffer compressed)348 public static boolean isValidCompressedBuffer(ByteBuffer compressed) 349 throws IOException 350 { 351 return impl.isValidCompressedBuffer(compressed, compressed.position(), 352 compressed.remaining()); 353 } 354 355 /** 356 * Returns true iff the contents of compressed buffer [offset, 357 * offset+length) can be uncompressed successfully. Does not return the 358 * uncompressed data. Takes time proportional to the input length, but is 359 * usually at least a factor of four faster than actual decompression. 360 */ isValidCompressedBuffer(long inputAddr, long offset, long length)361 public static boolean isValidCompressedBuffer(long inputAddr, long offset, long length) 362 throws IOException 363 { 364 return impl.isValidCompressedBuffer(inputAddr, offset, length); 365 } 366 367 /** 368 * Get the maximum byte size needed for compressing data of the given byte 369 * size. 370 * 371 * @param byteSize byte size of the data to compress 372 * @return maximum byte size of the compressed data 373 */ maxCompressedLength(int byteSize)374 public static int maxCompressedLength(int byteSize) 375 { 376 return impl.maxCompressedLength(byteSize); 377 } 378 379 /** 380 * Zero-copy compress using memory addresses. 381 * 382 * @param inputAddr input memory address 383 * @param inputSize input byte size 384 * @param destAddr destination address of the compressed data 385 * @return the compressed data size 386 * @throws IOException 387 */ rawCompress(long inputAddr, long inputSize, long destAddr)388 public static long rawCompress(long inputAddr, long inputSize, long destAddr) 389 throws IOException 390 { 391 return impl.rawCompress(inputAddr, inputSize, destAddr); 392 } 393 394 /** 395 * Zero-copy decompress using memory addresses. 396 * 397 * @param inputAddr input memory address 398 * @param inputSize input byte size 399 * @param destAddr destination address of the uncompressed data 400 * @return the uncompressed data size 401 * @throws IOException 402 */ rawUncompress(long inputAddr, long inputSize, long destAddr)403 public static long rawUncompress(long inputAddr, long inputSize, long destAddr) 404 throws IOException 405 { 406 return impl.rawUncompress(inputAddr, inputSize, destAddr); 407 } 408 409 /** 410 * Compress the input data and produce a byte array of the uncompressed data 411 * 412 * @param data input array. The input MUST be an array type 413 * @param byteSize the input byte size 414 * @return compressed data 415 */ rawCompress(Object data, int byteSize)416 public static byte[] rawCompress(Object data, int byteSize) 417 throws IOException 418 { 419 byte[] buf = new byte[Snappy.maxCompressedLength(byteSize)]; 420 int compressedByteSize = impl.rawCompress(data, 0, byteSize, buf, 0); 421 byte[] result = new byte[compressedByteSize]; 422 System.arraycopy(buf, 0, result, 0, compressedByteSize); 423 return result; 424 } 425 426 /** 427 * Compress the input buffer [offset,... ,offset+length) contents, then 428 * write the compressed data to the output buffer[offset, ...) 429 * 430 * @param input input array. This MUST be a primitive array type 431 * @param inputOffset byte offset at the output array 432 * @param inputLength byte length of the input data 433 * @param output output array. This MUST be a primitive array type 434 * @param outputOffset byte offset at the output array 435 * @return byte size of the compressed data 436 * @throws IOException 437 */ rawCompress(Object input, int inputOffset, int inputLength, byte[] output, int outputOffset)438 public static int rawCompress(Object input, int inputOffset, int inputLength, byte[] output, int outputOffset) 439 throws IOException 440 { 441 if (input == null || output == null) { 442 throw new NullPointerException("input or output is null"); 443 } 444 445 int compressedSize = impl 446 .rawCompress(input, inputOffset, inputLength, output, outputOffset); 447 return compressedSize; 448 } 449 450 /** 451 * Uncompress the content in the input buffer. The uncompressed data is 452 * written to the output buffer. 453 * <p/> 454 * Note that if you pass the wrong data or the range [inputOffset, 455 * inputOffset + inputLength) that cannot be uncompressed, your JVM might 456 * crash due to the access violation exception issued in the native code 457 * written in C++. To avoid this type of crash, use 458 * {@link #isValidCompressedBuffer(byte[], int, int)} first. 459 * 460 * @param input input byte array 461 * @param inputOffset byte offset in the input byte array 462 * @param inputLength byte length of the input data 463 * @param output output buffer, MUST be a primitive type array 464 * @param outputOffset byte offset in the output buffer 465 * @return the byte size of the uncompressed data 466 * @throws IOException when failed to uncompress the input data 467 */ rawUncompress(byte[] input, int inputOffset, int inputLength, Object output, int outputOffset)468 public static int rawUncompress(byte[] input, int inputOffset, int inputLength, Object output, int outputOffset) 469 throws IOException 470 { 471 if (input == null || output == null) { 472 throw new NullPointerException("input or output is null"); 473 } 474 return impl.rawUncompress(input, inputOffset, inputLength, output, outputOffset); 475 } 476 477 /** 478 * High-level API for uncompressing the input byte array. 479 * 480 * @param input 481 * @return the uncompressed byte array 482 * @throws IOException 483 */ uncompress(byte[] input)484 public static byte[] uncompress(byte[] input) 485 throws IOException 486 { 487 byte[] result = new byte[Snappy.uncompressedLength(input)]; 488 Snappy.uncompress(input, 0, input.length, result, 0); 489 return result; 490 } 491 492 /** 493 * Uncompress the content in the input buffer. The uncompressed data is 494 * written to the output buffer. 495 * <p/> 496 * Note that if you pass the wrong data or the range [inputOffset, 497 * inputOffset + inputLength) that cannot be uncompressed, your JVM might 498 * crash due to the access violation exception issued in the native code 499 * written in C++. To avoid this type of crash, use 500 * {@link #isValidCompressedBuffer(byte[], int, int)} first. 501 * 502 * @param input 503 * @param inputOffset 504 * @param inputLength 505 * @param output 506 * @param outputOffset 507 * @return the byte size of the uncompressed data 508 * @throws IOException 509 */ uncompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)510 public static int uncompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) 511 throws IOException 512 { 513 return rawUncompress(input, inputOffset, inputLength, output, outputOffset); 514 } 515 516 /** 517 * Uncompress the content in the input buffer. The result is dumped to the 518 * specified output buffer. 519 * <p/> 520 * Note that if you pass the wrong data or the range [pos(), limit()) that 521 * cannot be uncompressed, your JVM might crash due to the access violation 522 * exception issued in the native code written in C++. To avoid this type of 523 * crash, use {@link #isValidCompressedBuffer(ByteBuffer)} first. 524 * 525 * @param compressed buffer[pos() ... limit()) containing the input data 526 * @param uncompressed output of the the uncompressed data. It uses buffer[pos()..] 527 * @return uncompressed data size 528 * @throws IOException when failed to uncompress the given input 529 * @throws SnappyError when the input is not a direct buffer 530 */ uncompress(ByteBuffer compressed, ByteBuffer uncompressed)531 public static int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) 532 throws IOException 533 { 534 535 if (!compressed.isDirect()) { 536 throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer"); 537 } 538 if (!uncompressed.isDirect()) { 539 throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "destination is not a direct buffer"); 540 } 541 542 int cPos = compressed.position(); 543 int cLen = compressed.remaining(); 544 545 // pos limit 546 // [ ......UUUUUU.........] 547 int decompressedSize = impl.rawUncompress(compressed, cPos, cLen, uncompressed, 548 uncompressed.position()); 549 uncompressed.limit(uncompressed.position() + decompressedSize); 550 551 return decompressedSize; 552 } 553 554 /** 555 * Uncompress the input data as char array 556 * 557 * @param input 558 * @return the uncompressed data 559 * @throws IOException 560 */ uncompressCharArray(byte[] input)561 public static char[] uncompressCharArray(byte[] input) 562 throws IOException 563 { 564 return uncompressCharArray(input, 0, input.length); 565 } 566 567 /** 568 * Uncompress the input[offset, .., offset+length) as a char array 569 * 570 * @param input 571 * @param offset 572 * @param length 573 * @return the uncompressed data 574 * @throws IOException 575 */ uncompressCharArray(byte[] input, int offset, int length)576 public static char[] uncompressCharArray(byte[] input, int offset, int length) 577 throws IOException 578 { 579 int uncompressedLength = Snappy.uncompressedLength(input, offset, length); 580 char[] result = new char[uncompressedLength / 2]; 581 impl.rawUncompress(input, offset, length, result, 0); 582 return result; 583 } 584 585 /** 586 * Uncompress the input as a double array 587 * 588 * @param input 589 * @return the uncompressed data 590 * @throws IOException 591 */ uncompressDoubleArray(byte[] input)592 public static double[] uncompressDoubleArray(byte[] input) 593 throws IOException 594 { 595 int uncompressedLength = Snappy.uncompressedLength(input, 0, input.length); 596 double[] result = new double[uncompressedLength / 8]; 597 impl.rawUncompress(input, 0, input.length, result, 0); 598 return result; 599 } 600 601 /** 602 * Get the uncompressed byte size of the given compressed input. This 603 * operation takes O(1) time. 604 * 605 * @param input 606 * @return uncompressed byte size of the the given input data 607 * @throws IOException when failed to uncompress the given input. The error code is 608 * {@link SnappyErrorCode#PARSING_ERROR} 609 */ uncompressedLength(byte[] input)610 public static int uncompressedLength(byte[] input) 611 throws IOException 612 { 613 return impl.uncompressedLength(input, 0, input.length); 614 } 615 616 /** 617 * Get the uncompressed byte size of the given compressed input. This 618 * operation takes O(1) time. 619 * 620 * @param input 621 * @param offset 622 * @param length 623 * @return uncompressed byte size of the the given input data 624 * @throws IOException when failed to uncompress the given input. The error code is 625 * {@link SnappyErrorCode#PARSING_ERROR} 626 */ uncompressedLength(byte[] input, int offset, int length)627 public static int uncompressedLength(byte[] input, int offset, int length) 628 throws IOException 629 { 630 if (input == null) { 631 throw new NullPointerException("input is null"); 632 } 633 634 return impl.uncompressedLength(input, offset, length); 635 } 636 637 /** 638 * Get the uncompressed byte size of the given compressed input. This 639 * operation takes O(1) time. 640 * 641 * @param compressed input data [pos() ... limit()) 642 * @return uncompressed byte length of the given input 643 * @throws IOException when failed to uncompress the given input. The error code is 644 * {@link SnappyErrorCode#PARSING_ERROR} 645 * @throws SnappyError when the input is not a direct buffer 646 */ uncompressedLength(ByteBuffer compressed)647 public static int uncompressedLength(ByteBuffer compressed) 648 throws IOException 649 { 650 if (!compressed.isDirect()) { 651 throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer"); 652 } 653 654 return impl.uncompressedLength(compressed, compressed.position(), compressed.remaining()); 655 } 656 657 /** 658 * Get the uncompressed byte size of the given compressed input. This operation takes O(1) time. 659 * 660 * @param inputAddr compressed data address 661 * @param len byte length of the input 662 * @return uncompressed byte length of the given input 663 * @throws IOException when failed to uncompress the given input. The error code is 664 * {@link SnappyErrorCode#PARSING_ERROR} 665 */ uncompressedLength(long inputAddr, long len)666 public static long uncompressedLength(long inputAddr, long len) 667 throws IOException 668 { 669 return impl.uncompressedLength(inputAddr, len); 670 } 671 672 /** 673 * Uncompress the input as a float array 674 * 675 * @param input 676 * @return the uncompressed data 677 * @throws IOException 678 */ uncompressFloatArray(byte[] input)679 public static float[] uncompressFloatArray(byte[] input) 680 throws IOException 681 { 682 return uncompressFloatArray(input, 0, input.length); 683 } 684 685 /** 686 * Uncompress the input[offset, offset+length) as a float array 687 * 688 * @param input 689 * @param offset 690 * @param length 691 * @return the uncompressed data 692 * @throws IOException 693 */ uncompressFloatArray(byte[] input, int offset, int length)694 public static float[] uncompressFloatArray(byte[] input, int offset, int length) 695 throws IOException 696 { 697 int uncompressedLength = Snappy.uncompressedLength(input, offset, length); 698 float[] result = new float[uncompressedLength / 4]; 699 impl.rawUncompress(input, offset, length, result, 0); 700 return result; 701 } 702 703 /** 704 * Uncompress the input data as an int array 705 * 706 * @param input 707 * @return the uncompressed data 708 * @throws IOException 709 */ uncompressIntArray(byte[] input)710 public static int[] uncompressIntArray(byte[] input) 711 throws IOException 712 { 713 return uncompressIntArray(input, 0, input.length); 714 } 715 716 /** 717 * Uncompress the input[offset, offset+length) as an int array 718 * 719 * @param input 720 * @param offset 721 * @param length 722 * @return the uncompressed data 723 * @throws IOException 724 */ uncompressIntArray(byte[] input, int offset, int length)725 public static int[] uncompressIntArray(byte[] input, int offset, int length) 726 throws IOException 727 { 728 int uncompressedLength = Snappy.uncompressedLength(input, offset, length); 729 int[] result = new int[uncompressedLength / 4]; 730 impl.rawUncompress(input, offset, length, result, 0); 731 return result; 732 } 733 734 /** 735 * Uncompress the input data as a long array 736 * 737 * @param input 738 * @return the uncompressed data 739 * @throws IOException 740 */ uncompressLongArray(byte[] input)741 public static long[] uncompressLongArray(byte[] input) 742 throws IOException 743 { 744 return uncompressLongArray(input, 0, input.length); 745 } 746 747 /** 748 * Uncompress the input[offset, offset+length) as a long array 749 * 750 * @param input 751 * @param offset 752 * @param length 753 * @return the uncompressed data 754 * @throws IOException 755 */ uncompressLongArray(byte[] input, int offset, int length)756 public static long[] uncompressLongArray(byte[] input, int offset, int length) 757 throws IOException 758 { 759 int uncompressedLength = Snappy.uncompressedLength(input, offset, length); 760 long[] result = new long[uncompressedLength / 8]; 761 impl.rawUncompress(input, offset, length, result, 0); 762 return result; 763 } 764 765 /** 766 * Uncompress the input as a short array 767 * 768 * @param input 769 * @return the uncompressed data 770 * @throws IOException 771 */ uncompressShortArray(byte[] input)772 public static short[] uncompressShortArray(byte[] input) 773 throws IOException 774 { 775 return uncompressShortArray(input, 0, input.length); 776 } 777 778 /** 779 * Uncompress the input[offset, offset+length) as a short array 780 * 781 * @param input 782 * @param offset 783 * @param length 784 * @return the uncompressed data 785 * @throws IOException 786 */ uncompressShortArray(byte[] input, int offset, int length)787 public static short[] uncompressShortArray(byte[] input, int offset, int length) 788 throws IOException 789 { 790 int uncompressedLength = Snappy.uncompressedLength(input, offset, length); 791 short[] result = new short[uncompressedLength / 2]; 792 impl.rawUncompress(input, offset, length, result, 0); 793 return result; 794 } 795 796 /** 797 * Uncompress the input as a String 798 * 799 * @param input 800 * @return the uncompressed dasta 801 * @throws IOException 802 */ uncompressString(byte[] input)803 public static String uncompressString(byte[] input) 804 throws IOException 805 { 806 try { 807 return uncompressString(input, "UTF-8"); 808 } 809 catch (UnsupportedEncodingException e) { 810 throw new IllegalStateException("UTF-8 decoder is not found"); 811 } 812 } 813 814 /** 815 * Uncompress the input[offset, offset+length) as a String 816 * 817 * @param input 818 * @param offset 819 * @param length 820 * @return the uncompressed data 821 * @throws IOException 822 */ uncompressString(byte[] input, int offset, int length)823 public static String uncompressString(byte[] input, int offset, int length) 824 throws IOException 825 { 826 try { 827 return uncompressString(input, offset, length, "UTF-8"); 828 } 829 catch (UnsupportedEncodingException e) { 830 throw new IllegalStateException("UTF-8 decoder is not found"); 831 } 832 } 833 834 /** 835 * Uncompress the input[offset, offset+length) as a String of the given 836 * encoding 837 * 838 * @param input 839 * @param offset 840 * @param length 841 * @param encoding 842 * @return the uncompressed data 843 * @throws IOException 844 */ uncompressString(byte[] input, int offset, int length, String encoding)845 public static String uncompressString(byte[] input, int offset, int length, String encoding) 846 throws IOException, 847 UnsupportedEncodingException 848 { 849 byte[] uncompressed = new byte[uncompressedLength(input, offset, length)]; 850 uncompress(input, offset, length, uncompressed, 0); 851 return new String(uncompressed, encoding); 852 } 853 854 /** 855 * Uncompress the input[offset, offset+length) as a String of the given 856 * encoding 857 * 858 * @param input 859 * @param offset 860 * @param length 861 * @param encoding 862 * @return the uncompressed data 863 * @throws IOException 864 */ uncompressString(byte[] input, int offset, int length, Charset encoding)865 public static String uncompressString(byte[] input, int offset, int length, Charset encoding) 866 throws IOException, 867 UnsupportedEncodingException 868 { 869 byte[] uncompressed = new byte[uncompressedLength(input, offset, length)]; 870 uncompress(input, offset, length, uncompressed, 0); 871 return new String(uncompressed, encoding); 872 } 873 874 /** 875 * Uncompress the input as a String of the given encoding 876 * 877 * @param input 878 * @param encoding 879 * @return the uncompressed data 880 * @throws IOException 881 * @throws UnsupportedEncodingException 882 */ uncompressString(byte[] input, String encoding)883 public static String uncompressString(byte[] input, String encoding) 884 throws IOException, 885 UnsupportedEncodingException 886 { 887 byte[] uncompressed = uncompress(input); 888 return new String(uncompressed, encoding); 889 } 890 891 /** 892 * Uncompress the input as a String of the given encoding 893 * 894 * @param input 895 * @param encoding 896 * @return the uncompressed data 897 * @throws IOException 898 */ uncompressString(byte[] input, Charset encoding)899 public static String uncompressString(byte[] input, Charset encoding) 900 throws IOException, 901 UnsupportedEncodingException 902 { 903 byte[] uncompressed = uncompress(input); 904 return new String(uncompressed, encoding); 905 } 906 } 907