More consistency of some sort...
Oh god, what has possessed me to do this?
3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
17 #include "sm_globals.h"
18 #include "sm_stringutil.h"
19 #include "TextParsers.h"
21 inline const char *_strstr(const char *str, const char *substr)
23 #ifdef PLATFORM_WINDOWS
24 return strstr(str, substr);
25 #elif defined PLATFORM_LINUX
26 return (const char *)strstr(str, substr);
30 /*********************************************
32 * STRING MANIPULATION NATIVE IMPLEMENTATIONS *
34 *********************************************/
36 static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params)
39 pCtx->LocalToString(params[1], &str);
44 static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params)
46 typedef const char *(*STRSEARCH)(const char *, const char *);
50 pCtx->LocalToString(params[1], &str);
51 pCtx->LocalToString(params[2], &substr);
53 func = (params[3]) ? _strstr : stristr;
54 const char *pos = func(str, substr);
63 static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params)
65 typedef int (*STRCOMPARE)(const char *, const char *);
69 pCtx->LocalToString(params[1], &str1);
70 pCtx->LocalToString(params[2], &str2);
72 func = (params[3]) ? strcmp : stricmp;
74 return (func(str1, str2));
77 static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
81 pCtx->LocalToString(params[1], &dest);
82 pCtx->LocalToString(params[3], &src);
84 return strncopy(dest, src, params[2]);
87 static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params)
90 pCtx->LocalToString(params[1], &str);
92 return static_cast<cell_t>(strtol(str, &dummy, params[2]));
95 static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
98 pCtx->LocalToString(params[2], &str);
99 size_t res = UTIL_Format(str, params[3], "%d", params[1]);
101 return static_cast<cell_t>(res);
104 static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
107 pCtx->LocalToString(params[1], &str);
109 float val = (float)strtod(str, &dummy);
114 static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
117 pCtx->LocalToString(params[2], &str);
118 size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
120 return static_cast<cell_t>(res);
123 static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
129 pCtx->LocalToString(params[1], &buf);
130 pCtx->LocalToString(params[3], &fmt);
131 res = atcprintf(buf, static_cast<size_t>(params[2]), fmt, pCtx, params, &arg);
133 return static_cast<cell_t>(res);
136 static char g_formatbuf[2048];
137 static cell_t sm_format(IPluginContext *pCtx, const cell_t *params)
139 char *buf, *fmt, *destbuf;
140 cell_t start_addr, end_addr, maxparam;
145 pCtx->LocalToString(params[1], &destbuf);
146 pCtx->LocalToString(params[3], &fmt);
148 maxlen = static_cast<size_t>(params[2]);
149 start_addr = params[1];
150 end_addr = params[1] + maxlen;
151 maxparam = params[0];
153 for (cell_t i=3; i<=maxparam; i++)
155 if ((params[i] >= start_addr) && (params[i] <= end_addr))
161 buf = (copy) ? g_formatbuf : destbuf;
162 res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg);
166 memcpy(destbuf, g_formatbuf, res+1);
169 return static_cast<cell_t>(res);
172 static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
174 int vargPos = static_cast<int>(params[4]);
176 /* Get the parent parameter array */
177 sp_context_t *ctx = pContext->GetContext();
178 cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
180 cell_t max = local_params[0];
181 if (vargPos > (int)max + 1)
183 return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos);
186 cell_t addr_start = params[1];
187 cell_t addr_end = addr_start + params[2];
189 for (int i=vargPos; i<=max; i++)
191 /* Does this clip bounds? */
192 if ((local_params[i] >= addr_start)
193 && (local_params[i] <= addr_end))
200 /* Get destination info */
201 char *format, *destination;
202 size_t maxlen = static_cast<size_t>(params[2]);
206 destination = g_formatbuf;
208 pContext->LocalToString(params[1], &destination);
211 pContext->LocalToString(params[3], &format);
213 size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos);
215 /* Perform copy-on-write if we need to */
218 pContext->StringToLocal(params[1], maxlen, g_formatbuf);
224 /* :TODO: make this UTF8 safe */
225 static cell_t StrBreak(IPluginContext *pContext, const cell_t *params)
232 pContext->LocalToString(params[1], (char **)&input);
233 pContext->LocalToString(params[2], &out);
236 const char *inptr = input;
237 /* Eat up whitespace */
238 while (*inptr != '\0' && IsWhitespace(inptr))
252 const char *start, *end = NULL;
254 bool quoted = (*inptr == '"');
259 /* Read input until we reach a quote. */
260 while (*inptr != '\0' && *inptr != '"')
262 /* Update the end point, increment the stream. */
265 /* Read one more token if we reached an end quote */
272 /* Read input until we reach a space */
273 while (*inptr != '\0' && !IsWhitespace(inptr))
275 /* Update the end point, increment the stream. */
280 /* Copy the string we found, if necessary */
290 for (const char *ptr=start;
291 (ptr <= end) && ((unsigned)(outptr - out) < (outMax));
299 /* Consume more of the string until we reach non-whitespace */
300 while (*inptr != '\0' && IsWhitespace(inptr))
310 return inptr - input;
313 REGISTER_NATIVES(basicStrings)
315 {"strlen", sm_strlen},
316 {"StrBreak", StrBreak},
317 {"StrContains", sm_contain},
318 {"StrCompare", sm_strcmp},
319 {"StrCopy", sm_strcopy},
320 {"StringToInt", sm_strconvint},
321 {"IntToString", sm_numtostr},
322 {"StringToFloat", sm_strtofloat},
323 {"FloatToString", sm_floattostr},
324 {"Format", sm_format},
325 {"FormatEx", sm_formatex},
326 {"VFormat", sm_vformat},