- Added ToastOfDoom's String Commands Package. (tid:53411, topic:204976)
git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@15039 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
15cba9f33d
commit
ce4717c6a7
@ -6589,6 +6589,193 @@ This function will return 1 if the character number Position in the given string
|
|||||||
is a letter, 0 if it isn't a letter but a digit or a space.
|
is a letter, 0 if it isn't a letter but a digit or a space.
|
||||||
The first letter is position 0.
|
The first letter is position 0.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*charat(<string>,<index>)
|
||||||
|
|
||||||
|
Returns char at specified index. If index is out of range,
|
||||||
|
returns empty string.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
charat("This is a string", 10); //returns "s"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*setchar(<string>,<char>,<index>)
|
||||||
|
|
||||||
|
Returns the original string with the char at the specified
|
||||||
|
index set to the specified char. If index out of range, the
|
||||||
|
original string will be returned.
|
||||||
|
Only the 1st char in the <char> parameter will be used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
setchar("Cat", "B", 0); //returns "Bat"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*insertchar(<string>,<char>,<index>)
|
||||||
|
|
||||||
|
Returns the original string with the specified char inserted
|
||||||
|
at the specified index. If index is out of range, the char
|
||||||
|
will be inserted on the end of the string that it is closest.
|
||||||
|
Only the 1st char in the <char> parameter will be used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
setchar("laughter", "s", 0); //returns "slaughter"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*delchar(<string>,<index>)
|
||||||
|
|
||||||
|
Returns the original string with the char at the specified index
|
||||||
|
removed. If index is out of range, original string will be returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
delchar("Diet", 3); //returns "Die"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*strtoupper(<string>)
|
||||||
|
*strtolower(<string>)
|
||||||
|
|
||||||
|
Returns the specified string in it's uppercase/lowercase form.
|
||||||
|
All non-alpha characters will be preserved
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
strtoupper("The duck is blue!!"); //returns "THE DUCK IS BLUE!!"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*charisupper(<string>,<index>)
|
||||||
|
*charislower(<string>,<index>)
|
||||||
|
|
||||||
|
Returns 1 if character at specified index of specified string is
|
||||||
|
uppercase/lowercase. Otherwise, 0. Characters not of the alphabelt
|
||||||
|
will return 0.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
charisupper("eAthena", 1); //returns 1
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*substr(<string>,<start_index>,<end_index>)
|
||||||
|
|
||||||
|
Returns the sub-string of the specified string inclusively between
|
||||||
|
the set indexes.
|
||||||
|
If indexes are out of range, or the start index is after the end
|
||||||
|
index, an empty string will be returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
substr("foobar", 3, 5); //returns "bar"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*explode(<dest_array>,<string>,<delimiter>)
|
||||||
|
|
||||||
|
Breaks a string up into substrings based on the specified delimiter.
|
||||||
|
Substrings will be stored within the specified string array.
|
||||||
|
Only the 1st char of the delimiter parameter will be used.
|
||||||
|
If an empty string is passed as a delimiter, the string will be placed
|
||||||
|
in the array in it's original form.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
explode(.@my_array$, "Explode:Test:1965:red:PIE", ":");
|
||||||
|
//.@my_array$ contents will be...
|
||||||
|
//.@my_array$[0]: "Explode"
|
||||||
|
//.@my_array$[1]: "Test"
|
||||||
|
//.@my_array$[2]: "1965"
|
||||||
|
//.@my_array$[3]: "red"
|
||||||
|
//.@my_array$[4]: "PIE"
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*implode(<string_array>{,<glue>})
|
||||||
|
|
||||||
|
Combines all substrings within the specified string array into a single string.
|
||||||
|
If the glue parameter is specified, it will be inserted inbetween each substring.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
setarray .@my_array$[0], "This", "is", "a", "test";
|
||||||
|
implode(.@my_array$, " "); //returns "This is a test"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*sprintf(<format>[,param[,param[,...]]]) [Mirei]
|
||||||
|
|
||||||
|
C style sprintf. The resulting string is returned same as in PHP. All C format
|
||||||
|
specifiers are supported except %n. More info: sprintf @ www.cplusplus.com.
|
||||||
|
The number of params is only limited by eA's script engine.
|
||||||
|
|
||||||
|
See thread: http://www.eathena.ws/board/index.php?showtopic=190410
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.@format$ = 'The %s contains %d monkeys';
|
||||||
|
dispbottom(sprintf(.@format$, "zoo", 5)); //prints "The zoo contains 5 monkeys"
|
||||||
|
dispbottom(sprintf(.@format$, "barrel", 82)); //prints "The barrel contains 82 monkeys"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*sscanf(<string>,<format>[,param[,param[,...]]]) [Mirei]
|
||||||
|
|
||||||
|
C style sscanf. All C format specifiers are supported.
|
||||||
|
More info: sscanf @ www.cplusplus.com. The number of params is only limited
|
||||||
|
by eA's script engine.
|
||||||
|
|
||||||
|
See thread: http://www.eathena.ws/board/index.php?showtopic=191157
|
||||||
|
|
||||||
|
Example:
|
||||||
|
sscanf("This is a test: 42 foobar", "This is a test: %d %s", .@num, .@str$);
|
||||||
|
dispbottom(.@num + " " + .@str$); //prints "42 foobar"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*strpos(<haystack>,<needle>{,<offset>})
|
||||||
|
|
||||||
|
PHP style strpos. Finds a substring (needle) within a string (haystack).
|
||||||
|
The offset parameter indicates the index of the string to start searching.
|
||||||
|
Returns index of substring on successful search, else -1.
|
||||||
|
Comparison is case sensitive.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
strpos("foobar", "bar", 0); //returns 3
|
||||||
|
strpos("foobarfoo", "foo", 0); //returns 0
|
||||||
|
strpos("foobarfoo", "foo", 1); //returns 6
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*replacestr(<input>, <search>, <replace>{, <usecase>{, <count>}})
|
||||||
|
|
||||||
|
Replaces all instances of a search string in the input with the specified
|
||||||
|
replacement string. By default is case sensitive unless <usecase> is set
|
||||||
|
to 0. If specified it will only replace as many instances as specified
|
||||||
|
in the count parameter.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
replacestr("testing tester", "test", "dash"); //returns "dashing dasher"
|
||||||
|
replacestr("Donkey", "don", "mon", 0); //returns "monkey"
|
||||||
|
replacestr("test test test test test", "yay", 0, 3); //returns "yay yay yay test test"
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
*countstr(<input>, <search>{, <usecase>})
|
||||||
|
|
||||||
|
Counts all instances of a search string in the input. By default is case
|
||||||
|
sensitive unless <usecase> is set to 0.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
countstr("test test test Test", "test"); //returns 3
|
||||||
|
countstr("cake Cake", "Cake", 0); //returns 2
|
||||||
|
|
||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
*setfont <font>
|
*setfont <font>
|
||||||
|
802
src/map/script.c
802
src/map/script.c
@ -12579,6 +12579,792 @@ BUILDIN_FUNC(charisalpha)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// charisupper <str>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(charisupper)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
int pos = script_getnum(st,3);
|
||||||
|
|
||||||
|
int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISUPPER( str[pos] ) : 0;
|
||||||
|
|
||||||
|
script_pushint(st,val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// charislower <str>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(charislower)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
int pos = script_getnum(st,3);
|
||||||
|
|
||||||
|
int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISLOWER( str[pos] ) : 0;
|
||||||
|
|
||||||
|
script_pushint(st,val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// charat <str>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(charat)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
int pos = script_getnum(st,3);
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
output = (char*)aMallocA(2*sizeof(char));
|
||||||
|
output[0] = '\0';
|
||||||
|
|
||||||
|
if(str && pos >= 0 && (unsigned int)pos < strlen(str))
|
||||||
|
sprintf(output, "%c", str[pos]);
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// setchar <string>, <char>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(setchar)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
const char *c = script_getstr(st,3);
|
||||||
|
int index = script_getnum(st,4);
|
||||||
|
char *output;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
output = (char*)aMallocA(len + 1);
|
||||||
|
memcpy(output, str, len);
|
||||||
|
output[len] = '\0';
|
||||||
|
|
||||||
|
if(index >= 0 && index < len)
|
||||||
|
output[index] = c[0];
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// insertchar <string>, <char>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(insertchar)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
const char *c = script_getstr(st,3);
|
||||||
|
int index = script_getnum(st,4);
|
||||||
|
char *output;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
if(index < 0)
|
||||||
|
index = 0;
|
||||||
|
else if(index > len)
|
||||||
|
index = len;
|
||||||
|
|
||||||
|
output = (char*)aMallocA(len + 2);
|
||||||
|
|
||||||
|
memcpy(output, str, index);
|
||||||
|
output[index] = c[0];
|
||||||
|
memcpy(&output[index+1], &str[index], len - index);
|
||||||
|
output[len+1] = '\0';
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// delchar <string>, <index>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(delchar)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
int index = script_getnum(st,3);
|
||||||
|
char *output;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
if(index < 0 || index > len) {
|
||||||
|
//return original
|
||||||
|
++len;
|
||||||
|
output = (char*)aMallocA(len);
|
||||||
|
memcpy(output, str, len);
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = (char*)aMallocA(len);
|
||||||
|
|
||||||
|
memcpy(output, str, index);
|
||||||
|
memcpy(&output[index], &str[index+1], len - index);
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// strtoupper <str>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(strtoupper)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
char *output;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
output = (char*)aMallocA(strlen(str) + 1);
|
||||||
|
|
||||||
|
while(str[i] != '\0')
|
||||||
|
output[i++] = TOUPPER(str[i]);
|
||||||
|
output[i] = '\0';
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// strtolower <str>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(strtolower)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
char *output;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
output = (char*)aMallocA(strlen(str) + 1);
|
||||||
|
|
||||||
|
while(str[i] != '\0')
|
||||||
|
output[i++] = TOLOWER(str[i]);
|
||||||
|
output[i] = '\0';
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// substr <str>, <start>, <end>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(substr)
|
||||||
|
{
|
||||||
|
const char *str = script_getstr(st,2);
|
||||||
|
char *output;
|
||||||
|
int start = script_getnum(st,3);
|
||||||
|
int end = script_getnum(st,4);
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if(start >= 0 && end < strlen(str) && start <= end) {
|
||||||
|
len = end - start + 1;
|
||||||
|
output = (char*)aMallocA(len + 1);
|
||||||
|
memcpy(output, &str[start], len);
|
||||||
|
} else
|
||||||
|
output = (char*)aMallocA(1);
|
||||||
|
|
||||||
|
output[len] = '\0';
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// explode <dest_string_array>, <str>, <delimiter>
|
||||||
|
// Note: delimiter is limited to 1 char
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(explode)
|
||||||
|
{
|
||||||
|
struct script_data* data = script_getdata(st, 2);
|
||||||
|
const char *str = script_getstr(st,3);
|
||||||
|
const char delimiter = script_getstr(st, 4)[0];
|
||||||
|
int32 id;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
int i = 0, j = 0, k = 0;
|
||||||
|
int start;
|
||||||
|
|
||||||
|
|
||||||
|
char *temp;
|
||||||
|
const char* name;
|
||||||
|
|
||||||
|
TBL_PC* sd = NULL;
|
||||||
|
|
||||||
|
temp = (char*)aMallocA(len + 1);
|
||||||
|
|
||||||
|
if( !data_isreference(data) )
|
||||||
|
{
|
||||||
|
ShowError("script:explode: not a variable\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// not a variable
|
||||||
|
}
|
||||||
|
|
||||||
|
id = reference_getid(data);
|
||||||
|
start = reference_getindex(data);
|
||||||
|
name = reference_getname(data);
|
||||||
|
|
||||||
|
if( not_array_variable(*name) )
|
||||||
|
{
|
||||||
|
ShowError("script:explode: illegal scope\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// not supported
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !is_string_variable(name) )
|
||||||
|
{
|
||||||
|
ShowError("script:explode: not string array\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// data type mismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
if( not_server_variable(*name) )
|
||||||
|
{
|
||||||
|
sd = script_rid2sd(st);
|
||||||
|
if( sd == NULL )
|
||||||
|
return 0;// no player attached
|
||||||
|
}
|
||||||
|
|
||||||
|
while(str[i] != '\0') {
|
||||||
|
if(str[i] == delimiter && start < 127) { //break at delimiter but ignore after reaching last array index
|
||||||
|
temp[j] = '\0';
|
||||||
|
set_reg(st, sd, reference_uid(id, start++), name, (void*)temp, reference_getref(data));
|
||||||
|
j = 0;
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
temp[j++] = str[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//set last string
|
||||||
|
temp[j] = '\0';
|
||||||
|
set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data));
|
||||||
|
|
||||||
|
aFree(temp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// implode <string_array>
|
||||||
|
// implode <string_array>, <glue>
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(implode)
|
||||||
|
{
|
||||||
|
struct script_data* data = script_getdata(st, 2);
|
||||||
|
const char *glue, *name, *temp;
|
||||||
|
int32 glue_len = 0, array_size, id;
|
||||||
|
size_t len = 0;
|
||||||
|
int i, k = 0;
|
||||||
|
|
||||||
|
TBL_PC* sd = NULL;
|
||||||
|
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
if( !data_isreference(data) )
|
||||||
|
{
|
||||||
|
ShowError("script:implode: not a variable\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// not a variable
|
||||||
|
}
|
||||||
|
|
||||||
|
id = reference_getid(data);
|
||||||
|
name = reference_getname(data);
|
||||||
|
|
||||||
|
if( not_array_variable(*name) )
|
||||||
|
{
|
||||||
|
ShowError("script:implode: illegal scope\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// not supported
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !is_string_variable(name) )
|
||||||
|
{
|
||||||
|
ShowError("script:implode: not string array\n");
|
||||||
|
script_reportdata(data);
|
||||||
|
st->state = END;
|
||||||
|
return 1;// data type mismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
if( not_server_variable(*name) )
|
||||||
|
{
|
||||||
|
sd = script_rid2sd(st);
|
||||||
|
if( sd == NULL )
|
||||||
|
return 0;// no player attached
|
||||||
|
}
|
||||||
|
|
||||||
|
//count chars
|
||||||
|
array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1;
|
||||||
|
|
||||||
|
if(array_size == -1) //empty array check (AmsTaff)
|
||||||
|
{
|
||||||
|
ShowWarning("script:implode: array length = 0\n");
|
||||||
|
output = (char*)aMallocA(sizeof(char)*5);
|
||||||
|
sprintf(output,"%s","NULL");
|
||||||
|
} else {
|
||||||
|
for(i = 0; i <= array_size; ++i) {
|
||||||
|
temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data));
|
||||||
|
len += strlen(temp);
|
||||||
|
script_removetop(st, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//allocate mem
|
||||||
|
if( script_hasdata(st,3) ) {
|
||||||
|
glue = script_getstr(st,3);
|
||||||
|
glue_len = strlen(glue);
|
||||||
|
len += glue_len * (array_size);
|
||||||
|
}
|
||||||
|
output = (char*)aMallocA(len + 1);
|
||||||
|
|
||||||
|
//build output
|
||||||
|
for(i = 0; i < array_size; ++i) {
|
||||||
|
temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data));
|
||||||
|
len = strlen(temp);
|
||||||
|
memcpy(&output[k], temp, len);
|
||||||
|
k += len;
|
||||||
|
if(glue_len != 0) {
|
||||||
|
memcpy(&output[k], glue, glue_len);
|
||||||
|
k += glue_len;
|
||||||
|
}
|
||||||
|
script_removetop(st, -1, 0);
|
||||||
|
}
|
||||||
|
temp = (char*) get_val2(st, reference_uid(id, array_size), reference_getref(data));
|
||||||
|
len = strlen(temp);
|
||||||
|
memcpy(&output[k], temp, len);
|
||||||
|
k += len;
|
||||||
|
script_removetop(st, -1, 0);
|
||||||
|
|
||||||
|
output[k] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
script_pushstr(st, output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// sprintf(<format>, ...);
|
||||||
|
// Implements C sprintf, except format %n. The resulting string is
|
||||||
|
// returned, instead of being saved in variable by reference.
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(sprintf)
|
||||||
|
{
|
||||||
|
unsigned int len, argc = 0, arg = 0, buf2_len = 0;
|
||||||
|
const char* format;
|
||||||
|
char* p;
|
||||||
|
char* q;
|
||||||
|
char* buf = NULL;
|
||||||
|
char* buf2 = NULL;
|
||||||
|
struct script_data* data;
|
||||||
|
StringBuf final_buf;
|
||||||
|
|
||||||
|
// Fetch init data
|
||||||
|
format = script_getstr(st, 2);
|
||||||
|
argc = script_lastdata(st)-2;
|
||||||
|
len = strlen(format);
|
||||||
|
|
||||||
|
// Skip parsing, where no parsing is required.
|
||||||
|
if(len==0){
|
||||||
|
script_pushconststr(st,"");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pessimistic alloc
|
||||||
|
CREATE(buf, char, len+1);
|
||||||
|
|
||||||
|
// Need not be parsed, just solve stuff like %%.
|
||||||
|
if(argc==0){
|
||||||
|
sprintf(buf, format);
|
||||||
|
script_pushstrcopy(st, buf);
|
||||||
|
aFree(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
safestrncpy(buf, format, len+1);
|
||||||
|
|
||||||
|
// Issue sprintf for each parameter
|
||||||
|
StringBuf_Init(&final_buf);
|
||||||
|
q = buf;
|
||||||
|
while((p = strchr(q, '%'))!=NULL){
|
||||||
|
if(p!=q){
|
||||||
|
len = p-q+1;
|
||||||
|
if(buf2_len<len){
|
||||||
|
RECREATE(buf2, char, len);
|
||||||
|
buf2_len = len;
|
||||||
|
}
|
||||||
|
safestrncpy(buf2, q, len);
|
||||||
|
StringBuf_AppendStr(&final_buf, buf2);
|
||||||
|
q = p;
|
||||||
|
}
|
||||||
|
p = q+1;
|
||||||
|
if(*p=='%'){ // %%
|
||||||
|
StringBuf_AppendStr(&final_buf, "%");
|
||||||
|
q+=2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(*p=='n'){ // %n
|
||||||
|
ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
|
||||||
|
script_reportsrc(st);
|
||||||
|
q+=2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(arg>=argc){
|
||||||
|
ShowError("buildin_sprintf: Not enough arguments passed!\n");
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(buf2) aFree(buf2);
|
||||||
|
StringBuf_Destroy(&final_buf);
|
||||||
|
script_pushconststr(st,"");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if((p = strchr(q+1, '%'))==NULL){
|
||||||
|
p = strchr(q, 0); // EOS
|
||||||
|
}
|
||||||
|
len = p-q+1;
|
||||||
|
if(buf2_len<len){
|
||||||
|
RECREATE(buf2, char, len);
|
||||||
|
buf2_len = len;
|
||||||
|
}
|
||||||
|
safestrncpy(buf2, q, len);
|
||||||
|
q = p;
|
||||||
|
|
||||||
|
// Note: This assumes the passed value being the correct
|
||||||
|
// type to the current format specifier. If not, the server
|
||||||
|
// probably crashes or returns anything else, than expected,
|
||||||
|
// but it would behave in normal code the same way so it's
|
||||||
|
// the scripter's responsibility.
|
||||||
|
data = script_getdata(st, arg+3);
|
||||||
|
if(data_isstring(data)){ // String
|
||||||
|
StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
|
||||||
|
}else if(data_isint(data)){ // Number
|
||||||
|
StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
|
||||||
|
}else if(data_isreference(data)){ // Variable
|
||||||
|
char* name = reference_getname(data);
|
||||||
|
if(name[strlen(name)-1]=='$'){ // var Str
|
||||||
|
StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
|
||||||
|
}else{ // var Int
|
||||||
|
StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
|
||||||
|
}
|
||||||
|
}else{ // Unsupported type
|
||||||
|
ShowError("buildin_sprintf: Unknown argument type!\n");
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(buf2) aFree(buf2);
|
||||||
|
StringBuf_Destroy(&final_buf);
|
||||||
|
script_pushconststr(st,"");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append anything left
|
||||||
|
if(*q){
|
||||||
|
StringBuf_AppendStr(&final_buf, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passed more, than needed
|
||||||
|
if(arg<argc){
|
||||||
|
ShowWarning("buildin_sprintf: Unused arguments passed.\n");
|
||||||
|
script_reportsrc(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
script_pushstrcopy(st, StringBuf_Value(&final_buf));
|
||||||
|
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(buf2) aFree(buf2);
|
||||||
|
StringBuf_Destroy(&final_buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// sscanf(<str>, <format>, ...);
|
||||||
|
// Implements C sscanf.
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(sscanf){
|
||||||
|
unsigned int argc, arg = 0, len;
|
||||||
|
struct script_data* data;
|
||||||
|
struct map_session_data* sd = NULL;
|
||||||
|
const char* str;
|
||||||
|
const char* format;
|
||||||
|
const char* p;
|
||||||
|
const char* q;
|
||||||
|
char* buf = NULL;
|
||||||
|
char* buf_p;
|
||||||
|
char* ref_str = NULL;
|
||||||
|
int ref_int;
|
||||||
|
|
||||||
|
// Get data
|
||||||
|
str = script_getstr(st, 2);
|
||||||
|
format = script_getstr(st, 3);
|
||||||
|
argc = script_lastdata(st)-3;
|
||||||
|
|
||||||
|
len = strlen(format);
|
||||||
|
CREATE(buf, char, len*2+1);
|
||||||
|
|
||||||
|
// Issue sscanf for each parameter
|
||||||
|
*buf = 0;
|
||||||
|
q = format;
|
||||||
|
while(p = strchr(q, '%')){
|
||||||
|
if(p!=q){
|
||||||
|
strncat(buf, q, (size_t)(p-q));
|
||||||
|
q = p;
|
||||||
|
}
|
||||||
|
p = q+1;
|
||||||
|
if(*p=='*' || *p=='%'){ // Skip
|
||||||
|
strncat(buf, q, 2);
|
||||||
|
q+=2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(arg>=argc){
|
||||||
|
ShowError("buildin_sscanf: Not enough arguments passed!\n");
|
||||||
|
script_pushint(st, -1);
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(ref_str) aFree(ref_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if((p = strchr(q+1, '%'))==NULL){
|
||||||
|
p = strchr(q, 0); // EOS
|
||||||
|
}
|
||||||
|
len = p-q;
|
||||||
|
strncat(buf, q, len);
|
||||||
|
q = p;
|
||||||
|
|
||||||
|
// Validate output
|
||||||
|
data = script_getdata(st, arg+4);
|
||||||
|
if(!data_isreference(data) || !reference_tovariable(data)){
|
||||||
|
ShowError("buildin_sscanf: Target argument is not a variable!\n");
|
||||||
|
script_pushint(st, -1);
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(ref_str) aFree(ref_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
buf_p = reference_getname(data);
|
||||||
|
if(not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL){
|
||||||
|
script_pushint(st, -1);
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(ref_str) aFree(ref_str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save value if any
|
||||||
|
if(buf_p[strlen(buf_p)-1]=='$'){ // String
|
||||||
|
if(ref_str==NULL){
|
||||||
|
CREATE(ref_str, char, strlen(str)+1);
|
||||||
|
}
|
||||||
|
if(sscanf(str, buf, ref_str)==0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_str), reference_getref(data));
|
||||||
|
}else{ // Number
|
||||||
|
if(sscanf(str, buf, &ref_int)==0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_int), reference_getref(data));
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
|
||||||
|
// Disable used format (%... -> %*...)
|
||||||
|
buf_p = strchr(buf, 0);
|
||||||
|
memmove(buf_p-len+2, buf_p-len+1, len);
|
||||||
|
*(buf_p-len+1) = '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passed more, than needed
|
||||||
|
if(arg<argc){
|
||||||
|
ShowWarning("buildin_sscanf: Unused arguments passed.\n");
|
||||||
|
script_reportsrc(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
script_pushint(st, arg);
|
||||||
|
if(buf) aFree(buf);
|
||||||
|
if(ref_str) aFree(ref_str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
// strpos(<haystack>, <needle>)
|
||||||
|
// strpos(<haystack>, <needle>, <offset>)
|
||||||
|
//
|
||||||
|
// Implements PHP style strpos. Adapted from code from
|
||||||
|
// http://www.daniweb.com/code/snippet313.html, Dave Sinkula
|
||||||
|
//-------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(strpos) {
|
||||||
|
const char *haystack = script_getstr(st,2);
|
||||||
|
const char *needle = script_getstr(st,3);
|
||||||
|
int i;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if( script_hasdata(st,4) )
|
||||||
|
i = script_getnum(st,4);
|
||||||
|
else
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
if ( strlen(needle) == 0 ) {
|
||||||
|
script_pushint(st, -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(haystack);
|
||||||
|
for ( ; i < len; ++i ) {
|
||||||
|
if ( haystack[i] == *needle ) {
|
||||||
|
// matched starting char -- loop through remaining chars
|
||||||
|
const char *h, *n;
|
||||||
|
for ( h = &haystack[i], n = needle; *h && *n; ++h, ++n ) {
|
||||||
|
if ( *h != *n ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !*n ) { // matched all of 'needle' to null termination
|
||||||
|
script_pushint(st, i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script_pushint(st, -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===============================================================
|
||||||
|
// replacestr <input>, <search>, <replace>{, <usecase>{, <count>}}
|
||||||
|
//
|
||||||
|
// Note: Finds all instances of <search> in <input> and replaces
|
||||||
|
// with <replace>. If specified will only replace as many
|
||||||
|
// instances as specified in <count>. By default will be case
|
||||||
|
// sensitive.
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(replacestr)
|
||||||
|
{
|
||||||
|
const char *input = script_getstr(st, 2);
|
||||||
|
const char *find = script_getstr(st, 3);
|
||||||
|
const char *replace = script_getstr(st, 4);
|
||||||
|
size_t inputlen = strlen(input);
|
||||||
|
size_t findlen = strlen(find);
|
||||||
|
struct StringBuf output;
|
||||||
|
bool usecase = true;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
int numFinds = 0;
|
||||||
|
int i = 0, f = 0;
|
||||||
|
|
||||||
|
if(findlen == 0) {
|
||||||
|
ShowError("script:replacestr: Invalid search length.\n");
|
||||||
|
st->state = END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(script_hasdata(st, 5)) {
|
||||||
|
if(script_isint(st,5))
|
||||||
|
usecase = script_getnum(st, 5) != 0;
|
||||||
|
else {
|
||||||
|
ShowError("script:replacestr: Invalid usecase value. Expected int got string\n");
|
||||||
|
st->state = END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(script_hasdata(st, 6)) {
|
||||||
|
if(script_isint(st,6))
|
||||||
|
count = script_getnum(st, 6);
|
||||||
|
else {
|
||||||
|
ShowError("script:replacestr: Invalid count value. Expected int got string\n");
|
||||||
|
st->state = END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuf_Init(&output);
|
||||||
|
|
||||||
|
for(; i < inputlen; i++) {
|
||||||
|
if(count && count == numFinds) { //found enough, stop looking
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(f = 0; f <= findlen; f++) {
|
||||||
|
if(f == findlen) { //complete match
|
||||||
|
numFinds++;
|
||||||
|
StringBuf_AppendStr(&output, replace);
|
||||||
|
|
||||||
|
i += findlen - 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(usecase) {
|
||||||
|
if((i + f) > inputlen || input[i + f] != find[f]) {
|
||||||
|
StringBuf_Printf(&output, "%c", input[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if((i + f) > inputlen || input[i + f] != find[f] && TOUPPER(input[i+f]) != TOUPPER(find[f])) {
|
||||||
|
StringBuf_Printf(&output, "%c", input[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//append excess after enough found
|
||||||
|
if(i < inputlen)
|
||||||
|
StringBuf_AppendStr(&output, &(input[i]));
|
||||||
|
|
||||||
|
script_pushstrcopy(st, StringBuf_Value(&output));
|
||||||
|
StringBuf_Destroy(&output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//========================================================
|
||||||
|
// countstr <input>, <search>{, <usecase>}
|
||||||
|
//
|
||||||
|
// Note: Counts the number of times <search> occurs in
|
||||||
|
// <input>. By default will be case sensitive.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
BUILDIN_FUNC(countstr)
|
||||||
|
{
|
||||||
|
const char *input = script_getstr(st, 2);
|
||||||
|
const char *find = script_getstr(st, 3);
|
||||||
|
size_t inputlen = strlen(input);
|
||||||
|
size_t findlen = strlen(find);
|
||||||
|
bool usecase = true;
|
||||||
|
|
||||||
|
int numFinds = 0;
|
||||||
|
int i = 0, f = 0;
|
||||||
|
|
||||||
|
if(findlen == 0) {
|
||||||
|
ShowError("script:countstr: Invalid search length.\n");
|
||||||
|
st->state = END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(script_hasdata(st, 4)) {
|
||||||
|
if(script_isint(st,4))
|
||||||
|
usecase = script_getnum(st, 4) != 0;
|
||||||
|
else {
|
||||||
|
ShowError("script:countstr: Invalid usecase value. Expected int got string\n");
|
||||||
|
st->state = END;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < inputlen; i++) {
|
||||||
|
for(f = 0; f <= findlen; f++) {
|
||||||
|
if(f == findlen) { //complete match
|
||||||
|
numFinds++;
|
||||||
|
i += findlen - 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(usecase) {
|
||||||
|
if((i + f) > inputlen || input[i + f] != find[f]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if((i + f) > inputlen || input[i + f] != find[f] && TOUPPER(input[i+f]) != TOUPPER(find[f])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script_pushint(st, numFinds);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Changes the display name and/or display class of the npc.
|
/// Changes the display name and/or display class of the npc.
|
||||||
/// Returns 0 is successful, 1 if the npc does not exist.
|
/// Returns 0 is successful, 1 if the npc does not exist.
|
||||||
///
|
///
|
||||||
@ -15395,6 +16181,22 @@ struct script_function buildin_func[] = {
|
|||||||
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
|
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
|
||||||
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
|
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
|
||||||
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
|
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
|
||||||
|
BUILDIN_DEF(charat,"si"),
|
||||||
|
BUILDIN_DEF(setchar,"ssi"),
|
||||||
|
BUILDIN_DEF(insertchar,"ssi"),
|
||||||
|
BUILDIN_DEF(delchar,"si"),
|
||||||
|
BUILDIN_DEF(strtoupper,"s"),
|
||||||
|
BUILDIN_DEF(strtolower,"s"),
|
||||||
|
BUILDIN_DEF(charisupper, "si"),
|
||||||
|
BUILDIN_DEF(charislower, "si"),
|
||||||
|
BUILDIN_DEF(substr,"sii"),
|
||||||
|
BUILDIN_DEF(explode, "rss"),
|
||||||
|
BUILDIN_DEF(implode, "r?"),
|
||||||
|
BUILDIN_DEF(sprintf,"s*"), // [Mirei]
|
||||||
|
BUILDIN_DEF(sscanf,"ss*"), // [Mirei]
|
||||||
|
BUILDIN_DEF(strpos,"ss?"),
|
||||||
|
BUILDIN_DEF(replacestr,"sss??"),
|
||||||
|
BUILDIN_DEF(countstr,"ss?"),
|
||||||
BUILDIN_DEF(setnpcdisplay,"sv??"),
|
BUILDIN_DEF(setnpcdisplay,"sv??"),
|
||||||
BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine.
|
BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine.
|
||||||
BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info
|
BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info
|
||||||
|
Loading…
x
Reference in New Issue
Block a user