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},
-};