aboutsummaryrefslogtreecommitdiff
/*
 * InspIRCd -- Internet Relay Chat Daemon
 *
 *   Copyright (C) 2026 Sadie Powell <sadie@witchery.services>
 *
 * This file is part of InspIRCd.  InspIRCd is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 2.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#pragma once

namespace insp
{
	template<typename, typename>
	struct casemapped_equals_obj;
	template<typename>
	struct casemapped_hash_obj;
	template<typename, typename>
	struct casemapped_less_obj;

	/** Holds a list of characters and the value they map to. */
	using casemap = unsigned char;

	/** A flat map where the key is a case insensitive string using the IRC casemapping. */
	template<typename Value, typename Key = std::string>
	using casemapped_flat_map = insp::flat_map<std::string, Value, casemapped_less_obj<Key, Key>>;

	/** A flat multimap where the key is a case insensitive string using the IRC casemapping. */
	template<typename Value, typename Key = std::string>
	using casemapped_flat_multimap = insp::flat_multimap<std::string, Value, casemapped_less_obj<Key, Key>>;

	/** A flat set where the key is a case insensitive string using the IRC casemapping. */
	template<typename Key = std::string>
	using casemapped_flat_set = insp::flat_set<Key, casemapped_less_obj<Key, Key>>;

	/** A map where the key is a case insensitive string using the IRC casemapping. */
	template<typename Value, typename Key = std::string>
	using casemapped_map = std::map<Key, Value, casemapped_less_obj<Key, Key>>;

	/** A flat multimap where the key is a case insensitive string using the IRC casemapping. */
	template<typename Value, typename Key = std::string>
	using casemapped_multimap = std::multimap<Key, Value, casemapped_less_obj<Key, Key>>;

	/** An unordered map where the key is a case insensitive string using the IRC casemapping. */
	template<typename Value, typename Key = std::string>
	using casemapped_unordered_map = std::unordered_map<Key, Value, casemapped_hash_obj<Key>, casemapped_equals_obj<Key, Key>>;

	/** Determines if \p str1 and \p str2 are equivalent when compared case insensitively using the
	 * configured IRC casemapping.
	 * @param str1 The first string to compare.
	 * @param str2 The second string to compare.
	 * @return True if \p str1 and \p str2 are equivalent; otherwise, false.
	 */
	CoreExport bool casemapped_equals(const std::string_view& str1, const std::string_view& str2);

	/** Determines if \p str1 is lexographically less than \p str2 when compared insensitively using
	 * the configured IRC casemapping.
	 * @param str1 The first string to compare.
	 * @param str2 The second string to compare.
	 * @return True if \p str1 is ranked lower than \p str2; otherwise, false.
	 */
	CoreExport bool casemapped_less(const std::string_view& str1, const std::string_view& str2);

	/** Determines the unique hash of \p str for use in a hash map when hashed insensitively using
	 * the configured IRC casemapping.
	 * @param str The string to hash.
	 * @return The unique hash of \p str.
	 */
	CoreExport size_t casemapped_hash(const std::string_view& str);
}

/** A casemapping that uses ASCII rules, i.e. A-Z are mapped to a-z. */
extern CoreExport const insp::casemap ascii_case_insensitive_map[256];

/** The currently configured casemapping. This defaults to \ref ascii_case_insensitive_map. */
extern CoreExport const insp::casemap* national_case_insensitive_map;

/** IRC casemapping variant of \p std::equal_to<String>. */
template<typename String1, typename String2>
struct insp::casemapped_equals_obj
{
	/** @copydoc insp::casemapped_equals */
	inline bool operator()(const String1& str1, const String2& str2) const
	{
		return insp::casemapped_equals(str1, str2);
	}
};

/** IRC casemapping variant of std::hash<String>. */
template<typename String>
struct insp::casemapped_hash_obj
{
	/** @copydoc insp::casemapped_hash */
	inline size_t operator()(const String& str) const
	{
		return insp::casemapped_hash(str);
	}
};

/** IRC casemapping variant of std::less<String>. */
template<typename String1, typename String2>
struct insp::casemapped_less_obj
{
	/** @copydoc insp::casemapped_less */
	inline bool operator()(const String1& str1, const String2& str2) const
	{
		return insp::casemapped_less(str1, str2);
	}
};