core/sm_stringutil.cpp
author Borja Ferrer <faluco@alliedmods.net>
Fri Jan 12 23:56:02 2007 +0000 (2007-01-12)
changeset 288 d89bf250dac4
parent 276 065d151c41b2
child 351 7c219cde57e7
permissions -rw-r--r--
Added new debugger logger
Added format errors
Paused plugins now have their forwards blocked
Fixed bug where pausing a plugin wouldnt make any effect
faluco@230
     1
#include <stdlib.h>
faluco@230
     2
#include <ctype.h>
faluco@274
     3
#include <stdarg.h>
faluco@227
     4
#include "sm_stringutil.h"
faluco@288
     5
#include "CLogger.h"
faluco@227
     6
faluco@227
     7
#define LADJUST			0x00000004		/* left adjustment */
faluco@227
     8
#define ZEROPAD			0x00000080		/* zero (as opposed to blank) pad */
faluco@227
     9
#define to_digit(c)		((c) - '0')
faluco@227
    10
#define is_digit(c)		((unsigned)to_digit(c) <= 9)
faluco@227
    11
faluco@288
    12
#define CHECK_ARGS(x) \
faluco@288
    13
	if ((arg+x) > args) { \
faluco@288
    14
		g_Logger.LogError("String formatted incorrectly - parameter %d (total %d)", arg, args); \
faluco@288
    15
		return 0; \
faluco@227
    16
	}
faluco@227
    17
dvander@276
    18
//:TODO: review this code before we choose a license
dvander@276
    19
faluco@227
    20
void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
faluco@227
    21
{
faluco@227
    22
	int size = 0;
faluco@227
    23
	char *buf;
faluco@227
    24
	static char nlstr[] = {'(','n','u','l','l',')','\0'};
faluco@227
    25
faluco@227
    26
	buf = *buf_p;
faluco@227
    27
faluco@227
    28
	if (string == NULL)
faluco@227
    29
	{
faluco@227
    30
		string = nlstr;
faluco@227
    31
		prec = -1;
faluco@227
    32
	}
faluco@227
    33
faluco@227
    34
	if (prec >= 0)
faluco@227
    35
	{
faluco@227
    36
		for (size = 0; size < prec; size++) 
faluco@227
    37
		{
faluco@227
    38
			if (string[size] == '\0')
faluco@227
    39
			{
faluco@227
    40
				break;
faluco@227
    41
			}
faluco@227
    42
		}
faluco@227
    43
	} else {
faluco@227
    44
		while (string[size++]);
faluco@227
    45
		size--;
faluco@227
    46
	}
faluco@227
    47
faluco@227
    48
	if (size > (int)maxlen)
faluco@227
    49
	{
faluco@227
    50
		size = maxlen;
faluco@227
    51
	}
faluco@227
    52
faluco@227
    53
	maxlen -= size;
faluco@227
    54
	width -= size;
faluco@227
    55
faluco@227
    56
	while (size--)
faluco@227
    57
	{
faluco@227
    58
		*buf++ = *string++;
faluco@227
    59
	}
faluco@227
    60
faluco@227
    61
	while ((width-- > 0) && maxlen)
faluco@227
    62
	{
faluco@227
    63
		*buf++ = ' ';
faluco@227
    64
		maxlen--;
faluco@227
    65
	}
faluco@227
    66
faluco@227
    67
	*buf_p = buf;
faluco@227
    68
}
faluco@227
    69
faluco@227
    70
void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec)
faluco@227
    71
{
faluco@227
    72
	char text[32];
faluco@227
    73
	int digits;
faluco@227
    74
	double signedVal;
faluco@227
    75
	char *buf;
faluco@227
    76
	int val;
faluco@227
    77
faluco@227
    78
	// get the sign
faluco@227
    79
	signedVal = fval;
faluco@227
    80
	if (fval < 0)
faluco@227
    81
	{
faluco@227
    82
		fval = -fval;
faluco@227
    83
	}
faluco@227
    84
faluco@227
    85
	// write the float number
faluco@227
    86
	digits = 0;
faluco@227
    87
	val = (int)fval;
faluco@227
    88
	do
faluco@227
    89
	{
faluco@227
    90
		text[digits++] = '0' + val % 10;
faluco@227
    91
		val /= 10;
faluco@227
    92
	} while (val);
faluco@227
    93
faluco@227
    94
	if (signedVal < 0)
faluco@227
    95
	{
faluco@227
    96
		text[digits++] = '-';
faluco@227
    97
	}
faluco@227
    98
faluco@227
    99
	buf = *buf_p;
faluco@227
   100
faluco@227
   101
	while ((digits < width) && maxlen)
faluco@227
   102
	{
faluco@227
   103
		*buf++ = ' ';
faluco@227
   104
		width--;
faluco@227
   105
		maxlen--;
faluco@227
   106
	}
faluco@227
   107
faluco@227
   108
	while ((digits--) && maxlen)
faluco@227
   109
	{
faluco@227
   110
		*buf++ = text[digits];
faluco@227
   111
		maxlen--;
faluco@227
   112
	}
faluco@227
   113
faluco@227
   114
	*buf_p = buf;
faluco@227
   115
faluco@227
   116
	if (prec < 0)
faluco@227
   117
	{
faluco@227
   118
		prec = 6;
faluco@227
   119
	}
faluco@227
   120
	// write the fraction
faluco@227
   121
	digits = 0;
faluco@227
   122
	while (digits < prec)
faluco@227
   123
	{
faluco@227
   124
		fval -= (int)fval;
faluco@227
   125
		fval *= 10.0;
faluco@227
   126
		val = (int)fval;
faluco@227
   127
		text[digits++] = '0' + val % 10;
faluco@227
   128
	}
faluco@227
   129
faluco@227
   130
	if ((digits > 0) && maxlen)
faluco@227
   131
	{
faluco@227
   132
		buf = *buf_p;
faluco@227
   133
		*buf++ = '.';
faluco@227
   134
		maxlen--;
faluco@227
   135
		for (prec = 0; maxlen && (prec < digits); prec++)
faluco@227
   136
		{
faluco@227
   137
			*buf++ = text[prec];
faluco@227
   138
			maxlen--;
faluco@227
   139
		}
faluco@227
   140
		*buf_p = buf;
faluco@227
   141
	}
faluco@227
   142
}
faluco@227
   143
faluco@227
   144
void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
faluco@227
   145
{
faluco@227
   146
	char text[32];
faluco@227
   147
	int digits;
faluco@227
   148
	char *buf;
faluco@227
   149
faluco@227
   150
	digits = 0;
faluco@227
   151
	do
faluco@227
   152
	{
faluco@227
   153
		text[digits++] = '0' + val % 10;
faluco@227
   154
		val /= 10;
faluco@227
   155
	} while (val);
faluco@227
   156
faluco@227
   157
	buf = *buf_p;
faluco@227
   158
faluco@227
   159
	if (!(flags & LADJUST))
faluco@227
   160
	{
faluco@227
   161
		while (digits < width && maxlen)
faluco@227
   162
		{
faluco@227
   163
			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
faluco@227
   164
			width--;
faluco@227
   165
			maxlen--;
faluco@227
   166
		}
faluco@227
   167
	}
faluco@227
   168
faluco@227
   169
	while (digits-- && maxlen)
faluco@227
   170
	{
faluco@227
   171
		*buf++ = text[digits];
faluco@227
   172
		width--;
faluco@227
   173
		maxlen--;
faluco@227
   174
	}
faluco@227
   175
faluco@227
   176
	if (flags & LADJUST)
faluco@227
   177
	{
faluco@227
   178
		while (width-- && maxlen)
faluco@227
   179
		{
faluco@227
   180
			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
faluco@227
   181
			maxlen--;
faluco@227
   182
		}
faluco@227
   183
	}
faluco@227
   184
faluco@227
   185
	*buf_p = buf;
faluco@227
   186
}
faluco@227
   187
faluco@227
   188
void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
faluco@227
   189
{
faluco@227
   190
	char text[32];
faluco@227
   191
	int digits;
faluco@227
   192
	int signedVal;
faluco@227
   193
	char *buf;
faluco@227
   194
	unsigned int unsignedVal;
faluco@227
   195
faluco@227
   196
	digits = 0;
faluco@227
   197
	signedVal = val;
faluco@227
   198
	if (val < 0)
faluco@227
   199
	{
faluco@227
   200
		/* we want the unsigned version */
faluco@227
   201
		unsignedVal = abs(val);
faluco@227
   202
	} else {
faluco@227
   203
		unsignedVal = val;
faluco@227
   204
	}
faluco@227
   205
	do
faluco@227
   206
	{
faluco@227
   207
		text[digits++] = '0' + unsignedVal % 10;
faluco@227
   208
		unsignedVal /= 10;
faluco@227
   209
	} while (unsignedVal);
faluco@227
   210
faluco@227
   211
	if (signedVal < 0)
faluco@227
   212
	{
faluco@227
   213
		text[digits++] = '-';
faluco@227
   214
	}
faluco@227
   215
faluco@227
   216
	buf = *buf_p;
faluco@227
   217
faluco@227
   218
	if (!(flags & LADJUST))
faluco@227
   219
	{
faluco@227
   220
		while ((digits < width) && maxlen)
faluco@227
   221
		{
faluco@227
   222
			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
faluco@227
   223
			width--;
faluco@227
   224
			maxlen--;
faluco@227
   225
		}
faluco@227
   226
	}
faluco@227
   227
faluco@227
   228
	while (digits-- && maxlen)
faluco@227
   229
	{
faluco@227
   230
		*buf++ = text[digits];
faluco@227
   231
		width--;
faluco@227
   232
		maxlen--;
faluco@227
   233
	}
faluco@227
   234
faluco@227
   235
	if (flags & LADJUST)
faluco@227
   236
	{
faluco@227
   237
		while (width-- && maxlen)
faluco@227
   238
		{
faluco@227
   239
			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
faluco@227
   240
			maxlen--;
faluco@227
   241
		}
faluco@227
   242
	}
faluco@227
   243
faluco@227
   244
	*buf_p = buf;
faluco@227
   245
}
faluco@227
   246
dvander@276
   247
size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args)
dvander@276
   248
{
dvander@276
   249
	if (!buffer || !maxlen)
dvander@276
   250
	{
dvander@276
   251
		return 0;
dvander@276
   252
	}
dvander@276
   253
dvander@276
   254
	int arg = 0;
dvander@276
   255
	char *buf_p;
dvander@276
   256
	char ch;
dvander@276
   257
	int flags;
dvander@276
   258
	int width;
dvander@276
   259
	int prec;
dvander@276
   260
	int n;
dvander@276
   261
	char sign;
dvander@276
   262
	const char *fmt;
dvander@276
   263
	size_t llen = maxlen - 1;
dvander@276
   264
dvander@276
   265
	buf_p = buffer;
dvander@276
   266
	fmt = format;
dvander@276
   267
dvander@276
   268
	while (true)
dvander@276
   269
	{
dvander@276
   270
		// run through the format string until we hit a '%' or '\0'
dvander@276
   271
		for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
dvander@276
   272
		{
dvander@276
   273
			*buf_p++ = ch;
dvander@276
   274
			llen--;
dvander@276
   275
		}
dvander@276
   276
		if ((ch == '\0') || (llen <= 0))
dvander@276
   277
		{
dvander@276
   278
			goto done;
dvander@276
   279
		}
dvander@276
   280
dvander@276
   281
		// skip over the '%'
dvander@276
   282
		fmt++;
dvander@276
   283
dvander@276
   284
		// reset formatting state
dvander@276
   285
		flags = 0;
dvander@276
   286
		width = 0;
dvander@276
   287
		prec = -1;
dvander@276
   288
		sign = '\0';
dvander@276
   289
dvander@276
   290
rflag:
dvander@276
   291
		ch = *fmt++;
dvander@276
   292
reswitch:
dvander@276
   293
		switch(ch)
dvander@276
   294
		{
dvander@276
   295
		case '-':
dvander@276
   296
			{
dvander@276
   297
				flags |= LADJUST;
dvander@276
   298
				goto rflag;
dvander@276
   299
			}
dvander@276
   300
		case '.':
dvander@276
   301
			{
dvander@276
   302
				n = 0;
dvander@276
   303
				while(is_digit((ch = *fmt++)))
dvander@276
   304
				{
dvander@276
   305
					n = 10 * n + (ch - '0');
dvander@276
   306
				}
dvander@276
   307
				prec = (n < 0) ? -1 : n;
dvander@276
   308
				goto reswitch;
dvander@276
   309
			}
dvander@276
   310
		case '0':
dvander@276
   311
			{
dvander@276
   312
				flags |= ZEROPAD;
dvander@276
   313
				goto rflag;
dvander@276
   314
			}
dvander@276
   315
		case '1':
dvander@276
   316
		case '2':
dvander@276
   317
		case '3':
dvander@276
   318
		case '4':
dvander@276
   319
		case '5':
dvander@276
   320
		case '6':
dvander@276
   321
		case '7':
dvander@276
   322
		case '8':
dvander@276
   323
		case '9':
dvander@276
   324
			{
dvander@276
   325
				n = 0;
dvander@276
   326
				do
dvander@276
   327
				{
dvander@276
   328
					n = 10 * n + (ch - '0');
dvander@276
   329
					ch = *fmt++;
dvander@276
   330
				} while(is_digit(ch));
dvander@276
   331
				width = n;
dvander@276
   332
				goto reswitch;
dvander@276
   333
			}
dvander@276
   334
		case 'c':
dvander@276
   335
			{
dvander@276
   336
				if (!llen)
dvander@276
   337
				{
dvander@276
   338
					goto done;
dvander@276
   339
				}
dvander@276
   340
				char *c = (char *)args[arg];
dvander@276
   341
				*buf_p++ = *c;
dvander@276
   342
				llen--;
dvander@276
   343
				arg++;
dvander@276
   344
				break;
dvander@276
   345
			}
dvander@276
   346
		case 'd':
dvander@276
   347
		case 'i':
dvander@276
   348
			{
dvander@276
   349
				int *value = (int *)args[arg];
dvander@276
   350
				AddInt(&buf_p, llen, *value, width, flags);
dvander@276
   351
				arg++;
dvander@276
   352
				break;
dvander@276
   353
			}
dvander@276
   354
		case 'u':
dvander@276
   355
			{
dvander@276
   356
				unsigned int *value = (unsigned int *)args[arg];
dvander@276
   357
				AddUInt(&buf_p, llen, *value, width, flags);
dvander@276
   358
				arg++;
dvander@276
   359
				break;
dvander@276
   360
			}
dvander@276
   361
		case 'f':
dvander@276
   362
			{
dvander@276
   363
				float *value = (float *)args[arg];
dvander@276
   364
				AddFloat(&buf_p, llen, *value, width, prec);
dvander@276
   365
				arg++;
dvander@276
   366
				break;
dvander@276
   367
			}
dvander@276
   368
		case 's':
dvander@276
   369
			{
dvander@276
   370
				const char *str = (const char *)args[arg];
dvander@276
   371
				AddString(&buf_p, llen, str, width, prec);
dvander@276
   372
				arg++;
dvander@276
   373
				break;
dvander@276
   374
			}
dvander@276
   375
		case '%':
dvander@276
   376
			{
dvander@276
   377
				if (!llen)
dvander@276
   378
				{
dvander@276
   379
					goto done;
dvander@276
   380
				}
dvander@276
   381
				*buf_p++ = ch;
dvander@276
   382
				llen--;
dvander@276
   383
				break;
dvander@276
   384
			}
dvander@276
   385
		case '\0':
dvander@276
   386
			{
dvander@276
   387
				if (!llen)
dvander@276
   388
				{
dvander@276
   389
					goto done;
dvander@276
   390
				}
dvander@276
   391
				*buf_p++ = '%';
dvander@276
   392
				llen--;
dvander@276
   393
				goto done;
dvander@276
   394
			}
dvander@276
   395
		default:
dvander@276
   396
			{
dvander@276
   397
				if (!llen)
dvander@276
   398
				{
dvander@276
   399
					goto done;
dvander@276
   400
				}
dvander@276
   401
				*buf_p++ = ch;
dvander@276
   402
				llen--;
dvander@276
   403
				break;
dvander@276
   404
			}
dvander@276
   405
		}
dvander@276
   406
	}
dvander@276
   407
dvander@276
   408
done:
dvander@276
   409
	*buf_p = '\0';
dvander@276
   410
dvander@276
   411
	return (maxlen - llen - 1);
dvander@276
   412
}
dvander@276
   413
faluco@227
   414
size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
faluco@227
   415
{
dvander@276
   416
	if (!buffer || !maxlen)
dvander@276
   417
	{
dvander@276
   418
		return 0;
dvander@276
   419
	}
dvander@276
   420
faluco@227
   421
	int arg;
faluco@288
   422
	int args = params[0];
faluco@227
   423
	char *buf_p;
faluco@227
   424
	char ch;
faluco@227
   425
	int flags;
faluco@227
   426
	int width;
faluco@227
   427
	int prec;
faluco@227
   428
	int n;
faluco@227
   429
	char sign;
faluco@227
   430
	const char *fmt;
faluco@230
   431
	size_t llen = maxlen - 1;
faluco@227
   432
faluco@227
   433
	buf_p = buffer;
faluco@227
   434
	arg = *param;
faluco@227
   435
	fmt = format;
faluco@227
   436
faluco@227
   437
	while (true)
faluco@227
   438
	{
faluco@227
   439
		// run through the format string until we hit a '%' or '\0'
faluco@227
   440
		for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
faluco@227
   441
		{
faluco@227
   442
			*buf_p++ = ch;
faluco@227
   443
			llen--;
faluco@227
   444
		}
faluco@227
   445
		if ((ch == '\0') || (llen <= 0))
faluco@227
   446
		{
faluco@227
   447
			goto done;
faluco@227
   448
		}
faluco@227
   449
faluco@227
   450
		// skip over the '%'
faluco@227
   451
		fmt++;
faluco@227
   452
faluco@227
   453
		// reset formatting state
faluco@227
   454
		flags = 0;
faluco@227
   455
		width = 0;
faluco@227
   456
		prec = -1;
faluco@227
   457
		sign = '\0';
faluco@227
   458
faluco@227
   459
rflag:
faluco@227
   460
		ch = *fmt++;
faluco@227
   461
reswitch:
faluco@227
   462
		switch(ch)
faluco@227
   463
		{
faluco@227
   464
		case '-':
faluco@227
   465
			{
faluco@227
   466
				flags |= LADJUST;
faluco@227
   467
				goto rflag;
faluco@227
   468
			}
faluco@227
   469
		case '.':
faluco@227
   470
			{
faluco@227
   471
				n = 0;
faluco@227
   472
				while(is_digit((ch = *fmt++)))
faluco@227
   473
				{
faluco@227
   474
					n = 10 * n + (ch - '0');
faluco@227
   475
				}
faluco@227
   476
				prec = (n < 0) ? -1 : n;
faluco@227
   477
				goto reswitch;
faluco@227
   478
			}
faluco@227
   479
		case '0':
faluco@227
   480
			{
faluco@227
   481
				flags |= ZEROPAD;
faluco@227
   482
				goto rflag;
faluco@227
   483
			}
faluco@227
   484
		case '1':
faluco@227
   485
		case '2':
faluco@227
   486
		case '3':
faluco@227
   487
		case '4':
faluco@227
   488
		case '5':
faluco@227
   489
		case '6':
faluco@227
   490
		case '7':
faluco@227
   491
		case '8':
faluco@227
   492
		case '9':
faluco@227
   493
			{
faluco@227
   494
				n = 0;
faluco@227
   495
				do
faluco@227
   496
				{
faluco@227
   497
					n = 10 * n + (ch - '0');
faluco@227
   498
					ch = *fmt++;
faluco@227
   499
				} while(is_digit(ch));
faluco@227
   500
				width = n;
faluco@227
   501
				goto reswitch;
faluco@227
   502
			}
faluco@227
   503
		case 'c':
faluco@227
   504
			{
faluco@227
   505
				CHECK_ARGS(0);
faluco@230
   506
				if (!llen)
faluco@227
   507
				{
faluco@227
   508
					goto done;
faluco@227
   509
				}
faluco@227
   510
				char *c;
faluco@227
   511
				pCtx->LocalToString(params[arg], &c);
faluco@227
   512
				*buf_p++ = *c;
faluco@227
   513
				llen--;
faluco@227
   514
				arg++;
faluco@227
   515
				break;
faluco@227
   516
			}
faluco@227
   517
		case 'd':
faluco@227
   518
		case 'i':
faluco@227
   519
			{
faluco@227
   520
				CHECK_ARGS(0);
faluco@227
   521
				cell_t *value;
faluco@227
   522
				pCtx->LocalToPhysAddr(params[arg], &value);
faluco@227
   523
				AddInt(&buf_p, llen, static_cast<int>(*value), width, flags);
faluco@227
   524
				arg++;
faluco@227
   525
				break;
faluco@227
   526
			}
faluco@227
   527
		case 'u':
faluco@227
   528
			{
faluco@227
   529
				CHECK_ARGS(0);
faluco@227
   530
				cell_t *value;
faluco@227
   531
				pCtx->LocalToPhysAddr(params[arg], &value);
faluco@227
   532
				AddUInt(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
faluco@227
   533
				arg++;
faluco@227
   534
				break;
faluco@227
   535
			}
faluco@227
   536
		case 'f':
faluco@227
   537
			{
faluco@227
   538
				CHECK_ARGS(0);
faluco@227
   539
				cell_t *value;
faluco@227
   540
				pCtx->LocalToPhysAddr(params[arg], &value);
dvander@233
   541
				AddFloat(&buf_p, llen, sp_ctof(*value), width, prec);
faluco@227
   542
				arg++;
faluco@227
   543
				break;
faluco@227
   544
			}
faluco@227
   545
		case 's':
faluco@227
   546
			{
faluco@227
   547
				CHECK_ARGS(0);
faluco@227
   548
				char *str;
faluco@227
   549
				pCtx->LocalToString(params[arg], &str);
faluco@227
   550
				AddString(&buf_p, llen, str, width, prec);
faluco@227
   551
				arg++;
faluco@227
   552
				break;
faluco@227
   553
			}
faluco@227
   554
		case '%':
faluco@227
   555
			{
faluco@230
   556
				if (!llen)
faluco@227
   557
				{
faluco@227
   558
					goto done;
faluco@227
   559
				}
faluco@227
   560
				*buf_p++ = ch;
faluco@227
   561
				llen--;
faluco@227
   562
				break;
faluco@227
   563
			}
faluco@227
   564
		case '\0':
faluco@227
   565
			{
faluco@230
   566
				if (!llen)
faluco@227
   567
				{
faluco@227
   568
					goto done;
faluco@227
   569
				}
faluco@227
   570
				*buf_p++ = '%';
faluco@227
   571
				llen--;
faluco@227
   572
				goto done;
faluco@227
   573
			}
faluco@227
   574
		default:
faluco@227
   575
			{
faluco@230
   576
				if (!llen)
faluco@227
   577
				{
faluco@227
   578
					goto done;
faluco@227
   579
				}
faluco@227
   580
				*buf_p++ = ch;
faluco@227
   581
				llen--;
faluco@227
   582
				break;
faluco@227
   583
			}
faluco@227
   584
		}
faluco@227
   585
	}
faluco@227
   586
faluco@227
   587
done:
faluco@227
   588
	*buf_p = '\0';
faluco@227
   589
	*param = arg;
faluco@236
   590
	return (maxlen - llen - 1);
faluco@227
   591
}
faluco@230
   592
faluco@230
   593
const char *stristr(const char *str, const char *substr)
faluco@230
   594
{
faluco@230
   595
	if (!*substr)
faluco@230
   596
	{
faluco@230
   597
		return ((char *)str);
faluco@230
   598
	}
faluco@230
   599
faluco@230
   600
	char *needle = (char *)substr;
faluco@230
   601
	char *prevloc = (char *)str;
faluco@230
   602
	char *haystack = (char *)str;
faluco@230
   603
faluco@230
   604
	while (*haystack)
faluco@230
   605
	{
faluco@230
   606
		if (tolower(*haystack) == tolower(*needle))
faluco@230
   607
		{
faluco@230
   608
			haystack++;
faluco@230
   609
			if (!*++needle)
faluco@230
   610
			{
faluco@230
   611
				return prevloc;
faluco@230
   612
			}
faluco@230
   613
		} else {
faluco@230
   614
			haystack = ++prevloc;
faluco@230
   615
			needle = (char *)substr;
faluco@230
   616
		}
faluco@230
   617
	}
faluco@230
   618
faluco@230
   619
	return NULL;
faluco@230
   620
}
faluco@230
   621
dvander@233
   622
unsigned int strncopy(char *dest, const char *src, size_t count)
faluco@230
   623
{
faluco@230
   624
	if (!count)
faluco@230
   625
	{
faluco@230
   626
		return 0;
faluco@230
   627
	}
faluco@230
   628
faluco@230
   629
	char *start = dest;
faluco@230
   630
	while ((*src) && (--count))
faluco@230
   631
	{
faluco@230
   632
		*dest++ = *src++;
faluco@230
   633
	}
faluco@230
   634
	*dest = '\0';
faluco@230
   635
faluco@230
   636
	return (dest - start);
faluco@230
   637
}
faluco@274
   638
faluco@274
   639
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
faluco@274
   640
{
faluco@274
   641
	va_list ap;
faluco@274
   642
	va_start(ap, fmt);
faluco@274
   643
	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
faluco@274
   644
	va_end(ap);
faluco@274
   645
faluco@274
   646
	return (len >= maxlength) ? (maxlength - 1) : len;
faluco@274
   647
}