]> git.draconx.ca Git - upkg.git/blob - src/uobject.c
module: add missing return value to module_exit.
[upkg.git] / src / uobject.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <glib-object.h>
6
7 #include "uobject.h"
8 #include "upkg.h"
9 #include "pack.h"
10
11 #define U_OBJECT_GET_PRIV(o) \
12         G_TYPE_INSTANCE_GET_PRIVATE(o, U_OBJECT_TYPE, struct uobject_priv)
13
14 enum {
15         PROPERTY_BYTE = 1,
16         PROPERTY_INTEGER,
17         PROPERTY_BOOLEAN,
18         PROPERTY_FLOAT,
19         PROPERTY_OBJECT,
20         PROPERTY_NAME,
21         PROPERTY_STRING,
22         PROPERTY_CLASS,
23         PROPERTY_ARRAY,
24         PROPERTY_STRUCT,
25         PROPERTY_VECTOR,
26         PROPERTY_ROTATOR,
27         PROPERTY_STR,
28         PROPERTY_MAP,
29         PROPERTY_FIXEDARRAY,
30 };
31
32 struct uobject_property {
33         const char *name;
34         GValue val;
35 };
36
37 struct uobject_priv {
38         struct upkg_file *f;
39         size_t base, len;
40
41         unsigned char buf[2048];
42         unsigned long nbuf;
43 };
44
45 static unsigned long
46 get_real_size(unsigned long *real, unsigned size, unsigned char *buf, size_t n)
47 {
48         assert(size < 8);
49
50         *real = 0;
51         switch (size) {
52         case 0: *real =  1; return 0;
53         case 1: *real =  2; return 0;
54         case 2: *real =  4; return 0;
55         case 3: *real = 12; return 0;
56         case 4: *real = 16; return 0;
57         case 5:
58                 if (n < 1) return 0;
59                 *real = *buf;
60                 return 1;
61         case 6:
62                 if (n < 2) return 0;
63                 *real = unpack_16_le(buf);
64                 return 2;
65         case 7:
66                 if (n < 4) return 0;
67                 *real = unpack_32_le(buf);
68                 return 4;
69         }
70
71         return 0;
72 }
73
74 static unsigned long
75 decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long len)
76 {
77         struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
78         unsigned long real_size, rc;
79         int type, size, top;
80         GValue val = {0};
81
82         if (priv->nbuf-len < 1)
83                 return 0;
84         
85         type = (priv->buf[len] >> 0) & 0x0f;
86         size = (priv->buf[len] >> 4) & 0x07;
87         top  = (priv->buf[len] >> 7) & 0x01;
88         len += 1;
89
90         rc = get_real_size(&real_size, size, priv->buf, priv->nbuf-len);
91         if (real_size == 0)
92                 return 0;
93         len += rc;
94
95         switch (type) {
96         case PROPERTY_BYTE:
97                 if (priv->nbuf-len < 1)
98                         return 0;
99                 g_value_init(&val, G_TYPE_UCHAR);
100                 g_value_set_uchar(&val, priv->buf[len]);
101                 g_object_set_property(G_OBJECT(o), name, &val);
102                 break;
103         case PROPERTY_INTEGER:
104                 if (priv->nbuf-len < 4)
105                         return 0;
106                 g_value_init(&val, G_TYPE_ULONG);
107                 g_value_set_ulong(&val, unpack_32_le(priv->buf+len));
108                 g_object_set_property(G_OBJECT(o), name, &val);
109                 break;
110         default:
111                 fprintf(stderr, "Unhandled property type %x\n", (unsigned)type);
112         }
113
114         real_size += len;
115         if (real_size + len <= priv->nbuf) {
116                 priv->nbuf -= real_size;
117                 memmove(priv->buf, priv->buf+real_size, priv->nbuf);
118         } else {
119                 long skip = real_size - priv->nbuf;
120                 if (upkg_export_seek(f, skip, SEEK_CUR) != 0)
121                         return 0;
122                 priv->nbuf = 0;
123         }
124
125         return real_size;
126 }
127
128 /* Deserialize properties from an Unreal package. */
129 static int deserialize(UObject *o, struct upkg_file *f)
130 {
131         struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
132         unsigned long rc, tot_len = 0;
133
134         while (1) {
135                 unsigned long len = 0;
136                 const char *name;
137                 long tmp;
138
139                 /* Read some data into buffer. */
140                 if (!f->eof) {
141                         void  *buf = priv->buf + priv->nbuf;
142                         size_t amt = sizeof priv->buf - priv->nbuf;
143                         rc = upkg_export_read(f, buf, amt);
144                         if (rc == 0)
145                                 return -1;
146                         priv->nbuf += rc;
147                 }
148
149                 /* Get the property name. */
150                 rc = upkg_decode_index(&tmp, priv->buf+len, priv->nbuf-len);
151                 if (rc == 0)
152                         return -1;
153                 len = rc;
154
155                 name = upkg_get_name(f->pkg, tmp);
156                 if (!name) {
157                         return -1;
158                 } else if (strcmp(name, "None") == 0) {
159                         tot_len += len;
160                         break;
161                 }
162
163                 rc = decode_property(U_OBJECT(o), name, f, len);
164                 if (rc == 0)
165                         return -1;
166                 len = rc;
167
168                 tot_len += len;
169         }
170
171         f->base += tot_len;
172         f->len  -= tot_len;
173         upkg_export_seek(f, 0, SEEK_SET);
174
175         return 0;
176 }
177
178 int u_object_deserialize(GObject *obj, struct upkg_file *f)
179 {
180         g_return_val_if_fail(IS_U_OBJECT(obj), -1);
181         return U_OBJECT_GET_CLASS(obj)->deserialize(U_OBJECT(obj), f);
182 }
183
184 static void u_object_init(UObject *o)
185 {
186         struct uobject_priv *priv = U_OBJECT_GET_PRIV(o);
187 }
188
189 static void u_object_class_init(UObjectClass *class)
190 {
191         g_type_class_add_private(class, sizeof (struct uobject_priv));
192
193         class->deserialize = deserialize;
194 }
195
196 G_DEFINE_TYPE(UObject, u_object, G_TYPE_OBJECT);