diff options
author | Benjamin Otte <otte@gnome.org> | 2008-08-26 11:15:43 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2008-08-26 11:15:43 +0200 |
commit | 4dcba6e8e49fd209469945cbfd91793d23635d7f (patch) | |
tree | ddce086f74540ff657baee477771ab2e41d19ea7 | |
parent | 99fc769d0a73d48f7190e316d426dec1488cd1ac (diff) |
split ABC value handling into its own file and implement a bunch of functions for it
-rw-r--r-- | swfdec/swfdec_abc_global.c | 2 | ||||
-rw-r--r-- | swfdec/swfdec_abc_interpret.c | 180 | ||||
-rw-r--r-- | swfdec/swfdec_abc_multiname.c | 17 | ||||
-rw-r--r-- | swfdec/swfdec_abc_multiname.h | 6 | ||||
-rw-r--r-- | swfdec/swfdec_abc_object.c | 70 | ||||
-rw-r--r-- | swfdec/swfdec_abc_object.h | 3 | ||||
-rw-r--r-- | swfdec/swfdec_abc_pool.c | 17 | ||||
-rw-r--r-- | swfdec/swfdec_abc_value.c | 144 | ||||
-rw-r--r-- | swfdec/swfdec_abc_value.h | 9 |
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 (<mp) && SWFDEC_AS_VALUE_IS_STRING (&rtmp)) { int comp = strcmp (SWFDEC_AS_VALUE_GET_STRING (<mp), 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 |