summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-04-29 15:43:51 -0400
committerAdam <Adam@anope.org>2012-04-29 15:43:51 -0400
commit62818abbf4a39b7641ad2b84d1888ed03b653819 (patch)
tree8ac4d9cf71c728060f2a46f9688c81bea658a234 /src
parent4d9a96e8df6e0baad3fb55310122061de5907016 (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.cpp18
-rw-r--r--src/hashcomp.cpp92
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();