1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include "qwsvdef.h"
22
23 /*
24 ============
25 va
26
27 does a varargs printf into a temp buffer, so I don't need to have
28 varargs versions of all text functions.
29 ============
30 */
31 #define STRING_SIZE 1024
va(const char * format,...)32 char *va (const char *format, ...)
33 {
34 va_list argptr;
35 static char string[MAX_STRINGS][STRING_SIZE];
36 static int index1 = 0;
37
38 index1 &= (MAX_STRINGS - 1);
39 va_start (argptr, format);
40 vsnprintf (string[index1], STRING_SIZE, format, argptr);
41 va_end (argptr);
42
43 return string[index1++];
44 }
45
46 /*
47 ============================================================================
48
49 LIBRARY REPLACEMENT FUNCTIONS
50
51 ============================================================================
52 */
53
Q_atoi(const char * str)54 int Q_atoi (const char *str)
55 {
56 int val;
57 int sign;
58 int c;
59
60 if (!str)
61 return 0;
62
63 for (; *str && *str <= ' '; str++);
64
65 if (*str == '-')
66 {
67 sign = -1;
68 str++;
69 }
70 else
71 {
72 if (*str == '+')
73 str++;
74
75 sign = 1;
76 }
77
78 val = 0;
79
80 //
81 // check for hex
82 //
83 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
84 {
85 str += 2;
86 while (1)
87 {
88 c = (int)(unsigned char)*str++;
89 if ( isdigit(c) )
90 val = (val<<4) + c - '0';
91 else if ( isxdigit(c) )
92 val = (val<<4) + tolower(c) - 'a' + 10;
93 else
94 return val*sign;
95 }
96 }
97
98 //
99 // check for character
100 //
101 if (str[0] == '\'')
102 {
103 return sign * str[1];
104 }
105
106 //
107 // assume decimal
108 //
109 while (1)
110 {
111 c = (int)(unsigned char)*str++;
112 if ( !isdigit(c) )
113 return val*sign;
114 val = val*10 + c - '0';
115 }
116
117 return 0;
118 }
119
120
Q_atof(const char * str)121 float Q_atof (const char *str)
122 {
123 double val;
124 int sign;
125 int c;
126 int decimal, total;
127
128 if (!str)
129 return 0;
130
131 for (; *str && *str <= ' '; str++);
132
133 if (*str == '-')
134 {
135 sign = -1;
136 str++;
137 }
138 else
139 {
140 if (*str == '+')
141 str++;
142
143 sign = 1;
144 }
145
146 val = 0;
147
148 //
149 // check for hex
150 //
151 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
152 {
153 str += 2;
154 while (1)
155 {
156 c = (int)(unsigned char)*str++;
157 if ( isdigit(c) )
158 val = (val*16) + c - '0';
159 else if ( isxdigit(c) )
160 val = (val*16) + tolower(c) - 'a' + 10;
161 else
162 return val*sign;
163 }
164 }
165
166 //
167 // check for character
168 //
169 if (str[0] == '\'')
170 {
171 return sign * str[1];
172 }
173
174 //
175 // assume decimal
176 //
177 decimal = -1;
178 total = 0;
179 while (1)
180 {
181 c = *str++;
182 if (c == '.')
183 {
184 decimal = total;
185 continue;
186 }
187 if ( !isdigit(c) )
188 break;
189 val = val*10 + c - '0';
190 total++;
191 }
192
193 if (decimal == -1)
194 return val*sign;
195 while (total > decimal)
196 {
197 val /= 10;
198 total--;
199 }
200
201 return val*sign;
202 }
203
204 // removes trailing zeros
205 /*char *Q_ftos (float value)
206 {
207 static char str[128];
208 int i;
209
210 snprintf (str, sizeof(str), "%f", value);
211
212 for (i=strlen(str)-1 ; i>0 && str[i]=='0' ; i--)
213 str[i] = 0;
214 if (str[i] == '.')
215 str[i] = 0;
216
217 return str;
218 }*/
219
220 #if defined(_MSC_VER) && (_MSC_VER < 1900)
snprintf(char * buffer,size_t count,char const * format,...)221 int snprintf(char *buffer, size_t count, char const *format, ...)
222 {
223 int ret;
224 va_list argptr;
225 if (!count) return 0;
226 va_start(argptr, format);
227 ret = _vsnprintf(buffer, count, format, argptr);
228 buffer[count - 1] = 0;
229 va_end(argptr);
230 return ret;
231 }
232 #endif // !(Visual Studio 2015+)
233
234 #if defined(_MSC_VER) && (_MSC_VER < 1400)
vsnprintf(char * buffer,size_t count,const char * format,va_list argptr)235 int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
236 {
237 int ret;
238 if (!count) return 0;
239 ret = _vsnprintf(buffer, count, format, argptr);
240 buffer[count - 1] = 0;
241 return ret;
242 }
243 #endif
244
245 #if defined(__linux__) || defined(_WIN32)
246 /*
247 * Functions strlcpy, strlcat, strnstr and strcasestr
248 * was copied from FreeBSD 4.10 libc: src/lib/libc/string/
249 *
250 * // VVD
251 */
strlcpy(char * dst,const char * src,size_t siz)252 size_t strlcpy(char *dst, const char *src, size_t siz)
253 {
254 register char *d = dst;
255 register const char *s = src;
256 register size_t n = siz;
257
258 /* Copy as many bytes as will fit */
259 if (n != 0 && --n != 0)
260 {
261 do
262 {
263 if ((*d++ = *s++) == 0)
264 break;
265 }
266 while (--n != 0);
267 }
268
269 /* Not enough room in dst, add NUL and traverse rest of src */
270 if (n == 0)
271 {
272 if (siz != 0)
273 *d = '\0'; /* NUL-terminate dst */
274 while (*s++)
275 ;
276 }
277
278 return(s - src - 1); /* count does not include NUL */
279 }
280
strlcat(char * dst,const char * src,size_t siz)281 size_t strlcat(char *dst, const char *src, size_t siz)
282 {
283 register char *d = dst;
284 register const char *s = src;
285 register size_t n = siz;
286 size_t dlen;
287
288 /* Find the end of dst and adjust bytes left but don't go past end */
289 while (n-- != 0 && *d != '\0')
290 d++;
291 dlen = d - dst;
292 n = siz - dlen;
293
294 if (n == 0)
295 return(dlen + strlen(s));
296 while (*s != '\0')
297 {
298 if (n != 1)
299 {
300 *d++ = *s;
301 n--;
302 }
303 s++;
304 }
305 *d = '\0';
306
307 return(dlen + (s - src)); /* count does not include NUL */
308 }
309 #endif
310
311 #if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__)
strnstr(const char * s,const char * find,size_t slen)312 char *strnstr (const char *s, const char *find, size_t slen)
313 {
314 char c, sc;
315 size_t len;
316
317 if ((c = *find++) != '\0')
318 {
319 len = strlen (find);
320 do
321 {
322 do
323 {
324 if ((sc = *s++) == '\0' || slen-- < 1)
325 return (NULL);
326 }
327 while (sc != c);
328 if (len > slen)
329 return (NULL);
330 }
331 while (strncmp (s, find, len) != 0);
332 s--;
333 }
334 return ((char *)s);
335 }
336
337 /*
338 * Find the first occurrence of find in s, ignore case.
339 */
strcasestr(register const char * s,register const char * find)340 char *strcasestr(register const char *s, register const char *find)
341 {
342 register char c, sc;
343 register size_t len;
344
345 if ((c = *find++) != 0)
346 {
347 c = tolower((unsigned char)c);
348 len = strlen(find);
349 do
350 {
351 do
352 {
353 if ((sc = *s++) == 0)
354 return (NULL);
355 }
356 while ((char)tolower((unsigned char)sc) != c);
357 }
358 while (strncasecmp(s, find, len) != 0);
359 s--;
360 }
361 return ((char *)s);
362 }
363 #endif
364
365 #ifdef _WIN32
strchrn(const char * str,const char c)366 int strchrn (const char* str, const char c)
367 {
368 int i = 0;
369 while (*str)
370 if (*str++ == c)
371 ++i;
372 return i;
373 }
374 #endif
375
376 /*
377 ============================================================================
378
379 BYTE ORDER FUNCTIONS
380
381 ============================================================================
382 */
383
384 /*short ShortSwap (short s)
385 {
386 byte b1,b2;
387
388 b1 = s&255;
389 b2 = (s>>8)&255;
390
391 return (b1<<8) + b2;
392 }
393
394 int LongSwap (int l)
395 {
396 byte b1,b2,b3,b4;
397
398 b1 = l&255;
399 b2 = (l>>8)&255;
400 b3 = (l>>16)&255;
401 b4 = (l>>24)&255;
402
403 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
404 }
405
406 float FloatSwap (float f)
407 {
408 union
409 {
410 float f;
411 byte b[4];
412 } dat1, dat2;
413
414 dat1.f = f;
415 dat2.b[0] = dat1.b[3];
416 dat2.b[1] = dat1.b[2];
417 dat2.b[2] = dat1.b[1];
418 dat2.b[3] = dat1.b[0];
419 return dat2.f;
420 }*/
421
422 #ifndef id386
423 #ifdef __cplusplus
424 extern "C" {
425 #endif
ShortSwap(short s)426 short ShortSwap (short s)
427 {
428 union
429 {
430 short s;
431 byte b[2];
432 } dat1, dat2;
433 dat1.s = s;
434 dat2.b[0] = dat1.b[1];
435 dat2.b[1] = dat1.b[0];
436 return dat2.s;
437 }
438
LongSwap(int l)439 int LongSwap (int l)
440 {
441 union
442 {
443 int l;
444 byte b[4];
445 } dat1, dat2;
446 dat1.l = l;
447 dat2.b[0] = dat1.b[3];
448 dat2.b[1] = dat1.b[2];
449 dat2.b[2] = dat1.b[1];
450 dat2.b[3] = dat1.b[0];
451 return dat2.l;
452 }
453
FloatSwap(float f)454 float FloatSwap (float f)
455 {
456 union
457 {
458 float f;
459 byte b[4];
460 } dat1, dat2;
461 dat1.f = f;
462 dat2.b[0] = dat1.b[3];
463 dat2.b[1] = dat1.b[2];
464 dat2.b[2] = dat1.b[1];
465 dat2.b[3] = dat1.b[0];
466 return dat2.f;
467 }
468 #ifdef __cplusplus
469 } /* extern "C" */
470 #endif
471 #endif
472
473 #ifdef __PDP_ENDIAN__Q__
LongSwapPDP2Big(int l)474 int LongSwapPDP2Big (int l)
475 {
476 union
477 {
478 int l;
479 byte b[4];
480 } dat1, dat2;
481 dat1.l = l;
482 dat2.b[0] = dat1.b[1];
483 dat2.b[1] = dat1.b[0];
484 dat2.b[2] = dat1.b[3];
485 dat2.b[3] = dat1.b[2];
486 return dat2.l;
487 }
488
LongSwapPDP2Lit(int l)489 int LongSwapPDP2Lit (int l)
490 {
491 union
492 {
493 int l;
494 short s[2];
495 } dat1, dat2;
496 dat1.l = l;
497 dat2.s[0] = dat1.s[1];
498 dat2.s[1] = dat1.s[0];
499 return dat2.l;
500 }
501
FloatSwapPDP2Big(float f)502 float FloatSwapPDP2Big (float f)
503 {
504 union
505 {
506 float f;
507 byte b[4];
508 } dat1, dat2;
509 dat1.f = f;
510 dat2.b[0] = dat1.b[1];
511 dat2.b[1] = dat1.b[0];
512 dat2.b[2] = dat1.b[3];
513 dat2.b[3] = dat1.b[2];
514 return dat2.f;
515 }
516
FloatSwapPDP2Lit(float f)517 float FloatSwapPDP2Lit (float f)
518 {
519 union
520 {
521 float f;
522 short s[2];
523 } dat1, dat2;
524 dat1.f = f;
525 dat2.s[0] = dat1.s[1];
526 dat2.s[1] = dat1.s[0];
527 return dat2.f;
528 }
529 #endif
530
531 /*
532 ===================
533 Q_malloc
534
535 Use it instead of malloc so that if memory allocation fails,
536 the program exits with a message saying there's not enough memory
537 instead of crashing after trying to use a NULL pointer.
538 It also sets memory to zero.
539 ===================
540 */
Q_malloc(size_t size)541 void *Q_malloc (size_t size)
542 {
543 void *p = malloc(size);
544 //p = calloc(1, size); //malloc & memset or just calloc?
545 if (!p)
546 Sys_Error ("Q_malloc: Not enough memory free");
547 memset(p, 0, size);
548
549 return p;
550 }
551
Q_calloc(size_t n,size_t size)552 void *Q_calloc (size_t n, size_t size)
553 {
554 void *p = calloc(n, size);
555
556 if (!p)
557 Sys_Error ("Q_calloc: Not enough memory free");
558
559 return p;
560 }
561
562 /*
563 ===================
564 Q_strdup
565 ===================
566 */
Q_strdup(const char * src)567 char *Q_strdup (const char *src)
568 {
569 char *p = strdup(src);
570
571 if (!p)
572 Sys_Error ("Q_strdup: Not enough memory free");
573 return p;
574 }
575
576
577 /*
578 ============
579 COM_StripExtension
580 ============
581 */
COM_StripExtension(char * str)582 char *COM_StripExtension (char *str)
583 {
584 char *p = strrchr(str, '.');
585
586 /* truncate extension */
587 if (p)
588 *p = '\0';
589
590 return str;
591 }
592
593 /*
594 ============
595 COM_FileExtension
596 ============
597 */
COM_FileExtension(const char * in)598 char *COM_FileExtension (const char *in)
599 {
600 static char exten[8];
601 int i;
602
603 in = strrchr(in, '.');
604 if (!in || strchr(in, '/'))
605 return "";
606 in++;
607 for (i=0 ; i<7 && *in ; i++,in++)
608 exten[i] = *in;
609 exten[i] = 0;
610 return exten;
611 }
612
613 /*
614 ==================
615 COM_DefaultExtension
616
617 If path doesn't have a .EXT, append extension
618 (extension should include the .)
619 ==================
620 */
COM_DefaultExtension(char * path,const char * extension)621 void COM_DefaultExtension (char *path, const char *extension)
622 {
623 char *src;
624
625 src = path + strlen (path) - 1;
626
627 while (*src != '/' && src != path)
628 {
629 if (*src == '.')
630 return; // it has an extension
631 src--;
632 }
633
634 strlcat (path, extension, MAX_OSPATH);
635 }
636
637 //=====================================================
638
AdjustAngle(float current,float ideal,float fraction)639 float AdjustAngle(float current, float ideal, float fraction)
640 {
641 float move = ideal - current;
642
643 if (move >= 180)
644 move -= 360;
645 else if (move <= -180)
646 move += 360;
647
648 return current + fraction * move;
649 }
650
651 //=======================================================
652
wildcmp(char * wild,char * string)653 int wildcmp(char *wild, char *string)
654 {
655 char *cp=NULL, *mp=NULL;
656
657 while ((*string) && (*wild != '*'))
658 {
659 if ((*wild != *string) && (*wild != '?'))
660 {
661 return 0;
662 }
663 wild++;
664 string++;
665 }
666
667 while (*string)
668 {
669 if (*wild == '*')
670 {
671 if (!*++wild) //a * at the end of the wild string matches anything the checked string has
672 {
673 return 1;
674 }
675 mp = wild;
676 cp = string+1;
677 }
678 else if ((*wild == *string) || (*wild == '?'))
679 {
680 wild++;
681 string++;
682 }
683 else
684 {
685 wild = mp;
686 string = cp++;
687 }
688 }
689
690 while (*wild == '*')
691 {
692 wild++;
693 }
694 return !*wild;
695 }
696
697