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 #include <string>
17 #include <cstring>
18 #include <snappy.h>
19 #include "SnappyNative.h"
20
throw_exception(JNIEnv * env,jobject self,int errorCode)21 inline void throw_exception(JNIEnv *env, jobject self, int errorCode)
22 {
23 jclass c = env->FindClass("org/xerial/snappy/SnappyNative");
24 if(c==0)
25 return;
26 jmethodID mth_throwex = env->GetMethodID(c, "throw_error", "(I)V");
27 if(mth_throwex == 0)
28 return;
29 env->CallVoidMethod(self, mth_throwex, (jint) errorCode);
30 }
31
Java_org_xerial_snappy_SnappyNative_nativeLibraryVersion(JNIEnv * env,jobject self)32 JNIEXPORT jstring JNICALL Java_org_xerial_snappy_SnappyNative_nativeLibraryVersion
33 (JNIEnv * env, jobject self)
34 {
35 // TODO: Do we need to read this library version from resources/org/xerial/snappy/VERSION?
36 return env->NewStringUTF("1.1.3");
37 }
38
Java_org_xerial_snappy_SnappyNative_rawCompress__JJJ(JNIEnv * env,jobject self,jlong srcAddr,jlong length,jlong destAddr)39 JNIEXPORT jlong JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__JJJ
40 (JNIEnv* env, jobject self, jlong srcAddr, jlong length, jlong destAddr) {
41 size_t compressedLength;
42 snappy::RawCompress((char*) srcAddr, (size_t) length, (char*) destAddr, &compressedLength);
43 return (jlong) compressedLength;
44 }
45
Java_org_xerial_snappy_SnappyNative_rawUncompress__JJJ(JNIEnv * env,jobject self,jlong srcAddr,jlong length,jlong destAddr)46 JNIEXPORT jlong JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__JJJ
47 (JNIEnv* env, jobject self, jlong srcAddr, jlong length, jlong destAddr) {
48
49 size_t uncompressedLength;
50 snappy::GetUncompressedLength((char*) srcAddr, (size_t) length, &uncompressedLength);
51 bool ret = snappy::RawUncompress((char*) srcAddr, (size_t) length, (char*) destAddr);
52
53 if(!ret) {
54 throw_exception(env, self, 5);
55 return 0;
56 }
57
58 return (jlong) uncompressedLength;
59 }
60
61 /*
62 * Class: org_xerial_snappy_Snappy
63 * Method: compress
64 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)J
65 */
Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I(JNIEnv * env,jobject self,jobject uncompressed,jint upos,jint ulen,jobject compressed,jint cpos)66 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
67 (JNIEnv* env, jobject self, jobject uncompressed, jint upos, jint ulen, jobject compressed, jint cpos)
68 {
69 char* uncompressedBuffer = (char*) env->GetDirectBufferAddress(uncompressed);
70 char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
71 if(uncompressedBuffer == 0 || compressedBuffer == 0) {
72 throw_exception(env, self, 3);
73 return (jint) 0;
74 }
75
76 size_t compressedLength;
77 snappy::RawCompress(uncompressedBuffer + upos, (size_t) ulen, compressedBuffer + cpos, &compressedLength);
78 return (jint) compressedLength;
79 }
80
Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_lang_Object_2IILjava_lang_Object_2I(JNIEnv * env,jobject self,jobject input,jint inputOffset,jint inputLen,jobject output,jint outputOffset)81 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_lang_Object_2IILjava_lang_Object_2I
82 (JNIEnv * env, jobject self, jobject input, jint inputOffset, jint inputLen, jobject output, jint outputOffset)
83 {
84 char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
85 char* out = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
86 if(in == 0 || out == 0) {
87 // out of memory
88 if(in != 0) {
89 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
90 }
91 if(out != 0) {
92 env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
93 }
94 throw_exception(env, self, 4);
95 return 0;
96 }
97
98 size_t compressedLength;
99 snappy::RawCompress(in + inputOffset, (size_t) inputLen, out + outputOffset, &compressedLength);
100
101 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
102 env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
103
104 return (jint) compressedLength;
105 }
106
Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_lang_Object_2IILjava_lang_Object_2I(JNIEnv * env,jobject self,jobject input,jint inputOffset,jint inputLength,jobject output,jint outputOffset)107 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_lang_Object_2IILjava_lang_Object_2I
108 (JNIEnv * env, jobject self, jobject input, jint inputOffset, jint inputLength, jobject output, jint outputOffset)
109 {
110 char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
111 char* out = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
112 if(in == 0 || out == 0) {
113 // out of memory
114 if(in != 0) {
115 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
116 }
117 if(out != 0) {
118 env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
119 }
120 throw_exception(env, self, 4);
121 return 0;
122 }
123
124 size_t uncompressedLength;
125 snappy::GetUncompressedLength(in + inputOffset, (size_t) inputLength, &uncompressedLength);
126 bool ret = snappy::RawUncompress(in + inputOffset, (size_t) inputLength, out + outputOffset);
127
128 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
129 env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
130
131 if(!ret) {
132 throw_exception(env, self, 5);
133 return 0;
134 }
135
136 return (jint) uncompressedLength;
137 }
138
139 /*
140 * Class: org_xerial_snappy_Snappy
141 * Method: uncompress
142 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Z
143 */
Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I(JNIEnv * env,jobject self,jobject compressed,jint cpos,jint clen,jobject decompressed,jint dpos)144 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
145 (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen, jobject decompressed, jint dpos)
146 {
147 char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
148 char* decompressedBuffer = (char*) env->GetDirectBufferAddress(decompressed);
149 if(compressedBuffer == 0 || decompressedBuffer == 0) {
150 throw_exception(env, self, 3);
151 return (jint) 0;
152 }
153
154 size_t decompressedLength;
155 snappy::GetUncompressedLength(compressedBuffer + cpos, (size_t) clen, &decompressedLength);
156 bool ret = snappy::RawUncompress(compressedBuffer + cpos, (size_t) clen, decompressedBuffer + dpos);
157 if(!ret) {
158 throw_exception(env, self, 5);
159 return 0;
160 }
161
162 return (jint) decompressedLength;
163 }
164
165 /*
166 * Class: org_xerial_snappy_Snappy
167 * Method: maxCompressedLength
168 * Signature: (J)J
169 */
170
Java_org_xerial_snappy_SnappyNative_maxCompressedLength(JNIEnv *,jobject,jint size)171 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_maxCompressedLength
172 (JNIEnv *, jobject, jint size)
173 {
174 size_t l = snappy::MaxCompressedLength((size_t) size);
175 return (jint) l;
176 }
177
178 /*
179 * Class: org_xerial_snappy_Snappy
180 * Method: getUncompressedLength
181 * Signature: (Ljava/nio/ByteBuffer;)J
182 */
Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_nio_ByteBuffer_2II(JNIEnv * env,jobject self,jobject compressed,jint cpos,jint clen)183 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_nio_ByteBuffer_2II
184 (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen)
185 {
186 char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
187 if(compressedBuffer == 0) {
188 throw_exception(env, self, 3);
189 return (jint) 0;
190 }
191
192 size_t result;
193 bool ret = snappy::GetUncompressedLength(compressedBuffer + cpos, (size_t) clen, &result);
194 if(!ret) {
195 throw_exception(env, self, 2);
196 return 0;
197 }
198 return (jint) result;
199 }
200
Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_lang_Object_2II(JNIEnv * env,jobject self,jobject input,jint offset,jint length)201 JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_lang_Object_2II
202 (JNIEnv * env, jobject self, jobject input, jint offset, jint length)
203 {
204 char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
205 if(in == 0) {
206 // out of memory
207 throw_exception(env, self, 4);
208 return 0;
209 }
210
211 size_t result;
212 bool ret = snappy::GetUncompressedLength(in + offset, (size_t) length, &result);
213 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
214
215 if(!ret) {
216 throw_exception(env, self, 2);
217 return 0;
218 }
219
220 return (jint) result;
221 }
222
Java_org_xerial_snappy_SnappyNative_uncompressedLength__JJ(JNIEnv * env,jobject self,jlong inputAddr,jlong len)223 JNIEXPORT jlong JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__JJ
224 (JNIEnv *env, jobject self, jlong inputAddr, jlong len) {
225
226
227 size_t result;
228 bool ret = snappy::GetUncompressedLength((char*) inputAddr, (size_t) len, &result);
229 if(!ret) {
230 throw_exception(env, self, 2);
231 return 0;
232 }
233
234 return (jint) result;
235 }
236
Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_nio_ByteBuffer_2II(JNIEnv * env,jobject self,jobject compressed,jint cpos,jint clen)237 JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_nio_ByteBuffer_2II
238 (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen)
239 {
240 char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
241 if(compressedBuffer == 0) {
242 throw_exception(env, self, 3);
243 return (jint) 0;
244 }
245 bool ret = snappy::IsValidCompressedBuffer(compressedBuffer + cpos, (size_t) clen);
246 return ret;
247 }
248
249
Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_lang_Object_2II(JNIEnv * env,jobject self,jobject input,jint offset,jint length)250 JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_lang_Object_2II
251 (JNIEnv * env, jobject self, jobject input, jint offset, jint length)
252 {
253 char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
254 if(in == 0) {
255 // out of memory
256 throw_exception(env, self, 4);
257 return 0;
258 }
259 bool ret = snappy::IsValidCompressedBuffer(in + offset, (size_t) length);
260 env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
261 return ret;
262 }
263
Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__JJJ(JNIEnv * env,jobject self,jlong inputAddr,jlong offset,jlong length)264 JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__JJJ
265 (JNIEnv * env, jobject self, jlong inputAddr, jlong offset, jlong length)
266 {
267 if(inputAddr == 0) {
268 // out of memory
269 throw_exception(env, self, 4);
270 return 0;
271 }
272 bool ret = snappy::IsValidCompressedBuffer((char*) (inputAddr + offset), (size_t) length);
273 return ret;
274 }
275
276
Java_org_xerial_snappy_SnappyNative_arrayCopy(JNIEnv * env,jobject self,jobject input,jint offset,jint length,jobject output,jint output_offset)277 JNIEXPORT void JNICALL Java_org_xerial_snappy_SnappyNative_arrayCopy
278 (JNIEnv * env, jobject self, jobject input, jint offset, jint length, jobject output, jint output_offset)
279 {
280 char* src = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
281 char* dest = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
282 if(src == 0 || dest == 0) {
283 // out of memory
284 if(src != 0) {
285 env->ReleasePrimitiveArrayCritical((jarray) input, src, 0);
286 }
287 if(dest != 0) {
288 env->ReleasePrimitiveArrayCritical((jarray) output, dest, 0);
289 }
290 throw_exception(env, self, 4);
291 return;
292 }
293
294 memcpy(dest+output_offset, src+offset, (size_t) length);
295
296 env->ReleasePrimitiveArrayCritical((jarray) input, src, 0);
297 env->ReleasePrimitiveArrayCritical((jarray) output, dest, 0);
298 }
299
300