core/smn_string.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun Feb 04 22:41:44 2007 +0000 (2007-02-04)
changeset 430 ed37e9767ed4
parent 411 d954bff454a0
child 432 77112e9620fa
permissions -rw-r--r--
Optimized forwards, now paused functions are stored in a temp list so we dont have to check if they're runnable on each function execution.
     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 "sm_platform.h"
    15 #include <string.h>
    16 #include <stdlib.h>
    17 #include "sm_globals.h"
    18 #include "sm_stringutil.h"
    19 
    20 using namespace SourcePawn;
    21 
    22 inline const char *_strstr(const char *str, const char *substr)
    23 {
    24 #ifdef PLATFORM_WINDOWS
    25 	return strstr(str, substr);
    26 #elif defined PLATFORM_LINUX
    27 	return (const char *)strstr(str, substr);
    28 #endif
    29 }
    30 
    31 /*********************************************
    32 *                                            *
    33 * STRING MANIPULATION NATIVE IMPLEMENTATIONS *
    34 *                                            *
    35 *********************************************/
    36 
    37 static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params)
    38 {
    39 	char *str;
    40 	pCtx->LocalToString(params[1], &str);
    41 
    42 	return strlen(str);
    43 }
    44 
    45 static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params)
    46 {
    47 	typedef const char *(*STRSEARCH)(const char *, const char *);
    48 	STRSEARCH func;
    49 	char *str, *substr;
    50 
    51 	pCtx->LocalToString(params[1], &str);
    52 	pCtx->LocalToString(params[2], &substr);
    53 
    54 	func = (params[3]) ? _strstr : stristr;
    55 	const char *pos = func(str, substr);
    56 	if (pos)
    57 	{
    58 		return (pos - str);
    59 	}
    60 
    61 	return -1;
    62 }
    63 
    64 static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params)
    65 {
    66 	typedef int (*STRCOMPARE)(const char *, const char *);
    67 	STRCOMPARE func;
    68 	char *str1, *str2;
    69 
    70 	pCtx->LocalToString(params[1], &str1);
    71 	pCtx->LocalToString(params[2], &str2);
    72 
    73 	func = (params[3]) ? strcmp : stricmp;
    74 
    75 	return (func(str1, str2));
    76 }
    77 
    78 static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
    79 {
    80 	char *dest, *src;
    81 
    82 	pCtx->LocalToString(params[1], &dest);
    83 	pCtx->LocalToString(params[3], &src);
    84 
    85 	return strncopy(dest, src, params[2]);
    86 }
    87 
    88 static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params)
    89 {
    90 	char *str, *dummy;
    91 	pCtx->LocalToString(params[1], &str);
    92 
    93 	return static_cast<cell_t>(strtol(str, &dummy, params[2]));
    94 }
    95 
    96 static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
    97 {
    98 	char *str;
    99 	pCtx->LocalToString(params[2], &str);
   100 	size_t res = UTIL_Format(str, params[3], "%d", params[1]);
   101 
   102 	return static_cast<cell_t>(res);
   103 }
   104 
   105 static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
   106 {
   107 	char *str, *dummy;
   108 	pCtx->LocalToString(params[1], &str);
   109 
   110 	float val = (float)strtod(str, &dummy);
   111 
   112 	return sp_ftoc(val);
   113 }
   114 
   115 static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
   116 {
   117 	char *str;
   118 	pCtx->LocalToString(params[2], &str);
   119 	size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
   120 
   121 	return static_cast<cell_t>(res);
   122 }
   123 
   124 static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
   125 {
   126 	char *buf, *fmt;
   127 	size_t res;
   128 	int arg = 4;
   129 
   130 	pCtx->LocalToString(params[1], &buf);
   131 	pCtx->LocalToString(params[3], &fmt);
   132 	res = atcprintf(buf, static_cast<size_t>(params[2]), fmt, pCtx, params, &arg);
   133 
   134 	return static_cast<cell_t>(res);
   135 }
   136 
   137 static char g_formatbuf[2048];
   138 static cell_t sm_format(IPluginContext *pCtx, const cell_t *params)
   139 {
   140 	char *buf, *fmt, *destbuf;
   141 	cell_t start_addr, end_addr, maxparam;
   142 	size_t res, maxlen;
   143 	int arg = 4;
   144 	bool copy = false;
   145 
   146 	pCtx->LocalToString(params[1], &destbuf);
   147 	pCtx->LocalToString(params[3], &fmt);
   148 
   149 	maxlen = static_cast<size_t>(params[2]);
   150 	start_addr = params[1];
   151 	end_addr = params[1] + maxlen;
   152 	maxparam = params[0];
   153 
   154 	for (cell_t i=3; i<=maxparam; i++)
   155 	{
   156 		if ((params[i] >= start_addr) && (params[i] <= end_addr))
   157 		{
   158 			copy = true;
   159 			break;
   160 		}
   161 	}
   162 	buf = (copy) ? g_formatbuf : destbuf;
   163 	res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg);
   164 
   165 	if (copy)
   166 	{
   167 		memcpy(destbuf, g_formatbuf, res+1);
   168 	}
   169 
   170 	return static_cast<cell_t>(res);
   171 }
   172 
   173 static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
   174 {
   175 	int vargPos = static_cast<int>(params[4]);
   176 
   177 	/* Get the parent parameter array */
   178 	sp_context_t *ctx = pContext->GetContext();
   179 	cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
   180 
   181 	cell_t max = local_params[0];
   182 	if (vargPos > (int)max + 1)
   183 	{
   184 		return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos);
   185 	}
   186 
   187 	cell_t addr_start = params[1];
   188 	cell_t addr_end = addr_start + params[2];
   189 	bool copy = false;
   190 	for (int i=vargPos; i<=max; i++)
   191 	{
   192 		/* Does this clip bounds? */
   193 		if ((local_params[i] >= addr_start)
   194 			&& (local_params[i] <= addr_end))
   195 		{
   196 			copy = true;
   197 			break;
   198 		}
   199 	}
   200 
   201 	/* Get destination info */
   202 	char *format, *destination;
   203 	size_t maxlen = static_cast<size_t>(params[2]);
   204 
   205 	if (copy)
   206 	{
   207 		destination = g_formatbuf;
   208 	} else {
   209 		pContext->LocalToString(params[1], &destination);
   210 	}
   211 
   212 	pContext->LocalToString(params[3], &format);
   213 
   214 	size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos);
   215 
   216 	/* Perform copy-on-write if we need to */
   217 	if (copy)
   218 	{
   219 		pContext->StringToLocal(params[1], maxlen, g_formatbuf);
   220 	}
   221 
   222 	return total;
   223 }
   224 
   225 REGISTER_NATIVES(basicstrings)
   226 {
   227 	{"strlen",				sm_strlen},
   228 	{"StrContains",			sm_contain},
   229 	{"StrCompare",			sm_strcmp},
   230 	{"StrCopy",				sm_strcopy},
   231 	{"StringToInt",			sm_strconvint},
   232 	{"IntToString",			sm_numtostr},
   233 	{"StringToFloat",		sm_strtofloat},
   234 	{"FloatToString",		sm_floattostr},
   235 	{"Format",				sm_format},
   236 	{"FormatEx",			sm_formatex},
   237 	{"VFormat",				sm_vformat},
   238 	{NULL,					NULL},
   239 };