summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2008-08-26 11:15:43 +0200
committerBenjamin Otte <otte@gnome.org>2008-08-26 11:15:43 +0200
commit4dcba6e8e49fd209469945cbfd91793d23635d7f (patch)
treeddce086f74540ff657baee477771ab2e41d19ea7
parent99fc769d0a73d48f7190e316d426dec1488cd1ac (diff)
split ABC value handling into its own file and implement a bunch of functions for it
-rw-r--r--swfdec/swfdec_abc_global.c2
-rw-r--r--swfdec/swfdec_abc_interpret.c180
-rw-r--r--swfdec/swfdec_abc_multiname.c17
-rw-r--r--swfdec/swfdec_abc_multiname.h6
-rw-r--r--swfdec/swfdec_abc_object.c70
-rw-r--r--swfdec/swfdec_abc_object.h3
-rw-r--r--swfdec/swfdec_abc_pool.c17
-rw-r--r--swfdec/swfdec_abc_value.c144
-rw-r--r--swfdec/swfdec_abc_value.h9
9 files changed, 405 insertions, 43 deletions
diff --git a/swfdec/swfdec_abc_global.c b/swfdec/swfdec_abc_global.c
index afcea5ff..517e103a 100644
--- a/swfdec/swfdec_abc_global.c
+++ b/swfdec/swfdec_abc_global.c
@@ -315,7 +315,7 @@ swfdec_abc_global_get_builtin_class (SwfdecAbcGlobal *global, guint id)
traits = global->pool->instances[id];
- swfdec_abc_multiname_init (&mn, traits->name, traits->ns, NULL);
+ swfdec_abc_multiname_init (&mn, traits->ns, traits->name);
SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (global));
if (!swfdec_abc_object_get_variable (swfdec_gc_object_get_context (global),
&val, &mn, &val))
diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index 2fb94f5a..c892970b 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -747,6 +747,17 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
val = swfdec_as_stack_peek (context, 1);
*swfdec_as_stack_push (context) = *val;
continue;
+ case SWFDEC_ABC_OPCODE_EQUALS:
+ {
+ SwfdecAbcComparison comp;
+ val = swfdec_as_stack_peek (context, 2);
+ comp = swfdec_abc_value_equals (context, val, swfdec_as_stack_pop (context));
+ if (comp == SWFDEC_ABC_COMPARE_THROWN)
+ break;
+ g_assert (comp == SWFDEC_ABC_COMPARE_EQUAL || comp == SWFDEC_ABC_COMPARE_NOT_EQUAL);
+ SWFDEC_AS_VALUE_SET_BOOLEAN (val, comp == SWFDEC_ABC_COMPARE_EQUAL);
+ }
+ continue;
case SWFDEC_ABC_OPCODE_FIND_PROP_STRICT:
case SWFDEC_ABC_OPCODE_FIND_PROPERTY:
i = swfdec_bits_get_vu32 (&bits);
@@ -819,6 +830,150 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
break;
*val = SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (val))->slots[i - 1];
continue;
+ case SWFDEC_ABC_OPCODE_IFEQ:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_equals (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFFALSE:
+ i = swfdec_bits_get_s24 (&bits);
+ if (!swfdec_as_value_to_boolean (context, swfdec_as_stack_pop (context)) &&
+ !swfdec_abc_interpret_jump (context, &bits, i))
+ break;
+ continue;
+ case SWFDEC_ABC_OPCODE_IFGE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFGT:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFLE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFLT:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFNE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_equals (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_NOT_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFNLE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFNLT:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp != SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFNGE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFNGT:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp != SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFSTRICTEQ:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_strict_equals (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFSTRICTNE:
+ {
+ SwfdecAbcComparison comp;
+ i = swfdec_bits_get_s24 (&bits);
+ val = swfdec_as_stack_pop (context);
+ comp = swfdec_abc_value_strict_equals (context, swfdec_as_stack_pop (context), val);
+ if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+ (comp == SWFDEC_ABC_COMPARE_NOT_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+ break;
+ }
+ continue;
+ case SWFDEC_ABC_OPCODE_IFTRUE:
+ i = swfdec_bits_get_s24 (&bits);
+ if (swfdec_as_value_to_boolean (context, swfdec_as_stack_pop (context)) &&
+ !swfdec_abc_interpret_jump (context, &bits, i))
+ break;
+ continue;
case SWFDEC_ABC_OPCODE_INIT_PROPERTY:
{
SwfdecAbcTraits *traits;
@@ -1016,6 +1171,15 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
!swfdec_abc_object_set_variable (context, swfdec_as_stack_pop (context), &mn, val))
break;
continue;
+ case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
+ {
+ SwfdecAbcComparison comp;
+ val = swfdec_as_stack_peek (context, 2);
+ comp = swfdec_abc_value_strict_equals (context, val, swfdec_as_stack_pop (context));
+ g_assert (comp == SWFDEC_ABC_COMPARE_EQUAL || comp == SWFDEC_ABC_COMPARE_NOT_EQUAL);
+ SWFDEC_AS_VALUE_SET_BOOLEAN (val, comp == SWFDEC_ABC_COMPARE_EQUAL);
+ }
+ continue;
case SWFDEC_ABC_OPCODE_SWAP:
{
SwfdecAsValue tmp = *swfdec_as_stack_peek (context, 1);
@@ -1065,7 +1229,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
case SWFDEC_ABC_OPCODE_DOUBLE_TO_ATOM:
case SWFDEC_ABC_OPCODE_DXNS:
case SWFDEC_ABC_OPCODE_DXNS_LATE:
- case SWFDEC_ABC_OPCODE_EQUALS:
case SWFDEC_ABC_OPCODE_ESC_XATTR:
case SWFDEC_ABC_OPCODE_ESC_XELEM:
case SWFDEC_ABC_OPCODE_FIND_DEF:
@@ -1076,20 +1239,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
case SWFDEC_ABC_OPCODE_GREATER_THAN:
case SWFDEC_ABC_OPCODE_HAS_NEXT:
case SWFDEC_ABC_OPCODE_HAS_NEXT2:
- case SWFDEC_ABC_OPCODE_IFEQ:
- case SWFDEC_ABC_OPCODE_IFFALSE:
- case SWFDEC_ABC_OPCODE_IFGE:
- case SWFDEC_ABC_OPCODE_IFGT:
- case SWFDEC_ABC_OPCODE_IFLE:
- case SWFDEC_ABC_OPCODE_IFLT:
- case SWFDEC_ABC_OPCODE_IFNE:
- case SWFDEC_ABC_OPCODE_IFNLE:
- case SWFDEC_ABC_OPCODE_IFNLT:
- case SWFDEC_ABC_OPCODE_IFNGE:
- case SWFDEC_ABC_OPCODE_IFNGT:
- case SWFDEC_ABC_OPCODE_IFSTRICTEQ:
- case SWFDEC_ABC_OPCODE_IFSTRICTNE:
- case SWFDEC_ABC_OPCODE_IFTRUE:
case SWFDEC_ABC_OPCODE_IN:
case SWFDEC_ABC_OPCODE_INC_LOCAL:
case SWFDEC_ABC_OPCODE_INCLOCAL_I:
@@ -1119,7 +1268,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
case SWFDEC_ABC_OPCODE_SET_GLOBAL_SLOT:
case SWFDEC_ABC_OPCODE_SET_SLOT:
case SWFDEC_ABC_OPCODE_SET_SUPER:
- case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
case SWFDEC_ABC_OPCODE_SWEEP:
case SWFDEC_ABC_OPCODE_THROW:
case SWFDEC_ABC_OPCODE_TIMESTAMP:
diff --git a/swfdec/swfdec_abc_multiname.c b/swfdec/swfdec_abc_multiname.c
index 346fce66..e7de0acf 100644
--- a/swfdec/swfdec_abc_multiname.c
+++ b/swfdec/swfdec_abc_multiname.c
@@ -30,15 +30,26 @@
#include "swfdec_debug.h"
void
-swfdec_abc_multiname_init (SwfdecAbcMultiname *multi, const char *name,
- SwfdecAbcNamespace *ns, SwfdecAbcNsSet *set)
+swfdec_abc_multiname_init (SwfdecAbcMultiname *multi, SwfdecAbcNamespace *ns,
+ const char *name)
{
g_return_if_fail (multi != NULL);
- g_return_if_fail (ns == NULL || set == NULL);
g_return_if_fail (ns == NULL || ns == SWFDEC_ABC_MULTINAME_ANY || SWFDEC_IS_ABC_NAMESPACE (ns));
multi->name = name;
multi->ns = ns;
+ multi->nsset = NULL;
+}
+
+void
+swfdec_abc_multiname_init_set (SwfdecAbcMultiname *multi, SwfdecAbcNsSet *set,
+ const char *name)
+{
+ g_return_if_fail (multi != NULL);
+ g_return_if_fail (set != NULL);
+
+ multi->name = name;
+ multi->ns = NULL;
multi->nsset = set;
}
diff --git a/swfdec/swfdec_abc_multiname.h b/swfdec/swfdec_abc_multiname.h
index 4ed31868..e2c5bc79 100644
--- a/swfdec/swfdec_abc_multiname.h
+++ b/swfdec/swfdec_abc_multiname.h
@@ -35,9 +35,11 @@ struct _SwfdecAbcMultiname {
};
void swfdec_abc_multiname_init (SwfdecAbcMultiname * multi,
- const char * name,
SwfdecAbcNamespace * ns,
- SwfdecAbcNsSet * set);
+ const char * name);
+void swfdec_abc_multiname_init_set (SwfdecAbcMultiname * multi,
+ SwfdecAbcNsSet * set,
+ const char * name);
void swfdec_abc_multiname_init_from_string (SwfdecAbcMultiname * multi,
SwfdecAsContext * context,
const char * string);
diff --git a/swfdec/swfdec_abc_object.c b/swfdec/swfdec_abc_object.c
index 3216505c..5147fd8d 100644
--- a/swfdec/swfdec_abc_object.c
+++ b/swfdec/swfdec_abc_object.c
@@ -29,7 +29,9 @@
#include "swfdec_abc_multiname.h"
#include "swfdec_abc_scope_chain.h"
#include "swfdec_abc_traits.h"
+#include "swfdec_abc_value.h"
#include "swfdec_as_context.h"
+#include "swfdec_as_strings.h"
#include "swfdec_debug.h"
enum {
@@ -420,3 +422,71 @@ swfdec_abc_object_call_variable (SwfdecAsContext *context, const SwfdecAsValue *
}
}
}
+
+gboolean
+swfdec_abc_object_default_value (SwfdecAbcObject *object, SwfdecAsValue *default_value)
+{
+ SwfdecAsContext *context;
+ SwfdecAbcMultiname mn;
+ SwfdecAsValue val;
+
+ g_return_val_if_fail (SWFDEC_IS_ABC_OBJECT (object), FALSE);
+ g_return_val_if_fail (default_value != NULL, FALSE);
+
+ context = swfdec_gc_object_get_context (object);
+
+ /* first, call toString - if it returns a primitive, return it */
+ swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_valueOf);
+ SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+ if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, default_value))
+ return FALSE;
+ if (!SWFDEC_AS_VALUE_IS_OBJECT (default_value))
+ return TRUE;
+
+ /* second, call valueOf - if it returns a primitive, return it */
+ swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_toString);
+ SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+ if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, default_value))
+ return FALSE;
+ if (!SWFDEC_AS_VALUE_IS_OBJECT (default_value))
+ return TRUE;
+
+ /* Object doesn't want to be a string, complain */
+ swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR,
+ "Cannot convert %s to primitive.", object->traits->name);
+ SWFDEC_AS_VALUE_SET_UNDEFINED (default_value);
+ return FALSE;
+}
+
+const char *
+swfdec_abc_object_to_string (SwfdecAbcObject *object)
+{
+ SwfdecAsContext *context;
+ SwfdecAbcMultiname mn;
+ SwfdecAsValue val, ret;
+
+ g_return_val_if_fail (SWFDEC_IS_ABC_OBJECT (object), FALSE);
+
+ context = swfdec_gc_object_get_context (object);
+
+ /* first, call toString - if it returns a primitive, return it */
+ swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_toString);
+ SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+ if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, &ret))
+ return NULL;
+ if (!SWFDEC_AS_VALUE_IS_OBJECT (&ret))
+ return swfdec_abc_value_to_string (context, &ret);
+
+ /* second, call valueOf - if it returns a primitive, return it */
+ swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_valueOf);
+ SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+ if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, &ret))
+ return NULL;
+ if (!SWFDEC_AS_VALUE_IS_OBJECT (&ret))
+ return swfdec_abc_value_to_string (context, &ret);
+
+ /* Object doesn't want to be a string, complain */
+ swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR,
+ "Cannot convert %s to primitive.", object->traits->name);
+ return NULL;
+}
diff --git a/swfdec/swfdec_abc_object.h b/swfdec/swfdec_abc_object.h
index 70f81fbc..06395c48 100644
--- a/swfdec/swfdec_abc_object.h
+++ b/swfdec/swfdec_abc_object.h
@@ -64,8 +64,7 @@ SwfdecAbcObject * swfdec_abc_object_new_from_class(SwfdecAbcClass * classp);
gboolean swfdec_abc_object_default_value (SwfdecAbcObject * object,
SwfdecAsValue * default_value);
-gboolean swfdec_abc_object_to_string (SwfdecAbcObject * object,
- SwfdecAsValue * string);
+const char * swfdec_abc_object_to_string (SwfdecAbcObject * object);
gboolean swfdec_abc_object_call (SwfdecAbcObject * object,
guint argc,
SwfdecAsValue * argv,
diff --git a/swfdec/swfdec_abc_pool.c b/swfdec/swfdec_abc_pool.c
index dbd9422a..176ce416 100644
--- a/swfdec/swfdec_abc_pool.c
+++ b/swfdec/swfdec_abc_pool.c
@@ -335,9 +335,8 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
if (nameid >= pool->n_strings)
THROW (pool, "Cpool index %u is out of range %u.", nameid, pool->n_strings);
swfdec_abc_multiname_init (&pool->multinames[i],
- nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
nsid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->namespaces[nsid],
- NULL);
+ nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
break;
case 0x10:
SWFDEC_FIXME ("implement attributes");
@@ -346,14 +345,14 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
if (nameid >= pool->n_strings)
THROW (pool, "Cpool index %u is out of range %u.", nameid, pool->n_strings);
swfdec_abc_multiname_init (&pool->multinames[i],
- nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
- NULL, NULL);
+ NULL,
+ nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
break;
case 0x12:
SWFDEC_FIXME ("implement attributes");
case 0x11:
swfdec_abc_multiname_init (&pool->multinames[i],
- NULL, NULL, NULL);
+ NULL, NULL);
break;
case 0x0E:
SWFDEC_FIXME ("implement attributes");
@@ -364,9 +363,8 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
READ_U30 (nsid, bits);
if (nsid >= pool->n_nssets)
THROW (pool, "Cpool index %u is out of range %u.", nsid, pool->n_nssets);
- swfdec_abc_multiname_init (&pool->multinames[i],
- nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
- NULL, pool->nssets[nsid]);
+ swfdec_abc_multiname_init_set (&pool->multinames[i], pool->nssets[nsid],
+ nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
break;
case 0x1C:
SWFDEC_FIXME ("implement attributes");
@@ -374,8 +372,7 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
READ_U30 (nsid, bits);
if (nsid >= pool->n_nssets)
THROW (pool, "Cpool index %u is out of range %u.", nsid, pool->n_nssets);
- swfdec_abc_multiname_init (&pool->multinames[i],
- NULL, NULL, pool->nssets[nsid]);
+ swfdec_abc_multiname_init_set (&pool->multinames[i], pool->nssets[nsid], NULL);
break;
default:
THROW (pool, "Cpool entry %u is wrong type.", i);
diff --git a/swfdec/swfdec_abc_value.c b/swfdec/swfdec_abc_value.c
index dc58fc68..e36c4dc2 100644
--- a/swfdec/swfdec_abc_value.c
+++ b/swfdec/swfdec_abc_value.c
@@ -119,7 +119,7 @@ swfdec_abc_value_to_number (SwfdecAsContext *context, const SwfdecAsValue *value
gboolean
swfdec_abc_value_to_primitive (SwfdecAsValue *dest, const SwfdecAsValue *src)
{
- g_return_val_if_fail (SWFDEC_IS_AS_VALUE (dest), FALSE);
+ g_return_val_if_fail (dest != NULL, FALSE);
g_return_val_if_fail (SWFDEC_IS_AS_VALUE (src), FALSE);
if (SWFDEC_AS_VALUE_IS_OBJECT (src)) {
@@ -149,13 +149,7 @@ swfdec_abc_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value
case SWFDEC_AS_TYPE_STRING:
return SWFDEC_AS_VALUE_GET_STRING (value);
case SWFDEC_AS_TYPE_OBJECT:
- {
- SwfdecAsValue tmp;
- if (!swfdec_abc_object_to_string (
- SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)), &tmp))
- return SWFDEC_AS_STR_EMPTY;
- return swfdec_abc_value_to_string (context, &tmp);
- }
+ return swfdec_abc_object_to_string (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)));
case SWFDEC_AS_TYPE_NAMESPACE:
return SWFDEC_AS_VALUE_GET_NAMESPACE (value)->uri;
case SWFDEC_AS_TYPE_INT:
@@ -222,6 +216,8 @@ swfdec_abc_value_compare (SwfdecAsContext *context, const SwfdecAsValue *lval,
!swfdec_abc_value_to_primitive (&rtmp, rval))
return SWFDEC_ABC_COMPARE_THROWN;
+ /* FIXME: need special code for XMLList here */
+
if (SWFDEC_AS_VALUE_IS_STRING (&ltmp) && SWFDEC_AS_VALUE_IS_STRING (&rtmp)) {
int comp = strcmp (SWFDEC_AS_VALUE_GET_STRING (&ltmp),
SWFDEC_AS_VALUE_GET_STRING (&rtmp));
@@ -238,3 +234,135 @@ swfdec_abc_value_compare (SwfdecAsContext *context, const SwfdecAsValue *lval,
}
}
+SwfdecAbcComparison
+swfdec_abc_value_equals (SwfdecAsContext *context, const SwfdecAsValue *lval,
+ const SwfdecAsValue *rval)
+{
+ SwfdecAsValue tmp;
+ SwfdecAsValueType ltype, rtype;
+
+ g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_ABC_COMPARE_UNDEFINED);
+ g_return_val_if_fail (lval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+ g_return_val_if_fail (rval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+
+ ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
+ rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
+
+ /* FIXME: need special code for XMLList here */
+
+ if (ltype == rtype) {
+ switch (ltype) {
+ case SWFDEC_AS_TYPE_UNDEFINED:
+ case SWFDEC_AS_TYPE_NULL:
+ return SWFDEC_ABC_COMPARE_EQUAL;
+ case SWFDEC_AS_TYPE_BOOLEAN:
+ return SWFDEC_AS_VALUE_GET_BOOLEAN (lval) == SWFDEC_AS_VALUE_GET_BOOLEAN (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_NUMBER:
+ return SWFDEC_AS_VALUE_GET_NUMBER (lval) == SWFDEC_AS_VALUE_GET_NUMBER (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_STRING:
+ return SWFDEC_AS_VALUE_GET_STRING (lval) == SWFDEC_AS_VALUE_GET_STRING (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_OBJECT:
+ /* FIXME: Need special code for QName and XMLList here */
+ return SWFDEC_AS_VALUE_GET_OBJECT (lval) == SWFDEC_AS_VALUE_GET_OBJECT (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_NAMESPACE:
+ return swfdec_abc_namespace_equal (SWFDEC_AS_VALUE_GET_NAMESPACE (lval),
+ SWFDEC_AS_VALUE_GET_NAMESPACE (rval)) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_INT:
+ default:
+ g_assert_not_reached ();
+ return SWFDEC_ABC_COMPARE_UNDEFINED;
+ }
+ }
+
+ if ((ltype == SWFDEC_AS_TYPE_UNDEFINED && rtype == SWFDEC_AS_TYPE_NULL) ||
+ (ltype == SWFDEC_AS_TYPE_NULL && rtype == SWFDEC_AS_TYPE_UNDEFINED))
+ return SWFDEC_ABC_COMPARE_EQUAL;
+
+ if (ltype == SWFDEC_AS_TYPE_NUMBER && rtype == SWFDEC_AS_TYPE_STRING) {
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+ return swfdec_abc_value_equals (context, lval, &tmp);
+ }
+ if (ltype == SWFDEC_AS_TYPE_STRING && rtype == SWFDEC_AS_TYPE_NUMBER) {
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+ return swfdec_abc_value_equals (context, &tmp, rval);
+ }
+
+ /* FIXME: need special code for XMLList here */
+
+ if (ltype == SWFDEC_AS_TYPE_BOOLEAN) {
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+ return swfdec_abc_value_equals (context, &tmp, rval);
+ }
+ if (rtype == SWFDEC_AS_TYPE_BOOLEAN) {
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+ return swfdec_abc_value_equals (context, lval, &tmp);
+ }
+
+ if (rtype == SWFDEC_AS_TYPE_OBJECT &&
+ (ltype == SWFDEC_AS_TYPE_NUMBER || ltype == SWFDEC_AS_TYPE_STRING)) {
+ if (!swfdec_abc_object_default_value (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (rval)), &tmp))
+ return SWFDEC_ABC_COMPARE_THROWN;
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+ return swfdec_abc_value_equals (context, lval, &tmp);
+ }
+ if (ltype == SWFDEC_AS_TYPE_OBJECT &&
+ (rtype == SWFDEC_AS_TYPE_NUMBER || rtype == SWFDEC_AS_TYPE_STRING)) {
+ if (!swfdec_abc_object_default_value (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (lval)), &tmp))
+ return SWFDEC_ABC_COMPARE_THROWN;
+ SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+ return swfdec_abc_value_equals (context, &tmp, rval);
+ }
+
+ return SWFDEC_ABC_COMPARE_NOT_EQUAL;
+}
+
+SwfdecAbcComparison
+swfdec_abc_value_strict_equals (SwfdecAsContext *context, const SwfdecAsValue *lval,
+ const SwfdecAsValue *rval)
+{
+ SwfdecAsValueType ltype, rtype;
+
+ g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_ABC_COMPARE_UNDEFINED);
+ g_return_val_if_fail (lval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+ g_return_val_if_fail (rval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+
+ ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
+ rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
+
+ /* FIXME: need special code for XMLList here */
+
+ if (ltype == rtype) {
+ switch (ltype) {
+ case SWFDEC_AS_TYPE_UNDEFINED:
+ case SWFDEC_AS_TYPE_NULL:
+ return SWFDEC_ABC_COMPARE_EQUAL;
+ case SWFDEC_AS_TYPE_BOOLEAN:
+ return SWFDEC_AS_VALUE_GET_BOOLEAN (lval) == SWFDEC_AS_VALUE_GET_BOOLEAN (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_NUMBER:
+ return SWFDEC_AS_VALUE_GET_NUMBER (lval) == SWFDEC_AS_VALUE_GET_NUMBER (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_STRING:
+ return SWFDEC_AS_VALUE_GET_STRING (lval) == SWFDEC_AS_VALUE_GET_STRING (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_OBJECT:
+ /* FIXME: Need special code for XMLList here */
+ return SWFDEC_AS_VALUE_GET_OBJECT (lval) == SWFDEC_AS_VALUE_GET_OBJECT (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_NAMESPACE:
+ return SWFDEC_AS_VALUE_GET_NAMESPACE (lval) == SWFDEC_AS_VALUE_GET_NAMESPACE (rval) ?
+ SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+ case SWFDEC_AS_TYPE_INT:
+ default:
+ g_assert_not_reached ();
+ return SWFDEC_ABC_COMPARE_UNDEFINED;
+ }
+ }
+ return SWFDEC_ABC_COMPARE_NOT_EQUAL;
+}
+
diff --git a/swfdec/swfdec_abc_value.h b/swfdec/swfdec_abc_value.h
index dfccd872..f6b9ee1f 100644
--- a/swfdec/swfdec_abc_value.h
+++ b/swfdec/swfdec_abc_value.h
@@ -28,10 +28,11 @@ G_BEGIN_DECLS
typedef enum {
SWFDEC_ABC_COMPARE_UNDEFINED,
+ SWFDEC_ABC_COMPARE_NOT_EQUAL = SWFDEC_ABC_COMPARE_UNDEFINED,
SWFDEC_ABC_COMPARE_THROWN,
SWFDEC_ABC_COMPARE_LOWER,
SWFDEC_ABC_COMPARE_EQUAL,
- SWFDEC_ABC_COMPARE_GREATER
+ SWFDEC_ABC_COMPARE_GREATER,
} SwfdecAbcComparison;
gboolean swfdec_abc_value_to_boolean (SwfdecAsContext * context,
@@ -51,6 +52,12 @@ const char * swfdec_abc_value_get_type_name (const SwfdecAsValue * value);
SwfdecAbcComparison swfdec_abc_value_compare (SwfdecAsContext * context,
const SwfdecAsValue * lval,
const SwfdecAsValue * rval);
+SwfdecAbcComparison swfdec_abc_value_equals (SwfdecAsContext * context,
+ const SwfdecAsValue * lval,
+ const SwfdecAsValue * rval);
+SwfdecAbcComparison swfdec_abc_value_strict_equals (SwfdecAsContext * context,
+ const SwfdecAsValue * lval,
+ const SwfdecAsValue * rval);
G_END_DECLS