static gboolean swfdec_rectangle_from_as_object (SwfdecRectangle *rect, SwfdecAsObject *object) { SwfdecAsValue *val; SwfdecAsContext *cx = swfdec_gc_object_get_context (object); /* FIXME: This function is untested */ val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_x); if (val) rect->x = swfdec_as_value_to_integer (cx, val); else rect->x = 0; val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_y); if (val) rect->y = swfdec_as_value_to_integer (cx, val); else rect->y = 0; val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_width); if (val) rect->width = swfdec_as_value_to_integer (cx, val); else rect->width = 0; val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_height); if (val) rect->height = swfdec_as_value_to_integer (cx, val); else rect->height = 0; return rect->width > 0 && rect->height > 0; }
static void swfdec_point_from_as_object (int *x, int *y, SwfdecAsObject *object) { SwfdecAsValue *val; SwfdecAsContext *cx = swfdec_gc_object_get_context (object); /* FIXME: This function is untested */ val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_x); *x = swfdec_as_value_to_integer (cx, val); val = swfdec_as_object_peek_variable (object, SWFDEC_AS_STR_y); *y = swfdec_as_value_to_integer (cx, val); }
void swfdec_as_array_splice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { gint32 length, start_index, num_remove, num_add, at_end; SwfdecAsArray *array_new; if (object == NULL || SWFDEC_IS_MOVIE (object) || argc == 0) return; length = swfdec_as_array_length (object); start_index = swfdec_as_value_to_integer (cx, &argv[0]); if (start_index < 0) start_index = length + start_index; start_index = CLAMP (start_index, 0, length); if (argc > 1) { int tmp = swfdec_as_value_to_integer (cx, &argv[1]); if (tmp < 0) return; num_remove = MIN (tmp, length - start_index); } else { num_remove = length - start_index; } num_add = (argc > 2 ? argc - 2 : 0); at_end = length - num_remove - start_index; /* create return value */ array_new = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx)); swfdec_as_array_append_array_range (array_new, object, start_index, num_remove); SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (array_new)); /* move old data to the right spot */ swfdec_as_array_move_range (object, start_index + num_remove, at_end, start_index + num_add); if (num_remove > at_end) { swfdec_as_array_remove_range (object, start_index + at_end + num_add, length - (start_index + at_end + num_add)); } if (num_remove > num_add) swfdec_as_array_set_length_object (object, length - (num_remove - num_add)); /* add new data */ if (argc > 2) swfdec_as_array_set_range (object, start_index, argc - 2, argv + 2); }
static void swfdec_as_array_set (SwfdecAsObject *object, const char *variable, const SwfdecAsValue *val, guint flags) { gboolean indexvar; char *end; gint32 l; // we have to allow negative values here l = strtoul (variable, &end, 10); indexvar = (*end == 0); // if we changed to smaller length, destroy all values that are outside it // if (SWFDEC_AS_ARRAY (object)->check_length && !swfdec_strcmp (swfdec_gc_object_get_context (object)->version, variable, SWFDEC_AS_STR_length)) { gint32 length_old = swfdec_as_array_length (object); gint32 length_new = swfdec_as_value_to_integer (swfdec_gc_object_get_context (object), val); length_new = MAX (0, length_new); if (length_old > length_new) { swfdec_as_array_remove_range (object, length_new, length_old - length_new); } } SWFDEC_AS_OBJECT_CLASS (swfdec_as_array_parent_class)->set (object, variable, val, flags); // if we added new value outside the current length, set a bigger length if (indexvar && ++l > swfdec_as_array_length_as_integer (object)) swfdec_as_array_set_length_object (object, l); }
void swfdec_as_array_sort (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { guint pos; SortOption options; SwfdecAsFunction *custom_function; if (object == NULL || SWFDEC_IS_MOVIE (object)) return; pos = 0; if (argc > pos && !SWFDEC_AS_VALUE_IS_NUMBER (&argv[pos])) { SwfdecAsFunction *fun; if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[pos]) || !SWFDEC_IS_AS_FUNCTION ( fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&argv[pos]))) return; custom_function = fun; pos++; } else { custom_function = NULL; } if (argc > pos) { options = swfdec_as_value_to_integer (cx, &argv[pos]) & MASK_SORT_OPTION; } else { options = 0; } swfdec_as_array_do_sort (cx, object, &options, custom_function, NULL, ret); }
// inner function for swfdec_as_array_sort_compare static int swfdec_as_array_sort_compare_values (SwfdecAsContext *cx, const SwfdecAsValue *a, const SwfdecAsValue *b, SortOption options, SwfdecAsFunction *custom_function) { int retval; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), 0); g_return_val_if_fail (SWFDEC_IS_AS_VALUE (a), 0); g_return_val_if_fail (SWFDEC_IS_AS_VALUE (b), 0); g_return_val_if_fail (custom_function == NULL || SWFDEC_IS_AS_FUNCTION (custom_function), 0); if (custom_function != NULL) { SwfdecAsValue argv[2] = { *a, *b }; SwfdecAsValue ret; SwfdecAsContext *context = swfdec_gc_object_get_context (custom_function); swfdec_as_function_call (custom_function, NULL, 2, argv, &ret); retval = swfdec_as_value_to_integer (context, &ret); } else if (options & SORT_OPTION_NUMERIC && (SWFDEC_AS_VALUE_IS_NUMBER (a) || SWFDEC_AS_VALUE_IS_NUMBER (b)) && !SWFDEC_AS_VALUE_IS_UNDEFINED (a) && !SWFDEC_AS_VALUE_IS_UNDEFINED (b)) { if (!SWFDEC_AS_VALUE_IS_NUMBER (a)) { retval = 1; } else if (!SWFDEC_AS_VALUE_IS_NUMBER (b)) { retval = -1; } else { double an = swfdec_as_value_to_number (cx, a); double bn = swfdec_as_value_to_number (cx, b); retval = (an < bn ? -1 : (an > bn ? 1 : 0)); } } else { // can't pass swfdec_as_value_to_string calls directly to compare // functions, since the order of these is important const char *a_str = swfdec_as_value_to_string (cx, a); const char *b_str = swfdec_as_value_to_string (cx, b); if (options & SORT_OPTION_CASEINSENSITIVE) { retval = g_strcasecmp (a_str, b_str); } else { retval = strcmp (a_str, b_str); } } if (options & SORT_OPTION_DESCENDING) retval = -retval; return retval; }
void swfdec_as_array_slice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { gint32 length, start_index, num; SwfdecAsArray *array_new; if (object == NULL || SWFDEC_IS_MOVIE (object)) return; length = swfdec_as_array_length (object); if (argc > 0) { start_index = swfdec_as_value_to_integer (cx, &argv[0]); if (start_index < 0) start_index = length + start_index; start_index = CLAMP (start_index, 0, length); } else { start_index = 0; } if (argc > 1) { gint32 endIndex = swfdec_as_value_to_integer (cx, &argv[1]); if (endIndex < 0) endIndex = length + endIndex; endIndex = CLAMP (endIndex, start_index, length); num = endIndex - start_index; } else { num = length - start_index; } array_new = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx)); if (array_new == NULL) return; swfdec_as_array_append_array_range (array_new, object, start_index, num); SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (array_new)); }
static gint32 swfdec_as_array_length_as_integer (SwfdecAsObject *object) { SwfdecAsValue val; gint32 length; g_return_val_if_fail (object != NULL, 0); swfdec_as_object_get_variable (object, SWFDEC_AS_STR_length, &val); length = swfdec_as_value_to_integer (swfdec_gc_object_get_context (object), &val); return length; }
void broadcastMessage (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { SwfdecAsValue val; SwfdecAsObject *listeners, *o; gint i, length; const char *name; GSList *list = NULL, *walk; if (object == NULL) return; if (argc < 1) return; name = swfdec_as_value_to_string (cx, argv[0]); argv += 1; argc--; swfdec_as_object_get_variable (object, SWFDEC_AS_STR__listeners, &val); if (!SWFDEC_AS_VALUE_IS_COMPOSITE (val)) return; listeners = SWFDEC_AS_VALUE_GET_COMPOSITE (val); swfdec_as_object_get_variable (listeners, SWFDEC_AS_STR_length, &val); length = swfdec_as_value_to_integer (cx, val); /* return undefined if we won't try to call anything */ if (length <= 0) return; /* FIXME: solve this wth foreach, so it gets faster for weird cases */ for (i = 0; i < length; i++) { swfdec_as_object_get_variable (listeners, swfdec_as_integer_to_string (cx, i), &val); o = swfdec_as_value_to_object (cx, val); if (o == NULL) continue; list = g_slist_prepend (list, o); } if (list == NULL) return; list = g_slist_reverse (list); for (walk = list; walk; walk = walk->next) { swfdec_as_object_call (walk->data, name, argc, argv, &val); } g_slist_free (list); SWFDEC_AS_VALUE_SET_BOOLEAN (ret, TRUE); }
void swfdec_as_function_apply (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { SwfdecAsValue *argv_pass = NULL; int length = 0; SwfdecAsFunction *fun; SwfdecAsObject *thisp = NULL; SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_FUNCTION, &fun, "|O", &thisp); if (thisp == NULL) thisp = swfdec_as_object_new_empty (cx); if (argc > 1 && SWFDEC_AS_VALUE_IS_OBJECT (&argv[1])) { int i; SwfdecAsObject *array; SwfdecAsValue val; array = SWFDEC_AS_VALUE_GET_OBJECT (&argv[1]); swfdec_as_object_get_variable (array, SWFDEC_AS_STR_length, &val); length = swfdec_as_value_to_integer (cx, &val); if (length > 0) { /* FIXME: find a smarter way to do this, like providing argv not as an array */ if (!swfdec_as_context_try_use_mem (cx, sizeof (SwfdecAsValue) * length)) { swfdec_as_context_abort (cx, "too many arguments to Function.apply"); return; } argv_pass = g_malloc (sizeof (SwfdecAsValue) * length); for (i = 0; i < length; i++) { swfdec_as_object_get_variable (array, swfdec_as_integer_to_string (cx, i), &argv_pass[i]); } } else { length = 0; } } swfdec_as_function_call (fun, thisp, length, argv_pass, ret); if (argv_pass) { swfdec_as_context_unuse_mem (cx, sizeof (SwfdecAsValue) * length); g_free (argv_pass); } }
/** * swfdec_as_native_function_checkv: * @cx: a #SwfdecAsContext * @object: this object passed to the native function * @type: expected type of @object * @result: pointer to variable taking cast result of @object * @argc: count of arguments passed to the function * @argv: arguments passed to the function * @args: argument conversion string * @varargs: pointers to variables taking converted arguments * * This is the valist version of swfdec_as_native_function_check(). See that * function for details. * * Returns: %TRUE if the conversion succeeded, %FALSE otherwise **/ gboolean swfdec_as_native_function_checkv (SwfdecAsContext *cx, SwfdecAsObject *object, GType type, gpointer *result, guint argc, SwfdecAsValue *argv, const char *args, va_list varargs) { guint i; gboolean optional = FALSE; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), FALSE); g_return_val_if_fail (type == 0 || result != NULL, FALSE); /* check that we got a valid type */ if (type) { if (G_TYPE_CHECK_INSTANCE_TYPE (object, type)) { *result = object; } else if (object && G_TYPE_CHECK_INSTANCE_TYPE (object->relay, type)) { *result = object->relay; } else { return FALSE; } } for (i = 0; *args && i < argc; i++, args++) { switch (*args) { case 'v': { SwfdecAsValue *val = va_arg (varargs, SwfdecAsValue *); *val = argv[i]; } break; case 'b': { gboolean *b = va_arg (varargs, gboolean *); *b = swfdec_as_value_to_boolean (cx, argv[i]); } break; case 'i': { int *j = va_arg (varargs, int *); *j = swfdec_as_value_to_integer (cx, argv[i]); } break; case 'm': case 'M': { SwfdecMovie *m; SwfdecMovie **arg = va_arg (varargs, SwfdecMovie **); if (SWFDEC_AS_VALUE_IS_MOVIE (argv[i])) { m = SWFDEC_AS_VALUE_GET_MOVIE (argv[i]); } else { m = NULL; } if (m == NULL && *args != 'M') return FALSE; *arg = m; } break; case 'n': { double *d = va_arg (varargs, double *); *d = swfdec_as_value_to_number (cx, argv[i]); } break; case 's': { const char **s = va_arg (varargs, const char **); *s = swfdec_as_value_to_string (cx, argv[i]); } break; case 'o': case 'O': { SwfdecAsObject **o = va_arg (varargs, SwfdecAsObject **); *o = swfdec_as_value_to_object (cx, argv[i]); if (*o == NULL && *args != 'O') return FALSE; } break; case '|': g_return_val_if_fail (optional == FALSE, FALSE); optional = TRUE; i--; break; default: g_warning ("'%c' is not a valid type conversion", *args); return FALSE; } } if (*args && !optional && *args != '|') return FALSE; return TRUE; }