5 #include <glib-object.h>
12 #define U_OBJECT_GET_PRIV(o) \
13 G_TYPE_INSTANCE_GET_PRIVATE(o, U_OBJECT_TYPE, struct uobject_priv)
33 struct uobject_property {
42 struct avl_table *properties;
44 unsigned char buf[2048];
48 /* AVL tree functions. */
49 static int propcmp(const void *_a, const void *_b, void *_data)
51 const struct uobject_property *a = _a, *b = _b;
52 return strcmp(a->name, b->name);
55 static void propfree(void *item, void *data)
61 get_real_size(unsigned long *real, unsigned size, unsigned char *buf, size_t n)
67 case 0: *real = 1; return 0;
68 case 1: *real = 2; return 0;
69 case 2: *real = 4; return 0;
70 case 3: *real = 12; return 0;
71 case 4: *real = 16; return 0;
78 *real = unpack_16_le(buf);
82 *real = unpack_32_le(buf);
90 decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long len)
92 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
93 unsigned long real_size, rc;
97 if (priv->nbuf-len < 1)
100 type = (priv->buf[len] >> 0) & 0x0f;
101 size = (priv->buf[len] >> 4) & 0x07;
102 top = (priv->buf[len] >> 7) & 0x01;
105 rc = get_real_size(&real_size, size, priv->buf, priv->nbuf-len);
112 if (priv->nbuf-len < 1)
114 g_value_init(&val, G_TYPE_UCHAR);
115 g_value_set_uchar(&val, priv->buf[len]);
116 u_object_set_property(o, name, &val);
118 case PROPERTY_INTEGER:
119 if (priv->nbuf-len < 4)
121 g_value_init(&val, G_TYPE_ULONG);
122 g_value_set_ulong(&val, unpack_32_le(priv->buf+len));
123 u_object_set_property(o, name, &val);
126 fprintf(stderr, "Unhandled property type %x\n", (unsigned)type);
130 if (real_size + len <= priv->nbuf) {
131 priv->nbuf -= real_size;
132 memmove(priv->buf, priv->buf+real_size, priv->nbuf);
134 long skip = real_size - priv->nbuf;
135 if (upkg_export_seek(f, skip, SEEK_CUR) != 0)
143 /* Deserialize properties from an Unreal package. */
144 static int deserialize(UObject *o, struct upkg_file *f)
146 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
147 unsigned long rc, tot_len = 0;
150 unsigned long len = 0;
154 /* Read some data into buffer. */
156 void *buf = priv->buf + priv->nbuf;
157 size_t amt = sizeof priv->buf - priv->nbuf;
158 rc = upkg_export_read(f, buf, amt);
164 /* Get the property name. */
165 rc = upkg_decode_index(&tmp, priv->buf+len, priv->nbuf-len);
170 name = upkg_get_name(f->pkg, tmp);
173 } else if (strcmp(name, "None") == 0) {
178 rc = decode_property(U_OBJECT(o), name, f, len);
188 upkg_export_seek(f, 0, SEEK_SET);
193 int u_object_deserialize(GObject *obj, struct upkg_file *f)
195 g_return_val_if_fail(IS_U_OBJECT(obj), -1);
196 U_OBJECT_GET_CLASS(obj)->deserialize(U_OBJECT(obj), f);
199 static void u_object_init(UObject *o)
201 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
202 priv->properties = NULL;
205 void u_object_set_property(UObject *o, const char *name, const GValue *val)
207 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
208 struct uobject_property *prop, search = { .name = name };
211 if (!priv->properties) {
212 priv->properties = avl_create(propcmp, NULL, NULL);
213 g_return_if_fail(priv->properties != NULL);
216 prop = avl_find(priv->properties, &search);
218 g_value_unset(&prop->val);
219 g_value_init(&prop->val, G_VALUE_TYPE(val));
220 g_value_copy(val, &prop->val);
224 prop = malloc(sizeof *prop);
225 g_return_if_fail(prop != NULL);
227 *prop = (struct uobject_property) { .name = name };
228 g_value_init(&prop->val, G_VALUE_TYPE(val));
229 g_value_copy(val, &prop->val);
231 g_return_if_fail(avl_probe(priv->properties, prop) != NULL);
234 const GValue *u_object_get_property(UObject *o, const char *name)
236 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
237 struct uobject_property *prop, search = { .name = name };
239 if (!priv->properties)
242 prop = avl_find(priv->properties, &search);
248 static void u_object_finalize(GObject *o)
250 struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
252 if (priv->properties) {
253 avl_destroy(priv->properties, propfree);
254 priv->properties = NULL;
258 static void u_object_class_init(UObjectClass *class)
260 GObjectClass *go = G_OBJECT_CLASS(class);
262 class->deserialize = deserialize;
264 g_type_class_add_private(class, sizeof (struct uobject_priv));
265 go->finalize = u_object_finalize;
268 G_DEFINE_TYPE(UObject, u_object, G_TYPE_OBJECT);