void swfdec_as_function_init_context (SwfdecAsContext *context) { SwfdecAsObject *function, *proto; SwfdecAsValue val; g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); function = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_Function, NULL)); swfdec_as_object_set_variable_flags (context->global, SWFDEC_AS_STR_Function, SWFDEC_AS_VARIABLE_VERSION_6_UP); context->Function = function; SWFDEC_AS_VALUE_SET_OBJECT (&val, function); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); proto = swfdec_as_object_new_empty (context); context->Function_prototype = proto; SWFDEC_AS_VALUE_SET_OBJECT (&val, proto); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); swfdec_as_object_set_variable_and_flags (function, SWFDEC_AS_STR___proto__, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT | SWFDEC_AS_VARIABLE_VERSION_6_UP); SWFDEC_AS_VALUE_SET_OBJECT (&val, function); swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); }
void swfdec_video_movie_init_context (SwfdecPlayer *player) { SwfdecAsContext *context; SwfdecAsObject *video, *proto; SwfdecAsValue val; g_return_if_fail (SWFDEC_IS_PLAYER (player)); context = SWFDEC_AS_CONTEXT (player); video = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_Video, NULL)); SWFDEC_SANDBOX (context->global)->Video = video; proto = swfdec_as_object_new_empty (context); /* set the right properties on the Video object */ SWFDEC_AS_VALUE_SET_OBJECT (&val, proto); swfdec_as_object_set_variable_and_flags (video, SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); /* set the right properties on the Video.prototype object */ SWFDEC_AS_VALUE_SET_OBJECT (&val, video); swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Object_prototype); swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR___proto__, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); }
static guint check_object_variables (void) { SwfdecAsObject *o, *o2; guint errors = 0; SwfdecAsContext *context; const char *s; gpointer check = GUINT_TO_POINTER (-1); /* NOT NULL */ gpointer check2 = GUINT_TO_POINTER (-1); /* NOT NULL */ SwfdecAsValue v1, v2; context = g_object_new (SWFDEC_TYPE_AS_CONTEXT, NULL); swfdec_as_context_startup (context); g_assert (check != NULL); o = swfdec_as_object_new (context); o2 = swfdec_as_object_new (context); g_object_add_weak_pointer (G_OBJECT (o), &check); g_object_add_weak_pointer (G_OBJECT (o2), &check2); s = swfdec_as_context_get_string (context, "foo"); /* step one: set a variable */ SWFDEC_AS_VALUE_SET_OBJECT (&v1, o); swfdec_as_object_set_variable (context->global, s, &v1); SWFDEC_AS_VALUE_SET_OBJECT (&v2, o2); swfdec_as_object_set_variable (o, s, &v2); SWFDEC_AS_VALUE_SET_UNDEFINED (&v2); swfdec_as_object_get_variable (o, s, &v2); if (!SWFDEC_AS_VALUE_IS_OBJECT (&v2)) { ERROR ("variable changed type"); } else if (o2 != SWFDEC_AS_VALUE_GET_OBJECT (&v2)) { ERROR ("variable changed value"); } /* step 2: gc */ swfdec_as_context_gc (context); if (check == NULL || check2 == NULL) { ERROR ("GC collected a used object, bailing"); g_object_unref (context); return errors; } /* step 3: unset root reference and set cyclic variable */ swfdec_as_object_delete_variable (context->global, s); swfdec_as_object_set_variable (o2, s, &v1); SWFDEC_AS_VALUE_SET_UNDEFINED (&v1); swfdec_as_object_get_variable (o2, s, &v1); if (!SWFDEC_AS_VALUE_IS_OBJECT (&v1)) { ERROR ("variable changed type"); } else if (o != SWFDEC_AS_VALUE_GET_OBJECT (&v1)) { ERROR ("variable changed value"); } /* step 4: gc, ensure that both objects disappears */ swfdec_as_context_gc (context); if (check != NULL || check2 != NULL) { ERROR ("GC didn't collect unused object"); } g_object_unref (context); return errors; }
void swfdec_bitmap_data_clone (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { SwfdecBitmapData *bitmap, *clone; cairo_t *cr; SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, ""); if (bitmap->surface == NULL) return; clone = swfdec_bitmap_data_new (cx, swfdec_surface_has_alpha (bitmap->surface), cairo_image_surface_get_width (bitmap->surface), cairo_image_surface_get_height (bitmap->surface)); if (clone == NULL) return; cr = cairo_create (clone->surface); cairo_set_source_surface (cr, bitmap->surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (clone)); }
static gboolean swfdec_amf_parse_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val) { guint i, len; SwfdecAsObject *array; guint type; SwfdecAmfParseFunc func; len = swfdec_bits_get_bu32 (bits); array = swfdec_as_array_new (context); for (i = 0; i < len; i++) { SwfdecAsValue tmp; type = swfdec_bits_get_u8 (bits); if (type >= SWFDEC_AMF_N_TYPES || (func = parse_funcs[type]) == NULL) { SWFDEC_ERROR ("no parse func for AMF type %u", type); goto fail; } if (!func (context, bits, &tmp)) goto fail; swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &tmp); } SWFDEC_AS_VALUE_SET_OBJECT (val, array); return TRUE; fail: return FALSE; }
/** * swfdec_as_native_function_new: * @context: a #SwfdecAsContext * @name: name of the function * @native: function to call when executed * @prototype: The object to be used as "prototype" property for the created * function or %NULL for none. * * Creates a new native function, that will execute @native when called. You * might want to use swfdec_as_object_add_function() instead of this function. * * Returns: a new #SwfdecAsFunction **/ SwfdecAsFunction * swfdec_as_native_function_new (SwfdecAsContext *context, const char *name, SwfdecAsNative native, SwfdecAsObject *prototype) { SwfdecAsNativeFunction *fun; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (native != NULL, NULL); g_return_val_if_fail (prototype == NULL || SWFDEC_IS_AS_OBJECT (prototype), NULL); fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, "context", context, NULL); fun->native = native; fun->name = g_strdup (name); /* need to set prototype before setting the constructor or Function.constructor * being CONSTANT disallows setting it. */ if (prototype) { SwfdecAsValue val; SWFDEC_AS_VALUE_SET_OBJECT (&val, prototype); swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (fun), SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); } swfdec_as_function_set_constructor (SWFDEC_AS_FUNCTION (fun)); return SWFDEC_AS_FUNCTION (fun); }
static guint check_objects (void) { SwfdecAsObject *object; guint errors = 0; SwfdecAsContext *context; SwfdecAsValue val; gpointer check = GUINT_TO_POINTER (-1); /* NOT NULL */ context = g_object_new (SWFDEC_TYPE_AS_CONTEXT, NULL); swfdec_as_context_startup (context); g_assert (check != NULL); object = swfdec_as_object_new (context); g_object_add_weak_pointer (G_OBJECT (object), &check); SWFDEC_AS_VALUE_SET_OBJECT (&val, object); swfdec_as_object_set_variable (context->global, SWFDEC_AS_STR__root, &val); swfdec_as_context_gc (context); if (check == NULL) { ERROR ("GC collected a rooted object, bailing"); g_object_unref (context); return errors; } swfdec_as_object_delete_variable (context->global, SWFDEC_AS_STR__root); swfdec_as_context_gc (context); if (check != NULL) { ERROR ("GC did not collect an unreferenced object"); } g_object_unref (context); return errors; }
void swfdec_test_test_render (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval) { SwfdecTestTest *test; SwfdecTestImage *image; int x = 0, y = 0, w = 0, h = 0; SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_TEST, &test, "|iiii", &x, &y, &w, &h); if (!test->plugin_loaded || test->plugin_error || test->plugin_quit) return; if (argc == 0) { w = test->plugin.width; h = test->plugin.height; } image = swfdec_test_image_new (cx, w, h); if (test->plugin.screenshot) { test->plugin.screenshot (&test->plugin, cairo_image_surface_get_data (SWFDEC_TEST_IMAGE (image)->surface), x, y, w, h); SWFDEC_AS_VALUE_SET_OBJECT (retval, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (image))); } else { swfdec_test_throw (cx, "plugin doesn't implement render"); } }
void swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { const char **fields; SortOption *options; gint32 i, num_fields; SwfdecAsObject *array; SwfdecAsValue val; if (object == NULL || SWFDEC_IS_MOVIE (object)) return; if (argc < 1) return; if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[0])) { array = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]); if (!SWFDEC_IS_AS_ARRAY (array)) { SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } num_fields = swfdec_as_array_get_length (SWFDEC_AS_ARRAY (array)); if (num_fields <= 0) { SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } fields = g_new (const char *, num_fields + 1); for (i = 0; i < num_fields; i++) { swfdec_as_array_get_value (SWFDEC_AS_ARRAY (array), i, &val); if (SWFDEC_AS_VALUE_IS_OBJECT (&val) && SWFDEC_IS_AS_STRING (SWFDEC_AS_VALUE_GET_OBJECT (&val))) { fields[i] = SWFDEC_AS_STRING (SWFDEC_AS_VALUE_GET_OBJECT (&val))->string; } else { fields[i] = swfdec_as_value_to_string (cx, &val); } } fields[i] = NULL; } else {
static gboolean swfdec_amf_parse_object (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val) { SwfdecAsObject *object; object = swfdec_as_object_new (context); if (!swfdec_amf_parse_properties (context, bits, object)) return FALSE; SWFDEC_AS_VALUE_SET_OBJECT (val, object); return TRUE; }
static gboolean swfdec_amf_parse_mixed_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val) { guint len; SwfdecAsObject *array; len = swfdec_bits_get_bu32 (bits); array = swfdec_as_array_new (context); if (!swfdec_amf_parse_properties (context, bits, array)) return FALSE; SWFDEC_AS_VALUE_SET_OBJECT (val, array); return TRUE; }
// FIXME: untested static gboolean swfdec_amf_parse_date (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val) { double milliseconds = swfdec_bits_get_bdouble (bits); int utc_offset = swfdec_bits_get_bu16 (bits); if (utc_offset > 12 * 60) utc_offset -= 12 * 60; SWFDEC_AS_VALUE_SET_OBJECT (val, swfdec_as_date_new (context, milliseconds, utc_offset)); return TRUE; }
/** * swfdec_as_function_set_constructor: * @fun: a #SwfdecAsFunction * * Sets the constructor and prototype of @fun. This is a shortcut for calling * swfdec_as_object_set_constructor() with the right arguments. **/ void swfdec_as_function_set_constructor (SwfdecAsFunction *fun) { SwfdecAsContext *context; SwfdecAsObject *object; SwfdecAsValue val; g_return_if_fail (SWFDEC_IS_AS_FUNCTION (fun)); object = SWFDEC_AS_OBJECT (fun); context = swfdec_gc_object_get_context (fun); if (context->Function == NULL) return; SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Function); swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_constructor, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT); SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Function_prototype); swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR___proto__, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT | SWFDEC_AS_VARIABLE_VERSION_6_UP); }
static void swfdec_test_test_request_socket (SwfdecTestPlugin *plugin, SwfdecTestPluginSocket *psock) { SwfdecTestTest *test = SWFDEC_TEST_TEST_FROM_PLUGIN (plugin); SwfdecAsContext *cx = swfdec_gc_object_get_context (test); SwfdecTestSocket *sock; SwfdecAsValue val; sock = swfdec_test_socket_new (test, psock); SWFDEC_AS_VALUE_SET_OBJECT (&val, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (sock))); swfdec_as_relay_call (SWFDEC_AS_RELAY (test), swfdec_as_context_get_string (cx, "onSocket"), 1, &val, NULL); }
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); }
void swfdec_as_array_reverse (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { gint32 length; if (object == NULL || SWFDEC_IS_MOVIE (object)) return; length = swfdec_as_array_length (object); swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_reverse, &length); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); }
void swfdec_test_test_get_trace (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval) { SwfdecTestTest *test; SwfdecTestBuffer *buf; SwfdecBuffer *buffer; gsize len; SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_TEST, &test, ""); len = swfdec_buffer_queue_get_depth (test->trace); buffer = swfdec_buffer_queue_peek (test->trace, len); buf = swfdec_test_buffer_new (cx, buffer); SWFDEC_AS_VALUE_SET_OBJECT (retval, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (buf))); }
void swfdec_test_test_new (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval) { SwfdecTestTest *test; const char *filename = NULL; if (!swfdec_as_context_is_constructing (cx)) return; SWFDEC_AS_CHECK (0, NULL, "|s", &filename); test = g_object_new (SWFDEC_TYPE_TEST_TEST, "context", cx, NULL); swfdec_test_do_reset (test, filename); swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (test)); SWFDEC_AS_VALUE_SET_OBJECT (retval, object); }
void swfdec_color_transform_as_construct (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { SwfdecColorTransformAs *transform; if (!swfdec_as_context_is_constructing (cx)) return; transform = g_object_new (SWFDEC_TYPE_COLOR_TRANSFORM_AS, "context", cx, NULL); swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (transform)); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); if (argc < 8) return; SWFDEC_AS_CHECK (0, NULL, "nnnnnnnn", &transform->ra, &transform->ga, &transform->ba, &transform->aa, &transform->rb, &transform->gb, &transform->bb, &transform->ab); }
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)); }
void swfdec_bitmap_data_loadBitmap (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { SwfdecBitmapData *bitmap; SwfdecImage *image; const char *name; cairo_surface_t *isurface; cairo_t *cr; SWFDEC_AS_CHECK (0, NULL, "s", &name); g_assert (SWFDEC_IS_MOVIE (cx->frame->target)); image = swfdec_resource_get_export (SWFDEC_MOVIE (cx->frame->target)->resource, name); if (!SWFDEC_IS_IMAGE (image)) { SWFDEC_ERROR ("loadBitmap cannot find image with name %s", name); return; } /* FIXME: improve this to not create an image if there is one cached */ isurface = swfdec_image_create_surface (image, NULL); if (isurface == NULL) return; /* FIXME: use image directly instead of doing a copy and then deleting it */ bitmap = swfdec_bitmap_data_new (cx, swfdec_surface_has_alpha (isurface), cairo_image_surface_get_width (isurface), cairo_image_surface_get_height (isurface)); if (bitmap == NULL) return; cr = cairo_create (bitmap->surface); cairo_set_source_surface (cr, isurface, 0, 0); cairo_paint (cr); cairo_destroy (cr); cairo_surface_destroy (isurface); SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (bitmap)); }
void swfdec_as_array_concat (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret) { guint j; SwfdecAsObject *object_new; SwfdecAsArray *array_new; const char *var; if (object == NULL || SWFDEC_IS_MOVIE (object)) return; object_new = swfdec_as_array_new (cx); if (object_new == NULL) return; array_new = SWFDEC_AS_ARRAY (object_new); swfdec_as_array_append_array (array_new, object); for (j = 0; j < argc; j++) { if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[j]) && SWFDEC_IS_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[j]))) { swfdec_as_array_append_array (array_new, SWFDEC_AS_VALUE_GET_OBJECT (&argv[j])); } else { var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), swfdec_as_array_length (object_new)); swfdec_as_object_set_variable (object_new, var, &argv[j]); } } SWFDEC_AS_VALUE_SET_OBJECT (ret, object_new); }
static void swfdec_as_array_do_sort (SwfdecAsContext *cx, SwfdecAsObject *object, const SortOption *options, SwfdecAsFunction *custom_function, const char **fields, SwfdecAsValue *ret) { SortEntry *array; SortCollectData collect_data; SortCompareData compare_data; gint32 i, length; const char *var; SwfdecAsObject *target; SwfdecAsValue val; SortOption options_; gboolean descending; g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx)); g_return_if_fail (SWFDEC_IS_AS_OBJECT (object)); g_return_if_fail (options != NULL); g_return_if_fail (custom_function == NULL || SWFDEC_IS_AS_FUNCTION (custom_function)); g_return_if_fail (fields == NULL || fields[0] != NULL); length = swfdec_as_array_length (object); if (length == 0) { // special case for empty array, because g_try_new0 would return NULL SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } if (!swfdec_as_context_try_use_mem (cx, sizeof (SortEntry) * length)) { SWFDEC_WARNING ("Array not sorted, too big (%i elements)", length); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); return; } // FIXME: this should be different, but context's memory management is not // done properly yet array = g_try_new0 (SortEntry, length); if (!array) { SWFDEC_WARNING ("Array not sorted, too big (%i elements)", length); SWFDEC_AS_VALUE_SET_OBJECT (ret, object); goto done; } for (i = 0; i < length; i++) { array[i].index_ = i; } // collect values and indexes to the array collect_data.length = length; collect_data.array = array; swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_collect, &collect_data); // sort the array compare_data.context = cx; compare_data.fields = fields; compare_data.options = options; // if no fields, then we'll do descending here after the sort if (fields == NULL && options[0] & SORT_OPTION_DESCENDING) { descending = TRUE; options_ = options[0] & ~SORT_OPTION_DESCENDING; compare_data.options = &options_; } else { descending = FALSE; } compare_data.custom_function = custom_function; compare_data.equal_found = FALSE; swfdec_as_array_sort_array (array, length, swfdec_as_array_sort_compare, &compare_data); // check unique sort if (options[0] & SORT_OPTION_UNIQUESORT) { if (fields == NULL && custom_function != NULL) { // if we used custom_function for comparision, we shall now go trough the // sorted array and compare them using the default array sort comparision // and use that to decide if it's unique (no it doesn't make too much // sense) for (i = 0; i < length - 1; i++) { SwfdecAsValue *a = &array[i].value; SwfdecAsValue *b = &array[i + 1].value; if (swfdec_as_array_sort_compare_values (cx, a, b, 0, NULL) == 0) break; } if (i < length - 1) { SWFDEC_AS_VALUE_SET_INT (ret, 0); goto done; } } else if (compare_data.equal_found) { SWFDEC_AS_VALUE_SET_INT (ret, 0); goto done; } } if (options[0] & SORT_OPTION_RETURNINDEXEDARRAY) { target = swfdec_as_array_new (cx); if (!target) goto done; } else { target = object; } for (i = 0; i < length; i++) { SortEntry *entry = &array[i]; // set only the values that have new indexes if (!(options[0] & SORT_OPTION_RETURNINDEXEDARRAY) && entry->index_ == (descending ? length - i - 1 : i)) continue; var = swfdec_as_integer_to_string (cx, (descending ? length - i - 1 : i)); if (options[0] & SORT_OPTION_RETURNINDEXEDARRAY) { SWFDEC_AS_VALUE_SET_INT (&val, entry->index_); swfdec_as_object_set_variable (target, var, &val); } else { swfdec_as_object_set_variable (target, var, &entry->value); } } SWFDEC_AS_VALUE_SET_OBJECT (ret, target); done: g_free (array); swfdec_as_context_unuse_mem (cx, sizeof (SortEntry) * length); }
int main (int argc, char **argv) { char *script_filename = NULL; GError *error = NULL; SwfdecAsContext *context; SwfdecAsObject *array; SwfdecScript *script; SwfdecAsValue val; int i, ret; gboolean dump = FALSE; gboolean no_check = FALSE, only_check = FALSE; GOptionEntry options[] = { { "dump", 'd', 0, G_OPTION_ARG_NONE, &dump, "dump informative output on failure", FALSE }, { "no-check", 0, 0, G_OPTION_ARG_NONE, &no_check, "don't check if the system is ok for running the testsuite", FALSE }, { "self-check", 0, 0, G_OPTION_ARG_NONE, &only_check, "run a system check and exit", FALSE }, { "player", 'p', 0, G_OPTION_ARG_STRING, &swfdec_test_plugin_name, "player to test", "NAME" }, { "script", 's', 0, G_OPTION_ARG_STRING, &script_filename, "script to execute if not ./default.sts", "FILENAME" }, { NULL } }; GOptionContext *ctx; /* set the right warning levels */ g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); /* by default get rid of the loads of warnings the tests produce */ g_setenv ("SWFDEC_DEBUG", "2", FALSE); g_thread_init (NULL); swfdec_init (); ctx = g_option_context_new (""); g_option_context_add_main_entries (ctx, options, "options"); g_option_context_parse (ctx, &argc, &argv, &error); g_option_context_free (ctx); if (error) { g_printerr ("ERROR: wrong command line arguments: %s\n", error->message); g_error_free (error); return EXIT_FAILURE; } if (only_check || !no_check) { gboolean result = check_system (only_check); if (!result) { g_print ("ERROR: System checked failed, aborting. Use --no-check to disable.\n"); return 1; } else if (only_check) { return 0; } } g_assert (!only_check); /* allow env vars instead of options - eases running make check with different settings */ if (swfdec_test_plugin_name == NULL) swfdec_test_plugin_name = g_strdup (g_getenv ("SWFDEC_TEST_PLAYER")); script = load_script (script_filename); g_free (script_filename); if (script == NULL) return EXIT_FAILURE; context = g_object_new (SWFDEC_TYPE_AS_CONTEXT, NULL); swfdec_as_context_startup (context); SWFDEC_AS_VALUE_SET_BOOLEAN (&val, dump); swfdec_as_object_set_variable (context->global, swfdec_as_context_get_string (context, "dump"), &val); swfdec_test_function_init_context (context); swfdec_as_context_run_init_script (context, swfdec_test_initialize, sizeof (swfdec_test_initialize), SWFDEC_TEST_VERSION); array = swfdec_as_array_new (context); if (array == NULL) { g_print ("ERROR: Not enough memory"); return EXIT_FAILURE; } if (argc < 2) { GDir *dir; const char *file; dir = g_dir_open (".", 0, NULL); while ((file = g_dir_read_name (dir))) { if (!g_str_has_suffix (file, ".swf")) continue; SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (context, file)); swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val); } g_dir_close (dir); } else { for (i = 1; i < argc; i++) { SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (context, argv[i])); swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val); } } SWFDEC_AS_VALUE_SET_OBJECT (&val, array); swfdec_as_object_set_variable (context->global, swfdec_as_context_get_string (context, "filenames"), &val); swfdec_as_object_run (context->global, script); if (swfdec_as_context_catch (context, &val)) { g_print ("ERROR: %s\n", swfdec_as_value_to_string (context, &val)); ret = EXIT_FAILURE; } else { g_print ("SUCCESS\n"); ret = EXIT_SUCCESS; } swfdec_script_unref (script); g_object_unref (context); return ret; }