buffer.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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. /* Buffer interface */
  23. JNIEXPORT void JNICALL
  24. FUN(Buffer_finalize)(JNIEnv *env, jobject self)
  25. {
  26. fz_context *ctx = get_context(env);
  27. fz_buffer *buf = from_Buffer_safe(env, self);
  28. if (!ctx || !buf) return;
  29. (*env)->SetLongField(env, self, fid_Buffer_pointer, 0);
  30. fz_drop_buffer(ctx, buf);
  31. }
  32. JNIEXPORT jlong JNICALL
  33. FUN(Buffer_newNativeBuffer)(JNIEnv *env, jobject self, jint n)
  34. {
  35. fz_context *ctx = get_context(env);
  36. fz_buffer *buf = NULL;
  37. if (!ctx) return 0;
  38. if (n < 0) jni_throw_arg(env, "n cannot be negative");
  39. fz_try(ctx)
  40. buf = fz_new_buffer(ctx, n);
  41. fz_catch(ctx)
  42. jni_rethrow(env, ctx);
  43. return jlong_cast(buf);
  44. }
  45. JNIEXPORT jint JNICALL
  46. FUN(Buffer_getLength)(JNIEnv *env, jobject self)
  47. {
  48. fz_context *ctx = get_context(env);
  49. fz_buffer *buf = from_Buffer(env, self);
  50. if (!ctx || !buf) return -1;
  51. return (jint)fz_buffer_storage(ctx, buf, NULL);
  52. }
  53. JNIEXPORT jint JNICALL
  54. FUN(Buffer_readByte)(JNIEnv *env, jobject self, jint jat)
  55. {
  56. fz_context *ctx = get_context(env);
  57. fz_buffer *buf = from_Buffer(env, self);
  58. size_t at = (size_t) jat;
  59. size_t len;
  60. unsigned char *data;
  61. if (!ctx || !buf) return -1;
  62. if (jat < 0) jni_throw_oob(env, "at is negative");
  63. len = fz_buffer_storage(ctx, buf, &data);
  64. if (at >= len)
  65. return -1;
  66. return data[at];
  67. }
  68. JNIEXPORT jint JNICALL
  69. FUN(Buffer_readBytes)(JNIEnv *env, jobject self, jint jat, jobject jbs)
  70. {
  71. fz_context *ctx = get_context(env);
  72. fz_buffer *buf = from_Buffer(env, self);
  73. size_t at = (size_t) jat;
  74. jbyte *bs = NULL;
  75. size_t len;
  76. size_t remaining_input = 0;
  77. size_t remaining_output = 0;
  78. unsigned char *data;
  79. if (!ctx || !buf) return -1;
  80. if (jat < 0) jni_throw_oob(env, "at is negative");
  81. if (!jbs) jni_throw_arg(env, "buffer must not be null");
  82. len = fz_buffer_storage(ctx, buf, &data);
  83. if (at >= len)
  84. return -1;
  85. remaining_input = len - at;
  86. remaining_output = (*env)->GetArrayLength(env, jbs);
  87. len = fz_minz(remaining_output, remaining_input);
  88. bs = (*env)->GetByteArrayElements(env, jbs, NULL);
  89. if (!bs) jni_throw_io(env, "cannot get bytes to read");
  90. memcpy(bs, &data[at], len);
  91. (*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
  92. return (jint)len;
  93. }
  94. JNIEXPORT jint JNICALL
  95. FUN(Buffer_readBytesInto)(JNIEnv *env, jobject self, jint jat, jobject jbs, jint joff, jint jlen)
  96. {
  97. fz_context *ctx = get_context(env);
  98. fz_buffer *buf = from_Buffer(env, self);
  99. size_t at = (size_t) jat;
  100. jbyte *bs = NULL;
  101. size_t off = (size_t) joff;
  102. size_t len = (size_t) jlen;
  103. size_t bslen = 0;
  104. size_t blen;
  105. unsigned char *data;
  106. if (!ctx || !buf) return -1;
  107. if (jat < 0) jni_throw_oob(env, "at is negative");
  108. if (!jbs) jni_throw_arg(env, "buffer must not be null");
  109. if (joff < 0) jni_throw_oob(env, "offset is negative");
  110. if (jlen < 0) jni_throw_oob(env, "length is negative");
  111. bslen = (*env)->GetArrayLength(env, jbs);
  112. if (len > bslen - off) jni_throw_oob(env, "offset + length is outside of buffer");
  113. blen = fz_buffer_storage(ctx, buf, &data);
  114. if (at >= blen)
  115. return -1;
  116. len = fz_minz(len, blen - at);
  117. bs = (*env)->GetByteArrayElements(env, jbs, NULL);
  118. if (!bs) jni_throw_io(env, "cannot get bytes to read");
  119. memcpy(&bs[off], &data[at], len);
  120. (*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
  121. return (jint)len;
  122. }
  123. JNIEXPORT void JNICALL
  124. FUN(Buffer_writeByte)(JNIEnv *env, jobject self, jbyte b)
  125. {
  126. fz_context *ctx = get_context(env);
  127. fz_buffer *buf = from_Buffer(env, self);
  128. if (!ctx || !buf) return;
  129. fz_try(ctx)
  130. fz_append_byte(ctx, buf, b);
  131. fz_catch(ctx)
  132. jni_rethrow_void(env, ctx);
  133. }
  134. JNIEXPORT void JNICALL
  135. FUN(Buffer_writeBytes)(JNIEnv *env, jobject self, jobject jbs)
  136. {
  137. fz_context *ctx = get_context(env);
  138. fz_buffer *buf = from_Buffer(env, self);
  139. jsize len = 0;
  140. jbyte *bs = NULL;
  141. if (!ctx || !buf) return;
  142. if (!jbs) jni_throw_arg_void(env, "buffer must not be null");
  143. len = (*env)->GetArrayLength(env, jbs);
  144. bs = (*env)->GetByteArrayElements(env, jbs, NULL);
  145. if (!bs) jni_throw_io_void(env, "cannot get bytes to write");
  146. fz_try(ctx)
  147. fz_append_data(ctx, buf, bs, len);
  148. fz_always(ctx)
  149. (*env)->ReleaseByteArrayElements(env, jbs, bs, JNI_ABORT);
  150. fz_catch(ctx)
  151. jni_rethrow_void(env, ctx);
  152. }
  153. JNIEXPORT void JNICALL
  154. FUN(Buffer_writeBytesFrom)(JNIEnv *env, jobject self, jobject jbs, jint joff, jint jlen)
  155. {
  156. fz_context *ctx = get_context(env);
  157. fz_buffer *buf = from_Buffer(env, self);
  158. jbyte *bs = NULL;
  159. jsize off = (jsize) joff;
  160. jsize len = (jsize) jlen;
  161. jsize bslen = 0;
  162. if (!ctx || !buf) return;
  163. if (!jbs) jni_throw_arg_void(env, "buffer must not be null");
  164. bslen = (*env)->GetArrayLength(env, jbs);
  165. if (joff < 0) jni_throw_oob_void(env, "offset is negative");
  166. if (jlen < 0) jni_throw_oob_void(env, "length is negative");
  167. if (off + len > bslen) jni_throw_oob_void(env, "offset + length is outside of buffer");
  168. bs = (*env)->GetByteArrayElements(env, jbs, NULL);
  169. if (!bs) jni_throw_io_void(env, "cannot get bytes to write");
  170. fz_try(ctx)
  171. fz_append_data(ctx, buf, &bs[off], len);
  172. fz_always(ctx)
  173. (*env)->ReleaseByteArrayElements(env, jbs, bs, JNI_ABORT);
  174. fz_catch(ctx)
  175. jni_rethrow_void(env, ctx);
  176. }
  177. JNIEXPORT void JNICALL
  178. FUN(Buffer_writeBuffer)(JNIEnv *env, jobject self, jobject jbuf)
  179. {
  180. fz_context *ctx = get_context(env);
  181. fz_buffer *buf = from_Buffer(env, self);
  182. fz_buffer *cat = from_Buffer(env, jbuf);
  183. if (!ctx || !buf) return;
  184. if (!cat) jni_throw_arg_void(env, "buffer must not be null");
  185. fz_try(ctx)
  186. fz_append_buffer(ctx, buf, cat);
  187. fz_catch(ctx)
  188. jni_rethrow_void(env, ctx);
  189. }
  190. JNIEXPORT void JNICALL
  191. FUN(Buffer_writeRune)(JNIEnv *env, jobject self, jint rune)
  192. {
  193. fz_context *ctx = get_context(env);
  194. fz_buffer *buf = from_Buffer(env, self);
  195. if (!ctx || !buf) return;
  196. fz_try(ctx)
  197. fz_append_rune(ctx, buf, rune);
  198. fz_catch(ctx)
  199. jni_rethrow_void(env, ctx);
  200. }
  201. JNIEXPORT void JNICALL
  202. FUN(Buffer_writeLine)(JNIEnv *env, jobject self, jstring jline)
  203. {
  204. fz_context *ctx = get_context(env);
  205. fz_buffer *buf = from_Buffer(env, self);
  206. const char *line = NULL;
  207. if (!ctx || !buf) return;
  208. if (!jline) jni_throw_arg_void(env, "line must not be null");
  209. line = (*env)->GetStringUTFChars(env, jline, NULL);
  210. if (!line) return;
  211. fz_try(ctx)
  212. {
  213. fz_append_string(ctx, buf, line);
  214. fz_append_byte(ctx, buf, '\n');
  215. }
  216. fz_always(ctx)
  217. (*env)->ReleaseStringUTFChars(env, jline, line);
  218. fz_catch(ctx)
  219. jni_rethrow_void(env, ctx);
  220. }
  221. JNIEXPORT void JNICALL
  222. FUN(Buffer_writeLines)(JNIEnv *env, jobject self, jobject jlines)
  223. {
  224. fz_context *ctx = get_context(env);
  225. fz_buffer *buf = from_Buffer(env, self);
  226. int i = 0;
  227. jsize len = 0;
  228. if (!ctx || !buf) return;
  229. if (!jlines) jni_throw_arg_void(env, "lines must not be null");
  230. len = (*env)->GetArrayLength(env, jlines);
  231. for (i = 0; i < len; ++i)
  232. {
  233. const char *line;
  234. jobject jline;
  235. jline = (*env)->GetObjectArrayElement(env, jlines, i);
  236. if ((*env)->ExceptionCheck(env)) return;
  237. if (!jline)
  238. continue;
  239. line = (*env)->GetStringUTFChars(env, jline, NULL);
  240. if (!line) return;
  241. fz_try(ctx)
  242. {
  243. fz_append_string(ctx, buf, line);
  244. fz_append_byte(ctx, buf, '\n');
  245. }
  246. fz_always(ctx)
  247. (*env)->ReleaseStringUTFChars(env, jline, line);
  248. fz_catch(ctx)
  249. jni_rethrow_void(env, ctx);
  250. }
  251. }
  252. JNIEXPORT void JNICALL
  253. FUN(Buffer_save)(JNIEnv *env, jobject self, jstring jfilename)
  254. {
  255. fz_context *ctx = get_context(env);
  256. fz_buffer *buf = from_Buffer(env, self);
  257. const char *filename = NULL;
  258. if (!ctx || !buf) return;
  259. if (jfilename)
  260. {
  261. filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
  262. if (!filename) return;
  263. }
  264. fz_try(ctx)
  265. fz_save_buffer(ctx, buf, filename);
  266. fz_always(ctx)
  267. if (filename)
  268. (*env)->ReleaseStringUTFChars(env, jfilename, filename);
  269. fz_catch(ctx)
  270. jni_rethrow_void(env, ctx);
  271. }
  272. JNIEXPORT jobject JNICALL
  273. FUN(Buffer_slice)(JNIEnv *env, jobject self, jint start, jint end)
  274. {
  275. fz_context *ctx = get_context(env);
  276. fz_buffer *buf = from_Buffer(env, self);
  277. fz_buffer *copy = NULL;
  278. jobject jcopy = NULL;
  279. if (!ctx || !buf) return NULL;
  280. fz_try(ctx)
  281. copy = fz_slice_buffer(ctx, buf, start, end);
  282. fz_catch(ctx)
  283. jni_rethrow(env, ctx);
  284. jcopy = (*env)->NewObject(env, cls_Buffer, mid_Buffer_init, copy);
  285. if (!jcopy || (*env)->ExceptionCheck(env))
  286. return NULL;
  287. return jcopy;
  288. }
  289. JNIEXPORT jstring JNICALL
  290. FUN(Buffer_asString)(JNIEnv *env, jobject self)
  291. {
  292. fz_context *ctx = get_context(env);
  293. fz_buffer *buf = from_Buffer(env, self);
  294. const char *s = NULL;
  295. if (!ctx || !buf) return NULL;
  296. fz_try(ctx)
  297. s = fz_string_from_buffer(ctx, buf);
  298. fz_catch(ctx)
  299. jni_rethrow(env, ctx);
  300. return to_String_safe(ctx, env, s);
  301. }