comparison src/dmzlib.c @ 958:985225a93aeb

Add error code parameter to dmError() and dmErrorVA().
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 27 Feb 2015 03:58:25 +0200
parents 6b2f41844580
children 1832ac20edb2
comparison
equal deleted inserted replaced
957:b66653c9acb3 958:985225a93aeb
6 */ 6 */
7 #include "dmzlib.h" 7 #include "dmzlib.h"
8 8
9 9
10 #define DM_ZLIB_TMPBUF_SIZE (16 * 1024) 10 #define DM_ZLIB_TMPBUF_SIZE (16 * 1024)
11 #define STBI_ASSERT(x) // dummy 11 #define DMSTBI_ASSERT(x) // dummy
12
13
14 static int stbi__err(const char *s, const char *p)
15 {
16 (void) s;
17 (void) p;
18 return 0;
19 }
20 12
21 13
22 // @TODO: should statically initialize these for optimal thread safety 14 // @TODO: should statically initialize these for optimal thread safety
23 static Uint8 stbi__zdefault_length[288], stbi__zdefault_distance[32]; 15 static Uint8 stbi__zdefault_length[288], stbi__zdefault_distance[32];
24 16
55 } 47 }
56 48
57 49
58 static inline int stbi__bit_reverse_n(int v, int bits) 50 static inline int stbi__bit_reverse_n(int v, int bits)
59 { 51 {
60 STBI_ASSERT(bits <= 16); 52 DMSTBI_ASSERT(bits <= 16);
61 // to bit reverse n bits, reverse 16 and shift 53 // to bit reverse n bits, reverse 16 and shift
62 // e.g. 11 bits, bit reverse and shift away 5 54 // e.g. 11 bits, bit reverse and shift away 5
63 return stbi__bit_reverse_16(v) >> (16 - bits); 55 return stbi__bit_reverse_16(v) >> (16 - bits);
64 } 56 }
65 57
66 58
67 static int stbi__zbuild_huffman(DMZHuffmanContext * z, const Uint8 * sizelist, const int num) 59 static int stbi__zbuild_huffman(DMZHuffmanContext * ctx, const Uint8 * sizelist, const int num)
68 { 60 {
69 int i, k = 0; 61 int i, k = 0;
70 int code, next_code[16], sizes[17]; 62 int code, next_code[16], sizes[17];
71 63
72 // DEFLATE spec for generating codes 64 // DEFLATE spec for generating codes
73 memset(sizes, 0, sizeof(sizes)); 65 memset(sizes, 0, sizeof(sizes));
74 memset(z->fast, 0, sizeof(z->fast)); 66 memset(ctx->fast, 0, sizeof(ctx->fast));
75 67
76 for (i = 0; i < num; i++) 68 for (i = 0; i < num; i++)
77 sizes[sizelist[i]]++; 69 sizes[sizelist[i]]++;
78 70
79 sizes[0] = 0; 71 sizes[0] = 0;
80 for (i = 1; i < 16; i++) 72 for (i = 1; i < 16; i++)
81 { 73 {
82 if (sizes[i] > (1 << i)) 74 if (sizes[i] > (1 << i))
83 return stbi__err("fail!", "omg!"); 75 {
76 return dmError(DMERR_INTERNAL,
77 "Sizes assert failed while building Huffman codes.\n");
78 }
84 } 79 }
85 80
86 code = 0; 81 code = 0;
87 for (i = 1; i < 16; i++) 82 for (i = 1; i < 16; i++)
88 { 83 {
89 next_code[i] = code; 84 next_code[i] = code;
90 z->firstCode[i] = (Uint16) code; 85 ctx->firstCode[i] = (Uint16) code;
91 z->firstSymbol[i] = (Uint16) k; 86 ctx->firstSymbol[i] = (Uint16) k;
92 code = (code + sizes[i]); 87 code = (code + sizes[i]);
93 88
94 if (sizes[i] && code - 1 >= (1 << i)) 89 if (sizes[i] && code - 1 >= (1 << i))
95 return stbi__err("bad codelengths", "Corrupt JPEG"); 90 {
96 91 return dmError(DMERR_INVALID_DATA,
97 z->maxCode[i] = code << (16 - i); // preshift for inner loop 92 "Bad Huffman code lengths.\n");
93 }
94
95 ctx->maxCode[i] = code << (16 - i); // preshift for inner loop
98 code <<= 1; 96 code <<= 1;
99 k += sizes[i]; 97 k += sizes[i];
100 } 98 }
101 99
102 z->maxCode[16] = 0x10000; // sentinel 100 ctx->maxCode[16] = 0x10000; // sentinel
103 for (i = 0; i < num; i++) 101 for (i = 0; i < num; i++)
104 { 102 {
105 int s = sizelist[i]; 103 int s = sizelist[i];
106 if (s) 104 if (s)
107 { 105 {
108 int c = next_code[s] - z->firstCode[s] + z->firstSymbol[s]; 106 int c = next_code[s] - ctx->firstCode[s] + ctx->firstSymbol[s];
109 Uint16 fastv = (Uint16) ((s << 9) | i); 107 Uint16 fastv = (Uint16) ((s << 9) | i);
110 z->size[c] = (Uint8) s; 108 ctx->size[c] = (Uint8) s;
111 z->value[c] = (Uint16) i; 109 ctx->value[c] = (Uint16) i;
112 if (s <= STBI__ZFAST_BITS) 110 if (s <= STBI__ZFAST_BITS)
113 { 111 {
114 int k = stbi__bit_reverse_n(next_code[s], s); 112 int k = stbi__bit_reverse_n(next_code[s], s);
115 while (k < STBI__ZFAST_SIZE) 113 while (k < STBI__ZFAST_SIZE)
116 { 114 {
117 z->fast[k] = fastv; 115 ctx->fast[k] = fastv;
118 k += (1 << s); 116 k += (1 << s);
119 } 117 }
120 } 118 }
121 ++next_code[s]; 119 ++next_code[s];
122 } 120 }
123 } 121 }
124 return 1; 122 return 1;
125 } 123 }
126 124
127 125
128 static inline Uint8 stbi__zget8(DMZLibContext * z) 126 static inline Uint8 stbi__zget8(DMZLibContext * ctx)
129 { 127 {
130 if (z->zbuffer >= z->zbuffer_end) 128 if (ctx->zbuffer >= ctx->zbufferEnd)
131 return 0; 129 return 0;
132 130
133 return *z->zbuffer++; 131 return *ctx->zbuffer++;
134 } 132 }
135 133
136 134
137 static void stbi__fill_bits(DMZLibContext * z) 135 static void stbi__fill_bits(DMZLibContext * ctx)
138 { 136 {
139 do 137 do
140 { 138 {
141 STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); 139 DMSTBI_ASSERT(ctx->codeBuffer < (1U << ctx->numBits));
142 z->code_buffer |= stbi__zget8(z) << z->num_bits; 140 ctx->codeBuffer |= stbi__zget8(ctx) << ctx->numBits;
143 z->num_bits += 8; 141 ctx->numBits += 8;
144 } 142 }
145 while (z->num_bits <= 24); 143 while (ctx->numBits <= 24);
146 } 144 }
147 145
148 146
149 static inline unsigned int stbi__zreceive(DMZLibContext * z, int n) 147 static inline unsigned int stbi__zreceive(DMZLibContext * ctx, int n)
150 { 148 {
151 unsigned int k; 149 unsigned int val;
152 if (z->num_bits < n) 150
153 stbi__fill_bits(z); 151 if (ctx->numBits < n)
154 k = z->code_buffer & ((1 << n) - 1); 152 stbi__fill_bits(ctx);
155 z->code_buffer >>= n; 153
156 z->num_bits -= n; 154 val = ctx->codeBuffer & ((1 << n) - 1);
157 return k; 155 ctx->codeBuffer >>= n;
158 } 156 ctx->numBits -= n;
159 157
160 158 return val;
161 static int stbi__zhuffman_decode_slowpath(DMZLibContext * a, DMZHuffmanContext * z) 159 }
160
161
162 static int stbi__zhuffman_decode_slowpath(DMZLibContext * ctx, DMZHuffmanContext * huff, int *val)
162 { 163 {
163 int b, s, k; 164 int b, s, k;
164 165
165 // not resolved by fast table, so compute it the slow way 166 // not resolved by fast table, so compute it the slow way
166 // use jpeg approach, which requires MSbits at top 167 // use jpeg approach, which requires MSbits at top
167 k = stbi__bit_reverse_16(a->code_buffer); 168 k = stbi__bit_reverse_16(ctx->codeBuffer);
168 for (s = STBI__ZFAST_BITS + 1; ; s++) 169 for (s = STBI__ZFAST_BITS + 1; ; s++)
169 { 170 {
170 if (k < z->maxCode[s]) break; 171 if (k < huff->maxCode[s])
172 break;
171 } 173 }
172 174
173 if (s == 16) 175 if (s == 16)
174 return -1; // invalid code! 176 {
177 return dmError(DMERR_DATA_ERROR,
178 "Bad Huffman code.\n");
179 }
175 180
176 // code size is s, so: 181 // code size is s, so:
177 b = (k >> (16 - s)) - z->firstCode[s] + z->firstSymbol[s]; 182 b = (k >> (16 - s)) - huff->firstCode[s] + huff->firstSymbol[s];
178 STBI_ASSERT(z->size[b] == s); 183 DMSTBI_ASSERT(huff->size[b] == s);
179 a->code_buffer >>= s; 184
180 a->num_bits -= s; 185 ctx->codeBuffer >>= s;
181 return z->value[b]; 186 ctx->numBits -= s;
182 } 187 *val = huff->value[b];
183 188
184 189 return DMERR_OK;
185 static inline int stbi__zhuffman_decode(DMZLibContext * a, DMZHuffmanContext * z) 190 }
191
192
193 static inline int stbi__zhuffman_decode(DMZLibContext * ctx, DMZHuffmanContext * huff, int *val)
186 { 194 {
187 int b; 195 int b;
188 if (a->num_bits < 16) 196 if (ctx->numBits < 16)
189 stbi__fill_bits(a); 197 stbi__fill_bits(ctx);
190 198
191 b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; 199 b = huff->fast[ctx->codeBuffer & STBI__ZFAST_MASK];
192 if (b) 200 if (b)
193 { 201 {
194 int s = b >> 9; 202 int s = b >> 9;
195 a->code_buffer >>= s; 203 ctx->codeBuffer >>= s;
196 a->num_bits -= s; 204 ctx->numBits -= s;
197 return b & 511; 205 *val = b & 511;
198 } 206 return DMERR_OK;
199 return stbi__zhuffman_decode_slowpath(a, z); 207 }
200 } 208
201 209 return stbi__zhuffman_decode_slowpath(ctx, huff, val);
202 210 }
203 static int stbi__zexpand(DMZLibContext * z, char *zout, int n) // need to make room for n bytes 211
204 { 212
205 char *q; 213 static int stbi__zexpand(DMZLibContext * ctx, Uint8 *zout, size_t n)
206 int cur, limit; 214 {
207 z->zout = zout; 215 Uint8 *newBuf;
208 216 size_t cur, limit;
209 if (!z->z_expandable) 217
210 return stbi__err("output buffer limit", "Corrupt PNG"); 218 ctx->zout = zout;
211 219
212 cur = (int) (z->zout - z->zout_start); 220 if (!ctx->expandable)
213 limit = (int) (z->zout_end - z->zout_start); 221 {
222 return dmError(DMERR_BOUNDS,
223 "Output buffer limit hit, and is not expandable.\n");
224 }
225
226 cur = ctx->zout - ctx->zoutStart;
227 limit = ctx->zoutEnd - ctx->zoutStart;
214 228
215 while (cur + n > limit) 229 while (cur + n > limit)
216 limit *= 2; 230 limit *= 2;
217 231
218 if ((q = (char *) dmRealloc(z->zout_start, limit)) == NULL) 232 if ((newBuf = (Uint8 *) dmRealloc(ctx->zoutStart, limit)) == NULL)
219 return stbi__err("outofmem", "Out of memory"); 233 {
220 234 return dmError(DMERR_MALLOC,
221 z->zout_start = q; 235 "Could not reallocate buffer.\n");
222 z->zout = q + cur; 236 }
223 z->zout_end = q + limit; 237
224 return 1; 238 ctx->zoutStart = newBuf;
239 ctx->zout = newBuf + cur;
240 ctx->zoutEnd = newBuf + limit;
241
242 return DMERR_OK;
225 } 243 }
226 244
227 245
228 static const int stbi__zlength_base[31] = 246 static const int stbi__zlength_base[31] =
229 { 247 {
252 }; 270 };
253 271
254 272
255 static int stbi__parse_huffman_block(DMZLibContext * a) 273 static int stbi__parse_huffman_block(DMZLibContext * a)
256 { 274 {
257 char *zout = a->zout; 275 Uint8 *zout = a->zout;
258 for (;;) 276 for (;;)
259 { 277 {
260 int z = stbi__zhuffman_decode(a, &a->z_length); 278 int z, ret;
279 if ((ret = stbi__zhuffman_decode(a, &a->zlength, &z)) != DMERR_OK)
280 return ret;
281
261 if (z < 256) 282 if (z < 256)
262 { 283 {
263 if (z < 0) 284 if (zout >= a->zoutEnd)
264 return stbi__err("bad huffman code", "Corrupt PNG"); // error in huffman codes
265
266 if (zout >= a->zout_end)
267 { 285 {
268 if (!stbi__zexpand(a, zout, 1)) 286 if ((ret = stbi__zexpand(a, zout, 1)) != DMERR_OK)
269 return 0; 287 return ret;
288
270 zout = a->zout; 289 zout = a->zout;
271 } 290 }
272 *zout++ = (char) z; 291 *zout++ = (Uint8) z;
273 } 292 }
274 else 293 else
275 { 294 {
276 Uint8 *p; 295 Uint8 *p;
277 int len, dist; 296 int len, dist;
278 if (z == 256) 297 if (z == 256)
279 { 298 {
280 a->zout = zout; 299 a->zout = zout;
281 return 1; 300 return DMERR_OK;
282 } 301 }
283 z -= 257; 302 z -= 257;
284 303
285 len = stbi__zlength_base[z]; 304 len = stbi__zlength_base[z];
286 if (stbi__zlength_extra[z]) 305 if (stbi__zlength_extra[z])
287 len += stbi__zreceive(a, stbi__zlength_extra[z]); 306 len += stbi__zreceive(a, stbi__zlength_extra[z]);
288 307
289 z = stbi__zhuffman_decode(a, &a->z_distance); 308 if ((ret = stbi__zhuffman_decode(a, &a->zdistance, &z)) != DMERR_OK)
290 if (z < 0) 309 return ret;
291 return stbi__err("bad huffman code", "Corrupt PNG");
292 310
293 dist = stbi__zdist_base[z]; 311 dist = stbi__zdist_base[z];
294 if (stbi__zdist_extra[z]) 312 if (stbi__zdist_extra[z])
295 dist += stbi__zreceive(a, stbi__zdist_extra[z]); 313 dist += stbi__zreceive(a, stbi__zdist_extra[z]);
296 314
297 if (zout - a->zout_start < dist) 315 if (zout - a->zoutStart < dist)
298 return stbi__err("bad dist", "Corrupt PNG"); 316 {
299 317 return dmError(DMERR_DATA_ERROR,
300 if (zout + len > a->zout_end) 318 "Bad Huffman block distance.\n");
319 }
320
321 if (zout + len > a->zoutEnd)
301 { 322 {
302 if (!stbi__zexpand(a, zout, len)) 323 if (!stbi__zexpand(a, zout, len))
303 return 0; 324 return 0;
304 zout = a->zout; 325 zout = a->zout;
305 } 326 }
329 static int stbi__compute_huffman_codes(DMZLibContext * a) 350 static int stbi__compute_huffman_codes(DMZLibContext * a)
330 { 351 {
331 DMZHuffmanContext z_codelength; 352 DMZHuffmanContext z_codelength;
332 Uint8 lencodes[286 + 32 + 137]; //padding for maximum single op 353 Uint8 lencodes[286 + 32 + 137]; //padding for maximum single op
333 Uint8 codelength_sizes[19]; 354 Uint8 codelength_sizes[19];
334 int i, n; 355 int i, n, ret;
335 356
336 int hlit = stbi__zreceive(a, 5) + 257; 357 int hlit = stbi__zreceive(a, 5) + 257;
337 int hdist = stbi__zreceive(a, 5) + 1; 358 int hdist = stbi__zreceive(a, 5) + 1;
338 int hclen = stbi__zreceive(a, 4) + 4; 359 int hclen = stbi__zreceive(a, 4) + 4;
339 360
340 memset(codelength_sizes, 0, sizeof(codelength_sizes)); 361 memset(codelength_sizes, 0, sizeof(codelength_sizes));
341 362
342 for (i = 0; i < hclen; i++) 363 for (i = 0; i < hclen; i++)
343 { 364 {
344 int s = stbi__zreceive(a, 3); 365 int s = stbi__zreceive(a, 3);
345 codelength_sizes[length_dezigzag[i]] = (Uint8) s; 366 codelength_sizes[length_dezigzag[i]] = (Uint8) s;
346 } 367 }
347 if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) 368
348 return 0; 369 if ((ret = stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) != DMERR_OK)
349 370 return ret;
350 371
351 n = 0; 372 n = 0;
352 while (n < hlit + hdist) 373 while (n < hlit + hdist)
353 { 374 {
354 int c = stbi__zhuffman_decode(a, &z_codelength); 375 int c;
355 STBI_ASSERT(c >= 0 && c < 19); 376 if ((ret = stbi__zhuffman_decode(a, &z_codelength, &c)) != DMERR_OK)
377 return ret;
378
379 DMSTBI_ASSERT(c >= 0 && c < 19);
356 380
357 if (c < 16) 381 if (c < 16)
358 lencodes[n++] = (Uint8) c; 382 lencodes[n++] = (Uint8) c;
359 else 383 else
360 if (c == 16) 384 if (c == 16)
377 n += c; 401 n += c;
378 } 402 }
379 } 403 }
380 404
381 if (n != hlit + hdist) 405 if (n != hlit + hdist)
382 return stbi__err("bad codelengths", "Corrupt PNG"); 406 {
383 407 return dmError(DMERR_DATA_ERROR,
384 if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) 408 "Bad huffman codelengths.\n");
385 return 0; 409 }
386 410
387 if (!stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist)) 411 if ((ret = stbi__zbuild_huffman(&a->zlength, lencodes, hlit)) != DMERR_OK)
388 return 0; 412 return ret;
389 return 1; 413
414 if ((ret = stbi__zbuild_huffman(&a->zdistance, lencodes + hlit, hdist)) != DMERR_OK)
415 return ret;
416
417 return DMERR_OK;
390 } 418 }
391 419
392 420
393 static int stbi__parse_uncompressed_block(DMZLibContext * a) 421 static int stbi__parse_uncompressed_block(DMZLibContext * a)
394 { 422 {
395 Uint8 header[4]; 423 Uint8 header[4];
396 int len, nlen, k; 424 int len, nlen, k;
397 425
398 if (a->num_bits & 7) 426 if (a->numBits & 7)
399 stbi__zreceive(a, a->num_bits & 7); // discard 427 stbi__zreceive(a, a->numBits & 7); // discard
400 428
401 // drain the bit-packed data into header 429 // drain the bit-packed data into header
402 k = 0; 430 k = 0;
403 while (a->num_bits > 0) 431 while (a->numBits > 0)
404 { 432 {
405 header[k++] = (Uint8) (a->code_buffer & 255); // suppress MSVC run-time check 433 header[k++] = (Uint8) (a->codeBuffer & 255); // suppress MSVC run-time check
406 a->code_buffer >>= 8; 434 a->codeBuffer >>= 8;
407 a->num_bits -= 8; 435 a->numBits -= 8;
408 } 436 }
409 STBI_ASSERT(a->num_bits == 0); 437 DMSTBI_ASSERT(a->numBits == 0);
410 438
411 // now fill header the normal way 439 // now fill header the normal way
412 while (k < 4) 440 while (k < 4)
413 header[k++] = stbi__zget8(a); 441 header[k++] = stbi__zget8(a);
414 442
415 len = header[1] * 256 + header[0]; 443 len = (header[1] << 8) | header[0];
416 nlen = header[3] * 256 + header[2]; 444 nlen = (header[3] << 8) | header[2];
417 445
418 if (nlen != (len ^ 0xffff)) 446 if (nlen != (len ^ 0xffff))
419 return stbi__err("zlib corrupt", "Corrupt PNG"); 447 {
420 448 return dmError(DMERR_DATA_ERROR,
421 if (a->zbuffer + len > a->zbuffer_end) 449 "Compressed data corrupt.\n");
422 return stbi__err("read past buffer", "Corrupt PNG"); 450 }
423 451
424 if (a->zout + len > a->zout_end && !stbi__zexpand(a, a->zout, len)) 452 if (a->zbuffer + len > a->zbufferEnd)
425 return 0; 453 {
454 return dmError(DMERR_BOUNDS,
455 "Read past buffer, probably corrupt compressed data.\n");
456 }
457
458 if (a->zout + len > a->zoutEnd && !stbi__zexpand(a, a->zout, len))
459 {
460 return dmError(DMERR_DATA_ERROR,
461 "XXXX TODO");
462 }
426 463
427 memcpy(a->zout, a->zbuffer, len); 464 memcpy(a->zout, a->zbuffer, len);
428 a->zbuffer += len; 465 a->zbuffer += len;
429 a->zout += len; 466 a->zout += len;
430 return 1; 467
431 } 468 return DMERR_OK;
432 469 }
433 470
434 static int stbi__parse_zlib_header(DMZLibContext * a) 471
435 { 472 int dmZLibParseHeader(DMZLibContext * ctx, BOOL checkPNG)
436 int cmf = stbi__zget8(a); 473 {
474 int cmf = stbi__zget8(ctx);
475 int flags = stbi__zget8(ctx);
437 int cm = cmf & 15; 476 int cm = cmf & 15;
438 int flg = stbi__zget8(a);
439 // int cinfo = cmf >> 4; 477 // int cinfo = cmf >> 4;
440 478
441 if ((cmf * 256 + flg) % 31 != 0) 479 if ((cmf * 256 + flags) % 31 != 0)
442 return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec 480 {
443 481 return dmError(DMERR_INVALID_DATA,
444 if (flg & 32) 482 "Bad zlib header.");
445 return stbi__err("no preset dict", "Corrupt PNG"); // preset dictionary not allowed in png 483 }
446 484
447 if (cm != 8) 485 if (checkPNG && (flags & 32))
448 return stbi__err("bad compression", "Corrupt PNG"); // DEFLATE required for png 486 {
487 // preset dictionary not allowed in png
488 return dmError(DMERR_NOT_SUPPORTED,
489 "Preset dictionary not allowed in PNG.\n");
490 }
491
492 if (checkPNG && cm != 8)
493 {
494 return dmError(DMERR_INVALID_DATA,
495 "Bad or unsupported compression type.\n");
496 }
449 497
450 // window = 1 << (8 + cinfo)... but who cares, we fully buffer output 498 // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
451 return 1; 499 return DMERR_OK;
452 } 500 }
453 501
454 502
455 static int stbi__parse_zlib(DMZLibContext * a, BOOL parse_header) 503 int dmZLibDecode(DMZLibContext * ctx)
456 { 504 {
457 int final, type; 505 int final, type, ret;
458 506
459 if (parse_header && !stbi__parse_zlib_header(a)) 507 ctx->numBits = 0;
460 return 0; 508 ctx->codeBuffer = 0;
461
462 a->num_bits = 0;
463 a->code_buffer = 0;
464 do 509 do
465 { 510 {
466 final = stbi__zreceive(a, 1); 511 final = stbi__zreceive(ctx, 1);
467 type = stbi__zreceive(a, 2); 512 type = stbi__zreceive(ctx, 2);
468 if (type == 0) 513 if (type == 0)
469 { 514 {
470 if (!stbi__parse_uncompressed_block(a)) 515 if ((ret = stbi__parse_uncompressed_block(ctx)) != DMERR_OK)
471 return 0; 516 return ret;
472 } 517 }
473 else 518 else
474 if (type == 3) 519 if (type == 3)
475 return 0; 520 return 0;
476 else 521 else
477 { 522 {
478 if (type == 1) 523 if (type == 1)
479 { 524 {
480 // use fixed code lengths 525 // use fixed code lengths
481 if (!stbi__zbuild_huffman(&a->z_length, stbi__zdefault_length, 288)) 526 if ((ret = stbi__zbuild_huffman(&ctx->zlength, stbi__zdefault_length, 288)) != DMERR_OK)
482 return 0; 527 return ret;
483 528
484 if (!stbi__zbuild_huffman 529 if ((ret = stbi__zbuild_huffman(&ctx->zdistance, stbi__zdefault_distance, 32)) != DMERR_OK)
485 (&a->z_distance, stbi__zdefault_distance, 32)) 530 return ret;
486 return 0;
487 } 531 }
488 else 532 else
489 { 533 if ((ret = stbi__compute_huffman_codes(ctx)) != DMERR_OK)
490 if (!stbi__compute_huffman_codes(a)) 534 return ret;
491 return 0; 535
492 } 536 if ((ret = stbi__parse_huffman_block(ctx)) != DMERR_OK)
493 if (!stbi__parse_huffman_block(a)) 537 return ret;
494 return 0;
495 } 538 }
496 } 539 }
497 while (!final); 540 while (!final);
498 return 1; 541
499 } 542 return DMERR_OK;
500 543 }
501 544
502 static int stbi__do_zlib(DMZLibContext * a, char *obuf, int olen, int exp, 545
503 BOOL parse_header) 546 Uint8 *stbi_zlib_decode_malloc_guesssize_headerflag(
504 { 547 const Uint8 *buffer, const size_t len,
505 a->zout_start = obuf; 548 const size_t initialSize, size_t *outLen,
506 a->zout = obuf; 549 BOOL parseHeader)
507 a->zout_end = obuf + olen; 550 {
508 a->z_expandable = exp; 551 DMZLibContext ctx;
509 552 Uint8 *outBuf;
510 return stbi__parse_zlib(a, parse_header); 553 int ret;
511 } 554
512 555 if ((outBuf = dmMalloc(initialSize)) == NULL)
513 556 return NULL;
514 char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) 557
515 { 558 ctx.zbuffer = (Uint8 *) buffer;
516 DMZLibContext a; 559 ctx.zbufferEnd = (Uint8 *) buffer + len;
517 char *p = (char *) dmMalloc(initial_size); 560 ctx.zout = outBuf;
561 ctx.zoutStart = outBuf;
562 ctx.zoutEnd = outBuf + initialSize;
563 ctx.expandable = TRUE;
564
565 if (parseHeader && (ret = dmZLibParseHeader(&ctx, TRUE)) != DMERR_OK)
566 {
567 return dmError(ret,
568 "Failed to parse zlib header data.\n");
569 }
570
571 if ((ret = dmZLibDecode(&ctx)) != DMERR_OK)
572 {
573 if (outLen)
574 *outLen = ctx.zout - ctx.zoutStart;
575
576 return ctx.zoutStart;
577 }
578 else
579 {
580 dmFree(ctx.zoutStart);
581 return NULL;
582 }
583 }
584
585
586 #if 0
587
588 Uint8 *stbi_zlib_decode_malloc(Uint8 const *buffer, int len, int *outlen)
589 {
590 return stbi_zlib_decode_malloc_guesssize(buffer, len, DM_ZLIB_TMPBUF_SIZE, outlen);
591 }
592
593
594 int stbi_zlib_decode_buffer(Uint8 *obuffer, size_t olen, Uint8 const *ibuffer, size_t ilen, size_t *res)
595 {
596 DMZLibContext ctx;
597 int ret;
598
599 ctx.zbuffer = (Uint8 *) ibuffer;
600 ctx.zbufferEnd = (Uint8 *) ibuffer + ilen;
601
602 if ((ret = stbi__do_zlib(&a, obuffer, olen, 0, 1)) != DMERR_OK)
603 {
604 *res = a.zout - a.zoutStart;
605 return DMERR_OK;
606 }
607 else
608 return ret;
609 }
610
611
612 Uint8 *stbi_zlib_decode_noheader_malloc(Uint8 const *buffer, int len, size_t *outlen)
613 {
614 DMZLibContext ctx;
615 Uint8 *p = (Uint8 *) dmMalloc(DM_ZLIB_TMPBUF_SIZE);
518 if (p == NULL) 616 if (p == NULL)
519 return NULL; 617 return NULL;
520 a.zbuffer = (Uint8 *) buffer; 618
521 a.zbuffer_end = (Uint8 *) buffer + len; 619 ctx.zbuffer = (Uint8 *) buffer;
522 if (stbi__do_zlib(&a, p, initial_size, 1, 1)) 620 ctx.zbufferEnd = (Uint8 *) buffer + len;
523 { 621
524 if (outlen) 622 if (stbi__do_zlib(&ctx, p, DM_ZLIB_TMPBUF_SIZE, 1, 0))
525 *outlen = (int) (a.zout - a.zout_start); 623 {
526 return a.zout_start; 624 if (outlen != NULL)
625 *outlen = (int) (ctx.zout - a.zoutStart);
626 return a.zoutStart;
527 } 627 }
528 else 628 else
529 { 629 {
530 dmFree(a.zout_start); 630 dmFree(a.zoutStart);
531 return NULL; 631 return NULL;
532 } 632 }
533 } 633 }
534 634
535 635
536 char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) 636 int stbi_zlib_decode_noheader_buffer(Uint8 *obuffer, int olen, const Uint8 *ibuffer, int ilen)
537 {
538 return stbi_zlib_decode_malloc_guesssize(buffer, len, DM_ZLIB_TMPBUF_SIZE, outlen);
539 }
540
541
542 char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer,
543 int len, int initial_size, int *outlen, BOOL parse_header)
544 { 637 {
545 DMZLibContext a; 638 DMZLibContext a;
546 char *p = (char *) dmMalloc(initial_size); 639
547 if (p == NULL)
548 return NULL;
549
550 a.zbuffer = (Uint8 *) buffer;
551 a.zbuffer_end = (Uint8 *) buffer + len;
552 if (stbi__do_zlib(&a, p, initial_size, 1, parse_header))
553 {
554 if (outlen)
555 *outlen = (int) (a.zout - a.zout_start);
556 return a.zout_start;
557 }
558 else
559 {
560 dmFree(a.zout_start);
561 return NULL;
562 }
563 }
564
565
566 int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
567 {
568 DMZLibContext a;
569 a.zbuffer = (Uint8 *) ibuffer; 640 a.zbuffer = (Uint8 *) ibuffer;
570 a.zbuffer_end = (Uint8 *) ibuffer + ilen; 641 a.zbufferEnd = (Uint8 *) ibuffer + ilen;
571 if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) 642
572 return (int) (a.zout - a.zout_start); 643 if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
644 return (int) (a.zout - a.zoutStart);
573 else 645 else
574 return -1; 646 return -1;
575 } 647 }
576 648
577 649 #endif
578 char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
579 {
580 DMZLibContext a;
581 char *p = (char *) dmMalloc(DM_ZLIB_TMPBUF_SIZE);
582 if (p == NULL)
583 return NULL;
584
585 a.zbuffer = (Uint8 *) buffer;
586 a.zbuffer_end = (Uint8 *) buffer + len;
587
588 if (stbi__do_zlib(&a, p, DM_ZLIB_TMPBUF_SIZE, 1, 0))
589 {
590 if (outlen != NULL)
591 *outlen = (int) (a.zout - a.zout_start);
592 return a.zout_start;
593 }
594 else
595 {
596 dmFree(a.zout_start);
597 return NULL;
598 }
599 }
600
601
602 int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
603 {
604 DMZLibContext a;
605
606 a.zbuffer = (Uint8 *) ibuffer;
607 a.zbuffer_end = (Uint8 *) ibuffer + ilen;
608
609 if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
610 return (int) (a.zout - a.zout_start);
611 else
612 return -1;
613 }