📄 swfdec_as_object.c
字号:
/* Swfdec * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> * * 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 <strings.h>#include "swfdec_as_object.h"#include "swfdec_as_context.h"#include "swfdec_as_frame_internal.h"#include "swfdec_as_internal.h"#include "swfdec_as_native_function.h"#include "swfdec_as_stack.h"#include "swfdec_as_strings.h"#include "swfdec_debug.h"#include "swfdec_movie.h"/** * SECTION:SwfdecAsObject * @title: SwfdecAsObject * @short_description: the base object type for scriptable objects * * This is the basic object type in Swfdec. Every object used by the script * engine must be a #SwfdecAsObject. It handles memory management and assigning * variables to it. Almost all functions that are called on objects require that * the objects have been added to the garbage collector previously. For * custom-created objects, you need to do this using swfdec_as_object_add(), * built-in functions that create objects do this manually. * * Note that you cannot know the lifetime of a #SwfdecAsObject, since scripts * may assign it as a variable to other objects. So you should not assume to * know when an object gets removed. *//** * SwfdecAsObject: * * Every object value inside the Swfdec script engine must be a SwfdecAsObject. * If you want to add custom objects to your script engine, you need to create a * subclass. The class provides a number of virtual functions that you can * override to achieve the desired behaviour. *//** * SwfdecAsVariableFlag: * @SWFDEC_AS_VARIABLE_HIDDEN: Do not include variable in enumerations and * swfdec_as_object_foreach(). * @SWFDEC_AS_VARIABLE_PERMANENT: Do not all swfdec_as_object_delete_variable() * to delete this variable. * @SWFDEC_AS_VARIABLE_CONSTANT: Do not allow changing the value with * swfdec_as_object_set_variable(). * @SWFDEC_AS_VARIABLE_VERSION_6_UP: This symbol is only visible in version 6 * and above. * @SWFDEC_AS_VARIABLE_VERSION_NOT_6: This symbols is visible in all versions * but version 6. * @SWFDEC_AS_VARIABLE_VERSION_7_UP: This symbol is only visible in version 7 * and above. * @SWFDEC_AS_VARIABLE_VERSION_8_UP: This symbol is only visible in version 8 * and above. * * These flags are used to describe various properties of a variable inside * Swfdec. You can manually set them with swfdec_as_object_set_variable_flags(). *//** * SwfdecAsDeleteReturn: * @SWFDEC_AS_DELETE_NOT_FOUND: The variable was not found and therefore * couldn't be deleted. * @SWFDEC_AS_DELETE_DELETED: The variable was deleted. * @SWFDEC_AS_DELETE_NOT_DELETED: The variable was found but could not be * deleted. * * This is the return value used by swfdec_as_object_delete_variable(). It * describes the various outcomes of trying to delete a variable. *//** * SwfdecAsVariableForeach: * @object: The object this function is run on * @variable: garbage-collected name of the current variables * @value: value of the current variable * @flags: Flags associated with the current variable * @data: User dta passed to swfdec_as_object_foreach() * * Function prototype for the swfdec_as_object_foreach() function. * * Returns: %TRUE to continue running the foreach function, %FALSE to stop */typedef struct _SwfdecAsVariable SwfdecAsVariable;struct _SwfdecAsVariable { guint flags; /* SwfdecAsVariableFlag values */ SwfdecAsValue value; /* value of property */ SwfdecAsFunction * get; /* getter set with swfdec_as_object_add_property */ SwfdecAsFunction * set; /* setter or %NULL */};G_DEFINE_TYPE (SwfdecAsObject, swfdec_as_object, G_TYPE_OBJECT)static voidswfdec_as_object_dispose (GObject *gobject){ SwfdecAsObject *object = SWFDEC_AS_OBJECT (gobject); g_assert (object->properties == NULL); G_OBJECT_CLASS (swfdec_as_object_parent_class)->dispose (gobject);}static voidswfdec_as_object_mark_property (gpointer key, gpointer value, gpointer unused){ SwfdecAsVariable *var = value; swfdec_as_string_mark (key); if (var->get) { swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->get)); if (var->set) swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->set)); } else { swfdec_as_value_mark (&var->value); }}static voidswfdec_as_object_do_mark (SwfdecAsObject *object){ if (object->prototype) swfdec_as_object_mark (object->prototype); g_hash_table_foreach (object->properties, swfdec_as_object_mark_property, NULL);}static voidswfdec_as_object_do_add (SwfdecAsObject *object){}static gbooleanswfdec_as_object_lookup_case_insensitive (gpointer key, gpointer value, gpointer user_data){ return strcasecmp (key, user_data) == 0;}static gbooleanswfdec_as_variable_name_is_valid (const char *name){ return name != SWFDEC_AS_STR_EMPTY;}static inline SwfdecAsVariable *swfdec_as_object_hash_lookup (SwfdecAsObject *object, const char *variable){ SwfdecAsVariable *var = g_hash_table_lookup (object->properties, variable); if (var || object->context->version >= 7) return var; var = g_hash_table_find (object->properties, swfdec_as_object_lookup_case_insensitive, (gpointer) variable); return var;}static inline SwfdecAsVariable *swfdec_as_object_hash_create (SwfdecAsObject *object, const char *variable, guint flags){ SwfdecAsVariable *var; if (!swfdec_as_context_use_mem (object->context, sizeof (SwfdecAsVariable))) return NULL; if (!swfdec_as_variable_name_is_valid (variable)) return NULL; var = g_slice_new0 (SwfdecAsVariable); var->flags = flags; g_hash_table_insert (object->properties, (gpointer) variable, var); return var;}static gbooleanswfdec_as_object_do_get (SwfdecAsObject *object, SwfdecAsObject *orig, const char *variable, SwfdecAsValue *val, guint *flags){ SwfdecAsVariable *var = swfdec_as_object_hash_lookup (object, variable); if (var == NULL) return FALSE; /* variable flag checks */ if (var->flags & SWFDEC_AS_VARIABLE_VERSION_6_UP && object->context->version < 6) return FALSE; if (var->flags & SWFDEC_AS_VARIABLE_VERSION_NOT_6 && object->context->version == 6) return FALSE; if (var->flags & SWFDEC_AS_VARIABLE_VERSION_7_UP && object->context->version < 7) return FALSE; if (var->flags & SWFDEC_AS_VARIABLE_VERSION_8_UP && object->context->version < 8) return FALSE; if (var->get) { swfdec_as_function_call (var->get, orig, 0, NULL, val); swfdec_as_context_run (object->context); *flags = var->flags; } else { *val = var->value; *flags = var->flags; } return TRUE;}static voidswfdec_as_object_do_set (SwfdecAsObject *object, const char *variable, const SwfdecAsValue *val, guint flags){ SwfdecAsVariable *var; if (!swfdec_as_variable_name_is_valid (variable)) return; if (variable == SWFDEC_AS_STR___proto__) { if (SWFDEC_AS_VALUE_IS_OBJECT (val) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (val))) { object->prototype = SWFDEC_AS_VALUE_GET_OBJECT (val); } else { object->prototype = NULL; } } var = swfdec_as_object_hash_lookup (object, variable); if (var == NULL) { guint i; SwfdecAsObject *proto = object->prototype; for (i = 0; i < 256 && proto; i++) { var = swfdec_as_object_hash_lookup (proto, variable); if (var && var->get) break; proto = proto->prototype; var = NULL; } if (i == 256) { swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded"); return; } } if (var == NULL) { var = swfdec_as_object_hash_create (object, variable, flags); if (var == NULL) return; } else { if (var->flags & SWFDEC_AS_VARIABLE_CONSTANT) return; } if (var->get) { if (var->set) { SwfdecAsValue tmp; swfdec_as_function_call (var->set, object, 1, val, &tmp); swfdec_as_context_run (object->context); } } else { var->value = *val; }}static voidswfdec_as_object_do_set_flags (SwfdecAsObject *object, const char *variable, guint flags, guint mask){ SwfdecAsVariable *var = swfdec_as_object_hash_lookup (object, variable); if (var) var->flags = (var->flags & ~mask) | flags;}static voidswfdec_as_object_free_property (gpointer key, gpointer value, gpointer data){ SwfdecAsObject *object = data; swfdec_as_context_unuse_mem (object->context, sizeof (SwfdecAsVariable)); g_slice_free (SwfdecAsVariable, value);}static SwfdecAsDeleteReturnswfdec_as_object_do_delete (SwfdecAsObject *object, const char *variable){ SwfdecAsVariable *var; var = g_hash_table_lookup (object->properties, variable); if (var == NULL) return SWFDEC_AS_DELETE_NOT_FOUND; if (var->flags & SWFDEC_AS_VARIABLE_PERMANENT) return SWFDEC_AS_DELETE_NOT_DELETED; swfdec_as_object_free_property (NULL, var, object); if (!g_hash_table_remove (object->properties, variable)) { g_assert_not_reached (); } return SWFDEC_AS_DELETE_DELETED;}typedef struct { SwfdecAsObject * object; SwfdecAsVariableForeach func; gpointer data; gboolean retval;} ForeachData;static voidswfdec_as_object_hash_foreach (gpointer key, gpointer value, gpointer data){ ForeachData *fdata = data; SwfdecAsVariable *var = value; if (!fdata->retval) return; fdata->retval = fdata->func (fdata->object, key, &var->value, var->flags, fdata->data);}/* FIXME: does not do Adobe Flash's order for Enumerate actions */static gbooleanswfdec_as_object_do_foreach (SwfdecAsObject *object, SwfdecAsVariableForeach func, gpointer data){ ForeachData fdata = { object, func, data, TRUE }; g_hash_table_foreach (object->properties, swfdec_as_object_hash_foreach, &fdata); return fdata.retval;}typedef struct { SwfdecAsObject * object; SwfdecAsVariableForeachRemove func; gpointer data;} ForeachRemoveData;static gbooleanswfdec_as_object_hash_foreach_remove (gpointer key, gpointer value, gpointer data){ ForeachRemoveData *fdata = data; SwfdecAsVariable *var = value; if (!fdata->func (fdata->object, key, &var->value, var->flags, fdata->data)) return FALSE; swfdec_as_object_free_property (NULL, var, fdata->object); return TRUE;}/** * swfdec_as_object_foreach_remove: * @object: a #SwfdecAsObject * @func: function that determines which object to remove * @data: data to pass to @func * * Removes all variables form @object where @func returns %TRUE. This is an * internal function for array operations. * * Returns: he number of variables removed **/guintswfdec_as_object_foreach_remove (SwfdecAsObject *object, SwfdecAsVariableForeach func, gpointer data){ ForeachRemoveData fdata = { object, func, data }; g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), 0); g_return_val_if_fail (func != NULL, 0); return g_hash_table_foreach_remove (object->properties, swfdec_as_object_hash_foreach_remove, &fdata);}typedef struct { SwfdecAsObject * object; GHashTable * properties_new; SwfdecAsVariableForeachRename func; gpointer data;} ForeachRenameData;static gbooleanswfdec_as_object_hash_foreach_rename (gpointer key, gpointer value, gpointer data){ ForeachRenameData *fdata = data; SwfdecAsVariable *var = value; const char *key_new; key_new = fdata->func (fdata->object, key, &var->value, var->flags, fdata->data); if (key_new) { g_hash_table_insert (fdata->properties_new, (gpointer) key_new, var); } else { swfdec_as_object_free_property (NULL, var, fdata->object); } return TRUE;}/** * swfdec_as_object_foreach_rename: * @object: a #SwfdecAsObject * @func: function determining the new name
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -