ZlibDecompressor.c
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:10k
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #if defined HAVE_CONFIG_H
- #include <config.h>
- #endif
- #if defined HAVE_STDIO_H
- #include <stdio.h>
- #else
- #error 'stdio.h not found'
- #endif
- #if defined HAVE_STDLIB_H
- #include <stdlib.h>
- #else
- #error 'stdlib.h not found'
- #endif
- #if defined HAVE_STRING_H
- #include <string.h>
- #else
- #error 'string.h not found'
- #endif
- #if defined HAVE_DLFCN_H
- #include <dlfcn.h>
- #else
- #error 'dlfcn.h not found'
- #endif
- #include "org_apache_hadoop_io_compress_zlib.h"
- #include "org_apache_hadoop_io_compress_zlib_ZlibDecompressor.h"
- static jfieldID ZlibDecompressor_clazz;
- static jfieldID ZlibDecompressor_stream;
- static jfieldID ZlibDecompressor_compressedDirectBuf;
- static jfieldID ZlibDecompressor_compressedDirectBufOff;
- static jfieldID ZlibDecompressor_compressedDirectBufLen;
- static jfieldID ZlibDecompressor_uncompressedDirectBuf;
- static jfieldID ZlibDecompressor_directBufferSize;
- static jfieldID ZlibDecompressor_needDict;
- static jfieldID ZlibDecompressor_finished;
- static int (*dlsym_inflateInit2_)(z_streamp, int, const char *, int);
- static int (*dlsym_inflate)(z_streamp, int);
- static int (*dlsym_inflateSetDictionary)(z_streamp, const Bytef *, uInt);
- static int (*dlsym_inflateReset)(z_streamp);
- static int (*dlsym_inflateEnd)(z_streamp);
- JNIEXPORT void JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_initIDs(
- JNIEnv *env, jclass class
- ) {
- // Load libz.so
- void *libz = dlopen(HADOOP_ZLIB_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
- if (!libz) {
- THROW(env, "java/lang/UnsatisfiedLinkError", "Cannot load libz.so");
- return;
- }
- // Locate the requisite symbols from libz.so
- dlerror(); // Clear any existing error
- LOAD_DYNAMIC_SYMBOL(dlsym_inflateInit2_, env, libz, "inflateInit2_");
- LOAD_DYNAMIC_SYMBOL(dlsym_inflate, env, libz, "inflate");
- LOAD_DYNAMIC_SYMBOL(dlsym_inflateSetDictionary, env, libz, "inflateSetDictionary");
- LOAD_DYNAMIC_SYMBOL(dlsym_inflateReset, env, libz, "inflateReset");
- LOAD_DYNAMIC_SYMBOL(dlsym_inflateEnd, env, libz, "inflateEnd");
- // Initialize the requisite fieldIds
- ZlibDecompressor_clazz = (*env)->GetStaticFieldID(env, class, "clazz",
- "Ljava/lang/Class;");
- ZlibDecompressor_stream = (*env)->GetFieldID(env, class, "stream", "J");
- ZlibDecompressor_needDict = (*env)->GetFieldID(env, class, "needDict", "Z");
- ZlibDecompressor_finished = (*env)->GetFieldID(env, class, "finished", "Z");
- ZlibDecompressor_compressedDirectBuf = (*env)->GetFieldID(env, class,
- "compressedDirectBuf",
- "Ljava/nio/Buffer;");
- ZlibDecompressor_compressedDirectBufOff = (*env)->GetFieldID(env, class,
- "compressedDirectBufOff", "I");
- ZlibDecompressor_compressedDirectBufLen = (*env)->GetFieldID(env, class,
- "compressedDirectBufLen", "I");
- ZlibDecompressor_uncompressedDirectBuf = (*env)->GetFieldID(env, class,
- "uncompressedDirectBuf",
- "Ljava/nio/Buffer;");
- ZlibDecompressor_directBufferSize = (*env)->GetFieldID(env, class,
- "directBufferSize", "I");
- }
- JNIEXPORT jlong JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_init(
- JNIEnv *env, jclass cls, jint windowBits
- ) {
- z_stream *stream = malloc(sizeof(z_stream));
- memset((void*)stream, 0, sizeof(z_stream));
- if (stream == 0) {
- THROW(env, "java/lang/OutOfMemoryError", NULL);
- return (jlong)0;
- }
-
- int rv = dlsym_inflateInit2_(stream, windowBits, ZLIB_VERSION, sizeof(z_stream));
- if (rv != Z_OK) {
- // Contingency - Report error by throwing appropriate exceptions
- free(stream);
- stream = NULL;
-
- switch (rv) {
- case Z_MEM_ERROR:
- {
- THROW(env, "java/lang/OutOfMemoryError", NULL);
- }
- break;
- default:
- {
- THROW(env, "java/lang/InternalError", NULL);
- }
- break;
- }
- }
-
- return JLONG(stream);
- }
- JNIEXPORT void JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_setDictionary(
- JNIEnv *env, jclass cls, jlong stream,
- jarray b, jint off, jint len
- ) {
- Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
- if (!buf) {
- THROW(env, "java/lang/InternalError", NULL);
- return;
- }
- int rv = dlsym_inflateSetDictionary(ZSTREAM(stream), buf + off, len);
- (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
-
- if (rv != Z_OK) {
- // Contingency - Report error by throwing appropriate exceptions
- switch (rv) {
- case Z_STREAM_ERROR:
- case Z_DATA_ERROR:
- {
- THROW(env, "java/lang/IllegalArgumentException",
- (ZSTREAM(stream))->msg);
- }
- break;
- default:
- {
- THROW(env, "java/lang/InternalError", (ZSTREAM(stream))->msg);
- }
- break;
- }
- }
- }
- JNIEXPORT jint JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_inflateBytesDirect(
- JNIEnv *env, jobject this
- ) {
- // Get members of ZlibDecompressor
- z_stream *stream = ZSTREAM(
- (*env)->GetLongField(env, this,
- ZlibDecompressor_stream)
- );
- if (!stream) {
- THROW(env, "java/lang/NullPointerException", NULL);
- return (jint)0;
- }
- // Get members of ZlibDecompressor
- jobject clazz = (*env)->GetStaticObjectField(env, this,
- ZlibDecompressor_clazz);
- jarray compressed_direct_buf = (jarray)(*env)->GetObjectField(env, this,
- ZlibDecompressor_compressedDirectBuf);
- jint compressed_direct_buf_off = (*env)->GetIntField(env, this,
- ZlibDecompressor_compressedDirectBufOff);
- jint compressed_direct_buf_len = (*env)->GetIntField(env, this,
- ZlibDecompressor_compressedDirectBufLen);
- jarray uncompressed_direct_buf = (jarray)(*env)->GetObjectField(env, this,
- ZlibDecompressor_uncompressedDirectBuf);
- jint uncompressed_direct_buf_len = (*env)->GetIntField(env, this,
- ZlibDecompressor_directBufferSize);
- // Get the input direct buffer
- LOCK_CLASS(env, clazz, "ZlibDecompressor");
- Bytef *compressed_bytes = (*env)->GetDirectBufferAddress(env,
- compressed_direct_buf);
- UNLOCK_CLASS(env, clazz, "ZlibDecompressor");
-
- if (!compressed_bytes) {
- return (jint)0;
- }
-
- // Get the output direct buffer
- LOCK_CLASS(env, clazz, "ZlibDecompressor");
- Bytef *uncompressed_bytes = (*env)->GetDirectBufferAddress(env,
- uncompressed_direct_buf);
- UNLOCK_CLASS(env, clazz, "ZlibDecompressor");
- if (!uncompressed_bytes) {
- return (jint)0;
- }
-
- // Re-calibrate the z_stream
- stream->next_in = compressed_bytes + compressed_direct_buf_off;
- stream->next_out = uncompressed_bytes;
- stream->avail_in = compressed_direct_buf_len;
- stream->avail_out = uncompressed_direct_buf_len;
-
- // Decompress
- int rv = dlsym_inflate(stream, Z_PARTIAL_FLUSH);
- // Contingency? - Report error by throwing appropriate exceptions
- int no_decompressed_bytes = 0;
- switch (rv) {
- case Z_STREAM_END:
- {
- (*env)->SetBooleanField(env, this, ZlibDecompressor_finished, JNI_TRUE);
- } // cascade down
- case Z_OK:
- {
- compressed_direct_buf_off += compressed_direct_buf_len - stream->avail_in;
- (*env)->SetIntField(env, this, ZlibDecompressor_compressedDirectBufOff,
- compressed_direct_buf_off);
- (*env)->SetIntField(env, this, ZlibDecompressor_compressedDirectBufLen,
- stream->avail_in);
- no_decompressed_bytes = uncompressed_direct_buf_len - stream->avail_out;
- }
- break;
- case Z_NEED_DICT:
- {
- (*env)->SetBooleanField(env, this, ZlibDecompressor_needDict, JNI_TRUE);
- compressed_direct_buf_off += compressed_direct_buf_len - stream->avail_in;
- (*env)->SetIntField(env, this, ZlibDecompressor_compressedDirectBufOff,
- compressed_direct_buf_off);
- (*env)->SetIntField(env, this, ZlibDecompressor_compressedDirectBufLen,
- stream->avail_in);
- }
- break;
- case Z_BUF_ERROR:
- break;
- case Z_DATA_ERROR:
- {
- THROW(env, "java/io/IOException", stream->msg);
- }
- break;
- case Z_MEM_ERROR:
- {
- THROW(env, "java/lang/OutOfMemoryError", NULL);
- }
- break;
- default:
- {
- THROW(env, "java/lang/InternalError", stream->msg);
- }
- break;
- }
-
- return no_decompressed_bytes;
- }
- JNIEXPORT jlong JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_getBytesRead(
- JNIEnv *env, jclass cls, jlong stream
- ) {
- return (ZSTREAM(stream))->total_in;
- }
- JNIEXPORT jlong JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_getBytesWritten(
- JNIEnv *env, jclass cls, jlong stream
- ) {
- return (ZSTREAM(stream))->total_out;
- }
- JNIEXPORT void JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_reset(
- JNIEnv *env, jclass cls, jlong stream
- ) {
- if (dlsym_inflateReset(ZSTREAM(stream)) != Z_OK) {
- THROW(env, "java/lang/InternalError", 0);
- }
- }
- JNIEXPORT void JNICALL
- Java_org_apache_hadoop_io_compress_zlib_ZlibDecompressor_end(
- JNIEnv *env, jclass cls, jlong stream
- ) {
- if (dlsym_inflateEnd(ZSTREAM(stream)) == Z_STREAM_ERROR) {
- THROW(env, "java/lang/InternalError", 0);
- } else {
- free(ZSTREAM(stream));
- }
- }
- /**
- * vim: sw=2: ts=2: et:
- */