[Swfdec] Branch 'interpreter' - 3 commits - libswfdec/swfdec_bits.c
libswfdec/swfdec_swf_decoder.c test/Makefile.am
test/swfedit.c test/swfedit_file.c test/swfedit_file.h
test/swfedit_tag.c test/swfedit_tag.h test/swfedit_token.c
test/swfedit_token.h
Benjamin Otte
company at kemper.freedesktop.org
Mon Jan 22 09:35:06 PST 2007
libswfdec/swfdec_bits.c | 27 +-
libswfdec/swfdec_swf_decoder.c | 46 ----
test/Makefile.am | 19 +
test/swfedit.c | 81 +++++++
test/swfedit_file.c | 209 ++++++++++++++++++
test/swfedit_file.h | 59 +++++
test/swfedit_tag.c | 61 +++++
test/swfedit_tag.h | 56 ++++
test/swfedit_token.c | 464 +++++++++++++++++++++++++++++++++++++++++
test/swfedit_token.h | 79 ++++++
10 files changed, 1054 insertions(+), 47 deletions(-)
New commits:
diff-tree 72caf9482e2e7eb4bdc6cc0fa7578beb31645bac (from ac526c14b6a853304588e1c71ccc0ab709ac072e)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:34:59 2007 +0100
add a first shot at an swf file editor that is supposed to allow creating
broken files for testing purposes when it's done
diff --git a/test/Makefile.am b/test/Makefile.am
index 01c4f45..d168cfd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,10 @@
SUBDIRS = sound trace various
-noinst_PROGRAMS = swfdec-extract dump parse
+if WITH_GTK
+noinst_PROGRAMS = swfdec-extract dump parse swfedit
+else
+noinst_PROGRAMS = swfdec-extract dump parse
+endif
dump_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(PANGO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
dump_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
@@ -11,3 +15,16 @@ parse_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS
swfdec_extract_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
swfdec_extract_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
+
+swfedit_SOURCES = \
+ swfedit.c \
+ swfedit_file.c \
+ swfedit_tag.c \
+ swfedit_token.c
+
+noinst_HEADERS = \
+ swfedit_file.h \
+ swfedit_tag.h \
+ swfedit_token.h
diff --git a/test/swfedit.c b/test/swfedit.c
new file mode 100644
index 0000000..76fa744
--- /dev/null
+++ b/test/swfedit.c
@@ -0,0 +1,81 @@
+/* Swfedit
+ * 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 <gtk/gtk.h>
+#include "swfedit_file.h"
+
+static gboolean
+open_window (char *filename)
+{
+ SwfeditFile *file;
+ GtkWidget *window, *treeview;
+ GError *error = NULL;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ file = swfedit_file_new (filename, &error);
+ if (file == NULL) {
+ g_printerr ("Error openeing file %s: %s\n", filename, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file));
+ gtk_container_add (GTK_CONTAINER (window), treeview);
+ gtk_widget_show_all (window);
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
+ "text", SWFEDIT_COLUMN_NAME, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
+ "text", SWFEDIT_COLUMN_VALUE, "visible", SWFEDIT_COLUMN_VALUE_VISIBLE, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+ return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+ gtk_init (&argc, &argv);
+
+ if (argc <= 1) {
+ g_print ("Usage: %s FILENAME\n", argv[0]);
+ return 1;
+ }
+ if (open_window (argv[1])) {
+ gtk_main ();
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
new file mode 100644
index 0000000..e995c1b
--- /dev/null
+++ b/test/swfedit_file.c
@@ -0,0 +1,209 @@
+/* Swfedit
+ * 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 <zlib.h>
+
+#include "libswfdec/swfdec_bits.h"
+#include "libswfdec/swfdec_buffer.h"
+#include "libswfdec/swfdec_debug.h"
+#include "swfedit_file.h"
+#include "swfedit_tag.h"
+
+G_DEFINE_TYPE (SwfeditFile, swfedit_file, SWFEDIT_TYPE_TOKEN)
+
+static void
+swfedit_file_dispose (GObject *object)
+{
+ SwfeditFile *file = SWFEDIT_FILE (object);
+
+ g_list_foreach (file->tags, (GFunc) g_object_unref, NULL);
+ g_list_free (file->tags);
+ g_free (file->filename);
+
+ G_OBJECT_CLASS (swfedit_file_parent_class)->dispose (object);
+}
+
+static void *
+zalloc (void *opaque, unsigned int items, unsigned int size)
+{
+ return g_malloc (items * size);
+}
+
+static void
+zfree (void *opaque, void *addr)
+{
+ g_free (addr);
+}
+
+static SwfdecBuffer *
+swfenc_file_inflate (SwfdecBits *bits, guint size)
+{
+ SwfdecBuffer *decoded, *encoded;
+ z_stream z;
+ int ret;
+
+ encoded = swfdec_bits_get_buffer (bits, -1);
+ if (encoded == NULL)
+ return NULL;
+ decoded = swfdec_buffer_new_and_alloc (size);
+ z.zalloc = zalloc;
+ z.zfree = zfree;
+ z.opaque = NULL;
+ z.next_in = encoded->data;
+ z.avail_in = encoded->length;
+ z.next_out = decoded->data;
+ z.avail_out = decoded->length;
+ ret = inflateInit (&z);
+ SWFDEC_DEBUG ("inflateInit returned %d", ret);
+ if (ret >= Z_OK) {
+ ret = inflate (&z, Z_SYNC_FLUSH);
+ SWFDEC_DEBUG ("inflate returned %d", ret);
+ }
+ inflateEnd (&z);
+ swfdec_buffer_unref (encoded);
+ if (ret < Z_OK) {
+ swfdec_buffer_unref (decoded);
+ return NULL;
+ }
+ return decoded;
+}
+
+static SwfdecBuffer *
+swf_parse_header1 (SwfeditFile *file, SwfdecBits *bits, GError **error)
+{
+ guint sig1, sig2, sig3, bytes_total;
+
+ sig1 = swfdec_bits_get_u8 (bits);
+ sig2 = swfdec_bits_get_u8 (bits);
+ sig3 = swfdec_bits_get_u8 (bits);
+ if ((sig1 != 'F' && sig1 != 'C') || sig2 != 'W' || sig3 != 'S') {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "This is not a SWF file");
+ return NULL;
+ }
+
+ swfedit_token_add (SWFEDIT_TOKEN (file), "version", SWFEDIT_TOKEN_UINT8,
+ GUINT_TO_POINTER (swfdec_bits_get_u8 (bits)));
+ bytes_total = swfdec_bits_get_u32 (bits);
+
+ if (sig1 == 'C') {
+ /* compressed */
+ SwfdecBuffer *ret = swfenc_file_inflate (bits, bytes_total);
+ if (ret == NULL)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Unable to uncompress file");
+ return ret;
+ } else {
+ SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, -1);
+ if (ret == NULL)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "File too small");
+ return ret;
+ }
+}
+
+static void
+swf_parse_header2 (SwfeditFile *file, SwfdecBits *bits)
+{
+ SwfdecRect rect;
+
+ swfdec_bits_get_rect (bits, &rect);
+ swfdec_bits_syncbits (bits);
+ swfedit_token_add (SWFEDIT_TOKEN (file), "rate", SWFEDIT_TOKEN_UINT16,
+ GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
+ swfedit_token_add (SWFEDIT_TOKEN (file), "frames", SWFEDIT_TOKEN_UINT16,
+ GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
+}
+
+static gboolean
+swfedit_file_parse (SwfeditFile *file, SwfdecBits *bits, GError **error)
+{
+ SwfdecBuffer *next;
+
+ next = swf_parse_header1 (file, bits, error);
+ if (next == NULL)
+ return FALSE;
+ swfdec_bits_init (bits, next);
+ swf_parse_header2 (file, bits);
+
+ while (swfdec_bits_left (bits)) {
+ guint x = swfdec_bits_get_u16 (bits);
+ G_GNUC_UNUSED guint tag = (x >> 6) & 0x3ff;
+ guint tag_len = x & 0x3f;
+ SwfdecBuffer *buffer;
+ SwfeditTag *item;
+ char *name;
+ if (tag_len == 0x3f)
+ tag_len = swfdec_bits_get_u32 (bits);
+ if (tag_len > 0)
+ buffer = swfdec_bits_get_buffer (bits, tag_len);
+ else
+ buffer = swfdec_buffer_new ();
+ if (buffer == NULL) {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Invalid contents in file");
+ return FALSE;
+ }
+ item = swfedit_tag_new (tag, buffer);
+ name = g_strdup_printf ("Tag %u", tag);
+ swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item);
+ g_free (name);
+ }
+ swfdec_buffer_unref (next);
+ return TRUE;
+}
+
+static void
+swfedit_file_class_init (SwfeditFileClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_file_dispose;
+}
+
+static void
+swfedit_file_init (SwfeditFile *s)
+{
+}
+
+SwfeditFile *
+swfedit_file_new (const char *filename, GError **error)
+{
+ SwfeditFile *file;
+ SwfdecBuffer *buffer;
+ SwfdecBits bits;
+
+ buffer = swfdec_buffer_new_from_file (filename, error);
+ if (buffer == NULL)
+ return NULL;
+ swfdec_bits_init (&bits, buffer);
+ file = g_object_new (SWFEDIT_TYPE_FILE, NULL);
+ file->filename = g_strdup (filename);
+ if (!swfedit_file_parse (file, &bits, error)) {
+ swfdec_buffer_unref (buffer);
+ g_object_unref (file);
+ return NULL;
+ }
+ swfdec_buffer_unref (buffer);
+ return file;
+}
diff --git a/test/swfedit_file.h b/test/swfedit_file.h
new file mode 100644
index 0000000..39a89c5
--- /dev/null
+++ b/test/swfedit_file.h
@@ -0,0 +1,59 @@
+/* Swfedit
+ * 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 __SWFEDIT_FILE_H__
+#define __SWFEDIT_FILE_H__
+
+#include <libswfdec/swfdec_rect.h>
+#include "swfedit_token.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SwfeditFile SwfeditFile;
+typedef struct _SwfeditFileClass SwfeditFileClass;
+
+#define SWFEDIT_TYPE_FILE (swfedit_file_get_type())
+#define SWFEDIT_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_FILE))
+#define SWFEDIT_IS_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_FILE))
+#define SWFEDIT_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_FILE, SwfeditFile))
+#define SWFEDIT_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_FILE, SwfeditFileClass))
+#define SWFEDIT_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_FILE, SwfeditFileClass))
+
+struct _SwfeditFile {
+ SwfeditToken token;
+
+ char * filename; /* name this file is saved to */
+
+ /* defined objects */
+ GList * tags; /* ordered list of all tags in the file */
+};
+
+struct _SwfeditFileClass {
+ SwfeditTokenClass token_class;
+};
+
+GType swfedit_file_get_type (void);
+
+SwfeditFile * swfedit_file_new (const char * filename,
+ GError ** error);
+
+
+G_END_DECLS
+
+#endif
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
new file mode 100644
index 0000000..9bbebeb
--- /dev/null
+++ b/test/swfedit_tag.c
@@ -0,0 +1,61 @@
+/* Swfedit
+ * 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 <stdlib.h>
+#include <gtk/gtk.h>
+#include "swfedit_tag.h"
+
+G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN)
+
+static void
+swfedit_tag_dispose (GObject *object)
+{
+ //SwfeditTag *tag = SWFEDIT_TAG (object);
+
+ G_OBJECT_CLASS (swfedit_tag_parent_class)->dispose (object);
+}
+
+static void
+swfedit_tag_class_init (SwfeditTagClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_tag_dispose;
+}
+
+static void
+swfedit_tag_init (SwfeditTag *tag)
+{
+}
+
+SwfeditTag *
+swfedit_tag_new (guint tag, SwfdecBuffer *buffer)
+{
+ SwfeditTag *item;
+
+ item = g_object_new (SWFEDIT_TYPE_TAG, NULL);
+ item->tag = tag;
+ swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
+ return item;
+}
+
diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h
new file mode 100644
index 0000000..aad879e
--- /dev/null
+++ b/test/swfedit_tag.h
@@ -0,0 +1,56 @@
+/* Swfedit
+ * 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 __SWFEDIT_TAG_H__
+#define __SWFEDIT_TAG_H__
+
+#include <libswfdec/swfdec_buffer.h>
+#include "swfedit_token.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SwfeditTag SwfeditTag;
+typedef struct _SwfeditTagClass SwfeditTagClass;
+
+#define SWFEDIT_TYPE_TAG (swfedit_tag_get_type())
+#define SWFEDIT_IS_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_TAG))
+#define SWFEDIT_IS_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_TAG))
+#define SWFEDIT_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_TAG, SwfeditTag))
+#define SWFEDIT_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TAG, SwfeditTagClass))
+#define SWFEDIT_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TAG, SwfeditTagClass))
+
+struct _SwfeditTag {
+ SwfeditToken token;
+
+ guint tag; /* tag type */
+};
+
+struct _SwfeditTagClass {
+ SwfeditTokenClass token_class;
+};
+
+GType swfedit_tag_get_type (void);
+
+SwfeditTag * swfedit_tag_new (guint tag,
+ SwfdecBuffer * buffer);
+
+
+G_END_DECLS
+
+#endif
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
new file mode 100644
index 0000000..78951f2
--- /dev/null
+++ b/test/swfedit_token.c
@@ -0,0 +1,464 @@
+/* Swfedit
+ * 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 <stdlib.h>
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec_buffer.h>
+#include "swfedit_token.h"
+
+/*** CONVERTERS ***/
+
+static gboolean
+swfedit_binary_read (const char *s, gpointer* result)
+{
+ GByteArray *array = g_byte_array_new ();
+ guint8 byte;
+
+ while (g_ascii_isspace (*s)) s++;
+ do {
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ break;
+ s++;
+ byte *= 255;
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ break;
+ s++;
+ g_byte_array_append (array, &byte, 1);
+ while (g_ascii_isspace (*s)) s++;
+ } while (TRUE);
+ if (*s == '\0') {
+ SwfdecBuffer *buffer = swfdec_buffer_new ();
+ buffer->length = array->len;
+ buffer->data = array->data;
+ g_byte_array_free (array, FALSE);
+ *result = buffer;
+ return TRUE;
+ }
+ g_byte_array_free (array, TRUE);
+ return FALSE;
+}
+
+static char *
+swfedit_binary_write (gconstpointer value)
+{
+ guint i;
+ const SwfdecBuffer *buffer = value;
+ GString *string = g_string_new ("");
+
+ for (i = 0; i < buffer->length; i++) {
+ if (i && i % 4 == 0)
+ g_string_append_c (string, ' ');
+ g_string_append_printf (string, "%2X", buffer->data[i]);
+ }
+ return g_string_free (string, FALSE);
+}
+
+static gboolean
+swfedit_read_unsigned (const char *s, gulong max, gpointer* result)
+{
+ char *end;
+ gulong u;
+
+ g_assert (max <= G_MAXUINT);
+ u = strtoul (s, &end, 10);
+ if (*end != '\0')
+ return FALSE;
+ if (u > max)
+ return FALSE;
+ *result = GUINT_TO_POINTER ((guint) u);
+ return TRUE;
+}
+
+static gboolean
+swfedit_uint8_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT8, result);
+}
+
+static gboolean
+swfedit_uint16_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT16, result);
+}
+
+static gboolean
+swfedit_uint32_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT32, result);
+}
+
+static char *
+swfedit_write_unsigned (gconstpointer value)
+{
+ return g_strdup_printf ("%u", GPOINTER_TO_UINT (value));
+}
+
+struct {
+ gboolean (* read) (const char *s, gpointer *);
+ char * (* write) (gconstpointer value);
+ void (* free) (gpointer value);
+} converters[SWFEDIT_N_TOKENS] = {
+ { NULL, NULL, g_object_unref },
+ { swfedit_binary_read, swfedit_binary_write, (GDestroyNotify) swfdec_buffer_unref },
+ { swfedit_uint8_read, swfedit_write_unsigned, NULL },
+ { swfedit_uint16_read, swfedit_write_unsigned, NULL },
+ { swfedit_uint32_read, swfedit_write_unsigned, NULL },
+};
+
+/*** STRUCTS ***/
+
+typedef struct {
+ char * name;
+ SwfeditTokenType type;
+ gpointer value;
+} Entry;
+
+/*** GTK_TREE_MODEL ***/
+
+static GtkTreeModelFlags
+swfedit_token_get_flags (GtkTreeModel *tree_model)
+{
+ return 0;
+}
+
+static gint
+swfedit_token_get_n_columns (GtkTreeModel *tree_model)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+
+ return token->tokens->len;
+}
+
+static GType
+swfedit_token_get_column_type (GtkTreeModel *tree_model, gint index_)
+{
+ switch (index_) {
+ case SWFEDIT_COLUMN_NAME:
+ return G_TYPE_STRING;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ return G_TYPE_BOOLEAN;
+ case SWFEDIT_COLUMN_VALUE:
+ return G_TYPE_STRING;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+ return G_TYPE_NONE;
+}
+
+static gboolean
+swfedit_token_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+ guint i = gtk_tree_path_get_indices (path)[0];
+ Entry *entry;
+
+ if (i > token->tokens->len)
+ return FALSE;
+ entry = &g_array_index (token->tokens, Entry, i);
+ if (gtk_tree_path_get_depth (path) > 1) {
+ GtkTreePath *new;
+ int j;
+ int *indices;
+ gboolean ret;
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+ new = gtk_tree_path_new ();
+ indices = gtk_tree_path_get_indices (path);
+ for (j = 1; j < gtk_tree_path_get_depth (path); j++) {
+ gtk_tree_path_append_index (path, indices[j]);
+ }
+ ret = swfedit_token_get_iter (GTK_TREE_MODEL (entry->value), iter, new);
+ gtk_tree_path_free (new);
+ return ret;
+ } else {
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+ }
+}
+
+static GtkTreePath *
+swfedit_token_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ GtkTreePath *path = gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data2), -1);
+
+ while (token->parent) {
+ guint i;
+ SwfeditToken *parent = token->parent;
+ for (i = 0; i < parent->tokens->len; i++) {
+ Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ gtk_tree_path_prepend_index (path, i);
+ token = parent;
+ }
+ return path;
+}
+
+static void
+swfedit_token_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ switch (column) {
+ case SWFEDIT_COLUMN_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, entry->name);
+ return;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, converters[entry->type].write != NULL);
+ return;
+ case SWFEDIT_COLUMN_VALUE:
+ g_value_init (value, G_TYPE_STRING);
+ if (converters[entry->type].write)
+ g_value_take_string (value, converters[entry->type].write (entry->value));
+ return;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+}
+
+static gboolean
+swfedit_token_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+
+ if ((guint) GPOINTER_TO_INT (iter->user_data2) + 1 >= token->tokens->len)
+ return FALSE;
+
+ iter->user_data2++;
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (parent->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = entry->value;
+ iter->user_data2 = GINT_TO_POINTER (0);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ return entry->type == SWFEDIT_TOKEN_OBJECT;
+}
+
+static gint
+swfedit_token_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ token = entry->value;
+ return token->tokens->len;
+}
+
+static gboolean
+swfedit_token_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint n)
+{
+ SwfeditToken *token;
+ Entry *entry;
+
+ if (parent) {
+ token = SWFEDIT_TOKEN (parent->user_data);
+ entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ token = entry->value;
+ if ((guint) n >= token->tokens->len)
+ return FALSE;
+ }
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (n);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child)
+{
+ guint i;
+ SwfeditToken *token = SWFEDIT_TOKEN (child->user_data);
+ SwfeditToken *parent = token->parent;
+
+ if (parent == NULL)
+ return FALSE;
+
+ for (i = 0; i < parent->tokens->len; i++) {
+ Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+}
+
+static void
+swfedit_token_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = swfedit_token_get_flags;
+ iface->get_n_columns = swfedit_token_get_n_columns;
+ iface->get_column_type = swfedit_token_get_column_type;
+ iface->get_iter = swfedit_token_get_iter;
+ iface->get_path = swfedit_token_get_path;
+ iface->get_value = swfedit_token_get_value;
+ iface->iter_next = swfedit_token_iter_next;
+ iface->iter_children = swfedit_token_iter_children;
+ iface->iter_has_child = swfedit_token_iter_has_child;
+ iface->iter_n_children = swfedit_token_iter_n_children;
+ iface->iter_nth_child = swfedit_token_iter_nth_child;
+ iface->iter_parent = swfedit_token_iter_parent;
+}
+
+/*** SWFEDIT_TOKEN ***/
+
+G_DEFINE_TYPE_WITH_CODE (SwfeditToken, swfedit_token, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, swfedit_token_tree_model_init))
+
+static void
+swfedit_token_dispose (GObject *object)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (object);
+ guint i;
+
+ for (i = 0; i < token->tokens->len; i++) {
+ Entry *entry = &g_array_index (token->tokens, Entry, i);
+ g_free (entry->name);
+ if (converters[entry->type].free)
+ converters[entry->type].free (entry->value);
+ }
+ g_array_free (token->tokens, TRUE);
+
+ G_OBJECT_CLASS (swfedit_token_parent_class)->dispose (object);
+}
+
+static void
+swfedit_token_class_init (SwfeditTokenClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_token_dispose;
+}
+
+static void
+swfedit_token_init (SwfeditToken *token)
+{
+ token->tokens = g_array_new (FALSE, FALSE, sizeof (Entry));
+}
+
+SwfeditToken *
+swfedit_token_new (void)
+{
+ SwfeditToken *token;
+
+ token = g_object_new (SWFEDIT_TYPE_TOKEN, NULL);
+ return token;
+}
+
+void
+swfedit_token_add (SwfeditToken *token, const char *name, SwfeditTokenType type, gpointer value)
+{
+ Entry entry = { NULL, type, value };
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (type < SWFEDIT_N_TOKENS);
+
+ entry.name = g_strdup (name);
+ g_array_append_val (token->tokens, entry);
+}
+
+void
+swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value)
+{
+ GtkTreeModel *model;
+ Entry *entry;
+ guint i;
+ gpointer new;
+ GtkTreePath *path;
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (value != NULL);
+
+ model = GTK_TREE_MODEL (token);
+ token = iter->user_data;
+ i = GPOINTER_TO_UINT (iter->user_data2);
+ entry = &g_array_index (token->tokens, Entry, i);
+ if (converters[entry->type].read == NULL)
+ return;
+ if (!converters[entry->type].read (value, &new))
+ return;
+ if (converters[entry->type].free != NULL)
+ converters[entry->type].free (entry->value);
+ entry->value = new;
+
+ path = gtk_tree_model_get_path (model, iter);
+ gtk_tree_model_row_changed (model, path, iter);
+ gtk_tree_path_free (path);
+}
+
diff --git a/test/swfedit_token.h b/test/swfedit_token.h
new file mode 100644
index 0000000..1640027
--- /dev/null
+++ b/test/swfedit_token.h
@@ -0,0 +1,79 @@
+/* Swfedit
+ * 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 __SWFEDIT_TOKEN_H__
+#define __SWFEDIT_TOKEN_H__
+
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec_rect.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ SWFEDIT_TOKEN_OBJECT,
+ SWFEDIT_TOKEN_BINARY,
+ SWFEDIT_TOKEN_UINT8,
+ SWFEDIT_TOKEN_UINT16,
+ SWFEDIT_TOKEN_UINT32,
+ SWFEDIT_N_TOKENS
+} SwfeditTokenType;
+
+typedef enum {
+ SWFEDIT_COLUMN_NAME,
+ SWFEDIT_COLUMN_VALUE_VISIBLE,
+ SWFEDIT_COLUMN_VALUE
+} SwfeditColumn;
+
+typedef struct _SwfeditToken SwfeditToken;
+typedef struct _SwfeditTokenClass SwfeditTokenClass;
+
+#define SWFEDIT_TYPE_TOKEN (swfedit_token_get_type())
+#define SWFEDIT_IS_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_TOKEN))
+#define SWFEDIT_IS_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_TOKEN))
+#define SWFEDIT_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_TOKEN, SwfeditToken))
+#define SWFEDIT_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
+#define SWFEDIT_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
+
+struct _SwfeditToken {
+ GObject object;
+
+ SwfeditToken * parent; /* parent of this token or NULL */
+ gchar * name; /* name of token */
+ GArray * tokens; /* list of tokens */
+};
+
+struct _SwfeditTokenClass {
+ GObjectClass object_class;
+};
+
+GType swfedit_token_get_type (void);
+
+SwfeditToken * swfedit_token_new (void);
+void swfedit_token_add (SwfeditToken * token,
+ const char * name,
+ SwfeditTokenType type,
+ gpointer value);
+void swfedit_token_set (SwfeditToken * token,
+ GtkTreeIter * iter,
+ const char * value);
+
+
+G_END_DECLS
+
+#endif
diff-tree ac526c14b6a853304588e1c71ccc0ab709ac072e (from 134ac8ae16f9e1cf5dc68f4ebb97bba74bed0235)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:32:04 2007 +0100
convert the parsing code to the recent SwfdecBits API
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index a43c9ac..6539921 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -206,10 +206,7 @@ swf_parse_header2 (SwfdecSwfDecoder * s)
return SWFDEC_STATUS_NEEDBITS;
}
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
+ swfdec_bits_init (&s->b, buffer);
swfdec_bits_get_rect (&s->b, &rect);
if (rect.x0 != 0.0 || rect.y0 != 0.0)
@@ -239,7 +236,6 @@ swfdec_swf_decoder_parse (SwfdecDecoder
{
SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (dec);
int ret = SWFDEC_STATUS_OK;
- const unsigned char *endptr;
SwfdecBuffer *buffer;
s->b = s->parse;
@@ -271,12 +267,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder
if (buffer == NULL) {
return SWFDEC_STATUS_NEEDBITS;
}
-
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
-
+ swfdec_bits_init (&s->b, buffer);
x = swfdec_bits_get_u16 (&s->b);
tag = (x >> 6) & 0x3ff;
@@ -288,10 +279,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder
if (buffer == NULL) {
return SWFDEC_STATUS_NEEDBITS;
}
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
+ swfdec_bits_init (&s->b, buffer);
swfdec_bits_get_u16 (&s->b);
tag_len = swfdec_bits_get_u32 (&s->b);
@@ -313,21 +301,11 @@ swfdec_swf_decoder_parse (SwfdecDecoder
buffer = swfdec_buffer_queue_pull (s->input_queue, header_length);
swfdec_buffer_unref (buffer);
- if (tag_len > 0) {
+ if (tag_len > 0)
buffer = swfdec_buffer_queue_pull (s->input_queue, tag_len);
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
- endptr = s->b.ptr + tag_len;
- } else {
+ else
buffer = NULL;
- s->b.buffer = NULL;
- s->b.ptr = NULL;
- s->b.idx = 0;
- s->b.end = NULL;
- endptr = NULL;
- }
+ swfdec_bits_init (&s->b, buffer);
func = swfdec_swf_decoder_get_tag_func (tag);
if (func == NULL) {
SWFDEC_WARNING ("tag function not implemented for %d %s",
@@ -338,18 +316,10 @@ swfdec_swf_decoder_parse (SwfdecDecoder
s->parse_sprite = NULL;
swfdec_bits_syncbits (&s->b);
- if (s->b.ptr < endptr) {
+ if (swfdec_bits_left (&s->b)) {
SWFDEC_WARNING
("early finish (%d bytes) at %d, tag %d %s, length %d",
- endptr - s->b.ptr,
- swfdec_buffer_queue_get_offset (s->input_queue), tag,
- swfdec_swf_decoder_get_tag_name (tag), tag_len);
- //dumpbits (&s->b);
- }
- if (s->b.ptr > endptr) {
- SWFDEC_WARNING
- ("parse_overrun (%d bytes) at %d, tag %d %s, length %d",
- s->b.ptr - endptr,
+ swfdec_bits_left (&s->b) / 8,
swfdec_buffer_queue_get_offset (s->input_queue), tag,
swfdec_swf_decoder_get_tag_name (tag), tag_len);
}
diff-tree 134ac8ae16f9e1cf5dc68f4ebb97bba74bed0235 (from 878ec656b0711cd19c11554d0617109a058af799)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:17:48 2007 +0100
allow NULL buffer in swfdec_bits_init and 0 length in swfdec_bits_get_buffer
This simplifies error checking, since we catch errors in those cases anyway:
- NULL buffer bits are like data bits that finished reading
- 0 length get_buffer returns NULL, which is a valid return value for the error case
diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index 72cc3df..1a7e402 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -31,16 +31,27 @@
#include "swfdec_rect.h"
+/**
+ * swfdec_bits_init:
+ * @bits: a #SwfdecBits
+ * @buffer: buffer to use for data or NULL
+ *
+ * initializes @bits for use with the data in @buffer. The buffer will not be
+ * referenced, so you are responsible for keeping it around while @bits is used.
+ **/
void
swfdec_bits_init (SwfdecBits *bits, SwfdecBuffer *buffer)
{
g_return_if_fail (bits != NULL);
- g_return_if_fail (buffer != NULL);
- bits->buffer = buffer;
- bits->ptr = buffer->data;
- bits->idx = 0;
- bits->end = buffer->data + buffer->length;
+ if (buffer) {
+ bits->buffer = buffer;
+ bits->ptr = buffer->data;
+ bits->idx = 0;
+ bits->end = buffer->data + buffer->length;
+ } else {
+ memset (bits, 0, sizeof (SwfdecBits));
+ }
}
/**
@@ -567,7 +578,7 @@ swfdec_bits_get_buffer (SwfdecBits *bits
{
SwfdecBuffer *buffer;
- g_return_val_if_fail (len > 0 || len == -1, NULL);
+ g_return_val_if_fail (len >= -1, NULL);
if (len > 0) {
SWFDEC_BYTES_CHECK (bits, (unsigned int) len);
@@ -575,9 +586,9 @@ swfdec_bits_get_buffer (SwfdecBits *bits
swfdec_bits_syncbits (bits);
len = bits->end - bits->ptr;
g_assert (len >= 0);
- if (len == 0)
- return NULL;
}
+ if (len == 0)
+ return NULL;
if (bits->buffer) {
buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
} else {
More information about the Swfdec
mailing list