comparison mupdf-source/platform/java/jni/buffer.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 /* Buffer interface */
24
25 JNIEXPORT void JNICALL
26 FUN(Buffer_finalize)(JNIEnv *env, jobject self)
27 {
28 fz_context *ctx = get_context(env);
29 fz_buffer *buf = from_Buffer_safe(env, self);
30 if (!ctx || !buf) return;
31 (*env)->SetLongField(env, self, fid_Buffer_pointer, 0);
32 fz_drop_buffer(ctx, buf);
33 }
34
35 JNIEXPORT jlong JNICALL
36 FUN(Buffer_newNativeBuffer)(JNIEnv *env, jobject self, jint n)
37 {
38 fz_context *ctx = get_context(env);
39 fz_buffer *buf = NULL;
40
41 if (!ctx) return 0;
42 if (n < 0) jni_throw_arg(env, "n cannot be negative");
43
44 fz_try(ctx)
45 buf = fz_new_buffer(ctx, n);
46 fz_catch(ctx)
47 jni_rethrow(env, ctx);
48
49 return jlong_cast(buf);
50 }
51
52 JNIEXPORT jint JNICALL
53 FUN(Buffer_getLength)(JNIEnv *env, jobject self)
54 {
55 fz_context *ctx = get_context(env);
56 fz_buffer *buf = from_Buffer(env, self);
57
58 if (!ctx || !buf) return -1;
59
60 return (jint)fz_buffer_storage(ctx, buf, NULL);
61 }
62
63 JNIEXPORT jint JNICALL
64 FUN(Buffer_readByte)(JNIEnv *env, jobject self, jint jat)
65 {
66 fz_context *ctx = get_context(env);
67 fz_buffer *buf = from_Buffer(env, self);
68 size_t at = (size_t) jat;
69 size_t len;
70 unsigned char *data;
71
72 if (!ctx || !buf) return -1;
73 if (jat < 0) jni_throw_oob(env, "at is negative");
74
75 len = fz_buffer_storage(ctx, buf, &data);
76 if (at >= len)
77 return -1;
78
79 return data[at];
80 }
81
82 JNIEXPORT jint JNICALL
83 FUN(Buffer_readBytes)(JNIEnv *env, jobject self, jint jat, jobject jbs)
84 {
85 fz_context *ctx = get_context(env);
86 fz_buffer *buf = from_Buffer(env, self);
87 size_t at = (size_t) jat;
88 jbyte *bs = NULL;
89 size_t len;
90 size_t remaining_input = 0;
91 size_t remaining_output = 0;
92 unsigned char *data;
93
94 if (!ctx || !buf) return -1;
95 if (jat < 0) jni_throw_oob(env, "at is negative");
96 if (!jbs) jni_throw_arg(env, "buffer must not be null");
97
98 len = fz_buffer_storage(ctx, buf, &data);
99 if (at >= len)
100 return -1;
101
102 remaining_input = len - at;
103 remaining_output = (*env)->GetArrayLength(env, jbs);
104 len = fz_minz(remaining_output, remaining_input);
105
106 bs = (*env)->GetByteArrayElements(env, jbs, NULL);
107 if (!bs) jni_throw_io(env, "cannot get bytes to read");
108
109 memcpy(bs, &data[at], len);
110 (*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
111
112 return (jint)len;
113 }
114
115 JNIEXPORT jint JNICALL
116 FUN(Buffer_readBytesInto)(JNIEnv *env, jobject self, jint jat, jobject jbs, jint joff, jint jlen)
117 {
118 fz_context *ctx = get_context(env);
119 fz_buffer *buf = from_Buffer(env, self);
120 size_t at = (size_t) jat;
121 jbyte *bs = NULL;
122 size_t off = (size_t) joff;
123 size_t len = (size_t) jlen;
124 size_t bslen = 0;
125 size_t blen;
126 unsigned char *data;
127
128 if (!ctx || !buf) return -1;
129 if (jat < 0) jni_throw_oob(env, "at is negative");
130 if (!jbs) jni_throw_arg(env, "buffer must not be null");
131 if (joff < 0) jni_throw_oob(env, "offset is negative");
132 if (jlen < 0) jni_throw_oob(env, "length is negative");
133
134 bslen = (*env)->GetArrayLength(env, jbs);
135 if (len > bslen - off) jni_throw_oob(env, "offset + length is outside of buffer");
136
137 blen = fz_buffer_storage(ctx, buf, &data);
138 if (at >= blen)
139 return -1;
140
141 len = fz_minz(len, blen - at);
142
143 bs = (*env)->GetByteArrayElements(env, jbs, NULL);
144 if (!bs) jni_throw_io(env, "cannot get bytes to read");
145
146 memcpy(&bs[off], &data[at], len);
147 (*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
148
149 return (jint)len;
150 }
151
152 JNIEXPORT void JNICALL
153 FUN(Buffer_writeByte)(JNIEnv *env, jobject self, jbyte b)
154 {
155 fz_context *ctx = get_context(env);
156 fz_buffer *buf = from_Buffer(env, self);
157
158 if (!ctx || !buf) return;
159
160 fz_try(ctx)
161 fz_append_byte(ctx, buf, b);
162 fz_catch(ctx)
163 jni_rethrow_void(env, ctx);
164 }
165
166 JNIEXPORT void JNICALL
167 FUN(Buffer_writeBytes)(JNIEnv *env, jobject self, jobject jbs)
168 {
169 fz_context *ctx = get_context(env);
170 fz_buffer *buf = from_Buffer(env, self);
171 jsize len = 0;
172 jbyte *bs = NULL;
173
174 if (!ctx || !buf) return;
175 if (!jbs) jni_throw_arg_void(env, "buffer must not be null");
176
177 len = (*env)->GetArrayLength(env, jbs);
178 bs = (*env)->GetByteArrayElements(env, jbs, NULL);
179 if (!bs) jni_throw_io_void(env, "cannot get bytes to write");
180
181 fz_try(ctx)
182 fz_append_data(ctx, buf, bs, len);
183 fz_always(ctx)
184 (*env)->ReleaseByteArrayElements(env, jbs, bs, JNI_ABORT);
185 fz_catch(ctx)
186 jni_rethrow_void(env, ctx);
187 }
188
189 JNIEXPORT void JNICALL
190 FUN(Buffer_writeBytesFrom)(JNIEnv *env, jobject self, jobject jbs, jint joff, jint jlen)
191 {
192 fz_context *ctx = get_context(env);
193 fz_buffer *buf = from_Buffer(env, self);
194 jbyte *bs = NULL;
195 jsize off = (jsize) joff;
196 jsize len = (jsize) jlen;
197 jsize bslen = 0;
198
199 if (!ctx || !buf) return;
200 if (!jbs) jni_throw_arg_void(env, "buffer must not be null");
201
202 bslen = (*env)->GetArrayLength(env, jbs);
203 if (joff < 0) jni_throw_oob_void(env, "offset is negative");
204 if (jlen < 0) jni_throw_oob_void(env, "length is negative");
205 if (off + len > bslen) jni_throw_oob_void(env, "offset + length is outside of buffer");
206
207 bs = (*env)->GetByteArrayElements(env, jbs, NULL);
208 if (!bs) jni_throw_io_void(env, "cannot get bytes to write");
209
210 fz_try(ctx)
211 fz_append_data(ctx, buf, &bs[off], len);
212 fz_always(ctx)
213 (*env)->ReleaseByteArrayElements(env, jbs, bs, JNI_ABORT);
214 fz_catch(ctx)
215 jni_rethrow_void(env, ctx);
216 }
217
218 JNIEXPORT void JNICALL
219 FUN(Buffer_writeBuffer)(JNIEnv *env, jobject self, jobject jbuf)
220 {
221 fz_context *ctx = get_context(env);
222 fz_buffer *buf = from_Buffer(env, self);
223 fz_buffer *cat = from_Buffer(env, jbuf);
224
225 if (!ctx || !buf) return;
226 if (!cat) jni_throw_arg_void(env, "buffer must not be null");
227
228 fz_try(ctx)
229 fz_append_buffer(ctx, buf, cat);
230 fz_catch(ctx)
231 jni_rethrow_void(env, ctx);
232 }
233
234 JNIEXPORT void JNICALL
235 FUN(Buffer_writeRune)(JNIEnv *env, jobject self, jint rune)
236 {
237 fz_context *ctx = get_context(env);
238 fz_buffer *buf = from_Buffer(env, self);
239
240 if (!ctx || !buf) return;
241
242 fz_try(ctx)
243 fz_append_rune(ctx, buf, rune);
244 fz_catch(ctx)
245 jni_rethrow_void(env, ctx);
246 }
247
248 JNIEXPORT void JNICALL
249 FUN(Buffer_writeLine)(JNIEnv *env, jobject self, jstring jline)
250 {
251 fz_context *ctx = get_context(env);
252 fz_buffer *buf = from_Buffer(env, self);
253 const char *line = NULL;
254
255 if (!ctx || !buf) return;
256 if (!jline) jni_throw_arg_void(env, "line must not be null");
257
258 line = (*env)->GetStringUTFChars(env, jline, NULL);
259 if (!line) return;
260
261 fz_try(ctx)
262 {
263 fz_append_string(ctx, buf, line);
264 fz_append_byte(ctx, buf, '\n');
265 }
266 fz_always(ctx)
267 (*env)->ReleaseStringUTFChars(env, jline, line);
268 fz_catch(ctx)
269 jni_rethrow_void(env, ctx);
270 }
271
272 JNIEXPORT void JNICALL
273 FUN(Buffer_writeLines)(JNIEnv *env, jobject self, jobject jlines)
274 {
275 fz_context *ctx = get_context(env);
276 fz_buffer *buf = from_Buffer(env, self);
277 int i = 0;
278 jsize len = 0;
279
280 if (!ctx || !buf) return;
281 if (!jlines) jni_throw_arg_void(env, "lines must not be null");
282
283 len = (*env)->GetArrayLength(env, jlines);
284
285 for (i = 0; i < len; ++i)
286 {
287 const char *line;
288 jobject jline;
289
290 jline = (*env)->GetObjectArrayElement(env, jlines, i);
291 if ((*env)->ExceptionCheck(env)) return;
292
293 if (!jline)
294 continue;
295 line = (*env)->GetStringUTFChars(env, jline, NULL);
296 if (!line) return;
297
298 fz_try(ctx)
299 {
300 fz_append_string(ctx, buf, line);
301 fz_append_byte(ctx, buf, '\n');
302 }
303 fz_always(ctx)
304 (*env)->ReleaseStringUTFChars(env, jline, line);
305 fz_catch(ctx)
306 jni_rethrow_void(env, ctx);
307 }
308 }
309
310 JNIEXPORT void JNICALL
311 FUN(Buffer_save)(JNIEnv *env, jobject self, jstring jfilename)
312 {
313 fz_context *ctx = get_context(env);
314 fz_buffer *buf = from_Buffer(env, self);
315 const char *filename = NULL;
316
317 if (!ctx || !buf) return;
318 if (jfilename)
319 {
320 filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
321 if (!filename) return;
322 }
323
324 fz_try(ctx)
325 fz_save_buffer(ctx, buf, filename);
326 fz_always(ctx)
327 if (filename)
328 (*env)->ReleaseStringUTFChars(env, jfilename, filename);
329 fz_catch(ctx)
330 jni_rethrow_void(env, ctx);
331 }
332
333 JNIEXPORT jobject JNICALL
334 FUN(Buffer_slice)(JNIEnv *env, jobject self, jint start, jint end)
335 {
336 fz_context *ctx = get_context(env);
337 fz_buffer *buf = from_Buffer(env, self);
338 fz_buffer *copy = NULL;
339 jobject jcopy = NULL;
340
341 if (!ctx || !buf) return NULL;
342
343 fz_try(ctx)
344 copy = fz_slice_buffer(ctx, buf, start, end);
345 fz_catch(ctx)
346 jni_rethrow(env, ctx);
347
348 jcopy = (*env)->NewObject(env, cls_Buffer, mid_Buffer_init, copy);
349 if (!jcopy || (*env)->ExceptionCheck(env))
350 return NULL;
351
352 return jcopy;
353 }
354
355 JNIEXPORT jstring JNICALL
356 FUN(Buffer_asString)(JNIEnv *env, jobject self)
357 {
358 fz_context *ctx = get_context(env);
359 fz_buffer *buf = from_Buffer(env, self);
360 const char *s = NULL;
361
362 if (!ctx || !buf) return NULL;
363
364 fz_try(ctx)
365 s = fz_string_from_buffer(ctx, buf);
366 fz_catch(ctx)
367 jni_rethrow(env, ctx);
368
369 return to_String_safe(ctx, env, s);
370 }