Deflater.c 8.0 KB
Newer Older
D
duke 已提交
1
/*
O
ohair 已提交
2
 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
8
 * particular file as subject to the "Classpath" exception as provided
9
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
10 11 12 13 14 15 16 17 18 19 20
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
21 22 23
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
 */

/*
 * Native method support for java.util.zip.Deflater
 */

#include <stdio.h>
#include <stdlib.h>
#include "jlong.h"
#include "jni.h"
#include "jni_util.h"
#include "zlib.h"

#include "java_util_zip_Deflater.h"

#define DEF_MEM_LEVEL 8

static jfieldID levelID;
static jfieldID strategyID;
static jfieldID setParamsID;
static jfieldID finishID;
static jfieldID finishedID;
static jfieldID bufID, offID, lenID;

JNIEXPORT void JNICALL
Java_java_util_zip_Deflater_initIDs(JNIEnv *env, jclass cls)
{
    levelID = (*env)->GetFieldID(env, cls, "level", "I");
    strategyID = (*env)->GetFieldID(env, cls, "strategy", "I");
    setParamsID = (*env)->GetFieldID(env, cls, "setParams", "Z");
    finishID = (*env)->GetFieldID(env, cls, "finish", "Z");
    finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
    bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
    offID = (*env)->GetFieldID(env, cls, "off", "I");
    lenID = (*env)->GetFieldID(env, cls, "len", "I");
}

JNIEXPORT jlong JNICALL
Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level,
                                 jint strategy, jboolean nowrap)
{
    z_stream *strm = calloc(1, sizeof(z_stream));

    if (strm == 0) {
        JNU_ThrowOutOfMemoryError(env, 0);
        return jlong_zero;
    } else {
        char *msg;
        switch (deflateInit2(strm, level, Z_DEFLATED,
                             nowrap ? -MAX_WBITS : MAX_WBITS,
                             DEF_MEM_LEVEL, strategy)) {
          case Z_OK:
            return ptr_to_jlong(strm);
          case Z_MEM_ERROR:
            free(strm);
            JNU_ThrowOutOfMemoryError(env, 0);
            return jlong_zero;
          case Z_STREAM_ERROR:
            free(strm);
            JNU_ThrowIllegalArgumentException(env, 0);
            return jlong_zero;
          default:
            msg = strm->msg;
            free(strm);
            JNU_ThrowInternalError(env, msg);
            return jlong_zero;
        }
    }
}

JNIEXPORT void JNICALL
S
sherman 已提交
95
Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
D
duke 已提交
96 97 98 99 100 101 102
                                          jarray b, jint off, jint len)
{
    Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
    int res;
    if (buf == 0) {/* out of memory */
        return;
    }
S
sherman 已提交
103
    res = deflateSetDictionary((z_stream *)jlong_to_ptr(addr), buf + off, len);
D
duke 已提交
104 105 106 107 108 109 110 111
    (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
    switch (res) {
    case Z_OK:
        break;
    case Z_STREAM_ERROR:
        JNU_ThrowIllegalArgumentException(env, 0);
        break;
    default:
S
sherman 已提交
112
        JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg);
D
duke 已提交
113 114 115 116 117
        break;
    }
}

JNIEXPORT jint JNICALL
S
sherman 已提交
118
Java_java_util_zip_Deflater_deflateBytes(JNIEnv *env, jobject this, jlong addr,
119
                                         jarray b, jint off, jint len, jint flush)
D
duke 已提交
120
{
S
sherman 已提交
121
    z_stream *strm = jlong_to_ptr(addr);
D
duke 已提交
122

S
sherman 已提交
123 124 125 126 127 128 129 130 131
    jarray this_buf = (*env)->GetObjectField(env, this, bufID);
    jint this_off = (*env)->GetIntField(env, this, offID);
    jint this_len = (*env)->GetIntField(env, this, lenID);
    jbyte *in_buf;
    jbyte *out_buf;
    int res;
    if ((*env)->GetBooleanField(env, this, setParamsID)) {
        int level = (*env)->GetIntField(env, this, levelID);
        int strategy = (*env)->GetIntField(env, this, strategyID);
132 133
        in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
        if (in_buf == NULL) {
134 135 136
            // Throw OOME only when length is not zero
            if (this_len != 0)
                JNU_ThrowOutOfMemoryError(env, 0);
S
sherman 已提交
137 138
            return 0;
        }
139 140 141
        out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
        if (out_buf == NULL) {
            (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
142 143
            if (len != 0)
                JNU_ThrowOutOfMemoryError(env, 0);
S
sherman 已提交
144 145
            return 0;
        }
D
duke 已提交
146

147 148
        strm->next_in = (Bytef *) (in_buf + this_off);
        strm->next_out = (Bytef *) (out_buf + off);
S
sherman 已提交
149 150 151
        strm->avail_in = this_len;
        strm->avail_out = len;
        res = deflateParams(strm, level, strategy);
152 153
        (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
        (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
S
sherman 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

        switch (res) {
        case Z_OK:
            (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
            this_off += this_len - strm->avail_in;
            (*env)->SetIntField(env, this, offID, this_off);
            (*env)->SetIntField(env, this, lenID, strm->avail_in);
            return len - strm->avail_out;
        case Z_BUF_ERROR:
            (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
            return 0;
        default:
            JNU_ThrowInternalError(env, strm->msg);
            return 0;
        }
    } else {
        jboolean finish = (*env)->GetBooleanField(env, this, finishID);
171 172
        in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
        if (in_buf == NULL) {
173 174
            if (this_len != 0)
                JNU_ThrowOutOfMemoryError(env, 0);
S
sherman 已提交
175 176
            return 0;
        }
177 178 179
        out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
        if (out_buf == NULL) {
            (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
180 181
            if (len != 0)
                JNU_ThrowOutOfMemoryError(env, 0);
182

S
sherman 已提交
183 184
            return 0;
        }
D
duke 已提交
185

186 187
        strm->next_in = (Bytef *) (in_buf + this_off);
        strm->next_out = (Bytef *) (out_buf + off);
S
sherman 已提交
188 189 190
        strm->avail_in = this_len;
        strm->avail_out = len;
        res = deflate(strm, finish ? Z_FINISH : flush);
191 192
        (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
        (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
S
sherman 已提交
193 194 195 196 197 198 199 200 201 202 203 204

        switch (res) {
        case Z_STREAM_END:
            (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
            /* fall through */
        case Z_OK:
            this_off += this_len - strm->avail_in;
            (*env)->SetIntField(env, this, offID, this_off);
            (*env)->SetIntField(env, this, lenID, strm->avail_in);
            return len - strm->avail_out;
        case Z_BUF_ERROR:
            return 0;
D
duke 已提交
205
            default:
S
sherman 已提交
206 207
            JNU_ThrowInternalError(env, strm->msg);
            return 0;
D
duke 已提交
208 209 210 211 212
        }
    }
}

JNIEXPORT jint JNICALL
S
sherman 已提交
213
Java_java_util_zip_Deflater_getAdler(JNIEnv *env, jclass cls, jlong addr)
D
duke 已提交
214
{
S
sherman 已提交
215
    return ((z_stream *)jlong_to_ptr(addr))->adler;
D
duke 已提交
216 217 218
}

JNIEXPORT void JNICALL
S
sherman 已提交
219
Java_java_util_zip_Deflater_reset(JNIEnv *env, jclass cls, jlong addr)
D
duke 已提交
220
{
S
sherman 已提交
221
    if (deflateReset((z_stream *)jlong_to_ptr(addr)) != Z_OK) {
D
duke 已提交
222 223 224 225 226
        JNU_ThrowInternalError(env, 0);
    }
}

JNIEXPORT void JNICALL
S
sherman 已提交
227
Java_java_util_zip_Deflater_end(JNIEnv *env, jclass cls, jlong addr)
D
duke 已提交
228
{
S
sherman 已提交
229
    if (deflateEnd((z_stream *)jlong_to_ptr(addr)) == Z_STREAM_ERROR) {
D
duke 已提交
230 231
        JNU_ThrowInternalError(env, 0);
    } else {
S
sherman 已提交
232
        free((z_stream *)jlong_to_ptr(addr));
D
duke 已提交
233 234
    }
}