[Swfdec-commits] 9 commits - swfdec/Makefile.am swfdec/swfdec_as_context.c swfdec/swfdec_as_context.h swfdec/swfdec_as_frame.c swfdec/swfdec_as_frame_internal.h swfdec/swfdec_as_interpret.c swfdec/swfdec_constant_pool.c swfdec/swfdec_constant_pool.h swfdec/swfdec_resource.c swfdec/swfdec_script.c swfdec/swfdec_script_internal.h swfdec/swfdec_stream.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Tue Mar 25 14:56:43 PDT 2008


 swfdec/Makefile.am                                 |    2 
 swfdec/swfdec_as_context.c                         |   17 +
 swfdec/swfdec_as_context.h                         |    3 
 swfdec/swfdec_as_frame.c                           |   15 -
 swfdec/swfdec_as_frame_internal.h                  |    1 
 swfdec/swfdec_as_interpret.c                       |   24 +-
 swfdec/swfdec_constant_pool.c                      |  199 +++++++++++++++++++++
 swfdec/swfdec_constant_pool.h                      |   47 ++++
 swfdec/swfdec_resource.c                           |   13 -
 swfdec/swfdec_script.c                             |   77 --------
 swfdec/swfdec_script_internal.h                    |   13 -
 swfdec/swfdec_stream.c                             |    4 
 test/trace/crash-0.6.0-moviecliploader-7.swf.trace |    2 
 test/trace/crash-0.6.0-moviecliploader-8.swf.trace |    2 
 14 files changed, 298 insertions(+), 121 deletions(-)

New commits:
commit 87b32475634a25e9e22a087a00b14c631ab5ff6c
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 22:38:38 2008 +0100

    really abort when it's not a Flash file

diff --git a/swfdec/swfdec_resource.c b/swfdec/swfdec_resource.c
index 88cef97..57cd544 100644
--- a/swfdec/swfdec_resource.c
+++ b/swfdec/swfdec_resource.c
@@ -322,14 +322,15 @@ swfdec_resource_stream_target_parse (SwfdecStreamTarget *target, SwfdecStream *s
   return FALSE;
 }
 
-static void
+static gboolean
 swfdec_resource_abort_if_not_initialized (SwfdecResource *resource)
 {
   if (resource->sandbox)
-    return;
+    return FALSE;
 
   swfdec_as_context_abort (SWFDEC_AS_OBJECT (resource)->context,
       "This is not a Flash file");
+  return TRUE;
 }
 
 static void
@@ -349,7 +350,8 @@ swfdec_resource_stream_target_close (SwfdecStreamTarget *target, SwfdecStream *s
   SWFDEC_AS_VALUE_SET_INT (&val, 0); /* FIXME */
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
   resource->state = SWFDEC_RESOURCE_COMPLETE;
-  swfdec_resource_abort_if_not_initialized (resource);
+  if (swfdec_resource_abort_if_not_initialized (resource))
+    return;
 
   if (resource->movie != NULL) {
     swfdec_player_add_action (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context),
commit 4de4ea0a7b3d6f3410e49dda31264654aaba7b01
Merge: bf8dfe1... 6cf304b...
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 22:18:54 2008 +0100

    Merge branch '0.6'
    
    Conflicts:
    
    	test/trace/crash-0.6.0-moviecliploader-7.swf.trace
    	test/trace/crash-0.6.0-moviecliploader-8.swf.trace

commit 6cf304b397fec8b7f500ab39d2e8aae468fbdf65
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 22:02:08 2008 +0100

    cope better with errors during parsing that unset the target

diff --git a/swfdec/swfdec_stream.c b/swfdec/swfdec_stream.c
index de3d3ab..40944c9 100644
--- a/swfdec/swfdec_stream.c
+++ b/swfdec/swfdec_stream.c
@@ -215,9 +215,11 @@ swfdec_stream_process (gpointer streamp, gpointer unused)
 	if (swfdec_stream_target_parse (priv->target, stream)) {
 	  swfdec_stream_queue_processing (stream);
 	  goto out;
-	} else {
+	} else if (priv->target) {
 	  priv->processed_state = SWFDEC_STREAM_STATE_CLOSED;
 	  swfdec_stream_target_close (priv->target, stream);
+	} else {
+	  goto out;
 	}
       }
     }
commit 7276aa19b340f9dc817d3d604e2579e0268b1d6d
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 22:01:41 2008 +0100

    if we get a security error, keep using the old sandbox

diff --git a/swfdec/swfdec_resource.c b/swfdec/swfdec_resource.c
index ed64f7d..e07b15b 100644
--- a/swfdec/swfdec_resource.c
+++ b/swfdec/swfdec_resource.c
@@ -76,7 +76,9 @@ swfdec_resource_stream_target_image (SwfdecResource *instance)
 
   if (SWFDEC_IS_SWF_DECODER (instance->decoder)) {
     SwfdecSwfDecoder *dec = SWFDEC_SWF_DECODER (instance->decoder);
+    SwfdecSandbox *old_sandbox;
 
+    old_sandbox = instance->sandbox;
     instance->sandbox = swfdec_sandbox_get_for_url (player,
 	swfdec_loader_get_url (instance->loader), instance->version,
 	SWFDEC_SWF_DECODER (instance->decoder)->use_network);
@@ -95,7 +97,8 @@ swfdec_resource_stream_target_image (SwfdecResource *instance)
       SWFDEC_FIXME ("cannot continue loading %s, invalid rights", 
 	  swfdec_url_get_url (swfdec_loader_get_url (instance->loader)));
       swfdec_stream_set_target (SWFDEC_STREAM (instance->loader), NULL);
-      /* FIXME: anyting on the movie we need to clear? */
+      instance->sandbox = old_sandbox;
+      /* FIXME: anyting else on the movie we need to clear? */
     }
   } else {
     g_assert_not_reached ();
commit 7db2e30e6ad05c7d6753360d193db9e64bb6aa9a
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 22:00:35 2008 +0100

    remove debugging info from traces

diff --git a/test/trace/crash-0.6.0-moviecliploader-7.swf.trace b/test/trace/crash-0.6.0-moviecliploader-7.swf.trace
index 9b2ccc2..7696e88 100644
--- a/test/trace/crash-0.6.0-moviecliploader-7.swf.trace
+++ b/test/trace/crash-0.6.0-moviecliploader-7.swf.trace
@@ -1,4 +1,2 @@
 Start
-*** Security Sandbox Violation ***
-Connection to file:///home/medar/Projects/Flash/swfdec/test/pending/getvariable-exhaustive-8.swf halted - not permitted from file:///home/medar/Projects/Flash/swfdec/test/pending/crash-0.6.0-moviecliploader-7.swf
 Done
diff --git a/test/trace/crash-0.6.0-moviecliploader-8.swf.trace b/test/trace/crash-0.6.0-moviecliploader-8.swf.trace
index e87c7b5..7696e88 100644
--- a/test/trace/crash-0.6.0-moviecliploader-8.swf.trace
+++ b/test/trace/crash-0.6.0-moviecliploader-8.swf.trace
@@ -1,4 +1,2 @@
 Start
-*** Security Sandbox Violation ***
-Connection to file:///home/medar/Projects/Flash/swfdec/test/pending/getvariable-exhaustive-8.swf halted - not permitted from file:///home/medar/Projects/Flash/swfdec/test/pending/crash-0.6.0-moviecliploader-8.swf
 Done
commit 34603bcdc4ab6d2f0ff8f4bb1b56965b97202907
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 21 22:16:54 2008 +0100

    update to min API changes

diff --git a/vivified/core/vivi_ming.c b/vivified/core/vivi_ming.c
index a126455..c015c1a 100644
--- a/vivified/core/vivi_ming.c
+++ b/vivified/core/vivi_ming.c
@@ -88,7 +88,7 @@ vivi_ming_compile (const char *code, char **error)
 {
   byte *data;
   SWFAction action;
-  gsize len;
+  gssize len;
   SwfdecBuffer *buffer;
   SwfdecScript *script;
 
commit c366dd172877c5e2d04a901dd84eccb4bb334a0e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Feb 26 14:44:10 2008 +0200

    Add a test for assert in MovieClipLoader

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 3a26cbd..f6d1fdf 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -713,6 +713,11 @@ EXTRA_DIST = \
 	crash-0.5.90-empty-action.swf \
 	crash-0.5.90-empty-action.swf.trace \
 	crash-0.5.90-empty-action.xml \
+	crash-0.6.0-moviecliploader.as \
+	crash-0.6.0-moviecliploader-7.swf \
+	crash-0.6.0-moviecliploader-7.swf.trace \
+	crash-0.6.0-moviecliploader-8.swf \
+	crash-0.6.0-moviecliploader-8.swf.trace \
 	currentframe.swf \
 	currentframe.swf.trace \
 	dangling-compare.as \
diff --git a/test/trace/crash-0.6.0-moviecliploader-7.swf b/test/trace/crash-0.6.0-moviecliploader-7.swf
new file mode 100644
index 0000000..6439c1c
Binary files /dev/null and b/test/trace/crash-0.6.0-moviecliploader-7.swf differ
diff --git a/test/trace/crash-0.6.0-moviecliploader-7.swf.trace b/test/trace/crash-0.6.0-moviecliploader-7.swf.trace
new file mode 100644
index 0000000..9b2ccc2
--- /dev/null
+++ b/test/trace/crash-0.6.0-moviecliploader-7.swf.trace
@@ -0,0 +1,4 @@
+Start
+*** Security Sandbox Violation ***
+Connection to file:///home/medar/Projects/Flash/swfdec/test/pending/getvariable-exhaustive-8.swf halted - not permitted from file:///home/medar/Projects/Flash/swfdec/test/pending/crash-0.6.0-moviecliploader-7.swf
+Done
diff --git a/test/trace/crash-0.6.0-moviecliploader-8.swf b/test/trace/crash-0.6.0-moviecliploader-8.swf
new file mode 100644
index 0000000..aed18d2
Binary files /dev/null and b/test/trace/crash-0.6.0-moviecliploader-8.swf differ
diff --git a/test/trace/crash-0.6.0-moviecliploader-8.swf.trace b/test/trace/crash-0.6.0-moviecliploader-8.swf.trace
new file mode 100644
index 0000000..e87c7b5
--- /dev/null
+++ b/test/trace/crash-0.6.0-moviecliploader-8.swf.trace
@@ -0,0 +1,4 @@
+Start
+*** Security Sandbox Violation ***
+Connection to file:///home/medar/Projects/Flash/swfdec/test/pending/getvariable-exhaustive-8.swf halted - not permitted from file:///home/medar/Projects/Flash/swfdec/test/pending/crash-0.6.0-moviecliploader-8.swf
+Done
diff --git a/test/trace/crash-0.6.0-moviecliploader.as b/test/trace/crash-0.6.0-moviecliploader.as
new file mode 100644
index 0000000..5b62d8f
--- /dev/null
+++ b/test/trace/crash-0.6.0-moviecliploader.as
@@ -0,0 +1,16 @@
+// makeswf -n -v 7 -r 1 -o crash-0.6.0-moviecliploader.swf crash-0.6.0-moviecliploader.as
+
+// NOTE: Has to be compiled with -n
+
+trace ("Start");
+
+this.createEmptyMovieClip ("a", 0);
+var l = new MovieClipLoader ();
+l.loadClip ("getvariable-exhaustive-8.swf", a);
+
+function quit () {
+  trace ("Done");
+  loadMovie ("FSCommand:quit", "");
+}
+
+setInterval (quit, 2000);
commit bf8dfe10bbccc51c3d1928f555a5a577adbd279f
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 19:55:04 2008 +0100

    rewrite constant pools
    
    Constant pools are now automatically garbage collected and keep the buffer they
    refer to available.

diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index c75f15a..0d0bef3 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -36,6 +36,7 @@
 #include "swfdec_as_stack.h"
 #include "swfdec_as_strings.h"
 #include "swfdec_as_types.h"
+#include "swfdec_constant_pool.h"
 #include "swfdec_debug.h"
 #include "swfdec_internal.h" /* for swfdec_player_preinit_global() */
 #include "swfdec_script.h"
@@ -380,6 +381,18 @@ swfdec_as_context_mark_roots (gpointer key, gpointer value, gpointer data)
     swfdec_as_object_mark (object);
 }
 
+/* FIXME: replace this with refcounted strings? */
+static void 
+swfdec_as_context_mark_constant_pools (gpointer key, gpointer value, gpointer unused)
+{
+  SwfdecConstantPool *pool = value;
+  guint i;
+
+  for (i = 0; i < swfdec_constant_pool_size (pool); i++) {
+    swfdec_as_string_mark (swfdec_constant_pool_get (pool, i));
+  }
+}
+
 static void
 swfdec_as_context_do_mark (SwfdecAsContext *context)
 {
@@ -394,6 +407,7 @@ swfdec_as_context_do_mark (SwfdecAsContext *context)
   if (context->exception)
     swfdec_as_value_mark (&context->exception_value);
   g_hash_table_foreach (context->objects, swfdec_as_context_mark_roots, NULL);
+  g_hash_table_foreach (context->constant_pools, swfdec_as_context_mark_constant_pools, NULL);
 }
 
 /**
@@ -524,6 +538,8 @@ swfdec_as_context_dispose (GObject *object)
     g_critical ("%zu bytes of memory left over\n", context->memory);
   }
   g_assert (g_hash_table_size (context->objects) == 0);
+  g_assert (g_hash_table_size (context->constant_pools) == 0);
+  g_hash_table_destroy (context->constant_pools);
   g_hash_table_destroy (context->objects);
   g_hash_table_destroy (context->strings);
   g_rand_free (context->rand);
@@ -583,6 +599,7 @@ swfdec_as_context_init (SwfdecAsContext *context)
 
   context->strings = g_hash_table_new (g_str_hash, g_str_equal);
   context->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
+  context->constant_pools = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   for (s = swfdec_as_strings; *s == '\2'; s += strlen (s) + 1) {
     g_hash_table_insert (context->strings, (char *) s + 1, (char *) s);
diff --git a/swfdec/swfdec_as_context.h b/swfdec/swfdec_as_context.h
index 3f1ed1e..8cb877b 100644
--- a/swfdec/swfdec_as_context.h
+++ b/swfdec/swfdec_as_context.h
@@ -56,8 +56,9 @@ struct _SwfdecAsContext {
   /* bookkeeping for GC */
   gsize			memory;		/* total memory currently in use */
   gsize			memory_since_gc;/* memory allocated since last GC run */
-  GHashTable *		strings;	/* string=>memory mapping the context manages */
+  GHashTable *		strings;	/* string => memory mapping the context manages */
   GHashTable *		objects;	/* all objects the context manages */
+  GHashTable *		constant_pools;	/* memory address => SwfdecConstantPool for all gc'ed pools */
 
   /* execution state */
   unsigned int	      	version;	/* currently active version */
diff --git a/swfdec/swfdec_as_frame.c b/swfdec/swfdec_as_frame.c
index 39888b6..d4bf392 100644
--- a/swfdec/swfdec_as_frame.c
+++ b/swfdec/swfdec_as_frame.c
@@ -278,13 +278,9 @@ swfdec_as_frame_dispose (GObject *object)
   /* clean up */
   g_slice_free1 (sizeof (SwfdecAsValue) * frame->n_registers, frame->registers);
   if (frame->constant_pool) {
-    swfdec_constant_pool_free (frame->constant_pool);
+    swfdec_constant_pool_unref (frame->constant_pool);
     frame->constant_pool = NULL;
   }
-  if (frame->constant_pool_buffer) {
-    swfdec_buffer_unref (frame->constant_pool_buffer);
-    frame->constant_pool_buffer = NULL;
-  }
   g_array_free (frame->blocks, TRUE);
   g_slist_free (frame->scope_chain);
   if (frame->script) {
@@ -409,12 +405,9 @@ swfdec_as_frame_new (SwfdecAsContext *context, SwfdecScript *script)
   frame->n_registers = script->n_registers;
   frame->registers = g_slice_alloc0 (sizeof (SwfdecAsValue) * frame->n_registers);
   if (script->constant_pool) {
-    frame->constant_pool_buffer = swfdec_buffer_ref (script->constant_pool);
-    frame->constant_pool = swfdec_constant_pool_new_from_action (
-	script->constant_pool->data, script->constant_pool->length, script->version);
-    if (frame->constant_pool) {
-      swfdec_constant_pool_attach_to_context (frame->constant_pool, context);
-    } else {
+    frame->constant_pool = swfdec_constant_pool_new (context, 
+	script->constant_pool, script->version);
+    if (frame->constant_pool == NULL) {
       SWFDEC_ERROR ("couldn't create constant pool");
     }
   }
diff --git a/swfdec/swfdec_as_frame_internal.h b/swfdec/swfdec_as_frame_internal.h
index 07175a1..0dc9a5e 100644
--- a/swfdec/swfdec_as_frame_internal.h
+++ b/swfdec/swfdec_as_frame_internal.h
@@ -52,7 +52,6 @@ struct _SwfdecAsFrame {
   SwfdecAsValue *	registers;	/* the registers */
   guint			n_registers;	/* number of allocated registers */
   SwfdecConstantPool *	constant_pool;	/* constant pool currently in use */
-  SwfdecBuffer *	constant_pool_buffer;	/* buffer containing the raw data for constant_pool */
   SwfdecAsValue *	stack_begin;	/* beginning of stack */
   const guint8 *	pc;		/* program counter on stack */
   /* native function */
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index ff0a66c..3544a1b 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -287,19 +287,19 @@ swfdec_action_constant_pool (SwfdecAsContext *cx, guint action, const guint8 *da
 {
   SwfdecConstantPool *pool;
   SwfdecAsFrame *frame;
+  SwfdecBuffer *buffer;
 
   frame = cx->frame;
-  pool = swfdec_constant_pool_new_from_action (data, len, cx->version);
+  /* FIXME: lots of hackery to get at the buffer */
+  buffer = frame->script->buffer;
+  buffer = swfdec_buffer_new_subbuffer (buffer, data - buffer->data, len);
+  pool = swfdec_constant_pool_new (cx, buffer, cx->version);
+  swfdec_buffer_unref (buffer);
   if (pool == NULL)
     return;
-  swfdec_constant_pool_attach_to_context (pool, cx);
   if (frame->constant_pool)
-    swfdec_constant_pool_free (frame->constant_pool);
+    swfdec_constant_pool_unref (frame->constant_pool);
   frame->constant_pool = pool;
-  if (frame->constant_pool_buffer)
-    swfdec_buffer_unref (frame->constant_pool_buffer);
-  frame->constant_pool_buffer = swfdec_buffer_new_subbuffer (frame->script->buffer,
-      data - frame->script->buffer->data, len);
 }
 
 static void
@@ -1885,8 +1885,8 @@ swfdec_action_define_function (SwfdecAsContext *cx, guint action,
     g_free (function_name);
     return;
   }
-  if (frame->constant_pool_buffer)
-    script->constant_pool = swfdec_buffer_ref (frame->constant_pool_buffer);
+  if (frame->constant_pool)
+    script->constant_pool = swfdec_buffer_ref (swfdec_constant_pool_get_buffer (frame->constant_pool));
   script->flags = flags;
   script->n_registers = n_registers;
   script->n_arguments = n_args;
@@ -3059,9 +3059,11 @@ swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
   guint i;
   GString *string;
   SwfdecConstantPool *pool;
+  SwfdecBuffer *buffer;
 
   /* FIXME: version */
-  pool = swfdec_constant_pool_new_from_action (data, len, 6);
+  buffer = swfdec_buffer_new_static (data, len);
+  pool = swfdec_constant_pool_new (NULL, buffer, 6);
   if (pool == NULL)
     return g_strdup ("ConstantPool (invalid)");
   string = g_string_new ("ConstantPool");
@@ -3070,6 +3072,8 @@ swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
     g_string_append (string, swfdec_constant_pool_get (pool, i));
     g_string_append_printf (string, " (%u)", i);
   }
+  swfdec_constant_pool_unref (pool);
+  swfdec_buffer_unref (buffer);
   return g_string_free (string, FALSE);
 }
 
diff --git a/swfdec/swfdec_constant_pool.c b/swfdec/swfdec_constant_pool.c
index 2834a63..487af45 100644
--- a/swfdec/swfdec_constant_pool.c
+++ b/swfdec/swfdec_constant_pool.c
@@ -22,80 +22,178 @@
 #endif
 
 #include "swfdec_constant_pool.h"
+#include "swfdec_bits.h"
 #include "swfdec_debug.h"
 
 struct _SwfdecConstantPool {
   SwfdecAsContext *	context;	/* context we are attached to or NULL */
+  SwfdecBuffer *	buffer;		/* the buffer the strings were read from */
+  guint			refcount;	/* reference count */
   guint			n_strings;	/* number of strings */
   char *		strings[1];	/* n_strings strings */
 };
 
+/**
+ * swfdec_constant_pool_new:
+ * @context: a context to attach strings to or %NULL
+ * @buffer: buffer to read constant pool from
+ * @version: the Flash version to use when reading the strings
+ *
+ * Creates a new constant pool from the given @buffer. If the buffer is in the 
+ * wrong format, %NULL is returned. If a @context was given, the strings are 
+ * added to the context. This means the strings in the pool will be 
+ * garbage-collected already. When using a non-%NULL @context, the pool does 
+ * will not add a reference to the context. It is your responsibility to hold a
+ * reference to the context while you use the pool.
+ *
+ * Returns: a new constant pool or %NULL
+ **/
 SwfdecConstantPool *
-swfdec_constant_pool_new_from_action (const guint8 *data, guint len, guint version)
+swfdec_constant_pool_new (SwfdecAsContext *context, SwfdecBuffer *buffer, guint version)
 {
   guint i, n;
+  gsize size;
   SwfdecBits bits;
   SwfdecConstantPool *pool;
 
-  swfdec_bits_init_data (&bits, data, len);
+  g_return_val_if_fail (context == NULL || SWFDEC_IS_AS_CONTEXT (context), NULL);
+  g_return_val_if_fail (buffer != NULL, NULL);
+
+  /* try to find the pool in the context's cache */
+  if (context) {
+    pool = g_hash_table_lookup (context->constant_pools, buffer->data);
+    if (pool)
+      return swfdec_constant_pool_ref (pool);
+  }
+
+  swfdec_bits_init (&bits, buffer);
 
   n = swfdec_bits_get_u16 (&bits);
   if (n == 0)
     return NULL;
 
-  pool = g_malloc0 (sizeof (SwfdecConstantPool) + (n - 1) * sizeof (char *));
+  size = sizeof (SwfdecConstantPool) + (n - 1) * sizeof (char *);
+  pool = g_slice_alloc0 (size);
   pool->n_strings = n;
   for (i = 0; i < n; i++) {
     pool->strings[i] = swfdec_bits_get_string (&bits, version);
     if (pool->strings[i] == NULL) {
       SWFDEC_ERROR ("not enough strings available");
-      swfdec_constant_pool_free (pool);
+      g_slice_free1 (size, pool);
       return NULL;
     }
+    if (context)
+      pool->strings[i] = (char *) swfdec_as_context_give_string (context, pool->strings[i]);
   }
   if (swfdec_bits_left (&bits)) {
     SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", swfdec_bits_left (&bits) / 8);
   }
+  pool->buffer = swfdec_buffer_ref (buffer);
+  pool->refcount = 1;
+  /* put pool into the context's cache */
+  if (context) {
+    pool->context = context;
+    g_hash_table_insert (context->constant_pools, buffer->data, pool);
+  }
+  return pool;
+}
+
+/**
+ * swfdec_constant_pool_ref:
+ * @pool: a constant pool
+ *
+ * Increases the constant pool's reference by one.
+ *
+ * Returns: the passed in @pool.
+ **/
+SwfdecConstantPool *
+swfdec_constant_pool_ref (SwfdecConstantPool *pool)
+{
+  g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
+
+  pool->refcount++;
+
   return pool;
 }
 
+/**
+ * swfdec_constant_pool_unref:
+ * @pool: the pool to unref
+ *
+ * Removes a reference from the pool. If no more references are left, the pool
+ * will be freed.
+ **/
 void
-swfdec_constant_pool_attach_to_context (SwfdecConstantPool *pool, SwfdecAsContext *context)
+swfdec_constant_pool_unref (SwfdecConstantPool *pool)
 {
-  guint i;
+  g_return_if_fail (SWFDEC_IS_CONSTANT_POOL (pool));
+  g_return_if_fail (pool->refcount > 0);
 
-  g_return_if_fail (pool != NULL);
-  g_return_if_fail (pool->context == NULL);
-  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+  pool->refcount--;
+  if (pool->refcount)
+    return;
 
-  pool->context = context;
-  for (i = 0; i < pool->n_strings; i++) {
-    pool->strings[i] = (char *) swfdec_as_context_give_string (context, pool->strings[i]);
+  if (pool->context) {
+    g_hash_table_remove (pool->context->constant_pools, pool->buffer->data);
+  } else {
+    guint i;
+    for (i = 0; i < pool->n_strings; i++) {
+      g_free (pool->strings[i]);
+    }
   }
+  swfdec_buffer_unref (pool->buffer);
+  g_slice_free1 (sizeof (SwfdecConstantPool) + (pool->n_strings - 1) * sizeof (char *), pool);
 }
 
+/**
+ * swfdec_constant_pool_size:
+ * @pool: a pool
+ *
+ * Queries the number of strings in this pool.
+ *
+ * Returns: The number of strings in this @pool
+ **/
 guint
 swfdec_constant_pool_size (SwfdecConstantPool *pool)
 {
+  g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), 0);
+
   return pool->n_strings;
 }
 
+/**
+ * swfdec_constant_pool_get:
+ * @pool: a pool
+ * @i: index of the string to get
+ *
+ * Gets the requested string from the pool. The index must not excess the 
+ * number of elements in the pool. If the constant pool was created with a 
+ * context attached, the returned string will be garbage-collected already.
+ *
+ * Returns: the string at position @i
+ **/
 const char *
 swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
 {
-  g_assert (i < pool->n_strings);
+  g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
+  g_return_val_if_fail (i < pool->n_strings, NULL);
+
   return pool->strings[i];
 }
 
-void
-swfdec_constant_pool_free (SwfdecConstantPool *pool)
+/**
+ * swfdec_constant_pool_get_buffer:
+ * @pool: a constant pool
+ *
+ * Gets the buffer the pool was created from
+ *
+ * Returns: the buffer this pool was created from.
+ **/
+SwfdecBuffer *
+swfdec_constant_pool_get_buffer (SwfdecConstantPool *pool)
 {
-  if (pool->context == NULL) {
-    guint i;
-    for (i = 0; i < pool->n_strings; i++) {
-      g_free (pool->strings[i]);
-    }
-  }
-  g_free (pool);
+  g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
+
+  return pool->buffer;
 }
 
diff --git a/swfdec/swfdec_constant_pool.h b/swfdec/swfdec_constant_pool.h
index 675fa00..3592dbc 100644
--- a/swfdec/swfdec_constant_pool.h
+++ b/swfdec/swfdec_constant_pool.h
@@ -21,26 +21,25 @@
 #define _SWFDEC_CONSTANT_POOL_H_
 
 #include <swfdec/swfdec.h>
-#include <swfdec/swfdec_as_types.h>
-#include <swfdec/swfdec_types.h>
-#include <swfdec/swfdec_bits.h>
 
 G_BEGIN_DECLS
 
 
+#define SWFDEC_IS_CONSTANT_POOL(pool) ((pool) != NULL)
+
 typedef struct _SwfdecConstantPool SwfdecConstantPool;
 
 
-SwfdecConstantPool *
-		swfdec_constant_pool_new_from_action	(const guint8 *		data,
-							 guint			len,
+SwfdecConstantPool *	swfdec_constant_pool_new	(SwfdecAsContext *	context,
+							 SwfdecBuffer *		buffer,
 							 guint			version);
-void		swfdec_constant_pool_free	  	(SwfdecConstantPool *	pool);
-guint		swfdec_constant_pool_size		(SwfdecConstantPool *	pool);
-const char *	swfdec_constant_pool_get		(SwfdecConstantPool *	pool,
+SwfdecConstantPool *	swfdec_constant_pool_ref      	(SwfdecConstantPool *	pool);
+void			swfdec_constant_pool_unref     	(SwfdecConstantPool *	pool);
+
+guint			swfdec_constant_pool_size	(SwfdecConstantPool *	pool);
+const char *	  	swfdec_constant_pool_get	(SwfdecConstantPool *	pool,
 							 guint			i);
-void		swfdec_constant_pool_attach_to_context	(SwfdecConstantPool *	pool,
-							 SwfdecAsContext *	context);
+SwfdecBuffer *		swfdec_constant_pool_get_buffer	(SwfdecConstantPool *	pool);
 
 
 G_END_DECLS
commit 5d0f9f19c37a8d6f7e0f54418b437bd393b3dd32
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Mar 25 12:07:30 2008 +0100

    split out constant pool handling into its own file

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 217b5c0..aacb161 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -64,6 +64,7 @@ libswfdec_source_files = \
 	swfdec_color_as.c \
 	swfdec_color_matrix_filter.c \
 	swfdec_color_transform.c \
+	swfdec_constant_pool.c \
 	swfdec_convolution_filter.c \
 	swfdec_debug.c \
 	swfdec_decoder.c \
@@ -231,6 +232,7 @@ noinst_HEADERS = \
 	swfdec_codec_audio.h \
 	swfdec_codec_video.h \
 	swfdec_color.h \
+	swfdec_constant_pool.h \
 	swfdec_debug.h \
 	swfdec_decoder.h \
 	swfdec_draw.h \
diff --git a/swfdec/swfdec_constant_pool.c b/swfdec/swfdec_constant_pool.c
new file mode 100644
index 0000000..2834a63
--- /dev/null
+++ b/swfdec/swfdec_constant_pool.c
@@ -0,0 +1,101 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 "swfdec_constant_pool.h"
+#include "swfdec_debug.h"
+
+struct _SwfdecConstantPool {
+  SwfdecAsContext *	context;	/* context we are attached to or NULL */
+  guint			n_strings;	/* number of strings */
+  char *		strings[1];	/* n_strings strings */
+};
+
+SwfdecConstantPool *
+swfdec_constant_pool_new_from_action (const guint8 *data, guint len, guint version)
+{
+  guint i, n;
+  SwfdecBits bits;
+  SwfdecConstantPool *pool;
+
+  swfdec_bits_init_data (&bits, data, len);
+
+  n = swfdec_bits_get_u16 (&bits);
+  if (n == 0)
+    return NULL;
+
+  pool = g_malloc0 (sizeof (SwfdecConstantPool) + (n - 1) * sizeof (char *));
+  pool->n_strings = n;
+  for (i = 0; i < n; i++) {
+    pool->strings[i] = swfdec_bits_get_string (&bits, version);
+    if (pool->strings[i] == NULL) {
+      SWFDEC_ERROR ("not enough strings available");
+      swfdec_constant_pool_free (pool);
+      return NULL;
+    }
+  }
+  if (swfdec_bits_left (&bits)) {
+    SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", swfdec_bits_left (&bits) / 8);
+  }
+  return pool;
+}
+
+void
+swfdec_constant_pool_attach_to_context (SwfdecConstantPool *pool, SwfdecAsContext *context)
+{
+  guint i;
+
+  g_return_if_fail (pool != NULL);
+  g_return_if_fail (pool->context == NULL);
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+
+  pool->context = context;
+  for (i = 0; i < pool->n_strings; i++) {
+    pool->strings[i] = (char *) swfdec_as_context_give_string (context, pool->strings[i]);
+  }
+}
+
+guint
+swfdec_constant_pool_size (SwfdecConstantPool *pool)
+{
+  return pool->n_strings;
+}
+
+const char *
+swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
+{
+  g_assert (i < pool->n_strings);
+  return pool->strings[i];
+}
+
+void
+swfdec_constant_pool_free (SwfdecConstantPool *pool)
+{
+  if (pool->context == NULL) {
+    guint i;
+    for (i = 0; i < pool->n_strings; i++) {
+      g_free (pool->strings[i]);
+    }
+  }
+  g_free (pool);
+}
+
diff --git a/swfdec/swfdec_constant_pool.h b/swfdec/swfdec_constant_pool.h
new file mode 100644
index 0000000..675fa00
--- /dev/null
+++ b/swfdec/swfdec_constant_pool.h
@@ -0,0 +1,48 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef _SWFDEC_CONSTANT_POOL_H_
+#define _SWFDEC_CONSTANT_POOL_H_
+
+#include <swfdec/swfdec.h>
+#include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_types.h>
+#include <swfdec/swfdec_bits.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecConstantPool SwfdecConstantPool;
+
+
+SwfdecConstantPool *
+		swfdec_constant_pool_new_from_action	(const guint8 *		data,
+							 guint			len,
+							 guint			version);
+void		swfdec_constant_pool_free	  	(SwfdecConstantPool *	pool);
+guint		swfdec_constant_pool_size		(SwfdecConstantPool *	pool);
+const char *	swfdec_constant_pool_get		(SwfdecConstantPool *	pool,
+							 guint			i);
+void		swfdec_constant_pool_attach_to_context	(SwfdecConstantPool *	pool,
+							 SwfdecAsContext *	context);
+
+
+G_END_DECLS
+
+#endif
diff --git a/swfdec/swfdec_script.c b/swfdec/swfdec_script.c
index 66eeed0..d96b065 100644
--- a/swfdec/swfdec_script.c
+++ b/swfdec/swfdec_script.c
@@ -40,83 +40,6 @@
  * but usually just causes a lot of spam. */
 //#define SWFDEC_WARN_MISSING_PROPERTIES
 
-/*** CONSTANT POOLS ***/
-
-struct _SwfdecConstantPool {
-  SwfdecAsContext *	context;	/* context we are attached to or NULL */
-  guint			n_strings;	/* number of strings */
-  char *		strings[1];	/* n_strings strings */
-};
-
-SwfdecConstantPool *
-swfdec_constant_pool_new_from_action (const guint8 *data, guint len, guint version)
-{
-  guint i, n;
-  SwfdecBits bits;
-  SwfdecConstantPool *pool;
-
-  swfdec_bits_init_data (&bits, data, len);
-
-  n = swfdec_bits_get_u16 (&bits);
-  if (n == 0)
-    return NULL;
-
-  pool = g_malloc0 (sizeof (SwfdecConstantPool) + (n - 1) * sizeof (char *));
-  pool->n_strings = n;
-  for (i = 0; i < n; i++) {
-    pool->strings[i] = swfdec_bits_get_string (&bits, version);
-    if (pool->strings[i] == NULL) {
-      SWFDEC_ERROR ("not enough strings available");
-      swfdec_constant_pool_free (pool);
-      return NULL;
-    }
-  }
-  if (swfdec_bits_left (&bits)) {
-    SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", swfdec_bits_left (&bits) / 8);
-  }
-  return pool;
-}
-
-void
-swfdec_constant_pool_attach_to_context (SwfdecConstantPool *pool, SwfdecAsContext *context)
-{
-  guint i;
-
-  g_return_if_fail (pool != NULL);
-  g_return_if_fail (pool->context == NULL);
-  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
-
-  pool->context = context;
-  for (i = 0; i < pool->n_strings; i++) {
-    pool->strings[i] = (char *) swfdec_as_context_give_string (context, pool->strings[i]);
-  }
-}
-
-guint
-swfdec_constant_pool_size (SwfdecConstantPool *pool)
-{
-  return pool->n_strings;
-}
-
-const char *
-swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
-{
-  g_assert (i < pool->n_strings);
-  return pool->strings[i];
-}
-
-void
-swfdec_constant_pool_free (SwfdecConstantPool *pool)
-{
-  if (pool->context == NULL) {
-    guint i;
-    for (i = 0; i < pool->n_strings; i++) {
-      g_free (pool->strings[i]);
-    }
-  }
-  g_free (pool);
-}
-
 /*** SUPPORT FUNCTIONS ***/
 
 char *
diff --git a/swfdec/swfdec_script_internal.h b/swfdec/swfdec_script_internal.h
index 8dc4308..3546b3d 100644
--- a/swfdec/swfdec_script_internal.h
+++ b/swfdec/swfdec_script_internal.h
@@ -24,11 +24,11 @@
 #include <swfdec/swfdec_as_types.h>
 #include <swfdec/swfdec_types.h>
 #include <swfdec/swfdec_bits.h>
+#include <swfdec/swfdec_constant_pool.h>
 
 G_BEGIN_DECLS
 
 typedef struct _SwfdecScriptArgument SwfdecScriptArgument;
-typedef struct _SwfdecConstantPool SwfdecConstantPool;
 
 typedef enum {
   SWFDEC_SCRIPT_PRELOAD_THIS = (1 << 0),
@@ -68,17 +68,6 @@ struct _SwfdecScriptArgument {
 const char *	swfdec_action_get_name		(guint			action);
 guint		swfdec_action_get_from_name	(const char *		name);
 
-SwfdecConstantPool *
-		swfdec_constant_pool_new_from_action	(const guint8 *		data,
-							 guint			len,
-							 guint			version);
-void		swfdec_constant_pool_free	  	(SwfdecConstantPool *	pool);
-guint		swfdec_constant_pool_size		(SwfdecConstantPool *	pool);
-const char *	swfdec_constant_pool_get		(SwfdecConstantPool *	pool,
-							 guint			i);
-void		swfdec_constant_pool_attach_to_context	(SwfdecConstantPool *	pool,
-							 SwfdecAsContext *	context);
-
 SwfdecScript *	swfdec_script_new_from_bits   		(SwfdecBits *		bits,
 							 const char *		name,
 							 guint			version);


More information about the Swfdec-commits mailing list