Add strtok2 which fixes a trim issue with strtok (bug 3993, r=arkshine)

Former-commit-id: ad9e3ad972b6f7a2e34c61d615e25de07c9acdfa
This commit is contained in:
Nextra 2013-07-31 23:40:49 +02:00
parent da6d417d5d
commit eb43b69e4d
2 changed files with 137 additions and 0 deletions

View File

@ -851,11 +851,87 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params)
return 1; return 1;
} }
// Same as amx_strtok but fixes and expands trim, returns token pos if token was found, -1 otherwise
static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params)
{
int left_pos = 0, right_pos = 0, len, pos = -1;
unsigned int i = 0;
char *string = get_amxstring(amx, params[1], 0, len);
char *left = new char[len + 1], *right = new char[len + 1];
int left_max = params[3], right_max = params[5];
char token = static_cast<char>(params[6]);
/* Trim flags:
1 - ltrim left
2 - rtrim left
4 - ltrim right
8 - rtrim right
*/
int trim = params[7];
// ltrim left
if (trim & 1 && isspace(string[i]))
{
while (isspace(string[++i]));
}
for (; i < (unsigned int) len; ++i)
{
if (string[i] == token)
{
pos = i;
++i;
break;
}
left[left_pos++] = string[i];
}
// rtrim left
if (trim & 2 && left_pos && isspace(left[left_pos - 1]))
{
while (--left_pos >= 0 && isspace(left[left_pos]));
++left_pos;
}
// ltrim right
if (trim & 4 && isspace(string[i]))
{
while (isspace(string[++i]));
}
for (; i < (unsigned int) len; ++i)
{
right[right_pos++] = string[i];
}
// rtrim right
if (trim & 8 && right_pos && isspace(right[right_pos - 1]))
{
while (--right_pos >= 0 && isspace(right[right_pos]));
++right_pos;
}
right[right_pos] = 0;
left[left_pos] = 0;
set_amxstring(amx, params[2], left, left_max);
set_amxstring(amx, params[4], right, right_max);
delete [] left;
delete [] right;
return pos;
}
//added by BAILOPAN //added by BAILOPAN
//Takes a string and breaks it into a 1st param and rest params //Takes a string and breaks it into a 1st param and rest params
//strbreak(String[], First[], FirstLen, Rest[], RestLen) //strbreak(String[], First[], FirstLen, Rest[], RestLen)
static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */ static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */
{ {
int _len; int _len;
bool in_quote = false; bool in_quote = false;
bool had_quotes = false; bool had_quotes = false;
@ -1156,6 +1232,7 @@ AMX_NATIVE_INFO string_Natives[] =
{"trim", amx_trim}, {"trim", amx_trim},
{"ucfirst", amx_ucfirst}, {"ucfirst", amx_ucfirst},
{"strtok", amx_strtok}, {"strtok", amx_strtok},
{"strtok2", amx_strtok2},
{"strlen", amx_strlen}, {"strlen", amx_strlen},
{"strcat", n_strcat}, {"strcat", n_strcat},
{"strfind", n_strfind}, {"strfind", n_strfind},

View File

@ -162,6 +162,66 @@ native parse(const text[], ... );
*/ */
native strtok(const text[], Left[], leftLen, Right[], rightLen, token=' ', trimSpaces=0); native strtok(const text[], Left[], leftLen, Right[], rightLen, token=' ', trimSpaces=0);
/**
* Below are the trim flags for strtok2
*
* You can specify how the left and right buffers will
* be trimmed by strtok2. LTRIM trims spaces from the
* left side. RTRIM trims from the right side.
*
* The defines TRIM_INNER, TRIM_OUTER and TRIM_FULL are
* shorthands for commonly used flag combinations.
*
* When the initial string is trimmed, using TRIM_INNER
* for all subsequent strtok2 calls will ensure that left
* and right are always trimmed from both sides.
*
* Examples:
* str1[] = " This is * some text "
* strtok2(str1, left, 24, right, 24, '*', TRIM_FULL)
* left will be "This is", right will be "some text"
*
* str2[] = " Here is | an | example "
* trim(str2)
* strtok2(str2, left, 24, right, 24, '|', TRIM_INNER)
* left will be "Here is", right will be "an | example"
* strtok2(right, left, 24, right, 24, '|', TRIM_INNER)
* left will be "an", right will be "example"
*
* str3[] = " One - more "
* strtok2(str3, left, 24, right, 24, '-', TRIM_OUTER)
* left will be "One ", right will be " more"
*
* str4[] = " Final . example "
* strtok2(str4, left, 24, right, 24, '.', LTRIM_LEFT|LTRIM_RIGHT)
* left will be "Final ", right will be "example "
*/
#define LTRIM_LEFT (1<<0)
#define RTRIM_LEFT (1<<1)
#define LTRIM_RIGHT (1<<2)
#define RTRIM_RIGHT (1<<3)
#define TRIM_INNER RTRIM_LEFT|LTRIM_RIGHT
#define TRIM_OUTER LTRIM_LEFT|RTRIM_RIGHT
#define TRIM_FULL TRIM_OUTER|TRIM_INNER
/**
* Breaks a string in two by token
*
* Only available in 1.8.3 and above
*
* @param text String to tokenize
* @param left Buffer to store left half
* @param llen Size of left buffer
* @param right Buffer to store right half
* @param rlen Size of right buffer
* @param token Token to split by
* @param trim Flags for trimming behavior, see above
*
* @return Returns position of token in string if found,
* -1 if token was not found
*/
native strtok2(const text[], left[], const llen, right[], const rlen, const token = ' ', const trim = 0);
/* Gets parameters from text one at a time /* Gets parameters from text one at a time
It breaks a string into the first parameter and the rest of the parameters It breaks a string into the first parameter and the rest of the parameters