= (1U << 0U),

            kAlignNone    = (0U << 1U),
            kAlignLeft    = (1U << 1U),
            kAlignRight   = (2U << 1U),
            kAlignCenter  = (3U << 1U),
            kAlignNumeric = (4U << 1U),
            kAlignBitmask = (7U << 1U),

            kSignNone     = (0U << 4U),
            kSignMinus    = (1U << 4U),
            kSignPlus     = (2U << 4U),
            kSignSpace    = (3U << 4U),
            kSignBitmask  = (3U << 4U),

            kHash         = (1U << 6U),

            kUppercase    = (1U << 7U)
        };

        // --------------------------------------------------------------------
        // PRIVATE MEMBER FUNCTIONS
        // --------------------------------------------------------------------

        inline constexpr int sign_width(const bool negative) const noexcept
        {
            return (!negative && sign() <= Sign::kMinus)? 0 : 1;
        }

        inline constexpr int prefix_width() const noexcept
        {
            // Alternative format is valid for hexadecimal (including
            // pointers), octal, binary and all floating point types.
            return (!hash() || type_is_float())? 0 : type_is_integer_oct()? 1 : 2;
        }

        USF_CPP14_CONSTEXPR void write_sign(iterator& it, const bool negative) const noexcept
        {
            if(negative)
            {
                *it++ = '-';
            }
            else
            {
                const Sign s = sign();

                if(s!= Sign::kNone)
                {
                    if(s == Sign::kPlus )
                    {
                        *it++ = '+';
                    }
                    else if(s == Sign::kSpace)
                    {
                        *it++ ='';
                    }
                }
            }
        }

        USF_CPP14_CONSTEXPR void write_prefix(iterator& it) const noexcept
        {
            // Alternative format is valid for hexadecimal (including
            // pointers), octal, binary and all floating point types.
            if(hash() &&!type_is_float())
            {
                *it++ = '0';

                if(type_is_integer_bin())
                {
                    *it++ = uppercase()? 'B' : 'b';
                }
                else if(type_is_integer_hex() || type_is_pointer())
                {
                    *it++ = uppercase()? 'X' : 'x';
                }
            }
        }

        // --------------------------------------------------------------------
        // PRIVATE STATIC FUNCTIONS
        // --------------------------------------------------------------------

        // Parses the input as a positive integer that fits into a `uint8_t` type. This
        // function assumes that the first character is a digit and terminates parsing
        // at the presence of the first non-digit character or when value overflows.
        static USF_CPP14_CONSTEXPR
        uint8_t parse_positive_small_int(const_iterator& it, const int max_value)
        {
            assert(max_value < 256);

            int value = 0;

            do
            {
                value = (value * 10) + static_cast<int>(*it++ - '0');

                // Check for overflow
                USF_ENFORCE(value <= max_value, std::runtime_error);
            }while(*it >= '0' && *it <= '9');

            return static_cast<uint8_t>(value);
        }

        static USF_CPP14_CONSTEXPR uint8_t parse_align_flag(const CharT ch) noexcept
        {
            switch(ch)
            {
                case '<': return Flags::kAlignLeft;    break;
                case '>': return Flags::kAlignRight;   break;
                case '^': return Flags::kAlignCenter;  break;
                case '=': return Flags::kAlignNumeric; break;
                default : return Flags::kNone;         break;
            }
        }

        // --------------------------------------------------------------------
        // PRIVATE MEMBER VARIABLES
        // --------------------------------------------------------------------

        CharT   m_fill_char ='';
        Type    m_type      = Type::kNone;
        uint8_t m_flags     = Flags::kEmpty;
        uint8_t m_width     =  0;
         int8_t m_precision = -1;
         int8_t m_index     = -1;
};

} // namespace internal
} // namespace usf

#endif // USF_ARG_FORMAT_HPP


// ----------------------------------------------------------------------------
// @file    usf_arg_custom_type.hpp
// @brief   User-defined custom type class (using the delegate idiom).
// @date    07 January 2019
// ----------------------------------------------------------------------------

#ifndef USF_ARG_CUSTOM_TYPE_HPP
#define USF_ARG_CUSTOM_TYPE_HPP

namespace usf
{
namespace internal
{

template<typename CharT>
class ArgCustomType
{
    public:

        // --------------------------------------------------------------------
        // PUBLIC MEMBER FUNCTIONS
        // --------------------------------------------------------------------

        USF_CPP14_CONSTEXPR ArgCustomType() = delete;

        template<typename T, BasicStringSpan<CharT>(*func)(BasicStringSpan<CharT>, const T&)>
        static USF_CPP14_CONSTEXPR ArgCustomType create(const T* obj)
        {
            return ArgCustomType(invoke_func<T, func>, obj);
        }

        USF_CPP14_CONSTEXPR BasicStringSpan<CharT> operator()(BasicStringSpan<CharT> dst) const
        {
            return m_function(dst, m_obj);
        }

    private:

        // --------------------------------------------------------------------
        // PRIVATE TYPE ALIASES
        // --------------------------------------------------------------------

        using FunctionType = BasicStringSpan<CharT>(*)(BasicStringSpan<CharT>, const void*);

        // --------------------------------------------------------------------
        // PRIVATE MEMBER FUNCTIONS
        // --------------------------------------------------------------------

        USF_CPP14_CONSTEXPR ArgCustomType(const FunctionType func, const void* obj)
            : m_function{func}, m_obj{obj} {}

        template<typename T, BasicStringSpan<CharT>(*func)(BasicStringSpan<CharT>, const T&)>
        static USF_CPP14_CONSTEXPR BasicStringSpan<CharT> invoke_func(BasicStringSpan<CharT> dst, const void* obj)
        {
            return func(dst, *static_cast<const T*>(obj));
        }

        // --------------------------------------------------------------------
        // PRIVATE VARIABLES
        // --------------------------------------------------------------------

        const FunctionType m_function{nullptr};
        const void*        m_obj     {nullptr};
};

} // namespace internal
} // namespace usf

#endif // USF_ARG_CUSTOM_TYPE_HPP


// ----------------------------------------------------------------------------
// @file    usf_argument.hpp
// @brief   Argument format processor class.
// @date    14 January 2019
// ----------------------------------------------------------------------------

#ifndef USF_ARGUMENT_HPP
#define USF_ARGUMENT_HPP

namespace usf
{
namespace internal
{

template <typename CharT>
class Argument
{
    public:

        // --------------------------------------------------------------------
        // PUBLIC TYPE ALIASES
        // --------------------------------------------------------------------

        using       iterator =       CharT*;
        using const_iterator = const CharT*;

        using Format = ArgFormat<CharT>;

        // --------------------------------------------------------------------
        // PUBLIC MEMBER FUNCTIONS
        // --------------------------------------------------------------------

        constexpr Argument() = delete;

        constexpr Argument(const bool value) noexcept
            : m_bool(value), m_type_id(TypeId::kBool) {}

        constexpr Argument(const CharT value) noexcept
            : m_char(value), m_type_id(TypeId::kChar) {}

        constexpr Argument(const int32_t value) noexcept
            : m_int32(value), m_type_id(TypeId::kInt32) {}

        constexpr Argument(const uint32_t value) noexcept
            : m_uint32(value), m_type_id(TypeId::kUint32) {}

        constexpr Argument(const int64_t value) noexcept
            : m_int64(value), m_type_id(TypeId::kInt64) {}

        constexpr Argument(const uint64_t value) noexcept
            : m_uint64(value), m_type