fork(6) download
  1. #ifndef pretty_print_0x57547_sa4884X_0_1_h_guard_
  2. #define pretty_print_0x57547_sa4884X_0_1_h_guard_
  3.  
  4. #include <string>
  5. #include <iostream>
  6. #include <type_traits>
  7. #include <iterator>
  8. #include <utility>
  9.  
  10. #define PRETTY_DEFAULT_DECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
  11.   namespace pretty { template< __VA_ARGS__ >\
  12.   struct defaulted< TYPE > {\
  13.   static decor< TYPE > decoration(){\
  14.   return { PREFIX, DELIM, POSTFIX };\
  15.   } /*decoration*/ }; /*defaulted*/} /*pretty*/
  16.  
  17. #define PRETTY_DEFAULT_WDECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
  18.   namespace pretty { template< __VA_ARGS__ >\
  19.   struct defaulted< TYPE, wchar_t, std::char_traits<wchar_t> > {\
  20.   static decor< TYPE, wchar_t, std::char_traits<wchar_t> > decoration(){\
  21.   return { PREFIX, DELIM, POSTFIX };\
  22.   } /*decoration*/ }; /*defaulted*/} /*pretty*/
  23.  
  24. namespace pretty
  25. {
  26.  
  27. namespace detail
  28. {
  29. // drag in begin and end overloads
  30. using std::begin;
  31. using std::end;
  32. // helper template
  33. template <int I> using _ol = std::integral_constant<int, I>*;
  34. // SFINAE check whether T is a range with begin/end
  35. template<class T>
  36. class is_range
  37. {
  38. // helper function declarations using expression sfinae
  39. template <class U, _ol<0> = nullptr>
  40. static std::false_type b(...);
  41. template <class U, _ol<1> = nullptr>
  42. static auto b(U &v) -> decltype(begin(v), std::true_type());
  43. template <class U, _ol<0> = nullptr>
  44. static std::false_type e(...);
  45. template <class U, _ol<1> = nullptr>
  46. static auto e(U &v) -> decltype(end(v), std::true_type());
  47. // return types
  48. using b_return = decltype(b<T>(std::declval<T&>()));
  49. using e_return = decltype(e<T>(std::declval<T&>()));
  50. public:
  51. static const bool value = b_return::value && e_return::value;
  52. };
  53. }
  54.  
  55. // holder class for data
  56. template<class T, class CharT = char,
  57. class TraitT = std::char_traits < CharT >>
  58. struct decor
  59. {
  60. static const int xindex;
  61. std::basic_string<CharT, TraitT> prefix, delimiter, postfix;
  62. decor(std::basic_string<CharT, TraitT> const & pre = "",
  63. std::basic_string<CharT, TraitT> const & delim = "",
  64. std::basic_string<CharT, TraitT> const & post = "")
  65. : prefix(pre), delimiter(delim), postfix(post) {}
  66. };
  67.  
  68. template<class T, class charT, class traits>
  69. int const decor<T, charT, traits>::xindex = std::ios_base::xalloc();
  70.  
  71. namespace detail
  72. {
  73.  
  74. template<class T, class CharT, class TraitT>
  75. void manage_decor(std::ios_base::event evt, std::ios_base &s, int const idx)
  76. {
  77. using deco_type = decor<T, CharT, TraitT>;
  78. if (evt == std::ios_base::erase_event)
  79. { // erase deco
  80. void const * const p = s.pword(idx);
  81. if (p)
  82. {
  83. delete static_cast<deco_type const * const>(p);
  84. s.pword(idx) = nullptr;
  85. }
  86. }
  87. else if (evt == std::ios_base::copyfmt_event)
  88. { // copy deco
  89. void const * const p = s.pword(idx);
  90. if (p)
  91. {
  92. auto np = new deco_type{ *static_cast<deco_type const * const>(p) };
  93. s.pword(idx) = static_cast<void*>(np);
  94. }
  95. }
  96. }
  97.  
  98. template<class T>
  99. struct clearer {};
  100.  
  101. template<class T, class CharT, class TraitT>
  102. std::basic_ostream<CharT, TraitT>& operator<< (
  103. std::basic_ostream<CharT, TraitT> &s, clearer<T> const &)
  104. {
  105. using deco_type = decor<T, CharT, TraitT>;
  106. void const * const p = s.pword(deco_type::xindex);
  107. if (p)
  108. { // delete if set
  109. delete static_cast<deco_type const *>(p);
  110. s.pword(deco_type::xindex) = nullptr;
  111. }
  112. return s;
  113. }
  114.  
  115. template<class CharT, class TraitT = std::char_traits<CharT>>
  116. struct default_data
  117. {
  118. static inline std::basic_string<CharT, TraitT> prefix() { return{ "" }; }
  119. static inline std::basic_string<CharT, TraitT> delimiter() { return{ ", " }; }
  120. static inline std::basic_string<CharT, TraitT> postfix() { return{ "" }; }
  121. };
  122.  
  123. template<>
  124. struct default_data<wchar_t, std::char_traits<wchar_t>>
  125. {
  126. using CT = std::char_traits<wchar_t>;
  127. static inline std::basic_string<wchar_t, CT> prefix() { return{ L"" }; }
  128. static inline std::basic_string<wchar_t, CT> delimiter() { return{ L", " }; }
  129. static inline std::basic_string<wchar_t, CT> postfix() { return{ L"" }; }
  130. };
  131.  
  132. }
  133.  
  134. // Clear decoration for T
  135. template<class T>
  136. detail::clearer<T> clear() { return{}; }
  137. template<class T, class CharT, class TraitT>
  138. void clear(std::basic_ostream<CharT, TraitT> &s) { s << detail::clearer<T>{}; }
  139.  
  140. // impose decoration on ostream
  141. template<class T, class CharT, class TraitT>
  142. std::basic_ostream<CharT, TraitT>& operator<<(
  143. std::basic_ostream<CharT, TraitT> &s, decor<T, CharT, TraitT> && h)
  144. {
  145. using deco_type = decor<T, CharT, TraitT>;
  146. void const * const p = s.pword(deco_type::xindex);
  147. // delete if already set
  148. if (p) delete static_cast<decor<T, CharT, TraitT> const *>(p);
  149. s.pword(deco_type::xindex) = static_cast<void *>(new deco_type{ std::move(h) });
  150. // check whether we alread have a callback registered
  151. if (s.iword(deco_type::xindex) == 0)
  152. { // if this is not the case register callback and set iword
  153. s.register_callback(detail::manage_decor<T, CharT, TraitT>, deco_type::xindex);
  154. s.iword(deco_type::xindex) = 1;
  155. }
  156. return s;
  157. }
  158.  
  159. template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
  160. struct defaulted
  161. {
  162. static inline decor<T, CharT, TraitT> decoration()
  163. {
  164. return{ detail::default_data<CharT, TraitT>::prefix(),
  165. detail::default_data<CharT, TraitT>::delimiter(),
  166. detail::default_data<CharT, TraitT>::postfix() };
  167. }
  168. };
  169.  
  170. template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
  171. decor<T, CharT, TraitT> decoration(std::basic_string<CharT, TraitT> const & prefix,
  172. std::basic_string<CharT, TraitT> const & delimiter,
  173. std::basic_string<CharT, TraitT> const & postfix)
  174. {
  175. return{ prefix, delimiter, postfix };
  176. }
  177.  
  178. template<class T, class CharT = char,
  179. class TraitT = std::char_traits < CharT >>
  180. decor<T, CharT, TraitT> decoration(std::basic_string<CharT, TraitT> const & delimiter)
  181. {
  182. using str_type = std::basic_string<CharT, TraitT>;
  183. return{ defaulted<T, CharT, TraitT>::decoration().prefix,
  184. delimiter, defaulted<T, CharT, TraitT>::decoration().postfix };
  185. }
  186.  
  187. template<class T, class CharT = char,
  188. class TraitT = std::char_traits < CharT >>
  189. decor<T, CharT, TraitT> decoration(CharT const * const prefix,
  190. CharT const * const delimiter, CharT const * const postfix)
  191. {
  192. using str_type = std::basic_string<CharT, TraitT>;
  193. return{ str_type{ prefix }, str_type{ delimiter }, str_type{ postfix } };
  194. }
  195.  
  196. template<class T, class CharT = char,
  197. class TraitT = std::char_traits < CharT >>
  198. decor<T, CharT, TraitT> decoration(CharT const * const delimiter)
  199. {
  200. using str_type = std::basic_string<CharT, TraitT>;
  201. return{ defaulted<T, CharT, TraitT>::decoration().prefix,
  202. str_type{ delimiter }, defaulted<T, CharT, TraitT>::decoration().postfix };
  203. }
  204.  
  205. template<typename T, std::size_t N, std::size_t L>
  206. struct tuple
  207. {
  208. template<class CharT, class TraitT>
  209. static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
  210. std::basic_string<CharT, TraitT> const &delimiter)
  211. {
  212. s << std::get<N>(value) << delimiter;
  213. tuple<T, N + 1, L>::print(s, value, delimiter);
  214. }
  215. };
  216.  
  217. template<typename T, std::size_t N>
  218. struct tuple<T, N, N>
  219. {
  220. template<class CharT, class TraitT>
  221. static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
  222. std::basic_string<CharT, TraitT> const &) {
  223. s << std::get<N>(value);
  224. }
  225. };
  226.  
  227. }
  228.  
  229. template<class CharT, class TraitT>
  230. std::basic_ostream<CharT, TraitT> & operator<< (
  231. std::basic_ostream<CharT, TraitT> &s, std::tuple<> const & v)
  232. {
  233. using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
  234. using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
  235. void const * const p = s.pword(deco_type::xindex);
  236. auto const d = static_cast<deco_type const * const>(p);
  237. s << (d ? d->prefix : defaulted_type::decoration().prefix);
  238. s << (d ? d->postfix : defaulted_type::decoration().postfix);
  239. return s;
  240. }
  241.  
  242. template<class CharT, class TraitT, class ... T>
  243. std::basic_ostream<CharT, TraitT> & operator<< (
  244. std::basic_ostream<CharT, TraitT> &s, std::tuple<T...> const & v)
  245. {
  246. using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
  247. using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
  248. using pretty_tuple = pretty::tuple<std::tuple<T...>, 0U, sizeof...(T)-1U>;
  249. void const * const p = s.pword(deco_type::xindex);
  250. auto const d = static_cast<deco_type const * const>(p);
  251. s << (d ? d->prefix : defaulted_type::decoration().prefix);
  252. pretty_tuple::print(s, v, d ? d->delimiter : defaulted_type::decoration().delimiter);
  253. s << (d ? d->postfix : defaulted_type::decoration().postfix);
  254. return s;
  255. }
  256.  
  257. template<class T, class U, class CharT, class TraitT>
  258. std::basic_ostream<CharT, TraitT> & operator<< (
  259. std::basic_ostream<CharT, TraitT> &s, std::pair<T, U> const & v)
  260. {
  261. using deco_type = pretty::decor<std::pair<T, U>, CharT, TraitT>;
  262. using defaulted_type = pretty::defaulted<std::pair<T, U>, CharT, TraitT>;
  263. void const * const p = s.pword(deco_type::xindex);
  264. auto const d = static_cast<deco_type const * const>(p);
  265. s << (d ? d->prefix : defaulted_type::decoration().prefix);
  266. s << v.first;
  267. s << (d ? d->delimiter : defaulted_type::decoration().delimiter);
  268. s << v.second;
  269. s << (d ? d->postfix : defaulted_type::decoration().postfix);
  270. return s;
  271. }
  272.  
  273.  
  274. template<class T, class CharT = char,
  275. class TraitT = std::char_traits < CharT >>
  276. typename std::enable_if < pretty::detail::is_range<T>::value,
  277. std::basic_ostream < CharT, TraitT >> ::type & operator<< (
  278. std::basic_ostream<CharT, TraitT> &s, T const & v)
  279. {
  280. bool first(true);
  281. using deco_type = pretty::decor<T, CharT, TraitT>;
  282. using default_type = pretty::defaulted<T, CharT, TraitT>;
  283. void const * const p = s.pword(deco_type::xindex);
  284. auto d = static_cast<pretty::decor<T, CharT, TraitT> const * const>(p);
  285. s << (d ? d->prefix : default_type::decoration().prefix);
  286. for (auto const & e : v)
  287. { // v is range thus range based for works
  288. if (!first) s << (d ? d->delimiter : default_type::decoration().delimiter);
  289. s << e;
  290. first = false;
  291. }
  292. s << (d ? d->postfix : default_type::decoration().postfix);
  293. return s;
  294. }
  295.  
  296. #endif // pretty_print_0x57547_sa4884X_0_1_h_guard_
  297.  
  298.  
  299. #include <vector>
  300. #include <map>
  301. #include <set>
  302. #include <sstream>
  303. #include <list>
  304. #include <exception>
  305. #include <utility>
  306.  
  307. PRETTY_DEFAULT_DECORATION(T[N], "[", ";", "]", class T, std::size_t N)
  308. #define COMMA ,
  309. PRETTY_DEFAULT_DECORATION(std::pair<T COMMA U>, "(", ", ", ")", class T, class U)
  310.  
  311. int main(int argc, char ** argv)
  312. {
  313.  
  314. #ifndef _DROP_EXCEPTIONS
  315. try
  316. {
  317. #endif
  318.  
  319. float e[5] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
  320.  
  321. std::vector<std::vector<int>> m{ { 1,2,3 },{ 4,5,6 },{ 7,8,9 } };
  322. std::cout << pretty::decoration<std::vector<std::vector<int>>>("\n");
  323. std::cout << m;
  324. std::stringstream u, v;
  325. // apply different decoration to u and v
  326. u << pretty::decoration<float[5]>("{", "; ", "}");
  327. v << pretty::decoration<float[5]>("[", ", ", "]");
  328. std::cout << e << '\n'; // using specialized decoration above
  329. u << e << '\n';
  330. v << e << '\n';
  331. std::cout << u.str() << v.str();
  332.  
  333. std::set<int> ms{ 1, 5, 3, 2, 9, 6, 7 };
  334. std::cout << ms << '\n';
  335.  
  336. std::map<int, int> mm{ std::make_pair<const int, int>(1,1),
  337. std::make_pair<const int, int>(2,4),
  338. std::make_pair<const int, int>(3,7) };
  339. std::cout << mm << '\n';
  340.  
  341. std::list<int> ml{ 12, 12, 15, 8, 2, 1, 4 };
  342. std::cout << ml << '\n';
  343.  
  344. std::vector<int> mv{ 155, 32, 26, 0 };
  345. std::cout << mv << '\n';
  346.  
  347. std::vector<int> a{ 2, 3, 4, 1 }, b{ 4, 6, 1, 2 };
  348. std::vector<std::vector<int>> c{ a, b, b, a };
  349. std::vector<double> d{ 4.,5.,8.,124.4 };
  350.  
  351. std::cout << pretty::decoration<std::vector<int>>("[[ ", " :: ", " ]]");
  352. std::cout << a << '\n';
  353. std::cout << b << '\n';
  354. std::cout << pretty::clear<std::vector<int>>();
  355. std::cout << c << '\n';
  356. std::cout << d << '\n';
  357.  
  358.  
  359. #ifndef _DROP_EXCEPTIONS
  360. }
  361. catch (std::exception & e)
  362. {
  363. std::cout << e.what();
  364. }
  365. #endif
  366.  
  367. return 0;
  368. }
  369.  
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
1, 2, 3
4, 5, 6
7, 8, 9[1.1;2.2;3.3;4.4;5.5]
{1.1; 2.2; 3.3; 4.4; 5.5}
[1.1, 2.2, 3.3, 4.4, 5.5]
1, 2, 3, 5, 6, 7, 9
(1, 1), (2, 4), (3, 7)
12, 12, 15, 8, 2, 1, 4
155, 32, 26, 0
[[  2 :: 3 :: 4 :: 1  ]]
[[  4 :: 6 :: 1 :: 2  ]]
2, 3, 4, 1
4, 6, 1, 2
4, 6, 1, 2
2, 3, 4, 1
4, 5, 8, 124.4