ranges.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. // Formatting library for C++ - range and tuple support
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #ifndef FMT_RANGES_H_
  8. #define FMT_RANGES_H_
  9. #ifndef FMT_MODULE
  10. # include <initializer_list>
  11. # include <iterator>
  12. # include <string>
  13. # include <tuple>
  14. # include <type_traits>
  15. # include <utility>
  16. #endif
  17. #include "format.h"
  18. FMT_BEGIN_NAMESPACE
  19. FMT_EXPORT
  20. enum class range_format { disabled, map, set, sequence, string, debug_string };
  21. namespace detail {
  22. template <typename T> class is_map {
  23. template <typename U> static auto check(U*) -> typename U::mapped_type;
  24. template <typename> static void check(...);
  25. public:
  26. static constexpr const bool value =
  27. !std::is_void<decltype(check<T>(nullptr))>::value;
  28. };
  29. template <typename T> class is_set {
  30. template <typename U> static auto check(U*) -> typename U::key_type;
  31. template <typename> static void check(...);
  32. public:
  33. static constexpr const bool value =
  34. !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
  35. };
  36. template <typename... Ts> struct conditional_helper {};
  37. template <typename T, typename _ = void> struct is_range_ : std::false_type {};
  38. #if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
  39. # define FMT_DECLTYPE_RETURN(val) \
  40. ->decltype(val) { return val; } \
  41. static_assert( \
  42. true, "") // This makes it so that a semicolon is required after the
  43. // macro, which helps clang-format handle the formatting.
  44. // C array overload
  45. template <typename T, std::size_t N>
  46. auto range_begin(const T (&arr)[N]) -> const T* {
  47. return arr;
  48. }
  49. template <typename T, std::size_t N>
  50. auto range_end(const T (&arr)[N]) -> const T* {
  51. return arr + N;
  52. }
  53. template <typename T, typename Enable = void>
  54. struct has_member_fn_begin_end_t : std::false_type {};
  55. template <typename T>
  56. struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
  57. decltype(std::declval<T>().end())>>
  58. : std::true_type {};
  59. // Member function overloads.
  60. template <typename T>
  61. auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
  62. template <typename T>
  63. auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
  64. // ADL overloads. Only participate in overload resolution if member functions
  65. // are not found.
  66. template <typename T>
  67. auto range_begin(T&& rng)
  68. -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
  69. decltype(begin(static_cast<T&&>(rng)))> {
  70. return begin(static_cast<T&&>(rng));
  71. }
  72. template <typename T>
  73. auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
  74. decltype(end(static_cast<T&&>(rng)))> {
  75. return end(static_cast<T&&>(rng));
  76. }
  77. template <typename T, typename Enable = void>
  78. struct has_const_begin_end : std::false_type {};
  79. template <typename T, typename Enable = void>
  80. struct has_mutable_begin_end : std::false_type {};
  81. template <typename T>
  82. struct has_const_begin_end<
  83. T, void_t<decltype(*detail::range_begin(
  84. std::declval<const remove_cvref_t<T>&>())),
  85. decltype(detail::range_end(
  86. std::declval<const remove_cvref_t<T>&>()))>>
  87. : std::true_type {};
  88. template <typename T>
  89. struct has_mutable_begin_end<
  90. T, void_t<decltype(*detail::range_begin(std::declval<T&>())),
  91. decltype(detail::range_end(std::declval<T&>())),
  92. // the extra int here is because older versions of MSVC don't
  93. // SFINAE properly unless there are distinct types
  94. int>> : std::true_type {};
  95. template <typename T>
  96. struct is_range_<T, void>
  97. : std::integral_constant<bool, (has_const_begin_end<T>::value ||
  98. has_mutable_begin_end<T>::value)> {};
  99. # undef FMT_DECLTYPE_RETURN
  100. #endif
  101. // tuple_size and tuple_element check.
  102. template <typename T> class is_tuple_like_ {
  103. template <typename U>
  104. static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
  105. template <typename> static void check(...);
  106. public:
  107. static constexpr const bool value =
  108. !std::is_void<decltype(check<T>(nullptr))>::value;
  109. };
  110. // Check for integer_sequence
  111. #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
  112. template <typename T, T... N>
  113. using integer_sequence = std::integer_sequence<T, N...>;
  114. template <size_t... N> using index_sequence = std::index_sequence<N...>;
  115. template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
  116. #else
  117. template <typename T, T... N> struct integer_sequence {
  118. using value_type = T;
  119. static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); }
  120. };
  121. template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
  122. template <typename T, size_t N, T... Ns>
  123. struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
  124. template <typename T, T... Ns>
  125. struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
  126. template <size_t N>
  127. using make_index_sequence = make_integer_sequence<size_t, N>;
  128. #endif
  129. template <typename T>
  130. using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
  131. template <typename T, typename C, bool = is_tuple_like_<T>::value>
  132. class is_tuple_formattable_ {
  133. public:
  134. static constexpr const bool value = false;
  135. };
  136. template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
  137. template <size_t... Is>
  138. static auto all_true(index_sequence<Is...>,
  139. integer_sequence<bool, (Is >= 0)...>) -> std::true_type;
  140. static auto all_true(...) -> std::false_type;
  141. template <size_t... Is>
  142. static auto check(index_sequence<Is...>) -> decltype(all_true(
  143. index_sequence<Is...>{},
  144. integer_sequence<bool,
  145. (is_formattable<typename std::tuple_element<Is, T>::type,
  146. C>::value)...>{}));
  147. public:
  148. static constexpr const bool value =
  149. decltype(check(tuple_index_sequence<T>{}))::value;
  150. };
  151. template <typename Tuple, typename F, size_t... Is>
  152. FMT_CONSTEXPR void for_each(index_sequence<Is...>, Tuple&& t, F&& f) {
  153. using std::get;
  154. // Using a free function get<Is>(Tuple) now.
  155. const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
  156. ignore_unused(unused);
  157. }
  158. template <typename Tuple, typename F>
  159. FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) {
  160. for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
  161. std::forward<Tuple>(t), std::forward<F>(f));
  162. }
  163. template <typename Tuple1, typename Tuple2, typename F, size_t... Is>
  164. void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
  165. using std::get;
  166. const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
  167. ignore_unused(unused);
  168. }
  169. template <typename Tuple1, typename Tuple2, typename F>
  170. void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
  171. for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
  172. std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
  173. std::forward<F>(f));
  174. }
  175. namespace tuple {
  176. // Workaround a bug in MSVC 2019 (v140).
  177. template <typename Char, typename... T>
  178. using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
  179. using std::get;
  180. template <typename Tuple, typename Char, std::size_t... Is>
  181. auto get_formatters(index_sequence<Is...>)
  182. -> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
  183. } // namespace tuple
  184. #if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
  185. // Older MSVC doesn't get the reference type correctly for arrays.
  186. template <typename R> struct range_reference_type_impl {
  187. using type = decltype(*detail::range_begin(std::declval<R&>()));
  188. };
  189. template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
  190. using type = T&;
  191. };
  192. template <typename T>
  193. using range_reference_type = typename range_reference_type_impl<T>::type;
  194. #else
  195. template <typename Range>
  196. using range_reference_type =
  197. decltype(*detail::range_begin(std::declval<Range&>()));
  198. #endif
  199. // We don't use the Range's value_type for anything, but we do need the Range's
  200. // reference type, with cv-ref stripped.
  201. template <typename Range>
  202. using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
  203. template <typename Formatter>
  204. FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
  205. -> decltype(f.set_debug_format(set)) {
  206. f.set_debug_format(set);
  207. }
  208. template <typename Formatter>
  209. FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
  210. template <typename T>
  211. struct range_format_kind_
  212. : std::integral_constant<range_format,
  213. std::is_same<uncvref_type<T>, T>::value
  214. ? range_format::disabled
  215. : is_map<T>::value ? range_format::map
  216. : is_set<T>::value ? range_format::set
  217. : range_format::sequence> {};
  218. template <range_format K>
  219. using range_format_constant = std::integral_constant<range_format, K>;
  220. // These are not generic lambdas for compatibility with C++11.
  221. template <typename ParseContext> struct parse_empty_specs {
  222. template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
  223. f.parse(ctx);
  224. detail::maybe_set_debug_format(f, true);
  225. }
  226. ParseContext& ctx;
  227. };
  228. template <typename FormatContext> struct format_tuple_element {
  229. using char_type = typename FormatContext::char_type;
  230. template <typename T>
  231. void operator()(const formatter<T, char_type>& f, const T& v) {
  232. if (i > 0) ctx.advance_to(detail::copy<char_type>(separator, ctx.out()));
  233. ctx.advance_to(f.format(v, ctx));
  234. ++i;
  235. }
  236. int i;
  237. FormatContext& ctx;
  238. basic_string_view<char_type> separator;
  239. };
  240. } // namespace detail
  241. template <typename T> struct is_tuple_like {
  242. static constexpr const bool value =
  243. detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
  244. };
  245. template <typename T, typename C> struct is_tuple_formattable {
  246. static constexpr const bool value =
  247. detail::is_tuple_formattable_<T, C>::value;
  248. };
  249. template <typename Tuple, typename Char>
  250. struct formatter<Tuple, Char,
  251. enable_if_t<fmt::is_tuple_like<Tuple>::value &&
  252. fmt::is_tuple_formattable<Tuple, Char>::value>> {
  253. private:
  254. decltype(detail::tuple::get_formatters<Tuple, Char>(
  255. detail::tuple_index_sequence<Tuple>())) formatters_;
  256. basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
  257. basic_string_view<Char> opening_bracket_ =
  258. detail::string_literal<Char, '('>{};
  259. basic_string_view<Char> closing_bracket_ =
  260. detail::string_literal<Char, ')'>{};
  261. public:
  262. FMT_CONSTEXPR formatter() {}
  263. FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
  264. separator_ = sep;
  265. }
  266. FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
  267. basic_string_view<Char> close) {
  268. opening_bracket_ = open;
  269. closing_bracket_ = close;
  270. }
  271. template <typename ParseContext>
  272. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  273. auto it = ctx.begin();
  274. if (it != ctx.end() && *it != '}') report_error("invalid format specifier");
  275. detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
  276. return it;
  277. }
  278. template <typename FormatContext>
  279. auto format(const Tuple& value, FormatContext& ctx) const
  280. -> decltype(ctx.out()) {
  281. ctx.advance_to(detail::copy<Char>(opening_bracket_, ctx.out()));
  282. detail::for_each2(
  283. formatters_, value,
  284. detail::format_tuple_element<FormatContext>{0, ctx, separator_});
  285. return detail::copy<Char>(closing_bracket_, ctx.out());
  286. }
  287. };
  288. template <typename T, typename Char> struct is_range {
  289. static constexpr const bool value =
  290. detail::is_range_<T>::value && !detail::has_to_string_view<T>::value;
  291. };
  292. namespace detail {
  293. template <typename Context> struct range_mapper {
  294. using mapper = arg_mapper<Context>;
  295. template <typename T,
  296. FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
  297. static auto map(T&& value) -> T&& {
  298. return static_cast<T&&>(value);
  299. }
  300. template <typename T,
  301. FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
  302. static auto map(T&& value)
  303. -> decltype(mapper().map(static_cast<T&&>(value))) {
  304. return mapper().map(static_cast<T&&>(value));
  305. }
  306. };
  307. template <typename Char, typename Element>
  308. using range_formatter_type =
  309. formatter<remove_cvref_t<decltype(range_mapper<buffered_context<Char>>{}
  310. .map(std::declval<Element>()))>,
  311. Char>;
  312. template <typename R>
  313. using maybe_const_range =
  314. conditional_t<has_const_begin_end<R>::value, const R, R>;
  315. // Workaround a bug in MSVC 2015 and earlier.
  316. #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
  317. template <typename R, typename Char>
  318. struct is_formattable_delayed
  319. : is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
  320. #endif
  321. } // namespace detail
  322. template <typename...> struct conjunction : std::true_type {};
  323. template <typename P> struct conjunction<P> : P {};
  324. template <typename P1, typename... Pn>
  325. struct conjunction<P1, Pn...>
  326. : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
  327. template <typename T, typename Char, typename Enable = void>
  328. struct range_formatter;
  329. template <typename T, typename Char>
  330. struct range_formatter<
  331. T, Char,
  332. enable_if_t<conjunction<std::is_same<T, remove_cvref_t<T>>,
  333. is_formattable<T, Char>>::value>> {
  334. private:
  335. detail::range_formatter_type<Char, T> underlying_;
  336. basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
  337. basic_string_view<Char> opening_bracket_ =
  338. detail::string_literal<Char, '['>{};
  339. basic_string_view<Char> closing_bracket_ =
  340. detail::string_literal<Char, ']'>{};
  341. bool is_debug = false;
  342. template <typename Output, typename It, typename Sentinel, typename U = T,
  343. FMT_ENABLE_IF(std::is_same<U, Char>::value)>
  344. auto write_debug_string(Output& out, It it, Sentinel end) const -> Output {
  345. auto buf = basic_memory_buffer<Char>();
  346. for (; it != end; ++it) buf.push_back(*it);
  347. auto specs = format_specs();
  348. specs.type = presentation_type::debug;
  349. return detail::write<Char>(
  350. out, basic_string_view<Char>(buf.data(), buf.size()), specs);
  351. }
  352. template <typename Output, typename It, typename Sentinel, typename U = T,
  353. FMT_ENABLE_IF(!std::is_same<U, Char>::value)>
  354. auto write_debug_string(Output& out, It, Sentinel) const -> Output {
  355. return out;
  356. }
  357. public:
  358. FMT_CONSTEXPR range_formatter() {}
  359. FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
  360. return underlying_;
  361. }
  362. FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
  363. separator_ = sep;
  364. }
  365. FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
  366. basic_string_view<Char> close) {
  367. opening_bracket_ = open;
  368. closing_bracket_ = close;
  369. }
  370. template <typename ParseContext>
  371. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  372. auto it = ctx.begin();
  373. auto end = ctx.end();
  374. detail::maybe_set_debug_format(underlying_, true);
  375. if (it == end) return underlying_.parse(ctx);
  376. switch (detail::to_ascii(*it)) {
  377. case 'n':
  378. set_brackets({}, {});
  379. ++it;
  380. break;
  381. case '?':
  382. is_debug = true;
  383. set_brackets({}, {});
  384. ++it;
  385. if (it == end || *it != 's') report_error("invalid format specifier");
  386. FMT_FALLTHROUGH;
  387. case 's':
  388. if (!std::is_same<T, Char>::value)
  389. report_error("invalid format specifier");
  390. if (!is_debug) {
  391. set_brackets(detail::string_literal<Char, '"'>{},
  392. detail::string_literal<Char, '"'>{});
  393. set_separator({});
  394. detail::maybe_set_debug_format(underlying_, false);
  395. }
  396. ++it;
  397. return it;
  398. }
  399. if (it != end && *it != '}') {
  400. if (*it != ':') report_error("invalid format specifier");
  401. detail::maybe_set_debug_format(underlying_, false);
  402. ++it;
  403. }
  404. ctx.advance_to(it);
  405. return underlying_.parse(ctx);
  406. }
  407. template <typename R, typename FormatContext>
  408. auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
  409. auto mapper = detail::range_mapper<buffered_context<Char>>();
  410. auto out = ctx.out();
  411. auto it = detail::range_begin(range);
  412. auto end = detail::range_end(range);
  413. if (is_debug) return write_debug_string(out, it, end);
  414. out = detail::copy<Char>(opening_bracket_, out);
  415. int i = 0;
  416. for (; it != end; ++it) {
  417. if (i > 0) out = detail::copy<Char>(separator_, out);
  418. ctx.advance_to(out);
  419. auto&& item = *it; // Need an lvalue
  420. out = underlying_.format(mapper.map(item), ctx);
  421. ++i;
  422. }
  423. out = detail::copy<Char>(closing_bracket_, out);
  424. return out;
  425. }
  426. };
  427. FMT_EXPORT
  428. template <typename T, typename Char, typename Enable = void>
  429. struct range_format_kind
  430. : conditional_t<
  431. is_range<T, Char>::value, detail::range_format_kind_<T>,
  432. std::integral_constant<range_format, range_format::disabled>> {};
  433. template <typename R, typename Char>
  434. struct formatter<
  435. R, Char,
  436. enable_if_t<conjunction<
  437. bool_constant<
  438. range_format_kind<R, Char>::value != range_format::disabled &&
  439. range_format_kind<R, Char>::value != range_format::map &&
  440. range_format_kind<R, Char>::value != range_format::string &&
  441. range_format_kind<R, Char>::value != range_format::debug_string>
  442. // Workaround a bug in MSVC 2015 and earlier.
  443. #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
  444. ,
  445. detail::is_formattable_delayed<R, Char>
  446. #endif
  447. >::value>> {
  448. private:
  449. using range_type = detail::maybe_const_range<R>;
  450. range_formatter<detail::uncvref_type<range_type>, Char> range_formatter_;
  451. public:
  452. using nonlocking = void;
  453. FMT_CONSTEXPR formatter() {
  454. if (detail::const_check(range_format_kind<R, Char>::value !=
  455. range_format::set))
  456. return;
  457. range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
  458. detail::string_literal<Char, '}'>{});
  459. }
  460. template <typename ParseContext>
  461. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  462. return range_formatter_.parse(ctx);
  463. }
  464. template <typename FormatContext>
  465. auto format(range_type& range, FormatContext& ctx) const
  466. -> decltype(ctx.out()) {
  467. return range_formatter_.format(range, ctx);
  468. }
  469. };
  470. // A map formatter.
  471. template <typename R, typename Char>
  472. struct formatter<
  473. R, Char,
  474. enable_if_t<range_format_kind<R, Char>::value == range_format::map>> {
  475. private:
  476. using map_type = detail::maybe_const_range<R>;
  477. using element_type = detail::uncvref_type<map_type>;
  478. decltype(detail::tuple::get_formatters<element_type, Char>(
  479. detail::tuple_index_sequence<element_type>())) formatters_;
  480. bool no_delimiters_ = false;
  481. public:
  482. FMT_CONSTEXPR formatter() {}
  483. template <typename ParseContext>
  484. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  485. auto it = ctx.begin();
  486. auto end = ctx.end();
  487. if (it != end) {
  488. if (detail::to_ascii(*it) == 'n') {
  489. no_delimiters_ = true;
  490. ++it;
  491. }
  492. if (it != end && *it != '}') {
  493. if (*it != ':') report_error("invalid format specifier");
  494. ++it;
  495. }
  496. ctx.advance_to(it);
  497. }
  498. detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
  499. return it;
  500. }
  501. template <typename FormatContext>
  502. auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
  503. auto out = ctx.out();
  504. basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
  505. if (!no_delimiters_) out = detail::copy<Char>(open, out);
  506. int i = 0;
  507. auto mapper = detail::range_mapper<buffered_context<Char>>();
  508. basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
  509. for (auto&& value : map) {
  510. if (i > 0) out = detail::copy<Char>(sep, out);
  511. ctx.advance_to(out);
  512. detail::for_each2(formatters_, mapper.map(value),
  513. detail::format_tuple_element<FormatContext>{
  514. 0, ctx, detail::string_literal<Char, ':', ' '>{}});
  515. ++i;
  516. }
  517. basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
  518. if (!no_delimiters_) out = detail::copy<Char>(close, out);
  519. return out;
  520. }
  521. };
  522. // A (debug_)string formatter.
  523. template <typename R, typename Char>
  524. struct formatter<
  525. R, Char,
  526. enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
  527. range_format_kind<R, Char>::value ==
  528. range_format::debug_string>> {
  529. private:
  530. using range_type = detail::maybe_const_range<R>;
  531. using string_type =
  532. conditional_t<std::is_constructible<
  533. detail::std_string_view<Char>,
  534. decltype(detail::range_begin(std::declval<R>())),
  535. decltype(detail::range_end(std::declval<R>()))>::value,
  536. detail::std_string_view<Char>, std::basic_string<Char>>;
  537. formatter<string_type, Char> underlying_;
  538. public:
  539. template <typename ParseContext>
  540. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  541. return underlying_.parse(ctx);
  542. }
  543. template <typename FormatContext>
  544. auto format(range_type& range, FormatContext& ctx) const
  545. -> decltype(ctx.out()) {
  546. auto out = ctx.out();
  547. if (detail::const_check(range_format_kind<R, Char>::value ==
  548. range_format::debug_string))
  549. *out++ = '"';
  550. out = underlying_.format(
  551. string_type{detail::range_begin(range), detail::range_end(range)}, ctx);
  552. if (detail::const_check(range_format_kind<R, Char>::value ==
  553. range_format::debug_string))
  554. *out++ = '"';
  555. return out;
  556. }
  557. };
  558. template <typename It, typename Sentinel, typename Char = char>
  559. struct join_view : detail::view {
  560. It begin;
  561. Sentinel end;
  562. basic_string_view<Char> sep;
  563. join_view(It b, Sentinel e, basic_string_view<Char> s)
  564. : begin(std::move(b)), end(e), sep(s) {}
  565. };
  566. template <typename It, typename Sentinel, typename Char>
  567. struct formatter<join_view<It, Sentinel, Char>, Char> {
  568. private:
  569. using value_type =
  570. #ifdef __cpp_lib_ranges
  571. std::iter_value_t<It>;
  572. #else
  573. typename std::iterator_traits<It>::value_type;
  574. #endif
  575. formatter<remove_cvref_t<value_type>, Char> value_formatter_;
  576. using view_ref = conditional_t<std::is_copy_constructible<It>::value,
  577. const join_view<It, Sentinel, Char>&,
  578. join_view<It, Sentinel, Char>&&>;
  579. public:
  580. using nonlocking = void;
  581. template <typename ParseContext>
  582. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
  583. return value_formatter_.parse(ctx);
  584. }
  585. template <typename FormatContext>
  586. auto format(view_ref& value, FormatContext& ctx) const
  587. -> decltype(ctx.out()) {
  588. auto it = std::forward<view_ref>(value).begin;
  589. auto out = ctx.out();
  590. if (it == value.end) return out;
  591. out = value_formatter_.format(*it, ctx);
  592. ++it;
  593. while (it != value.end) {
  594. out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
  595. ctx.advance_to(out);
  596. out = value_formatter_.format(*it, ctx);
  597. ++it;
  598. }
  599. return out;
  600. }
  601. };
  602. /// Returns a view that formats the iterator range `[begin, end)` with elements
  603. /// separated by `sep`.
  604. template <typename It, typename Sentinel>
  605. auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
  606. return {std::move(begin), end, sep};
  607. }
  608. /**
  609. * Returns a view that formats `range` with elements separated by `sep`.
  610. *
  611. * **Example**:
  612. *
  613. * auto v = std::vector<int>{1, 2, 3};
  614. * fmt::print("{}", fmt::join(v, ", "));
  615. * // Output: 1, 2, 3
  616. *
  617. * `fmt::join` applies passed format specifiers to the range elements:
  618. *
  619. * fmt::print("{:02}", fmt::join(v, ", "));
  620. * // Output: 01, 02, 03
  621. */
  622. template <typename Range>
  623. auto join(Range&& r, string_view sep)
  624. -> join_view<decltype(detail::range_begin(r)),
  625. decltype(detail::range_end(r))> {
  626. return {detail::range_begin(r), detail::range_end(r), sep};
  627. }
  628. template <typename Char, typename... T> struct tuple_join_view : detail::view {
  629. const std::tuple<T...>& tuple;
  630. basic_string_view<Char> sep;
  631. tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
  632. : tuple(t), sep{s} {}
  633. };
  634. // Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
  635. // support in tuple_join. It is disabled by default because of issues with
  636. // the dynamic width and precision.
  637. #ifndef FMT_TUPLE_JOIN_SPECIFIERS
  638. # define FMT_TUPLE_JOIN_SPECIFIERS 0
  639. #endif
  640. template <typename Char, typename... T>
  641. struct formatter<tuple_join_view<Char, T...>, Char> {
  642. template <typename ParseContext>
  643. FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
  644. return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
  645. }
  646. template <typename FormatContext>
  647. auto format(const tuple_join_view<Char, T...>& value,
  648. FormatContext& ctx) const -> typename FormatContext::iterator {
  649. return do_format(value, ctx,
  650. std::integral_constant<size_t, sizeof...(T)>());
  651. }
  652. private:
  653. std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
  654. template <typename ParseContext>
  655. FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
  656. std::integral_constant<size_t, 0>)
  657. -> decltype(ctx.begin()) {
  658. return ctx.begin();
  659. }
  660. template <typename ParseContext, size_t N>
  661. FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
  662. std::integral_constant<size_t, N>)
  663. -> decltype(ctx.begin()) {
  664. auto end = ctx.begin();
  665. #if FMT_TUPLE_JOIN_SPECIFIERS
  666. end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
  667. if (N > 1) {
  668. auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
  669. if (end != end1)
  670. report_error("incompatible format specs for tuple elements");
  671. }
  672. #endif
  673. return end;
  674. }
  675. template <typename FormatContext>
  676. auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
  677. std::integral_constant<size_t, 0>) const ->
  678. typename FormatContext::iterator {
  679. return ctx.out();
  680. }
  681. template <typename FormatContext, size_t N>
  682. auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
  683. std::integral_constant<size_t, N>) const ->
  684. typename FormatContext::iterator {
  685. auto out = std::get<sizeof...(T) - N>(formatters_)
  686. .format(std::get<sizeof...(T) - N>(value.tuple), ctx);
  687. if (N <= 1) return out;
  688. out = detail::copy<Char>(value.sep, out);
  689. ctx.advance_to(out);
  690. return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
  691. }
  692. };
  693. namespace detail {
  694. // Check if T has an interface like a container adaptor (e.g. std::stack,
  695. // std::queue, std::priority_queue).
  696. template <typename T> class is_container_adaptor_like {
  697. template <typename U> static auto check(U* p) -> typename U::container_type;
  698. template <typename> static void check(...);
  699. public:
  700. static constexpr const bool value =
  701. !std::is_void<decltype(check<T>(nullptr))>::value;
  702. };
  703. template <typename Container> struct all {
  704. const Container& c;
  705. auto begin() const -> typename Container::const_iterator { return c.begin(); }
  706. auto end() const -> typename Container::const_iterator { return c.end(); }
  707. };
  708. } // namespace detail
  709. template <typename T, typename Char>
  710. struct formatter<
  711. T, Char,
  712. enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
  713. bool_constant<range_format_kind<T, Char>::value ==
  714. range_format::disabled>>::value>>
  715. : formatter<detail::all<typename T::container_type>, Char> {
  716. using all = detail::all<typename T::container_type>;
  717. template <typename FormatContext>
  718. auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
  719. struct getter : T {
  720. static auto get(const T& t) -> all {
  721. return {t.*(&getter::c)}; // Access c through the derived class.
  722. }
  723. };
  724. return formatter<all>::format(getter::get(t), ctx);
  725. }
  726. };
  727. FMT_BEGIN_EXPORT
  728. /**
  729. * Returns an object that formats `std::tuple` with elements separated by `sep`.
  730. *
  731. * **Example**:
  732. *
  733. * auto t = std::tuple<int, char>{1, 'a'};
  734. * fmt::print("{}", fmt::join(t, ", "));
  735. * // Output: 1, a
  736. */
  737. template <typename... T>
  738. FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
  739. -> tuple_join_view<char, T...> {
  740. return {tuple, sep};
  741. }
  742. /**
  743. * Returns an object that formats `std::initializer_list` with elements
  744. * separated by `sep`.
  745. *
  746. * **Example**:
  747. *
  748. * fmt::print("{}", fmt::join({1, 2, 3}, ", "));
  749. * // Output: "1, 2, 3"
  750. */
  751. template <typename T>
  752. auto join(std::initializer_list<T> list, string_view sep)
  753. -> join_view<const T*, const T*> {
  754. return join(std::begin(list), std::end(list), sep);
  755. }
  756. FMT_END_EXPORT
  757. FMT_END_NAMESPACE
  758. #endif // FMT_RANGES_H_