From d7f6cf28921b5b8bdf8a242ddad8f95a4a449656 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 14 Mar 2018 02:27:15 +0100 Subject: [PATCH] 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 --- src/base/system.c | 31 ++++++++++++++++++--- src/base/system.h | 38 ++++++++++++++++++++++++++ src/engine/server/server.cpp | 42 ++--------------------------- src/game/client/components/chat.cpp | 2 +- src/game/server/gamecontext.cpp | 2 +- src/test/str.cpp | 20 ++++++++++++++ 6 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 7633fe913..cede1f8d4 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -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 */ diff --git a/src/base/system.h b/src/base/system.h index 9a1922387..756fc9a79 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -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 diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 206ebc448..3890bafef 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -44,43 +44,6 @@ #include #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(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]) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 39346c2b2..d0c046269 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -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; } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index d3a8d3efb..9f3e95f76 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -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; } diff --git a/src/test/str.cpp b/src/test/str.cpp index 05a113720..2e44d48d5 100644 --- a/src/test/str.cpp +++ b/src/test/str.cpp @@ -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"); +}