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