fix jsut committed crasher by rewriting startDrag action
[swfdec.git] / libswfdec / swfdec_bits.c
blob9ec3988da153f25fc54fe10b6ed185d0d4204aac
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <string.h>
27 #include <zlib.h>
29 #include "swfdec_bits.h"
30 #include "swfdec_debug.h"
31 #include "swfdec_decoder.h"
32 #include "swfdec_rect.h"
35 #define SWFDEC_BITS_CHECK(b,n) G_STMT_START { \
36 if (swfdec_bits_left(b) < (n)) { \
37 SWFDEC_ERROR ("reading past end of buffer"); \
38 b->ptr = b->end; \
39 b->idx = 0; \
40 return 0; \
41 } \
42 }G_STMT_END
43 #define SWFDEC_BYTES_CHECK(b,n) G_STMT_START { \
44 g_assert (b->end >= b->ptr); \
45 g_assert (b->idx == 0); \
46 if ((unsigned long) (b->end - b->ptr) < n) { \
47 SWFDEC_ERROR ("reading past end of buffer"); \
48 b->ptr = b->end; \
49 b->idx = 0; \
50 return 0; \
51 } \
52 } G_STMT_END
54 /**
55 * swfdec_bits_init:
56 * @bits: a #SwfdecBits
57 * @buffer: buffer to use for data or NULL
59 * initializes @bits for use with the data in @buffer. The buffer will not be
60 * referenced, so you are responsible for keeping it around while @bits is used.
61 **/
62 void
63 swfdec_bits_init (SwfdecBits *bits, SwfdecBuffer *buffer)
65 g_return_if_fail (bits != NULL);
67 if (buffer) {
68 bits->buffer = buffer;
69 bits->ptr = buffer->data;
70 bits->idx = 0;
71 bits->end = buffer->data + buffer->length;
72 } else {
73 memset (bits, 0, sizeof (SwfdecBits));
77 /**
78 * swfdec_bits_init_bits:
79 * @bits: a #SwfdecBits
80 * @from: a #SwfdecBits to initialize from
81 * @bytes: number of bytes to move to @bits
83 * Initializes @bits for use with the next @bytes bytes from @from. If not
84 * enough bytes are available, less bytes will be available in @bits. @from
85 * will skip the bytes now available in @bits. If you want to know if this
86 * function moves enough bytes, you should ensure that enough data is
87 * available using swfdec_bits_left() before calling this function.
88 **/
89 void
90 swfdec_bits_init_bits (SwfdecBits *bits, SwfdecBits *from, guint bytes)
92 g_return_if_fail (bits != NULL);
93 g_return_if_fail (from != NULL);
94 g_return_if_fail (from->idx == 0);
96 bits->buffer = from->buffer;
97 bits->ptr = from->ptr;
98 if (bytes > (guint) (from->end - from->ptr))
99 bytes = from->end - from->ptr;
100 bits->end = bits->ptr + bytes;
101 bits->idx = 0;
102 from->ptr = bits->end;
106 * swfdec_bits_init_data:
107 * @bits: the #SwfdecBits to initialize
108 * @data: data to initialize with
109 * @len: length of the data
111 * Initializes @bits for use with the given @data. All operations on @bits will
112 * return copies of the data, so after use, you can free the supplied data. Using
113 * %NULL for @data is valid if @len is 0.
115 void
116 swfdec_bits_init_data (SwfdecBits *bits, const guint8 *data, guint len)
118 g_return_if_fail (bits != NULL);
119 g_return_if_fail (data != NULL || len == 0);
121 bits->buffer = NULL;
122 bits->ptr = data;
123 bits->idx = 0;
124 bits->end = bits->ptr + len;
127 guint
128 swfdec_bits_left (const SwfdecBits *b)
130 if (b->ptr == NULL)
131 return 0;
132 g_assert (b->end >= b->ptr);
133 g_assert (b->end > b->ptr || b->idx == 0);
134 return (b->end - b->ptr) * 8 - b->idx;
138 swfdec_bits_getbit (SwfdecBits * b)
140 int r;
142 SWFDEC_BITS_CHECK (b, 1);
144 r = ((*b->ptr) >> (7 - b->idx)) & 1;
146 b->idx++;
147 if (b->idx >= 8) {
148 b->ptr++;
149 b->idx = 0;
152 return r;
155 guint
156 swfdec_bits_getbits (SwfdecBits * b, guint n)
158 unsigned long r = 0;
159 guint i;
161 SWFDEC_BITS_CHECK (b, n);
163 while (n > 0) {
164 i = MIN (n, 8 - b->idx);
165 r <<= i;
166 r |= ((*b->ptr) >> (8 - i - b->idx)) & ((1 << i) - 1);
167 n -= i;
168 if (i == 8) {
169 b->ptr++;
170 } else {
171 b->idx += i;
172 if (b->idx >= 8) {
173 b->ptr++;
174 b->idx = 0;
178 return r;
181 guint
182 swfdec_bits_peekbits (const SwfdecBits * b, guint n)
184 SwfdecBits tmp = *b;
186 return swfdec_bits_getbits (&tmp, n);
190 swfdec_bits_getsbits (SwfdecBits * b, guint n)
192 unsigned long r = 0;
194 SWFDEC_BITS_CHECK (b, n);
196 if (n == 0)
197 return 0;
198 r = -swfdec_bits_getbit (b);
199 r = (r << (n - 1)) | swfdec_bits_getbits (b, n - 1);
200 return r;
203 guint
204 swfdec_bits_peek_u8 (const SwfdecBits * b)
206 g_assert (b->idx == 0);
207 g_assert (b->ptr <= b->end);
208 if (b->ptr == b->end)
209 return 0;
211 return *b->ptr;
214 guint
215 swfdec_bits_get_u8 (SwfdecBits * b)
217 SWFDEC_BYTES_CHECK (b, 1);
219 return *b->ptr++;
222 guint
223 swfdec_bits_get_u16 (SwfdecBits * b)
225 guint r;
227 SWFDEC_BYTES_CHECK (b, 2);
229 r = b->ptr[0] | (b->ptr[1] << 8);
230 b->ptr += 2;
232 return r;
236 swfdec_bits_get_s16 (SwfdecBits * b)
238 short r;
240 SWFDEC_BYTES_CHECK (b, 2);
242 r = b->ptr[0] | (b->ptr[1] << 8);
243 b->ptr += 2;
245 return r;
248 guint
249 swfdec_bits_get_u32 (SwfdecBits * b)
251 guint r;
253 SWFDEC_BYTES_CHECK (b, 4);
255 r = b->ptr[0] | (b->ptr[1] << 8) | (b->ptr[2] << 16) | (b->ptr[3] << 24);
256 b->ptr += 4;
258 return r;
261 guint
262 swfdec_bits_get_bu16 (SwfdecBits *b)
264 guint r;
266 SWFDEC_BYTES_CHECK (b, 2);
268 r = (b->ptr[0] << 8) | b->ptr[1];
269 b->ptr += 2;
271 return r;
274 guint
275 swfdec_bits_get_bu24 (SwfdecBits *b)
277 guint r;
279 SWFDEC_BYTES_CHECK (b, 3);
281 r = (b->ptr[0] << 16) | (b->ptr[1] << 8) | b->ptr[2];
282 b->ptr += 3;
284 return r;
287 guint
288 swfdec_bits_get_bu32 (SwfdecBits *b)
290 guint r;
292 SWFDEC_BYTES_CHECK (b, 4);
294 r = (b->ptr[0] << 24) | (b->ptr[1] << 16) | (b->ptr[2] << 8) | b->ptr[3];
295 b->ptr += 4;
297 return r;
300 float
301 swfdec_bits_get_float (SwfdecBits * b)
303 union {
304 gint32 i;
305 float f;
306 } conv;
308 SWFDEC_BYTES_CHECK (b, 4);
310 conv.i = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
311 b->ptr += 4;
313 return conv.f;
316 /* fixup mad byte ordering of doubles in flash files.
317 * If little endian x86 byte order is 0 1 2 3 4 5 6 7 and PPC32 byte order is
318 * 7 6 5 4 3 2 1 0, then Flash uses 4 5 6 7 0 1 2 3.
319 * If your architecture has a different byte ordering for storing doubles,
320 * this conversion function will fail. To find out your byte ordering, you can
321 * use this command line:
322 * python -c "import struct; print struct.unpack('8c', struct.pack('d', 7.949928895127363e-275))"
324 double
325 swfdec_bits_get_double (SwfdecBits * b)
327 union {
328 guint32 i[2];
329 double d;
330 } conv;
332 SWFDEC_BYTES_CHECK (b, 8);
334 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
335 conv.i[1] = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
336 conv.i[0] = (b->ptr[7] << 24) | (b->ptr[6] << 16) | (b->ptr[5] << 8) | b->ptr[4];
337 #else
338 conv.i[0] = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
339 conv.i[1] = (b->ptr[7] << 24) | (b->ptr[6] << 16) | (b->ptr[5] << 8) | b->ptr[4];
340 #if 0
341 conv.i[0] = (b->ptr[0] << 24) | (b->ptr[1] << 16) | (b->ptr[2] << 8) | b->ptr[3];
342 conv.i[1] = (b->ptr[4] << 24) | (b->ptr[5] << 16) | (b->ptr[6] << 8) | b->ptr[7];
343 #endif
344 #endif
345 b->ptr += 8;
347 return conv.d;
350 double
351 swfdec_bits_get_bdouble (SwfdecBits * b)
353 double d;
354 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
355 guint64 tmp;
356 gpointer p;
357 #endif
359 SWFDEC_BYTES_CHECK (b, 8);
361 #if G_BYTE_ORDER == G_BIG_ENDIAN
362 d = *((double *) b->ptr);
363 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
364 tmp = *((guint64 *) b->ptr);
365 tmp = GUINT64_FROM_BE (tmp);
366 p = &tmp;
367 d = *((double *) p);
368 #endif
369 b->ptr += 8;
371 return d;
374 void
375 swfdec_bits_syncbits (SwfdecBits * b)
377 if (b->idx) {
378 b->ptr++;
379 b->idx = 0;
383 void
384 swfdec_bits_get_color_transform (SwfdecBits * bits, SwfdecColorTransform * ct)
386 int has_add;
387 int has_mult;
388 int n_bits;
390 has_add = swfdec_bits_getbit (bits);
391 has_mult = swfdec_bits_getbit (bits);
392 n_bits = swfdec_bits_getbits (bits, 4);
393 if (has_mult) {
394 ct->ra = swfdec_bits_getsbits (bits, n_bits);
395 ct->ga = swfdec_bits_getsbits (bits, n_bits);
396 ct->ba = swfdec_bits_getsbits (bits, n_bits);
397 ct->aa = swfdec_bits_getsbits (bits, n_bits);
398 } else {
399 ct->ra = 256;
400 ct->ga = 256;
401 ct->ba = 256;
402 ct->aa = 256;
404 if (has_add) {
405 ct->rb = swfdec_bits_getsbits (bits, n_bits);
406 ct->gb = swfdec_bits_getsbits (bits, n_bits);
407 ct->bb = swfdec_bits_getsbits (bits, n_bits);
408 ct->ab = swfdec_bits_getsbits (bits, n_bits);
409 } else {
410 ct->rb = 0;
411 ct->gb = 0;
412 ct->bb = 0;
413 ct->ab = 0;
415 swfdec_bits_syncbits (bits);
418 void
419 swfdec_bits_get_matrix (SwfdecBits * bits, cairo_matrix_t *matrix,
420 cairo_matrix_t *inverse)
422 int has_scale;
423 int has_rotate;
424 int n_translate_bits;
426 has_scale = swfdec_bits_getbit (bits);
427 if (has_scale) {
428 int n_scale_bits = swfdec_bits_getbits (bits, 5);
429 matrix->xx = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_scale_bits));
430 matrix->yy = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_scale_bits));
432 SWFDEC_LOG ("scalefactors: x = %d/65536, y = %d/65536",
433 SWFDEC_DOUBLE_TO_FIXED (matrix->xx), SWFDEC_DOUBLE_TO_FIXED (matrix->yy));
434 } else {
435 SWFDEC_LOG ("no scalefactors given");
436 matrix->xx = 1.0;
437 matrix->yy = 1.0;
439 has_rotate = swfdec_bits_getbit (bits);
440 if (has_rotate) {
441 int n_rotate_bits = swfdec_bits_getbits (bits, 5);
442 matrix->yx = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_rotate_bits));
443 matrix->xy = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_rotate_bits));
445 SWFDEC_LOG ("skew: xy = %d/65536, yx = %d/65536",
446 SWFDEC_DOUBLE_TO_FIXED (matrix->xy),
447 SWFDEC_DOUBLE_TO_FIXED (matrix->yx));
448 } else {
449 SWFDEC_LOG ("no rotation");
450 matrix->xy = 0;
451 matrix->yx = 0;
453 n_translate_bits = swfdec_bits_getbits (bits, 5);
454 matrix->x0 = swfdec_bits_getsbits (bits, n_translate_bits);
455 matrix->y0 = swfdec_bits_getsbits (bits, n_translate_bits);
457 swfdec_matrix_ensure_invertible (matrix, inverse);
458 swfdec_bits_syncbits (bits);
461 static const char *
462 swfdec_bits_skip_string (SwfdecBits *bits)
464 char *s;
465 const char *end;
466 guint len;
468 SWFDEC_BYTES_CHECK (bits, 1);
469 end = memchr (bits->ptr, 0, bits->end - bits->ptr);
470 if (end == NULL) {
471 SWFDEC_ERROR ("could not parse string");
472 return NULL;
475 len = end - (const char *) bits->ptr;
476 s = (char *) bits->ptr;
477 bits->ptr += len + 1;
479 return s;
483 * swfdec_bits_get_string_with_version:
484 * @bits: a #SwfdecBits
485 * @version: Flash player version
487 * Prior to Flash 6, strings used to be encoded as LATIN1. Since Flash 6,
488 * strings are encoded as UTF-8. This version does the check automatically
489 * and converts strings to UTF-8.
491 * Returns: a UTF-8 encoded string or %NULL on error
493 char *
494 swfdec_bits_get_string_with_version (SwfdecBits *bits, guint version)
496 const char *s;
498 g_return_val_if_fail (bits != NULL, NULL);
500 s = swfdec_bits_skip_string (bits);
501 if (s == NULL)
502 return NULL;
504 if (version < 6) {
505 char *ret = g_convert (s, -1, "UTF-8", "LATIN1", NULL , NULL, NULL);
506 if (ret == NULL)
507 g_warning ("Could not convert string from LATIN1 to UTF-8");
508 return ret;
509 } else {
510 if (!g_utf8_validate (s, -1, NULL)) {
511 SWFDEC_ERROR ("parsed string is not valid utf-8");
512 return NULL;
514 return g_strdup (s);
518 /* FIXME: deprecated - someone remove this */
519 char *
520 swfdec_bits_get_string (SwfdecBits * bits)
522 return swfdec_bits_get_string_with_version (bits, 6);
526 * swfdec_bits_skip_bytes:
527 * @bits: a #SwfdecBits
528 * @n_bytes: number of bytes to skip
530 * Skips up to @n_bytes bytes in @bits. If not enough bytes are available,
531 * only the available amount is skipped and a warning is printed.
533 * Returns: the number of bytes actually skipped
535 guint
536 swfdec_bits_skip_bytes (SwfdecBits *bits, guint n_bytes)
538 g_assert (bits->idx == 0);
539 if ((guint) (bits->end - bits->ptr) < n_bytes) {
540 SWFDEC_WARNING ("supposed to skip %u bytes, but only %td available",
541 n_bytes, bits->end - bits->ptr);
542 n_bytes = bits->end - bits->ptr;
544 bits->ptr += n_bytes;
545 return n_bytes;
549 * swfdec_bits_get_string_length:
550 * @bits: a #SwfdecBits
551 * @len: number of bytes to read
553 * Reads the next @len bytes into a string and validates it as UTF-8.
555 * Returns: a new string or %NULL on error
557 char *
558 swfdec_bits_get_string_length (SwfdecBits * bits, guint len)
560 char *ret;
562 if (len == 0)
563 return g_strdup ("");
564 SWFDEC_BYTES_CHECK (bits, len);
566 ret = g_strndup ((char *) bits->ptr, len);
567 bits->ptr += len;
568 if (!g_utf8_validate (ret, -1, NULL)) {
569 SWFDEC_ERROR ("parsed string is not valid utf-8");
570 g_free (ret);
571 ret = NULL;
573 return ret;
576 SwfdecColor
577 swfdec_bits_get_color (SwfdecBits * bits)
579 guint r, g, b;
581 r = swfdec_bits_get_u8 (bits);
582 g = swfdec_bits_get_u8 (bits);
583 b = swfdec_bits_get_u8 (bits);
585 return SWFDEC_COLOR_COMBINE (r, g, b, 0xff);
588 SwfdecColor
589 swfdec_bits_get_rgba (SwfdecBits * bits)
591 guint r, g, b, a;
593 r = swfdec_bits_get_u8 (bits);
594 g = swfdec_bits_get_u8 (bits);
595 b = swfdec_bits_get_u8 (bits);
596 a = swfdec_bits_get_u8 (bits);
598 return SWFDEC_COLOR_COMBINE (r, g, b, a);
601 SwfdecGradient *
602 swfdec_bits_get_gradient (SwfdecBits * bits)
604 SwfdecGradient *grad;
605 guint i, n_gradients;
607 n_gradients = swfdec_bits_get_u8 (bits);
608 grad = g_malloc (sizeof (SwfdecGradient) +
609 sizeof (SwfdecGradientEntry) * (MAX (n_gradients, 1) - 1));
610 for (i = 0; i < n_gradients && swfdec_bits_left (bits); i++) {
611 grad->array[i].ratio = swfdec_bits_get_u8 (bits);
612 grad->array[i].color = swfdec_bits_get_color (bits);
614 if (i < n_gradients) {
615 SWFDEC_ERROR ("not enough data for %u gradients, could only read %u",
616 n_gradients, i);
618 grad->n_gradients = i;
619 return grad;
622 SwfdecGradient *
623 swfdec_bits_get_gradient_rgba (SwfdecBits * bits)
625 SwfdecGradient *grad;
626 guint i, n_gradients;
628 n_gradients = swfdec_bits_get_u8 (bits);
629 grad = g_malloc (sizeof (SwfdecGradient) +
630 sizeof (SwfdecGradientEntry) * (n_gradients - 1));
631 for (i = 0; i < n_gradients && swfdec_bits_left (bits); i++) {
632 grad->array[i].ratio = swfdec_bits_get_u8 (bits);
633 grad->array[i].color = swfdec_bits_get_rgba (bits);
635 if (i < n_gradients) {
636 SWFDEC_ERROR ("not enough data for %u gradients, could only read %u",
637 n_gradients, i);
639 grad->n_gradients = i;
640 return grad;
643 SwfdecGradient *
644 swfdec_bits_get_morph_gradient (SwfdecBits * bits)
646 SwfdecGradient *grad;
647 guint i, n_gradients;
649 n_gradients = swfdec_bits_get_u8 (bits);
650 n_gradients *= 2;
651 grad = g_malloc (sizeof (SwfdecGradient) +
652 sizeof (SwfdecGradientEntry) * (n_gradients - 1));
653 for (i = 0; i < n_gradients && swfdec_bits_left (bits); i++) {
654 grad->array[i].ratio = swfdec_bits_get_u8 (bits);
655 grad->array[i].color = swfdec_bits_get_rgba (bits);
657 if (i < n_gradients) {
658 SWFDEC_ERROR ("not enough data for %u gradients, could only read %u",
659 n_gradients, i);
661 grad->n_gradients = i;
662 return grad;
665 void
666 swfdec_bits_get_rect (SwfdecBits * bits, SwfdecRect *rect)
668 int nbits;
670 nbits = swfdec_bits_getbits (bits, 5);
671 rect->x0 = swfdec_bits_getsbits (bits, nbits);
672 rect->x1 = swfdec_bits_getsbits (bits, nbits);
673 rect->y0 = swfdec_bits_getsbits (bits, nbits);
674 rect->y1 = swfdec_bits_getsbits (bits, nbits);
676 swfdec_bits_syncbits (bits);
680 * swfdec_bits_get_buffer:
681 * @bits: #SwfdecBits
682 * @len: length of buffer or -1 for maximum
684 * Gets the contents of the next @len bytes of @bits and buts them in a new
685 * subbuffer. If @len is 0 (or @len is -1 and no more data is available), this
686 * is considered a reading error and %NULL is returned.
688 * Returns: the new #SwfdecBuffer or NULL if the requested amount of data
689 * isn't available
691 SwfdecBuffer *
692 swfdec_bits_get_buffer (SwfdecBits *bits, int len)
694 SwfdecBuffer *buffer;
696 g_return_val_if_fail (len >= -1, NULL);
698 if (len > 0) {
699 SWFDEC_BYTES_CHECK (bits, (guint) len);
700 } else {
701 g_assert (bits->idx == 0);
702 len = bits->end - bits->ptr;
703 g_assert (len >= 0);
705 if (len == 0)
706 return NULL;
707 if (bits->buffer) {
708 buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
709 } else {
710 buffer = swfdec_buffer_new_and_alloc (len);
711 memcpy (buffer->data, bits->ptr, len);
713 bits->ptr += len;
714 return buffer;
717 static void *
718 swfdec_bits_zalloc (void *opaque, guint items, guint size)
720 return g_malloc (items * size);
723 static void
724 swfdec_bits_zfree (void *opaque, void *addr)
726 g_free (addr);
730 * swfdec_bits_decompress:
731 * @bits: a #SwfdecBits
732 * @compressed: number of bytes to decompress or -1 for the rest
733 * @decompressed: number of bytes to expect in the decompressed result or -1
734 * if unknown
736 * Decompresses the next @compressed bytes of data in @bits using the zlib
737 * decompression algorithm and returns the result in a buffer. If @decompressed
738 * was set and not enough data is available, the return buffer will be filled
739 * up with 0 bytes.
741 * Returns: a new #SwfdecBuffer containing the decompressed data or NULL on
742 * failure. If @decompressed &gt; 0, the buffer's length will be @decompressed.
744 SwfdecBuffer *
745 swfdec_bits_decompress (SwfdecBits *bits, int compressed, int decompressed)
747 z_stream z = { 0, };
748 SwfdecBuffer *buffer;
749 int result;
751 g_return_val_if_fail (bits != NULL, NULL);
752 g_return_val_if_fail (compressed >= -1, NULL);
753 g_return_val_if_fail (decompressed > 0 || decompressed == -1, NULL);
755 /* prepare the bits structure */
756 if (compressed > 0) {
757 SWFDEC_BYTES_CHECK (bits, (guint) compressed);
758 } else {
759 g_assert (bits->idx == 0);
760 compressed = bits->end - bits->ptr;
761 g_assert (compressed >= 0);
763 if (compressed == 0)
764 return NULL;
766 z.zalloc = swfdec_bits_zalloc;
767 z.zfree = swfdec_bits_zfree;
768 z.opaque = NULL;
769 z.next_in = (Bytef *) bits->ptr;
770 z.avail_in = compressed;
771 result = inflateInit (&z);
772 if (result != Z_OK) {
773 SWFDEC_ERROR ("Error initialising zlib: %d %s", result, z.msg ? z.msg : "");
774 goto fail;
776 buffer = swfdec_buffer_new_and_alloc (decompressed > 0 ? decompressed : compressed * 2);
777 z.next_out = buffer->data;
778 z.avail_out = buffer->length;
779 while (TRUE) {
780 result = inflate (&z, decompressed > 0 ? Z_FINISH : 0);
781 switch (result) {
782 case Z_STREAM_END:
783 goto out;
784 case Z_OK:
785 if (decompressed < 0) {
786 buffer->data = g_realloc (buffer->data, buffer->length + compressed);
787 buffer->length += compressed;
788 z.next_out = buffer->data + z.total_out;
789 z.avail_out = buffer->length - z.total_out;
790 goto out;
792 /* else fall through */
793 default:
794 SWFDEC_ERROR ("error decompressing data: inflate returned %d %s",
795 result, z.msg ? z.msg : "");
796 swfdec_buffer_unref (buffer);
797 goto fail;
800 out:
801 if (decompressed < 0) {
802 buffer->length = z.total_out;
803 } else {
804 if (buffer->length < z.total_out) {
805 SWFDEC_WARNING ("Not enough data decompressed: %lu instead of %u expected",
806 z.total_out, buffer->length);
807 memset (buffer->data + z.total_out, 0, buffer->length - z.total_out);
810 result = inflateEnd (&z);
811 if (result != Z_OK) {
812 SWFDEC_ERROR ("error in inflateEnd: %d %s", result, z.msg ? z.msg : "");
814 bits->ptr += compressed;
815 return buffer;
817 fail:
818 bits->ptr += compressed;
819 return NULL;