From ad9e3ad972b6f7a2e34c61d615e25de07c9acdfa Mon Sep 17 00:00:00 2001 From: Nextra Date: Wed, 31 Jul 2013 23:40:49 +0200 Subject: [PATCH] Add strtok2 which fixes a trim issue with strtok (bug 3993, r=arkshine) --- amxmodx/string.cpp | 77 ++++++++++++++++++++++++++++++++++++++ plugins/include/string.inc | 60 +++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index 41c9084b..5f597512 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -851,11 +851,87 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params) 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(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 //Takes a string and breaks it into a 1st param and rest params //strbreak(String[], First[], FirstLen, Rest[], RestLen) static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */ { + int _len; bool in_quote = false; bool had_quotes = false; @@ -1156,6 +1232,7 @@ AMX_NATIVE_INFO string_Natives[] = {"trim", amx_trim}, {"ucfirst", amx_ucfirst}, {"strtok", amx_strtok}, + {"strtok2", amx_strtok2}, {"strlen", amx_strlen}, {"strcat", n_strcat}, {"strfind", n_strfind}, diff --git a/plugins/include/string.inc b/plugins/include/string.inc index 8b910c55..57a702a6 100755 --- a/plugins/include/string.inc +++ b/plugins/include/string.inc @@ -162,6 +162,66 @@ native parse(const text[], ... ); */ 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 It breaks a string into the first parameter and the rest of the parameters