summaryrefslogtreecommitdiff
path: root/src/hashcomp.cpp
blob: 7ce28df133d293e040eaac79c829e6d1b3c6bb19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * Copyright (C) 2002-2011 InspIRCd Development Team
 * Copyright (C) 2008-2012 Anope Team <team@anope.org>
 *
 * Please read COPYING and README for further details.
 *
 * These classes have been copied from InspIRCd and modified
 * for use in Anope.
 */

#include "services.h"
#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 a special string class, ci::string,
 * which is a case-insensitive equivalent to std::string.
 *
 */
 
bool ci::ci_char_traits::eq(char c1st, 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)
{
	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)
{
	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)
	{
		register char c1 = ct.toupper(*str1), c2 = ct.toupper(*str2);

		if (c1 > c2)
			return 1;
		else if (c1 < c2)
			return -1;
		else if (!c1 || !c2)
			return 0;

		++str1;
		++str2;
	}
	return 0;
}

const char *ci::ci_char_traits::find(const char *s1, int n, 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;
}

/** Compare two Anope::strings as ci::strings and find which one is less
 * @param s1 The first string
 * @param s2 The second string
 * @return true if s1 < s2, else false
 */
bool ci::less::operator()(const Anope::string &s1, const Anope::string &s2) const
{
	return s1.ci_str().compare(s2.ci_str()) < 0;
}

sepstream::sepstream(const Anope::string &source, char seperator) : tokens(source), sep(seperator)
{
	last_starting_position = n = tokens.begin();
}

bool sepstream::GetToken(Anope::string &token)
{
	Anope::string::iterator lsp = last_starting_position;

	while (n != tokens.end())
	{
		if (*n == sep || n + 1 == tokens.end())
		{
			last_starting_position = n + 1;
			token = Anope::string(lsp, n + 1 == tokens.end() ? n + 1 : n);

			while (token.length() && token.rfind(sep) == token.length() - 1)
				token.erase(token.end() - 1);

			++n;

			return true;
		}

		++n;
	}

	token.clear();
	return false;
}

const Anope::string sepstream::GetRemaining()
{
	return Anope::string(n, tokens.end());
}

bool sepstream::StreamEnd()
{
	return n == tokens.end();
}