Quake II RTX doxygen  1.0 dev
shared.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "shared/shared.h"
20 
21 vec3_t vec3_origin = { 0, 0, 0 };
22 
23 void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
24 {
25  float angle;
26  float sr, sp, sy, cr, cp, cy;
27 
28  angle = angles[YAW] * (M_PI * 2 / 360);
29  sy = sin(angle);
30  cy = cos(angle);
31  angle = angles[PITCH] * (M_PI * 2 / 360);
32  sp = sin(angle);
33  cp = cos(angle);
34  angle = angles[ROLL] * (M_PI * 2 / 360);
35  sr = sin(angle);
36  cr = cos(angle);
37 
38  if (forward) {
39  forward[0] = cp * cy;
40  forward[1] = cp * sy;
41  forward[2] = -sp;
42  }
43  if (right) {
44  right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
45  right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
46  right[2] = -1 * sr * cp;
47  }
48  if (up) {
49  up[0] = (cr * sp * cy + -sr * -sy);
50  up[1] = (cr * sp * sy + -sr * cy);
51  up[2] = cr * cp;
52  }
53 }
54 
55 vec_t VectorNormalize(vec3_t v)
56 {
57  float length, ilength;
58 
59  length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
60  length = sqrtf(length); // FIXME
61 
62  if (length) {
63  ilength = 1 / length;
64  v[0] *= ilength;
65  v[1] *= ilength;
66  v[2] *= ilength;
67  }
68 
69  return length;
70 
71 }
72 
73 vec_t VectorNormalize2(vec3_t v, vec3_t out)
74 {
75  float length, ilength;
76 
77  length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
78  length = sqrtf(length); // FIXME
79 
80  if (length) {
81  ilength = 1 / length;
82  out[0] = v[0] * ilength;
83  out[1] = v[1] * ilength;
84  out[2] = v[2] * ilength;
85  }
86 
87  return length;
88 
89 }
90 
91 void ClearBounds(vec3_t mins, vec3_t maxs)
92 {
93  mins[0] = mins[1] = mins[2] = 99999;
94  maxs[0] = maxs[1] = maxs[2] = -99999;
95 }
96 
97 void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs)
98 {
99  int i;
100  vec_t val;
101 
102  for (i = 0; i < 3; i++) {
103  val = v[i];
104  if (val < mins[i])
105  mins[i] = val;
106  if (val > maxs[i])
107  maxs[i] = val;
108  }
109 }
110 
111 void UnionBounds(vec3_t a[2], vec3_t b[2], vec3_t c[2])
112 {
113  c[0][0] = b[0][0] < a[0][0] ? b[0][0] : a[0][0];
114  c[0][1] = b[0][1] < a[0][1] ? b[0][1] : a[0][1];
115  c[0][2] = b[0][2] < a[0][2] ? b[0][2] : a[0][2];
116 
117  c[1][0] = b[1][0] > a[1][0] ? b[1][0] : a[1][0];
118  c[1][1] = b[1][1] > a[1][1] ? b[1][1] : a[1][1];
119  c[1][2] = b[1][2] > a[1][2] ? b[1][2] : a[1][2];
120 }
121 
122 /*
123 =================
124 RadiusFromBounds
125 =================
126 */
127 vec_t RadiusFromBounds(const vec3_t mins, const vec3_t maxs)
128 {
129  int i;
130  vec3_t corner;
131  vec_t a, b;
132 
133  for (i = 0; i < 3; i++) {
134  a = Q_fabs(mins[i]);
135  b = Q_fabs(maxs[i]);
136  corner[i] = a > b ? a : b;
137  }
138 
139  return VectorLength(corner);
140 }
141 
142 //====================================================================================
143 
144 // unused:
145 // static const char hexchars[] = "0123456789ABCDEF";
146 
147 /*
148 ============
149 COM_SkipPath
150 ============
151 */
152 char *COM_SkipPath(const char *pathname)
153 {
154  char *last;
155 
156  if (!pathname) {
157  Com_Error(ERR_FATAL, "%s: NULL", __func__);
158  }
159 
160  last = (char *)pathname;
161  while (*pathname) {
162  if (*pathname == '/')
163  last = (char *)pathname + 1;
164  pathname++;
165  }
166  return last;
167 }
168 
169 /*
170 ============
171 COM_StripExtension
172 ============
173 */
174 void COM_StripExtension(const char *in, char *out, size_t size)
175 {
176  char *s;
177 
178  Q_strlcpy(out, in, size);
179 
180  s = out + strlen(out);
181 
182  while (s != out) {
183  if (*s == '/') {
184  break;
185  }
186  if (*s == '.') {
187  *s = 0;
188  break;
189  }
190  s--;
191  }
192 }
193 
194 /*
195 ============
196 COM_FileExtension
197 ============
198 */
199 char *COM_FileExtension(const char *in)
200 {
201  const char *s;
202  const char *last;
203 
204  if (!in) {
205  Com_Error(ERR_FATAL, "%s: NULL", __func__);
206  }
207 
208  s = in + strlen(in);
209  last = s;
210 
211  while (s != in) {
212  if (*s == '/') {
213  break;
214  }
215  if (*s == '.') {
216  return (char *)s;
217  }
218  s--;
219  }
220 
221  return (char *)last;
222 }
223 
224 /*
225 ============
226 COM_FileBase
227 ============
228 */
229 void COM_FileBase(char *in, char *out)
230 {
231  char *s, *s2;
232 
233  s = in + strlen(in) - 1;
234 
235  while (s != in && *s != '.')
236  s--;
237 
238  for (s2 = s; s2 != in && *s2 != '/'; s2--)
239  ;
240 
241  if (s - s2 < 2)
242  out[0] = 0;
243  else {
244  s--;
245  strncpy(out, s2 + 1, s - s2);
246  out[s - s2] = 0;
247  }
248 }
249 
250 /*
251 ============
252 COM_FilePath
253 
254 Returns the path up to, but not including the last /
255 ============
256 */
257 void COM_FilePath(const char *in, char *out, size_t size)
258 {
259  char *s;
260 
261  Q_strlcpy(out, in, size);
262  s = strrchr(out, '/');
263  if (s) {
264  *s = 0;
265  } else {
266  *out = 0;
267  }
268 }
269 
270 
271 /*
272 ==================
273 COM_DefaultExtension
274 
275 if path doesn't have .EXT, append extension
276 (extension should include the .)
277 ==================
278 */
279 size_t COM_DefaultExtension(char *path, const char *ext, size_t size)
280 {
281  char *src;
282  size_t len;
283 
284  if (*path) {
285  len = strlen(path);
286  src = path + len - 1;
287 
288  while (*src != '/' && src != path) {
289  if (*src == '.')
290  return len; // it has an extension
291  src--;
292  }
293  }
294 
295  len = Q_strlcat(path, ext, size);
296  return len;
297 }
298 
299 /*
300 ==================
301 COM_IsFloat
302 
303 Returns true if the given string is valid representation
304 of floating point number.
305 ==================
306 */
307 qboolean COM_IsFloat(const char *s)
308 {
309  int c, dot = '.';
310 
311  if (*s == '-') {
312  s++;
313  }
314  if (!*s) {
315  return qfalse;
316  }
317 
318  do {
319  c = *s++;
320  if (c == dot) {
321  dot = 0;
322  } else if (!Q_isdigit(c)) {
323  return qfalse;
324  }
325  } while (*s);
326 
327  return qtrue;
328 }
329 
330 qboolean COM_IsUint(const char *s)
331 {
332  int c;
333 
334  if (!*s) {
335  return qfalse;
336  }
337 
338  do {
339  c = *s++;
340  if (!Q_isdigit(c)) {
341  return qfalse;
342  }
343  } while (*s);
344 
345  return qtrue;
346 }
347 
348 qboolean COM_IsPath(const char *s)
349 {
350  int c;
351 
352  if (!*s) {
353  return qfalse;
354  }
355 
356  do {
357  c = *s++;
358  if (!Q_ispath(c)) {
359  return qfalse;
360  }
361  } while (*s);
362 
363  return qtrue;
364 }
365 
366 qboolean COM_IsWhite(const char *s)
367 {
368  int c;
369 
370  while (*s) {
371  c = *s++;
372  if (Q_isgraph(c)) {
373  return qfalse;
374  }
375  }
376 
377  return qtrue;
378 }
379 
380 int SortStrcmp(const void *p1, const void *p2)
381 {
382  return strcmp(*(const char **)p1, *(const char **)p2);
383 }
384 
385 int SortStricmp(const void *p1, const void *p2)
386 {
387  return Q_stricmp(*(const char **)p1, *(const char **)p2);
388 }
389 
390 /*
391 ================
392 COM_strclr
393 
394 Operates inplace, normalizing high-bit and removing unprintable characters.
395 Returns final number of characters, not including the NUL character.
396 ================
397 */
398 size_t COM_strclr(char *s)
399 {
400  char *p;
401  int c;
402  size_t len;
403 
404  p = s;
405  len = 0;
406  while (*s) {
407  c = *s++;
408  c &= 127;
409  if (Q_isprint(c)) {
410  *p++ = c;
411  len++;
412  }
413  }
414 
415  *p = 0;
416 
417  return len;
418 }
419 
420 /*
421 ============
422 va
423 
424 does a varargs printf into a temp buffer, so I don't need to have
425 varargs versions of all text functions.
426 FIXME: make this buffer size safe someday
427 ============
428 */
429 char *va(const char *format, ...)
430 {
431  va_list argptr;
432  static char buffers[2][0x2800];
433  static int index;
434 
435  index ^= 1;
436 
437  va_start(argptr, format);
438  Q_vsnprintf(buffers[index], sizeof(buffers[0]), format, argptr);
439  va_end(argptr);
440 
441  return buffers[index];
442 }
443 
444 static char com_token[4][MAX_TOKEN_CHARS];
445 static int com_tokidx;
446 
447 /*
448 ==============
449 COM_Parse
450 
451 Parse a token out of a string.
452 Handles C and C++ comments.
453 ==============
454 */
455 char *COM_Parse(const char **data_p)
456 {
457  int c;
458  int len;
459  const char *data;
460  char *s = com_token[com_tokidx++ & 3];
461 
462  data = *data_p;
463  len = 0;
464  s[0] = 0;
465 
466  if (!data) {
467  *data_p = NULL;
468  return s;
469  }
470 
471 // skip whitespace
472 skipwhite:
473  while ((c = *data) <= ' ') {
474  if (c == 0) {
475  *data_p = NULL;
476  return s;
477  }
478  data++;
479  }
480 
481 // skip // comments
482  if (c == '/' && data[1] == '/') {
483  data += 2;
484  while (*data && *data != '\n')
485  data++;
486  goto skipwhite;
487  }
488 
489 // skip /* */ comments
490  if (c == '/' && data[1] == '*') {
491  data += 2;
492  while (*data) {
493  if (data[0] == '*' && data[1] == '/') {
494  data += 2;
495  break;
496  }
497  data++;
498  }
499  goto skipwhite;
500  }
501 
502 // handle quoted strings specially
503  if (c == '\"') {
504  data++;
505  while (1) {
506  c = *data++;
507  if (c == '\"' || !c) {
508  goto finish;
509  }
510 
511  if (len < MAX_TOKEN_CHARS - 1) {
512  s[len++] = c;
513  }
514  }
515  }
516 
517 // parse a regular word
518  do {
519  if (len < MAX_TOKEN_CHARS - 1) {
520  s[len++] = c;
521  }
522  data++;
523  c = *data;
524  } while (c > 32);
525 
526 finish:
527  s[len] = 0;
528 
529  *data_p = data;
530  return s;
531 }
532 
533 /*
534 ==============
535 COM_Compress
536 
537 Operates in place, removing excess whitespace and comments.
538 Non-contiguous line feeds are preserved.
539 
540 Returns resulting data length.
541 ==============
542 */
543 size_t COM_Compress(char *data)
544 {
545  int c, n = 0;
546  char *s = data, *d = data;
547 
548  while (*s) {
549  // skip whitespace
550  if (*s <= ' ') {
551  if (n == 0) {
552  n = ' ';
553  }
554  do {
555  c = *s++;
556  if (c == '\n') {
557  n = '\n';
558  }
559  if (!c) {
560  goto finish;
561  }
562  } while (*s <= ' ');
563  }
564 
565  // skip // comments
566  if (s[0] == '/' && s[1] == '/') {
567  n = ' ';
568  s += 2;
569  while (*s && *s != '\n') {
570  s++;
571  }
572  continue;
573  }
574 
575  // skip /* */ comments
576  if (s[0] == '/' && s[1] == '*') {
577  n = ' ';
578  s += 2;
579  while (*s) {
580  if (s[0] == '*' && s[1] == '/') {
581  s += 2;
582  break;
583  }
584  if (*s == '\n') {
585  n = '\n';
586  }
587  s++;
588  }
589  continue;
590  }
591 
592  // add whitespace character
593  if (n) {
594  *d++ = n;
595  n = 0;
596  }
597 
598  // handle quoted strings specially
599  if (*s == '\"') {
600  s++;
601  *d++ = '\"';
602  do {
603  c = *s++;
604  if (!c) {
605  goto finish;
606  }
607  *d++ = c;
608  } while (c != '\"');
609  continue;
610  }
611 
612  // handle line feed escape
613  if (*s == '\\' && s[1] == '\n') {
614  s += 2;
615  continue;
616  }
617  if (*s == '\\' && s[1] == '\r' && s[2] == '\n') {
618  s += 3;
619  continue;
620  }
621 
622  // parse a regular word
623  do {
624  *d++ = *s++;
625  } while (*s > ' ');
626  }
627 
628 finish:
629  *d = 0;
630 
631  return d - data;
632 }
633 
634 /*
635 ============================================================================
636 
637  LIBRARY REPLACEMENT FUNCTIONS
638 
639 ============================================================================
640 */
641 
642 int Q_strncasecmp(const char *s1, const char *s2, size_t n)
643 {
644  int c1, c2;
645 
646  do {
647  c1 = *s1++;
648  c2 = *s2++;
649 
650  if (!n--)
651  return 0; /* strings are equal until end point */
652 
653  if (c1 != c2) {
654  c1 = Q_tolower(c1);
655  c2 = Q_tolower(c2);
656  if (c1 < c2)
657  return -1;
658  if (c1 > c2)
659  return 1; /* strings not equal */
660  }
661  } while (c1);
662 
663  return 0; /* strings are equal */
664 }
665 
666 int Q_strcasecmp(const char *s1, const char *s2)
667 {
668  int c1, c2;
669 
670  do {
671  c1 = *s1++;
672  c2 = *s2++;
673 
674  if (c1 != c2) {
675  c1 = Q_tolower(c1);
676  c2 = Q_tolower(c2);
677  if (c1 < c2)
678  return -1;
679  if (c1 > c2)
680  return 1; /* strings not equal */
681  }
682  } while (c1);
683 
684  return 0; /* strings are equal */
685 }
686 
687 char *Q_strcasestr(const char *s1, const char *s2)
688 {
689  size_t l1, l2;
690 
691  l2 = strlen(s2);
692  if (!l2) {
693  return (char *)s1;
694  }
695 
696  l1 = strlen(s1);
697  while (l1 >= l2) {
698  l1--;
699  if (!Q_strncasecmp(s1, s2, l2)) {
700  return (char *)s1;
701  }
702  s1++;
703  }
704 
705  return NULL;
706 }
707 
708 /*
709 ===============
710 Q_strlcpy
711 
712 Returns length of the source string.
713 ===============
714 */
715 size_t Q_strlcpy(char *dst, const char *src, size_t size)
716 {
717  size_t ret = strlen(src);
718 
719  if (size) {
720  size_t len = ret >= size ? size - 1 : ret;
721  memcpy(dst, src, len);
722  dst[len] = 0;
723  }
724 
725  return ret;
726 }
727 
728 /*
729 ===============
730 Q_strlcat
731 
732 Returns length of the source and destinations strings combined.
733 ===============
734 */
735 size_t Q_strlcat(char *dst, const char *src, size_t size)
736 {
737  size_t ret, len = strlen(dst);
738 
739  if (len >= size) {
740  Com_Error(ERR_FATAL, "%s: already overflowed", __func__);
741  }
742 
743  ret = Q_strlcpy(dst + len, src, size - len);
744  ret += len;
745 
746  return ret;
747 }
748 
749 /*
750 ===============
751 Q_concat
752 
753 Returns number of characters that would be written into the buffer,
754 excluding trailing '\0'. If the returned value is equal to or greater than
755 buffer size, resulting string is truncated.
756 ===============
757 */
758 size_t Q_concat(char *dest, size_t size, ...)
759 {
760  va_list argptr;
761  const char *s;
762  size_t len, total = 0;
763 
764  va_start(argptr, size);
765  while ((s = va_arg(argptr, const char *)) != NULL) {
766  len = strlen(s);
767  if (total + len < size) {
768  memcpy(dest, s, len);
769  dest += len;
770  }
771  total += len;
772  }
773  va_end(argptr);
774 
775  if (size) {
776  *dest = 0;
777  }
778 
779  return total;
780 }
781 
782 /*
783 ===============
784 Q_vsnprintf
785 
786 Returns number of characters that would be written into the buffer,
787 excluding trailing '\0'. If the returned value is equal to or greater than
788 buffer size, resulting string is truncated.
789 ===============
790 */
791 size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
792 {
793  int ret;
794 
795  if (size > INT_MAX)
796  Com_Error(ERR_FATAL, "%s: bad buffer size", __func__);
797 
798 #ifdef _WIN32
799  if (size) {
800  ret = _vsnprintf(dest, size - 1, fmt, argptr);
801  if (ret < 0 || ret >= size - 1)
802  dest[size - 1] = 0;
803  } else {
804  ret = _vscprintf(fmt, argptr);
805  }
806 #else
807  ret = vsnprintf(dest, size, fmt, argptr);
808 #endif
809 
810  // exploit the fact -1 becomes SIZE_MAX > size
811  return (size_t)ret;
812 }
813 
814 /*
815 ===============
816 Q_vscnprintf
817 
818 Returns number of characters actually written into the buffer,
819 excluding trailing '\0'. If buffer size is 0, this function does nothing
820 and returns 0.
821 ===============
822 */
823 size_t Q_vscnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
824 {
825  size_t ret;
826 
827  if (!size)
828  return 0;
829 
830  ret = Q_vsnprintf(dest, size, fmt, argptr);
831  if (ret < size)
832  return ret;
833 
834  return size - 1;
835 }
836 
837 /*
838 ===============
839 Q_snprintf
840 
841 Returns number of characters that would be written into the buffer,
842 excluding trailing '\0'. If the returned value is equal to or greater than
843 buffer size, resulting string is truncated.
844 ===============
845 */
846 size_t Q_snprintf(char *dest, size_t size, const char *fmt, ...)
847 {
848  va_list argptr;
849  size_t ret;
850 
851  va_start(argptr, fmt);
852  ret = Q_vsnprintf(dest, size, fmt, argptr);
853  va_end(argptr);
854 
855  return ret;
856 }
857 
858 /*
859 ===============
860 Q_scnprintf
861 
862 Returns number of characters actually written into the buffer,
863 excluding trailing '\0'. If buffer size is 0, this function does nothing
864 and returns 0.
865 ===============
866 */
867 size_t Q_scnprintf(char *dest, size_t size, const char *fmt, ...)
868 {
869  va_list argptr;
870  size_t ret;
871 
872  va_start(argptr, fmt);
873  ret = Q_vscnprintf(dest, size, fmt, argptr);
874  va_end(argptr);
875 
876  return ret;
877 }
878 
879 char *Q_strchrnul(const char *s, int c)
880 {
881  while (*s && *s != c) {
882  s++;
883  }
884  return (char *)s;
885 }
886 
887 /*
888 ===============
889 Q_memccpy
890 
891 Copies no more than 'size' bytes stopping when 'c' character is found.
892 Returns pointer to next byte after 'c' in 'dst', or NULL if 'c' was not found.
893 ===============
894 */
895 void *Q_memccpy(void *dst, const void *src, int c, size_t size)
896 {
897  byte *d = dst;
898  const byte *s = src;
899 
900  while (size--) {
901  if ((*d++ = *s++) == c) {
902  return d;
903  }
904  }
905 
906  return NULL;
907 }
908 
909 void Q_setenv(const char *name, const char *value)
910 {
911 #ifdef _WIN32
912  if (!value) {
913  value = "";
914  }
915 #if (_MSC_VER >= 1400)
916  _putenv_s(name, value);
917 #else
918  _putenv(va("%s=%s", name, value));
919 #endif
920 #else // _WIN32
921  if (value) {
922  setenv(name, value, 1);
923  } else {
924  unsetenv(name);
925  }
926 #endif // !_WIN32
927 }
928 
929 /*
930 =====================================================================
931 
932  INFO STRINGS
933 
934 =====================================================================
935 */
936 
937 /*
938 ===============
939 Info_ValueForKey
940 
941 Searches the string for the given
942 key and returns the associated value, or an empty string.
943 ===============
944 */
945 char *Info_ValueForKey(const char *s, const char *key)
946 {
947  // use 4 buffers so compares work without stomping on each other
948  static char value[4][MAX_INFO_STRING];
949  static int valueindex;
950  char pkey[MAX_INFO_STRING];
951  char *o;
952 
953  valueindex++;
954  if (*s == '\\')
955  s++;
956  while (1) {
957  o = pkey;
958  while (*s != '\\') {
959  if (!*s)
960  goto fail;
961  *o++ = *s++;
962  }
963  *o = 0;
964  s++;
965 
966  o = value[valueindex & 3];
967  while (*s != '\\' && *s) {
968  *o++ = *s++;
969  }
970  *o = 0;
971 
972  if (!strcmp(key, pkey))
973  return value[valueindex & 3];
974 
975  if (!*s)
976  goto fail;
977  s++;
978  }
979 
980 fail:
981  o = value[valueindex & 3];
982  *o = 0;
983  return o;
984 }
985 
986 /*
987 ==================
988 Info_RemoveKey
989 ==================
990 */
991 void Info_RemoveKey(char *s, const char *key)
992 {
993  char *start;
994  char pkey[MAX_INFO_STRING];
995  char *o;
996 
997  while (1) {
998  start = s;
999  if (*s == '\\')
1000  s++;
1001  o = pkey;
1002  while (*s != '\\') {
1003  if (!*s)
1004  return;
1005  *o++ = *s++;
1006  }
1007  *o = 0;
1008  s++;
1009 
1010  while (*s != '\\' && *s) {
1011  s++;
1012  }
1013 
1014  if (!strcmp(key, pkey)) {
1015  o = start; // remove this part
1016  while (*s) {
1017  *o++ = *s++;
1018  }
1019  *o = 0;
1020  s = start;
1021  continue; // search for duplicates
1022  }
1023 
1024  if (!*s)
1025  return;
1026  }
1027 
1028 }
1029 
1030 
1031 /*
1032 ==================
1033 Info_Validate
1034 
1035 Some characters are illegal in info strings because they
1036 can mess up the server's parsing.
1037 Also checks the length of keys/values and the whole string.
1038 ==================
1039 */
1040 qboolean Info_Validate(const char *s)
1041 {
1042  size_t len, total;
1043  int c;
1044 
1045  total = 0;
1046  while (1) {
1047  //
1048  // validate key
1049  //
1050  if (*s == '\\') {
1051  s++;
1052  if (++total == MAX_INFO_STRING) {
1053  return qfalse; // oversize infostring
1054  }
1055  }
1056  if (!*s) {
1057  return qfalse; // missing key
1058  }
1059  len = 0;
1060  while (*s != '\\') {
1061  c = *s++;
1062  if (!Q_isprint(c) || c == '\"' || c == ';') {
1063  return qfalse; // illegal characters
1064  }
1065  if (++len == MAX_INFO_KEY) {
1066  return qfalse; // oversize key
1067  }
1068  if (++total == MAX_INFO_STRING) {
1069  return qfalse; // oversize infostring
1070  }
1071  if (!*s) {
1072  return qfalse; // missing value
1073  }
1074  }
1075 
1076  //
1077  // validate value
1078  //
1079  s++;
1080  if (++total == MAX_INFO_STRING) {
1081  return qfalse; // oversize infostring
1082  }
1083  if (!*s) {
1084  return qfalse; // missing value
1085  }
1086  len = 0;
1087  while (*s != '\\') {
1088  c = *s++;
1089  if (!Q_isprint(c) || c == '\"' || c == ';') {
1090  return qfalse; // illegal characters
1091  }
1092  if (++len == MAX_INFO_VALUE) {
1093  return qfalse; // oversize value
1094  }
1095  if (++total == MAX_INFO_STRING) {
1096  return qfalse; // oversize infostring
1097  }
1098  if (!*s) {
1099  return qtrue; // end of string
1100  }
1101  }
1102  }
1103 
1104  return qfalse; // quiet compiler warning
1105 }
1106 
1107 /*
1108 ============
1109 Info_SubValidate
1110 ============
1111 */
1112 size_t Info_SubValidate(const char *s)
1113 {
1114  size_t len;
1115  int c;
1116 
1117  len = 0;
1118  while (*s) {
1119  c = *s++;
1120  c &= 127; // strip high bits
1121  if (c == '\\' || c == '\"' || c == ';') {
1122  return SIZE_MAX; // illegal characters
1123  }
1124  if (++len == MAX_QPATH) {
1125  return MAX_QPATH; // oversize value
1126  }
1127  }
1128 
1129  return len;
1130 }
1131 
1132 /*
1133 ==================
1134 Info_SetValueForKey
1135 ==================
1136 */
1137 qboolean Info_SetValueForKey(char *s, const char *key, const char *value)
1138 {
1139  char newi[MAX_INFO_STRING], *v;
1140  size_t l, kl, vl;
1141  int c;
1142 
1143  // validate key
1144  kl = Info_SubValidate(key);
1145  if (kl >= MAX_QPATH) {
1146  return qfalse;
1147  }
1148 
1149  // validate value
1150  vl = Info_SubValidate(value);
1151  if (vl >= MAX_QPATH) {
1152  return qfalse;
1153  }
1154 
1155  Info_RemoveKey(s, key);
1156  if (!vl) {
1157  return qtrue;
1158  }
1159 
1160  l = strlen(s);
1161  if (l + kl + vl + 2 >= MAX_INFO_STRING) {
1162  return qfalse;
1163  }
1164 
1165  newi[0] = '\\';
1166  memcpy(newi + 1, key, kl);
1167  newi[kl + 1] = '\\';
1168  memcpy(newi + kl + 2, value, vl + 1);
1169 
1170  // only copy ascii values
1171  s += l;
1172  v = newi;
1173  while (*v) {
1174  c = *v++;
1175  c &= 127; // strip high bits
1176  if (Q_isprint(c))
1177  *s++ = c;
1178  }
1179  *s = 0;
1180 
1181  return qtrue;
1182 }
1183 
1184 /*
1185 ==================
1186 Info_NextPair
1187 ==================
1188 */
1189 void Info_NextPair(const char **string, char *key, char *value)
1190 {
1191  char *o;
1192  const char *s;
1193 
1194  *value = *key = 0;
1195 
1196  s = *string;
1197  if (!s) {
1198  return;
1199  }
1200 
1201  if (*s == '\\')
1202  s++;
1203 
1204  if (!*s) {
1205  *string = NULL;
1206  return;
1207  }
1208 
1209  o = key;
1210  while (*s && *s != '\\') {
1211  *o++ = *s++;
1212  }
1213  *o = 0;
1214 
1215  if (!*s) {
1216  *string = NULL;
1217  return;
1218  }
1219 
1220  o = value;
1221  s++;
1222  while (*s && *s != '\\') {
1223  *o++ = *s++;
1224  }
1225  *o = 0;
1226 
1227  *string = s;
1228 }
1229 
1230 /*
1231 ==================
1232 Info_Print
1233 ==================
1234 */
1235 void Info_Print(const char *infostring)
1236 {
1237  char key[MAX_INFO_STRING];
1238  char value[MAX_INFO_STRING];
1239 
1240  while (1) {
1241  Info_NextPair(&infostring, key, value);
1242  if (!infostring)
1243  break;
1244 
1245  if (!key[0])
1246  strcpy(key, "<MISSING KEY>");
1247 
1248  if (!value[0])
1249  strcpy(value, "<MISSING VALUE>");
1250 
1251  Com_Printf("%-20s %s\n", key, value);
1252  }
1253 }
1254 
RadiusFromBounds
vec_t RadiusFromBounds(const vec3_t mins, const vec3_t maxs)
Definition: shared.c:127
Q_strlcat
size_t Q_strlcat(char *dst, const char *src, size_t size)
Definition: shared.c:735
COM_IsFloat
qboolean COM_IsFloat(const char *s)
Definition: shared.c:307
Info_Validate
qboolean Info_Validate(const char *s)
Definition: shared.c:1040
Q_strncasecmp
int Q_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: shared.c:642
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
com_token
static char com_token[4][MAX_TOKEN_CHARS]
Definition: shared.c:444
data_p
static byte * data_p
Definition: mem.c:100
COM_IsPath
qboolean COM_IsPath(const char *s)
Definition: shared.c:348
Q_setenv
void Q_setenv(const char *name, const char *value)
Definition: shared.c:909
Q_vsnprintf
size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:791
ext
char ext[4]
Definition: images.c:657
Q_strchrnul
char * Q_strchrnul(const char *s, int c)
Definition: shared.c:879
vec3_origin
vec3_t vec3_origin
Definition: shared.c:21
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
COM_FileBase
void COM_FileBase(char *in, char *out)
Definition: shared.c:229
forward
static vec3_t forward
Definition: p_view.c:27
UnionBounds
void UnionBounds(vec3_t a[2], vec3_t b[2], vec3_t c[2])
Definition: shared.c:111
Info_ValueForKey
char * Info_ValueForKey(const char *s, const char *key)
Definition: shared.c:945
va
char * va(const char *format,...)
Definition: shared.c:429
SortStricmp
int SortStricmp(const void *p1, const void *p2)
Definition: shared.c:385
ClearBounds
void ClearBounds(vec3_t mins, vec3_t maxs)
Definition: shared.c:91
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: shared.c:23
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
COM_IsWhite
qboolean COM_IsWhite(const char *s)
Definition: shared.c:366
COM_Compress
size_t COM_Compress(char *data)
Definition: shared.c:543
Info_Print
void Info_Print(const char *infostring)
Definition: shared.c:1235
VectorNormalize2
vec_t VectorNormalize2(vec3_t v, vec3_t out)
Definition: shared.c:73
Q_strcasecmp
int Q_strcasecmp(const char *s1, const char *s2)
Definition: shared.c:666
COM_IsUint
qboolean COM_IsUint(const char *s)
Definition: shared.c:330
c
statCounters_t c
Definition: main.c:30
COM_StripExtension
void COM_StripExtension(const char *in, char *out, size_t size)
Definition: shared.c:174
up
static vec3_t up
Definition: p_view.c:27
right
static vec3_t right
Definition: p_view.c:27
com_tokidx
static int com_tokidx
Definition: shared.c:445
Q_strcasestr
char * Q_strcasestr(const char *s1, const char *s2)
Definition: shared.c:687
Q_vscnprintf
size_t Q_vscnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:823
COM_SkipPath
char * COM_SkipPath(const char *pathname)
Definition: shared.c:152
Q_memccpy
void * Q_memccpy(void *dst, const void *src, int c, size_t size)
Definition: shared.c:895
COM_Parse
char * COM_Parse(const char **data_p)
Definition: shared.c:455
COM_DefaultExtension
size_t COM_DefaultExtension(char *path, const char *ext, size_t size)
Definition: shared.c:279
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
SortStrcmp
int SortStrcmp(const void *p1, const void *p2)
Definition: shared.c:380
Info_SetValueForKey
qboolean Info_SetValueForKey(char *s, const char *key, const char *value)
Definition: shared.c:1137
Info_NextPair
void Info_NextPair(const char **string, char *key, char *value)
Definition: shared.c:1189
COM_FileExtension
char * COM_FileExtension(const char *in)
Definition: shared.c:199
Q_scnprintf
size_t Q_scnprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:867
COM_FilePath
void COM_FilePath(const char *in, char *out, size_t size)
Definition: shared.c:257
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
AddPointToBounds
void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs)
Definition: shared.c:97
Info_RemoveKey
void Info_RemoveKey(char *s, const char *key)
Definition: shared.c:991
Info_SubValidate
size_t Info_SubValidate(const char *s)
Definition: shared.c:1112
COM_strclr
size_t COM_strclr(char *s)
Definition: shared.c:398