core/smn_string.cpp
author David Anderson <dvander@alliedmods.net>
Mon Mar 19 01:44:09 2007 +0000 (2007-03-19)
changeset 647 1e29dcc9ca97
parent 631 76dc2aa558e5
child 653 ef60870067ff
permissions -rw-r--r--
fixed a potential bug with kicking players during authorization
     1 /**
     2  * ===============================================================
     3  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     4  * ===============================================================
     5  *
     6  * This file is not open source and may not be copied without explicit
     7  * written permission of AlliedModders LLC.  This file may not be redistributed 
     8  * in whole or significant part.
     9  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    10  *
    11  * Version: $Id$
    12  */
    13 
    14 #include <string.h>
    15 #include <stdlib.h>
    16 #include "sm_globals.h"
    17 #include "sm_stringutil.h"
    18 #include "TextParsers.h"
    19 
    20 inline const char *_strstr(const char *str, const char *substr)
    21 {
    22 #ifdef PLATFORM_WINDOWS
    23 	return strstr(str, substr);
    24 #elif defined PLATFORM_LINUX
    25 	return (const char *)strstr(str, substr);
    26 #endif
    27 }
    28 
    29 /*********************************************
    30 *                                            *
    31 * STRING MANIPULATION NATIVE IMPLEMENTATIONS *
    32 *                                            *
    33 *********************************************/
    34 
    35 static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params)
    36 {
    37 	char *str;
    38 	pCtx->LocalToString(params[1], &str);
    39 
    40 	return strlen(str);
    41 }
    42 
    43 static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params)
    44 {
    45 	typedef const char *(*STRSEARCH)(const char *, const char *);
    46 	STRSEARCH func;
    47 	char *str, *substr;
    48 
    49 	pCtx->LocalToString(params[1], &str);
    50 	pCtx->LocalToString(params[2], &substr);
    51 
    52 	func = (params[3]) ? _strstr : stristr;
    53 	const char *pos = func(str, substr);
    54 	if (pos)
    55 	{
    56 		return (pos - str);
    57 	}
    58 
    59 	return -1;
    60 }
    61 
    62 static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params)
    63 {
    64 	typedef int (*STRCOMPARE)(const char *, const char *);
    65 	STRCOMPARE func;
    66 	char *str1, *str2;
    67 
    68 	pCtx->LocalToString(params[1], &str1);
    69 	pCtx->LocalToString(params[2], &str2);
    70 
    71 	func = (params[3]) ? strcmp : stricmp;
    72 
    73 	return (func(str1, str2));
    74 }
    75 
    76 static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
    77 {
    78 	char *dest, *src;
    79 
    80 	pCtx->LocalToString(params[1], &dest);
    81 	pCtx->LocalToString(params[3], &src);
    82 
    83 	return strncopy(dest, src, params[2]);
    84 }
    85 
    86 static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params)
    87 {
    88 	char *str, *dummy;
    89 	pCtx->LocalToString(params[1], &str);
    90 
    91 	return static_cast<cell_t>(strtol(str, &dummy, params[2]));
    92 }
    93 
    94 static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
    95 {
    96 	char *str;
    97 	pCtx->LocalToString(params[2], &str);
    98 	size_t res = UTIL_Format(str, params[3], "%d", params[1]);
    99 
   100 	return static_cast<cell_t>(res);
   101 }
   102 
   103 static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
   104 {
   105 	char *str, *dummy;
   106 	pCtx->LocalToString(params[1], &str);
   107 
   108 	float val = (float)strtod(str, &dummy);
   109 
   110 	return sp_ftoc(val);
   111 }
   112 
   113 static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
   114 {
   115 	char *str;
   116 	pCtx->LocalToString(params[2], &str);
   117 	size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
   118 
   119 	return static_cast<cell_t>(res);
   120 }
   121 
   122 static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
   123 {
   124 	char *buf, *fmt;
   125 	size_t res;
   126 	int arg = 4;
   127 
   128 	pCtx->LocalToString(params[1], &buf);
   129 	pCtx->LocalToString(params[3], &fmt);
   130 	res = atcprintf(buf, static_cast<size_t>(params[2]), fmt, pCtx, params, &arg);
   131 
   132 	return static_cast<cell_t>(res);
   133 }
   134 
   135 static char g_formatbuf[2048];
   136 static cell_t sm_format(IPluginContext *pCtx, const cell_t *params)
   137 {
   138 	char *buf, *fmt, *destbuf;
   139 	cell_t start_addr, end_addr, maxparam;
   140 	size_t res, maxlen;
   141 	int arg = 4;
   142 	bool copy = false;
   143 
   144 	pCtx->LocalToString(params[1], &destbuf);
   145 	pCtx->LocalToString(params[3], &fmt);
   146 
   147 	maxlen = static_cast<size_t>(params[2]);
   148 	start_addr = params[1];
   149 	end_addr = params[1] + maxlen;
   150 	maxparam = params[0];
   151 
   152 	for (cell_t i=3; i<=maxparam; i++)
   153 	{
   154 		if ((params[i] >= start_addr) && (params[i] <= end_addr))
   155 		{
   156 			copy = true;
   157 			break;
   158 		}
   159 	}
   160 	buf = (copy) ? g_formatbuf : destbuf;
   161 	res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg);
   162 
   163 	if (copy)
   164 	{
   165 		memcpy(destbuf, g_formatbuf, res+1);
   166 	}
   167 
   168 	return static_cast<cell_t>(res);
   169 }
   170 
   171 static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
   172 {
   173 	int vargPos = static_cast<int>(params[4]);
   174 
   175 	/* Get the parent parameter array */
   176 	sp_context_t *ctx = pContext->GetContext();
   177 	cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
   178 
   179 	cell_t max = local_params[0];
   180 	if (vargPos > (int)max + 1)
   181 	{
   182 		return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos);
   183 	}
   184 
   185 	cell_t addr_start = params[1];
   186 	cell_t addr_end = addr_start + params[2];
   187 	bool copy = false;
   188 	for (int i=vargPos; i<=max; i++)
   189 	{
   190 		/* Does this clip bounds? */
   191 		if ((local_params[i] >= addr_start)
   192 			&& (local_params[i] <= addr_end))
   193 		{
   194 			copy = true;
   195 			break;
   196 		}
   197 	}
   198 
   199 	/* Get destination info */
   200 	char *format, *destination;
   201 	size_t maxlen = static_cast<size_t>(params[2]);
   202 
   203 	if (copy)
   204 	{
   205 		destination = g_formatbuf;
   206 	} else {
   207 		pContext->LocalToString(params[1], &destination);
   208 	}
   209 
   210 	pContext->LocalToString(params[3], &format);
   211 
   212 	size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos);
   213 
   214 	/* Perform copy-on-write if we need to */
   215 	if (copy)
   216 	{
   217 		pContext->StringToLocal(params[1], maxlen, g_formatbuf);
   218 	}
   219 
   220 	return total;
   221 }
   222 
   223 /* :TODO: make this UTF8 safe */
   224 static cell_t StrBreak(IPluginContext *pContext, const cell_t *params)
   225 {
   226 	const char *input;
   227 	char *out;
   228 	size_t outMax;
   229 
   230 	/* Get parameters */
   231 	pContext->LocalToString(params[1], (char **)&input);
   232 	pContext->LocalToString(params[2], &out);
   233 	outMax = params[3];
   234 
   235 	const char *inptr = input;
   236 	/* Eat up whitespace */
   237 	while (*inptr != '\0' && IsWhitespace(inptr))
   238 	{
   239 		inptr++;
   240 	}
   241 
   242 	if (*inptr == '\0')
   243 	{
   244 		if (outMax)
   245 		{
   246 			*out = '\0';
   247 		}
   248 		return -1;
   249 	}
   250 
   251 	const char *start, *end = NULL;
   252 
   253 	bool quoted = (*inptr == '"');
   254 	if (quoted)
   255 	{
   256 		inptr++;
   257 		start = inptr;
   258 		/* Read input until we reach a quote. */
   259 		while (*inptr != '\0' && *inptr != '"')
   260 		{
   261 			/* Update the end point, increment the stream. */
   262 			end = inptr++;
   263 		}
   264 		/* Read one more token if we reached an end quote */
   265 		if (*inptr == '"')
   266 		{
   267 			inptr++;
   268 		}
   269 	} else {
   270 		start = inptr;
   271 		/* Read input until we reach a space */
   272 		while (*inptr != '\0' && !IsWhitespace(inptr))
   273 		{
   274 			/* Update the end point, increment the stream. */
   275 			end = inptr++;
   276 		}
   277 	}
   278 
   279 	/* Copy the string we found, if necessary */
   280 	if (end == NULL)
   281 	{
   282 		if (outMax)
   283 		{
   284 			*out = '\0';
   285 		}
   286 	} else if (outMax) {
   287 		char *outptr = out;
   288 		outMax--;
   289 		for (const char *ptr=start;
   290 			(ptr <= end) && ((unsigned)(outptr - out) < (outMax));
   291 			ptr++, outptr++)
   292 			{
   293 			*outptr = *ptr;
   294 		}
   295 		*outptr = '\0';
   296 	}
   297 
   298 	/* Consume more of the string until we reach non-whitespace */
   299 	while (*inptr != '\0' && IsWhitespace(inptr))
   300 	{
   301 		inptr++;
   302 	}
   303 
   304 	if (*inptr == '\0')
   305 	{
   306 		return -1;
   307 	}
   308 
   309 	return inptr - input;
   310 }
   311 
   312 REGISTER_NATIVES(basicStrings)
   313 {
   314 	{"strlen",				sm_strlen},
   315 	{"StrBreak",			StrBreak},
   316 	{"StrContains",			sm_contain},
   317 	{"StrCompare",			sm_strcmp},
   318 	{"StrCopy",				sm_strcopy},
   319 	{"StringToInt",			sm_strconvint},
   320 	{"IntToString",			sm_numtostr},
   321 	{"StringToFloat",		sm_strtofloat},
   322 	{"FloatToString",		sm_floattostr},
   323 	{"Format",				sm_format},
   324 	{"FormatEx",			sm_formatex},
   325 	{"VFormat",				sm_vformat},
   326 	{NULL,					NULL},
   327 };