anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

hashcomp.cpp (3575B)

      1 /*
      2  *
      3  * (C) 2002-2011 InspIRCd Development Team
      4  * (C) 2008-2022 Anope Team <team@anope.org>
      5  *
      6  * Please read COPYING and README for further details.
      7  */
      8 
      9 #include "services.h"
     10 #include "hashcomp.h"
     11 #include "anope.h"
     12 
     13 /* Case map in use by Anope */
     14 std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
     15 /* Cache of the above case map, forced upper */
     16 static unsigned char case_map_upper[256], case_map_lower[256];
     17 
     18 /* called whenever Anope::casemap is modified to rebuild the casemap cache */
     19 void Anope::CaseMapRebuild()
     20 {
     21 	const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap);
     22 
     23 	for (unsigned i = 0; i < sizeof(case_map_upper); ++i)
     24 	{
     25 		case_map_upper[i] = ct.toupper(i);
     26 		case_map_lower[i] = ct.tolower(i);
     27 	}
     28 }
     29 
     30 unsigned char Anope::tolower(unsigned char c)
     31 {
     32 	return case_map_lower[c];
     33 }
     34 
     35 unsigned char Anope::toupper(unsigned char c)
     36 {
     37 	return case_map_upper[c];
     38 }
     39 
     40 /*
     41  *
     42  * This is an implementation of a special string class, ci::string,
     43  * which is a case-insensitive equivalent to std::string.
     44  *
     45  */
     46 
     47 bool ci::ci_char_traits::eq(char c1st, char c2nd)
     48 {
     49 	return case_map_upper[static_cast<unsigned char>(c1st)] == case_map_upper[static_cast<unsigned char>(c2nd)];
     50 }
     51 
     52 bool ci::ci_char_traits::ne(char c1st, char c2nd)
     53 {
     54 	return !eq(c1st, c2nd);
     55 }
     56 
     57 bool ci::ci_char_traits::lt(char c1st, char c2nd)
     58 {
     59 	return case_map_upper[static_cast<unsigned char>(c1st)] < case_map_upper[static_cast<unsigned char>(c2nd)];
     60 }
     61 
     62 int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n)
     63 {
     64 	for (unsigned i = 0; i < n; ++i)
     65 	{
     66 		unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)],
     67 					c2 = case_map_upper[static_cast<unsigned char>(*str2)];
     68 
     69 		if (c1 > c2)
     70 			return 1;
     71 		else if (c1 < c2)
     72 			return -1;
     73 		else if (!c1 || !c2)
     74 			return 0;
     75 
     76 		++str1;
     77 		++str2;
     78 	}
     79 	return 0;
     80 }
     81 
     82 const char *ci::ci_char_traits::find(const char *s1, int n, char c)
     83 {
     84 	while (n-- > 0 && case_map_upper[static_cast<unsigned char>(*s1)] != case_map_upper[static_cast<unsigned char>(c)])
     85 		++s1;
     86 	return n >= 0 ? s1 : NULL;
     87 }
     88 
     89 bool ci::less::operator()(const Anope::string &s1, const Anope::string &s2) const
     90 {
     91 	return s1.ci_str().compare(s2.ci_str()) < 0;
     92 }
     93 
     94 sepstream::sepstream(const Anope::string &source, char separator, bool ae) : tokens(source), sep(separator), pos(0), allow_empty(ae)
     95 {
     96 }
     97 
     98 bool sepstream::GetToken(Anope::string &token)
     99 {
    100 	if (this->StreamEnd())
    101 	{
    102 		token.clear();
    103 		return false;
    104 	}
    105 
    106 	if (!this->allow_empty)
    107 	{
    108 		this->pos = this->tokens.find_first_not_of(this->sep, this->pos);
    109 		if (this->pos == std::string::npos)
    110 		{
    111 			this->pos = this->tokens.length() + 1;
    112 			token.clear();
    113 			return false;
    114 		}
    115 	}
    116 
    117 	size_t p = this->tokens.find(this->sep, this->pos);
    118 	if (p == std::string::npos)
    119 		p = this->tokens.length();
    120 
    121 	token = this->tokens.substr(this->pos, p - this->pos);
    122 	this->pos = p + 1;
    123 
    124 	return true;
    125 }
    126 
    127 bool sepstream::GetToken(Anope::string &token, int num)
    128 {
    129 	int i;
    130 	for (i = 0; i < num + 1 && this->GetToken(token); ++i);
    131 	return i == num + 1;
    132 }
    133 
    134 int sepstream::NumTokens()
    135 {
    136 	int i;
    137 	Anope::string token;
    138 	for (i = 0; this->GetToken(token); ++i);
    139 	return i;
    140 }
    141 
    142 bool sepstream::GetTokenRemainder(Anope::string &token, int num)
    143 {
    144 	if (this->GetToken(token, num))
    145 	{
    146 		if (!this->StreamEnd())
    147 			token += sep + this->GetRemaining();
    148 
    149 		return true;
    150 	}
    151 
    152 	return false;
    153 }
    154 
    155 const Anope::string sepstream::GetRemaining()
    156 {
    157 	return !this->StreamEnd() ? this->tokens.substr(this->pos) : "";
    158 }
    159 
    160 bool sepstream::StreamEnd()
    161 {
    162 	return this->pos > this->tokens.length();
    163 }