2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
27 #include "swfdec_as_string.h"
28 #include "swfdec_as_array.h"
29 #include "swfdec_as_context.h"
30 #include "swfdec_as_internal.h"
31 #include "swfdec_as_native_function.h"
32 #include "swfdec_as_strings.h"
33 #include "swfdec_debug.h"
35 G_DEFINE_TYPE (SwfdecAsString
, swfdec_as_string
, SWFDEC_TYPE_AS_RELAY
)
38 swfdec_as_string_do_mark (SwfdecGcObject
*object
)
40 SwfdecAsString
*string
= SWFDEC_AS_STRING (object
);
42 swfdec_as_string_mark (string
->string
);
44 SWFDEC_GC_OBJECT_CLASS (swfdec_as_string_parent_class
)->mark (object
);
48 swfdec_as_string_class_init (SwfdecAsStringClass
*klass
)
50 SwfdecGcObjectClass
*gc_class
= SWFDEC_GC_OBJECT_CLASS (klass
);
52 gc_class
->mark
= swfdec_as_string_do_mark
;
56 swfdec_as_string_init (SwfdecAsString
*string
)
58 string
->string
= SWFDEC_AS_STR_EMPTY
;
63 #define SWFDEC_AS_STRING_CHECK(result,...) G_STMT_START {\
66 SWFDEC_AS_VALUE_SET_COMPOSITE (&_tmp, object); \
67 *(result) = swfdec_as_value_to_string (cx, _tmp);\
69 *(result) = SWFDEC_AS_STR_undefined; \
71 if (!swfdec_as_native_function_check (cx, object, 0, NULL, argc, argv, __VA_ARGS__)) \
76 swfdec_as_str_nth_char (const char *s
, guint n
)
79 s
= g_utf8_next_char (s
);
83 SWFDEC_AS_NATIVE (251, 9, swfdec_as_string_lastIndexOf
)
85 swfdec_as_string_lastIndexOf (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
86 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
92 SWFDEC_AS_STRING_CHECK (&string
, "s", &s
);
95 int offset
= swfdec_as_value_to_integer (cx
, argv
[1]);
98 *ret
= swfdec_as_value_from_integer (cx
, -1);
103 while (*tmp
&& offset
-- != 0)
104 tmp
= g_utf8_next_char (tmp
);
109 s
= g_strrstr_len (string
, len
, s
);
111 *ret
= swfdec_as_value_from_integer (cx
, g_utf8_pointer_to_offset (string
, s
));
113 *ret
= swfdec_as_value_from_integer (cx
, -1);
117 SWFDEC_AS_NATIVE (251, 8, swfdec_as_string_indexOf
)
119 swfdec_as_string_indexOf (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
120 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
123 int offset
=0, len
, i
=-1;
124 const char *s
, *t
= NULL
;
126 SWFDEC_AS_STRING_CHECK (&string
, "s", &s
);
129 offset
= swfdec_as_value_to_integer (cx
, argv
[1]);
132 len
= g_utf8_strlen (string
, -1);
134 t
= strstr (g_utf8_offset_to_pointer (string
, offset
), s
);
137 i
= g_utf8_pointer_to_offset (string
, t
);
140 *ret
= swfdec_as_value_from_integer (cx
, i
);
143 SWFDEC_AS_NATIVE (251, 5, swfdec_as_string_charAt
)
145 swfdec_as_string_charAt (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
146 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
152 SWFDEC_AS_STRING_CHECK (&string
, "i", &i
);
155 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_EMPTY
);
158 s
= swfdec_as_str_nth_char (string
, i
);
160 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_EMPTY
);
163 t
= g_utf8_next_char (s
);
164 s
= swfdec_as_context_give_string (cx
, g_strndup (s
, t
- s
));
165 SWFDEC_AS_VALUE_SET_STRING (ret
, s
);
168 SWFDEC_AS_NATIVE (251, 6, swfdec_as_string_charCodeAt
)
170 swfdec_as_string_charCodeAt (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
171 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
178 SWFDEC_AS_STRING_CHECK (&string
, "i", &i
);
181 *ret
= swfdec_as_value_from_number (cx
, NAN
);
184 s
= swfdec_as_str_nth_char (string
, i
);
186 if (cx
->version
> 5) {
187 *ret
= swfdec_as_value_from_number (cx
, NAN
);
189 *ret
= swfdec_as_value_from_integer (cx
, 0);
193 c
= g_utf8_get_char (s
);
194 *ret
= swfdec_as_value_from_number (cx
, c
);
198 swfdec_as_string_fromCharCode_5 (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
199 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
203 GError
*error
= NULL
;
205 GByteArray
*array
= g_byte_array_new ();
208 for (i
= 0; i
< argc
; i
++) {
209 c
= ((guint
) swfdec_as_value_to_integer (cx
, argv
[i
])) % 65536;
212 g_byte_array_append (array
, &append
, 1);
215 g_byte_array_append (array
, &append
, 1);
218 /* FIXME: are these the correct charset names? */
219 s
= g_convert ((char *) array
->data
, array
->len
, "UTF-8", "LATIN1", NULL
, NULL
, &error
);
225 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, s
));
227 SWFDEC_ERROR ("%s", error
->message
);
228 g_error_free (error
);
230 g_byte_array_free (array
, TRUE
);
234 swfdec_as_string_fromCharCode_6 (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
235 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
241 GError
*error
= NULL
;
246 chars
= g_new (gunichar
, argc
);
248 for (i
= 0; i
< argc
; i
++) {
249 chars
[i
] = ((guint
) swfdec_as_value_to_integer (cx
, argv
[i
])) % 65536;
252 s
= g_ucs4_to_utf8 (chars
, argc
, NULL
, NULL
, &error
);
254 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_get_string (cx
, s
));
257 SWFDEC_ERROR ("%s", error
->message
);
258 g_error_free (error
);
265 SWFDEC_AS_NATIVE (251, 14, swfdec_as_string_fromCharCode
)
267 swfdec_as_string_fromCharCode (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
268 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
270 if (cx
->version
<= 5) {
271 swfdec_as_string_fromCharCode_5 (cx
, object
, argc
, argv
, ret
);
273 swfdec_as_string_fromCharCode_6 (cx
, object
, argc
, argv
, ret
);
277 SWFDEC_AS_NATIVE (251, 0, swfdec_as_string_construct
)
279 swfdec_as_string_construct (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
280 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
285 s
= swfdec_as_value_to_string (cx
, argv
[0]);
287 s
= SWFDEC_AS_STR_EMPTY
;
290 if (swfdec_as_context_is_constructing (cx
)) {
291 SwfdecAsString
*string
= g_object_new (SWFDEC_TYPE_AS_STRING
, "context", cx
, NULL
);
295 swfdec_as_object_set_relay (object
, SWFDEC_AS_RELAY (string
));
297 val
= swfdec_as_value_from_integer (cx
, g_utf8_strlen (string
->string
, -1));
298 swfdec_as_object_set_variable_and_flags (object
, SWFDEC_AS_STR_length
,
299 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
);
301 SWFDEC_AS_VALUE_SET_OBJECT (ret
, object
);
303 SWFDEC_AS_VALUE_SET_STRING (ret
, s
);
307 SWFDEC_AS_NATIVE (251, 2, swfdec_as_string_toString
)
309 swfdec_as_string_toString (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
310 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
312 SwfdecAsString
*string
;
314 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_STRING
, &string
, "");
316 SWFDEC_AS_VALUE_SET_STRING (ret
, string
->string
);
319 SWFDEC_AS_NATIVE (251, 1, swfdec_as_string_valueOf
)
321 swfdec_as_string_valueOf (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
322 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
326 SWFDEC_AS_STRING_CHECK (&string
, "");
328 SWFDEC_AS_VALUE_SET_STRING (ret
, string
);
332 swfdec_as_string_split_5 (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
333 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
337 const char *str
, *end
, *delim
;
340 SWFDEC_AS_STRING_CHECK (&str
, "");
342 arr
= swfdec_as_array_new (cx
);
343 SWFDEC_AS_VALUE_SET_OBJECT (ret
, arr
);
344 /* hi, i'm the special case */
345 if (argc
< 1 || SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[0])) {
346 delim
= SWFDEC_AS_STR_COMMA
;
348 delim
= swfdec_as_value_to_string (cx
, argv
[0]);
350 if (delim
== SWFDEC_AS_STR_EMPTY
) {
351 SWFDEC_AS_VALUE_SET_STRING (&val
, str
);
352 swfdec_as_array_push (arr
, &val
);
355 if (argc
> 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[1])) {
356 swfdec_as_value_to_string (cx
, argv
[0]);
357 count
= swfdec_as_value_to_integer (cx
, argv
[1]);
363 if (str
== SWFDEC_AS_STR_EMPTY
|| delim
[1] != 0) {
364 SWFDEC_AS_VALUE_SET_STRING (&val
, str
);
365 swfdec_as_array_push (arr
, &val
);
369 end
= strchr (str
, delim
[0]);
371 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_get_string (cx
, str
));
372 swfdec_as_array_push (arr
, &val
);
375 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_give_string (cx
, g_strndup (str
, end
- str
)));
376 swfdec_as_array_push (arr
, &val
);
383 swfdec_as_string_split_6 (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
384 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
388 const char *str
, *end
, *delim
;
392 SWFDEC_AS_STRING_CHECK (&str
, "");
394 arr
= swfdec_as_array_new (cx
);
395 SWFDEC_AS_VALUE_SET_OBJECT (ret
, arr
);
396 /* hi, i'm the special case */
397 if (argc
< 1 || SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[0])) {
398 SWFDEC_AS_VALUE_SET_STRING (&val
, str
);
399 swfdec_as_array_push (arr
, &val
);
402 delim
= swfdec_as_value_to_string (cx
, argv
[0]);
403 if (str
== SWFDEC_AS_STR_EMPTY
) {
404 if (strlen (delim
) > 0) {
405 SWFDEC_AS_VALUE_SET_STRING (&val
, str
);
406 swfdec_as_array_push (arr
, &val
);
410 if (argc
> 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[1]))
411 count
= swfdec_as_value_to_integer (cx
, argv
[1]);
416 len
= strlen (delim
);
418 if (delim
== SWFDEC_AS_STR_EMPTY
) {
424 end
= strstr (str
, delim
);
426 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_get_string (cx
, str
));
427 swfdec_as_array_push (arr
, &val
);
431 SWFDEC_AS_VALUE_SET_STRING (&val
, swfdec_as_context_give_string (cx
, g_strndup (str
, end
- str
)));
432 swfdec_as_array_push (arr
, &val
);
438 SWFDEC_AS_NATIVE (251, 12, swfdec_as_string_split
)
440 swfdec_as_string_split (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
441 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
443 if (cx
->version
<= 5) {
444 swfdec_as_string_split_5 (cx
, object
, argc
, argv
, ret
);
446 swfdec_as_string_split_6 (cx
, object
, argc
, argv
, ret
);
450 SWFDEC_AS_NATIVE (251, 10, swfdec_as_string_slice
)
452 swfdec_as_string_slice (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
453 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
455 int start
, end
, length
;
458 SWFDEC_AS_STRING_CHECK (&str
, "i", &start
);
460 length
= g_utf8_strlen (str
, -1);
464 start
= CLAMP (start
, 0, length
);
467 end
= swfdec_as_value_to_integer (cx
, argv
[1]);
470 end
= CLAMP (end
, start
, length
);
475 SWFDEC_AS_VALUE_SET_STRING (ret
,
476 swfdec_as_str_sub (cx
, str
, start
, end
- start
));
479 SWFDEC_AS_NATIVE (251, 7, swfdec_as_string_concat
)
481 swfdec_as_string_concat (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
482 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
488 SWFDEC_AS_STRING_CHECK (&s
, "");
490 string
= g_string_new (s
);
492 for (i
= 0; i
< argc
; i
++) {
493 string
= g_string_append (string
, swfdec_as_value_to_string (cx
, argv
[i
]));
496 SWFDEC_AS_VALUE_SET_STRING (ret
,
497 swfdec_as_context_give_string (cx
, g_string_free (string
, FALSE
)));
501 swfdec_as_str_sub (SwfdecAsContext
*cx
, const char *str
, guint offset
, guint len
)
505 str
= g_utf8_offset_to_pointer (str
, offset
);
506 end
= g_utf8_offset_to_pointer (str
, len
);
507 str
= swfdec_as_context_give_string (cx
, g_strndup (str
, end
- str
));
511 SWFDEC_AS_NATIVE (251, 13, swfdec_as_string_substr
)
513 swfdec_as_string_substr (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
514 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
519 SWFDEC_AS_STRING_CHECK (&string
, "i", &from
);
521 len
= g_utf8_strlen (string
, -1);
523 if (argc
> 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[1])) {
524 to
= swfdec_as_value_to_integer (cx
, argv
[1]);
533 if (from
< 0 && to
>= -from
)
541 from
= CLAMP (from
, 0, len
);
542 to
= CLAMP (to
, 0, len
- from
);
543 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_str_sub (cx
, string
, from
, to
));
546 SWFDEC_AS_NATIVE (251, 11, swfdec_as_string_substring
)
548 swfdec_as_string_substring (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
549 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
554 SWFDEC_AS_STRING_CHECK (&string
, "i", &from
);
556 len
= g_utf8_strlen (string
, -1);
557 if (argc
> 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[1])) {
558 to
= swfdec_as_value_to_integer (cx
, argv
[1]);
562 from
= MAX (from
, 0);
564 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_EMPTY
);
567 to
= CLAMP (to
, 0, len
);
573 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_str_sub (cx
, string
, from
, to
- from
));
576 SWFDEC_AS_NATIVE (251, 4, swfdec_as_string_toLowerCase
)
578 swfdec_as_string_toLowerCase (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
579 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
584 SWFDEC_AS_STRING_CHECK (&string
, "");
586 s
= g_utf8_strdown (string
, -1);
587 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, s
));
590 SWFDEC_AS_NATIVE (251, 3, swfdec_as_string_toUpperCase
)
592 swfdec_as_string_toUpperCase (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
593 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
598 SWFDEC_AS_STRING_CHECK (&string
, "");
600 s
= g_utf8_strup (string
, -1);
601 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, s
));
604 // only available as ASnative
605 SWFDEC_AS_NATIVE (102, 1, swfdec_as_string_old_toLowerCase
)
607 swfdec_as_string_old_toLowerCase (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
608 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
613 SWFDEC_AS_STRING_CHECK (&string
, "");
615 s
= g_ascii_strdown (string
, -1);
616 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, s
));
619 // only available as ASnative
620 SWFDEC_AS_NATIVE (102, 0, swfdec_as_string_old_toUpperCase
)
622 swfdec_as_string_old_toUpperCase (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
623 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
628 SWFDEC_AS_STRING_CHECK (&string
, "");
630 s
= g_ascii_strup (string
, -1);
631 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, s
));
634 /* escape and unescape are implemented here so the mad string functions share the same place */
637 swfdec_as_string_unescape_5 (SwfdecAsContext
*cx
, const char *msg
)
640 char cur
= 0; /* currently decoded character */
642 guint decoding
= 0; /* set if we're decoding a %XY string */
644 /* attention: c is a char* */
645 #define APPEND(chr) G_STMT_START{ \
646 g_byte_array_append (array, (guchar *) chr, 1); \
648 in
= s
= g_convert (msg
, -1, "LATIN1", "UTF-8", NULL
, NULL
, NULL
);
650 SWFDEC_FIXME ("%s can not be converted to utf8 - is this Flash 5 or what?", msg
);
653 array
= g_byte_array_new ();
657 if (*s
>= '0' && *s
<= '9') {
658 cur
= cur
* 16 + *s
- '0';
659 } else if (*s
>= 'A' && *s
<= 'F') {
660 cur
= cur
* 16 + *s
- 'A' + 10;
661 } else if (*s
>= 'a' && *s
<= 'f') {
662 cur
= cur
* 16 + *s
- 'a' + 10;
672 } else if (*s
== '%') {
674 } else if (*s
== '+') {
683 if (array
->len
== 0) {
684 g_byte_array_free (array
, TRUE
);
688 g_byte_array_append (array
, (guchar
*) &cur
, 1);
689 out
= g_convert ((char *) array
->data
, -1, "UTF-8", "LATIN1", NULL
, NULL
, NULL
);
690 g_byte_array_free (array
, TRUE
);
694 g_warning ("can't convert %s to UTF-8", msg
);
696 return g_strdup ("");
702 swfdec_as_string_escape (SwfdecAsContext
*cx
, const char *s
)
707 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx
), NULL
);
708 g_return_val_if_fail (s
!= NULL
, NULL
);
710 array
= g_byte_array_new ();
711 if (cx
->version
<= 5) {
712 in
= g_convert (s
, -1, "LATIN1", "UTF-8", NULL
, NULL
, NULL
);
714 SWFDEC_FIXME ("%s can not be converted to utf8 - is this Flash 5 or what?", s
);
721 if ((*s
>= '0' && *s
<= '9') ||
722 (*s
>= 'A' && *s
<= 'Z') ||
723 (*s
>= 'a' && *s
<= 'z')) {
724 g_byte_array_append (array
, (guchar
*) s
, 1);
726 guchar add
[3] = { '%', 0, 0 };
727 add
[1] = (guchar
) *s
/ 16;
728 add
[2] = (guchar
) *s
% 16;
729 add
[1] += add
[1] < 10 ? '0' : ('A' - 10);
730 add
[2] += add
[2] < 10 ? '0' : ('A' - 10);
731 g_byte_array_append (array
, add
, 3);
735 g_byte_array_append (array
, (guchar
*) s
, 1);
737 return (char *) g_byte_array_free (array
, FALSE
);
740 SWFDEC_AS_NATIVE (100, 0, swfdec_as_string_escape_internal
)
742 swfdec_as_string_escape_internal (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
743 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
748 SWFDEC_AS_CHECK (0, NULL
, "s", &s
);
750 result
= swfdec_as_string_escape (cx
, s
);
751 if (result
!= NULL
) {
752 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_get_string (cx
, result
));
755 SWFDEC_AS_VALUE_SET_UNDEFINED (ret
);
760 swfdec_as_string_unescape_6 (SwfdecAsContext
*cx
, const char *s
)
764 char cur
= 0; /* currently decoded character */
765 guint decoding
= 0; /* set if we're decoding a %XY string */
766 guint utf8left
= 0; /* how many valid utf8 chars are still required */
767 const guchar invalid
[3] = { 0xEF, 0xBF, 0xBD };
769 /* attention: c is a char* */
770 /* can't use break inside G_STMT_START */
771 #define APPEND(chr) G_STMT_START{ \
774 if ((c & 0xC0) == 0x80) { \
775 g_byte_array_append (array, &c, 1); \
778 guint __len = array->len - 1; \
779 while ((array->data[__len] & 0xC0) != 0xC0) \
781 g_byte_array_set_size (array, __len); \
782 g_byte_array_append (array, invalid, 3); \
787 g_byte_array_append (array, &c, 1); \
788 } else if (c < 0xC0) { \
789 guchar __foo = 0xC2; \
790 g_byte_array_append (array, &__foo, 1); \
791 g_byte_array_append (array, &c, 1); \
792 } else if (c > 0xF7) { \
795 g_byte_array_append (array, &c, 1); \
796 utf8left = (c < 0xE0) ? 1 : ((c < 0xF0) ? 2 : 3); \
800 array
= g_byte_array_new ();
805 if (*s
>= '0' && *s
<= '9') {
806 cur
= cur
* 16 + *s
- '0';
807 } else if (*s
>= 'A' && *s
<= 'F') {
808 cur
= cur
* 16 + *s
- 'A' + 10;
809 } else if (*s
>= 'a' && *s
<= 'f') {
810 cur
= cur
* 16 + *s
- 'a' + 10;
814 if ((guchar
) *s
> 0x7F) {
823 } else if (*s
== '%') {
825 } else if (*s
== '+') {
835 /* loop for break statement in APPEND macro */
837 guint __len
= array
->len
- 1;
838 while ((array
->data
[__len
] & 0xC0) != 0xC0)
840 g_byte_array_set_size (array
, __len
);
842 g_byte_array_append (array
, (guchar
*) &cur
, 1);
843 if (g_utf8_validate ((char *) array
->data
, -1, NULL
)) {
844 return (char *) g_byte_array_free (array
, FALSE
);
846 g_warning ("%s unescaped is invalid UTF-8", msg
);
847 g_byte_array_free (array
, TRUE
);
848 return g_strdup ("");
854 swfdec_as_string_unescape (SwfdecAsContext
*context
, const char *string
)
856 if (context
->version
< 6) {
857 return swfdec_as_string_unescape_5 (context
, string
);
859 return swfdec_as_string_unescape_6 (context
, string
);
863 SWFDEC_AS_NATIVE (100, 1, swfdec_as_string_unescape_internal
)
865 swfdec_as_string_unescape_internal (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
866 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
871 SWFDEC_AS_CHECK (0, NULL
, "s", &s
);
873 result
= swfdec_as_string_unescape (cx
, s
);
874 if (result
!= NULL
) {
875 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_get_string (cx
, result
));
878 SWFDEC_AS_VALUE_SET_UNDEFINED (ret
);
882 // only available as ASnative
883 SWFDEC_AS_NATIVE (3, 0, swfdec_as_string_old_constructor
)
885 swfdec_as_string_old_constructor (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
886 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
888 SWFDEC_STUB ("old 'String' function (only available as ASnative)");