make swfdec_as_object_mark() only mark if not marked yet
[swfdec.git] / swfdec / swfdec_bits.c
blob0a604fc1c4123f9964cf091a9b97b314ea3ffabb
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_color.h"
31 #include "swfdec_debug.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;
262 swfdec_bits_get_s32 (SwfdecBits *b)
264 return (gint32) swfdec_bits_get_u32 (b);
267 guint
268 swfdec_bits_get_bu16 (SwfdecBits *b)
270 guint r;
272 SWFDEC_BYTES_CHECK (b, 2);
274 r = (b->ptr[0] << 8) | b->ptr[1];
275 b->ptr += 2;
277 return r;
280 guint
281 swfdec_bits_get_bu24 (SwfdecBits *b)
283 guint r;
285 SWFDEC_BYTES_CHECK (b, 3);
287 r = (b->ptr[0] << 16) | (b->ptr[1] << 8) | b->ptr[2];
288 b->ptr += 3;
290 return r;
293 guint
294 swfdec_bits_get_bu32 (SwfdecBits *b)
296 guint r;
298 SWFDEC_BYTES_CHECK (b, 4);
300 r = (b->ptr[0] << 24) | (b->ptr[1] << 16) | (b->ptr[2] << 8) | b->ptr[3];
301 b->ptr += 4;
303 return r;
306 float
307 swfdec_bits_get_float (SwfdecBits * b)
309 union {
310 gint32 i;
311 float f;
312 } conv;
314 SWFDEC_BYTES_CHECK (b, 4);
316 conv.i = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
317 b->ptr += 4;
319 return conv.f;
322 /* fixup mad byte ordering of doubles in flash files.
323 * If little endian x86 byte order is 0 1 2 3 4 5 6 7 and PPC32 byte order is
324 * 7 6 5 4 3 2 1 0, then Flash uses 4 5 6 7 0 1 2 3.
325 * If your architecture has a different byte ordering for storing doubles,
326 * this conversion function will fail. To find out your byte ordering, you can
327 * use this command line:
328 * python -c "import struct; print struct.unpack('8c', struct.pack('d', 7.949928895127363e-275))"
330 double
331 swfdec_bits_get_double (SwfdecBits * b)
333 union {
334 guint32 i[2];
335 double d;
336 } conv;
338 SWFDEC_BYTES_CHECK (b, 8);
340 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
341 conv.i[1] = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
342 conv.i[0] = (b->ptr[7] << 24) | (b->ptr[6] << 16) | (b->ptr[5] << 8) | b->ptr[4];
343 #else
344 conv.i[0] = (b->ptr[3] << 24) | (b->ptr[2] << 16) | (b->ptr[1] << 8) | b->ptr[0];
345 conv.i[1] = (b->ptr[7] << 24) | (b->ptr[6] << 16) | (b->ptr[5] << 8) | b->ptr[4];
346 #endif
347 b->ptr += 8;
349 return conv.d;
352 double
353 swfdec_bits_get_bdouble (SwfdecBits * b)
355 union {
356 double d;
357 guint64 u64;
358 } u;
360 SWFDEC_BYTES_CHECK (b, 8);
362 memcpy (&u.u64, b->ptr, 8);
363 b->ptr += 8;
365 u.u64 = GUINT64_FROM_BE (u.u64);
367 return u.d;
370 void
371 swfdec_bits_syncbits (SwfdecBits * b)
373 if (b->idx) {
374 b->ptr++;
375 b->idx = 0;
379 void
380 swfdec_bits_get_color_transform (SwfdecBits * bits, SwfdecColorTransform * ct)
382 int has_add;
383 int has_mult;
384 int n_bits;
386 ct->mask = FALSE;
387 has_add = swfdec_bits_getbit (bits);
388 has_mult = swfdec_bits_getbit (bits);
389 n_bits = swfdec_bits_getbits (bits, 4);
390 if (has_mult) {
391 ct->ra = swfdec_bits_getsbits (bits, n_bits);
392 ct->ga = swfdec_bits_getsbits (bits, n_bits);
393 ct->ba = swfdec_bits_getsbits (bits, n_bits);
394 ct->aa = swfdec_bits_getsbits (bits, n_bits);
395 } else {
396 ct->ra = 256;
397 ct->ga = 256;
398 ct->ba = 256;
399 ct->aa = 256;
401 if (has_add) {
402 ct->rb = swfdec_bits_getsbits (bits, n_bits);
403 ct->gb = swfdec_bits_getsbits (bits, n_bits);
404 ct->bb = swfdec_bits_getsbits (bits, n_bits);
405 ct->ab = swfdec_bits_getsbits (bits, n_bits);
406 } else {
407 ct->rb = 0;
408 ct->gb = 0;
409 ct->bb = 0;
410 ct->ab = 0;
412 swfdec_bits_syncbits (bits);
415 void
416 swfdec_bits_get_matrix (SwfdecBits * bits, cairo_matrix_t *matrix,
417 cairo_matrix_t *inverse)
419 int has_scale;
420 int has_rotate;
421 int n_translate_bits;
423 has_scale = swfdec_bits_getbit (bits);
424 if (has_scale) {
425 int n_scale_bits = swfdec_bits_getbits (bits, 5);
426 matrix->xx = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_scale_bits));
427 matrix->yy = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_scale_bits));
429 SWFDEC_LOG ("scalefactors: x = %d/65536, y = %d/65536",
430 SWFDEC_DOUBLE_TO_FIXED (matrix->xx), SWFDEC_DOUBLE_TO_FIXED (matrix->yy));
431 } else {
432 SWFDEC_LOG ("no scalefactors given");
433 matrix->xx = 1.0;
434 matrix->yy = 1.0;
436 has_rotate = swfdec_bits_getbit (bits);
437 if (has_rotate) {
438 int n_rotate_bits = swfdec_bits_getbits (bits, 5);
439 matrix->yx = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_rotate_bits));
440 matrix->xy = SWFDEC_FIXED_TO_DOUBLE (swfdec_bits_getsbits (bits, n_rotate_bits));
442 SWFDEC_LOG ("skew: xy = %d/65536, yx = %d/65536",
443 SWFDEC_DOUBLE_TO_FIXED (matrix->xy),
444 SWFDEC_DOUBLE_TO_FIXED (matrix->yx));
445 } else {
446 SWFDEC_LOG ("no rotation");
447 matrix->xy = 0;
448 matrix->yx = 0;
450 n_translate_bits = swfdec_bits_getbits (bits, 5);
451 matrix->x0 = swfdec_bits_getsbits (bits, n_translate_bits);
452 matrix->y0 = swfdec_bits_getsbits (bits, n_translate_bits);
454 swfdec_matrix_ensure_invertible (matrix, inverse);
455 swfdec_bits_syncbits (bits);
458 static const char *
459 swfdec_bits_skip_string (SwfdecBits *bits)
461 char *s;
462 const char *end;
463 guint len;
465 SWFDEC_BYTES_CHECK (bits, 1);
466 end = memchr (bits->ptr, 0, bits->end - bits->ptr);
467 if (end == NULL) {
468 SWFDEC_ERROR ("could not parse string");
469 return NULL;
472 len = end - (const char *) bits->ptr;
473 s = (char *) bits->ptr;
474 bits->ptr += len + 1;
476 return s;
480 * swfdec_bits_get_string:
481 * @bits: a #SwfdecBits
482 * @version: Flash player version
484 * Prior to Flash 6, strings used to be encoded as LATIN1. Since Flash 6,
485 * strings are encoded as UTF-8. This version does that check automatically
486 * and converts strings to UTF-8.
488 * Returns: a UTF-8 encoded string or %NULL on error
490 char *
491 swfdec_bits_get_string (SwfdecBits *bits, guint version)
493 const char *s;
495 g_return_val_if_fail (bits != NULL, NULL);
497 s = swfdec_bits_skip_string (bits);
498 if (s == NULL)
499 return NULL;
501 if (version < 6) {
502 char *ret = g_convert (s, -1, "UTF-8", "LATIN1", NULL , NULL, NULL);
503 if (ret == NULL)
504 g_warning ("Could not convert string from LATIN1 to UTF-8");
505 return ret;
506 } else {
507 if (!g_utf8_validate (s, -1, NULL)) {
508 SWFDEC_ERROR ("parsed string is not valid utf-8");
509 return NULL;
511 return g_strdup (s);
516 * swfdec_bits_skip_bytes:
517 * @bits: a #SwfdecBits
518 * @n_bytes: number of bytes to skip
520 * Skips up to @n_bytes bytes in @bits. If not enough bytes are available,
521 * only the available amount is skipped and a warning is printed.
523 * Returns: the number of bytes actually skipped
525 guint
526 swfdec_bits_skip_bytes (SwfdecBits *bits, guint n_bytes)
528 g_assert (bits->idx == 0);
529 if ((guint) (bits->end - bits->ptr) < n_bytes) {
530 SWFDEC_WARNING ("supposed to skip %u bytes, but only %td available",
531 n_bytes, bits->end - bits->ptr);
532 n_bytes = bits->end - bits->ptr;
534 bits->ptr += n_bytes;
535 return n_bytes;
539 * swfdec_bits_get_string_length:
540 * @bits: a #SwfdecBits
541 * @len: number of bytes to read
542 * @version: flash version number
544 * Reads the next @len bytes (not characters!) into a string and validates
545 * its encoding is correct based on supplied version number.
547 * Returns: a new UTF-8 string or %NULL on error
549 char *
550 swfdec_bits_get_string_length (SwfdecBits * bits, guint len, guint version)
552 char *ret;
554 if (len == 0)
555 return g_strdup ("");
556 SWFDEC_BYTES_CHECK (bits, len);
558 ret = g_strndup ((char *) bits->ptr, len);
559 bits->ptr += len;
561 if (version < 6) {
562 char *tmp = g_convert (ret, -1, "UTF-8", "LATIN1", NULL , NULL, NULL);
563 g_free(ret);
564 ret = tmp;
565 } else {
566 if (!g_utf8_validate (ret, -1, NULL)) {
567 SWFDEC_ERROR ("parsed string is not valid utf-8");
568 g_free (ret);
569 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 void
602 swfdec_bits_get_rect (SwfdecBits * bits, SwfdecRect *rect)
604 int nbits;
606 nbits = swfdec_bits_getbits (bits, 5);
607 rect->x0 = swfdec_bits_getsbits (bits, nbits);
608 rect->x1 = swfdec_bits_getsbits (bits, nbits);
609 rect->y0 = swfdec_bits_getsbits (bits, nbits);
610 rect->y1 = swfdec_bits_getsbits (bits, nbits);
612 swfdec_bits_syncbits (bits);
616 * swfdec_bits_get_buffer:
617 * @bits: #SwfdecBits
618 * @len: length of buffer or -1 for maximum
620 * Gets the contents of the next @len bytes of @bits and buts them in a new
621 * subbuffer.
623 * Returns: the new #SwfdecBuffer or %NULL if the requested amount of data
624 * isn't available
626 SwfdecBuffer *
627 swfdec_bits_get_buffer (SwfdecBits *bits, int len)
629 SwfdecBuffer *buffer;
631 g_return_val_if_fail (len >= -1, NULL);
633 if (len >= 0) {
634 SWFDEC_BYTES_CHECK (bits, (guint) len);
635 } else {
636 g_assert (bits->idx == 0);
637 len = bits->end - bits->ptr;
638 g_assert (len >= 0);
640 if (len == 0)
641 return swfdec_buffer_new (0);
642 if (bits->buffer) {
643 buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
644 } else {
645 buffer = swfdec_buffer_new (len);
646 memcpy (buffer->data, bits->ptr, len);
648 bits->ptr += len;
649 return buffer;
652 static void *
653 swfdec_bits_zalloc (void *opaque, guint items, guint size)
655 return g_malloc (items * size);
658 static void
659 swfdec_bits_zfree (void *opaque, void *addr)
661 g_free (addr);
665 * swfdec_bits_decompress:
666 * @bits: a #SwfdecBits
667 * @compressed: number of bytes to decompress or -1 for the rest
668 * @decompressed: number of bytes to expect in the decompressed result or -1
669 * if unknown
671 * Decompresses the next @compressed bytes of data in @bits using the zlib
672 * decompression algorithm and returns the result in a buffer. If @decompressed
673 * was set and not enough data is available, the return buffer will be filled
674 * up with 0 bytes.
676 * Returns: a new #SwfdecBuffer containing the decompressed data or NULL on
677 * failure. If @decompressed &gt; 0, the buffer's length will be @decompressed.
679 SwfdecBuffer *
680 swfdec_bits_decompress (SwfdecBits *bits, int compressed, int decompressed)
682 z_stream z = { 0, };
683 SwfdecBuffer *buffer;
684 int result;
686 g_return_val_if_fail (bits != NULL, NULL);
687 g_return_val_if_fail (compressed >= -1, NULL);
688 g_return_val_if_fail (decompressed > 0 || decompressed == -1, NULL);
690 /* prepare the bits structure */
691 if (compressed > 0) {
692 SWFDEC_BYTES_CHECK (bits, (guint) compressed);
693 } else {
694 g_assert (bits->idx == 0);
695 compressed = bits->end - bits->ptr;
696 g_assert (compressed >= 0);
698 if (compressed == 0)
699 return NULL;
701 z.zalloc = swfdec_bits_zalloc;
702 z.zfree = swfdec_bits_zfree;
703 z.opaque = NULL;
704 z.next_in = (Bytef *) bits->ptr;
705 z.avail_in = compressed;
706 result = inflateInit (&z);
707 if (result != Z_OK) {
708 SWFDEC_ERROR ("Error initialising zlib: %d %s", result, z.msg ? z.msg : "");
709 goto fail;
711 buffer = swfdec_buffer_new (decompressed > 0 ? decompressed : compressed * 2);
712 z.next_out = buffer->data;
713 z.avail_out = buffer->length;
714 while (TRUE) {
715 result = inflate (&z, decompressed > 0 ? Z_FINISH : 0);
716 switch (result) {
717 case Z_STREAM_END:
718 goto out;
719 case Z_OK:
720 if (decompressed < 0) {
721 buffer->data = g_realloc (buffer->data, buffer->length + compressed);
722 buffer->length += compressed;
723 z.next_out = buffer->data + z.total_out;
724 z.avail_out = buffer->length - z.total_out;
725 goto out;
727 /* else fall through */
728 default:
729 SWFDEC_ERROR ("error decompressing data: inflate returned %d %s",
730 result, z.msg ? z.msg : "");
731 swfdec_buffer_unref (buffer);
732 goto fail;
735 out:
736 if (decompressed < 0) {
737 buffer->length = z.total_out;
738 } else {
739 if (buffer->length > z.total_out) {
740 SWFDEC_WARNING ("Not enough data decompressed: %lu instead of %"G_GSIZE_FORMAT" expected",
741 (gulong) z.total_out, buffer->length);
742 memset (buffer->data + z.total_out, 0, buffer->length - z.total_out);
745 result = inflateEnd (&z);
746 if (result != Z_OK) {
747 SWFDEC_ERROR ("error in inflateEnd: %d %s", result, z.msg ? z.msg : "");
749 bits->ptr += compressed;
750 return buffer;
752 fail:
753 bits->ptr += compressed;
754 return NULL;