diff options
author | Adam <Adam@anope.org> | 2012-04-29 15:43:51 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-04-29 15:43:51 -0400 |
commit | 62818abbf4a39b7641ad2b84d1888ed03b653819 (patch) | |
tree | 8ac4d9cf71c728060f2a46f9688c81bea658a234 /src | |
parent | 4d9a96e8df6e0baad3fb55310122061de5907016 (diff) |
Added options:casemap to chose how case insensitive strings are compared, using ascii, rfc1459, or a locale installed on the system
Diffstat (limited to 'src')
-rw-r--r-- | src/config.cpp | 18 | ||||
-rw-r--r-- | src/hashcomp.cpp | 92 |
2 files changed, 39 insertions, 71 deletions
diff --git a/src/config.cpp b/src/config.cpp index 51a930393..74ba31bd2 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -16,6 +16,7 @@ #include "access.h" #include "opertype.h" #include "channels.h" +#include "hashcomp.h" /*************************************************************************/ @@ -197,6 +198,22 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->NameServer = "127.0.0.1"; } } + + if (this->CaseMap == "ascii") + Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>()); + else if (this->CaseMap == "rfc1459") + Anope::casemap = std::locale(std::locale(), new Anope::rfc1459_ctype<char>()); + else + { + try + { + Anope::casemap = std::locale(this->CaseMap.c_str()); + } + catch (const std::runtime_error &) + { + Log() << "Unknown casemap " << this->CaseMap << " - casemap not changed"; + } + } } bool ServerConfig::CheckOnce(const Anope::string &tag) @@ -1149,6 +1166,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"networkinfo", "nicklen", "31", new ValueContainerUInt(&conf->NickLen), DT_UINTEGER | DT_NORELOAD, ValidateNickLen}, {"networkinfo", "userlen", "10", new ValueContainerUInt(&conf->UserLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, {"networkinfo", "hostlen", "64", new ValueContainerUInt(&conf->HostLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, + {"options", "casemap", "ascii", new ValueContainerString(&conf->CaseMap), DT_STRING, NoValidation}, {"options", "passlen", "32", new ValueContainerUInt(&conf->PassLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, {"options", "seed", "0", new ValueContainerLUInt(&conf->Seed), DT_LUINTEGER, NoValidation}, {"options", "nobackupokay", "no", new ValueContainerBool(&conf->NoBackupOkay), DT_BOOLEAN, NoValidation}, diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 84773b369..7ce28df13 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -12,89 +12,47 @@ #include "hashcomp.h" #include "anope.h" +/* Case map in use by Anope */ +std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>()); + /* * - * This is an implementation of two special string classes: - * - * irc::string which is a case-insensitive equivalent to - * std::string which is not only case-insensitive but - * can also do scandanavian comparisons, e.g. { = [, etc. - * - * ci::string which is a case-insensitive equivalent to - * std::string. - * - * These classes depend on rfc_case_insensitive_map and - * ascii_case_insensitive_map + * This is an implementation of a special string class, ci::string, + * which is a case-insensitive equivalent to std::string. * */ -bool irc::irc_char_traits::eq(char c1st, char c2nd) -{ - return rfc_case_insensitive_map[static_cast<unsigned char>(c1st)] == rfc_case_insensitive_map[static_cast<unsigned char>(c2nd)]; -} - -bool irc::irc_char_traits::ne(char c1st, char c2nd) -{ - return rfc_case_insensitive_map[static_cast<unsigned char>(c1st)] != rfc_case_insensitive_map[static_cast<unsigned char>(c2nd)]; -} - -bool irc::irc_char_traits::lt(char c1st, char c2nd) -{ - return rfc_case_insensitive_map[static_cast<unsigned char>(c1st)] < rfc_case_insensitive_map[static_cast<unsigned char>(c2nd)]; -} - -int irc::irc_char_traits::compare(const char *str1, const char *str2, size_t n) -{ - for (unsigned i = 0; i < n; ++i) - { - if (rfc_case_insensitive_map[static_cast<unsigned char>(*str1)] > rfc_case_insensitive_map[static_cast<unsigned char>(*str2)]) - return 1; - - if (rfc_case_insensitive_map[static_cast<unsigned char>(*str1)] < rfc_case_insensitive_map[static_cast<unsigned char>(*str2)]) - return -1; - - if (!*str1 || !*str2) - return 0; - - ++str1; - ++str2; - } - return 0; -} - -const char *irc::irc_char_traits::find(const char *s1, int n, char c) -{ - while (n-- > 0 && rfc_case_insensitive_map[static_cast<unsigned char>(*s1)] != rfc_case_insensitive_map[static_cast<unsigned char>(c)]) - ++s1; - return n >= 0 ? s1 : NULL; -} - bool ci::ci_char_traits::eq(char c1st, char c2nd) { - return ascii_case_insensitive_map[static_cast<unsigned char>(c1st)] == ascii_case_insensitive_map[static_cast<unsigned char>(c2nd)]; + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + return ct.toupper(c1st) == ct.toupper(c2nd); } bool ci::ci_char_traits::ne(char c1st, char c2nd) { - return ascii_case_insensitive_map[static_cast<unsigned char>(c1st)] != ascii_case_insensitive_map[static_cast<unsigned char>(c2nd)]; + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + return ct.toupper(c1st) != ct.toupper(c2nd); } bool ci::ci_char_traits::lt(char c1st, char c2nd) { - return ascii_case_insensitive_map[static_cast<unsigned char>(c1st)] < ascii_case_insensitive_map[static_cast<unsigned char>(c2nd)]; + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + return ct.toupper(c1st) < ct.toupper(c2nd); } int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n) { + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + for (unsigned i = 0; i < n; ++i) { - if (ascii_case_insensitive_map[static_cast<unsigned char>(*str1)] > ascii_case_insensitive_map[static_cast<unsigned char>(*str2)]) - return 1; + register char c1 = ct.toupper(*str1), c2 = ct.toupper(*str2); - if (ascii_case_insensitive_map[static_cast<unsigned char>(*str1)] < ascii_case_insensitive_map[static_cast<unsigned char>(*str2)]) + if (c1 > c2) + return 1; + else if (c1 < c2) return -1; - - if (!*str1 || !*str2) + else if (!c1 || !c2) return 0; ++str1; @@ -105,7 +63,9 @@ int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n) const char *ci::ci_char_traits::find(const char *s1, int n, char c) { - while (n-- > 0 && ascii_case_insensitive_map[static_cast<unsigned char>(*s1)] != ascii_case_insensitive_map[static_cast<unsigned char>(c)]) + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + register char c_u = ct.toupper(c); + while (n-- > 0 && ct.toupper(*s1) != c_u) ++s1; return n >= 0 ? s1 : NULL; } @@ -120,16 +80,6 @@ bool ci::less::operator()(const Anope::string &s1, const Anope::string &s2) cons return s1.ci_str().compare(s2.ci_str()) < 0; } -/** Compare two Anope::strings as irc::strings and find which one is les - * @param s1 The first string - * @param s2 The second string - * @return true if s1 < s2, else false - */ -bool irc::less::operator()(const Anope::string &s1, const Anope::string &s2) const -{ - return s1.irc_str().compare(s2.irc_str()) < 0; -} - sepstream::sepstream(const Anope::string &source, char seperator) : tokens(source), sep(seperator) { last_starting_position = n = tokens.begin(); |