Fix some system.c insanity

`str_utf8_isspace` now returns true if the passed code point renders as
a space, instead of when not.

Add `str_utf8_trim_right`, use this function and
`str_utf8_skip_whitespaces` in the server.

Add tests for the three functions
This commit is contained in:
heinrich5991 2018-03-14 02:27:15 +01:00
parent fcddc5aaf8
commit d7f6cf2892
6 changed files with 90 additions and 45 deletions

View file

@ -2685,11 +2685,11 @@ float str_tofloat(const char *str) { return atof(str); }
int str_utf8_isspace(int code)
{
return code > 0x20 && code != 0xA0 && code != 0x034F && code != 0x2800 &&
return !(code > 0x20 && code != 0xA0 && code != 0x034F && code != 0x2800 &&
(code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) &&
(code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) &&
(code < 0xFE00 || code > 0xFE0F) && code != 0xFEFF &&
(code < 0xFFF9 || code > 0xFFFC);
(code < 0xFFF9 || code > 0xFFFC));
}
const char *str_utf8_skip_whitespaces(const char *str)
@ -2703,7 +2703,7 @@ const char *str_utf8_skip_whitespaces(const char *str)
code = str_utf8_decode(&str);
// check if unicode is not empty
if(str_utf8_isspace(code))
if(!str_utf8_isspace(code))
{
return str_old;
}
@ -2712,6 +2712,31 @@ const char *str_utf8_skip_whitespaces(const char *str)
return str;
}
void str_utf8_trim_right(char *param)
{
const char *str = param;
char *end = 0;
while(*str)
{
char *str_old = (char *)str;
int code = str_utf8_decode(&str);
// check if unicode is not empty
if(!str_utf8_isspace(code))
{
end = 0;
}
else if(!end)
{
end = str_old;
}
}
if(end)
{
*end = 0;
}
}
int str_utf8_isstart(char c)
{
if((c&0xC0) == 0x80) /* 10xxxxxx */

View file

@ -1581,12 +1581,50 @@ int str_utf8_to_skeleton(const char *str, int *buf, int buf_len);
*/
int str_utf8_comp_confusable(const char *a, const char *b);
/*
Function: str_utf8_isspace
Checks whether the given Unicode codepoint renders as space.
Parameters:
code - Unicode codepoint to check.
Returns:
0 if the codepoint does not render as space, != 0 if it does.
*/
int str_utf8_isspace(int code);
int str_utf8_isstart(char c);
/*
Function: str_utf8_skip_whitespaces
Skips leading characters that render as spaces.
Parameters:
str - Pointer to the string.
Returns:
Pointer to the first non-whitespace character found
within the string.
Remarks:
- The strings are treated as zero-terminated strings.
*/
const char *str_utf8_skip_whitespaces(const char *str);
/*
Function: str_utf8_trim_right
Removes trailing characters that render as spaces by modifying
the string in-place.
Parameters:
str - Pointer to the string.
Remarks:
- The strings are treated as zero-terminated strings.
- The string is modified in-place.
*/
void str_utf8_trim_right(char *str);
/*
Function: str_utf8_rewind
Moves a cursor backwards in an utf8 string

View file

@ -44,43 +44,6 @@
#include <windows.h>
#endif
static const char *StrLtrim(const char *pStr)
{
while(*pStr)
{
const char *pStrOld = pStr;
int Code = str_utf8_decode(&pStr);
// check if unicode is not empty
if(str_utf8_isspace(Code))
{
return pStrOld;
}
}
return pStr;
}
static void StrRtrim(char *pStr)
{
const char *p = pStr;
const char *pEnd = 0;
while(*p)
{
const char *pStrOld = p;
int Code = str_utf8_decode(&p);
// check if unicode is not empty
if(str_utf8_isspace(Code))
{
pEnd = 0;
}
else if(pEnd == 0)
pEnd = pStrOld;
}
if(pEnd != 0)
*(const_cast<char *>(pEnd)) = 0;
}
CSnapIDPool::CSnapIDPool()
{
@ -343,14 +306,13 @@ CServer::CServer()
Init();
}
int CServer::TrySetClientName(int ClientID, const char *pName)
{
char aTrimmedName[64];
// trim the name
str_copy(aTrimmedName, StrLtrim(pName), sizeof(aTrimmedName));
StrRtrim(aTrimmedName);
str_copy(aTrimmedName, str_utf8_skip_whitespaces(pName), sizeof(aTrimmedName));
str_utf8_trim_right(aTrimmedName);
// check for empty names
if(!aTrimmedName[0])

View file

@ -462,7 +462,7 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine)
int Code = str_utf8_decode(&pStr);
// check if unicode is not empty
if(str_utf8_isspace(Code))
if(!str_utf8_isspace(Code))
{
pEnd = 0;
}

View file

@ -1171,7 +1171,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
int Code = str_utf8_decode(&p);
// check if unicode is not empty
if(str_utf8_isspace(Code))
if(!str_utf8_isspace(Code))
{
pEnd = 0;
}

View file

@ -17,3 +17,23 @@ TEST(Str, Dist)
EXPECT_EQ(str_utf8_dist("flaw", "lawn"), 2);
EXPECT_EQ(str_utf8_dist("saturday", "sunday"), 3);
}
TEST(Str, Utf8Isspace)
{
EXPECT_TRUE(str_utf8_isspace(' '));
EXPECT_FALSE(str_utf8_isspace('a'));
}
TEST(Str, Utf8SkipWhitespaces)
{
EXPECT_STREQ(str_utf8_skip_whitespaces("abc"), "abc");
EXPECT_STREQ(str_utf8_skip_whitespaces("abc "), "abc ");
EXPECT_STREQ(str_utf8_skip_whitespaces(" abc"), "abc");
}
TEST(Str, Utf8TrimRight)
{
char A1[] = "abc"; str_utf8_trim_right(A1); EXPECT_STREQ(A1, "abc");
char A2[] = " abc"; str_utf8_trim_right(A2); EXPECT_STREQ(A2, " abc");
char A3[] = "abc "; str_utf8_trim_right(A3); EXPECT_STREQ(A3, "abc");
}