#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 | 23398 | ququlala | "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl." | ||
//guest/ShadauxCat/Sprawl/Mainline/tag/detail/tag_detail.hpp | |||||
#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 |