1 | #include "fitz-imp.h" |
2 | |
3 | #include <string.h> |
4 | #include <stdarg.h> |
5 | |
6 | fz_buffer * |
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 = fz_malloc(ctx, size); |
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 | /* |
32 | Create a new buffer with existing data. |
33 | |
34 | data: Pointer to existing data. |
35 | size: Size of existing data. |
36 | |
37 | Takes ownership of data. Does not make a copy. Calls fz_free on the |
38 | data when the buffer is deallocated. Do not use 'data' after passing |
39 | to this function. |
40 | |
41 | Returns pointer to new buffer. Throws exception on allocation |
42 | failure. |
43 | */ |
44 | fz_buffer * |
45 | fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, size_t size) |
46 | { |
47 | fz_buffer *b = NULL; |
48 | |
49 | fz_try(ctx) |
50 | { |
51 | b = fz_malloc_struct(ctx, fz_buffer); |
52 | b->refs = 1; |
53 | b->data = data; |
54 | b->cap = size; |
55 | b->len = size; |
56 | b->unused_bits = 0; |
57 | } |
58 | fz_catch(ctx) |
59 | { |
60 | fz_free(ctx, data); |
61 | fz_rethrow(ctx); |
62 | } |
63 | |
64 | return b; |
65 | } |
66 | |
67 | /* |
68 | Like fz_new_buffer, but does not take ownership. |
69 | */ |
70 | fz_buffer * |
71 | fz_new_buffer_from_shared_data(fz_context *ctx, const unsigned char *data, size_t size) |
72 | { |
73 | fz_buffer *b; |
74 | |
75 | b = fz_malloc_struct(ctx, fz_buffer); |
76 | b->refs = 1; |
77 | b->data = (unsigned char *)data; /* cast away const */ |
78 | b->cap = size; |
79 | b->len = size; |
80 | b->unused_bits = 0; |
81 | b->shared = 1; |
82 | |
83 | return b; |
84 | } |
85 | |
86 | /* |
87 | Create a new buffer containing a copy of the passed data. |
88 | */ |
89 | fz_buffer * |
90 | fz_new_buffer_from_copied_data(fz_context *ctx, const unsigned char *data, size_t size) |
91 | { |
92 | fz_buffer *b = fz_new_buffer(ctx, size); |
93 | b->len = size; |
94 | memcpy(b->data, data, size); |
95 | return b; |
96 | } |
97 | |
98 | /* |
99 | Create a new buffer with data decoded from a base64 input string. |
100 | */ |
101 | fz_buffer * |
102 | fz_new_buffer_from_base64(fz_context *ctx, const char *data, size_t size) |
103 | { |
104 | fz_buffer *buf = fz_new_buffer(ctx, size); |
105 | const char *end = data + (size > 0 ? size : strlen(data)); |
106 | const char *s = data; |
107 | fz_try(ctx) |
108 | { |
109 | while (s < end) |
110 | { |
111 | int c = *s++; |
112 | if (c >= 'A' && c <= 'Z') |
113 | fz_append_bits(ctx, buf, c - 'A', 6); |
114 | else if (c >= 'a' && c <= 'z') |
115 | fz_append_bits(ctx, buf, c - 'a' + 26, 6); |
116 | else if (c >= '0' && c <= '9') |
117 | fz_append_bits(ctx, buf, c - '0' + 52, 6); |
118 | else if (c == '+') |
119 | fz_append_bits(ctx, buf, 62, 6); |
120 | else if (c == '/') |
121 | fz_append_bits(ctx, buf, 63, 6); |
122 | } |
123 | } |
124 | fz_catch(ctx) |
125 | { |
126 | fz_drop_buffer(ctx, buf); |
127 | fz_rethrow(ctx); |
128 | } |
129 | return buf; |
130 | } |
131 | |
132 | fz_buffer * |
133 | fz_keep_buffer(fz_context *ctx, fz_buffer *buf) |
134 | { |
135 | return fz_keep_imp(ctx, buf, &buf->refs); |
136 | } |
137 | |
138 | void |
139 | fz_drop_buffer(fz_context *ctx, fz_buffer *buf) |
140 | { |
141 | if (fz_drop_imp(ctx, buf, &buf->refs)) |
142 | { |
143 | if (!buf->shared) |
144 | fz_free(ctx, buf->data); |
145 | fz_free(ctx, buf); |
146 | } |
147 | } |
148 | |
149 | /* |
150 | Ensure that a buffer has a given capacity, |
151 | truncating data if required. |
152 | |
153 | capacity: The desired capacity for the buffer. If the current size |
154 | of the buffer contents is smaller than capacity, it is truncated. |
155 | */ |
156 | void |
157 | fz_resize_buffer(fz_context *ctx, fz_buffer *buf, size_t size) |
158 | { |
159 | if (buf->shared) |
160 | fz_throw(ctx, FZ_ERROR_GENERIC, "cannot resize a buffer with shared storage" ); |
161 | buf->data = fz_realloc(ctx, buf->data, size); |
162 | buf->cap = size; |
163 | if (buf->len > buf->cap) |
164 | buf->len = buf->cap; |
165 | } |
166 | |
167 | /* |
168 | Make some space within a buffer (i.e. ensure that |
169 | capacity > size). |
170 | */ |
171 | void |
172 | fz_grow_buffer(fz_context *ctx, fz_buffer *buf) |
173 | { |
174 | size_t newsize = (buf->cap * 3) / 2; |
175 | if (newsize == 0) |
176 | newsize = 256; |
177 | fz_resize_buffer(ctx, buf, newsize); |
178 | } |
179 | |
180 | static void |
181 | fz_ensure_buffer(fz_context *ctx, fz_buffer *buf, size_t min) |
182 | { |
183 | size_t newsize = buf->cap; |
184 | if (newsize < 16) |
185 | newsize = 16; |
186 | while (newsize < min) |
187 | { |
188 | newsize = (newsize * 3) / 2; |
189 | } |
190 | fz_resize_buffer(ctx, buf, newsize); |
191 | } |
192 | |
193 | /* |
194 | Trim wasted capacity from a buffer by resizing internal memory. |
195 | */ |
196 | void |
197 | fz_trim_buffer(fz_context *ctx, fz_buffer *buf) |
198 | { |
199 | if (buf->cap > buf->len+1) |
200 | fz_resize_buffer(ctx, buf, buf->len); |
201 | } |
202 | |
203 | void |
204 | fz_clear_buffer(fz_context *ctx, fz_buffer *buf) |
205 | { |
206 | buf->len = 0; |
207 | } |
208 | |
209 | /* |
210 | Zero-terminate buffer in order to use as a C string. |
211 | |
212 | This byte is invisible and does not affect the length of the buffer as returned by fz_buffer_storage. |
213 | The zero byte is written *after* the data, and subsequent writes will overwrite the terminating byte. |
214 | */ |
215 | void |
216 | fz_terminate_buffer(fz_context *ctx, fz_buffer *buf) |
217 | { |
218 | /* ensure that there is a zero-byte after the end of the data */ |
219 | if (buf->len + 1 > buf->cap) |
220 | fz_grow_buffer(ctx, buf); |
221 | buf->data[buf->len] = 0; |
222 | } |
223 | |
224 | /* |
225 | Retrieve internal memory of buffer. |
226 | |
227 | datap: Output parameter that will be pointed to the data. |
228 | |
229 | Returns the current size of the data in bytes. |
230 | */ |
231 | size_t |
232 | fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap) |
233 | { |
234 | if (datap) |
235 | *datap = (buf ? buf->data : NULL); |
236 | return (buf ? buf->len : 0); |
237 | } |
238 | |
239 | /* |
240 | Ensure that a buffer's data ends in a |
241 | 0 byte, and return a pointer to it. |
242 | */ |
243 | const char * |
244 | fz_string_from_buffer(fz_context *ctx, fz_buffer *buf) |
245 | { |
246 | if (!buf) |
247 | return "" ; |
248 | fz_terminate_buffer(ctx, buf); |
249 | return (const char *)buf->data; |
250 | } |
251 | |
252 | /* |
253 | Take ownership of buffer contents. |
254 | Performs the same task as fz_buffer_storage, but ownership of |
255 | the data buffer returns with this call. The buffer is left |
256 | empty. |
257 | |
258 | Note: Bad things may happen if this is called on a buffer with |
259 | multiple references that is being used from multiple threads. |
260 | |
261 | data: Pointer to place to retrieve data pointer. |
262 | |
263 | Returns length of stream. |
264 | */ |
265 | size_t |
266 | (fz_context *ctx, fz_buffer *buf, unsigned char **datap) |
267 | { |
268 | size_t len = buf ? buf->len : 0; |
269 | *datap = (buf ? buf->data : NULL); |
270 | |
271 | if (buf) |
272 | { |
273 | buf->data = NULL; |
274 | buf->len = 0; |
275 | } |
276 | return len; |
277 | } |
278 | |
279 | void |
280 | fz_append_buffer(fz_context *ctx, fz_buffer *buf, fz_buffer *) |
281 | { |
282 | if (buf->cap - buf->len < extra->len) |
283 | { |
284 | buf->data = fz_realloc(ctx, buf->data, buf->len + extra->len); |
285 | buf->cap = buf->len + extra->len; |
286 | } |
287 | |
288 | memcpy(buf->data + buf->len, extra->data, extra->len); |
289 | buf->len += extra->len; |
290 | } |
291 | |
292 | /* |
293 | fz_append_*: Append data to a buffer. |
294 | fz_append_printf: Format and append data to buffer using printf-like formatting (see fz_vsnprintf). |
295 | fz_append_pdf_string: Append a string with PDF syntax quotes and escapes. |
296 | The buffer will automatically grow as required. |
297 | */ |
298 | void |
299 | fz_append_data(fz_context *ctx, fz_buffer *buf, const void *data, size_t len) |
300 | { |
301 | if (buf->len + len > buf->cap) |
302 | fz_ensure_buffer(ctx, buf, buf->len + len); |
303 | memcpy(buf->data + buf->len, data, len); |
304 | buf->len += len; |
305 | buf->unused_bits = 0; |
306 | } |
307 | |
308 | void |
309 | fz_append_string(fz_context *ctx, fz_buffer *buf, const char *data) |
310 | { |
311 | size_t len = strlen(data); |
312 | if (buf->len + len > buf->cap) |
313 | fz_ensure_buffer(ctx, buf, buf->len + len); |
314 | memcpy(buf->data + buf->len, data, len); |
315 | buf->len += len; |
316 | buf->unused_bits = 0; |
317 | } |
318 | |
319 | void |
320 | fz_append_byte(fz_context *ctx, fz_buffer *buf, int val) |
321 | { |
322 | if (buf->len + 1 > buf->cap) |
323 | fz_grow_buffer(ctx, buf); |
324 | buf->data[buf->len++] = val; |
325 | buf->unused_bits = 0; |
326 | } |
327 | |
328 | void |
329 | fz_append_rune(fz_context *ctx, fz_buffer *buf, int c) |
330 | { |
331 | char data[10]; |
332 | int len = fz_runetochar(data, c); |
333 | if (buf->len + len > buf->cap) |
334 | fz_ensure_buffer(ctx, buf, buf->len + len); |
335 | memcpy(buf->data + buf->len, data, len); |
336 | buf->len += len; |
337 | buf->unused_bits = 0; |
338 | } |
339 | |
340 | void |
341 | fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x) |
342 | { |
343 | fz_append_byte(ctx, buf, (x >> 24) & 0xFF); |
344 | fz_append_byte(ctx, buf, (x >> 16) & 0xFF); |
345 | fz_append_byte(ctx, buf, (x >> 8) & 0xFF); |
346 | fz_append_byte(ctx, buf, (x) & 0xFF); |
347 | } |
348 | |
349 | void |
350 | fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x) |
351 | { |
352 | fz_append_byte(ctx, buf, (x >> 8) & 0xFF); |
353 | fz_append_byte(ctx, buf, (x) & 0xFF); |
354 | } |
355 | |
356 | void |
357 | fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x) |
358 | { |
359 | fz_append_byte(ctx, buf, (x)&0xFF); |
360 | fz_append_byte(ctx, buf, (x>>8)&0xFF); |
361 | fz_append_byte(ctx, buf, (x>>16)&0xFF); |
362 | fz_append_byte(ctx, buf, (x>>24)&0xFF); |
363 | } |
364 | |
365 | void |
366 | fz_append_int16_le(fz_context *ctx, fz_buffer *buf, int x) |
367 | { |
368 | fz_append_byte(ctx, buf, (x)&0xFF); |
369 | fz_append_byte(ctx, buf, (x>>8)&0xFF); |
370 | } |
371 | |
372 | void |
373 | fz_append_bits(fz_context *ctx, fz_buffer *buf, int val, int bits) |
374 | { |
375 | int shift; |
376 | |
377 | /* Throughout this code, the invariant is that we need to write the |
378 | * bottom 'bits' bits of 'val' into the stream. On entry we assume |
379 | * that val & ((1<<bits)-1) == val, but we do not rely on this after |
380 | * having written the first partial byte. */ |
381 | |
382 | if (bits == 0) |
383 | return; |
384 | |
385 | /* buf->len always covers all the bits in the buffer, including |
386 | * any unused ones in the last byte, which will always be 0. |
387 | * buf->unused_bits = the number of unused bits in the last byte. |
388 | */ |
389 | |
390 | /* Find the amount we need to shift val up by so that it will be in |
391 | * the correct position to be inserted into any existing data byte. */ |
392 | shift = (buf->unused_bits - bits); |
393 | |
394 | /* Extend the buffer as required before we start; that way we never |
395 | * fail part way during writing. If shift < 0, then we'll need -shift |
396 | * more bits. */ |
397 | if (shift < 0) |
398 | { |
399 | int = (7-shift)>>3; /* Round up to bytes */ |
400 | fz_ensure_buffer(ctx, buf, buf->len + extra); |
401 | } |
402 | |
403 | /* Write any bits that will fit into the existing byte */ |
404 | if (buf->unused_bits) |
405 | { |
406 | buf->data[buf->len-1] |= (shift >= 0 ? (((unsigned int)val)<<shift) : (((unsigned int)val)>>-shift)); |
407 | if (shift >= 0) |
408 | { |
409 | /* If we were shifting up, we're done. */ |
410 | buf->unused_bits -= bits; |
411 | return; |
412 | } |
413 | /* The number of bits left to write is the number that didn't |
414 | * fit in this first byte. */ |
415 | bits = -shift; |
416 | } |
417 | |
418 | /* Write any whole bytes */ |
419 | while (bits >= 8) |
420 | { |
421 | bits -= 8; |
422 | buf->data[buf->len++] = val>>bits; |
423 | } |
424 | |
425 | /* Write trailing bits (with 0's in unused bits) */ |
426 | if (bits > 0) |
427 | { |
428 | bits = 8-bits; |
429 | buf->data[buf->len++] = val<<bits; |
430 | } |
431 | buf->unused_bits = bits; |
432 | } |
433 | |
434 | void |
435 | fz_append_bits_pad(fz_context *ctx, fz_buffer *buf) |
436 | { |
437 | buf->unused_bits = 0; |
438 | } |
439 | |
440 | static void fz_append_emit(fz_context *ctx, void *buffer, int c) |
441 | { |
442 | fz_append_byte(ctx, buffer, c); |
443 | } |
444 | |
445 | void |
446 | fz_append_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...) |
447 | { |
448 | va_list args; |
449 | va_start(args, fmt); |
450 | fz_format_string(ctx, buffer, fz_append_emit, fmt, args); |
451 | va_end(args); |
452 | } |
453 | |
454 | void |
455 | fz_append_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args) |
456 | { |
457 | fz_format_string(ctx, buffer, fz_append_emit, fmt, args); |
458 | } |
459 | |
460 | void |
461 | fz_append_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text) |
462 | { |
463 | size_t len = 2; |
464 | const char *s = text; |
465 | char *d; |
466 | char c; |
467 | |
468 | while ((c = *s++) != 0) |
469 | { |
470 | switch (c) |
471 | { |
472 | case '\n': |
473 | case '\r': |
474 | case '\t': |
475 | case '\b': |
476 | case '\f': |
477 | case '(': |
478 | case ')': |
479 | case '\\': |
480 | len++; |
481 | break; |
482 | } |
483 | len++; |
484 | } |
485 | |
486 | while(buffer->cap - buffer->len < len) |
487 | fz_grow_buffer(ctx, buffer); |
488 | |
489 | s = text; |
490 | d = (char *)buffer->data + buffer->len; |
491 | *d++ = '('; |
492 | while ((c = *s++) != 0) |
493 | { |
494 | switch (c) |
495 | { |
496 | case '\n': |
497 | *d++ = '\\'; |
498 | *d++ = 'n'; |
499 | break; |
500 | case '\r': |
501 | *d++ = '\\'; |
502 | *d++ = 'r'; |
503 | break; |
504 | case '\t': |
505 | *d++ = '\\'; |
506 | *d++ = 't'; |
507 | break; |
508 | case '\b': |
509 | *d++ = '\\'; |
510 | *d++ = 'b'; |
511 | break; |
512 | case '\f': |
513 | *d++ = '\\'; |
514 | *d++ = 'f'; |
515 | break; |
516 | case '(': |
517 | *d++ = '\\'; |
518 | *d++ = '('; |
519 | break; |
520 | case ')': |
521 | *d++ = '\\'; |
522 | *d++ = ')'; |
523 | break; |
524 | case '\\': |
525 | *d++ = '\\'; |
526 | *d++ = '\\'; |
527 | break; |
528 | default: |
529 | *d++ = c; |
530 | } |
531 | } |
532 | *d = ')'; |
533 | buffer->len += len; |
534 | } |
535 | |
536 | void |
537 | fz_md5_buffer(fz_context *ctx, fz_buffer *buffer, unsigned char digest[16]) |
538 | { |
539 | fz_md5 state; |
540 | fz_md5_init(&state); |
541 | if (buffer) |
542 | fz_md5_update(&state, buffer->data, buffer->len); |
543 | fz_md5_final(&state, digest); |
544 | } |
545 | |
546 | #ifdef TEST_BUFFER_WRITE |
547 | |
548 | #define TEST_LEN 1024 |
549 | |
550 | void |
551 | fz_test_buffer_write(fz_context *ctx) |
552 | { |
553 | fz_buffer *master = fz_new_buffer(ctx, TEST_LEN); |
554 | fz_buffer *copy = fz_new_buffer(ctx, TEST_LEN); |
555 | fz_stream *stm; |
556 | int i, j, k; |
557 | |
558 | /* Make us a dummy buffer */ |
559 | for (i = 0; i < TEST_LEN; i++) |
560 | { |
561 | master->data[i] = rand(); |
562 | } |
563 | master->len = TEST_LEN; |
564 | |
565 | /* Now copy that buffer several times, checking it for validity */ |
566 | stm = fz_open_buffer(ctx, master); |
567 | for (i = 0; i < 256; i++) |
568 | { |
569 | memset(copy->data, i, TEST_LEN); |
570 | copy->len = 0; |
571 | j = TEST_LEN * 8; |
572 | do |
573 | { |
574 | k = (rand() & 31)+1; |
575 | if (k > j) |
576 | k = j; |
577 | fz_append_bits(ctx, copy, fz_read_bits(ctx, stm, k), k); |
578 | j -= k; |
579 | } |
580 | while (j); |
581 | |
582 | if (memcmp(copy->data, master->data, TEST_LEN) != 0) |
583 | fprintf(stderr, "Copied buffer is different!\n" ); |
584 | fz_seek(stm, 0, 0); |
585 | } |
586 | fz_drop_stream(stm); |
587 | fz_drop_buffer(ctx, master); |
588 | fz_drop_buffer(ctx, copy); |
589 | } |
590 | #endif |
591 | |