Benjamin Otte
2007-Jan-22 09:35 UTC
[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
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@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@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@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@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@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@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@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@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@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@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 {
Possibly Parallel Threads
- Branch 'interpreter' - 28 commits - configure.ac libswfdec/js libswfdec/swfdec_buffer.c libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_player.c
- 12 commits - configure.ac doc/swfdec.types Makefile.am test/crashfinder.c test/dump.c test/Makefile.am test/swfdec-extract.c test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_file.c test/swfedit_file.h test/swfedit_list.c test/swfedit_list.h
- 7 commits - libswfdec/swfdec_image.c libswfdec/swfdec_script.c libswfdec/swfdec_script.h test/Makefile.am test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_list.c test/swfedit_tag.c test/swfedit_token.c test/swfedit_token.h test/swfscript.c
- 109 commits - configure.ac libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_buffer.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_codec_screen.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h
- 9 commits - libswfdec/js libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_codec_screen.c libswfdec/swfdec_image.c libswfdec/swfdec_script.c test/Makefile.am test/swfdec_out.c test/swfdec_out.h test/swfedit.c test/swfedit_file.c