]> git.draconx.ca Git - upkg.git/blobdiff - src/uobject.c
build: Add uobject/package.h to Makefile.am
[upkg.git] / src / uobject.c
index 7dedc08560fdde1906848cb11e7562cdfec8b894..64e7c4c396c8474cff1913b72bb939a61c5d8ccd 100644 (file)
@@ -1,16 +1,34 @@
+/*
+ *  upkg: tool for manipulating Unreal Tournament packages.
+ *  Copyright (C) 2009 Nick Bowler
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <glib-object.h>
 
-#include "uobject.h"
+#include <uobject/uobject.h>
 #include "upkg.h"
 #include "pack.h"
-#include "avl.h"
 
 #define U_OBJECT_GET_PRIV(o) \
-       G_TYPE_INSTANCE_GET_PRIVATE(o, U_OBJECT_TYPE, struct uobject_priv)
+       G_TYPE_INSTANCE_GET_PRIVATE(o, U_OBJECT_TYPE, struct u_object_priv)
 
 enum {
        PROPERTY_BYTE = 1,
@@ -30,32 +48,15 @@ enum {
        PROPERTY_FIXEDARRAY,
 };
 
-struct uobject_property {
-       const char *name;
-       GValue val;
-};
-
-struct uobject_priv {
+struct u_object_priv {
        struct upkg_file *f;
        size_t base, len;
 
-       struct avl_table *properties;
-
        unsigned char buf[2048];
        unsigned long nbuf;
 };
 
-/* AVL tree functions. */
-static int propcmp(const void *_a, const void *_b, void *_data)
-{
-       const struct uobject_property *a = _a, *b = _b;
-       return strcmp(a->name, b->name);
-}
-
-static void propfree(void *item, void *data)
-{
-       free(item);
-}
+G_DEFINE_TYPE(UObject, u_object, G_TYPE_OBJECT);
 
 static unsigned long
 get_real_size(unsigned long *real, unsigned size, unsigned char *buf, size_t n)
@@ -89,7 +90,7 @@ get_real_size(unsigned long *real, unsigned size, unsigned char *buf, size_t n)
 static unsigned long
 decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long len)
 {
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
+       struct u_object_priv *priv = U_OBJECT_GET_PRIV(o);
        unsigned long real_size, rc;
        int type, size, top;
        GValue val = {0};
@@ -113,14 +114,14 @@ decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long
                        return 0;
                g_value_init(&val, G_TYPE_UCHAR);
                g_value_set_uchar(&val, priv->buf[len]);
-               u_object_set_property(o, name, &val);
+               g_object_set_property(G_OBJECT(o), name, &val);
                break;
        case PROPERTY_INTEGER:
                if (priv->nbuf-len < 4)
                        return 0;
                g_value_init(&val, G_TYPE_ULONG);
                g_value_set_ulong(&val, unpack_32_le(priv->buf+len));
-               u_object_set_property(o, name, &val);
+               g_object_set_property(G_OBJECT(o), name, &val);
                break;
        default:
                fprintf(stderr, "Unhandled property type %x\n", (unsigned)type);
@@ -143,7 +144,7 @@ decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long
 /* Deserialize properties from an Unreal package. */
 static int deserialize(UObject *o, struct upkg_file *f)
 {
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
+       struct u_object_priv *priv = U_OBJECT_GET_PRIV(o);
        unsigned long rc, tot_len = 0;
 
        while (1) {
@@ -156,7 +157,7 @@ static int deserialize(UObject *o, struct upkg_file *f)
                        void  *buf = priv->buf + priv->nbuf;
                        size_t amt = sizeof priv->buf - priv->nbuf;
                        rc = upkg_export_read(f, buf, amt);
-                       if (rc == 0)
+                       if (rc == 0 && priv->nbuf == 0)
                                return -1;
                        priv->nbuf += rc;
                }
@@ -165,20 +166,20 @@ static int deserialize(UObject *o, struct upkg_file *f)
                rc = upkg_decode_index(&tmp, priv->buf+len, priv->nbuf-len);
                if (rc == 0)
                        return -1;
-               len += rc;
+               len = rc;
 
                name = upkg_get_name(f->pkg, tmp);
                if (!name) {
                        return -1;
                } else if (strcmp(name, "None") == 0) {
-                       tot_len += rc;
+                       tot_len += len;
                        break;
                }
 
                rc = decode_property(U_OBJECT(o), name, f, len);
                if (rc == 0)
                        return -1;
-               len += rc;
+               len = rc;
 
                tot_len += len;
        }
@@ -190,79 +191,54 @@ static int deserialize(UObject *o, struct upkg_file *f)
        return 0;
 }
 
-int u_object_deserialize(GObject *obj, struct upkg_file *f)
+int u_object_deserialize(GObject *obj, struct upkg *pkg, unsigned long idx)
 {
        g_return_val_if_fail(IS_U_OBJECT(obj), -1);
-       U_OBJECT_GET_CLASS(obj)->deserialize(obj, f);
-}
-
-static void u_object_init(UObject *o)
-{
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
-       priv->properties = NULL;
-}
-
-void u_object_set_property(UObject *o, const char *name, const GValue *val)
-{
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
-       struct uobject_property *prop, search = { .name = name };
-       void **p;
+       UObject *uo = U_OBJECT(obj);
+       struct upkg_file *f;
+       int rc;
 
-       if (!priv->properties) {
-               priv->properties = avl_create(propcmp, NULL, NULL);
-               g_return_if_fail(priv->properties != NULL);
+       g_return_val_if_fail(uo->pkg_file == NULL, -1);
+       f = upkg_export_open(pkg, idx);
+       if (!f) {
+               return -1;
        }
 
-       prop = avl_find(priv->properties, &search);
-       if (prop) {
-               g_value_unset(&prop->val);
-               g_value_init(&prop->val, G_VALUE_TYPE(val));
-               g_value_copy(val, &prop->val);
-               return;
+       rc = U_OBJECT_GET_CLASS(obj)->deserialize(uo, f);
+       if (rc != 0) {
+               upkg_export_close(f);
+       } else {
+               uo->pkg      = pkg;
+               uo->pkg_idx  = idx;
+               uo->pkg_file = f;
        }
 
-       prop = malloc(sizeof *prop);
-       g_return_if_fail(prop != NULL);
-
-       *prop = (struct uobject_property) { .name = name };
-       g_value_init(&prop->val, G_VALUE_TYPE(val));
-       g_value_copy(val, &prop->val);
-
-       g_return_if_fail(avl_probe(priv->properties, &prop) != NULL);
+       return rc;
 }
 
-const GValue *u_object_get_property(UObject *o, const char *name)
+static void u_object_init(UObject *o)
 {
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
-       struct uobject_property *prop, search = { .name = name };
-
-       if (!priv->properties)
-               return NULL;
-
-       prop = avl_find(priv->properties, &search);
-       if (!prop)
-               return NULL;
-       return &prop->val;
+       o->pkg      = NULL;
+       o->pkg_file = NULL;
+       o->pkg_idx  = 0;
 }
 
 static void u_object_finalize(GObject *o)
 {
-       struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
+       UObject *uo = U_OBJECT(o);
 
-       if (priv->properties) {
-               avl_destroy(priv->properties, propfree);
-               priv->properties = NULL;
+       if (uo->pkg_file) {
+               upkg_export_close(uo->pkg_file);
        }
+
+       G_OBJECT_CLASS(u_object_parent_class)->finalize(o);
 }
 
 static void u_object_class_init(UObjectClass *class)
 {
+       g_type_class_add_private(class, sizeof (struct u_object_priv));
        GObjectClass *go = G_OBJECT_CLASS(class);
 
        class->deserialize = deserialize;
-
-       g_type_class_add_private(class, sizeof (struct uobject_priv));
-       go->finalize = u_object_finalize;
+       go->finalize       = u_object_finalize;
 }
-
-G_DEFINE_TYPE(UObject, u_object, G_TYPE_OBJECT);