/* * MIT License * * Copyright (c) 2016 Jacek Galowicz * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include "stl_symbols.hpp" #include "charlist.hpp" namespace pprintpp { template struct always_false { static constexpr bool value {false}; }; using namespace typelist; using namespace charlist; template struct type2fmt; template <> struct type2fmt { using type = char_tl_t<'c'>; }; template <> struct type2fmt { using type = char_tl_t<'d'>; }; template <> struct type2fmt { using type = char_tl_t<'d'>; }; template <> struct type2fmt { using type = char_tl_t<'l', 'd'>; }; template <> struct type2fmt { using type = char_tl_t<'l', 'l', 'd'>; }; template <> struct type2fmt { using type = char_tl_t<'u'>; }; template <> struct type2fmt { using type = char_tl_t<'u'>; }; template <> struct type2fmt { using type = char_tl_t<'u'>; }; template <> struct type2fmt { using type = char_tl_t<'l', 'u'>; }; template <> struct type2fmt { using type = char_tl_t<'l', 'l', 'u'>; }; template <> struct type2fmt { using type = char_tl_t<'d'>; }; template <> struct type2fmt { using type = char_tl_t<'f'>; }; template <> struct type2fmt { using type = char_tl_t<'l', 'f'>; }; template <> struct type2fmt { using type = char_tl_t<'p'>; }; template struct type2fmt { using type = char_tl_t<'p'>; }; template struct format_str { using raw_T = remove_cv_t; static constexpr bool s_fmt {contains>::value}; static constexpr bool is_str {is_same::type>>::value}; static constexpr bool is_int {is_int_type::value}; static constexpr bool has_x {contains>::value}; using raw_fmt = typename type2fmt::type; using uint_x_fmt = typename conditional, char_t<'x'>>, char_t<'u'>, char_t<'x'>>, raw_fmt >::type; using fmt_type = typename conditional, char_t<'s'>>, uint_x_fmt >::type; using filtered_fl = remove_t>, char_t<'s'>>; using type = append_t; }; template struct find_brace; template struct find_brace, InList>, OutList, 1> { using before = OutList; using after = InList; }; template struct find_brace, InList>, OutList, N> : public find_brace>, N> { static_assert(C != '{', "Found nested braces: {...{...}...}!" " Maybe you want to mask the outer one?"); }; template struct find_brace { static_assert(N + 1 == N, "Missing } after {."); }; template struct autoformat; template <> struct autoformat { using type = null_t; }; template struct autoformat { using type = null_t; static_assert(always_false::value, "There are more vars than format tokens!"); }; template struct autoformat, tl, SL>>, TL> { using type = tl, tl, typename autoformat::type>>; }; template struct autoformat, SL>, tl> { using type = tl, typename autoformat::type>; }; template struct autoformat, tl, SL>>, TL> { using type = tl, typename autoformat::type>; }; template struct autoformat, SL>, TL> { using other_brace = find_brace; using format_block = typename other_brace::before; using rest_str = typename other_brace::after; static_assert(!is_same::value, "There are more {} than arguments to print"); using T = typename TL::head; using fmt_str = typename format_str::type; using type = tl, append_t::type>>; }; template struct autoformat, TL> { using type = tl::type>; }; template using autoformat_t = tl_to_varlist< typename autoformat, PtList>::type >; template make_t tie_types(Ts...); #define AUTOFORMAT(s, ...) \ ({ \ struct strprov { static constexpr const char * const str() { return s; } }; \ using paramtypes = decltype(pprintpp::tie_types(__VA_ARGS__)); \ using af = pprintpp::autoformat_t; \ af::str(); \ }) #define pprintf(s, ...) printf(AUTOFORMAT(s, ## __VA_ARGS__), ## __VA_ARGS__) #define pfprintf(f, s, ...) fprintf(f, AUTOFORMAT(s, ## __VA_ARGS__), ## __VA_ARGS__) #define psprintf(str, s, ...) sprintf(str, AUTOFORMAT(s, ## __VA_ARGS__), ## __VA_ARGS__) }