1 /*
2 msg.c
3
4 (description)
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STRINGS_H
35 # include <strings.h>
36 #endif
37
38 #include "QF/msg.h"
39 #include "QF/qendian.h"
40 #include "QF/sys.h"
41
42 #include "compat.h"
43
44 /*
45 MESSAGE IO FUNCTIONS
46
47 Handles byte ordering and avoids alignment errors
48 */
49
50 // writing functions ==========================================================
51
52 VISIBLE void
MSG_WriteByte(sizebuf_t * sb,int c)53 MSG_WriteByte (sizebuf_t *sb, int c)
54 {
55 byte *buf;
56
57 buf = SZ_GetSpace (sb, 1);
58 *buf = c;
59 }
60
61 VISIBLE void
MSG_WriteShort(sizebuf_t * sb,int c)62 MSG_WriteShort (sizebuf_t *sb, int c)
63 {
64 byte *buf;
65
66 buf = SZ_GetSpace (sb, 2);
67 *buf++ = ((unsigned int) c) & 0xff;
68 *buf = ((unsigned int) c) >> 8;
69 }
70
71 VISIBLE void
MSG_WriteLong(sizebuf_t * sb,int c)72 MSG_WriteLong (sizebuf_t *sb, int c)
73 {
74 byte *buf;
75
76 buf = SZ_GetSpace (sb, 4);
77 *buf++ = ((unsigned int) c) & 0xff;
78 *buf++ = (((unsigned int) c) >> 8) & 0xff;
79 *buf++ = (((unsigned int) c) >> 16) & 0xff;
80 *buf = ((unsigned int) c) >> 24;
81 }
82
83 VISIBLE void
MSG_WriteFloat(sizebuf_t * sb,float f)84 MSG_WriteFloat (sizebuf_t *sb, float f)
85 {
86 union {
87 float f;
88 unsigned int l;
89 } dat;
90
91 dat.f = f;
92 dat.l = LittleLong (dat.l);
93
94 SZ_Write (sb, &dat.l, 4);
95 }
96
97 VISIBLE void
MSG_WriteString(sizebuf_t * sb,const char * s)98 MSG_WriteString (sizebuf_t *sb, const char *s)
99 {
100 if (!s)
101 SZ_Write (sb, "", 1);
102 else
103 SZ_Write (sb, s, strlen (s) + 1);
104 }
105
106 VISIBLE void
MSG_WriteBytes(sizebuf_t * sb,const void * buf,int len)107 MSG_WriteBytes (sizebuf_t *sb, const void *buf, int len)
108 {
109 SZ_Write (sb, buf, len);
110 }
111
112 VISIBLE void
MSG_WriteCoord(sizebuf_t * sb,float coord)113 MSG_WriteCoord (sizebuf_t *sb, float coord)
114 {
115 MSG_WriteShort (sb, (int) (coord * 8.0));
116 }
117
118 VISIBLE void
MSG_WriteCoordV(sizebuf_t * sb,const vec3_t coord)119 MSG_WriteCoordV (sizebuf_t *sb, const vec3_t coord)
120 {
121 byte *buf;
122 unsigned int i, j;
123
124 buf = SZ_GetSpace (sb, 6);
125 for (i = 0; i < 3; i++) {
126 j = (int) (coord[i] * 8.0);
127 *buf++ = j & 0xff;
128 *buf++ = j >> 8;
129 }
130 }
131
132 VISIBLE void
MSG_WriteCoordAngleV(sizebuf_t * sb,const vec3_t coord,const vec3_t angles)133 MSG_WriteCoordAngleV (sizebuf_t *sb, const vec3_t coord, const vec3_t angles)
134 {
135 byte *buf;
136 int i, j;
137
138 buf = SZ_GetSpace (sb, 9);
139 for (i = 0; i < 3; i++) {
140 j = (int) (coord[i] * 8.0);
141 *buf++ = j & 0xff;
142 *buf++ = j >> 8;
143 *buf++ = ((int) (angles[i] * (256.0 / 360.0)) & 255);
144 }
145 }
146
147 VISIBLE void
MSG_WriteAngle(sizebuf_t * sb,float angle)148 MSG_WriteAngle (sizebuf_t *sb, float angle)
149 {
150 MSG_WriteByte (sb, (int) (angle * (256.0 / 360.0)) & 255);
151 }
152
153 VISIBLE void
MSG_WriteAngleV(sizebuf_t * sb,const vec3_t angles)154 MSG_WriteAngleV (sizebuf_t *sb, const vec3_t angles)
155 {
156 byte *buf;
157 int i;
158
159 buf = SZ_GetSpace (sb, 3);
160 for (i = 0; i < 3; i++) {
161 *buf++ = ((int) (angles[i] * (256.0 / 360.0)) & 255);
162 }
163 }
164
165 VISIBLE void
MSG_WriteAngle16(sizebuf_t * sb,float angle)166 MSG_WriteAngle16 (sizebuf_t *sb, float angle)
167 {
168 MSG_WriteShort (sb, (int) (angle * (65536.0 / 360.0)) & 65535);
169 }
170
171 VISIBLE void
MSG_WriteAngle16V(sizebuf_t * sb,const vec3_t angles)172 MSG_WriteAngle16V (sizebuf_t *sb, const vec3_t angles)
173 {
174 byte *buf;
175 int i;
176 unsigned short ang;
177
178 buf = SZ_GetSpace (sb, 6);
179 for (i = 0; i < 3; i++) {
180 ang = (int) (angles[i] * (65536.0 / 360.0)) & 65535;
181 *buf++ = ang & 0xff;
182 *buf++ = ang >> 8;
183 }
184 }
185
186 VISIBLE void
MSG_WriteUTF8(sizebuf_t * sb,unsigned utf8)187 MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8)
188 {
189 byte *buf;
190 int count;
191
192 if (utf8 & 0x80000000) {
193 return; // invalid (FIXME die?)
194 } else if (utf8 & 0x7c000000) {
195 buf = SZ_GetSpace (sb, count = 6);
196 *buf = 0xfc | ((utf8 & 0x40000000) >> 30); // 1 bit
197 utf8 <<= 2;
198 } else if (utf8 & 0x03e00000) {
199 buf = SZ_GetSpace (sb, count = 5);
200 *buf = 0xf8 | ((utf8 & 0x30000000) >> 28); // 2 bits
201 utf8 <<= 4;
202 } else if (utf8 & 0x001f0000) {
203 buf = SZ_GetSpace (sb, count = 4);
204 *buf = 0xf0 | ((utf8 & 0x001c0000) >> 18); // 3 bits
205 utf8 <<= 14;
206 } else if (utf8 & 0x0000f800) {
207 buf = SZ_GetSpace (sb, count = 3);
208 *buf = 0xe0 | ((utf8 & 0x0000f000) >> 12); // 4 bits
209 utf8 <<= 20;
210 } else if (utf8 & 0x00000780) {
211 buf = SZ_GetSpace (sb, count = 2);
212 *buf = 0xc0 | ((utf8 & 0x00000780) >> 7); // 5 bits
213 utf8 <<= 25;
214 } else {
215 buf = SZ_GetSpace (sb, count = 1);
216 *buf = utf8;
217 return;
218 }
219 while (--count) {
220 *buf++ = 0x80 | ((utf8 & 0xfc000000) >> 26);
221 utf8 <<= 6;
222 }
223 }
224
225 // reading functions ==========================================================
226
227 VISIBLE void
MSG_BeginReading(qmsg_t * msg)228 MSG_BeginReading (qmsg_t *msg)
229 {
230 msg->readcount = 0;
231 msg->badread = false;
232 }
233
234 VISIBLE int
MSG_GetReadCount(qmsg_t * msg)235 MSG_GetReadCount (qmsg_t *msg)
236 {
237 return msg->readcount;
238 }
239
240 VISIBLE int
MSG_ReadByte(qmsg_t * msg)241 MSG_ReadByte (qmsg_t *msg)
242 {
243 if (msg->readcount + 1 <= msg->message->cursize)
244 return (unsigned char) msg->message->data[msg->readcount++];
245
246 msg->badread = true;
247 return -1;
248 }
249
250 VISIBLE int
MSG_ReadShort(qmsg_t * msg)251 MSG_ReadShort (qmsg_t *msg)
252 {
253 int c;
254
255 if (msg->readcount + 2 <= msg->message->cursize) {
256 c = (msg->message->data[msg->readcount]
257 + (msg->message->data[msg->readcount + 1] << 8));
258 msg->readcount += 2;
259 return c;
260 }
261 msg->readcount = msg->message->cursize;
262 msg->badread = true;
263 return -1;
264 }
265
266 VISIBLE int
MSG_ReadLong(qmsg_t * msg)267 MSG_ReadLong (qmsg_t *msg)
268 {
269 int c;
270
271 if (msg->readcount + 4 <= msg->message->cursize) {
272 c = msg->message->data[msg->readcount]
273 + (msg->message->data[msg->readcount + 1] << 8)
274 + (msg->message->data[msg->readcount + 2] << 16)
275 + (msg->message->data[msg->readcount + 3] << 24);
276 msg->readcount += 4;
277 return c;
278 }
279 msg->readcount = msg->message->cursize;
280 msg->badread = true;
281 return -1;
282 }
283
284 VISIBLE float
MSG_ReadFloat(qmsg_t * msg)285 MSG_ReadFloat (qmsg_t *msg)
286 {
287 union {
288 byte b[4];
289 float f;
290 int l;
291 } dat;
292
293 if (msg->readcount + 4 <= msg->message->cursize) {
294 dat.b[0] = msg->message->data[msg->readcount];
295 dat.b[1] = msg->message->data[msg->readcount + 1];
296 dat.b[2] = msg->message->data[msg->readcount + 2];
297 dat.b[3] = msg->message->data[msg->readcount + 3];
298 msg->readcount += 4;
299
300 dat.l = LittleLong (dat.l);
301
302 return dat.f;
303 }
304
305 msg->readcount = msg->message->cursize;
306 msg->badread = true;
307 return -1;
308 }
309
310 VISIBLE const char *
MSG_ReadString(qmsg_t * msg)311 MSG_ReadString (qmsg_t *msg)
312 {
313 char *string;
314 size_t len, maxlen;
315
316 if (msg->badread || msg->readcount + 1 > msg->message->cursize) {
317 msg->badread = true;
318 return "";
319 }
320
321 string = (char *) &msg->message->data[msg->readcount];
322
323 maxlen = msg->message->cursize - msg->readcount;
324 len = strnlen (string, maxlen);
325 if (len == maxlen) {
326 msg->readcount = msg->readcount;
327 msg->badread = true;
328 if (len + 1 > msg->badread_string_size) {
329 if (msg->badread_string)
330 free (msg->badread_string);
331 msg->badread_string = malloc (len + 1);
332 msg->badread_string_size = len + 1;
333 }
334 if (!msg->badread_string)
335 Sys_Error ("MSG_ReadString: out of memory");
336 strncpy (msg->badread_string, string, len);
337 msg->badread_string[len] = 0;
338 return msg->badread_string;
339 }
340 msg->readcount += len + 1;
341
342 return string;
343 }
344
345 VISIBLE int
MSG_ReadBytes(qmsg_t * msg,void * buf,int len)346 MSG_ReadBytes (qmsg_t *msg, void *buf, int len)
347 {
348 if (msg->badread || len > msg->message->cursize - msg->readcount) {
349 msg->badread = true;
350 len = msg->message->cursize - msg->readcount;
351 }
352 memcpy (buf, msg->message->data + msg->readcount, len);
353 msg->readcount += len;
354 return len;
355 }
356
357 VISIBLE float
MSG_ReadCoord(qmsg_t * msg)358 MSG_ReadCoord (qmsg_t *msg)
359 {
360 return (short) MSG_ReadShort (msg) * (1.0 / 8.0);
361 }
362
363 VISIBLE void
MSG_ReadCoordV(qmsg_t * msg,vec3_t coord)364 MSG_ReadCoordV (qmsg_t *msg, vec3_t coord)
365 {
366 int i;
367
368 for (i = 0; i < 3; i++)
369 coord[i] = (short) MSG_ReadShort (msg) * (1.0 / 8.0);
370 }
371
372 VISIBLE void
MSG_ReadCoordAngleV(qmsg_t * msg,vec3_t coord,vec3_t angles)373 MSG_ReadCoordAngleV (qmsg_t *msg, vec3_t coord, vec3_t angles)
374 {
375 int i;
376
377 for (i = 0; i < 3; i++) {
378 coord[i] = (short) MSG_ReadShort (msg) * (1.0 / 8.0);
379 angles[i] = ((signed char) MSG_ReadByte (msg)) * (360.0 / 256.0);
380 }
381 }
382
383 VISIBLE float
MSG_ReadAngle(qmsg_t * msg)384 MSG_ReadAngle (qmsg_t *msg)
385 {
386 return ((signed char) MSG_ReadByte (msg)) * (360.0 / 256.0);
387 }
388
389 VISIBLE void
MSG_ReadAngleV(qmsg_t * msg,vec3_t angles)390 MSG_ReadAngleV (qmsg_t *msg, vec3_t angles)
391 {
392 int i;
393
394 for (i = 0; i < 3; i++)
395 angles[i] = ((signed char) MSG_ReadByte (msg)) * (360.0 / 256.0);
396 }
397
398 VISIBLE float
MSG_ReadAngle16(qmsg_t * msg)399 MSG_ReadAngle16 (qmsg_t *msg)
400 {
401 return (short) MSG_ReadShort (msg) * (360.0 / 65536.0);
402 }
403
404 VISIBLE void
MSG_ReadAngle16V(qmsg_t * msg,vec3_t angles)405 MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles)
406 {
407 int i;
408
409 for (i = 0; i < 3; i++)
410 angles[i] = (short) MSG_ReadShort (msg) * (360.0 / 65536.0);
411 }
412
413 VISIBLE int
MSG_ReadUTF8(qmsg_t * msg)414 MSG_ReadUTF8 (qmsg_t *msg)
415 {
416 byte *buf, *start, c;
417 int val = 0, count;
418
419 if (msg->badread || msg->message->cursize == msg->readcount) {
420 msg->badread = true;
421 return -1;
422 }
423 buf = start = msg->message->data + msg->readcount;
424
425 c = *buf++;
426 if (c < 0x80) { // 0x00 - 0x7f 1,7,7
427 val = c;
428 count = 1;
429 } else if (c < 0xc0) { // 0x80 - 0xbf not a valid first byte
430 msg->badread = true;
431 return -1;
432 } else if (c < 0xe0) { // 0xc0 - 0xdf 2,5,11
433 count = 2;
434 val = c & 0x1f;
435 } else if (c < 0xf0) { // 0xe0 - 0xef 3,4,16
436 count = 3;
437 val = c & 0x0f;
438 } else if (c < 0xf8) { // 0xf0 - 0xf7 4,3,21
439 count = 4;
440 val = c & 0x07;
441 } else if (c < 0xfc) { // 0xf8 - 0xfb 5,2,26
442 count = 5;
443 val = c & 0x03;
444 } else if (c < 0xfe) { // 0xfc - 0xfd 6,1,31
445 count = 6;
446 val = c & 0x01;
447 } else { // 0xfe - 0xff never valid
448 msg->badread = true;
449 return -1;
450 }
451 if (count > (msg->message->cursize - msg->readcount)) {
452 msg->badread = true;
453 return -1;
454 }
455 while (--count) {
456 c = *buf++;
457 if ((c & 0xc0) != 0x80) {
458 msg->badread = true;
459 return -1;
460 }
461 val <<= 6;
462 val |= c & 0x3f;
463 }
464 msg->readcount += buf - start;
465 return val;
466 }
467