q_std.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. // standard library stuff for game DLL
  4. #include "g_local.h"
  5. //====================================================================================
  6. g_fmt_data_t g_fmt_data;
  7. bool COM_IsSeparator(char c, const char *seps)
  8. {
  9. if (!c)
  10. return true;
  11. for (const char *sep = seps; *sep; sep++)
  12. if (*sep == c)
  13. return true;
  14. return false;
  15. }
  16. /*
  17. ==============
  18. COM_ParseEx
  19. Parse a token out of a string
  20. ==============
  21. */
  22. char *COM_ParseEx(const char **data_p, const char *seps, char *buffer, size_t buffer_size)
  23. {
  24. static char com_token[MAX_TOKEN_CHARS];
  25. if (!buffer)
  26. {
  27. buffer = com_token;
  28. buffer_size = MAX_TOKEN_CHARS;
  29. }
  30. int c;
  31. int len;
  32. const char *data;
  33. data = *data_p;
  34. len = 0;
  35. buffer[0] = '\0';
  36. if (!data)
  37. {
  38. *data_p = nullptr;
  39. return buffer;
  40. }
  41. // skip whitespace
  42. skipwhite:
  43. while (COM_IsSeparator(c = *data, seps))
  44. {
  45. if (c == '\0')
  46. {
  47. *data_p = nullptr;
  48. return buffer;
  49. }
  50. data++;
  51. }
  52. // skip // comments
  53. if (c == '/' && data[1] == '/')
  54. {
  55. while (*data && *data != '\n')
  56. data++;
  57. goto skipwhite;
  58. }
  59. // handle quoted strings specially
  60. if (c == '\"')
  61. {
  62. data++;
  63. while (1)
  64. {
  65. c = *data++;
  66. if (c == '\"' || !c)
  67. {
  68. const size_t endpos = std::min<size_t>(len, buffer_size - 1); // [KEX] avoid overflow
  69. buffer[endpos] = '\0';
  70. *data_p = data;
  71. return buffer;
  72. }
  73. if (len < buffer_size)
  74. {
  75. buffer[len] = c;
  76. len++;
  77. }
  78. }
  79. }
  80. // parse a regular word
  81. do
  82. {
  83. if (len < buffer_size)
  84. {
  85. buffer[len] = c;
  86. len++;
  87. }
  88. data++;
  89. c = *data;
  90. } while (!COM_IsSeparator(c, seps));
  91. if (len == buffer_size)
  92. {
  93. gi.Com_PrintFmt("Token exceeded {} chars, discarded.\n", buffer_size);
  94. len = 0;
  95. }
  96. buffer[len] = '\0';
  97. *data_p = data;
  98. return buffer;
  99. }
  100. /*
  101. ============================================================================
  102. LIBRARY REPLACEMENT FUNCTIONS
  103. ============================================================================
  104. */
  105. // NB: these funcs are duplicated in the engine; this define gates us for
  106. // static compilation.
  107. #if defined(KEX_Q2GAME_DYNAMIC)
  108. int Q_strcasecmp(const char *s1, const char *s2)
  109. {
  110. int c1, c2;
  111. do
  112. {
  113. c1 = *s1++;
  114. c2 = *s2++;
  115. if (c1 != c2)
  116. {
  117. if (c1 >= 'a' && c1 <= 'z')
  118. c1 -= ('a' - 'A');
  119. if (c2 >= 'a' && c2 <= 'z')
  120. c2 -= ('a' - 'A');
  121. if (c1 != c2)
  122. return c1 < c2 ? -1 : 1; // strings not equal
  123. }
  124. } while (c1);
  125. return 0; // strings are equal
  126. }
  127. int Q_strncasecmp(const char *s1, const char *s2, size_t n)
  128. {
  129. int c1, c2;
  130. do
  131. {
  132. c1 = *s1++;
  133. c2 = *s2++;
  134. if (!n--)
  135. return 0; // strings are equal until end point
  136. if (c1 != c2)
  137. {
  138. if (c1 >= 'a' && c1 <= 'z')
  139. c1 -= ('a' - 'A');
  140. if (c2 >= 'a' && c2 <= 'z')
  141. c2 -= ('a' - 'A');
  142. if (c1 != c2)
  143. return c1 < c2 ? -1 : 1; // strings not equal
  144. }
  145. } while (c1);
  146. return 0; // strings are equal
  147. }
  148. /*
  149. =====================================================================
  150. BSD STRING UTILITIES - haleyjd 20170610
  151. =====================================================================
  152. */
  153. /*
  154. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  155. * All rights reserved.
  156. *
  157. * Redistribution and use in source and binary forms, with or without
  158. * modification, are permitted provided that the following conditions
  159. * are met:
  160. * 1. Redistributions of source code must retain the above copyright
  161. * notice, this list of conditions and the following disclaimer.
  162. * 2. Redistributions in binary form must reproduce the above copyright
  163. * notice, this list of conditions and the following disclaimer in the
  164. * documentation and/or other materials provided with the distribution.
  165. * 3. The name of the author may not be used to endorse or promote products
  166. * derived from this software without specific prior written permission.
  167. *
  168. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  169. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  170. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  171. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  172. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  173. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  174. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  175. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  176. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  177. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  178. */
  179. /*
  180. * Copy src to string dst of size siz. At most siz-1 characters
  181. * will be copied. Always NUL terminates (unless siz == 0).
  182. * Returns strlen(src); if retval >= siz, truncation occurred.
  183. */
  184. size_t Q_strlcpy(char *dst, const char *src, size_t siz)
  185. {
  186. char *d = dst;
  187. const char *s = src;
  188. size_t n = siz;
  189. /* Copy as many bytes as will fit */
  190. if(n != 0 && --n != 0)
  191. {
  192. do
  193. {
  194. if((*d++ = *s++) == 0)
  195. break;
  196. }
  197. while(--n != 0);
  198. }
  199. /* Not enough room in dst, add NUL and traverse rest of src */
  200. if(n == 0)
  201. {
  202. if(siz != 0)
  203. *d = '\0'; /* NUL-terminate dst */
  204. while(*s++)
  205. ; // counter loop
  206. }
  207. return (s - src - 1); /* count does not include NUL */
  208. }
  209. /*
  210. * Appends src to string dst of size siz (unlike strncat, siz is the
  211. * full size of dst, not space left). At most siz-1 characters
  212. * will be copied. Always NUL terminates (unless siz == 0).
  213. * Returns strlen(src); if retval >= siz, truncation occurred.
  214. */
  215. size_t Q_strlcat(char *dst, const char *src, size_t siz)
  216. {
  217. char *d = dst;
  218. const char *s = src;
  219. size_t n = siz;
  220. size_t dlen;
  221. /* Find the end of dst and adjust bytes left but don't go past end */
  222. while(*d != '\0' && n-- != 0)
  223. d++;
  224. dlen = d - dst;
  225. n = siz - dlen;
  226. if(n == 0)
  227. return(dlen + strlen(s));
  228. while(*s != '\0')
  229. {
  230. if(n != 1)
  231. {
  232. *d++ = *s;
  233. n--;
  234. }
  235. s++;
  236. }
  237. *d = '\0';
  238. return (dlen + (s - src)); /* count does not include NUL */
  239. }
  240. #if !defined(USE_CPP20_FORMAT) && !defined(NO_FMT_SOURCE)
  241. // fmt ugliness because we haven't figured out FMT_INCLUDE_ONLY
  242. #include "../src/format.cc"
  243. #endif
  244. #endif
  245. //====================================================================