Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "mupdf/fitz.h"
2
3
fz_buffer *
4
fz_new_buffer(fz_context *ctx, int size)
5
{
6
fz_buffer *b;
7
8
size = size > 1 ? size : 16;
9
10
b = fz_malloc_struct(ctx, fz_buffer);
11
b->refs = 1;
12
fz_try(ctx)
13
{
14
b->data = fz_malloc(ctx, size);
15
}
16
fz_catch(ctx)
17
{
18
fz_free(ctx, b);
19
fz_rethrow(ctx);
20
}
21
b->cap = size;
22
b->len = 0;
23
b->unused_bits = 0;
24
25
return b;
26
}
27
28
fz_buffer *
29
fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, int size)
30
{
31
fz_buffer *b;
32
33
b = fz_malloc_struct(ctx, fz_buffer);
34
b->refs = 1;
35
b->data = data;
36
b->cap = size;
37
b->len = size;
38
b->unused_bits = 0;
39
40
return b;
41
}
42
43
fz_buffer *
44
fz_keep_buffer(fz_context *ctx, fz_buffer *buf)
45
{
46
if (buf)
47
buf->refs ++;
48
return buf;
49
}
50
51
void
52
fz_drop_buffer(fz_context *ctx, fz_buffer *buf)
53
{
54
if (!buf)
55
return;
56
if (--buf->refs == 0)
57
{
58
fz_free(ctx, buf->data);
59
fz_free(ctx, buf);
60
}
61
}
62
63
void
64
fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size)
65
{
66
buf->data = fz_resize_array(ctx, buf->data, size, 1);
67
buf->cap = size;
68
if (buf->len > buf->cap)
69
buf->len = buf->cap;
70
}
71
72
void
73
fz_grow_buffer(fz_context *ctx, fz_buffer *buf)
74
{
75
int newsize = (buf->cap * 3) / 2;
76
if (newsize == 0)
77
newsize = 256;
78
fz_resize_buffer(ctx, buf, newsize);
79
}
80
81
static void
82
fz_ensure_buffer(fz_context *ctx, fz_buffer *buf, int min)
83
{
84
int newsize = buf->cap;
85
if (newsize < 16)
86
newsize = 16;
87
while (newsize < min)
88
{
89
newsize = (newsize * 3) / 2;
90
}
91
fz_resize_buffer(ctx, buf, newsize);
92
}
93
94
void
95
fz_trim_buffer(fz_context *ctx, fz_buffer *buf)
96
{
97
if (buf->cap > buf->len+1)
98
fz_resize_buffer(ctx, buf, buf->len);
99
}
100
101
int
102
fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
103
{
104
if (datap)
105
*datap = (buf ? buf->data : NULL);
106
return (buf ? buf->len : 0);
107
}
108
109
void
110
fz_buffer_cat(fz_context *ctx, fz_buffer *buf, fz_buffer *extra)
111
{
112
if (buf->cap - buf->len < extra->len)
113
{
114
buf->data = fz_resize_array(ctx, buf->data, buf->len + extra->len, 1);
115
buf->cap = buf->len + extra->len;
116
}
117
118
memcpy(buf->data + buf->len, extra->data, extra->len);
119
buf->len += extra->len;
120
}
121
122
void fz_write_buffer(fz_context *ctx, fz_buffer *buf, const void *data, int len)
123
{
124
if (buf->len + len > buf->cap)
125
fz_ensure_buffer(ctx, buf, buf->len + len);
126
memcpy(buf->data + buf->len, data, len);
127
buf->len += len;
128
buf->unused_bits = 0;
129
}
130
131
void fz_write_buffer_byte(fz_context *ctx, fz_buffer *buf, int val)
132
{
133
if (buf->len + 1 > buf->cap)
134
fz_grow_buffer(ctx, buf);
135
buf->data[buf->len++] = val;
136
buf->unused_bits = 0;
137
}
138
139
void fz_write_buffer_rune(fz_context *ctx, fz_buffer *buf, int c)
140
{
141
char data[10];
142
int len = fz_runetochar(data, c);
143
if (buf->len + len > buf->cap)
144
fz_ensure_buffer(ctx, buf, buf->len + len);
145
memcpy(buf->data + buf->len, data, len);
146
buf->len += len;
147
buf->unused_bits = 0;
148
}
149
150
void fz_write_buffer_bits(fz_context *ctx, fz_buffer *buf, int val, int bits)
151
{
152
int shift;
153
154
/* Throughout this code, the invariant is that we need to write the
155
* bottom 'bits' bits of 'val' into the stream. On entry we assume
156
* that val & ((1<<bits)-1) == val, but we do not rely on this after
157
* having written the first partial byte. */
158
159
if (bits == 0)
160
return;
161
162
/* buf->len always covers all the bits in the buffer, including
163
* any unused ones in the last byte, which will always be 0.
164
* buf->unused_bits = the number of unused bits in the last byte.
165
*/
166
167
/* Find the amount we need to shift val up by so that it will be in
168
* the correct position to be inserted into any existing data byte. */
169
shift = (buf->unused_bits - bits);
170
171
/* Extend the buffer as required before we start; that way we never
172
* fail part way during writing. If shift < 0, then we'll need -shift
173
* more bits. */
174
if (shift < 0)
175
{
176
int extra = (7-shift)>>3; /* Round up to bytes */
177
fz_ensure_buffer(ctx, buf, buf->len + extra);
178
}
179
180
/* Write any bits that will fit into the existing byte */
181
if (buf->unused_bits)
182
{
183
buf->data[buf->len-1] |= (shift >= 0 ? (((unsigned int)val)<<shift) : (((unsigned int)val)>>-shift));
184
if (shift >= 0)
185
{
186
/* If we were shifting up, we're done. */
187
buf->unused_bits -= bits;
188
return;
189
}
190
/* The number of bits left to write is the number that didn't
191
* fit in this first byte. */
192
bits = -shift;
193
}
194
195
/* Write any whole bytes */
196
while (bits >= 8)
197
{
198
bits -= 8;
199
buf->data[buf->len++] = val>>bits;
200
}
201
202
/* Write trailing bits (with 0's in unused bits) */
203
if (bits > 0)
204
{
205
bits = 8-bits;
206
buf->data[buf->len++] = val<<bits;
207
}
208
buf->unused_bits = bits;
209
}
210
211
void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf)
212
{
213
buf->unused_bits = 0;
214
}
215
216
int
217
fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...)
218
{
219
int ret;
220
va_list args;
221
va_start(args, fmt);
222
ret = fz_buffer_vprintf(ctx, buffer, fmt, args);
223
va_end(args);
224
return ret;
225
}
226
227
int
228
fz_buffer_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list old_args)
229
{
230
int slack;
231
int len;
232
va_list args;
233
234
slack = buffer->cap - buffer->len;
235
va_copy(args, old_args);
236
len = fz_vsnprintf((char *)buffer->data + buffer->len, slack, fmt, args);
237
va_copy_end(args);
238
239
/* len = number of chars written, not including the terminating
240
* NULL, so len+1 > slack means "truncated". */
241
if (len+1 > slack)
242
{
243
/* Grow the buffer and retry */
244
fz_ensure_buffer(ctx, buffer, buffer->len + len);
245
slack = buffer->cap - buffer->len;
246
247
va_copy(args, old_args);
248
len = fz_vsnprintf((char *)buffer->data + buffer->len, slack, fmt, args);
249
va_copy_end(args);
250
}
251
252
buffer->len += len;
253
254
return len;
255
}
256
257
void
258
fz_buffer_cat_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text)
259
{
260
int len = 2;
261
const char *s = text;
262
char *d;
263
char c;
264
265
while ((c = *s++) != 0)
266
{
267
switch (c)
268
{
269
case '\n':
270
case '\r':
271
case '\t':
272
case '\b':
273
case '\f':
274
case '(':
275
case ')':
276
case '\\':
277
len++;
278
break;
279
}
280
len++;
281
}
282
283
while(buffer->cap - buffer->len < len)
284
fz_grow_buffer(ctx, buffer);
285
286
s = text;
287
d = (char *)buffer->data + buffer->len;
288
*d++ = '(';
289
while ((c = *s++) != 0)
290
{
291
switch (c)
292
{
293
case '\n':
294
*d++ = '\\';
295
*d++ = 'n';
296
break;
297
case '\r':
298
*d++ = '\\';
299
*d++ = 'r';
300
break;
301
case '\t':
302
*d++ = '\\';
303
*d++ = 't';
304
break;
305
case '\b':
306
*d++ = '\\';
307
*d++ = 'b';
308
break;
309
case '\f':
310
*d++ = '\\';
311
*d++ = 'f';
312
break;
313
case '(':
314
*d++ = '\\';
315
*d++ = '(';
316
break;
317
case ')':
318
*d++ = '\\';
319
*d++ = ')';
320
break;
321
case '\\':
322
*d++ = '\\';
323
*d++ = '\\';
324
break;
325
default:
326
*d++ = c;
327
}
328
}
329
*d = ')';
330
buffer->len += len;
331
}
332
333
#ifdef TEST_BUFFER_WRITE
334
335
#define TEST_LEN 1024
336
337
void
338
fz_test_buffer_write(fz_context *ctx)
339
{
340
fz_buffer *master = fz_new_buffer(ctx, TEST_LEN);
341
fz_buffer *copy = fz_new_buffer(ctx, TEST_LEN);
342
fz_stream *stm;
343
int i, j, k;
344
345
/* Make us a dummy buffer */
346
for (i = 0; i < TEST_LEN; i++)
347
{
348
master->data[i] = rand();
349
}
350
master->len = TEST_LEN;
351
352
/* Now copy that buffer several times, checking it for validity */
353
stm = fz_open_buffer(ctx, master);
354
for (i = 0; i < 256; i++)
355
{
356
memset(copy->data, i, TEST_LEN);
357
copy->len = 0;
358
j = TEST_LEN * 8;
359
do
360
{
361
k = (rand() & 31)+1;
362
if (k > j)
363
k = j;
364
fz_write_buffer_bits(ctx, copy, fz_read_bits(ctx, stm, k), k);
365
j -= k;
366
}
367
while (j);
368
369
if (memcmp(copy->data, master->data, TEST_LEN) != 0)
370
fprintf(stderr, "Copied buffer is different!\n");
371
fz_seek(stm, 0, 0);
372
}
373
fz_drop_stream(stm);
374
fz_drop_buffer(ctx, master);
375
fz_drop_buffer(ctx, copy);
376
}
377
#endif
378
379