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