diff -r 7602d7fb60d9 -r 026da5437111 core/smn_string.cpp --- a/core/smn_string.cpp Fri Jul 11 06:51:21 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,622 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include -#include -#include "sm_globals.h" -#include "sm_stringutil.h" -#include -#include - -inline const char *_strstr(const char *str, const char *substr) -{ -#ifdef PLATFORM_WINDOWS - return strstr(str, substr); -#elif defined PLATFORM_LINUX - return (const char *)strstr(str, substr); -#endif -} - -/********************************************* -* * -* STRING MANIPULATION NATIVE IMPLEMENTATIONS * -* * -*********************************************/ - -static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params) -{ - char *str; - pCtx->LocalToString(params[1], &str); - - return strlen(str); -} - -static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params) -{ - typedef const char *(*STRSEARCH)(const char *, const char *); - STRSEARCH func; - char *str, *substr; - - pCtx->LocalToString(params[1], &str); - pCtx->LocalToString(params[2], &substr); - - func = (params[3]) ? _strstr : stristr; - const char *pos = func(str, substr); - if (pos) - { - return (pos - str); - } - - return -1; -} - -static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params) -{ - typedef int (*STRCOMPARE)(const char *, const char *); - STRCOMPARE func; - char *str1, *str2; - - pCtx->LocalToString(params[1], &str1); - pCtx->LocalToString(params[2], &str2); - - func = (params[3]) ? strcmp : stricmp; - - return (func(str1, str2)); -} - -static cell_t sm_strncmp(IPluginContext *pCtx, const cell_t *params) -{ - char *str1, *str2; - - pCtx->LocalToString(params[1], &str1); - pCtx->LocalToString(params[2], &str2); - - if (params[4]) - { - return strncmp(str1, str2, (size_t)params[3]); - } else { - return strncasecmp(str1, str2, (size_t)params[3]); - } -} - -static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params) -{ - char *dest, *src; - - pCtx->LocalToString(params[1], &dest); - pCtx->LocalToString(params[3], &src); - - return strncopy(dest, src, params[2]); -} - -static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params) -{ - char *str, *dummy; - pCtx->LocalToString(params[1], &str); - - return static_cast(strtol(str, &dummy, params[2])); -} - -static cell_t StringToIntEx(IPluginContext *pCtx, const cell_t *params) -{ - char *str, *dummy = NULL; - cell_t *addr; - pCtx->LocalToString(params[1], &str); - pCtx->LocalToPhysAddr(params[2], &addr); - - *addr = static_cast(strtol(str, &dummy, params[3])); - - return dummy - str; -} - -static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params) -{ - char *str; - pCtx->LocalToString(params[2], &str); - size_t res = UTIL_Format(str, params[3], "%d", params[1]); - - return static_cast(res); -} - -static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params) -{ - char *str, *dummy; - pCtx->LocalToString(params[1], &str); - - float val = (float)strtod(str, &dummy); - - return sp_ftoc(val); -} - -static cell_t StringToFloatEx(IPluginContext *pCtx, const cell_t *params) -{ - char *str, *dummy = NULL; - cell_t *addr; - pCtx->LocalToString(params[1], &str); - pCtx->LocalToPhysAddr(params[2], &addr); - - float val = (float)strtod(str, &dummy); - - *addr = sp_ftoc(val); - - return dummy - str; -} - -static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params) -{ - char *str; - pCtx->LocalToString(params[2], &str); - size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1])); - - return static_cast(res); -} - -static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params) -{ - char *buf, *fmt; - size_t res; - int arg = 4; - - pCtx->LocalToString(params[1], &buf); - pCtx->LocalToString(params[3], &fmt); - res = atcprintf(buf, static_cast(params[2]), fmt, pCtx, params, &arg); - - return static_cast(res); -} - -static char g_formatbuf[2048]; -static cell_t sm_format(IPluginContext *pCtx, const cell_t *params) -{ - char *buf, *fmt, *destbuf; - cell_t start_addr, end_addr, maxparam; - size_t res, maxlen; - int arg = 4; - bool copy = false; - - pCtx->LocalToString(params[1], &destbuf); - pCtx->LocalToString(params[3], &fmt); - - maxlen = static_cast(params[2]); - start_addr = params[1]; - end_addr = params[1] + maxlen; - maxparam = params[0]; - - for (cell_t i=3; i<=maxparam; i++) - { - if ((params[i] >= start_addr) && (params[i] <= end_addr)) - { - copy = true; - break; - } - } - buf = (copy) ? g_formatbuf : destbuf; - res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg); - - if (copy) - { - memcpy(destbuf, g_formatbuf, res+1); - } - - return static_cast(res); -} - -static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params) -{ - int vargPos = static_cast(params[4]); - - /* Get the parent parameter array */ - cell_t *local_params = pContext->GetLocalParams(); - - cell_t max = local_params[0]; - if (vargPos > (int)max + 1) - { - return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos); - } - - cell_t addr_start = params[1]; - cell_t addr_end = addr_start + params[2]; - bool copy = false; - for (int i=vargPos; i<=max; i++) - { - /* Does this clip bounds? */ - if ((local_params[i] >= addr_start) - && (local_params[i] <= addr_end)) - { - copy = true; - break; - } - } - - /* Get destination info */ - char *format, *destination; - size_t maxlen = static_cast(params[2]); - - if (copy) - { - destination = g_formatbuf; - } else { - pContext->LocalToString(params[1], &destination); - } - - pContext->LocalToString(params[3], &format); - - size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos); - - /* Perform copy-on-write if we need to */ - if (copy) - { - pContext->StringToLocal(params[1], maxlen, g_formatbuf); - } - - return total; -} - -/* :TODO: make this UTF8 safe */ -static cell_t BreakString(IPluginContext *pContext, const cell_t *params) -{ - const char *input; - char *out; - size_t outMax; - - /* Get parameters */ - pContext->LocalToString(params[1], (char **)&input); - pContext->LocalToString(params[2], &out); - outMax = params[3]; - - const char *inptr = input; - /* Eat up whitespace */ - while (*inptr != '\0' && textparsers->IsWhitespace(inptr)) - { - inptr++; - } - - if (*inptr == '\0') - { - if (outMax) - { - *out = '\0'; - } - return -1; - } - - const char *start, *end = NULL; - - bool quoted = (*inptr == '"'); - if (quoted) - { - inptr++; - start = inptr; - /* Read input until we reach a quote. */ - while (*inptr != '\0' && *inptr != '"') - { - /* Update the end point, increment the stream. */ - end = inptr++; - } - /* Read one more token if we reached an end quote */ - if (*inptr == '"') - { - inptr++; - } - } else { - start = inptr; - /* Read input until we reach a space */ - while (*inptr != '\0' && !textparsers->IsWhitespace(inptr)) - { - /* Update the end point, increment the stream. */ - end = inptr++; - } - } - - /* Copy the string we found, if necessary */ - if (end == NULL) - { - if (outMax) - { - *out = '\0'; - } - } else if (outMax) { - char *outptr = out; - outMax--; - for (const char *ptr=start; - (ptr <= end) && ((unsigned)(outptr - out) < (outMax)); - ptr++, outptr++) - { - *outptr = *ptr; - } - *outptr = '\0'; - } - - /* Consume more of the string until we reach non-whitespace */ - while (*inptr != '\0' && textparsers->IsWhitespace(inptr)) - { - inptr++; - } - - if (*inptr == '\0') - { - return -1; - } - - return inptr - input; -} - -static cell_t GetCharBytes(IPluginContext *pContext, const cell_t *params) -{ - char *str; - pContext->LocalToString(params[1], &str); - - return _GetUTF8CharBytes(str); -}; - -static cell_t IsCharAlpha(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - if (_GetUTF8CharBytes(&chr) != 1) - { - return 0; - } - - return isalpha(chr); -} - -static cell_t IsCharNumeric(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - if (_GetUTF8CharBytes(&chr) != 1) - { - return 0; - } - - return isdigit(chr); -} - -static cell_t IsCharSpace(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - if (_GetUTF8CharBytes(&chr) != 1) - { - return 0; - } - - return isspace(chr); -} - -static cell_t IsCharMB(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - unsigned int bytes = _GetUTF8CharBytes(&chr); - if (bytes == 1) - { - return 0; - } - - return bytes; -} - -static cell_t IsCharUpper(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - if (_GetUTF8CharBytes(&chr) != 1) - { - return 0; - } - - return isupper(chr); -} - -static cell_t IsCharLower(IPluginContext *pContext, const cell_t *params) -{ - char chr = params[1]; - - if (_GetUTF8CharBytes(&chr) != 1) - { - return 0; - } - - return islower(chr); -} - -static cell_t ReplaceString(IPluginContext *pContext, const cell_t *params) -{ - char *text, *search, *replace; - size_t maxlength; - - pContext->LocalToString(params[1], &text); - pContext->LocalToString(params[3], &search); - pContext->LocalToString(params[4], &replace); - maxlength = (size_t)params[2]; - - if (search[0] == '\0') - { - return pContext->ThrowNativeError("Cannot replace searches of empty strings"); - } - - return UTIL_ReplaceAll(text, maxlength, search, replace); -} - -static cell_t ReplaceStringEx(IPluginContext *pContext, const cell_t *params) -{ - char *text, *search, *replace; - size_t maxlength; - - pContext->LocalToString(params[1], &text); - pContext->LocalToString(params[3], &search); - pContext->LocalToString(params[4], &replace); - maxlength = (size_t)params[2]; - - size_t searchLen = (params[5] == -1) ? strlen(search) : (size_t)params[5]; - size_t replaceLen = (params[6] == -1) ? strlen(replace) : (size_t)params[6]; - - if (searchLen == 0) - { - return pContext->ThrowNativeError("Cannot replace searches of empty strings"); - } - - char *ptr = UTIL_ReplaceEx(text, maxlength, search, searchLen, replace, replaceLen); - - if (ptr == NULL) - { - return -1; - } - - return ptr - text; -} - -static cell_t TrimString(IPluginContext *pContext, const cell_t *params) -{ - char *str; - pContext->LocalToString(params[1], &str); - - size_t chars = strlen(str); - - if (chars == 0) - { - return 0; - } - - char *end = str + chars - 1; - - /* Iterate backwards through string until we reach first non-whitespace char */ - while (end >= str && textparsers->IsWhitespace(end)) - { - end--; - } - - /* Replace first whitespace char (at the end) with null terminator */ - *(end + 1) = '\0'; - - /* Iterate forwards through string until first non-whitespace char is reached */ - while (textparsers->IsWhitespace(str)) - { - str++; - } - - size_t bytes; - pContext->StringToLocalUTF8(params[1], chars + 1, str, &bytes); - - return bytes; -} - -static cell_t SplitString(IPluginContext *pContext, const cell_t *params) -{ - char *text, *split; - - pContext->LocalToString(params[1], &text); - pContext->LocalToString(params[2], &split); - - size_t maxLen = (size_t)params[4]; - size_t textLen = strlen(text); - size_t splitLen = strlen(split); - - if (splitLen > textLen) - { - return -1; - } - - /** - * Note that it's <= ... you could also just add 1, - * but this is a bit nicer - */ - for (size_t i=0; i<=textLen - splitLen; i++) - { - if (strncmp(&text[i], split, splitLen) == 0) - { - /* Split hereeeee */ - if (i >= maxLen) - { - pContext->StringToLocalUTF8(params[3], maxLen, text, NULL); - } else { - pContext->StringToLocalUTF8(params[3], i+1, text, NULL); - } - return (cell_t)(i + splitLen); - } - } - - return -1; -} - -static cell_t StripQuotes(IPluginContext *pContext, const cell_t *params) -{ - char *text; - size_t length; - - pContext->LocalToString(params[1], &text); - length = strlen(text); - - if (text[0] == '"' && text[length-1] == '"') - { - /* Null-terminate */ - text[--length] = '\0'; - /* Move the remaining bytes (including null terminator) down by one */ - memmove(&text[0], &text[1], length); - - return 1; - } - - return 0; -} - -REGISTER_NATIVES(basicStrings) -{ - {"BreakString", BreakString}, - {"FloatToString", sm_floattostr}, - {"Format", sm_format}, - {"FormatEx", sm_formatex}, - {"GetCharBytes", GetCharBytes}, - {"IntToString", sm_numtostr}, - {"IsCharAlpha", IsCharAlpha}, - {"IsCharLower", IsCharLower}, - {"IsCharMB", IsCharMB}, - {"IsCharNumeric", IsCharNumeric}, - {"IsCharSpace", IsCharSpace}, - {"IsCharUpper", IsCharUpper}, - {"ReplaceString", ReplaceString}, - {"ReplaceStringEx", ReplaceStringEx}, - {"SplitString", SplitString}, - {"strlen", sm_strlen}, - {"StrContains", sm_contain}, - {"strcmp", sm_strcmp}, - {"strncmp", sm_strncmp}, - {"strcopy", sm_strcopy}, - {"StringToInt", sm_strconvint}, - {"StringToIntEx", StringToIntEx}, - {"StringToFloat", sm_strtofloat}, - {"StringToFloatEx", StringToFloatEx}, - {"StripQuotes", StripQuotes}, - {"TrimString", TrimString}, - {"VFormat", sm_vformat}, - {NULL, NULL}, -};