X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/6637b91cdb7b3d3e923f3d72e36be07e9009e7e8..0438ce1525f7c1e722140c046fccb0f686b4cab2:/src/uobject.c diff --git a/src/uobject.c b/src/uobject.c index 94b5942..ec04e30 100644 --- a/src/uobject.c +++ b/src/uobject.c @@ -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 #include #include #include #include -#include "uobject.h" +#include #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) { @@ -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(U_OBJECT(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);