00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "../common/common.h"
00029 #include "utf8.h"
00030
00035 const char *Com_SkipPath (const char *pathname)
00036 {
00037 char const* const last = strrchr(pathname, '/');
00038 return last ? last + 1 : pathname;
00039 }
00040
00041 char *Com_Trim (char *s)
00042 {
00043 char *left, *right;
00044
00045 left = s;
00046
00047 while (isspace(*left))
00048 left++;
00049
00050 right = left + strlen(left) - 1;
00051
00052 while (isspace(*right))
00053 *right-- = 0;
00054
00055 return left;
00056 }
00057
00061 static int Com_FilterAfterStar (const char *pattern, const char *text)
00062 {
00063 register const char *p = pattern, *t = text;
00064 register char c, c1;
00065
00066 while ((c = *p++) == '?' || c == '*')
00067 if (c == '?' && *t++ == '\0')
00068 return 0;
00069
00070 if (c == '\0')
00071 return 1;
00072
00073 if (c == '\\')
00074 c1 = *p;
00075 else
00076 c1 = c;
00077
00078 while (1) {
00079 if ((c == '[' || *t == c1) && Com_Filter(p - 1, t))
00080 return 1;
00081 if (*t++ == '\0')
00082 return 0;
00083 }
00084 }
00085
00100 int Com_Filter (const char *pattern, const char *text)
00101 {
00102 register const char *p = pattern, *t = text;
00103 register char c;
00104
00105 while ((c = *p++) != '\0')
00106 switch (c) {
00107 case '?':
00108 if (*t == '\0')
00109 return 0;
00110 else
00111 ++t;
00112 break;
00113
00114 case '\\':
00115 if (*p++ != *t++)
00116 return 0;
00117 break;
00118
00119 case '*':
00120 return Com_FilterAfterStar(p, t);
00121
00122 case '[':
00123 {
00124 register char c1 = *t++;
00125 int invert;
00126
00127 if (!c1)
00128 return (0);
00129
00130 invert = ((*p == '!') || (*p == '^'));
00131 if (invert)
00132 p++;
00133
00134 c = *p++;
00135 while (1) {
00136 register char cstart = c, cend = c;
00137
00138 if (c == '\\') {
00139 cstart = *p++;
00140 cend = cstart;
00141 }
00142 if (c == '\0')
00143 return 0;
00144
00145 c = *p++;
00146 if (c == '-' && *p != ']') {
00147 cend = *p++;
00148 if (cend == '\\')
00149 cend = *p++;
00150 if (cend == '\0')
00151 return 0;
00152 c = *p++;
00153 }
00154 if (c1 >= cstart && c1 <= cend)
00155 goto match;
00156 if (c == ']')
00157 break;
00158 }
00159 if (!invert)
00160 return 0;
00161 break;
00162
00163 match:
00164
00165 while (c != ']') {
00166 if (c == '\0')
00167 return 0;
00168 c = *p++;
00169 if (c == '\0')
00170 return 0;
00171 else if (c == '\\')
00172 ++p;
00173 }
00174 if (invert)
00175 return 0;
00176 break;
00177 }
00178
00179 default:
00180 if (c != *t++)
00181 return 0;
00182 }
00183
00184 return *t == '\0';
00185 }
00186
00194 void Com_ReplaceFilename (const char *fileName, const char *name, char *path, size_t size)
00195 {
00196 char *slash, *end;
00197
00198 Q_strncpyz(path, fileName, size);
00199
00200 end = path;
00201 while ((slash = strchr(end, '/')) != 0)
00202 end = slash + 1;
00203
00204 strcpy(end, name + 1);
00205 }
00206
00214 void Com_StripExtension (const char *in, char *out, const size_t size)
00215 {
00216 char *out_ext = NULL;
00217 int i = 1;
00218
00219 while (*in && i < size) {
00220 *out++ = *in++;
00221 i++;
00222
00223 if (*in == '.')
00224 out_ext = out;
00225 }
00226
00227 if (out_ext)
00228 *out_ext = 0;
00229 else
00230 *out = 0;
00231 }
00232
00237 const char *Com_GetExtension (const char *path)
00238 {
00239 const char *src = path + strlen(path) - 1;
00240 while (*src != '/' && src != path) {
00241 if (*src == '.')
00242 return src + 1;
00243 src--;
00244 }
00245
00246 return NULL;
00247 }
00248
00252 void Com_DefaultExtension (char *path, size_t len, const char *extension)
00253 {
00254 char oldPath[MAX_OSPATH];
00255 const char *src;
00256
00257
00258
00259 src = path + strlen(path) - 1;
00260
00261 while (*src != '/' && src != path) {
00262 if (*src == '.')
00263 return;
00264 src--;
00265 }
00266
00267 Q_strncpyz(oldPath, path, sizeof(oldPath));
00268 Com_sprintf(path, len, "%s%s", oldPath, extension);
00269 }
00270
00275 void Com_FilePath (const char *in, char *out)
00276 {
00277 const char *s = in + strlen(in) - 1;
00278
00279 while (s != in && *s != '/')
00280 s--;
00281
00282 Q_strncpyz(out, in, s - in + 1);
00283 }
00284
00293 int Q_FloatSort (const void *float1, const void *float2)
00294 {
00295 return (*(const float *)float1 - *(const float *)float2);
00296 }
00297
00306 int Q_StringSort (const void *string1, const void *string2)
00307 {
00308 const char *s1 = (const char *)string1;
00309 const char *s2 = (const char *)string2;
00310 if (*s1 < *s2)
00311 return -1;
00312 else if (*s1 == *s2) {
00313 while (*s1) {
00314 s1++;
00315 s2++;
00316 if (*s1 < *s2)
00317 return -1;
00318 if (*s1 > *s2)
00319 return 1;
00320 }
00321 return 0;
00322 } else
00323 return 1;
00324 }
00325
00326 #define VA_BUFSIZE 4096
00327
00331 char *va (const char *format, ...)
00332 {
00333 va_list argptr;
00334
00335 static char string[16][VA_BUFSIZE];
00336 static unsigned int index = 0;
00337 char *buf;
00338
00339 buf = string[index & 0x0F];
00340 index++;
00341
00342 va_start(argptr, format);
00343 Q_vsnprintf(buf, VA_BUFSIZE, format, argptr);
00344 va_end(argptr);
00345
00346 return buf;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 char *Q_strlwr (char *str)
00356 {
00357 char* origs = str;
00358 while (*str) {
00359 *str = tolower(*str);
00360 str++;
00361 }
00362 return origs;
00363 }
00364
00365 #ifndef HAVE_STRNCASECMP
00366 int Q_strncasecmp (const char *s1, const char *s2, size_t n)
00367 {
00368 while (n-- != 0) {
00369 int c1 = *s1++;
00370 int c2 = *s2++;
00371
00372 if (c1 != c2) {
00373 if ('a' <= c1 && c1 <= 'z')
00374 c1 += 'a' - 'A';
00375 if ('a' <= c2 && c2 <= 'z')
00376 c2 += 'a' - 'A';
00377 if (c1 != c2)
00378 return (unsigned char)c1 - (unsigned char)c2;
00379 }
00380
00381 if (c1 == '\0')
00382 break;
00383 }
00384
00385 return 0;
00386 }
00387 #endif
00388
00395 #ifdef DEBUG
00396 void Q_strncpyzDebug (char *dest, const char *src, size_t destsize, const char *file, int line)
00397 #else
00398 void Q_strncpyz (char *dest, const char *src, size_t destsize)
00399 #endif
00400 {
00401 #ifdef DEBUG
00402 if (!dest)
00403 Sys_Error("Q_strncpyz: NULL dest (%s, %i)", file, line);
00404 if (!src)
00405 Sys_Error("Q_strncpyz: NULL src (%s, %i)", file, line);
00406 if (destsize < 1)
00407 Sys_Error("Q_strncpyz: destsize < 1 (%s, %i)", file, line);
00408 #endif
00409 UTF8_strncpyz(dest, src, destsize);
00410 }
00411
00420 void Q_strcat (char *dest, const char *src, size_t destsize)
00421 {
00422 size_t dest_length;
00423 dest_length = strlen(dest);
00424 if (dest_length >= destsize)
00425 Sys_Error("Q_strcat: already overflowed");
00426 Q_strncpyz(dest + dest_length, src, destsize - dest_length);
00427 }
00428
00436 qboolean Com_sprintf (char *dest, size_t size, const char *fmt, ...)
00437 {
00438 va_list ap;
00439 int len;
00440
00441 if (!fmt)
00442 return qfalse;
00443
00444 va_start(ap, fmt);
00445 len = Q_vsnprintf(dest, size, fmt, ap);
00446 va_end(ap);
00447
00448 if (len <= size - 1)
00449 return qtrue;
00450
00451
00452 len = size - 1;
00453
00454
00455 if (len > 0 && (unsigned char) dest[len - 1] >= 0x80) {
00456 int i = len - 1;
00457 while ((i > 0) && ((unsigned char) dest[i] & 0xc0) == 0x80)
00458 i--;
00459 if (UTF8_char_len(dest[i]) + i > len) {
00460 dest[i] = '\0';
00461 }
00462 #ifdef DEBUG
00463 else {
00464
00465 len = i + UTF8_char_len(dest[i]);
00466 assert(dest[len] == '\0');
00467 }
00468 #endif
00469 }
00470
00471 return qfalse;
00472 }
00473
00477 int Q_vsnprintf (char *str, size_t size, const char *format, va_list ap)
00478 {
00479 int len;
00480
00481 #if defined(_WIN32)
00482 len = _vsnprintf(str, size, format, ap);
00483 str[size - 1] = '\0';
00484 #ifdef DEBUG
00485 if (len == -1)
00486 Com_Printf("Q_vsnprintf: string (%.32s...) was truncated (%i) - target buffer too small ("UFO_SIZE_T")\n", str, len, size);
00487 #endif
00488 #else
00489 len = vsnprintf(str, size, format, ap);
00490 #ifdef DEBUG
00491 if ((size_t)len >= size)
00492 Com_Printf("Q_vsnprintf: string (%.32s...) was truncated (%i) - target buffer too small ("UFO_SIZE_T")\n", str, len, size);
00493 #endif
00494 #endif
00495
00496 return len;
00497 }
00498
00499 const char *Q_stristr (const char *str, const char *substr)
00500 {
00501 const size_t sublen = strlen(substr);
00502 while (*str) {
00503 if (!Q_strncasecmp(str, substr, sublen))
00504 break;
00505 str++;
00506 }
00507 if (!(*str))
00508 str = NULL;
00509 return str;
00510 }