]> git.tdb.fi Git - gldbg.git/blob - source/gldecoder.c
cd290aa513b3f1e69ea21009b95513bdff46a5ac
[gldbg.git] / source / gldecoder.c
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include "functions.h"
11 #include "gldecoder.h"
12 #include "tmpalloc.h"
13
14 typedef struct sGlPacket
15 {
16         const char *ptr;
17         unsigned chunk;
18         unsigned total;
19 } GlPacket;
20
21 static void read_short(short *, GlPacket *);
22 static void read_int(int *, GlPacket *);
23 static int decode_func(GlDecoder *, unsigned short, GlPacket *);
24 static int decode_gldfunc(GlDecoder *, unsigned short, GlPacket *);
25
26 GlDecoder *gldecoder_new(void *user_data, void (*destroy)(void *))
27 {
28         GlDecoder *dec;
29
30         dec = (GlDecoder *)malloc(sizeof(GlDecoder));
31         memset(dec, 0, sizeof(GlDecoder));
32         dec->user_data = user_data;
33         dec->destroy = destroy;
34
35         return dec;
36 }
37
38 void gldecoder_delete(GlDecoder *dec)
39 {
40         if(dec->destroy)
41                 dec->destroy(dec->user_data);
42         free(dec);
43 }
44
45 int gldecoder_decode(GlDecoder *dec, const char *data, unsigned len)
46 {
47         unsigned short func;
48         GlPacket packet;
49
50         if(len<sizeof(int)+sizeof(short))
51                 return -1;
52
53         packet.ptr = data;
54         packet.chunk = len;
55         read_int((int *)&packet.chunk, &packet);
56
57         if(packet.chunk&0x80000000)
58         {
59                 packet.chunk &= 0x7FFFFFFF;
60                 packet.total = packet.chunk;
61
62                 while(1)
63                 {
64                         if(len<packet.total+sizeof(int))
65                                 return -1;
66
67                         GlPacket p = { packet.ptr+packet.total, len-packet.total, 0 };
68                         unsigned chunk;
69                         read_int((int *)&chunk, &p);
70                         packet.total += chunk&0x7FFFFFFF;
71                         if(!(chunk&0x80000000))
72                                 break;
73                 }
74         }
75         else
76                 packet.total = packet.chunk;
77
78         if(len<packet.total)
79                 return -1;
80
81         read_short((short *)&func, &packet);
82
83         if(dec)
84         {
85                 int ret = 0;
86
87                 if(func&0x8000)
88                         ret = decode_gldfunc(dec, func, &packet);
89                 else
90                         ret = decode_func(dec, func, &packet);
91                 if(ret<0)
92                         return -1;
93         }
94
95         return packet.ptr+packet.total-data;
96 }
97
98 static void next_chunk(GlPacket *pkt)
99 {
100         if(pkt->total==0)
101                 return;
102         pkt->chunk = pkt->total;
103         read_int((int *)&pkt->chunk, pkt);
104         pkt->chunk &= 0x7FFFFFFF;
105 }
106
107 static void read_generic(void *v, unsigned size, int byteswap, GlPacket *pkt)
108 {
109         if(pkt->chunk==0)
110                 next_chunk(pkt);
111
112         if(pkt->chunk>=size)
113         {
114                 // TODO: Actually implement byteswap if needed
115                 (void)byteswap;
116                 memcpy(v, pkt->ptr, size);
117                 pkt->ptr += size;
118                 pkt->chunk -= size;
119                 pkt->total -= size;
120         }
121         else
122         {
123                 memset(v, 0, size);
124                 pkt->total -= pkt->chunk;
125                 pkt->chunk = 0;
126         }
127 }
128
129 static void read_char(char *v, GlPacket *pkt)
130 {
131         read_generic(v, 1, 0, pkt);
132 }
133
134 static void read_short(short *v, GlPacket *pkt)
135 {
136         read_generic(v, sizeof(short), 1, pkt);
137 }
138
139 static void read_int(int *v, GlPacket *pkt)
140 {
141         read_generic(v, sizeof(int), 1, pkt);
142 }
143
144 static void read_long(long *v, GlPacket *pkt)
145 {
146         read_generic(v, sizeof(long), 1, pkt);
147 }
148
149 static void read_long_long(long long *v, GlPacket *pkt)
150 {
151         read_generic(v, sizeof(long long), 1, pkt);
152 }
153
154 static void read_float(float *v, GlPacket *pkt)
155 {
156         read_generic(v, sizeof(float), 1, pkt);
157 }
158
159 static void read_double(double *v, GlPacket *pkt)
160 {
161         read_generic(v, sizeof(double), 1, pkt);
162 }
163
164 typedef const void *pointer;
165
166 static void read_pointer(pointer *v, GlPacket *pkt)
167 {
168         read_generic(v, sizeof(pointer), 1, pkt);
169 }
170
171 static void read_data(pointer *v, GlPacket *pkt)
172 {
173         int vlen;
174         read_int(&vlen, pkt);
175         if(vlen)
176                 *v = pkt->ptr;
177         else
178                 *v = NULL;
179 }
180
181 typedef const char *string;
182
183 static void read_string(string *v, GlPacket *pkt)
184 {
185         read_data((pointer *)v, pkt);
186 }
187
188 static void read_string_array(string **v, GlPacket *pkt)
189 {
190         int count;
191         int i;
192         read_int(&count, pkt);
193         *v = (string *)tmpalloc(count*sizeof(string));
194         for(i=0; i<count; ++i)
195                 read_string(*v+i, pkt);
196 }
197
198 #include "gensrc/gldecoder.funcs"
199
200 static void decode_gldError(GlDecoder *dec, GlPacket *pkt)
201 {
202         GLenum code;
203         read_int((int *)&code, pkt);
204         if(dec->gldError)
205                 dec->gldError(dec->user_data, code);
206 }
207
208 static int decode_gldfunc(GlDecoder *dec, unsigned short func, GlPacket *pkt)
209 {
210         switch(func)
211         {
212         case FUNC_GLDERROR: decode_gldError(dec, pkt); break;
213         default: return -1;
214         }
215         return 0;
216 }