2 * ===============================================================
3 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ===============================================================
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
16 #include "sm_globals.h"
17 #include "sm_stringutil.h"
19 inline const char *_strstr(const char *str, const char *substr)
21 #ifdef PLATFORM_WINDOWS
22 return strstr(str, substr);
23 #elif defined PLATFORM_LINUX
24 return (const char *)strstr(str, substr);
28 /*********************************************
30 * STRING MANIPULATION NATIVE IMPLEMENTATIONS *
32 *********************************************/
34 static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params)
37 pCtx->LocalToString(params[1], &str);
42 static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params)
44 typedef const char *(*STRSEARCH)(const char *, const char *);
48 pCtx->LocalToString(params[1], &str);
49 pCtx->LocalToString(params[2], &substr);
51 func = (params[3]) ? _strstr : stristr;
52 const char *pos = func(str, substr);
61 static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params)
63 typedef int (*STRCOMPARE)(const char *, const char *);
67 pCtx->LocalToString(params[1], &str1);
68 pCtx->LocalToString(params[2], &str2);
70 func = (params[3]) ? strcmp : stricmp;
72 return (func(str1, str2));
75 static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
79 pCtx->LocalToString(params[1], &dest);
80 pCtx->LocalToString(params[3], &src);
82 return strncopy(dest, src, params[2]);
85 static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params)
88 pCtx->LocalToString(params[1], &str);
90 return static_cast<cell_t>(strtol(str, &dummy, params[2]));
93 static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
96 pCtx->LocalToString(params[2], &str);
97 size_t res = UTIL_Format(str, params[3], "%d", params[1]);
99 return static_cast<cell_t>(res);
102 static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
105 pCtx->LocalToString(params[1], &str);
107 float val = (float)strtod(str, &dummy);
112 static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
115 pCtx->LocalToString(params[2], &str);
116 size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
118 return static_cast<cell_t>(res);
121 static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
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);
131 return static_cast<cell_t>(res);
134 static char g_formatbuf[2048];
135 static cell_t sm_format(IPluginContext *pCtx, const cell_t *params)
137 char *buf, *fmt, *destbuf;
138 cell_t start_addr, end_addr, maxparam;
143 pCtx->LocalToString(params[1], &destbuf);
144 pCtx->LocalToString(params[3], &fmt);
146 maxlen = static_cast<size_t>(params[2]);
147 start_addr = params[1];
148 end_addr = params[1] + maxlen;
149 maxparam = params[0];
151 for (cell_t i=3; i<=maxparam; i++)
153 if ((params[i] >= start_addr) && (params[i] <= end_addr))
159 buf = (copy) ? g_formatbuf : destbuf;
160 res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg);
164 memcpy(destbuf, g_formatbuf, res+1);
167 return static_cast<cell_t>(res);
170 static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
172 int vargPos = static_cast<int>(params[4]);
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)));
178 cell_t max = local_params[0];
179 if (vargPos > (int)max + 1)
181 return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos);
184 cell_t addr_start = params[1];
185 cell_t addr_end = addr_start + params[2];
187 for (int i=vargPos; i<=max; i++)
189 /* Does this clip bounds? */
190 if ((local_params[i] >= addr_start)
191 && (local_params[i] <= addr_end))
198 /* Get destination info */
199 char *format, *destination;
200 size_t maxlen = static_cast<size_t>(params[2]);
204 destination = g_formatbuf;
206 pContext->LocalToString(params[1], &destination);
209 pContext->LocalToString(params[3], &format);
211 size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos);
213 /* Perform copy-on-write if we need to */
216 pContext->StringToLocal(params[1], maxlen, g_formatbuf);
222 REGISTER_NATIVES(basicstrings)
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},