diff options
-rw-r--r-- | indexer/editable_map_object.cpp | 42 | ||||
-rw-r--r-- | indexer/editable_map_object.hpp | 1 | ||||
-rw-r--r-- | indexer/indexer_tests/editable_map_object_test.cpp | 19 |
3 files changed, 58 insertions, 4 deletions
diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp index 6d3dac6999..02067c4e32 100644 --- a/indexer/editable_map_object.cpp +++ b/indexer/editable_map_object.cpp @@ -7,10 +7,13 @@ #include "base/macros.hpp" #include "base/string_utils.hpp" -#include "std/cctype.hpp" -#include "std/cmath.hpp" -#include "std/regex.hpp" -#include "std/sstream.hpp" +#include <codecvt> +#include <cctype> +#include <cmath> +#include <regex> +#include <sstream> + +using namespace std; namespace { @@ -756,4 +759,35 @@ bool EditableMapObject::ValidateLevel(string const & level) return strings::to_double(level, result) && result > kMinBuildingLevel && result <= kMaximumLevelsEditableByUsers; } + +// static +bool EditableMapObject::ValidateName(string const & name) +{ + if (name.empty()) + return true; + + if (strings::IsASCIIString(name)) + return regex_match(name, regex(R"(^[ A-Za-z0-9.,?!@()\-:;"'`]+$)")); + + std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter; + + std::u32string const u32name = converter.from_bytes(name); + + std::u32string const excludedSymbols = U"$%^~§><{}[]*=_#№±\n\t\r\v\f|√•π÷׶∆°"; + + for (auto const ch : u32name) + { + // Exclude arrows, mathematical symbols, borders, geometric shapes. + if (ch >= U'\U00002190' && ch <= U'\U00002BFF') + return false; + // Exclude format controls, musical symbols, emoticons, ornamental and pictographs, + // ancient and exotic alphabets. + if (ch >= U'\U0000FFF0' && ch <= U'\U0001F9FF') + return false; + + if (find(excludedSymbols.cbegin(), excludedSymbols.cend(), ch) != excludedSymbols.cend()) + return false; + } + return true; +} } // namespace osm diff --git a/indexer/editable_map_object.hpp b/indexer/editable_map_object.hpp index 9e58442c83..981316da07 100644 --- a/indexer/editable_map_object.hpp +++ b/indexer/editable_map_object.hpp @@ -165,6 +165,7 @@ public: static bool ValidateWebsite(string const & site); static bool ValidateEmail(string const & email); static bool ValidateLevel(string const & level); + static bool ValidateName(string const & name); /// Check whether langCode can be used as default name. static bool CanUseAsDefaultName(int8_t const langCode, vector<int8_t> const & nativeMwmLanguages); diff --git a/indexer/indexer_tests/editable_map_object_test.cpp b/indexer/indexer_tests/editable_map_object_test.cpp index be61b1772e..5f984cef2a 100644 --- a/indexer/indexer_tests/editable_map_object_test.cpp +++ b/indexer/indexer_tests/editable_map_object_test.cpp @@ -188,6 +188,25 @@ UNIT_TEST(EditableMapObject_ValidateEmail) TEST(!EditableMapObject::ValidateEmail("email@e#$%&'*+-/=?^`_{}|~.com"), ()); } +UNIT_TEST(EditableMapObject_ValidateName) +{ + vector<string> correctNames = {"abc", "абв", "ᆺᆯㅕ", "꫞ꪺꫀꪸ", "a b?c", "a!b.c", "a(b)c""a,b.c"}; + vector<string> incorrectNames = {"a$bc", "a%bc", "a^bc", "a~bc", "a§bc", "a>bc", "a<bc", "a{bc", + "a[bc", "*", "a*bc", "a=bc", "a_bc", "a#bc", "a№bc", "a±bc", + "a\nbc", "a\tbc", "a\rbc", "a\vbc", "a\fbc", "a|bc", "N√", + "Hello World!\U0001F600", "Exit →", "∫0dx = C", "\U0001210A"}; + + for (auto const & name : correctNames) + { + TEST(EditableMapObject::ValidateName(name), ()); + } + + for (auto const & name : incorrectNames) + { + TEST(!EditableMapObject::ValidateName(name), ()); + } +} + UNIT_TEST(EditableMapObject_CanUseAsDefaultName) { EditableMapObject emo; |