core/sm_stringutil.cpp
branchsourcemod-1.1.0
changeset 2283 03a67e41afbc
parent 1951 c7b4237fff50
child 2287 017a725c9d17
     1.1 --- a/core/sm_stringutil.cpp	Fri Mar 28 06:21:34 2008 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1277 +0,0 @@
     1.4 -/**
     1.5 - * vim: set ts=4 :
     1.6 - * =============================================================================
     1.7 - * SourceMod
     1.8 - * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     1.9 - * =============================================================================
    1.10 - *
    1.11 - * This program is free software; you can redistribute it and/or modify it under
    1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
    1.13 - * Free Software Foundation.
    1.14 - * 
    1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
    1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 - * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    1.18 - * details.
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License along with
    1.21 - * this program.  If not, see <http://www.gnu.org/licenses/>.
    1.22 - *
    1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
    1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
    1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    1.26 - * by the Valve Corporation.  You must obey the GNU General Public License in
    1.27 - * all respects for all other code used.  Additionally, AlliedModders LLC grants
    1.28 - * this exception to all derivative works.  AlliedModders LLC defines further
    1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    1.30 - * or <http://www.sourcemod.net/license.php>.
    1.31 - *
    1.32 - * Version: $Id$
    1.33 - */
    1.34 -
    1.35 -#include <stdlib.h>
    1.36 -#include <ctype.h>
    1.37 -#include <stdarg.h>
    1.38 -#include "sm_stringutil.h"
    1.39 -#include "Logger.h"
    1.40 -#include "PluginSys.h"
    1.41 -#include "Translator.h"
    1.42 -#include "PlayerManager.h"
    1.43 -
    1.44 -#define LADJUST			0x00000004		/* left adjustment */
    1.45 -#define ZEROPAD			0x00000080		/* zero (as opposed to blank) pad */
    1.46 -#define UPPERDIGITS		0x00000200		/* make alpha digits uppercase */
    1.47 -#define to_digit(c)		((c) - '0')
    1.48 -#define is_digit(c)		((unsigned)to_digit(c) <= 9)
    1.49 -
    1.50 -#define CHECK_ARGS(x) \
    1.51 -	if ((arg+x) > args) { \
    1.52 -		pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "String formatted incorrectly - parameter %d (total %d)", arg, args); \
    1.53 -		return 0; \
    1.54 -	}
    1.55 -
    1.56 -size_t CorePlayerTranslate(int client, char *buffer, size_t maxlength, const char *phrase, void **params)
    1.57 -{
    1.58 -	Translation pTrans;
    1.59 -	TransError err;
    1.60 -
    1.61 -	err = g_pCorePhrases->GetTranslation(phrase, g_Translator.GetClientLanguage(client), &pTrans);
    1.62 -	if (err != Trans_Okay)
    1.63 -	{
    1.64 -		err = g_pCorePhrases->GetTranslation(phrase, g_Translator.GetServerLanguage(), &pTrans);
    1.65 -		if (err != Trans_Okay && g_Translator.GetServerLanguage() != CORELANG_ENGLISH)
    1.66 -		{
    1.67 -			err = g_pCorePhrases->GetTranslation(phrase, CORELANG_ENGLISH, &pTrans);
    1.68 -		}
    1.69 -	}
    1.70 -
    1.71 -	if (err != Trans_Okay)
    1.72 -	{
    1.73 -		return UTIL_Format(buffer, maxlength, "%s", phrase);
    1.74 -	}
    1.75 -
    1.76 -	return g_Translator.Translate(buffer, maxlength, params, &pTrans);
    1.77 -}
    1.78 -
    1.79 -inline bool TryTranslation(CPlugin *pl, const char *key, unsigned int langid, unsigned int langcount, Translation *pTrans)
    1.80 -{
    1.81 -	TransError err = Trans_BadLanguage;
    1.82 -	CPhraseFile *phrfl;
    1.83 -
    1.84 -	for (size_t i=0; i<langcount && err!=Trans_Okay; i++)
    1.85 -	{
    1.86 -		phrfl = g_Translator.GetFileByIndex(pl->GetLangFileByIndex(i));
    1.87 -		err = phrfl->GetTranslation(key, langid, pTrans);
    1.88 -	}
    1.89 -
    1.90 -	return (err == Trans_Okay) ? true : false;
    1.91 -}
    1.92 -
    1.93 -inline void ReorderTranslationParams(const Translation *pTrans, cell_t *params)
    1.94 -{
    1.95 -	cell_t new_params[MAX_TRANSLATE_PARAMS];
    1.96 -	for (unsigned int i = 0; i < pTrans->fmt_count; i++)
    1.97 -	{
    1.98 -		new_params[i] = params[pTrans->fmt_order[i]];
    1.99 -	}
   1.100 -	memcpy(params, new_params, pTrans->fmt_count * sizeof(cell_t));
   1.101 -}
   1.102 -
   1.103 -size_t Translate(char *buffer,
   1.104 -				 size_t maxlen,
   1.105 -				 IPluginContext *pCtx,
   1.106 -				 const char *key,
   1.107 -				 cell_t target,
   1.108 -				 const cell_t *params,
   1.109 -				 int *arg,
   1.110 -				 bool *error)
   1.111 -{
   1.112 -	unsigned int langid;
   1.113 -	*error = false;
   1.114 -	Translation pTrans;
   1.115 -	CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext());
   1.116 -	size_t langcount = pl->GetLangFileCount();
   1.117 -	unsigned int max_params = 0;
   1.118 -
   1.119 -try_serverlang:
   1.120 -	if (target == LANG_SERVER)
   1.121 -	{
   1.122 -		langid = g_Translator.GetServerLanguage();
   1.123 - 	}
   1.124 -	else if ((target >= 1) && (target <= g_Players.GetMaxClients()))
   1.125 -	{
   1.126 -		langid = g_Translator.GetClientLanguage(target);
   1.127 -	}
   1.128 -	else
   1.129 -	{
   1.130 -		pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target);
   1.131 -		goto error_out;
   1.132 -	}
   1.133 -
   1.134 -	if (!TryTranslation(pl, key, langid, langcount, &pTrans))
   1.135 -	{
   1.136 -		if (target != LANG_SERVER && langid != g_Translator.GetServerLanguage())
   1.137 -		{
   1.138 -			target = LANG_SERVER;
   1.139 -			goto try_serverlang;
   1.140 -		}
   1.141 -		else if (langid != LANGUAGE_ENGLISH)
   1.142 -		{
   1.143 -			if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans))
   1.144 -			{
   1.145 -				pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
   1.146 -				goto error_out;
   1.147 -			}
   1.148 -		}
   1.149 -		else
   1.150 -		{
   1.151 -			pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
   1.152 -			goto error_out;
   1.153 -		}
   1.154 -	}
   1.155 -
   1.156 -	max_params = pTrans.fmt_count;
   1.157 -
   1.158 -	if (max_params)
   1.159 -	{
   1.160 -		cell_t new_params[MAX_TRANSLATE_PARAMS];
   1.161 -
   1.162 -		/* Check if we're going to over the limit */
   1.163 -		if ((*arg) + (max_params - 1) > (size_t)params[0])
   1.164 -		{
   1.165 -			pCtx->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, 
   1.166 -				"Translation string formatted incorrectly - missing at least %d parameters", 
   1.167 -				((*arg + (max_params - 1)) - params[0])
   1.168 -				);
   1.169 -			goto error_out;
   1.170 -		}
   1.171 -
   1.172 -		/* If we need to re-order the parameters, do so with a temporary array.
   1.173 -		 * Otherwise, we could run into trouble with continual formats, a la ShowActivity().
   1.174 -		 */
   1.175 -		memcpy(new_params, params, sizeof(cell_t) * (params[0] + 1));
   1.176 -		ReorderTranslationParams(&pTrans, &new_params[*arg]);
   1.177 -
   1.178 -		return atcprintf(buffer, maxlen, pTrans.szPhrase, pCtx, new_params, arg);
   1.179 -	}
   1.180 -	else
   1.181 -	{
   1.182 -		return atcprintf(buffer, maxlen, pTrans.szPhrase, pCtx, params, arg);
   1.183 -	}
   1.184 -	
   1.185 -error_out:
   1.186 -	*error = true;
   1.187 -	return 0;
   1.188 -}
   1.189 -
   1.190 -void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
   1.191 -{
   1.192 -	int size = 0;
   1.193 -	char *buf;
   1.194 -	static char nlstr[] = {'(','n','u','l','l',')','\0'};
   1.195 -
   1.196 -	buf = *buf_p;
   1.197 -
   1.198 -	if (string == NULL)
   1.199 -	{
   1.200 -		string = nlstr;
   1.201 -		prec = -1;
   1.202 -	}
   1.203 -
   1.204 -	if (prec >= 0)
   1.205 -	{
   1.206 -		for (size = 0; size < prec; size++) 
   1.207 -		{
   1.208 -			if (string[size] == '\0')
   1.209 -			{
   1.210 -				break;
   1.211 -			}
   1.212 -		}
   1.213 -	}
   1.214 -	else
   1.215 -	{
   1.216 -		while (string[size++]);
   1.217 -		size--;
   1.218 -	}
   1.219 -
   1.220 -	if (size > (int)maxlen)
   1.221 -	{
   1.222 -		size = maxlen;
   1.223 -	}
   1.224 -
   1.225 -	maxlen -= size;
   1.226 -	width -= size;
   1.227 -
   1.228 -	while (size--)
   1.229 -	{
   1.230 -		*buf++ = *string++;
   1.231 -	}
   1.232 -
   1.233 -	while ((width-- > 0) && maxlen)
   1.234 -	{
   1.235 -		*buf++ = ' ';
   1.236 -		maxlen--;
   1.237 -	}
   1.238 -
   1.239 -	*buf_p = buf;
   1.240 -}
   1.241 -
   1.242 -void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec, int flags)
   1.243 -{
   1.244 -	int digits;					// non-fraction part digits
   1.245 -	double tmp;					// temporary
   1.246 -	char *buf = *buf_p;			// output buffer pointer
   1.247 -	int val;					// temporary
   1.248 -	int sign = 0;				// 0: positive, 1: negative
   1.249 -	int fieldlength;			// for padding
   1.250 -	int significant_digits = 0;	// number of significant digits written
   1.251 -	const int MAX_SIGNIFICANT_DIGITS = 16;
   1.252 -
   1.253 -	// default precision
   1.254 -	if (prec < 0)
   1.255 -	{
   1.256 -		prec = 6;
   1.257 -	}
   1.258 -
   1.259 -	// get the sign
   1.260 -	if (fval < 0)
   1.261 -	{
   1.262 -		fval = -fval;
   1.263 -		sign = 1;
   1.264 -	}
   1.265 -
   1.266 -	// compute whole-part digits count
   1.267 -	digits = (int)log10(fval) + 1;
   1.268 -
   1.269 -	// Only print 0.something if 0 < fval < 1
   1.270 -	if (digits < 1)
   1.271 -	{
   1.272 -		digits = 1;
   1.273 -	}
   1.274 -
   1.275 -	// compute the field length
   1.276 -	fieldlength = digits + prec + ((prec > 0) ? 1 : 0) + sign;
   1.277 -
   1.278 -	// minus sign BEFORE left padding if padding with zeros
   1.279 -	if (sign && maxlen && (flags & ZEROPAD))
   1.280 -	{
   1.281 -		*buf++ = '-';
   1.282 -		maxlen--;
   1.283 -	}
   1.284 -
   1.285 -	// right justify if required
   1.286 -	if ((flags & LADJUST) == 0)
   1.287 -	{
   1.288 -		while ((fieldlength < width) && maxlen)
   1.289 -		{
   1.290 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.291 -			width--;
   1.292 -			maxlen--;
   1.293 -		}
   1.294 -	}
   1.295 -
   1.296 -	// minus sign AFTER left padding if padding with spaces
   1.297 -	if (sign && maxlen && !(flags & ZEROPAD))
   1.298 -	{
   1.299 -		*buf++ = '-';
   1.300 -		maxlen--;
   1.301 -	}
   1.302 -
   1.303 -	// write the whole part
   1.304 -	tmp = pow(10.0, digits-1);
   1.305 -	while ((digits--) && maxlen)
   1.306 -	{
   1.307 -		if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
   1.308 -		{
   1.309 -			*buf++ = '0';
   1.310 -		}
   1.311 -		else
   1.312 -		{
   1.313 -			val = (int)(fval / tmp);
   1.314 -			*buf++ = '0' + val;
   1.315 -			fval -= val * tmp;
   1.316 -			tmp *= 0.1;
   1.317 -		}
   1.318 -		maxlen--;
   1.319 -	}
   1.320 -
   1.321 -	// write the fraction part
   1.322 -	if (maxlen)
   1.323 -	{
   1.324 -		*buf++ = '.';
   1.325 -		maxlen--;
   1.326 -	}
   1.327 -
   1.328 -	tmp = pow(10.0, prec);
   1.329 -
   1.330 -	fval *= tmp;
   1.331 -	while (prec-- && maxlen)
   1.332 -	{
   1.333 -		if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
   1.334 -		{
   1.335 -			*buf++ = '0';
   1.336 -		}
   1.337 -		else
   1.338 -		{
   1.339 -			tmp *= 0.1;
   1.340 -			val = (int)(fval / tmp);
   1.341 -			*buf++ = '0' + val;
   1.342 -			fval -= val * tmp;
   1.343 -		}
   1.344 -		maxlen--;
   1.345 -	}
   1.346 -
   1.347 -	// left justify if required
   1.348 -	if (flags & LADJUST)
   1.349 -	{
   1.350 -		while ((fieldlength < width) && maxlen)
   1.351 -		{
   1.352 -			// right-padding only with spaces, ZEROPAD is ignored
   1.353 -			*buf++ = ' ';
   1.354 -			width--;
   1.355 -			maxlen--;
   1.356 -		}
   1.357 -	}
   1.358 -
   1.359 -	// update parent's buffer pointer
   1.360 -	*buf_p = buf;
   1.361 -}
   1.362 -
   1.363 -void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
   1.364 -{
   1.365 -	char text[32];
   1.366 -	int digits;
   1.367 -	char *buf;
   1.368 -
   1.369 -	digits = 0;
   1.370 -	do
   1.371 -	{
   1.372 -		text[digits++] = '0' + val % 10;
   1.373 -		val /= 10;
   1.374 -	} while (val);
   1.375 -
   1.376 -	buf = *buf_p;
   1.377 -
   1.378 -	if (!(flags & LADJUST))
   1.379 -	{
   1.380 -		while (digits < width && maxlen)
   1.381 -		{
   1.382 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.383 -			width--;
   1.384 -			maxlen--;
   1.385 -		}
   1.386 -	}
   1.387 -
   1.388 -	while (digits-- && maxlen)
   1.389 -	{
   1.390 -		*buf++ = text[digits];
   1.391 -		width--;
   1.392 -		maxlen--;
   1.393 -	}
   1.394 -
   1.395 -	if (flags & LADJUST)
   1.396 -	{
   1.397 -		while (width-- && maxlen)
   1.398 -		{
   1.399 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.400 -			maxlen--;
   1.401 -		}
   1.402 -	}
   1.403 -
   1.404 -	*buf_p = buf;
   1.405 -}
   1.406 -
   1.407 -void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
   1.408 -{
   1.409 -	char text[32];
   1.410 -	int digits;
   1.411 -	int signedVal;
   1.412 -	char *buf;
   1.413 -	unsigned int unsignedVal;
   1.414 -
   1.415 -	digits = 0;
   1.416 -	signedVal = val;
   1.417 -	if (val < 0)
   1.418 -	{
   1.419 -		/* we want the unsigned version */
   1.420 -		unsignedVal = abs(val);
   1.421 -	}
   1.422 -	else
   1.423 -	{
   1.424 -		unsignedVal = val;
   1.425 -	}
   1.426 -
   1.427 -	do
   1.428 -	{
   1.429 -		text[digits++] = '0' + unsignedVal % 10;
   1.430 -		unsignedVal /= 10;
   1.431 -	} while (unsignedVal);
   1.432 -
   1.433 -	if (signedVal < 0)
   1.434 -	{
   1.435 -		text[digits++] = '-';
   1.436 -	}
   1.437 -
   1.438 -	buf = *buf_p;
   1.439 -
   1.440 -	if (!(flags & LADJUST))
   1.441 -	{
   1.442 -		while ((digits < width) && maxlen)
   1.443 -		{
   1.444 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.445 -			width--;
   1.446 -			maxlen--;
   1.447 -		}
   1.448 -	}
   1.449 -
   1.450 -	while (digits-- && maxlen)
   1.451 -	{
   1.452 -		*buf++ = text[digits];
   1.453 -		width--;
   1.454 -		maxlen--;
   1.455 -	}
   1.456 -
   1.457 -	if (flags & LADJUST)
   1.458 -	{
   1.459 -		while (width-- && maxlen)
   1.460 -		{
   1.461 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.462 -			maxlen--;
   1.463 -		}
   1.464 -	}
   1.465 -
   1.466 -	*buf_p = buf;
   1.467 -}
   1.468 -
   1.469 -void AddHex(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
   1.470 -{
   1.471 -	char text[32];
   1.472 -	int digits;
   1.473 -	char *buf;
   1.474 -	char digit;
   1.475 -	int hexadjust;
   1.476 -
   1.477 -	if (flags & UPPERDIGITS)
   1.478 -	{
   1.479 -		hexadjust = 'A' - '9' - 1;
   1.480 -	}
   1.481 -	else
   1.482 -	{
   1.483 -		hexadjust = 'a' - '9' - 1;
   1.484 -	}
   1.485 -
   1.486 -	digits = 0;
   1.487 -	do 
   1.488 -	{
   1.489 -		digit = ('0' + val % 16);
   1.490 -		if (digit > '9')
   1.491 -		{
   1.492 -			digit += hexadjust;
   1.493 -		}
   1.494 -
   1.495 -		text[digits++] = digit;
   1.496 -		val /= 16;
   1.497 -	} while(val);
   1.498 -
   1.499 -	buf = *buf_p;
   1.500 -
   1.501 -	if (!(flags & LADJUST))
   1.502 -	{
   1.503 -		while (digits < width && maxlen)
   1.504 -		{
   1.505 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.506 -			width--;
   1.507 -			maxlen--;
   1.508 -		}
   1.509 -	}
   1.510 -
   1.511 -	while (digits-- && maxlen)
   1.512 -	{
   1.513 -		*buf++ = text[digits];
   1.514 -		width--;
   1.515 -		maxlen--;
   1.516 -	}
   1.517 -
   1.518 -	if (flags & LADJUST)
   1.519 -	{
   1.520 -		while (width-- && maxlen)
   1.521 -		{
   1.522 -			*buf++ = (flags & ZEROPAD) ? '0' : ' ';
   1.523 -			maxlen--;
   1.524 -		}
   1.525 -	}
   1.526 -
   1.527 -	*buf_p = buf;
   1.528 -}
   1.529 -
   1.530 -size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args)
   1.531 -{
   1.532 -	if (!buffer || !maxlen)
   1.533 -	{
   1.534 -		return 0;
   1.535 -	}
   1.536 -
   1.537 -	int arg = 0;
   1.538 -	char *buf_p;
   1.539 -	char ch;
   1.540 -	int flags;
   1.541 -	int width;
   1.542 -	int prec;
   1.543 -	int n;
   1.544 -	char sign;
   1.545 -	const char *fmt;
   1.546 -	size_t llen = maxlen - 1;
   1.547 -
   1.548 -	buf_p = buffer;
   1.549 -	fmt = format;
   1.550 -
   1.551 -	while (true)
   1.552 -	{
   1.553 -		// run through the format string until we hit a '%' or '\0'
   1.554 -		for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
   1.555 -		{
   1.556 -			*buf_p++ = ch;
   1.557 -			llen--;
   1.558 -		}
   1.559 -		if ((ch == '\0') || (llen <= 0))
   1.560 -		{
   1.561 -			goto done;
   1.562 -		}
   1.563 -
   1.564 -		// skip over the '%'
   1.565 -		fmt++;
   1.566 -
   1.567 -		// reset formatting state
   1.568 -		flags = 0;
   1.569 -		width = 0;
   1.570 -		prec = -1;
   1.571 -		sign = '\0';
   1.572 -
   1.573 -rflag:
   1.574 -		ch = *fmt++;
   1.575 -reswitch:
   1.576 -		switch(ch)
   1.577 -		{
   1.578 -		case '-':
   1.579 -			{
   1.580 -				flags |= LADJUST;
   1.581 -				goto rflag;
   1.582 -			}
   1.583 -		case '.':
   1.584 -			{
   1.585 -				n = 0;
   1.586 -				while(is_digit((ch = *fmt++)))
   1.587 -				{
   1.588 -					n = 10 * n + (ch - '0');
   1.589 -				}
   1.590 -				prec = (n < 0) ? -1 : n;
   1.591 -				goto reswitch;
   1.592 -			}
   1.593 -		case '0':
   1.594 -			{
   1.595 -				flags |= ZEROPAD;
   1.596 -				goto rflag;
   1.597 -			}
   1.598 -		case '1':
   1.599 -		case '2':
   1.600 -		case '3':
   1.601 -		case '4':
   1.602 -		case '5':
   1.603 -		case '6':
   1.604 -		case '7':
   1.605 -		case '8':
   1.606 -		case '9':
   1.607 -			{
   1.608 -				n = 0;
   1.609 -				do
   1.610 -				{
   1.611 -					n = 10 * n + (ch - '0');
   1.612 -					ch = *fmt++;
   1.613 -				} while(is_digit(ch));
   1.614 -				width = n;
   1.615 -				goto reswitch;
   1.616 -			}
   1.617 -		case 'c':
   1.618 -			{
   1.619 -				if (!llen)
   1.620 -				{
   1.621 -					goto done;
   1.622 -				}
   1.623 -				char *c = (char *)args[arg];
   1.624 -				*buf_p++ = *c;
   1.625 -				llen--;
   1.626 -				arg++;
   1.627 -				break;
   1.628 -			}
   1.629 -		case 'd':
   1.630 -		case 'i':
   1.631 -			{
   1.632 -				int *value = (int *)args[arg];
   1.633 -				AddInt(&buf_p, llen, *value, width, flags);
   1.634 -				arg++;
   1.635 -				break;
   1.636 -			}
   1.637 -		case 'u':
   1.638 -			{
   1.639 -				unsigned int *value = (unsigned int *)args[arg];
   1.640 -				AddUInt(&buf_p, llen, *value, width, flags);
   1.641 -				arg++;
   1.642 -				break;
   1.643 -			}
   1.644 -		case 'f':
   1.645 -			{
   1.646 -				float *value = (float *)args[arg];
   1.647 -				AddFloat(&buf_p, llen, *value, width, prec, flags);
   1.648 -				arg++;
   1.649 -				break;
   1.650 -			}
   1.651 -		case 's':
   1.652 -			{
   1.653 -				const char *str = (const char *)args[arg];
   1.654 -				AddString(&buf_p, llen, str, width, prec);
   1.655 -				arg++;
   1.656 -				break;
   1.657 -			}
   1.658 -		case 'X':
   1.659 -			{
   1.660 -				unsigned int *value = (unsigned int *)args[arg];
   1.661 -				flags |= UPPERDIGITS;
   1.662 -				AddHex(&buf_p, llen, *value, width, flags);
   1.663 -				arg++;
   1.664 -				break;
   1.665 -			}
   1.666 -		case 'x':
   1.667 -			{
   1.668 -				unsigned int *value = (unsigned int *)args[arg];
   1.669 -				AddHex(&buf_p, llen, *value, width, flags);
   1.670 -				arg++;
   1.671 -				break;
   1.672 -			}
   1.673 -		case '%':
   1.674 -			{
   1.675 -				if (!llen)
   1.676 -				{
   1.677 -					goto done;
   1.678 -				}
   1.679 -				*buf_p++ = ch;
   1.680 -				llen--;
   1.681 -				break;
   1.682 -			}
   1.683 -		case '\0':
   1.684 -			{
   1.685 -				if (!llen)
   1.686 -				{
   1.687 -					goto done;
   1.688 -				}
   1.689 -				*buf_p++ = '%';
   1.690 -				llen--;
   1.691 -				goto done;
   1.692 -			}
   1.693 -		default:
   1.694 -			{
   1.695 -				if (!llen)
   1.696 -				{
   1.697 -					goto done;
   1.698 -				}
   1.699 -				*buf_p++ = ch;
   1.700 -				llen--;
   1.701 -				break;
   1.702 -			}
   1.703 -		}
   1.704 -	}
   1.705 -
   1.706 -done:
   1.707 -	*buf_p = '\0';
   1.708 -
   1.709 -	return (maxlen - llen - 1);
   1.710 -}
   1.711 -
   1.712 -size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
   1.713 -{
   1.714 -	if (!buffer || !maxlen)
   1.715 -	{
   1.716 -		return 0;
   1.717 -	}
   1.718 -
   1.719 -	int arg;
   1.720 -	int args = params[0];
   1.721 -	char *buf_p;
   1.722 -	char ch;
   1.723 -	int flags;
   1.724 -	int width;
   1.725 -	int prec;
   1.726 -	int n;
   1.727 -	char sign;
   1.728 -	const char *fmt;
   1.729 -	size_t llen = maxlen - 1;
   1.730 -
   1.731 -	buf_p = buffer;
   1.732 -	arg = *param;
   1.733 -	fmt = format;
   1.734 -
   1.735 -	while (true)
   1.736 -	{
   1.737 -		// run through the format string until we hit a '%' or '\0'
   1.738 -		for (ch = *fmt; llen && ((ch = *fmt) != '\0') && (ch != '%'); fmt++)
   1.739 -		{
   1.740 -			*buf_p++ = ch;
   1.741 -			llen--;
   1.742 -		}
   1.743 -		if ((ch == '\0') || (llen <= 0))
   1.744 -		{
   1.745 -			goto done;
   1.746 -		}
   1.747 -
   1.748 -		// skip over the '%'
   1.749 -		fmt++;
   1.750 -
   1.751 -		// reset formatting state
   1.752 -		flags = 0;
   1.753 -		width = 0;
   1.754 -		prec = -1;
   1.755 -		sign = '\0';
   1.756 -
   1.757 -rflag:
   1.758 -		ch = *fmt++;
   1.759 -reswitch:
   1.760 -		switch(ch)
   1.761 -		{
   1.762 -		case '-':
   1.763 -			{
   1.764 -				flags |= LADJUST;
   1.765 -				goto rflag;
   1.766 -			}
   1.767 -		case '.':
   1.768 -			{
   1.769 -				n = 0;
   1.770 -				while(is_digit((ch = *fmt++)))
   1.771 -				{
   1.772 -					n = 10 * n + (ch - '0');
   1.773 -				}
   1.774 -				prec = (n < 0) ? -1 : n;
   1.775 -				goto reswitch;
   1.776 -			}
   1.777 -		case '0':
   1.778 -			{
   1.779 -				flags |= ZEROPAD;
   1.780 -				goto rflag;
   1.781 -			}
   1.782 -		case '1':
   1.783 -		case '2':
   1.784 -		case '3':
   1.785 -		case '4':
   1.786 -		case '5':
   1.787 -		case '6':
   1.788 -		case '7':
   1.789 -		case '8':
   1.790 -		case '9':
   1.791 -			{
   1.792 -				n = 0;
   1.793 -				do
   1.794 -				{
   1.795 -					n = 10 * n + (ch - '0');
   1.796 -					ch = *fmt++;
   1.797 -				} while(is_digit(ch));
   1.798 -				width = n;
   1.799 -				goto reswitch;
   1.800 -			}
   1.801 -		case 'c':
   1.802 -			{
   1.803 -				CHECK_ARGS(0);
   1.804 -				if (!llen)
   1.805 -				{
   1.806 -					goto done;
   1.807 -				}
   1.808 -				char *c;
   1.809 -				pCtx->LocalToString(params[arg], &c);
   1.810 -				*buf_p++ = *c;
   1.811 -				llen--;
   1.812 -				arg++;
   1.813 -				break;
   1.814 -			}
   1.815 -		case 'd':
   1.816 -		case 'i':
   1.817 -			{
   1.818 -				CHECK_ARGS(0);
   1.819 -				cell_t *value;
   1.820 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.821 -				AddInt(&buf_p, llen, static_cast<int>(*value), width, flags);
   1.822 -				arg++;
   1.823 -				break;
   1.824 -			}
   1.825 -		case 'u':
   1.826 -			{
   1.827 -				CHECK_ARGS(0);
   1.828 -				cell_t *value;
   1.829 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.830 -				AddUInt(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
   1.831 -				arg++;
   1.832 -				break;
   1.833 -			}
   1.834 -		case 'f':
   1.835 -			{
   1.836 -				CHECK_ARGS(0);
   1.837 -				cell_t *value;
   1.838 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.839 -				AddFloat(&buf_p, llen, sp_ctof(*value), width, prec, flags);
   1.840 -				arg++;
   1.841 -				break;
   1.842 -			}
   1.843 -		case 'L':
   1.844 -			{
   1.845 -				CHECK_ARGS(0);
   1.846 -				cell_t *value;
   1.847 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.848 -				char buffer[255];
   1.849 -				if (*value)
   1.850 -				{
   1.851 -					CPlayer *player = g_Players.GetPlayerByIndex(*value);
   1.852 -					if (!player || !player->IsConnected())
   1.853 -					{
   1.854 -						return pCtx->ThrowNativeError("Client index %d is invalid", *value);
   1.855 -					}
   1.856 -					const char *auth = player->GetAuthString();
   1.857 -					if (!auth || auth[0] == '\0')
   1.858 -					{
   1.859 -						auth = "STEAM_ID_PENDING";
   1.860 -					}
   1.861 -					int userid = engine->GetPlayerUserId(player->GetEdict());
   1.862 -					UTIL_Format(buffer, 
   1.863 -						sizeof(buffer), 
   1.864 -						"%s<%d><%s><>", 
   1.865 -						player->GetName(),
   1.866 -						userid,
   1.867 -						auth);
   1.868 -				}
   1.869 -				else
   1.870 -				{
   1.871 -					UTIL_Format(buffer,
   1.872 -						sizeof(buffer),
   1.873 -						"Console<0><Console><Console>");
   1.874 -				}
   1.875 -				AddString(&buf_p, llen, buffer, width, prec);
   1.876 -				arg++;
   1.877 -				break;
   1.878 -			}
   1.879 -		case 'N':
   1.880 -			{
   1.881 -				CHECK_ARGS(0);
   1.882 -				cell_t *value;
   1.883 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.884 -
   1.885 -				const char *name = "Console";
   1.886 -				if (*value)
   1.887 -				{
   1.888 -					CPlayer *player = g_Players.GetPlayerByIndex(*value);
   1.889 -					if (!player || !player->IsConnected())
   1.890 -					{
   1.891 -						return pCtx->ThrowNativeError("Client index %d is invalid", *value);
   1.892 -					}
   1.893 -					name = player->GetName();
   1.894 -				}
   1.895 -				AddString(&buf_p, llen, name, width, prec);
   1.896 -				arg++;
   1.897 -				break;
   1.898 -			}
   1.899 -		case 's':
   1.900 -			{
   1.901 -				CHECK_ARGS(0);
   1.902 -				char *str;
   1.903 -				int err;
   1.904 -				if ((err=pCtx->LocalToString(params[arg], &str)) != SP_ERROR_NONE)
   1.905 -				{
   1.906 -					pCtx->ThrowNativeErrorEx(err, "Could not deference string");
   1.907 -					return 0;
   1.908 -				}
   1.909 -				AddString(&buf_p, llen, str, width, prec);
   1.910 -				arg++;
   1.911 -				break;
   1.912 -			}
   1.913 -		case 'T':
   1.914 -			{
   1.915 -				CHECK_ARGS(1);
   1.916 -				char *key;
   1.917 -				bool error;
   1.918 -				size_t res;
   1.919 -				cell_t *target;
   1.920 -				pCtx->LocalToString(params[arg++], &key);
   1.921 -				pCtx->LocalToPhysAddr(params[arg++], &target);
   1.922 -				res = Translate(buf_p, llen, pCtx, key, *target, params, &arg, &error);
   1.923 -				if (error)
   1.924 -				{
   1.925 -					return 0;
   1.926 -				}
   1.927 -				buf_p += res;
   1.928 -				llen -= res;
   1.929 -				break;
   1.930 -			}
   1.931 -		case 't':
   1.932 -			{
   1.933 -				CHECK_ARGS(0);
   1.934 -				char *key;
   1.935 -				bool error;
   1.936 -				size_t res;
   1.937 -				cell_t target = g_SourceMod.GetGlobalTarget();
   1.938 -				pCtx->LocalToString(params[arg++], &key);
   1.939 -				res = Translate(buf_p, llen, pCtx, key, target, params, &arg, &error);
   1.940 -				if (error)
   1.941 -				{
   1.942 -					return 0;
   1.943 -				}
   1.944 -				buf_p += res;
   1.945 -				llen -= res;
   1.946 -				break;
   1.947 -			}
   1.948 -		case 'X':
   1.949 -			{
   1.950 -				CHECK_ARGS(0);
   1.951 -				cell_t *value;
   1.952 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.953 -				flags |= UPPERDIGITS;
   1.954 -				AddHex(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
   1.955 -				arg++;
   1.956 -				break;
   1.957 -			}
   1.958 -		case 'x':
   1.959 -			{
   1.960 -				CHECK_ARGS(0);
   1.961 -				cell_t *value;
   1.962 -				pCtx->LocalToPhysAddr(params[arg], &value);
   1.963 -				AddHex(&buf_p, llen, static_cast<unsigned int>(*value), width, flags);
   1.964 -				arg++;
   1.965 -				break;
   1.966 -			}
   1.967 -		case '%':
   1.968 -			{
   1.969 -				if (!llen)
   1.970 -				{
   1.971 -					goto done;
   1.972 -				}
   1.973 -				*buf_p++ = ch;
   1.974 -				llen--;
   1.975 -				break;
   1.976 -			}
   1.977 -		case '\0':
   1.978 -			{
   1.979 -				if (!llen)
   1.980 -				{
   1.981 -					goto done;
   1.982 -				}
   1.983 -				*buf_p++ = '%';
   1.984 -				llen--;
   1.985 -				goto done;
   1.986 -			}
   1.987 -		default:
   1.988 -			{
   1.989 -				if (!llen)
   1.990 -				{
   1.991 -					goto done;
   1.992 -				}
   1.993 -				*buf_p++ = ch;
   1.994 -				llen--;
   1.995 -				break;
   1.996 -			}
   1.997 -		}
   1.998 -	}
   1.999 -
  1.1000 -done:
  1.1001 -	*buf_p = '\0';
  1.1002 -	*param = arg;
  1.1003 -	return (maxlen - llen - 1);
  1.1004 -}
  1.1005 -
  1.1006 -const char *stristr(const char *str, const char *substr)
  1.1007 -{
  1.1008 -	if (!*substr)
  1.1009 -	{
  1.1010 -		return ((char *)str);
  1.1011 -	}
  1.1012 -
  1.1013 -	char *needle = (char *)substr;
  1.1014 -	char *prevloc = (char *)str;
  1.1015 -	char *haystack = (char *)str;
  1.1016 -
  1.1017 -	while (*haystack)
  1.1018 -	{
  1.1019 -		if (tolower(*haystack) == tolower(*needle))
  1.1020 -		{
  1.1021 -			haystack++;
  1.1022 -			if (!*++needle)
  1.1023 -			{
  1.1024 -				return prevloc;
  1.1025 -			}
  1.1026 -		}
  1.1027 -		else
  1.1028 -		{
  1.1029 -			haystack = ++prevloc;
  1.1030 -			needle = (char *)substr;
  1.1031 -		}
  1.1032 -	}
  1.1033 -
  1.1034 -	return NULL;
  1.1035 -}
  1.1036 -
  1.1037 -unsigned int strncopy(char *dest, const char *src, size_t count)
  1.1038 -{
  1.1039 -	if (!count)
  1.1040 -	{
  1.1041 -		return 0;
  1.1042 -	}
  1.1043 -
  1.1044 -	char *start = dest;
  1.1045 -	while ((*src) && (--count))
  1.1046 -	{
  1.1047 -		*dest++ = *src++;
  1.1048 -	}
  1.1049 -	*dest = '\0';
  1.1050 -
  1.1051 -	return (dest - start);
  1.1052 -}
  1.1053 -
  1.1054 -size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
  1.1055 -{
  1.1056 -	va_list ap;
  1.1057 -	va_start(ap, fmt);
  1.1058 -	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
  1.1059 -	va_end(ap);
  1.1060 -
  1.1061 -	if (len >= maxlength)
  1.1062 -	{
  1.1063 -		buffer[maxlength - 1] = '\0';
  1.1064 -		return (maxlength - 1);
  1.1065 -	}
  1.1066 -	else
  1.1067 -	{
  1.1068 -		return len;
  1.1069 -	}
  1.1070 -}
  1.1071 -
  1.1072 -size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap)
  1.1073 -{
  1.1074 -	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
  1.1075 -
  1.1076 -	if (len >= maxlength)
  1.1077 -	{
  1.1078 -		buffer[maxlength - 1] = '\0';
  1.1079 -		return (maxlength - 1);
  1.1080 -	}
  1.1081 -	else
  1.1082 -	{
  1.1083 -		return len;
  1.1084 -	}
  1.1085 -}
  1.1086 -
  1.1087 -char *sm_strdup(const char *str)
  1.1088 -{
  1.1089 -	char *ptr = new char[strlen(str)+1];
  1.1090 -	strcpy(ptr, str);
  1.1091 -	return ptr;
  1.1092 -}
  1.1093 -
  1.1094 -unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace)
  1.1095 -{
  1.1096 -	size_t searchLen = strlen(search);
  1.1097 -	size_t replaceLen = strlen(replace);
  1.1098 -
  1.1099 -	char *ptr = subject;
  1.1100 -	unsigned int total = 0;
  1.1101 -	while ((ptr = UTIL_ReplaceEx(ptr, maxlength, search, searchLen, replace, replaceLen)) != NULL)
  1.1102 -	{
  1.1103 -		total++;
  1.1104 -		if (*ptr == '\0')
  1.1105 -		{
  1.1106 -			break;
  1.1107 -		}
  1.1108 -	}
  1.1109 -
  1.1110 -	return total;
  1.1111 -}
  1.1112 -
  1.1113 -/**
  1.1114 - * NOTE: Do not edit this for the love of god unless you have 
  1.1115 - * read the test cases and understand the code behind each one.
  1.1116 - * While I don't guarantee there aren't mistakes, I do guarantee
  1.1117 - * that plugins will end up relying on tiny idiosyncracies of this
  1.1118 - * function, just like they did with AMX Mod X.
  1.1119 - *
  1.1120 - * There are explicitly more cases than the AMX Mod X version because
  1.1121 - * we're not doing a blind copy.  Each case is specifically optimized
  1.1122 - * for what needs to be done.  Even better, we don't have to error on
  1.1123 - * bad buffer sizes.  Instead, this function will smartly cut off the 
  1.1124 - * string in a way that pushes old data out.
  1.1125 - */
  1.1126 -char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen)
  1.1127 -{
  1.1128 -	char *ptr = subject;
  1.1129 -	size_t browsed = 0;
  1.1130 -	size_t textLen = strlen(subject);
  1.1131 -
  1.1132 -	/* It's not possible to search or replace */
  1.1133 -	if (searchLen > textLen)
  1.1134 -	{
  1.1135 -		return NULL;
  1.1136 -	}
  1.1137 -
  1.1138 -	/* Handle the case of one byte replacement.
  1.1139 -	 * It's only valid in one case.
  1.1140 -	 */
  1.1141 -	if (maxLen == 1)
  1.1142 -	{
  1.1143 -		/* If the search matches and the replace length is 0, 
  1.1144 -		 * we can just terminate the string and be done.
  1.1145 -		 */
  1.1146 -		if (strcmp(subject, search) == 0 && replaceLen == 0)
  1.1147 -		{
  1.1148 -			*subject = '\0';
  1.1149 -			return subject;
  1.1150 -		}
  1.1151 -		else
  1.1152 -		{
  1.1153 -			return NULL;
  1.1154 -		}
  1.1155 -	}
  1.1156 -
  1.1157 -	/* Subtract one off the maxlength so we can include the null terminator */
  1.1158 -	maxLen--;
  1.1159 -
  1.1160 -	while (*ptr != '\0' && (browsed <= textLen - searchLen))
  1.1161 -	{
  1.1162 -		/* See if we get a comparison */
  1.1163 -		if (strncmp(ptr, search, searchLen) == 0)
  1.1164 -		{
  1.1165 -			if (replaceLen > searchLen)
  1.1166 -			{
  1.1167 -				/* First, see if we have enough space to do this operation */
  1.1168 -				if (maxLen - textLen < replaceLen - searchLen)
  1.1169 -				{
  1.1170 -					/* First, see if the replacement length goes out of bounds. */
  1.1171 -					if (browsed + replaceLen >= maxLen)
  1.1172 -					{
  1.1173 -						/* EXAMPLE CASE:
  1.1174 -						 * Subject: AABBBCCC
  1.1175 -						 * Buffer : 12 bytes
  1.1176 -						 * Search : BBB
  1.1177 -						 * Replace: DDDDDDDDDD
  1.1178 -						 * OUTPUT : AADDDDDDDDD
  1.1179 -						 * POSITION:           ^
  1.1180 -						 */
  1.1181 -						/* If it does, we'll just bound the length and do a strcpy. */
  1.1182 -						replaceLen = maxLen - browsed;
  1.1183 -						/* Note, we add one to the final result for the null terminator */
  1.1184 -						strncopy(ptr, replace, replaceLen+1);
  1.1185 -					}
  1.1186 -					else
  1.1187 -					{
  1.1188 -						/* EXAMPLE CASE:
  1.1189 -						 * Subject: AABBBCCC
  1.1190 -						 * Buffer : 12 bytes
  1.1191 -						 * Search : BBB
  1.1192 -						 * Replace: DDDDDDD
  1.1193 -						 * OUTPUT : AADDDDDDDCC
  1.1194 -						 * POSITION:         ^
  1.1195 -						 */
  1.1196 -						/* We're going to have some bytes left over... */
  1.1197 -						size_t origBytesToCopy = (textLen - (browsed + searchLen)) + 1;
  1.1198 -						size_t realBytesToCopy = (maxLen - (browsed + replaceLen)) + 1;
  1.1199 -						char *moveFrom = ptr + searchLen + (origBytesToCopy - realBytesToCopy);
  1.1200 -						char *moveTo = ptr + replaceLen;
  1.1201 -
  1.1202 -						/* First, move our old data out of the way. */
  1.1203 -						memmove(moveTo, moveFrom, realBytesToCopy);
  1.1204 -
  1.1205 -						/* Now, do our replacement. */
  1.1206 -						memcpy(ptr, replace, replaceLen);
  1.1207 -					}
  1.1208 -				}
  1.1209 -				else
  1.1210 -				{
  1.1211 -					/* EXAMPLE CASE:
  1.1212 -					 * Subject: AABBBCCC
  1.1213 -					 * Buffer : 12 bytes
  1.1214 -					 * Search : BBB
  1.1215 -					 * Replace: DDDD
  1.1216 -					 * OUTPUT : AADDDDCCC
  1.1217 -					 * POSITION:      ^
  1.1218 -					 */
  1.1219 -					/* Yes, we have enough space.  Do a normal move operation. */
  1.1220 -					char *moveFrom = ptr + searchLen;
  1.1221 -					char *moveTo = ptr + replaceLen;
  1.1222 -
  1.1223 -					/* First move our old data out of the way. */
  1.1224 -					size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
  1.1225 -					memmove(moveTo, moveFrom, bytesToCopy);
  1.1226 -
  1.1227 -					/* Now do our replacement. */
  1.1228 -					memcpy(ptr, replace, replaceLen);
  1.1229 -				}
  1.1230 -			}
  1.1231 -			else if (replaceLen < searchLen)
  1.1232 -			{
  1.1233 -				/* EXAMPLE CASE:
  1.1234 -				 * Subject: AABBBCCC
  1.1235 -				 * Buffer : 12 bytes
  1.1236 -				 * Search : BBB
  1.1237 -				 * Replace: D
  1.1238 -				 * OUTPUT : AADCCC
  1.1239 -				 * POSOTION:   ^
  1.1240 -				 */
  1.1241 -				/* If the replacement does not grow the string length, we do not
  1.1242 -				 * need to do any fancy checking at all.  Yay!
  1.1243 -				 */
  1.1244 -				char *moveFrom = ptr + searchLen;		/* Start after the search pointer */
  1.1245 -				char *moveTo = ptr + replaceLen;		/* Copy to where the replacement ends */
  1.1246 -
  1.1247 -				/* Copy our replacement in, if any */
  1.1248 -				if (replaceLen)
  1.1249 -				{
  1.1250 -					memcpy(ptr, replace, replaceLen);
  1.1251 -				}
  1.1252 -
  1.1253 -				/* Figure out how many bytes to move down, including null terminator */
  1.1254 -				size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
  1.1255 -
  1.1256 -				/* Move the rest of the string down */
  1.1257 -				memmove(moveTo, moveFrom, bytesToCopy);
  1.1258 -			}
  1.1259 -			else
  1.1260 -			{
  1.1261 -				/* EXAMPLE CASE:
  1.1262 -				 * Subject: AABBBCCC
  1.1263 -				 * Buffer : 12 bytes
  1.1264 -				 * Search : BBB
  1.1265 -				 * Replace: DDD
  1.1266 -				 * OUTPUT : AADDDCCC
  1.1267 -				 * POSITION:     ^
  1.1268 -				 */
  1.1269 -				/* We don't have to move anything around, just do a straight copy */
  1.1270 -				memcpy(ptr, replace, replaceLen);
  1.1271 -			}
  1.1272 -
  1.1273 -			return ptr + replaceLen;
  1.1274 -		}
  1.1275 -		ptr++;
  1.1276 -		browsed++;
  1.1277 -	}
  1.1278 -
  1.1279 -	return NULL;
  1.1280 -}