Initial revision
This commit is contained in:
541
amxmodx/string.cpp
Executable file
541
amxmodx/string.cpp
Executable file
@ -0,0 +1,541 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2003 Aleksander Naszko
|
||||
*
|
||||
* This file is part of AMX Mod.
|
||||
*
|
||||
* AMX Mod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* AMX Mod 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 AMX Mod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h>
|
||||
#include <meta_api.h>
|
||||
#include <ctype.h>
|
||||
#include "amxmod.h"
|
||||
|
||||
const char* stristr(const char* str,const char* substr)
|
||||
{
|
||||
register char *needle = (char *)substr;
|
||||
register char *prevloc = (char *)str;
|
||||
register char *haystack = (char *)str;
|
||||
|
||||
while (*haystack) {
|
||||
if (tolower(*haystack) == tolower(*needle)) {
|
||||
haystack++;
|
||||
if (!*++needle)
|
||||
return prevloc;
|
||||
}
|
||||
else {
|
||||
haystack = ++prevloc;
|
||||
needle = (char *)substr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* format_amxstring(AMX *amx, cell *params, int parm,int& len)
|
||||
{
|
||||
static char buffer[2][3072];
|
||||
static char format[16];
|
||||
char *ptr,*arg;
|
||||
char *dest = *buffer;
|
||||
cell *src = get_amxaddr(amx, params[parm++]);
|
||||
int numparam = *params/sizeof(cell);
|
||||
while(*src) {
|
||||
if (*src=='%'&&*(src+1)) {
|
||||
ptr = format;
|
||||
*ptr++ = *src++;
|
||||
if (*src=='%'){
|
||||
*dest++=*src++;
|
||||
continue;
|
||||
}
|
||||
while (!isalpha(*ptr++=*src++))
|
||||
;
|
||||
*ptr=0;
|
||||
if (numparam < parm) continue;
|
||||
arg = buffer[1];
|
||||
switch(*(ptr-1)){
|
||||
case 's': sprintf(arg,format,get_amxstring(amx, params[parm++],2,len)); break;
|
||||
case 'f': case 'g': sprintf(arg,format,*(float*)get_amxaddr(amx, params[parm++])); break;
|
||||
default: sprintf(arg,format,(int)*get_amxaddr(amx, params[parm++]));
|
||||
}
|
||||
while(*arg) *dest++=*arg++;
|
||||
continue;
|
||||
}
|
||||
*dest++=*src++;
|
||||
|
||||
}
|
||||
*dest=0;
|
||||
len = dest - *buffer;
|
||||
return *buffer;
|
||||
}
|
||||
|
||||
int amxstring_len(cell* a)
|
||||
{
|
||||
register int c = 0;
|
||||
|
||||
while( a[ c ] )
|
||||
++c;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
cell* get_amxaddr(AMX *amx,cell amx_addr)
|
||||
{
|
||||
return (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||
}
|
||||
|
||||
int set_amxstring(AMX *amx,cell amx_addr,const char *source,int max)
|
||||
{
|
||||
cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||
cell* start = dest;
|
||||
while (max--&&*source)
|
||||
*dest++=(cell)*source++;
|
||||
*dest = 0;
|
||||
return dest-start;
|
||||
}
|
||||
|
||||
char* get_amxstring(AMX *amx,cell amx_addr,int id, int& len)
|
||||
{
|
||||
static char buffor[4][3072];
|
||||
register cell* source = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||
register char* dest = buffor[id];
|
||||
char* start = dest;
|
||||
while (*dest++=(char)*source++)
|
||||
;
|
||||
len = --dest - start;
|
||||
return start;
|
||||
}
|
||||
|
||||
void copy_amxmemory(cell* dest,cell* src,int len)
|
||||
{
|
||||
while (len--)
|
||||
*dest++=*src++;
|
||||
}
|
||||
|
||||
|
||||
char* parse_arg(char** line,int& state)
|
||||
{
|
||||
static char arg[3072];
|
||||
char* dest = arg;
|
||||
state = 0;
|
||||
while(**line) {
|
||||
if ( isspace(**line) ) {
|
||||
if (state == 1)
|
||||
break;
|
||||
else if (!state) {
|
||||
(*line)++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (state != 2)
|
||||
state = 1;
|
||||
if (**line=='"') {
|
||||
(*line)++;
|
||||
if (state == 2)
|
||||
break;
|
||||
state = 2;
|
||||
continue;
|
||||
}
|
||||
*dest++ = *(*line)++;
|
||||
}
|
||||
*dest = '\0';
|
||||
return arg;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL replace(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
static char buffor[3072];
|
||||
cell *a = get_amxaddr(amx,params[1]);
|
||||
cell *b = get_amxaddr(amx,params[3]);
|
||||
cell *c = get_amxaddr(amx,params[4]);
|
||||
int iMain = amxstring_len(a);
|
||||
int iWhat = amxstring_len(b);
|
||||
int iWith = amxstring_len(c);
|
||||
int iPot = iMain + iWith - iWhat;
|
||||
if (iPot>=params[2]){
|
||||
amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
}
|
||||
char *d = buffor;
|
||||
cell *x, *y, *z = a, *l = a;
|
||||
int p = 0;
|
||||
while(*a){
|
||||
if (*a==*b){
|
||||
x=a+1;
|
||||
y=b+1;
|
||||
p=1;
|
||||
if (!*y) break;
|
||||
while(*x==*y){
|
||||
x++; y++; p++;
|
||||
if (!*y) break;
|
||||
}
|
||||
if (!*y) break;
|
||||
p = 0;
|
||||
*d++=(char)*a++;
|
||||
continue;
|
||||
}
|
||||
*d++=(char)*a++;
|
||||
}
|
||||
if (p){
|
||||
while(*c) *d++=(char)*c++;
|
||||
a+=p;
|
||||
while(*a) *d++=(char)*a++;
|
||||
*d=0;
|
||||
d = buffor;
|
||||
while(*d) *z++=*d++;
|
||||
*z=0;
|
||||
return (z-l);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL contain(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
register cell *a = get_amxaddr(amx,params[2]);
|
||||
register cell *b = get_amxaddr(amx,params[1]);
|
||||
register cell *c = b;
|
||||
cell* str = b;
|
||||
cell* substr = a;
|
||||
while (*c) {
|
||||
if (*c == *a) {
|
||||
c++;
|
||||
if (!*++a)
|
||||
return b - str;
|
||||
}
|
||||
else {
|
||||
c = ++b;
|
||||
a = substr;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL containi(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
register cell *a = get_amxaddr(amx,params[2]);
|
||||
register cell *b = get_amxaddr(amx,params[1]);
|
||||
register cell *c = b;
|
||||
cell* str = b;
|
||||
cell* substr = a;
|
||||
while (*c) {
|
||||
if (tolower(*c) == tolower(*a)) {
|
||||
c++;
|
||||
if (!*++a)
|
||||
return b - str;
|
||||
}
|
||||
else {
|
||||
c = ++b;
|
||||
a = substr;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL strtonum(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
int iLen;
|
||||
return atoi(get_amxstring(amx,params[1],0,iLen));
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL numtostr(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
char szTemp[32];
|
||||
sprintf(szTemp,"%d",(int)params[1]);
|
||||
return set_amxstring(amx,params[2],szTemp,params[3]);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL add(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
cell *src = get_amxaddr(amx,params[3]);
|
||||
cell *dest = get_amxaddr(amx,params[1]);
|
||||
cell *start = dest;
|
||||
int c = params[2], d = params[4];
|
||||
while(*dest&&c--)
|
||||
++dest;
|
||||
if (d){
|
||||
while(c--&&d--&&*src)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
return (dest-start);
|
||||
}
|
||||
while(c--&&*src)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
return (dest-start);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL copy(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
cell *src = get_amxaddr(amx,params[3]);
|
||||
cell *dest = get_amxaddr(amx,params[1]);
|
||||
cell *start = dest;
|
||||
int c = params[2];
|
||||
while(c--&&*src)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
return (dest-start);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL copyc(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
cell *src = get_amxaddr(amx,params[3]);
|
||||
cell *dest = get_amxaddr(amx,params[1]);
|
||||
cell *start = dest;
|
||||
int c = params[2];
|
||||
cell ch = params[4];
|
||||
while(c--&&*src&&*src!=ch)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
return (dest-start);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL setc(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
cell *src = get_amxaddr(amx,params[1]);
|
||||
int c = params[2];
|
||||
cell ch = params[3];
|
||||
while(c--)
|
||||
*src++=ch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL equal(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
cell *a = get_amxaddr(amx,params[1]);
|
||||
cell *b = get_amxaddr(amx,params[2]);
|
||||
int c = params[3];
|
||||
if (c) {
|
||||
while (--c&&*a&&(*a==*b))
|
||||
++a, ++b;
|
||||
return (*a-*b)?0:1;
|
||||
}
|
||||
int ret;
|
||||
while(!(ret=*a-*b)&&*b)
|
||||
++a, ++b;
|
||||
return ret?0:1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL equali(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
cell *a = get_amxaddr(amx,params[1]);
|
||||
cell *b = get_amxaddr(amx,params[2]);
|
||||
int f,l, c = params[3];
|
||||
if (c) {
|
||||
do {
|
||||
f = tolower(*a++);
|
||||
l = tolower(*b++);
|
||||
}
|
||||
while (--c &&l&&f&& f==l);
|
||||
return(f - l)?0:1;
|
||||
}
|
||||
do {
|
||||
f = tolower(*a++);
|
||||
l = tolower(*b++);
|
||||
} while (f && f == l);
|
||||
return (f - l)?0:1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL format(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
int len;
|
||||
return set_amxstring(amx,params[1],format_amxstring(amx,params,3,len),params[2]);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL parse(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
int inum = *params/sizeof(cell), iarg = 2, c;
|
||||
char* arg, *parse = get_amxstring(amx,params[1],0,c);
|
||||
cell *cptr;
|
||||
int state;
|
||||
while(*parse){
|
||||
arg = parse_arg(&parse,state);
|
||||
if (state){
|
||||
if (inum <= iarg)
|
||||
return( (iarg-2)>>1 );
|
||||
cptr = get_amxaddr(amx,params[iarg++]);
|
||||
c = *get_amxaddr(amx,params[iarg++]);
|
||||
while(c--&&*arg)
|
||||
*cptr++=(cell)*arg++;
|
||||
*cptr=0;
|
||||
}
|
||||
}
|
||||
|
||||
return( (iarg-2)>>1 );
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL strtolower(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
cell *cptr = get_amxaddr(amx,params[1]);
|
||||
cell *begin = cptr;
|
||||
while(*cptr){
|
||||
*cptr = tolower(*cptr);
|
||||
cptr++;
|
||||
}
|
||||
return cptr - begin;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL strtoupper(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
cell *cptr = get_amxaddr(amx,params[1]);
|
||||
cell *begin = cptr;
|
||||
while(*cptr){
|
||||
*cptr = toupper(*cptr);
|
||||
cptr++;
|
||||
}
|
||||
return cptr - begin;
|
||||
}
|
||||
|
||||
int fo_numargs(AMX *amx)
|
||||
{
|
||||
unsigned char *data =amx->base+(int)((AMX_HEADER *)amx->base)->dat;
|
||||
cell bytes= * (cell *)(data+(int)amx->frm+2*sizeof(cell));
|
||||
return (int)(bytes/sizeof(cell));
|
||||
}
|
||||
|
||||
int fo_getargnum(AMX *amx, int pos)
|
||||
{
|
||||
unsigned char *data =amx->base+(int)((AMX_HEADER *)amx->base)->dat;
|
||||
cell value = * (cell *)(data+(int)amx->frm+(pos+3)*sizeof(cell));
|
||||
return *(cell *)(data+(int)value);
|
||||
}
|
||||
|
||||
float fo_getargfloat(AMX *amx, int pos)
|
||||
{
|
||||
unsigned char *data =amx->base+(int)((AMX_HEADER *)amx->base)->dat;
|
||||
cell value = * (cell *)(data+(int)amx->frm+(pos+3)*sizeof(cell));
|
||||
cell number = *(cell *)(data+(int)value);
|
||||
return *(float *)((void *)&number);
|
||||
}
|
||||
|
||||
char* fo_getargstr(AMX *amx, int swap, int pos)
|
||||
{
|
||||
unsigned char *data =amx->base+(int)((AMX_HEADER *)amx->base)->dat;
|
||||
cell src_value= * (cell *)(data+(int)amx->frm+(pos+3)*sizeof(cell));
|
||||
cell value;
|
||||
static char buffer[2][3072];
|
||||
char* b = buffer[swap];
|
||||
int a = 0;
|
||||
do {
|
||||
value = src_value + a++ * sizeof(cell);
|
||||
value = *(cell *)(data+(int)value);
|
||||
*b++ = value;
|
||||
} while (value);
|
||||
|
||||
return buffer[swap];
|
||||
}
|
||||
|
||||
char* format_arguments(AMX *amx, int parm,int& len)
|
||||
{
|
||||
static char buffer[2][3072];
|
||||
static char format[16];
|
||||
char *ptr,*arg, *dest = *buffer;
|
||||
char *src = fo_getargstr(amx, 0,parm++);
|
||||
int numparam = fo_numargs(amx);
|
||||
while(*src) {
|
||||
if (*src=='%'&&*(src+1)) {
|
||||
ptr = format;
|
||||
*ptr++ = *src++;
|
||||
if (*src=='%'){
|
||||
*dest++=*src++;
|
||||
continue;
|
||||
}
|
||||
while (!isalpha(*ptr++=*src++))
|
||||
;
|
||||
*ptr='\0';
|
||||
if (numparam < parm) continue;
|
||||
arg = buffer[1];
|
||||
switch(*(ptr-1)){
|
||||
case 's': sprintf(arg,format,fo_getargstr(amx,1, parm++)); break;
|
||||
case 'f': case 'g': sprintf(arg,format,fo_getargfloat(amx, parm++)); break;
|
||||
default: sprintf(arg,format,fo_getargnum(amx, parm++));
|
||||
}
|
||||
while(*arg) *dest++=*arg++;
|
||||
continue;
|
||||
}
|
||||
*dest++=*src++;
|
||||
}
|
||||
*dest='\0';
|
||||
len = dest - *buffer;
|
||||
return *buffer;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL format_args(AMX *amx, cell *params)
|
||||
{
|
||||
int len;
|
||||
int pos = params[3];
|
||||
if (pos < 0){
|
||||
amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
}
|
||||
char* string = format_arguments(amx, pos ,len); // indexed from 0
|
||||
return set_amxstring(amx,params[1],string,params[2]);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL is_digit(AMX *amx, cell *params)
|
||||
{
|
||||
return isdigit( params[1] );
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL is_alnum(AMX *amx, cell *params)
|
||||
{
|
||||
return isalnum( params[1] );
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL is_space(AMX *amx, cell *params)
|
||||
{
|
||||
return isspace( params[1] );
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL is_alpha(AMX *amx, cell *params)
|
||||
{
|
||||
return isalpha( params[1] );
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO string_Natives[] = {
|
||||
{ "add", add },
|
||||
{ "contain", contain },
|
||||
{ "containi", containi },
|
||||
{ "copy", copy },
|
||||
{ "copyc", copyc },
|
||||
{ "equal", equal },
|
||||
{ "equali", equali },
|
||||
{ "format", format },
|
||||
{ "format_args", format_args },
|
||||
{ "isdigit", is_digit },
|
||||
{ "isalnum", is_alnum },
|
||||
{ "isspace", is_space },
|
||||
{ "isalpha", is_alpha },
|
||||
{ "numtostr", numtostr },
|
||||
{ "num_to_str", numtostr },
|
||||
{ "parse", parse },
|
||||
{ "replace", replace },
|
||||
{ "setc", setc },
|
||||
{ "strtolower", strtolower },
|
||||
{ "strtonum", strtonum },
|
||||
{ "strtoupper", strtoupper },
|
||||
{ "str_to_num", strtonum },
|
||||
{ NULL, NULL }
|
||||
};
|
Reference in New Issue
Block a user