#pragma once
#include <type_traits>
#include <stddef.h>
#include <sys/types.h>
#include <stdint.h>
#include "../common/compat.hpp"
#include "../if/if.hpp"
#ifndef SPRAWL_CHR_MAX
#define SPRAWL_CHR_MAX 64
#endif
static_assert(SPRAWL_CHR_MAX >= 2 && (SPRAWL_CHR_MAX & (SPRAWL_CHR_MAX - 1)) == 0 && SPRAWL_CHR_MAX <= 32768, "SPRAWL_CHR_MAX must be a power of 2 between 2 and 32768");
#define SPRAWL_CHR(str, size, idx) (idx < size ? str[idx] : '\0')
#define SPRAWL_CHR_2(str, size, idx) SPRAWL_CHR(str, size, idx), SPRAWL_CHR(str, size, idx+1)
#if SPRAWL_CHR_MAX >= 4
#define SPRAWL_CHR_4(str, size, idx) SPRAWL_CHR_2(str, size, idx), SPRAWL_CHR_2(str, size, idx+2)
#endif
#if SPRAWL_CHR_MAX >= 8
#define SPRAWL_CHR_8(str, size, idx) SPRAWL_CHR_4(str, size, idx), SPRAWL_CHR_4(str, size, idx+4)
#endif
#if SPRAWL_CHR_MAX >= 16
#define SPRAWL_CHR_16(str, size, idx) SPRAWL_CHR_8(str, size, idx), SPRAWL_CHR_8(str, size, idx+8)
#endif
#if SPRAWL_CHR_MAX >= 32
#define SPRAWL_CHR_32(str, size, idx) SPRAWL_CHR_16(str, size, idx), SPRAWL_CHR_16(str, size, idx+16)
#endif
#if SPRAWL_CHR_MAX >= 64
#define SPRAWL_CHR_64(str, size, idx) SPRAWL_CHR_32(str, size, idx), SPRAWL_CHR_32(str, size, idx+32)
#endif
#if SPRAWL_CHR_MAX >= 128
#define SPRAWL_CHR_128(str, size, idx) SPRAWL_CHR_64(str, size, idx), SPRAWL_CHR_64(str, size, idx+64)
#endif
#if SPRAWL_CHR_MAX >= 256
#define SPRAWL_CHR_256(str, size, idx) SPRAWL_CHR_128(str, size, idx), SPRAWL_CHR_128(str, size, idx+128)
#endif
#if SPRAWL_CHR_MAX >= 512
#define SPRAWL_CHR_512(str, size, idx) SPRAWL_CHR_256(str, size, idx), SPRAWL_CHR_256(str, size, idx+256)
#endif
#if SPRAWL_CHR_MAX >= 1024
#define SPRAWL_CHR_1024(str, size, idx) SPRAWL_CHR_512(str, size, idx), SPRAWL_CHR_512(str, size, idx+512)
#endif
#if SPRAWL_CHR_MAX >= 2048
#define SPRAWL_CHR_2048(str, size, idx) SPRAWL_CHR_1024(str, size, idx), SPRAWL_CHR_1024(str, size, idx+1024)
#endif
#if SPRAWL_CHR_MAX >= 4096
#define SPRAWL_CHR_4096(str, size, idx) SPRAWL_CHR_2048(str, size, idx), SPRAWL_CHR_2048(str, size, idx+2048)
#endif
#if SPRAWL_CHR_MAX >= 8192
#define SPRAWL_CHR_8192(str, size, idx) SPRAWL_CHR_4096(str, size, idx), SPRAWL_CHR_4096(str, size, idx+4096)
#endif
#if SPRAWL_CHR_MAX >= 16384
#define SPRAWL_CHR_16384(str, size, idx) SPRAWL_CHR_8192(str, size, idx), SPRAWL_CHR_8192(str, size, idx+8192)
#endif
#if SPRAWL_CHR_MAX >= 32768
#define SPRAWL_CHR_32768(str, size, idx) SPRAWL_CHR_16384(str, size, idx), SPRAWL_CHR_16384(str, size, idx+16384)
#endif
#define SPRAWL_CHR_MACRO_2(val) SPRAWL_CHR_ ## val
#define SPRAWL_CHR_MACRO(val) SPRAWL_CHR_MACRO_2(val)
#define SPRAWL_CHR_MAX_MACRO SPRAWL_CHR_MACRO(SPRAWL_CHR_MAX)
#define SPRAWL_TAG(s) ::sprawl::detail::TagWrapper< ::sprawl::detail::SizeChecker<sizeof(s) - 1>::value, 1, ::sprawl::Tag<0>, ::sprawl::detail::IsPositive<sizeof(s) - 1>::value, true, SPRAWL_CHR_MAX_MACRO(s, sizeof(s), 0)>::type
#include "detail/tag_detail.hpp"
#include "type_list.hpp"
namespace sprawl
{
//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
#if SPRAWL_64_BIT
template<size_t t_Seed>
struct Murmur3
{
template<char... t_Chars>
struct Hash
{
static constexpr size_t outputHash1 = detail::murmur3::Murmur3<t_Seed, t_Chars...>::value;
static constexpr size_t outputHash2 = outputHash1 ^ sizeof...(t_Chars);
static constexpr size_t outputHash3 = outputHash2 ^ (outputHash2 >> 33);
static constexpr size_t outputHash4 = outputHash3 * 0xff51afd7ed558ccdULL;
static constexpr size_t outputHash5 = outputHash4 ^ (outputHash4 >> 33);
static constexpr size_t outputHash6 = outputHash5 * 0xc4ceb9fe1a85ec53ULL;
static constexpr size_t value = outputHash6 ^ (outputHash6 >> 33);
};
};
#else
template<size_t t_Seed>
struct Murmur3
{
template<char... t_Chars>
struct Hash
{
static constexpr size_t outputHash1 = detail::murmur3::Murmur3<t_Seed, t_Chars...>::value;
static constexpr size_t outputHash2 = outputHash1 ^ sizeof...(t_Chars);
static constexpr size_t outputHash3 = outputHash2 ^ (outputHash2 >> 16);
static constexpr size_t outputHash4 = outputHash3 * 0x85ebca6b;
static constexpr size_t outputHash5 = outputHash4 ^ (outputHash4 >> 13);
static constexpr size_t outputHash6 = outputHash5 * 0xc2b2ae35;
static constexpr size_t value = outputHash6 ^ (outputHash6 >> 16);
};
};
#endif
#if SPRAWL_COMPILER_MSVC
# pragma warning(pop)
#endif
template<char... t_Chars>
struct CharIn
{
template<char t_CheckChar>
using Check = detail::CharIn<t_CheckChar, t_Chars...>;
};
struct IsWhitespace
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = detail::CharIn<t_CheckChar, ' ', '\n', '\t', '\v', '\f', '\r'>::value;
};
};
struct IsLineEnding
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = detail::CharIn<t_CheckChar, '\n', '\r'>::value;
};
};
struct IsDigit
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = detail::CharIn<t_CheckChar, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'>::value;
};
};
struct IsUpper
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = ('A' <= t_CheckChar && t_CheckChar <= 'Z');
};
};
struct IsLower
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = ('a' <= t_CheckChar && t_CheckChar <= 'z');
};
};
struct IsAlpha
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = IsUpper::Check<t_CheckChar>::value || IsLower::Check<t_CheckChar>::value;
};
};
struct IsAlnum
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = IsAlpha::Check<t_CheckChar>::value || IsDigit::Check<t_CheckChar>::value;
};
};
struct IsPrintable
{
template<char t_CheckChar>
struct Check
{
static constexpr bool value = (32 <= t_CheckChar && t_CheckChar <= 127) || t_CheckChar < 0;
};
};
struct IsTitle
{
template<char t_PreviousChar, char t_CheckChar>
struct ComplexCheck
{
static constexpr bool value = IsUpper::Check<t_CheckChar>::value ? (IsWhitespace::Check<t_PreviousChar>::value || t_PreviousChar == -1) : !(IsWhitespace::Check<t_PreviousChar>::value || t_PreviousChar == -1);
};
};
template<char t_PreviousChar, char t_CurrentChar>
struct Upper
{
static constexpr char value = (('a' <= t_CurrentChar && t_CurrentChar <= 'z') ? ((t_CurrentChar - 'a') + 'A') : t_CurrentChar);
};
template<char t_PreviousChar, char t_CurrentChar>
struct Lower
{
static constexpr char value = (('A' <= t_CurrentChar && t_CurrentChar <= 'Z') ? ((t_CurrentChar - 'A') + 'a') : t_CurrentChar);
};
template<char t_PreviousChar, char t_CurrentChar>
struct SwapCase
{
static constexpr char value = (('A' <= t_CurrentChar && t_CurrentChar <= 'Z') ? ((t_CurrentChar - 'A') + 'a') : ('a' <= t_CurrentChar && t_CurrentChar <= 'z') ? ((t_CurrentChar - 'a') + 'A') : t_CurrentChar);
};
template<char t_PreviousChar, char t_CurrentChar>
struct Title
{
static constexpr char value = t_PreviousChar == -1 || IsWhitespace::Check<t_PreviousChar>::value ? Upper<t_PreviousChar, t_CurrentChar>::value : Lower<t_PreviousChar, t_CurrentChar>::value;
};
template<char t_PreviousChar, char t_CurrentChar>
struct Capitalize
{
static constexpr char value = t_PreviousChar == -1 ? Upper<t_PreviousChar, t_CurrentChar>::value : Lower<t_PreviousChar, t_CurrentChar>::value;
};
template<ssize_t t_Len, char... t_Chars>
struct Tag
{
public:
static constexpr ssize_t length = t_Len;
static CONSTEXPR_ARRAY char name[t_Len + 1] SPRAWL_CONSTEXPR_INCLASS_INIT({ t_Chars..., '\0' });
typedef ssize_t length_type;
typedef char char_type;
template<ssize_t t_Idx, ssize_t t_Length = t_Len - t_Idx>
using Substring = typename detail::TagWrapper<(t_Idx < 0 ? 0 : (t_Length >(t_Len - t_Idx)) ? (t_Len - t_Idx) : t_Length), t_Idx < 0 ? 0 : (1 - t_Idx), Tag<0>, detail::IsPositive<t_Idx < 0 ? 0 : ((t_Length >(t_Len - t_Idx)) ? (t_Len - t_Idx) : t_Length)>::value, detail::IsPositive<t_Idx < 0 ? 0 : (1 - t_Idx)>::value, t_Chars...>::type;
template<typename t_OtherTagType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t Find()
{
return detail::FindTag<Substring<t_Start, t_End - t_Start>, t_OtherTagType, 0>::result != -1 ? detail::FindTag<Substring<t_Start, t_End - t_Start>, t_OtherTagType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t Find(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return t_Length - 1 <= Tag::length && t_Length - 1 <= (end - start) ? find_(0, start, end, str, t_Chars...) : -1;
}
template<typename t_OtherTagType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t RFind()
{
return detail::RFindTag<Substring<t_Start, t_End - t_Start>, t_OtherTagType, 0>::result != -1 ? detail::RFindTag<Substring<t_Start, t_End - t_Start>, t_OtherTagType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t RFind(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return t_Length - 1 <= Tag::length && t_Length - 1 <= (end - start) ? rfind_(0, start, end, str, t_Chars...) : -1;
}
template<typename t_PredType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindFirstOf()
{
return detail::FindPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result != -1 ? detail::FindPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t FindFirstOf(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return findFirstOf_(0, start, end, str, t_Chars...);
}
template<typename t_PredType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindLastOf()
{
return detail::RFindPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result != -1 ? detail::RFindPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t FindLastOf(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return findLastOf_(0, start, end, str, t_Chars...);
}
template<typename t_PredType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindFirstNotOf()
{
return detail::FindNotPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result != -1 ? detail::FindNotPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t FindFirstNotOf(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return findFirstNotOf_(0, start, end, str, t_Chars...);
}
template<typename t_PredType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindLastNotOf()
{
return detail::RFindNotPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result != -1 ? detail::RFindNotPred<Substring<t_Start, t_End - t_Start>, t_PredType, 0>::result + t_Start : -1;
}
template<ssize_t t_Length>
static constexpr ssize_t FindLastNotOf(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return findLastNotOf_(0, start, end, str, t_Chars...);
}
template<template <char t_PreviousChar, char t_CurrentChar> class t_TransformType>
using Transform = typename detail::TransformTag<t_TransformType, Tag<0>, -1, t_Chars...>::type;
//Using as a namespace so following namespace naming conventions despite being a struct.
struct tag_detail
{
template<typename t_OtherTagType>
struct AppendTagHelper
{
};
template<ssize_t t_OtherLength, char... t_OtherChars>
struct AppendTagHelper<Tag<t_OtherLength, t_OtherChars...>>
{
typedef Tag<t_Len + t_OtherLength, t_Chars..., t_OtherChars...> type;
};
#if SPRAWL_COMPILER_MSVC
template<ssize_t t_TargetIdx, bool t_CharWithinBounds, char... t_AdditionalChars>
struct CharAt;
template<ssize_t t_TargetIdx, bool t_CharWithinBounds, char t_FirstChar, char... t_AdditionalChars>
struct CharAt<t_TargetIdx, t_CharWithinBounds, t_FirstChar, t_AdditionalChars...>
{
static constexpr char value = t_TargetIdx < 0 ? -1 :
t_TargetIdx == 0 ? t_FirstChar :
CharAt<t_TargetIdx - 1, t_CharWithinBounds, t_AdditionalChars...>::value;
};
template<ssize_t t_TargetIdx, bool t_CharWithinBounds, char t_FirstChar>
struct CharAt<t_TargetIdx, t_CharWithinBounds, t_FirstChar>
{
static constexpr char value = t_TargetIdx < 0 ? -1 : t_TargetIdx == 0 ? t_FirstChar : -1;
};
template<ssize_t t_TargetIdx, bool t_CharWithinBounds>
struct CharAt<t_TargetIdx, t_CharWithinBounds>
{
static constexpr char value = -1;
};
template<char t_NextChar, bool t_CharWithinBounds>
struct CharAt<-1, t_CharWithinBounds, t_NextChar>
{
static constexpr char value = -1;
};
#else
template<ssize_t t_TargetIdx, bool t_CharWithinBounds, char... t_Chars>
struct CharAt
{
static constexpr char value = name[t_TargetIdx];
};
template<ssize_t t_TargetIdx, char... t_Chars>
struct CharAt<t_TargetIdx, false, t_Chars...>
{
static constexpr char value = -1;
};
#endif
template<typename t_PredicateType, ssize_t t_Idx = 0, bool t_ShouldStrip = t_PredicateType::template Check<CharAt<t_Idx, t_Idx >= 0 && t_Idx <= t_Len, t_Chars...>::value>::value>
struct LStripHelper
{
typedef typename LStripHelper<t_PredicateType, t_Idx + 1>::type type;
};
template<typename t_PredicateType, ssize_t t_Idx>
struct LStripHelper<t_PredicateType, t_Idx, false>
{
typedef Substring<t_Idx> type;
};
template<typename t_PredicateType, ssize_t t_Idx = 0, bool t_ShouldStrip = t_PredicateType::template Check<CharAt<t_Len - t_Idx - 1, (t_Len - t_Idx - 1) >= 0 && (t_Len - t_Idx - 1) <= t_Len, t_Chars...>::value>::value>
struct RStripHelper
{
typedef typename RStripHelper<t_PredicateType, t_Idx + 1>::type type;
};
template<typename t_PredicateType, ssize_t t_Idx>
struct RStripHelper<t_PredicateType, t_Idx, false>
{
typedef Substring<0, t_Len - t_Idx> type;
};
template<typename t_SearchStringType, ssize_t t_SplitLocation>
struct PartitionHelper
{
typedef TypeList<Substring<0, t_SplitLocation>, t_SearchStringType, Substring<t_SplitLocation + t_SearchStringType::length>> type;
};
template<typename t_SearchStringType>
struct PartitionHelper<t_SearchStringType, -1>
{
typedef TypeList<Tag, SPRAWL_TAG(""), SPRAWL_TAG("")> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelper
{
typedef typename SplitHelper<
typename t_TagToSearchType::template Substring<t_SplitLocation + t_SearchStringType::length>,
t_SearchStringType,
typename t_TypeSoFar::template Append<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>
>,
t_TagToSearchType::template Substring<t_SplitLocation + t_SearchStringType::length>::template Find<t_SearchStringType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct SplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct SplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperInList
{
typedef typename SplitHelperInList<
typename t_TagToSearchType::template Substring<
t_SplitLocation + detail::MatchLength<
t_TagToSearchType, t_SplitLocation, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>
>::value
>,
t_AccessibleByGetType,
typename t_TypeSoFar::template Append<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>
>,
t_TagToSearchType::template Substring<
t_SplitLocation + detail::MatchLength<
t_TagToSearchType, t_SplitLocation, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>
>::value
>::template FindFirstInList<t_AccessibleByGetType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct SplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct SplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperAnyOf
{
typedef typename SplitHelperAnyOf<
typename t_TagToSearchType::template Substring<t_SplitLocation + 1>,
t_PredType,
typename t_TypeSoFar::template Append<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>
>,
t_TagToSearchType::template Substring<t_SplitLocation + 1>::template FindFirstOf<t_PredType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct SplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct SplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperAnyNotOf
{
typedef typename SplitHelperAnyNotOf<
typename t_TagToSearchType::template Substring<t_SplitLocation + 1>,
t_PredType,
typename t_TypeSoFar::template Append<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>
>,
t_TagToSearchType::template Substring<t_SplitLocation + 1>::template FindFirstNotOf<t_PredType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct SplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct SplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct SplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelper
{
typedef typename RSplitHelper<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>,
t_SearchStringType,
typename TypeList<typename t_TagToSearchType::template Substring<t_SplitLocation + t_SearchStringType::length>>::template Extend<t_TypeSoFar>,
t_TagToSearchType::template Substring<0, t_SplitLocation>::template RFind<t_SearchStringType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct RSplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_SearchStringType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct RSplitHelper<t_TagToSearchType, t_SearchStringType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperInList
{
typedef typename RSplitHelperInList<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>,
t_AccessibleByGetType,
typename TypeList<typename t_TagToSearchType::template Substring<t_SplitLocation + detail::MatchLength<t_TagToSearchType, t_SplitLocation, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>>::value>>::template Extend<t_TypeSoFar>,
t_TagToSearchType::template Substring<0, t_SplitLocation>::template FindLastInList<t_AccessibleByGetType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct RSplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_AccessibleByGetType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct RSplitHelperInList<t_TagToSearchType, t_AccessibleByGetType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperAnyOf
{
typedef typename RSplitHelperAnyOf<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>,
t_PredType,
typename TypeList<typename t_TagToSearchType::template Substring<t_SplitLocation + 1>>::template Extend<t_TypeSoFar>,
t_TagToSearchType::template Substring<0, t_SplitLocation>::template FindLastOf<t_PredType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct RSplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct RSplitHelperAnyOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperAnyNotOf
{
typedef typename RSplitHelperAnyNotOf<
typename t_TagToSearchType::template Substring<0, t_SplitLocation>,
t_PredType,
typename TypeList<typename t_TagToSearchType::template Substring<t_SplitLocation + 1>>::template Extend<t_TypeSoFar>,
t_TagToSearchType::template Substring<0, t_SplitLocation>::template FindLastNotOf<t_PredType>(),
t_CurrentSplit + 1,
t_MaxSplit
>::type type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_CurrentSplit, ssize_t t_MaxSplit>
struct RSplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_CurrentSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_MaxSplit>
struct RSplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, t_SplitLocation, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_PredType, typename t_TypeSoFar, ssize_t t_MaxSplit>
struct RSplitHelperAnyNotOf<t_TagToSearchType, t_PredType, t_TypeSoFar, -1, t_MaxSplit, t_MaxSplit>
{
typedef typename TypeList<t_TagToSearchType>::template Extend<t_TypeSoFar> type;
};
template<typename t_TagToSearchType, typename t_TypeSoFar, ssize_t t_SplitLocation, ssize_t t_EndOfSplit, bool t_KeepEnds>
struct SplitLinesHelper
{
typedef typename SplitLinesHelper<
typename t_TagToSearchType::template Substring<t_EndOfSplit + 1>,
typename t_TypeSoFar::template Append<
typename t_TagToSearchType::template Substring<0, t_KeepEnds ? t_EndOfSplit + 1 : t_SplitLocation>
>,
t_TagToSearchType::template Substring<t_EndOfSplit + 1>::template FindFirstOf<sprawl::IsLineEnding>(),
t_TagToSearchType::template Substring<t_EndOfSplit + 1>
::template Substring<t_TagToSearchType::template Substring<t_EndOfSplit + 1>::template FindFirstOf<sprawl::IsLineEnding>()>
::template FindFirstNotOf<sprawl::IsLineEnding>(),
t_KeepEnds
>::type type;
};
template<typename t_TagToSearchType, typename t_TypeSoFar, ssize_t t_SplitLocation, bool t_KeepEnds>
struct SplitLinesHelper<t_TagToSearchType, t_TypeSoFar, t_SplitLocation, -1, t_KeepEnds>
{
typedef typename t_TypeSoFar::template Append<typename t_TagToSearchType::template Substring<0, t_KeepEnds ? t_TagToSearchType::length : t_SplitLocation>> type;
};
template<typename t_TagToSearchType, typename t_TypeSoFar, bool t_KeepEnds>
struct SplitLinesHelper<t_TagToSearchType, t_TypeSoFar, -1, -1, t_KeepEnds>
{
typedef typename t_TypeSoFar::template Append<t_TagToSearchType> type;
};
template<typename t_Type, bool integer, bool floating, bool boolean>
struct As;
template<typename t_Type>
struct As<t_Type, true, false, false>
{
static constexpr t_Type value = t_Type(detail::TagToInt<t_Chars...>::value);
};
template<typename t_Type>
struct As<t_Type, true, false, true>
{
static constexpr bool value = detail::TagToBool<Tag::Transform<sprawl::Lower>>::value;
};
template<typename t_Type>
struct As<t_Type, false, true, false>
{
static constexpr t_Type value = t_Type(detail::TagToDouble<t_Chars...>::value);
};
};
template<typename t_PredicateType = IsWhitespace>
using LStrip = typename tag_detail::template LStripHelper<t_PredicateType>::type;
template<typename t_PredicateType = IsWhitespace>
using RStrip = typename tag_detail::template RStripHelper<t_PredicateType>::type;
template<typename t_PredicateType = IsWhitespace>
using Strip = typename LStrip<t_PredicateType>::template RStrip<t_PredicateType>;
template<char t_CharToAdd>
using AppendChar = Tag<t_Len + 1, t_Chars..., t_CharToAdd>;
template<typename t_OtherTagType>
using Append = typename tag_detail::template AppendTagHelper<t_OtherTagType>::type;
template<ssize_t t_Start, ssize_t t_Length = t_Len - t_Start>
using Erase = typename Substring<0, t_Start>::template Append<Substring<t_Start + t_Length, t_Len - (t_Start + t_Length)>>;
template<typename t_AccessibleByGetType>
using Join = typename detail::JoinTags<Tag, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>>::type;
template<typename t_AccessibleByGetType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindFirstInList()
{
return detail::FindTagInList<Substring<t_Start, t_End - t_Start>, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>>::value;
}
template<typename t_AccessibleByGetType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t FindLastInList()
{
return detail::RFindTagInList<Substring<t_Start, t_End - t_Start>, t_AccessibleByGetType, 0, detail::HasGet<t_AccessibleByGetType, 1>>::value;
}
static constexpr bool IsAlnum()
{
return detail::MeetsCondition<sprawl::IsAlnum, t_Chars...>::value;
}
static constexpr bool IsAlpha()
{
return detail::MeetsCondition<sprawl::IsAlpha, t_Chars...>::value;
}
static constexpr bool IsDigit()
{
return detail::MeetsCondition<sprawl::IsDigit, t_Chars...>::value;
}
static constexpr bool IsLower()
{
return detail::MeetsCondition<sprawl::IsLower, t_Chars...>::value;
}
static constexpr bool IsSpace()
{
return detail::MeetsCondition<sprawl::IsWhitespace, t_Chars...>::value;
}
static constexpr bool IsUpper()
{
return detail::MeetsCondition<sprawl::IsUpper, t_Chars...>::value;
}
static constexpr bool IsPrintable()
{
return detail::MeetsCondition<sprawl::IsPrintable, t_Chars...>::value;
}
static constexpr bool IsTitle()
{
return detail::MeetsComplexCondition<sprawl::IsTitle, -1, t_Chars...>::value;
}
template<typename t_OtherTagType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr bool StartsWith()
{
return t_OtherTagType::length <= length && t_OtherTagType::length <= (t_End - t_Start) && Substring<t_Start, t_End - t_Start>::template Substring<0, t_OtherTagType::length>::template EqualTo<t_OtherTagType>();
}
template<typename t_OtherTagType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr bool EndsWith()
{
return t_OtherTagType::length <= length && t_OtherTagType::length <= (t_End - t_Start) && Substring<t_Start, t_End - t_Start>::template Substring<Substring<t_Start, t_End - t_Start>::length - t_OtherTagType::length, t_OtherTagType::length>::template EqualTo<t_OtherTagType>();
}
template<size_t t_Length>
static constexpr bool StartsWith(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
(void)(str);
(void)(start);
(void)(end);
return t_Length - 1 <= Tag::length && t_Length - 1 <= (end - start) && equalTo_(0, t_Length - 1, start, str, t_Chars...);
}
template<ssize_t t_Length>
static constexpr bool EndsWith(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
(void)(str);
(void)(start);
(void)(end);
return t_Length - 1 <= Tag::length && t_Length - 1 <= (end - start) && equalTo_(0, t_Length - 1, end - (t_Length - 1), str, t_Chars...);
}
template<typename t_OtherTagType>
static constexpr bool Contains()
{
return detail::FindTag<Tag, t_OtherTagType, 0>::result != -1;
}
template<size_t t_Length>
static constexpr bool Contains(char const (&str)[t_Length])
{
return Find(str) != -1;
}
template<typename t_OtherTagType, ssize_t t_Start = 0, ssize_t t_End = t_Len>
static constexpr ssize_t Count()
{
return detail::CountTag<Tag, t_OtherTagType, t_Start, t_End>::value;
}
template<size_t t_Length>
static constexpr ssize_t Count(char const (&str)[t_Length], ssize_t start = 0, ssize_t end = t_Len)
{
return Find(str, start, end) != -1 ? 1 + Count(str, Find(str, start, end) + 1, end) : 0;
}
template<ssize_t t_Idx>
static constexpr char CharAt()
{
return tag_detail::template CharAt<t_Idx, t_Idx >= 0 && t_Idx <= t_Len, t_Chars...>::value;
}
template<typename t_Type>
static constexpr t_Type As()
{
return tag_detail::template As<t_Type, std::is_integral<t_Type>::value, std::is_floating_point<t_Type>::value, std::is_same<t_Type, bool>::value>::value;
}
template<typename t_FindTagType, typename t_ReplaceWithType, ssize_t count = -1>
using Replace = typename detail::ReplaceTags<Tag, t_FindTagType, t_ReplaceWithType, count>::type;
template<typename t_FindTagType, typename t_ReplaceWithType, ssize_t count = -1>
using RReplace = typename detail::RReplaceTags<Tag, t_FindTagType, t_ReplaceWithType, count>::type;
template<typename t_TagListType, typename t_ReplaceWithType, ssize_t count = -1>
using ReplaceAnyInList = typename detail::ReplaceTagsInList<Tag, t_TagListType, t_ReplaceWithType, count>::type;
template<typename t_TagListType, typename t_ReplaceWithType, ssize_t count = -1>
using RReplaceAnyInList = typename detail::RReplaceTagsInList<Tag, t_TagListType, t_ReplaceWithType, count>::type;
template<typename t_PredType, typename t_ReplaceWithType, ssize_t count = -1>
using ReplaceAnyOf = typename detail::ReplaceTagsAnyOf<Tag, t_PredType, t_ReplaceWithType, count, FindFirstOf<t_PredType>()>::type;
template<typename t_PredType, typename t_ReplaceWithType, ssize_t count = -1>
using ReplaceAnyNotOf = typename detail::ReplaceTagsAnyNotOf<Tag, t_PredType, t_ReplaceWithType, count, FindFirstNotOf<t_PredType>()>::type;
template<typename t_PredType, typename t_ReplaceWithType, ssize_t count = -1>
using RReplaceAnyOf = typename detail::RReplaceTagsAnyOf<Tag, t_PredType, t_ReplaceWithType, count, FindLastOf<t_PredType>()>::type;
template<typename t_PredType, typename t_ReplaceWithType, ssize_t count = -1>
using RReplaceAnyNotOf = typename detail::RReplaceTagsAnyNotOf<Tag, t_PredType, t_ReplaceWithType, count, FindLastNotOf<t_PredType>()>::type;
template<ssize_t t_Start, ssize_t t_Length, typename t_OtherTagType>
using ReplaceAt = typename Substring<0, t_Start>::template Append<t_OtherTagType>::template Append<Substring<t_Start + t_Length>>;
template<typename t_TagToSplitOnType>
using Partition = typename tag_detail::template PartitionHelper<t_TagToSplitOnType, Find<t_TagToSplitOnType>()>::type;
template<typename t_TagToSplitOnType>
using RPartition = typename tag_detail::template PartitionHelper<t_TagToSplitOnType, RFind<t_TagToSplitOnType>()>::type;
template<typename t_TagToSplitOnType, ssize_t t_MaxSplit = -1>
using Split = typename tag_detail::template SplitHelper<Tag, t_TagToSplitOnType, TypeList<>, Find<t_TagToSplitOnType>(), 0, t_MaxSplit>::type;
template<typename t_AccessibleByGetType, ssize_t t_MaxSplit = -1>
using SplitAnyInList = typename tag_detail::template SplitHelperInList<Tag, t_AccessibleByGetType, TypeList<>, FindFirstInList<t_AccessibleByGetType>(), 0, t_MaxSplit>::type;
template<typename t_PredType, ssize_t t_MaxSplit = -1>
using SplitAnyOf = typename tag_detail::template SplitHelperAnyOf<Tag, t_PredType, TypeList<>, FindFirstOf<t_PredType>(), 0, t_MaxSplit>::type;
template<typename t_PredType, ssize_t t_MaxSplit = -1>
using SplitAnyNotOf = typename tag_detail::template SplitHelperAnyNotOf<Tag, t_PredType, TypeList<>, FindFirstNotOf<t_PredType>(), 0, t_MaxSplit>::type;
template<typename t_TagToSplitOnType, ssize_t t_MaxSplit = -1>
using RSplit = typename tag_detail::template RSplitHelper<Tag, t_TagToSplitOnType, TypeList<>, RFind<t_TagToSplitOnType>(), 0, t_MaxSplit>::type;
template<typename t_AccessibleByGetType, ssize_t t_MaxSplit = -1>
using RSplitAnyInList = typename tag_detail::template RSplitHelperInList<Tag, t_AccessibleByGetType, TypeList<>, FindLastInList<t_AccessibleByGetType>(), 0, t_MaxSplit>::type;
template<typename t_PredType, ssize_t t_MaxSplit = -1>
using RSplitAnyOf = typename tag_detail::template RSplitHelperAnyOf<Tag, t_PredType, TypeList<>, FindLastOf<t_PredType>(), 0, t_MaxSplit>::type;
template<typename t_PredType, ssize_t t_MaxSplit = -1>
using RSplitAnyNotOf = typename tag_detail::template RSplitHelperAnyNotOf<Tag, t_PredType, TypeList<>, FindLastNotOf<t_PredType>(), 0, t_MaxSplit>::type;
template<bool t_KeepEnds = false>
using SplitLines = typename tag_detail::template SplitLinesHelper<Tag, TypeList<>, FindFirstOf<sprawl::IsLineEnding>(), Substring<FindFirstOf<sprawl::IsLineEnding>()>::template FindFirstNotOf<sprawl::IsLineEnding>(), t_KeepEnds>::type;
template<ssize_t t_Idx, typename t_OtherTagType>
using Insert = typename Substring<0, t_Idx>::template Append<t_OtherTagType>::template Append<Substring<t_Idx>>;
template<ssize_t t_Length>
static constexpr bool EqualTo(char const (&str)[t_Length])
{
return t_Length - 1 == Tag::length ? equalTo_(0, length, 0, str, t_Chars...) : false;
}
template<typename t_OtherTagType>
static constexpr bool EqualTo()
{
return std::is_same<Tag, t_OtherTagType>::value;
}
template<typename t_HashType = Murmur3<0>>
static constexpr auto Hash() -> decltype(t_HashType::template Hash<t_Chars...>::value)
{
return t_HashType::template Hash<t_Chars...>::value;
}
template<ssize_t t_Start, ssize_t t_End = t_Len, ssize_t t_Interval = 1>
using Slice = typename detail::SliceTag<
Tag,
Tag<0>,
(t_Start >= t_Len ? t_Len - 1 : t_Start < 0 ? 0 : t_Start),
(t_End > t_Len ? t_Len : t_End < -1 ? -1 : t_End),
t_Interval,
(t_Start >= t_Len ? t_Len - 1 : t_Start < 0 ? 0 : t_Start),
((t_Start < t_End ? t_Start < t_End : t_Start > t_End) && ((t_End - t_Start)/t_Interval) > 0)
>::type;
private:
template<size_t t_Length>
static constexpr bool equalTo_(ssize_t /*idx*/, ssize_t /*length_*/, ssize_t /*offset*/, char const (&/*str*/)[t_Length])
{
return t_Length == 1 && Tag::length == 0;
}
template<size_t t_Length>
static constexpr bool equalTo_(ssize_t idx, ssize_t length_, ssize_t offset, char const (&str)[t_Length], char compareChar)
{
return offset > 0 ? false : idx >= length_ ? true : str[idx] == compareChar;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MorCharTypes>
static constexpr bool equalTo_(ssize_t idx, ssize_t length_, ssize_t offset, char const (&str)[t_Length], t_FirstCharType compareChar, t_MorCharTypes... moreChars)
{
return
offset > 0
?
equalTo_(idx, length_, offset - 1, str, moreChars...)
:
idx >= length_
?
true
:
str[idx] == compareChar ? equalTo_(idx + 1, length_, offset, str, moreChars...) : false;
}
template<size_t t_Length>
static constexpr ssize_t find_(ssize_t idx, ssize_t start, size_t end, char const (&str)[t_Length], char compareChar)
{
return
idx + t_Length - 1 > end
?
-1
:
idx >= start
?
equalTo_(0, t_Length - 1, 0, str, compareChar)
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MorCharTypes>
static constexpr ssize_t find_(ssize_t idx, ssize_t start, size_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MorCharTypes... moreChars)
{
return
idx + t_Length - 1 > end
?
-1
:
idx >= start
?
equalTo_(0, t_Length - 1, 0, str, compareChar, moreChars...)
?
idx
:
find_(idx + 1, start, end, str, moreChars...)
:
find_(idx + 1, start, end, str, moreChars...);
}
template<size_t t_Length>
static constexpr ssize_t rfind_(ssize_t idx, ssize_t start, size_t end, char const (&str)[t_Length], char compareChar)
{
return
idx + t_Length - 1 > end
?
-1
:
idx >= start
?
equalTo_(0, t_Length - 1, 0, str, compareChar)
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MoreCharTypes>
static constexpr ssize_t rfind_(ssize_t idx, ssize_t start, size_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MoreCharTypes... moreChars)
{
return
idx + t_Length - 1 > end
?
-1
:
idx >= start
?
rfind_(idx + 1, start, end, str, moreChars...) != -1
?
rfind_(idx + 1, start, end, str, moreChars...)
:
equalTo_(0, t_Length - 1, 0, str, compareChar, moreChars...)
?
idx
:
-1
:
rfind_(idx + 1, start, end, str, moreChars...);
}
template<size_t t_Length>
static constexpr bool isOneOf_(char const (&str)[t_Length], char compareChar, size_t idx)
{
return idx == t_Length ? false : compareChar == str[idx] ? true : isOneOf_(str, compareChar, idx + 1);
}
template<size_t t_Length>
static constexpr ssize_t findFirstOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], char compareChar)
{
return
idx >= end
?
-1
:
idx >= start
?
isOneOf_(str, compareChar, 0)
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MorCharTypes>
static constexpr ssize_t findFirstOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MorCharTypes... moreChars)
{
return
idx >= end
?
-1
:
idx >= start
?
isOneOf_(str, compareChar, 0)
?
idx
:
findFirstOf_(idx + 1, start, end, str, moreChars...)
:
findFirstOf_(idx + 1, start, end, str, moreChars...);
}
template<size_t t_Length>
static constexpr ssize_t findLastOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], char compareChar)
{
return
idx >= end
?
-1
:
idx >= start
?
isOneOf_(str, compareChar, 0)
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MoreCharTypes>
static constexpr ssize_t findLastOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MoreCharTypes... moreChars)
{
return
idx >= end
?
-1
:
idx >= start
?
findLastOf_(idx + 1, start, end, str, moreChars...) != -1
?
findLastOf_(idx + 1, start, end, str, moreChars...)
:
isOneOf_(str, compareChar, 0)
?
idx
:
-1
:
findLastOf_(idx + 1, start, end, str, moreChars...);
}
template<size_t t_Length>
static constexpr ssize_t findFirstNotOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], char compareChar)
{
return
idx >= end
?
-1
:
idx >= start
?
(!isOneOf_(str, compareChar, 0))
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MorCharTypes>
static constexpr ssize_t findFirstNotOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MorCharTypes... moreChars)
{
return
idx >= end
?
-1
:
idx >= start
?
(!isOneOf_(str, compareChar, 0))
?
idx
:
findFirstNotOf_(idx + 1, start, end, str, moreChars...)
:
findFirstNotOf_(idx + 1, start, end, str, moreChars...);
}
template<size_t t_Length>
static constexpr ssize_t findLastNotOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], char compareChar)
{
return
idx >= end
?
-1
:
idx >= start
?
(!isOneOf_(str, compareChar, 0))
?
idx
:
-1
:
-1;
}
template<size_t t_Length, typename t_FirstCharType, typename... t_MoreCharTypes>
static constexpr ssize_t findLastNotOf_(ssize_t idx, ssize_t start, ssize_t end, char const (&str)[t_Length], t_FirstCharType compareChar, t_MoreCharTypes... moreChars)
{
return
idx >= end
?
-1
:
idx >= start
?
findLastNotOf_(idx + 1, start, end, str, moreChars...) != -1
?
findLastNotOf_(idx + 1, start, end, str, moreChars...)
:
(!isOneOf_(str, compareChar, 0))
?
idx
:
-1
:
findLastNotOf_(idx + 1, start, end, str, moreChars...);
}
};
template<ssize_t t_Len, char... t_Chars>
CONSTEXPR_ARRAY char Tag<t_Len, t_Chars...>::name[t_Len + 1] SPRAWL_CONSTEXPR_OUT_OF_CLASS_INIT({ t_Chars..., '\0' });
namespace detail
{
template<typename t_Type>
struct TypeToString
{
private:
struct NameSize
{
char const* name;
size_t size;
constexpr NameSize(char const* name_, size_t size_) : name(name_), size(size_) {}
};
#if defined(_MSC_VER) && !defined(__clang__)
static constexpr size_t prefix_size = sizeof("sprawl::detail::TypeToString<") - 1;
static constexpr size_t postfix_size = sizeof(">::f") - 1;
#else
static constexpr size_t prefix_size = sizeof("static sprawl::detail::TypeToString::NameSize sprawl::detail::TypeToString<") - 1;
static constexpr size_t postfix_size = sizeof(">::f() [t_Type = ]") - 1;
#endif
static constexpr NameSize f()
{
#if defined(_MSC_VER) && !defined(__clang__)
return{ __FUNCTION__ + prefix_size, sizeof(__FUNCTION__) - prefix_size - postfix_size };
#else
return{ __PRETTY_FUNCTION__ + prefix_size, sizeof(__PRETTY_FUNCTION__) - prefix_size - postfix_size - ((sizeof(__PRETTY_FUNCTION__) - prefix_size - postfix_size) / 2) };
#endif
}
static constexpr NameSize nameSize = f();
public:
//Gotta do this the hard way since we can't sizeof()...
typedef typename ::sprawl::detail::TagWrapper<
::sprawl::detail::SizeChecker<nameSize.size - 1>::value, 1,
::sprawl::Tag<0>,
::sprawl::detail::IsPositive<nameSize.size - 1>::value,
true,
SPRAWL_CHR_MAX_MACRO(nameSize.name, nameSize.size, 0)
>::type nakedType;
#if defined(_MSC_VER) && !defined(__clang__)
// Consistency - msvc adds 'struct' or 'class' to the typename, clang/gcc do not.
// Also, msvc doesn't include spaces after commas, clang/gcc do.
// Also, msvc will add a space after every >, while clang/gcc will only put it between them - for simplicity, we're removing all spaces that follow >
typedef typename If<nakedType::StartsWith("struct "), typename nakedType::template ReplaceAt<0, 7, SPRAWL_TAG("")>>
::template ElseIf<nakedType::StartsWith("class "), typename nakedType::template ReplaceAt<0, 6, SPRAWL_TAG("")>>
::template Else<nakedType>
::template type<::sprawl::UnmatchedIfSequence>
::template Replace<SPRAWL_TAG(","), SPRAWL_TAG(", ")>
::template Replace<SPRAWL_TAG("> "), SPRAWL_TAG(">")>
::template Replace<SPRAWL_TAG(" class "), SPRAWL_TAG(" ")>
::template Replace<SPRAWL_TAG(" struct "), SPRAWL_TAG(" ")>
::template Replace<SPRAWL_TAG("<class "), SPRAWL_TAG("<")>
::template Replace<SPRAWL_TAG("<struct "), SPRAWL_TAG("<")>
type;
#else
typedef typename nakedType::template Replace<SPRAWL_TAG("> "), SPRAWL_TAG(">")> type;
#endif
};
template<typename t_Type, t_Type t_Value, bool t_IsSingleDigit = (t_Value >= 0 && t_Value < 10), bool t_IsNegative = (t_Value < 0)>
struct TagFromInt
{
typedef typename TagFromInt<t_Type, t_Value / 10>::type::template Append<Tag<1, char(t_Value % 10) + '0'>> type;
};
template<typename t_Type, t_Type t_Value>
struct TagFromInt<t_Type, t_Value, true, false>
{
typedef Tag<1, char(t_Value) + '0'> type;
};
template<typename t_Type, t_Type t_Value>
struct TagFromInt<t_Type, t_Value, false, true>
{
typedef typename Tag<1, '-'>::Append<typename TagFromInt<t_Type, 0 - t_Value>::type> type;
};
template<typename t_Type, t_Type t_Value, bool t_IsSingleDigit = (t_Value >= 0 && t_Value < 10)>
struct TagFromUInt
{
typedef typename TagFromUInt<t_Type, t_Value / 10>::type::template Append<Tag<1, char(t_Value % 10) + '0'>> type;
};
template<typename t_Type, t_Type t_Value>
struct TagFromUInt<t_Type, t_Value, true>
{
typedef Tag<1, char(t_Value) + '0'> type;
};
template<bool t_Value>
struct TagFromBool
{
typedef Tag<4, 't', 'r', 'u', 'e'> type;
};
template<>
struct TagFromBool<false>
{
typedef Tag<5, 'f', 'a', 'l', 's', 'e'> type;
};
}
template<typename t_Type>
using TypeName = typename detail::TypeToString<t_Type>::type;
template<typename t_Type>
struct TagFrom;
template<>
struct TagFrom<char>
{
template<char t_Char>
using FromValue = Tag<1, t_Char>;
};
template<> struct TagFrom<signed char> { template<signed char t_Value> using FromValue = typename detail::TagFromInt<signed char, t_Value>::type; };
template<> struct TagFrom<short > { template<short t_Value > using FromValue = typename detail::TagFromInt<short, t_Value>::type; };
template<> struct TagFrom<int > { template<int t_Value > using FromValue = typename detail::TagFromInt<int, t_Value>::type; };
template<> struct TagFrom<long > { template<long t_Value > using FromValue = typename detail::TagFromInt<long, t_Value>::type; };
template<> struct TagFrom<long long > { template<long long t_Value > using FromValue = typename detail::TagFromInt<long long, t_Value>::type; };
template<> struct TagFrom<unsigned char > { template<unsigned char t_Value > using FromValue = typename detail::TagFromUInt<unsigned char, t_Value>::type; };
template<> struct TagFrom<unsigned short > { template<unsigned short t_Value > using FromValue = typename detail::TagFromUInt<unsigned short, t_Value>::type; };
template<> struct TagFrom<unsigned int > { template<unsigned int t_Value > using FromValue = typename detail::TagFromUInt<unsigned int, t_Value>::type; };
template<> struct TagFrom<unsigned long > { template<unsigned long t_Value > using FromValue = typename detail::TagFromUInt<unsigned long, t_Value>::type; };
template<> struct TagFrom<unsigned long long> { template<unsigned long long t_Value> using FromValue = typename detail::TagFromUInt<unsigned long long, t_Value>::type; };
template<> struct TagFrom<bool> { template<bool t_Value> using FromValue = typename detail::TagFromBool<t_Value>::type; };
template<>
struct TagFrom<std::nullptr_t>
{
template<std::nullptr_t value>
using FromValue = Tag<6, '(', 'n', 'u', 'l', 'l', ')'>;
};
} | # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #3 | 20951 | ShadauxCat |
- Reworked ConcurrentQueue::Dequeue to be a lot faster and wait-free - Added constexpr constructor for sprawl tag - Added support for specifying base for int-to-tag conversion - Added ability to force poolallocator to pass through to malloc - Added a helper class that will eventually be used in StringBuilder for faster int-to-string conversion #review-20952 post-commit |
||
| #2 | 19912 | ShadauxCat |
Fix various linux warnings and errors under clang 3.6 #review-19913 |
||
| #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 |