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