File indexing completed on 2025-04-19 09:06:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef H_PRETTY_PRINT
0014 #define H_PRETTY_PRINT
0015
0016
0017
0018 #include <cstddef>
0019 #include <iterator>
0020 #include <memory>
0021 #include <ostream>
0022 #include <set>
0023 #include <tuple>
0024 #include <type_traits>
0025 #include <unordered_set>
0026 #include <utility>
0027 #include <valarray>
0028
0029 namespace Rivet
0030 {
0031 namespace pretty_print
0032 {
0033 namespace detail
0034 {
0035
0036
0037 struct sfinae_base
0038 {
0039 using yes = char;
0040 using no = yes[2];
0041 };
0042
0043 template <typename T>
0044 struct has_const_iterator : private sfinae_base
0045 {
0046 private:
0047 template <typename C> static yes & test(typename C::const_iterator*);
0048 template <typename C> static no & test(...);
0049 public:
0050 static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
0051 using type = T;
0052 };
0053
0054 template <typename T>
0055 struct has_begin_end : private sfinae_base
0056 {
0057 private:
0058 template <typename C>
0059 static yes & f(typename std::enable_if<
0060 std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
0061 typename C::const_iterator(C::*)() const>::value>::type *);
0062
0063 template <typename C> static no & f(...);
0064
0065 template <typename C>
0066 static yes & g(typename std::enable_if<
0067 std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
0068 typename C::const_iterator(C::*)() const>::value, void>::type*);
0069
0070 template <typename C> static no & g(...);
0071
0072 public:
0073 static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
0074 static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
0075 };
0076
0077 }
0078
0079
0080
0081
0082 template <typename TChar>
0083 struct delimiters_values
0084 {
0085 using char_type = TChar;
0086 const char_type * prefix;
0087 const char_type * delimiter;
0088 const char_type * postfix;
0089 };
0090
0091
0092
0093
0094 template <typename T, typename TChar>
0095 struct delimiters
0096 {
0097 using type = delimiters_values<TChar>;
0098 static const type values;
0099 };
0100
0101
0102
0103
0104
0105
0106 template <typename T,
0107 typename TChar = char,
0108 typename TCharTraits = ::std::char_traits<TChar>,
0109 typename TDelimiters = delimiters<T, TChar>>
0110 struct print_container_helper
0111 {
0112 using delimiters_type = TDelimiters;
0113 using ostream_type = std::basic_ostream<TChar, TCharTraits>;
0114
0115 template <typename U>
0116 struct printer
0117 {
0118 static void print_body(const U & c, ostream_type & stream)
0119 {
0120 using std::begin;
0121 using std::end;
0122
0123 auto it = begin(c);
0124 const auto the_end = end(c);
0125
0126 if (it != the_end)
0127 {
0128 for ( ; ; )
0129 {
0130 stream << *it;
0131
0132 if (++it == the_end) break;
0133
0134 if (delimiters_type::values.delimiter != NULL)
0135 stream << delimiters_type::values.delimiter;
0136 }
0137 }
0138 }
0139 };
0140
0141 print_container_helper(const T & container)
0142 : container_(container)
0143 { }
0144
0145 inline void operator()(ostream_type & stream) const
0146 {
0147 if (delimiters_type::values.prefix != NULL)
0148 stream << delimiters_type::values.prefix;
0149
0150 printer<T>::print_body(container_, stream);
0151
0152 if (delimiters_type::values.postfix != NULL)
0153 stream << delimiters_type::values.postfix;
0154 }
0155
0156 private:
0157 const T & container_;
0158 };
0159
0160
0161
0162 template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
0163 template <typename T1, typename T2>
0164 struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>>
0165 {
0166 using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
0167
0168 static void print_body(const std::pair<T1, T2> & c, ostream_type & stream)
0169 {
0170 stream << c.first;
0171 if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
0172 stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
0173 stream << c.second;
0174 }
0175 };
0176
0177
0178
0179 template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
0180 template <typename ...Args>
0181 struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>>
0182 {
0183 using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
0184 using element_type = std::tuple<Args...>;
0185
0186 template <std::size_t I> struct Int { };
0187
0188 static void print_body(const element_type & c, ostream_type & stream)
0189 {
0190 tuple_print(c, stream, Int<0>());
0191 }
0192
0193 static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>)
0194 {
0195 }
0196
0197 static void tuple_print(const element_type & c, ostream_type & stream,
0198 typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type)
0199 {
0200 stream << std::get<0>(c);
0201 tuple_print(c, stream, Int<1>());
0202 }
0203
0204 template <std::size_t N>
0205 static void tuple_print(const element_type & c, ostream_type & stream, Int<N>)
0206 {
0207 if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
0208 stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
0209
0210 stream << std::get<N>(c);
0211
0212 tuple_print(c, stream, Int<N + 1>());
0213 }
0214 };
0215
0216
0217
0218 template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
0219 inline std::basic_ostream<TChar, TCharTraits> & operator<<(
0220 std::basic_ostream<TChar, TCharTraits> & stream,
0221 const print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
0222 {
0223 helper(stream);
0224 return stream;
0225 }
0226
0227
0228
0229
0230 template <typename T>
0231 struct is_container : public std::integral_constant<bool,
0232 detail::has_const_iterator<T>::value &&
0233 detail::has_begin_end<T>::beg_value &&
0234 detail::has_begin_end<T>::end_value> { };
0235
0236 template <typename T, std::size_t N>
0237 struct is_container<T[N]> : std::true_type { };
0238
0239 template <std::size_t N>
0240 struct is_container<char[N]> : std::false_type { };
0241
0242 template <typename T>
0243 struct is_container<std::valarray<T>> : std::true_type { };
0244
0245 template <typename T1, typename T2>
0246 struct is_container<std::pair<T1, T2>> : std::true_type { };
0247
0248 template <typename ...Args>
0249 struct is_container<std::tuple<Args...>> : std::true_type { };
0250
0251
0252
0253
0254 template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
0255 template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
0256 template <typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
0257 template <typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
0258
0259
0260
0261
0262 template <typename T, typename TComp, typename TAllocator>
0263 struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
0264
0265 template <typename T, typename TComp, typename TAllocator>
0266 const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
0267
0268 template <typename T, typename TComp, typename TAllocator>
0269 struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
0270
0271 template <typename T, typename TComp, typename TAllocator>
0272 const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
0273
0274 template <typename T, typename TComp, typename TAllocator>
0275 struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
0276
0277 template <typename T, typename TComp, typename TAllocator>
0278 const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
0279
0280 template <typename T, typename TComp, typename TAllocator>
0281 struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
0282
0283 template <typename T, typename TComp, typename TAllocator>
0284 const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
0285
0286 template <typename T, typename THash, typename TEqual, typename TAllocator>
0287 struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
0288
0289 template <typename T, typename THash, typename TEqual, typename TAllocator>
0290 const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
0291
0292 template <typename T, typename THash, typename TEqual, typename TAllocator>
0293 struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
0294
0295 template <typename T, typename THash, typename TEqual, typename TAllocator>
0296 const delimiters_values<wchar_t> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
0297
0298 template <typename T, typename THash, typename TEqual, typename TAllocator>
0299 struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
0300
0301 template <typename T, typename THash, typename TEqual, typename TAllocator>
0302 const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
0303
0304 template <typename T, typename THash, typename TEqual, typename TAllocator>
0305 struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
0306
0307 template <typename T, typename THash, typename TEqual, typename TAllocator>
0308 const delimiters_values<wchar_t> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
0309
0310
0311
0312
0313 template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
0314 template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
0315 template <typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
0316 template <typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
0317
0318 template <typename ...Args> struct delimiters<std::tuple<Args...>, char> { static const delimiters_values<char> values; };
0319 template <typename ...Args> const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = { "(", ", ", ")" };
0320 template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; };
0321 template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" };
0322
0323
0324
0325
0326
0327
0328 struct custom_delims_base
0329 {
0330 virtual ~custom_delims_base() { }
0331 virtual std::ostream & stream(::std::ostream &) = 0;
0332 virtual std::wostream & stream(::std::wostream &) = 0;
0333 };
0334
0335 template <typename T, typename Delims>
0336 struct custom_delims_wrapper : custom_delims_base
0337 {
0338 custom_delims_wrapper(const T & t_) : t(t_) { }
0339
0340 std::ostream & stream(std::ostream & s)
0341 {
0342 return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
0343 }
0344
0345 std::wostream & stream(std::wostream & s)
0346 {
0347 return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
0348 }
0349
0350 private:
0351 const T & t;
0352 };
0353
0354 template <typename Delims>
0355 struct custom_delims
0356 {
0357 template <typename Container>
0358 custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
0359
0360 std::unique_ptr<custom_delims_base> base;
0361 };
0362
0363 template <typename TChar, typename TCharTraits, typename Delims>
0364 inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p)
0365 {
0366 return p.base->stream(s);
0367 }
0368
0369
0370
0371
0372
0373 template<typename T>
0374 struct array_wrapper_n
0375 {
0376 typedef const T * const_iterator;
0377 typedef T value_type;
0378
0379 array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
0380 inline const_iterator begin() const { return _array; }
0381 inline const_iterator end() const { return _array + _n; }
0382
0383 private:
0384 const T * const _array;
0385 size_t _n;
0386 };
0387
0388
0389
0390
0391
0392 template <typename T>
0393 struct bucket_print_wrapper
0394 {
0395 typedef typename T::const_local_iterator const_iterator;
0396 typedef typename T::size_type size_type;
0397
0398 const_iterator begin() const
0399 {
0400 return m_map.cbegin(n);
0401 }
0402
0403 const_iterator end() const
0404 {
0405 return m_map.cend(n);
0406 }
0407
0408 bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
0409
0410 private:
0411 const T & m_map;
0412 const size_type n;
0413 };
0414
0415 }
0416
0417
0418
0419
0420 template<typename T>
0421 inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
0422 {
0423 return pretty_print::array_wrapper_n<T>(a, n);
0424 }
0425
0426 template <typename T> pretty_print::bucket_print_wrapper<T>
0427 bucket_print(const T & m, typename T::size_type n)
0428 {
0429 return pretty_print::bucket_print_wrapper<T>(m, n);
0430 }
0431
0432
0433 }
0434
0435
0436
0437
0438
0439
0440 namespace std
0441 {
0442
0443
0444 template<typename T, typename TChar, typename TCharTraits>
0445 inline typename enable_if< ::Rivet::pretty_print::is_container<T>::value,
0446 basic_ostream<TChar, TCharTraits> &>::type
0447 operator<<(std::basic_ostream<TChar, TCharTraits> & stream, const T & container)
0448 {
0449 return stream << ::Rivet::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
0450 }
0451
0452 }
0453
0454
0455
0456 #endif