1 #include "mupdf/fitz.h"
2
3 #include <string.h>
4 #include <stdarg.h>
5
6 fz_buffer *
fz_new_buffer(fz_context * ctx,size_t size)7 fz_new_buffer(fz_context *ctx, size_t size)
8 {
9 fz_buffer *b;
10
11 size = size > 1 ? size : 16;
12
13 b = fz_malloc_struct(ctx, fz_buffer);
14 b->refs = 1;
15 fz_try(ctx)
16 {
17 b->data = Memento_label(fz_malloc(ctx, size), "fz_buffer_data");
18 }
19 fz_catch(ctx)
20 {
21 fz_free(ctx, b);
22 fz_rethrow(ctx);
23 }
24 b->cap = size;
25 b->len = 0;
26 b->unused_bits = 0;
27
28 return b;
29 }
30
31 fz_buffer *
fz_new_buffer_from_data(fz_context * ctx,unsigned char * data,size_t size)32 fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, size_t size)
33 {
34 fz_buffer *b = NULL;
35
36 fz_try(ctx)
37 {
38 b = fz_malloc_struct(ctx, fz_buffer);
39 b->refs = 1;
40 b->data = data;
41 b->cap = size;
42 b->len = size;
43 b->unused_bits = 0;
44 }
45 fz_catch(ctx)
46 {
47 fz_free(ctx, data);
48 fz_rethrow(ctx);
49 }
50
51 return b;
52 }
53
54 fz_buffer *
fz_new_buffer_from_shared_data(fz_context * ctx,const unsigned char * data,size_t size)55 fz_new_buffer_from_shared_data(fz_context *ctx, const unsigned char *data, size_t size)
56 {
57 fz_buffer *b;
58
59 b = fz_malloc_struct(ctx, fz_buffer);
60 b->refs = 1;
61 b->data = (unsigned char *)data; /* cast away const */
62 b->cap = size;
63 b->len = size;
64 b->unused_bits = 0;
65 b->shared = 1;
66
67 return b;
68 }
69
70 fz_buffer *
fz_new_buffer_from_copied_data(fz_context * ctx,const unsigned char * data,size_t size)71 fz_new_buffer_from_copied_data(fz_context *ctx, const unsigned char *data, size_t size)
72 {
73 fz_buffer *b = fz_new_buffer(ctx, size);
74 b->len = size;
75 memcpy(b->data, data, size);
76 return b;
77 }
78
79 fz_buffer *
fz_new_buffer_from_base64(fz_context * ctx,const char * data,size_t size)80 fz_new_buffer_from_base64(fz_context *ctx, const char *data, size_t size)
81 {
82 fz_buffer *buf = fz_new_buffer(ctx, size);
83 const char *end = data + (size > 0 ? size : strlen(data));
84 const char *s = data;
85 fz_try(ctx)
86 {
87 while (s < end)
88 {
89 int c = *s++;
90 if (c >= 'A' && c <= 'Z')
91 fz_append_bits(ctx, buf, c - 'A', 6);
92 else if (c >= 'a' && c <= 'z')
93 fz_append_bits(ctx, buf, c - 'a' + 26, 6);
94 else if (c >= '0' && c <= '9')
95 fz_append_bits(ctx, buf, c - '0' + 52, 6);
96 else if (c == '+')
97 fz_append_bits(ctx, buf, 62, 6);
98 else if (c == '/')
99 fz_append_bits(ctx, buf, 63, 6);
100 }
101 }
102 fz_catch(ctx)
103 {
104 fz_drop_buffer(ctx, buf);
105 fz_rethrow(ctx);
106 }
107 return buf;
108 }
109
110 fz_buffer *
fz_keep_buffer(fz_context * ctx,fz_buffer * buf)111 fz_keep_buffer(fz_context *ctx, fz_buffer *buf)
112 {
113 return fz_keep_imp(ctx, buf, &buf->refs);
114 }
115
116 void
fz_drop_buffer(fz_context * ctx,fz_buffer * buf)117 fz_drop_buffer(fz_context *ctx, fz_buffer *buf)
118 {
119 if (fz_drop_imp(ctx, buf, &buf->refs))
120 {
121 if (!buf->shared)
122 fz_free(ctx, buf->data);
123 fz_free(ctx, buf);
124 }
125 }
126
127 void
fz_resize_buffer(fz_context * ctx,fz_buffer * buf,size_t size)128 fz_resize_buffer(fz_context *ctx, fz_buffer *buf, size_t size)
129 {
130 if (buf->shared)
131 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot resize a buffer with shared storage");
132 buf->data = fz_realloc(ctx, buf->data, size);
133 buf->cap = size;
134 if (buf->len > buf->cap)
135 buf->len = buf->cap;
136 }
137
138 void
fz_grow_buffer(fz_context * ctx,fz_buffer * buf)139 fz_grow_buffer(fz_context *ctx, fz_buffer *buf)
140 {
141 size_t newsize = (buf->cap * 3) / 2;
142 if (newsize == 0)
143 newsize = 256;
144 fz_resize_buffer(ctx, buf, newsize);
145 }
146
147 static void
fz_ensure_buffer(fz_context * ctx,fz_buffer * buf,size_t min)148 fz_ensure_buffer(fz_context *ctx, fz_buffer *buf, size_t min)
149 {
150 size_t newsize = buf->cap;
151 if (newsize < 16)
152 newsize = 16;
153 while (newsize < min)
154 {
155 newsize = (newsize * 3) / 2;
156 }
157 fz_resize_buffer(ctx, buf, newsize);
158 }
159
160 void
fz_trim_buffer(fz_context * ctx,fz_buffer * buf)161 fz_trim_buffer(fz_context *ctx, fz_buffer *buf)
162 {
163 if (buf->cap > buf->len+1)
164 fz_resize_buffer(ctx, buf, buf->len);
165 }
166
167 void
fz_clear_buffer(fz_context * ctx,fz_buffer * buf)168 fz_clear_buffer(fz_context *ctx, fz_buffer *buf)
169 {
170 buf->len = 0;
171 }
172
173 void
fz_terminate_buffer(fz_context * ctx,fz_buffer * buf)174 fz_terminate_buffer(fz_context *ctx, fz_buffer *buf)
175 {
176 /* ensure that there is a zero-byte after the end of the data */
177 if (buf->len + 1 > buf->cap)
178 fz_grow_buffer(ctx, buf);
179 buf->data[buf->len] = 0;
180 }
181
182 size_t
fz_buffer_storage(fz_context * ctx,fz_buffer * buf,unsigned char ** datap)183 fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
184 {
185 if (datap)
186 *datap = (buf ? buf->data : NULL);
187 return (buf ? buf->len : 0);
188 }
189
190 const char *
fz_string_from_buffer(fz_context * ctx,fz_buffer * buf)191 fz_string_from_buffer(fz_context *ctx, fz_buffer *buf)
192 {
193 if (!buf)
194 return "";
195 fz_terminate_buffer(ctx, buf);
196 return (const char *)buf->data;
197 }
198
199 size_t
fz_buffer_extract(fz_context * ctx,fz_buffer * buf,unsigned char ** datap)200 fz_buffer_extract(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
201 {
202 size_t len = buf ? buf->len : 0;
203 *datap = (buf ? buf->data : NULL);
204
205 if (buf)
206 {
207 buf->data = NULL;
208 buf->len = 0;
209 }
210 return len;
211 }
212
213 void
fz_append_buffer(fz_context * ctx,fz_buffer * buf,fz_buffer * extra)214 fz_append_buffer(fz_context *ctx, fz_buffer *buf, fz_buffer *extra)
215 {
216 if (buf->cap - buf->len < extra->len)
217 {
218 buf->data = fz_realloc(ctx, buf->data, buf->len + extra->len);
219 buf->cap = buf->len + extra->len;
220 }
221
222 memcpy(buf->data + buf->len, extra->data, extra->len);
223 buf->len += extra->len;
224 }
225
226 void
fz_append_data(fz_context * ctx,fz_buffer * buf,const void * data,size_t len)227 fz_append_data(fz_context *ctx, fz_buffer *buf, const void *data, size_t len)
228 {
229 if (buf->len + len > buf->cap)
230 fz_ensure_buffer(ctx, buf, buf->len + len);
231 memcpy(buf->data + buf->len, data, len);
232 buf->len += len;
233 buf->unused_bits = 0;
234 }
235
236 void
fz_append_string(fz_context * ctx,fz_buffer * buf,const char * data)237 fz_append_string(fz_context *ctx, fz_buffer *buf, const char *data)
238 {
239 size_t len = strlen(data);
240 if (buf->len + len > buf->cap)
241 fz_ensure_buffer(ctx, buf, buf->len + len);
242 memcpy(buf->data + buf->len, data, len);
243 buf->len += len;
244 buf->unused_bits = 0;
245 }
246
247 void
fz_append_byte(fz_context * ctx,fz_buffer * buf,int val)248 fz_append_byte(fz_context *ctx, fz_buffer *buf, int val)
249 {
250 if (buf->len + 1 > buf->cap)
251 fz_grow_buffer(ctx, buf);
252 buf->data[buf->len++] = val;
253 buf->unused_bits = 0;
254 }
255
256 void
fz_append_rune(fz_context * ctx,fz_buffer * buf,int c)257 fz_append_rune(fz_context *ctx, fz_buffer *buf, int c)
258 {
259 char data[10];
260 int len = fz_runetochar(data, c);
261 if (buf->len + len > buf->cap)
262 fz_ensure_buffer(ctx, buf, buf->len + len);
263 memcpy(buf->data + buf->len, data, len);
264 buf->len += len;
265 buf->unused_bits = 0;
266 }
267
268 void
fz_append_int32_be(fz_context * ctx,fz_buffer * buf,int x)269 fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x)
270 {
271 fz_append_byte(ctx, buf, (x >> 24) & 0xFF);
272 fz_append_byte(ctx, buf, (x >> 16) & 0xFF);
273 fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
274 fz_append_byte(ctx, buf, (x) & 0xFF);
275 }
276
277 void
fz_append_int16_be(fz_context * ctx,fz_buffer * buf,int x)278 fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x)
279 {
280 fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
281 fz_append_byte(ctx, buf, (x) & 0xFF);
282 }
283
284 void
fz_append_int32_le(fz_context * ctx,fz_buffer * buf,int x)285 fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x)
286 {
287 fz_append_byte(ctx, buf, (x)&0xFF);
288 fz_append_byte(ctx, buf, (x>>8)&0xFF);
289 fz_append_byte(ctx, buf, (x>>16)&0xFF);
290 fz_append_byte(ctx, buf, (x>>24)&0xFF);
291 }
292
293 void
fz_append_int16_le(fz_context * ctx,fz_buffer * buf,int x)294 fz_append_int16_le(fz_context *ctx, fz_buffer *buf, int x)
295 {
296 fz_append_byte(ctx, buf, (x)&0xFF);
297 fz_append_byte(ctx, buf, (x>>8)&0xFF);
298 }
299
300 void
fz_append_bits(fz_context * ctx,fz_buffer * buf,int val,int bits)301 fz_append_bits(fz_context *ctx, fz_buffer *buf, int val, int bits)
302 {
303 int shift;
304
305 /* Throughout this code, the invariant is that we need to write the
306 * bottom 'bits' bits of 'val' into the stream. On entry we assume
307 * that val & ((1<<bits)-1) == val, but we do not rely on this after
308 * having written the first partial byte. */
309
310 if (bits == 0)
311 return;
312
313 /* buf->len always covers all the bits in the buffer, including
314 * any unused ones in the last byte, which will always be 0.
315 * buf->unused_bits = the number of unused bits in the last byte.
316 */
317
318 /* Find the amount we need to shift val up by so that it will be in
319 * the correct position to be inserted into any existing data byte. */
320 shift = (buf->unused_bits - bits);
321
322 /* Extend the buffer as required before we start; that way we never
323 * fail part way during writing. If shift < 0, then we'll need -shift
324 * more bits. */
325 if (shift < 0)
326 {
327 int extra = (7-shift)>>3; /* Round up to bytes */
328 fz_ensure_buffer(ctx, buf, buf->len + extra);
329 }
330
331 /* Write any bits that will fit into the existing byte */
332 if (buf->unused_bits)
333 {
334 buf->data[buf->len-1] |= (shift >= 0 ? (((unsigned int)val)<<shift) : (((unsigned int)val)>>-shift));
335 if (shift >= 0)
336 {
337 /* If we were shifting up, we're done. */
338 buf->unused_bits -= bits;
339 return;
340 }
341 /* The number of bits left to write is the number that didn't
342 * fit in this first byte. */
343 bits = -shift;
344 }
345
346 /* Write any whole bytes */
347 while (bits >= 8)
348 {
349 bits -= 8;
350 buf->data[buf->len++] = val>>bits;
351 }
352
353 /* Write trailing bits (with 0's in unused bits) */
354 if (bits > 0)
355 {
356 bits = 8-bits;
357 buf->data[buf->len++] = val<<bits;
358 }
359 buf->unused_bits = bits;
360 }
361
362 void
fz_append_bits_pad(fz_context * ctx,fz_buffer * buf)363 fz_append_bits_pad(fz_context *ctx, fz_buffer *buf)
364 {
365 buf->unused_bits = 0;
366 }
367
fz_append_emit(fz_context * ctx,void * buffer,int c)368 static void fz_append_emit(fz_context *ctx, void *buffer, int c)
369 {
370 fz_append_byte(ctx, buffer, c);
371 }
372
373 void
fz_append_printf(fz_context * ctx,fz_buffer * buffer,const char * fmt,...)374 fz_append_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...)
375 {
376 va_list args;
377 va_start(args, fmt);
378 fz_format_string(ctx, buffer, fz_append_emit, fmt, args);
379 va_end(args);
380 }
381
382 void
fz_append_vprintf(fz_context * ctx,fz_buffer * buffer,const char * fmt,va_list args)383 fz_append_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args)
384 {
385 fz_format_string(ctx, buffer, fz_append_emit, fmt, args);
386 }
387
388 void
fz_append_pdf_string(fz_context * ctx,fz_buffer * buffer,const char * text)389 fz_append_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text)
390 {
391 size_t len = 2;
392 const char *s = text;
393 char *d;
394 char c;
395
396 while ((c = *s++) != 0)
397 {
398 switch (c)
399 {
400 case '\n':
401 case '\r':
402 case '\t':
403 case '\b':
404 case '\f':
405 case '(':
406 case ')':
407 case '\\':
408 len++;
409 break;
410 }
411 len++;
412 }
413
414 while(buffer->cap - buffer->len < len)
415 fz_grow_buffer(ctx, buffer);
416
417 s = text;
418 d = (char *)buffer->data + buffer->len;
419 *d++ = '(';
420 while ((c = *s++) != 0)
421 {
422 switch (c)
423 {
424 case '\n':
425 *d++ = '\\';
426 *d++ = 'n';
427 break;
428 case '\r':
429 *d++ = '\\';
430 *d++ = 'r';
431 break;
432 case '\t':
433 *d++ = '\\';
434 *d++ = 't';
435 break;
436 case '\b':
437 *d++ = '\\';
438 *d++ = 'b';
439 break;
440 case '\f':
441 *d++ = '\\';
442 *d++ = 'f';
443 break;
444 case '(':
445 *d++ = '\\';
446 *d++ = '(';
447 break;
448 case ')':
449 *d++ = '\\';
450 *d++ = ')';
451 break;
452 case '\\':
453 *d++ = '\\';
454 *d++ = '\\';
455 break;
456 default:
457 *d++ = c;
458 }
459 }
460 *d = ')';
461 buffer->len += len;
462 }
463
464 void
fz_md5_buffer(fz_context * ctx,fz_buffer * buffer,unsigned char digest[16])465 fz_md5_buffer(fz_context *ctx, fz_buffer *buffer, unsigned char digest[16])
466 {
467 fz_md5 state;
468 fz_md5_init(&state);
469 if (buffer)
470 fz_md5_update(&state, buffer->data, buffer->len);
471 fz_md5_final(&state, digest);
472 }
473
474 #ifdef TEST_BUFFER_WRITE
475
476 #define TEST_LEN 1024
477
478 void
fz_test_buffer_write(fz_context * ctx)479 fz_test_buffer_write(fz_context *ctx)
480 {
481 fz_buffer *master = fz_new_buffer(ctx, TEST_LEN);
482 fz_buffer *copy = fz_new_buffer(ctx, TEST_LEN);
483 fz_stream *stm;
484 int i, j, k;
485
486 /* Make us a dummy buffer */
487 for (i = 0; i < TEST_LEN; i++)
488 {
489 master->data[i] = rand();
490 }
491 master->len = TEST_LEN;
492
493 /* Now copy that buffer several times, checking it for validity */
494 stm = fz_open_buffer(ctx, master);
495 for (i = 0; i < 256; i++)
496 {
497 memset(copy->data, i, TEST_LEN);
498 copy->len = 0;
499 j = TEST_LEN * 8;
500 do
501 {
502 k = (rand() & 31)+1;
503 if (k > j)
504 k = j;
505 fz_append_bits(ctx, copy, fz_read_bits(ctx, stm, k), k);
506 j -= k;
507 }
508 while (j);
509
510 if (memcmp(copy->data, master->data, TEST_LEN) != 0)
511 fprintf(stderr, "Copied buffer is different!\n");
512 fz_seek(stm, 0, 0);
513 }
514 fz_drop_stream(stm);
515 fz_drop_buffer(ctx, master);
516 fz_drop_buffer(ctx, copy);
517 }
518 #endif
519