📄 swfdec_as_array.c
字号:
/* Swfdec * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> * 2007 Pekka Lampila <pekka.lampila@iki.fi> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "swfdec_as_array.h"#include "swfdec_as_context.h"#include "swfdec_as_frame_internal.h"#include "swfdec_as_function.h"#include "swfdec_as_internal.h"#include "swfdec_as_native_function.h"#include "swfdec_as_strings.h"#include "swfdec_debug.h"#include "swfdec_player_internal.h"G_DEFINE_TYPE (SwfdecAsArray, swfdec_as_array, SWFDEC_TYPE_AS_OBJECT)/** * SECTION:SwfdecAsArray * @title: SwfdecAsArray * @short_description: the array object * * The array object provides some convenience functions for creating and * modifying arrays. *//** * SwfdecAsArray * * This is the type of the array object. *//* * Internal helper functions *//* NB: type is important for overflow */static inline gint32swfdec_as_array_to_index (const char *str){ char *end; gulong l; g_return_val_if_fail (str != NULL, -1); l = strtoul (str, &end, 10); if (*end != 0 || l > G_MAXINT32) return -1; return l;}static gint32swfdec_as_array_get_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 (object->context, &val); return length;}static gint32swfdec_as_array_get_length (SwfdecAsObject *object){ gint32 length; length = swfdec_as_array_get_length_as_integer (object); if (length < 0) return 0; return length;}static voidswfdec_as_array_set_length (SwfdecAsObject *object, gint32 length){ SwfdecAsValue val; g_return_if_fail (object != NULL); SWFDEC_AS_VALUE_SET_INT (&val, length); swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length, &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);}typedef struct { gint32 start_index; gint32 num;} ForeachRemoveRangeData;static gbooleanswfdec_as_array_foreach_remove_range (SwfdecAsObject *object, const char *variable, SwfdecAsValue *value, guint flags, gpointer data){ ForeachRemoveRangeData *fdata = data; gint32 idx; idx = swfdec_as_array_to_index (variable); if (idx == -1) return FALSE; if (idx >= fdata->start_index && idx < fdata->start_index + fdata->num) return TRUE; return FALSE;}static voidswfdec_as_array_remove_range (SwfdecAsArray *array, gint32 start_index, gint32 num){ SwfdecAsObject *object = SWFDEC_AS_OBJECT (array); g_return_if_fail (SWFDEC_IS_AS_ARRAY (array)); g_return_if_fail (start_index >= 0); g_return_if_fail (num >= 0); g_return_if_fail (start_index + num <= swfdec_as_array_get_length (object)); if (num == 0) return; // to avoid foreach loop, use special case when removing just one variable if (num == 1) { const char *var = swfdec_as_double_to_string (object->context, start_index); swfdec_as_object_delete_variable (object, var); } else { ForeachRemoveRangeData fdata = { start_index, num }; swfdec_as_object_foreach_remove (object, swfdec_as_array_foreach_remove_range, &fdata); }}typedef struct { gint32 start_index; gint32 num; gint32 to_index;} ForeachMoveRangeData;static const char *swfdec_as_array_foreach_move_range (SwfdecAsObject *object, const char *variable, SwfdecAsValue *value, guint flags, gpointer data){ ForeachMoveRangeData *fdata = data; gint32 idx; idx = swfdec_as_array_to_index (variable); if (idx == -1) return variable; if (idx >= fdata->start_index && idx < fdata->start_index + fdata->num) { return swfdec_as_double_to_string (object->context, fdata->to_index + idx - fdata->start_index); } else if (idx >= fdata->to_index && idx < fdata->to_index + fdata->num) { return NULL; } else { return variable; }}static voidswfdec_as_array_move_range (SwfdecAsObject *object, gint32 from_index, gint32 num, gint32 to_index){ ForeachMoveRangeData fdata = { from_index, num, to_index }; g_return_if_fail (SWFDEC_IS_AS_OBJECT (object)); g_return_if_fail (from_index >= 0); g_return_if_fail (num >= 0); g_return_if_fail (from_index + num <= swfdec_as_array_get_length (object)); g_return_if_fail (to_index >= 0); if (num == 0 || from_index == to_index) return; swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_move_range, &fdata); // only changes length if it becomes bigger, not if it becomes smaller if (to_index + num > swfdec_as_array_get_length (object)) swfdec_as_array_set_length (object, to_index + num);}static voidswfdec_as_array_set_range (SwfdecAsObject *object, gint32 start_index, gint32 num, const SwfdecAsValue *value){ gint32 i; const char *var; // allow negative indexes g_return_if_fail (SWFDEC_IS_AS_OBJECT (object)); g_return_if_fail (num >= 0); g_return_if_fail (value != NULL); for (i = 0; i < num; i++) { var = swfdec_as_double_to_string (object->context, start_index + i); swfdec_as_object_set_variable (object, var, &value[i]); }}static voidswfdec_as_array_append_internal (SwfdecAsObject *object, guint n, const SwfdecAsValue *value){ // allow negative length swfdec_as_array_set_range (object, swfdec_as_array_get_length_as_integer (object), n, value);}/** * swfdec_as_array_push: * @array: a #SwfdecAsArray * @value: the value to add * * Adds the given value to the array. This a macro that just calls * swfdec_as_array_append(). *//** * swfdec_as_array_append: * @array: a #SwfdecAsArray * @n: number of values to add * @values: the values to add * * Appends the given @values to the array. **/voidswfdec_as_array_append (SwfdecAsArray *array, guint n, const SwfdecAsValue *value){ // don't allow negative length swfdec_as_array_set_range (SWFDEC_AS_OBJECT (array), swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array)), n, value);}typedef struct { SwfdecAsObject *object_to; gint32 offset; gint32 start_index; gint32 num;} ForeachAppendArrayRangeData;static gbooleanswfdec_as_array_foreach_append_array_range (SwfdecAsObject *object, const char *variable, SwfdecAsValue *value, guint flags, gpointer data){ ForeachAppendArrayRangeData *fdata = data; gint32 idx; const char *var; idx = swfdec_as_array_to_index (variable); if (idx >= fdata->start_index && idx < fdata->start_index + fdata->num) { var = swfdec_as_double_to_string (fdata->object_to->context, fdata->offset + (idx - fdata->start_index)); swfdec_as_object_set_variable (fdata->object_to, var, value); } return TRUE;}static voidswfdec_as_array_append_array_range (SwfdecAsArray *array_to, SwfdecAsObject *object_from, gint32 start_index, gint32 num){ ForeachAppendArrayRangeData fdata; g_return_if_fail (SWFDEC_IS_AS_ARRAY (array_to)); g_return_if_fail (SWFDEC_IS_AS_OBJECT (object_from)); g_return_if_fail (start_index >= 0); g_return_if_fail ( start_index + num <= swfdec_as_array_get_length (object_from)); if (num == 0) return; fdata.object_to = SWFDEC_AS_OBJECT (array_to); fdata.offset = swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array_to)); fdata.start_index = start_index; fdata.num = num; swfdec_as_array_set_length (fdata.object_to, fdata.offset + fdata.num); swfdec_as_object_foreach (object_from, swfdec_as_array_foreach_append_array_range, &fdata);}static voidswfdec_as_array_append_array (SwfdecAsArray *array_to, SwfdecAsObject *object_from){ swfdec_as_array_append_array_range (array_to, object_from, 0, swfdec_as_array_get_length (object_from));}/* * Class functions */static voidswfdec_as_array_set (SwfdecAsObject *object, const char *variable, const SwfdecAsValue *val, guint flags){ char *end; gboolean indexvar = TRUE; gint32 l = strtoul (variable, &end, 10); if (*end != 0 || l > G_MAXINT32) indexvar = FALSE; // if we changed to smaller length, destroy all values that are outside it if (!strcmp (variable, SWFDEC_AS_STR_length)) { gint32 length_old = swfdec_as_array_get_length (object); gint32 length_new = MAX (0, swfdec_as_value_to_integer (object->context, val)); if (length_old > length_new) { swfdec_as_array_remove_range (SWFDEC_AS_ARRAY (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) { if (++l > swfdec_as_array_get_length_as_integer (object)) swfdec_as_array_set_length (object, l); }}static voidswfdec_as_array_class_init (SwfdecAsArrayClass *klass){ SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass); asobject_class->set = swfdec_as_array_set;}static voidswfdec_as_array_init (SwfdecAsArray *array){}/* * The rest *//** * swfdec_as_array_new: * @context: a #SwfdecAsContext *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -