Make UTF-8 safe others strings natives (#610)

This commit is contained in:
Vincent Herbet 2018-10-14 17:44:15 +02:00 committed by Arkshine
parent f63bc38f5c
commit be526418bf

View File

@ -1,4 +1,4 @@
// vim: set ts=4 sw=4 tw=99 noet: // vim: set ts=4 sw=4 tw=99 noet:
// //
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team. // Copyright (C) The AMX Mod X Development Team.
@ -210,6 +210,16 @@ void copy_amxmemory(cell* dest, cell* src, int len)
*dest++=*src++; *dest++=*src++;
} }
bool utf8isspace(const char* string)
{
return utf8iscategory(string, 1, UTF8_CATEGORY_ISSPACE) != 0;
}
size_t utf8getspaces(const char* string)
{
return utf8iscategory(string, SIZE_MAX, UTF8_CATEGORY_ISSPACE);
}
char* parse_arg(char** line, int& state) char* parse_arg(char** line, int& state)
{ {
static char arg[3072]; static char arg[3072];
@ -218,7 +228,7 @@ char* parse_arg(char** line, int& state)
while (**line) while (**line)
{ {
if (isspace(**line)) if (utf8isspace(*line))
{ {
if (state == 1) if (state == 1)
break; break;
@ -919,6 +929,7 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params)
int right_pos = 0; int right_pos = 0;
unsigned int i = 0; unsigned int i = 0;
bool done_flag = false; bool done_flag = false;
size_t spaces;
int len = 0; int len = 0;
//string[] //string[]
@ -938,9 +949,9 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params)
{ {
if (trim && !done_flag) if (trim && !done_flag)
{ {
if (isspace(string[i])) if ((spaces = utf8getspaces(string + i) > 0))
{ {
while (isspace(string[++i])); i += spaces;
done_flag = true; done_flag = true;
} }
} }
@ -974,6 +985,7 @@ static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params)
{ {
int left_pos = 0, right_pos = 0, len, pos = -1; int left_pos = 0, right_pos = 0, len, pos = -1;
unsigned int i = 0; unsigned int i = 0;
size_t spaces;
char *string = get_amxstring(amx, params[1], 0, len); char *string = get_amxstring(amx, params[1], 0, len);
char *left = new char[len + 1], *right = new char[len + 1]; char *left = new char[len + 1], *right = new char[len + 1];
@ -989,9 +1001,9 @@ static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params)
int trim = params[7]; int trim = params[7];
// ltrim left // ltrim left
if (trim & 1 && isspace(string[i])) if (trim & 1 && (spaces = utf8getspaces(string)) > 0)
{ {
while (isspace(string[++i])); i += spaces;
} }
for (; i < (unsigned int) len; ++i) for (; i < (unsigned int) len; ++i)
@ -1007,17 +1019,17 @@ static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params)
} }
// rtrim left // rtrim left
if (trim & 2 && left_pos && isspace(left[left_pos - 1])) if (trim & 2 && left_pos && utf8isspace(&left[left_pos - 1]))
{ {
while (--left_pos >= 0 && isspace(left[left_pos])); while (--left_pos >= 0 && utf8isspace(&left[left_pos]));
++left_pos; ++left_pos;
} }
// ltrim right // ltrim right
if (trim & 4 && isspace(string[i])) if (trim & 4 && (spaces = utf8getspaces(string + i)) > 0)
{ {
while (isspace(string[++i])); i += spaces;
} }
for (; i < (unsigned int) len; ++i) for (; i < (unsigned int) len; ++i)
@ -1026,9 +1038,9 @@ static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params)
} }
// rtrim right // rtrim right
if (trim & 8 && right_pos && isspace(right[right_pos - 1])) if (trim & 8 && right_pos && utf8isspace(&right[right_pos - 1]))
{ {
while (--right_pos >= 0 && isspace(right[right_pos])); while (--right_pos >= 0 && utf8isspace(&right[right_pos]));
++right_pos; ++right_pos;
} }
@ -1058,8 +1070,12 @@ static cell AMX_NATIVE_CALL argparse(AMX *amx, cell *params)
// Strip all left-hand whitespace. // Strip all left-hand whitespace.
size_t i = start_pos; size_t i = start_pos;
while (i < input_len && isspace(input[i])) size_t spaces;
i++;
if ((spaces = utf8getspaces(input + i)) > 0)
{
i += spaces;
}
if (i >= input_len) { if (i >= input_len) {
*buffer = '\0'; *buffer = '\0';
@ -1078,7 +1094,7 @@ static cell AMX_NATIVE_CALL argparse(AMX *amx, cell *params)
} }
// If not in quotes, and we see a space, stop. // If not in quotes, and we see a space, stop.
if (isspace(input[i]) && !in_quote) if (utf8isspace(input + i) && !in_quote)
break; break;
if (size_t(bufpos - buffer) < buflen) if (size_t(bufpos - buffer) < buflen)
@ -1106,9 +1122,13 @@ static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */
int RightMax = params[5]; int RightMax = params[5];
size_t len = (size_t)_len; size_t len = (size_t)_len;
size_t spaces;
if ((spaces = utf8getspaces(string)) > 0)
{
i += spaces;
}
while (isspace(string[i]) && i<len)
i++;
beg = i; beg = i;
for (; i<len; i++) for (; i<len; i++)
{ {
@ -1120,12 +1140,12 @@ static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */
if (i == len-1) if (i == len-1)
goto do_copy; goto do_copy;
} else { } else {
if (isspace(string[i]) && !in_quote) if (!in_quote && (spaces = utf8getspaces(string + i)) > 0)
{ {
do_copy: do_copy:
size_t pos = i; size_t pos = i;
while (isspace(string[i])) i += spaces;
i++;
const char *start = had_quotes ? &(string[beg+1]) : &(string[beg]); const char *start = had_quotes ? &(string[beg+1]) : &(string[beg]);
size_t _end = had_quotes ? (i==len-1 ? 1 : 2) : 0; size_t _end = had_quotes ? (i==len-1 ? 1 : 2) : 0;
size_t end = (pos - _end > (size_t)LeftMax) ? (size_t)LeftMax : pos - _end; size_t end = (pos - _end > (size_t)LeftMax) ? (size_t)LeftMax : pos - _end;
@ -1367,18 +1387,27 @@ static cell AMX_NATIVE_CALL amx_strlen(AMX *amx, cell *params)
static cell AMX_NATIVE_CALL amx_trim(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_trim(AMX *amx, cell *params)
{ {
int len, newlen; int length;
char *str = get_amxstring(amx, params[1], 0, len); auto string = get_amxstring(amx, params[1], 0, length);
UTIL_TrimLeft(str); auto leftSpaces = utf8getspaces(string);
UTIL_TrimRight(str); auto rightSpaces = 0u;
newlen = strlen(str); auto originalLength = length;
len -= newlen;
set_amxstring(amx, params[1], str, newlen); if (leftSpaces < size_t(length))
{
while (--length >= 0 && utf8isspace(string + length))
{
++rightSpaces;
}
}
return len; auto totalSpaces = leftSpaces + rightSpaces;
set_amxstring(amx, params[1], string + leftSpaces, originalLength - totalSpaces);
return totalSpaces;
} }
static cell AMX_NATIVE_CALL n_strcat(AMX *amx, cell *params) static cell AMX_NATIVE_CALL n_strcat(AMX *amx, cell *params)