dvander@370: /** dvander@370: * =============================================================== dvander@370: * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. dvander@370: * =============================================================== dvander@370: * dvander@370: * This file is not open source and may not be copied without explicit dvander@370: * written permission of AlliedModders LLC. This file may not be redistributed dvander@370: * in whole or significant part. dvander@370: * For information, see LICENSE.txt or http://www.sourcemod.net/license.php dvander@370: * dvander@370: * Version: $Id$ dvander@370: */ dvander@370: faluco@225: #include dvander@233: #include dvander@233: #include "sm_globals.h" faluco@230: #include "sm_stringutil.h" faluco@225: faluco@225: inline const char *_strstr(const char *str, const char *substr) faluco@225: { faluco@225: #ifdef PLATFORM_WINDOWS faluco@225: return strstr(str, substr); dvander@351: #elif defined PLATFORM_LINUX faluco@225: return (const char *)strstr(str, substr); faluco@225: #endif faluco@225: } faluco@225: faluco@225: /********************************************* faluco@225: * * faluco@225: * STRING MANIPULATION NATIVE IMPLEMENTATIONS * faluco@225: * * faluco@225: *********************************************/ faluco@225: faluco@225: static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params) faluco@225: { faluco@225: char *str; faluco@225: pCtx->LocalToString(params[1], &str); faluco@225: faluco@225: return strlen(str); faluco@225: } faluco@225: faluco@225: static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params) faluco@225: { faluco@225: typedef const char *(*STRSEARCH)(const char *, const char *); faluco@225: STRSEARCH func; faluco@225: char *str, *substr; faluco@225: faluco@225: pCtx->LocalToString(params[1], &str); faluco@225: pCtx->LocalToString(params[2], &substr); faluco@225: faluco@225: func = (params[3]) ? _strstr : stristr; faluco@225: const char *pos = func(str, substr); faluco@225: if (pos) faluco@225: { faluco@225: return (pos - str); faluco@225: } faluco@225: faluco@225: return -1; faluco@225: } faluco@225: dvander@233: static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params) faluco@225: { faluco@225: typedef int (*STRCOMPARE)(const char *, const char *); faluco@225: STRCOMPARE func; faluco@225: char *str1, *str2; faluco@225: faluco@225: pCtx->LocalToString(params[1], &str1); faluco@225: pCtx->LocalToString(params[2], &str2); faluco@225: faluco@225: func = (params[3]) ? strcmp : stricmp; faluco@225: dvander@233: return (func(str1, str2)); faluco@225: } faluco@225: faluco@225: static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params) faluco@225: { faluco@230: char *dest, *src; faluco@225: faluco@225: pCtx->LocalToString(params[1], &dest); faluco@225: pCtx->LocalToString(params[3], &src); faluco@225: faluco@230: return strncopy(dest, src, params[2]); faluco@225: } faluco@226: dvander@233: static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params) faluco@226: { dvander@233: char *str, *dummy; faluco@226: pCtx->LocalToString(params[1], &str); faluco@226: dvander@233: return static_cast(strtol(str, &dummy, params[2])); faluco@226: } faluco@226: faluco@226: static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params) faluco@226: { faluco@226: char *str; faluco@226: pCtx->LocalToString(params[2], &str); faluco@274: size_t res = UTIL_Format(str, params[3], "%d", params[1]); faluco@226: faluco@274: return static_cast(res); faluco@226: } faluco@226: faluco@226: static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params) faluco@226: { dvander@233: char *str, *dummy; faluco@226: pCtx->LocalToString(params[1], &str); faluco@226: dvander@233: float val = (float)strtod(str, &dummy); dvander@233: dvander@233: return sp_ftoc(val); faluco@226: } faluco@226: faluco@226: static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params) faluco@226: { faluco@226: char *str; faluco@226: pCtx->LocalToString(params[2], &str); faluco@274: size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1])); faluco@226: faluco@274: return static_cast(res); faluco@226: } dvander@233: faluco@236: static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params) faluco@236: { faluco@236: char *buf, *fmt; faluco@236: size_t res; faluco@236: int arg = 4; faluco@236: faluco@236: pCtx->LocalToString(params[1], &buf); faluco@236: pCtx->LocalToString(params[3], &fmt); faluco@236: res = atcprintf(buf, static_cast(params[2]), fmt, pCtx, params, &arg); faluco@236: faluco@236: return static_cast(res); faluco@236: } faluco@236: faluco@236: static char g_formatbuf[2048]; faluco@236: static cell_t sm_format(IPluginContext *pCtx, const cell_t *params) faluco@236: { faluco@236: char *buf, *fmt, *destbuf; faluco@236: cell_t start_addr, end_addr, maxparam; faluco@236: size_t res, maxlen; faluco@236: int arg = 4; faluco@236: bool copy = false; faluco@236: faluco@236: pCtx->LocalToString(params[1], &destbuf); faluco@236: pCtx->LocalToString(params[3], &fmt); faluco@236: faluco@236: maxlen = static_cast(params[2]); faluco@236: start_addr = params[1]; faluco@236: end_addr = params[1] + maxlen; faluco@236: maxparam = params[0]; faluco@236: faluco@236: for (cell_t i=3; i<=maxparam; i++) faluco@236: { faluco@236: if ((params[i] >= start_addr) && (params[i] <= end_addr)) faluco@236: { faluco@236: copy = true; faluco@236: break; faluco@236: } faluco@236: } faluco@236: buf = (copy) ? g_formatbuf : destbuf; faluco@236: res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg); faluco@236: faluco@236: if (copy) faluco@236: { faluco@236: memcpy(destbuf, g_formatbuf, res+1); faluco@236: } faluco@236: faluco@236: return static_cast(res); faluco@236: } faluco@236: dvander@411: static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params) dvander@411: { dvander@411: int vargPos = static_cast(params[4]); dvander@411: dvander@411: /* Get the parent parameter array */ dvander@411: sp_context_t *ctx = pContext->GetContext(); dvander@411: cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t))); dvander@411: dvander@411: cell_t max = local_params[0]; dvander@411: if (vargPos > (int)max + 1) dvander@411: { dvander@411: return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos); dvander@411: } dvander@411: dvander@411: cell_t addr_start = params[1]; dvander@411: cell_t addr_end = addr_start + params[2]; dvander@411: bool copy = false; dvander@411: for (int i=vargPos; i<=max; i++) dvander@411: { dvander@411: /* Does this clip bounds? */ dvander@411: if ((local_params[i] >= addr_start) dvander@411: && (local_params[i] <= addr_end)) dvander@411: { dvander@411: copy = true; dvander@411: break; dvander@411: } dvander@411: } dvander@411: dvander@411: /* Get destination info */ dvander@411: char *format, *destination; dvander@411: size_t maxlen = static_cast(params[2]); dvander@411: dvander@411: if (copy) dvander@411: { dvander@411: destination = g_formatbuf; dvander@411: } else { dvander@411: pContext->LocalToString(params[1], &destination); dvander@411: } dvander@411: dvander@411: pContext->LocalToString(params[3], &format); dvander@411: dvander@411: size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos); dvander@411: dvander@411: /* Perform copy-on-write if we need to */ dvander@411: if (copy) dvander@411: { dvander@411: pContext->StringToLocal(params[1], maxlen, g_formatbuf); dvander@411: } dvander@411: dvander@411: return total; dvander@411: } dvander@411: dvander@233: REGISTER_NATIVES(basicstrings) dvander@233: { dvander@233: {"strlen", sm_strlen}, dvander@233: {"StrContains", sm_contain}, dvander@233: {"StrCompare", sm_strcmp}, dvander@233: {"StrCopy", sm_strcopy}, dvander@233: {"StringToInt", sm_strconvint}, dvander@233: {"IntToString", sm_numtostr}, dvander@233: {"StringToFloat", sm_strtofloat}, dvander@233: {"FloatToString", sm_floattostr}, dvander@255: {"Format", sm_format}, dvander@255: {"FormatEx", sm_formatex}, dvander@411: {"VFormat", sm_vformat}, dvander@233: {NULL, NULL}, dvander@233: };