tag_detail.hpp #1

  • //
  • guest/
  • ShadauxCat/
  • Sprawl/
  • Mainline/
  • tag/
  • detail/
  • tag_detail.hpp
  • View
  • Commits
  • Open Download .zip Download (38 KB)
#pragma once

#include "../tag_list_info.hpp"

namespace sprawl
{
	template<ssize_t t_Len, char... t_Chars>
	struct Tag;

	namespace detail
	{
		template<ssize_t t_Size>
		struct SizeChecker
		{
			static_assert(t_Size <= SPRAWL_CHR_MAX, "Size of tag exceeds SPRAWL_CHR_MAX; please increase SPRAWL_CHR_MAX to a larger power of 2.");
			static constexpr ssize_t value = t_Size <= SPRAWL_CHR_MAX ? t_Size : SPRAWL_CHR_MAX;
		};

		template<ssize_t t_Idx>
		struct IsPositive
		{
			static constexpr bool value = (t_Idx > 0);
		};

		template<char t_SearchChar, char t_FirstChar, char... t_MoreChars>
		struct CharIn
		{
			static constexpr bool value = (t_SearchChar == t_FirstChar ? true : CharIn<t_SearchChar, t_MoreChars...>::value);
		};

		template<char t_SearchChar, char t_LastChar>
		struct CharIn<t_SearchChar, t_LastChar>
		{
			static constexpr bool value = (t_SearchChar == t_LastChar);
		};

		template<typename t_ConditionType, char... t_AdditionalChars>
		struct MeetsCondition;

		template<typename t_ConditionType, char t_CurrentChar, char... t_AdditionalChars>
		struct MeetsCondition<t_ConditionType, t_CurrentChar, t_AdditionalChars...>
		{
			static constexpr bool value = t_ConditionType::template Check<t_CurrentChar>::value ? MeetsCondition<t_ConditionType, t_AdditionalChars...>::value : false;
		};

		template<typename t_ConditionType, char t_CurrentChar>
		struct MeetsCondition<t_ConditionType, t_CurrentChar>
		{
			static constexpr bool value = t_ConditionType::template Check<t_CurrentChar>::value;
		};

		template<typename t_ConditionType>
		struct MeetsCondition<t_ConditionType>
		{
			static constexpr bool value = false;
		};

		template<typename t_ConditionType, char t_PreviousChar, char... t_AdditionalChars>
		struct MeetsComplexCondition;

		template<typename t_ConditionType, char t_PreviousChar, char t_CurrentChar, char... t_AdditionalChars>
		struct MeetsComplexCondition<t_ConditionType, t_PreviousChar, t_CurrentChar, t_AdditionalChars...>
		{
			static constexpr bool value = t_ConditionType::template ComplexCheck<t_PreviousChar, t_CurrentChar>::value ? MeetsComplexCondition<t_ConditionType, t_CurrentChar, t_AdditionalChars...>::value : false;
		};

		template<typename t_ConditionType, char t_PreviousChar, char t_CurrentChar>
		struct MeetsComplexCondition<t_ConditionType, t_PreviousChar, t_CurrentChar>
		{
			static constexpr bool value = t_ConditionType::template ComplexCheck<t_PreviousChar, t_CurrentChar>::value;
		};

		template<typename t_ConditionType, char t_PreviousChar>
		struct MeetsComplexCondition<t_ConditionType, t_PreviousChar>
		{
			static constexpr bool value = false;
		};

		template<ssize_t t_Length, ssize_t t_Idx, typename t_CharsSoFarType, bool t_LengthIsPositive, bool t_IdxIsPositive, char... t_Chars>
		struct TagWrapper;

		template<ssize_t t_Idx, typename t_CharsSoFarType, char t_FirstChar, char... t_Chars>
		struct TagWrapper<0, t_Idx, t_CharsSoFarType, true, true, t_FirstChar, t_Chars...>
		{
			typedef t_CharsSoFarType type;
		};

		template<ssize_t t_Length, typename t_CharsSoFarType, char t_FirstChar, char... t_Chars>
		struct TagWrapper<t_Length, t_Length, t_CharsSoFarType, true, true, t_FirstChar, t_Chars...>
		{
			typedef typename t_CharsSoFarType::template AppendChar<t_FirstChar> type;
		};

		template<ssize_t t_Length, ssize_t t_Idx, typename t_CharsSoFarType, char t_FirstChar, char... t_Chars>
		struct TagWrapper<t_Length, t_Idx, t_CharsSoFarType, true, true, t_FirstChar, t_Chars...>
		{
			typedef typename TagWrapper<t_Length, t_Idx + 1, typename t_CharsSoFarType::template AppendChar<t_FirstChar>, true, IsPositive<t_Idx + 1>::value, t_Chars...>::type type;
		};

		template<ssize_t t_Length, ssize_t t_Idx, typename t_TagType, bool t_IdxIsPositive, char... t_Chars>
		struct TagWrapper<t_Length, t_Idx, t_TagType, false, t_IdxIsPositive, t_Chars...>
		{
			typedef t_TagType type;
		};


		template<ssize_t t_Length, typename t_CharsSoFarType, char t_FirstChar, char... t_Chars>
		struct TagWrapper<t_Length, t_Length, t_CharsSoFarType, true, false, t_FirstChar, t_Chars...>
		{
			typedef t_CharsSoFarType type;
		};

		template<ssize_t t_Length, ssize_t t_Idx, typename t_CharsSoFarType, char t_FirstChar, char... t_Chars>
		struct TagWrapper<t_Length, t_Idx, t_CharsSoFarType, true, false, t_FirstChar, t_Chars...>
		{
			typedef typename TagWrapper<t_Length, t_Idx + 1, t_CharsSoFarType, true, IsPositive<t_Idx + 1>::value, t_Chars...>::type type;
		};

		template<template <char t_PreviousChar, char t_CurrentChar> class t_TransformType, typename t_CharsSoFarType, char t_PreviousChar, char... t_Chars>
		struct TransformTag
		{

		};

		template<template <char t_PreviousChar, char t_CurrentChar> class t_TransformType, typename t_CharsSoFarType, char t_PreviousChar>
		struct TransformTag<t_TransformType, t_CharsSoFarType, t_PreviousChar>
		{
			typedef t_CharsSoFarType type;
		};

		template<template <char t_PreviousChar, char t_CurrentChar> class t_TransformType, typename t_CharsSoFarType, char t_PreviousChar, char t_FirstChar, char... t_Chars>
		struct TransformTag<t_TransformType, t_CharsSoFarType, t_PreviousChar, t_FirstChar, t_Chars...>
			: public TransformTag<t_TransformType, typename t_CharsSoFarType::template AppendChar<t_TransformType<t_PreviousChar, t_FirstChar>::value>, t_TransformType<t_PreviousChar, t_FirstChar>::value, t_Chars...>
		{

		};

		template<typename t_TagToSearchType, typename t_TagToFindType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - (t_Idx - ssize_t(t_TagToFindType::length))>::value>
		struct FindTag
		{
			static constexpr ssize_t result = t_TagToSearchType::template Substring<t_Idx, t_TagToFindType::length>::template EqualTo<t_TagToFindType>() ? t_Idx : FindTag<t_TagToSearchType, t_TagToFindType, t_Idx + 1>::result;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, ssize_t t_Idx>
		struct FindTag<t_TagToSearchType, t_TagToFindType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - (t_Idx - ssize_t(t_TagToFindType::length))>::value>
		struct RFindTag
		{
			static constexpr ssize_t result = RFindTag<t_TagToSearchType, t_TagToFindType, t_Idx + 1>::result != -1 ? RFindTag<t_TagToSearchType, t_TagToFindType, t_Idx + 1>::result : t_TagToSearchType::template Substring<t_Idx, t_TagToFindType::length>::template EqualTo<t_TagToFindType>() ? t_Idx : -1;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, ssize_t t_Idx>
		struct RFindTag<t_TagToSearchType, t_TagToFindType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - t_Idx>::value>
		struct FindPred
		{
			static constexpr ssize_t result = t_PredType::template Check<t_TagToSearchType::template CharAt<t_Idx>()>::value ? t_Idx : FindPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx>
		struct FindPred<t_TagToSearchType, t_PredType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - t_Idx>::value>
		struct RFindPred
		{
			static constexpr ssize_t result = RFindPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result != -1 ? RFindPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result : t_PredType::template Check<t_TagToSearchType::template CharAt<t_Idx>()>::value ? t_Idx : -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx>
		struct RFindPred<t_TagToSearchType, t_PredType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - t_Idx>::value>
		struct FindNotPred
		{
			static constexpr ssize_t result = (!t_PredType::template Check<t_TagToSearchType::template CharAt<t_Idx>()>::value) ? t_Idx : FindNotPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx>
		struct FindNotPred<t_TagToSearchType, t_PredType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx, bool t_IdxIsPositive = IsPositive<ssize_t(t_TagToSearchType::length) - t_Idx>::value>
		struct RFindNotPred
		{
			static constexpr ssize_t result = RFindNotPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result != -1 ? RFindNotPred<t_TagToSearchType, t_PredType, t_Idx + 1>::result : (!t_PredType::template Check<t_TagToSearchType::template CharAt<t_Idx>()>::value) ? t_Idx : -1;
		};

		template<typename t_TagToSearchType, typename t_PredType, ssize_t t_Idx>
		struct RFindNotPred<t_TagToSearchType, t_PredType, t_Idx, false>
		{
			static constexpr ssize_t result = -1;
		};

		template<typename t_TagToSearchType, typename t_TagToCountType, ssize_t t_Start, ssize_t t_End, bool t_WasFound = (t_TagToSearchType::template Find<t_TagToCountType, t_Start, t_End>() != -1)>
		struct CountTag
		{
			static constexpr ssize_t value = 1 + CountTag<t_TagToSearchType, t_TagToCountType, t_TagToSearchType::template Find<t_TagToCountType, t_Start, t_End>() + 1, t_End>::value;
		};

		template<typename t_TagToSearchType, typename t_TagToCountType, ssize_t t_Start, ssize_t t_End>
		struct CountTag<t_TagToSearchType, t_TagToCountType, t_Start, t_End, false>
		{
			static constexpr ssize_t value = 0;
		};

		template<size_t t_Idx>
		struct HasGetTestHelper
		{
			template<typename t_Type, typename = typename std::enable_if<(t_Idx < TagListInfo<t_Type>::numElements)>::type>
				static std::true_type HasGetTest(const t_Type&);

				static std::false_type HasGetTest(...);
		};

		template<class t_Type, size_t t_Idx>
		using HasGet = decltype(HasGetTestHelper<t_Idx>::HasGetTest(std::declval<t_Type>()));

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, size_t t_Idx, typename t_NextIndexExistsType>
		struct FindTagInList
		{
			static constexpr ssize_t thisTagLoc = t_TagToSearchType::template Find<typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type>();
			static constexpr ssize_t nextTagLoc = FindTagInList<t_TagToSearchType, t_AccessibleByGetType, t_Idx + 1, HasGet<t_AccessibleByGetType, t_Idx + 2>>::value;
			static constexpr ssize_t value = thisTagLoc < nextTagLoc ? thisTagLoc == -1 ? nextTagLoc : thisTagLoc : nextTagLoc == -1 ? thisTagLoc : nextTagLoc;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, size_t t_Idx>
		struct FindTagInList<t_TagToSearchType, t_AccessibleByGetType, t_Idx, std::false_type>
		{
			static constexpr ssize_t value = t_TagToSearchType::template Find<typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type>();
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, size_t t_Idx, typename t_NextIndexExistsType>
		struct RFindTagInList
		{
			static constexpr ssize_t thisTagLoc = t_TagToSearchType::template RFind<typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type>();
			static constexpr ssize_t nextTagLoc = RFindTagInList<t_TagToSearchType, t_AccessibleByGetType, t_Idx + 1, HasGet<t_AccessibleByGetType, t_Idx + 2>>::value;
			static constexpr ssize_t value = thisTagLoc > nextTagLoc ? thisTagLoc : nextTagLoc;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, size_t t_Idx>
		struct RFindTagInList<t_TagToSearchType, t_AccessibleByGetType, t_Idx, std::false_type>
		{
			static constexpr ssize_t value = t_TagToSearchType::template RFind<typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type>();
		};

		template<typename t_TagToJoinType, typename t_AccessibleByGetType, size_t t_Idx, typename t_NextIndexExistsType>
		struct JoinTags
		{
			typedef typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type
				::template Append<t_TagToJoinType>
				::template Append<typename JoinTags<t_TagToJoinType, t_AccessibleByGetType, t_Idx + 1, HasGet<t_AccessibleByGetType, t_Idx + 2>>::type> type;
		};

		template<typename t_TagToJoinType, typename t_AccessibleByGetType, size_t t_Idx>
		struct JoinTags<t_TagToJoinType, t_AccessibleByGetType, t_Idx, std::false_type>
		{
			typedef typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type type;
		};

		template<typename t_TagToJoinType, ssize_t t_Start, typename t_AccessibleByGetType, size_t t_Idx, typename t_NextIndexExistsType>
		struct MatchLength
		{
			typedef typename std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type thisType;
			static constexpr ssize_t length = thisType::length;
			static constexpr bool match = t_TagToJoinType::template Substring<t_Start, length>::template EqualTo<thisType>();
			static constexpr ssize_t value = match ? length : MatchLength<t_TagToJoinType, t_Start, t_AccessibleByGetType, t_Idx + 1, HasGet<t_AccessibleByGetType, t_Idx + 2>>::value;
		};

		template<typename t_TagToJoinType, ssize_t t_Start, typename t_AccessibleByGetType, size_t t_Idx>
		struct MatchLength<t_TagToJoinType, t_Start, t_AccessibleByGetType, t_Idx, std::false_type>
		{
			static constexpr ssize_t value = std::remove_reference<typename TagListInfo<t_AccessibleByGetType>::template Element<t_Idx>>::type::length;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt = t_TagToSearchType::template Find<t_TagToFindType>()>
		struct ReplaceTags
		{
			typedef typename t_TagToSearchType::template Substring<0, t_ReplaceAt>::template Append<t_ReplacementType>::template Append<typename ReplaceTags<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + t_TagToFindType::length>, t_TagToFindType, t_ReplacementType, t_Count - 1>::type> type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_Count>
		struct ReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct ReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType>
		struct ReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt = t_TagToSearchType::template FindFirstInList<t_AccessibleByGetType>()>
		struct ReplaceTagsInList
		{
			typedef typename t_TagToSearchType::template Substring<0, t_ReplaceAt>::template Append<t_ReplacementType>::template Append<typename ReplaceTagsInList<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + MatchLength<t_TagToSearchType, t_ReplaceAt, t_AccessibleByGetType, 0, HasGet<t_AccessibleByGetType, 1>>::value>, t_AccessibleByGetType, t_ReplacementType, t_Count - 1>::type> type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_Count>
		struct ReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct ReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType>
		struct ReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt>
		struct ReplaceTagsAnyOf
		{
			typedef typename t_TagToSearchType::
				template Substring<0, t_ReplaceAt>::
				template Append<t_ReplacementType>::
				template Append<
				typename ReplaceTagsAnyOf<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + 1>,
				t_PredType,
				t_ReplacementType,
				t_Count - 1,
				t_TagToSearchType::template Substring<t_ReplaceAt + 1>::template FindFirstOf<t_PredType>()
				>::type
				> type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count>
		struct ReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct ReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType>
		struct ReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt>
		struct ReplaceTagsAnyNotOf
		{
			typedef typename t_TagToSearchType::
				template Substring<0, t_ReplaceAt>::
				template Append<t_ReplacementType>::
				template Append<
				typename ReplaceTagsAnyNotOf<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + 1>,
				t_PredType,
				t_ReplacementType,
				t_Count - 1,
				t_TagToSearchType::template Substring<t_ReplaceAt + 1>::template FindFirstNotOf<t_PredType>()
				>::type
				> type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count>
		struct ReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct ReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType>
		struct ReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt = t_TagToSearchType::template RFind<t_TagToFindType>()>
		struct RReplaceTags
		{
			typedef typename RReplaceTags<
				typename t_TagToSearchType::template Substring<0, t_ReplaceAt>, t_TagToFindType, t_ReplacementType, t_Count - 1
			>::type::template Append<t_ReplacementType>::template Append<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + t_TagToFindType::length>
			> type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_Count>
		struct RReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct RReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_TagToFindType, typename t_ReplacementType>
		struct RReplaceTags<t_TagToSearchType, t_TagToFindType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};


		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt = t_TagToSearchType::template FindLastInList<t_AccessibleByGetType>()>
		struct RReplaceTagsInList
		{
			typedef typename RReplaceTagsInList<
				typename t_TagToSearchType::template Substring<0, t_ReplaceAt>, t_AccessibleByGetType, t_ReplacementType, t_Count - 1
			>::type::template Append<t_ReplacementType>::template Append<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + MatchLength<t_TagToSearchType, t_ReplaceAt, t_AccessibleByGetType, 0, HasGet<t_AccessibleByGetType, 1>>::value>
			> type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_Count>
		struct RReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct RReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_ReplacementType>
		struct RReplaceTagsInList<t_TagToSearchType, t_AccessibleByGetType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt>
		struct RReplaceTagsAnyOf
		{
			typedef typename RReplaceTagsAnyOf<
				typename t_TagToSearchType::template Substring<0, t_ReplaceAt>,
				t_PredType,
				t_ReplacementType,
				t_Count - 1,
				t_TagToSearchType::template Substring<0, t_ReplaceAt>::template FindLastOf<t_PredType>()
			>::type
				::template Append<t_ReplacementType>
				::template Append<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + 1>
				> type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count>
		struct RReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct RReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType>
		struct RReplaceTagsAnyOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count, ssize_t t_ReplaceAt>
		struct RReplaceTagsAnyNotOf
		{
			typedef typename RReplaceTagsAnyNotOf<
				typename t_TagToSearchType::template Substring<0, t_ReplaceAt>,
				t_PredType,
				t_ReplacementType,
				t_Count - 1,
				t_TagToSearchType::template Substring<0, t_ReplaceAt>::template FindLastNotOf<t_PredType>()
			>::type
				::template Append<t_ReplacementType>
				::template Append<
				typename t_TagToSearchType::template Substring<t_ReplaceAt + 1>
				> type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_Count>
		struct RReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, t_Count, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType, ssize_t t_ReplaceAt>
		struct RReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, t_ReplaceAt>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSearchType, typename t_PredType, typename t_ReplacementType>
		struct RReplaceTagsAnyNotOf<t_TagToSearchType, t_PredType, t_ReplacementType, 0, -1>
		{
			typedef t_TagToSearchType type;
		};

		template<typename t_TagToSplit, typename t_TypeSoFarType, ssize_t t_Start, ssize_t t_End, ssize_t t_Interval, ssize_t t_Idx, bool t_WithinInterval>
		struct SliceTag
		{
			typedef typename t_TypeSoFarType::template AppendChar<t_TagToSplit::template CharAt<t_Idx>()> interimType;
			static constexpr ssize_t nextIdx = t_Idx + t_Interval;
			typedef typename SliceTag<
				t_TagToSplit, 
				interimType, 
				t_Start, 
				t_End, 
				t_Interval, 
				nextIdx, 
				(t_Start < t_End ? (nextIdx >= t_Start && nextIdx < t_End) : (nextIdx <= t_Start && nextIdx > t_End))
			>::type type;
		};

		template<typename t_TagToSplit, typename t_TypeSoFarType, ssize_t t_Start, ssize_t t_End, ssize_t t_Interval, ssize_t t_Idx>
		struct SliceTag<t_TagToSplit, t_TypeSoFarType, t_Start, t_End, t_Interval, t_Idx, false>
		{
			typedef t_TypeSoFarType type;
		};

		template<char... t_AllChars>
		struct tagToInt_;

		template<bool t_IsDigit, char t_FirstChar, char... t_MoreChars>
		struct TagToIntRecurseIf
		{
			static constexpr uint64_t value = (t_FirstChar - '0') * tagToInt_<t_MoreChars...>::order + tagToInt_<t_MoreChars...>::value;
			static constexpr uint64_t order = tagToInt_<t_MoreChars...>::order * 10;
		};

		template<char t_FirstChar, char... t_MoreChars>
		struct TagToIntRecurseIf<false, t_FirstChar, t_MoreChars...>
		{
			static constexpr uint64_t value = 0;
			static constexpr uint64_t order = 1;
		};

		template<char t_FirstChar, char... t_MoreChars>
		struct tagToInt_<t_FirstChar, t_MoreChars...>
		{
			static constexpr uint64_t value = TagToIntRecurseIf<(t_FirstChar >= '0' && t_FirstChar <= '9'), t_FirstChar, t_MoreChars...>::value;
			static constexpr uint64_t order = TagToIntRecurseIf<(t_FirstChar >= '0' && t_FirstChar <= '9'), t_FirstChar, t_MoreChars...>::order;
		};

		template<char t_FirstChar>
		struct tagToInt_<t_FirstChar>
		{
			static constexpr uint64_t value = (t_FirstChar >= '0' && t_FirstChar <= '9') ? (t_FirstChar - '0') : 0;
			static constexpr uint64_t order = (t_FirstChar >= '0' && t_FirstChar <= '9') ? 10 : 1;
		};

		template<char... t_Chars>
		struct TagToInt;

		template<char t_Char, char... t_Chars>
		struct TagToInt<t_Char, t_Chars...>
		{
			static constexpr int64_t value = int64_t(tagToInt_<t_Char, t_Chars...>::value);
		};

		template<char... t_Chars>
		struct TagToInt<'-', t_Chars...>
		{
			static constexpr int64_t value = -int64_t(tagToInt_<t_Chars...>::value);
		};

		template<char... t_Chars>
		struct TagToInt<'+', t_Chars...>
		{
			static constexpr int64_t value = int64_t(tagToInt_<t_Chars...>::value);
		};

		template<char t_Char>
		struct TagToInt<t_Char>
		{
			static constexpr int64_t value = (t_Char >= '0' && t_Char <= '9') ? (t_Char - '0') : 0;
		};

		template<char... t_AllChars>
		struct tagToDouble_;

		template<bool t_IsDigit, char t_FirstChar, char... t_MoreChars>
		struct TagToDoubleRecurseIf
		{
			static constexpr long double value = (t_FirstChar - '0') * tagToDouble_<t_MoreChars...>::order + tagToDouble_<t_MoreChars...>::value;
			static constexpr long double order = tagToInt_<t_MoreChars...>::order * 10;
		};

		template<char t_FirstChar, char... t_MoreChars>
		struct TagToDoubleRecurseIf<false, t_FirstChar, t_MoreChars...>
		{
			static constexpr long double value = 0;
			static constexpr long double order = 1;
		};

		template<char t_FirstChar, char... t_MoreChars>
		struct tagToDouble_<t_FirstChar, t_MoreChars...>
		{
			static constexpr long double value = TagToDoubleRecurseIf<(t_FirstChar >= '0' && t_FirstChar <= '9'), t_FirstChar, t_MoreChars...>::value;
			static constexpr long double order = TagToDoubleRecurseIf<(t_FirstChar >= '0' && t_FirstChar <= '9'), t_FirstChar, t_MoreChars...>::order;
		};

		template<char... t_MoreChars>
		struct tagToDouble_<'.', t_MoreChars...>
		{
			static constexpr long double value = ((long double)(tagToInt_<t_MoreChars...>::value) / (long double)(tagToInt_<t_MoreChars...>::order));
			static constexpr long double order = 1;
		};

		template<char t_FirstChar>
		struct tagToDouble_<t_FirstChar>
		{
			static constexpr long double value = (t_FirstChar >= '0' && t_FirstChar <= '9') ? (t_FirstChar - '0') : 0;
			static constexpr long double order = (t_FirstChar >= '0' && t_FirstChar <= '9') ? 10 : 1;
		};

		template<>
		struct tagToDouble_<'.'>
		{
			static constexpr long double value = 0;
			static constexpr long double order = 1;
		};

		template<char... t_Chars>
		struct TagToDouble;

		template<char t_Char, char... t_Chars>
		struct TagToDouble<t_Char, t_Chars...>
		{
			static constexpr long double value = tagToDouble_<t_Char, t_Chars...>::value;
		};

		template<char... t_Chars>
		struct TagToDouble<'-', t_Chars...>
		{
			static constexpr long double value = -tagToDouble_<t_Chars...>::value;
		};

		template<char... t_Chars>
		struct TagToDouble<'+', t_Chars...>
		{
			static constexpr long double value = tagToDouble_<t_Chars...>::value;
		};

		template<char t_Char>
		struct TagToDouble<t_Char>
		{
			static constexpr long double value = (t_Char >= '0' && t_Char <= '9') ? (t_Char - '0') : 0;
		};

		template<typename t_TagType>
		struct TagToBool;

		template<ssize_t t_Len, char... t_Chars>
		struct TagToBool<Tag<t_Len, t_Chars...>>
		{
			static constexpr bool value = TagToDouble<t_Chars...>::value != 0.0;
		};

		template<>
		struct TagToBool<Tag<4, 't', 'r', 'u', 'e'>>
		{
			static constexpr bool value = true;
		};

		template<>
		struct TagToBool<Tag<5, 'f', 'a', 'l', 's', 'e'>>
		{
			static constexpr bool value = false;
		};

		//MSVC likes to complain about integer constant overflow here, but hash algorithms use that intentionally so this is being unilaterally disabled for this section.
#if SPRAWL_COMPILER_MSVC
#	pragma warning(push)
#	pragma warning(disable: 4307)
#endif
		namespace murmur3
		{
#if SPRAWL_32_BIT
			constexpr size_t c1 = 0xcc9e2d51;
			constexpr size_t c2 = 0x1b873593;
			constexpr uint8_t r1 = 15;
			constexpr uint8_t r2 = 13;
			constexpr size_t m = 5;
			constexpr size_t n = 0xe6546b64;

			constexpr size_t rotateLeft_(const size_t x, const uint8_t r)
			{
				return (x << r) | (x >> (32 - r));
			}

			template<char t_FirstChar, char t_SecondChar = '\0', char t_ThirdChar = '\0', char t_FourthChar = '\0'>
			struct charsToInt_
			{
#if SPRAWL_LITTLE_ENDIAN
				static constexpr size_t i = t_FourthChar;
				static constexpr size_t i2 = (i << 8) | t_ThirdChar;
				static constexpr size_t i3 = (i2 << 8) | t_SecondChar;
				static constexpr size_t value = (i3 << 8) | t_FirstChar;
#else
				static constexpr size_t i1 = t_FirstChar;
				static constexpr size_t i2 = (i1 << 8) | t_SecondChar;
				static constexpr size_t i3 = (i2 << 8) | t_ThirdChar;
				static constexpr size_t value = (i3 << 8) | t_FourthChar;
#endif
			};
#else
			constexpr size_t c1 = 0x87c37b91114253d5ULL;
			constexpr size_t c2 = 0x4cf5ad432745937fULL;
			constexpr uint8_t r1 = 15;
			constexpr uint8_t r2 = 13;
			constexpr size_t m = 5;
			constexpr size_t n = 0x52dce72938495ab5ULL;

			constexpr size_t rotateLeft_(const size_t x, const uint8_t r)
			{
				return (x << r) | (x >> (64 - r));
			}

			template<char t_FirstChar, char t_SecondChar = '\0', char t_ThirdChar = '\0', char t_FourthChar = '\0', char t_FifthChar = '\0', char t_SixthChar = '\0', char t_SeventhChar = '\0', char t_EighthChar = '\0'>
			struct charsToInt_
			{
#if SPRAWL_LITTLE_ENDIAN
				static constexpr size_t i1 = t_EighthChar;
				static constexpr size_t i2 = (i1 << 8) | t_SeventhChar;
				static constexpr size_t i3 = (i2 << 8) | t_SixthChar;
				static constexpr size_t i4 = (i3 << 8) | t_FifthChar;
				static constexpr size_t i5 = (i4 << 8) | t_FourthChar;
				static constexpr size_t i6 = (i5 << 8) | t_ThirdChar;
				static constexpr size_t i7 = (i6 << 8) | t_SecondChar;
				static constexpr size_t value = (i7 << 8) | t_FirstChar;
#else
				static constexpr size_t i1 = t_FirstChar;
				static constexpr size_t i2 = (i1 << 8) | t_SecondChar;
				static constexpr size_t i3 = (i2 << 8) | t_ThirdChar;
				static constexpr size_t i4 = (i3 << 8) | t_FourthChar;
				static constexpr size_t i5 = (i4 << 8) | t_FifthChar;
				static constexpr size_t i6 = (i5 << 8) | t_SixthChar;
				static constexpr size_t i7 = (i6 << 8) | t_SeventhChar;
				static constexpr size_t value = (i7 << 8) | t_EighthChar;
#endif
			};
#endif

			template<size_t t_FinalChunk, char... t_Chars>
			struct getFinalChunk_;

			template<size_t t_FinalChunk, char t_C1>
			struct getFinalChunk_<t_FinalChunk, t_C1>
			{
				static constexpr size_t value = t_FinalChunk | charsToInt_<t_C1>::value;
			};

			template<size_t t_FinalChunk, char t_C1, char t_C2>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2>::value;
			};

			template<size_t t_FinalChunk, char t_C1, char t_C2, char t_C3>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2, t_C3>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2, t_C3>::value;
			};

#if SPRAWL_64_BIT
			template<size_t t_FinalChunk, char t_C1, char t_C2, char t_C3, char t_C4>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2, t_C3, t_C4>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2, t_C3, t_C4>::value;
			};

			template<size_t t_FinalChunk, char t_C1, char t_C2, char t_C3, char t_C4, char t_C5>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2, t_C3, t_C4, t_C5>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2, t_C3, t_C4, t_C5>::value;
			};

			template<size_t t_FinalChunk, char t_C1, char t_C2, char t_C3, char t_C4, char t_C5, char t_C6>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2, t_C3, t_C4, t_C5, t_C6>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2, t_C3, t_C4, t_C5, t_C6>::value;
			};

			template<size_t t_FinalChunk, char t_C1, char t_C2, char t_C3, char t_C4, char t_C5, char t_C6, char t_C7>
			struct getFinalChunk_<t_FinalChunk, t_C1, t_C2, t_C3, t_C4, t_C5, t_C6, t_C7>
			{
				static constexpr size_t finalChunk2 = t_FinalChunk | size_t(t_C1);
				static constexpr size_t value = getFinalChunk_<finalChunk2 << 8, t_C2, t_C3, t_C4, t_C5, t_C6, t_C7>::value;
			};
#endif

			template<size_t t_OutputHash, char... t_Chars>
			struct Murmur3
			{
				static constexpr size_t finalChunk = 0;
				static constexpr size_t finalChunk2 = getFinalChunk_<finalChunk, t_Chars...>::value;
				static constexpr size_t finalChunk3 = finalChunk2 * c1;
				static constexpr size_t finalChunk4 = rotateLeft_(finalChunk3, r1);
				static constexpr size_t finalChunk5 = finalChunk4 * c2;
				static constexpr size_t value = t_OutputHash ^ finalChunk5;
			};

#if SPRAWL_64_BIT
			template<size_t t_OutputHash, char t_FirstChar, char t_SecondChar, char t_ThirdChar, char t_FourthChar, char t_FifthChar, char t_SixthChar, char t_SeventhChar, char t_EighthChar, char... t_MoreChars>
			struct Murmur3<t_OutputHash, t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar, t_FifthChar, t_SixthChar, t_SeventhChar, t_EighthChar, t_MoreChars...>
			{
				static constexpr size_t k = charsToInt_<t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar, t_FifthChar, t_SixthChar, t_SeventhChar, t_EighthChar>::value;
				static constexpr size_t k2 = k * c1;
				static constexpr size_t k3 = rotateLeft_(k2, r1);
				static constexpr size_t k4 = k3 * c2;
				static constexpr size_t output1 = t_OutputHash ^ k4;
				static constexpr size_t output2 = rotateLeft_(output1, r2);
				static constexpr size_t output3 = (output2 * m) + n;
				static constexpr size_t value = Murmur3<output3, t_MoreChars...>::value;
			};

			template<size_t t_OutputHash, char t_FirstChar, char t_SecondChar, char t_ThirdChar, char t_FourthChar, char t_FifthChar, char t_SixthChar, char t_SeventhChar, char t_EighthChar>
			struct Murmur3<t_OutputHash, t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar, t_FifthChar, t_SixthChar, t_SeventhChar, t_EighthChar>
			{
				static constexpr size_t k = charsToInt_<t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar, t_FifthChar, t_SixthChar, t_SeventhChar, t_EighthChar>::value;
				static constexpr size_t k2 = k * c1;
				static constexpr size_t k3 = rotateLeft_(k2, r1);
				static constexpr size_t k4 = k3 * c2;
				static constexpr size_t output1 = t_OutputHash ^ k4;
				static constexpr size_t output2 = rotateLeft_(output1, r2);
				static constexpr size_t value = (output2 * m) + n;
			};
		}
#else
			template<size_t t_OutputHash, char t_FirstChar, char t_SecondChar, char t_ThirdChar, char t_FourthChar, char... t_MoreChars>
			struct Murmur3<t_OutputHash, t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar, t_MoreChars...>
			{
				static constexpr size_t k = charsToInt_<t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar>::value;
				static constexpr size_t k2 = k * c1;
				static constexpr size_t k3 = rotateLeft_(k2, r1);
				static constexpr size_t k4 = k3 * c2;
				static constexpr size_t output1 = t_OutputHash ^ k4;
				static constexpr size_t output2 = rotateLeft_(output1, r2);
				static constexpr size_t output3 = (output2 * m) + n;
				static constexpr size_t value = Murmur3<output3, t_MoreChars...>::value;
			};

			template<size_t t_OutputHash, char t_FirstChar, char t_SecondChar, char t_ThirdChar, char t_FourthChar>
			struct Murmur3<t_OutputHash, t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar>
			{
				static constexpr size_t k = charsToInt_<t_FirstChar, t_SecondChar, t_ThirdChar, t_FourthChar>::value;
				static constexpr size_t k2 = k * c1;
				static constexpr size_t k3 = rotateLeft_(k2, r1);
				static constexpr size_t k4 = k3 * c2;
				static constexpr size_t output1 = t_OutputHash ^ k4;
				static constexpr size_t output2 = rotateLeft_(output1, r2);
				static constexpr size_t value = (output2 * m) + n;
			};
		}
#endif
#if SPRAWL_COMPILER_MSVC
#	pragma warning(pop)
#endif
	}
}
# Change User Description Committed
#1 19906 ShadauxCat - Added tag, compile time string type
- Since tag requires visual studio 2015, removed compatibility code for earlier versions of visual studio
- Improved compiler detection
- Added endianness detection
- Added template if/else helper
- Fixed bug with murmur3 64 bit
- Added seed argument for murmur3

#review-19907