make swfdec_as_object_mark() only mark if not marked yet
[swfdec.git] / swfdec / swfdec_as_number.c
blobfae652f4efba9ad536a9b6008542b24401dd3577
1 /* Swfdec
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.
8 *
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
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <math.h>
26 #include "swfdec_as_number.h"
27 #include "swfdec_as_context.h"
28 #include "swfdec_as_frame.h"
29 #include "swfdec_as_internal.h"
30 #include "swfdec_as_native_function.h"
31 #include "swfdec_as_strings.h"
32 #include "swfdec_debug.h"
34 G_DEFINE_TYPE (SwfdecAsNumber, swfdec_as_number, SWFDEC_TYPE_AS_RELAY)
36 static void
37 swfdec_as_number_class_init (SwfdecAsNumberClass *klass)
41 static void
42 swfdec_as_number_init (SwfdecAsNumber *number)
46 /*** AS CODE ***/
48 SWFDEC_AS_NATIVE (106, 2, swfdec_as_number_construct)
49 void
50 swfdec_as_number_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
51 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
53 double d;
55 if (argc > 0) {
56 d = swfdec_as_value_to_number (cx, &argv[0]);
57 } else {
58 d = 0;
61 if (swfdec_as_context_is_constructing (cx)) {
62 SwfdecAsNumber *num = g_object_new (SWFDEC_TYPE_AS_NUMBER, "context", cx, NULL);
63 num->number = d;
64 swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (num));
65 SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
66 } else {
67 swfdec_as_value_set_number (cx, ret, d);
71 // code adapted from Tamarin's convertDoubleToStringRadix in MathUtils.cpp
72 // 2008-02-16
73 static const char *
74 swfdec_as_number_toStringRadix (SwfdecAsContext *context, double value,
75 int radix)
77 gboolean negative;
78 GString *str;
79 double left = floor (value);
81 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_AS_STR_NaN);
82 g_return_val_if_fail (radix >= 2 && radix <= 36, SWFDEC_AS_STR_NaN);
83 g_return_val_if_fail (!isinf (value) && !isnan (value), SWFDEC_AS_STR_NaN);
85 if (value < 0) {
86 negative = TRUE;
87 value = -value;
88 } else {
89 negative = FALSE;
92 if (value < 1)
93 return SWFDEC_AS_STR_0;
95 str = g_string_new ("");
97 left = floor (value);
99 while (left != 0)
101 double val = left;
102 left = floor (left / radix);
103 val -= (left * radix);
105 g_string_prepend_c (str,
106 (val < 10 ? ((int)val + '0') : ((int)val + ('a' - 10))));
109 if (negative)
110 g_string_prepend_c (str, '-');
112 return swfdec_as_context_give_string (context, g_string_free (str, FALSE));
115 SWFDEC_AS_NATIVE (106, 1, swfdec_as_number_toString)
116 void
117 swfdec_as_number_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
118 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
120 SwfdecAsNumber *num;
121 SwfdecAsValue val;
122 const char *s;
123 int radix = 10;
125 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_NUMBER, &num, "|i", &radix);
127 if (radix == 10 || radix < 2 || radix > 36 || isinf (num->number) ||
128 isnan (num->number)) {
129 swfdec_as_value_set_number (cx, &val, num->number);
130 s = swfdec_as_value_to_string (cx, val);
131 } else {
132 s = swfdec_as_number_toStringRadix (cx, num->number, radix);
134 SWFDEC_AS_VALUE_SET_STRING (ret, s);
137 SWFDEC_AS_NATIVE (106, 0, swfdec_as_number_valueOf)
138 void
139 swfdec_as_number_valueOf (SwfdecAsContext *cx, SwfdecAsObject *object,
140 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
142 SwfdecAsNumber *num;
144 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_NUMBER, &num, "");
146 swfdec_as_value_set_number (cx, ret, num->number);
149 // only available as ASnative
150 SWFDEC_AS_NATIVE (3, 1, swfdec_as_number_old_constructor)
151 void
152 swfdec_as_number_old_constructor (SwfdecAsContext *cx, SwfdecAsObject *object,
153 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
155 SWFDEC_STUB ("old 'Number' function (only available as ASnative)");
158 // only available as ASnative
159 SWFDEC_AS_NATIVE (3, 4, swfdec_as_number_old_toString)
160 void
161 swfdec_as_number_old_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
162 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
164 SWFDEC_STUB ("old 'Number.prototype.toString' function (only available as ASnative)");