Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:53

0001 //          Copyright Louis Delacroix 2010 - 2014.
0002 // Distributed under the Boost Software License, Version 1.0.
0003 //    (See accompanying file LICENSE_1_0.txt or copy at
0004 //          http://www.boost.org/LICENSE_1_0.txt)
0005 //
0006 // A pretty printing library for C++
0007 //
0008 // Usage:
0009 // Include this header, and operator<< will "just work".
0010 //
0011 // See: https://louisdx.github.io/cxx-prettyprint/
0012 
0013 #ifndef H_PRETTY_PRINT
0014 #define H_PRETTY_PRINT
0015 
0016 /// @cond PRETTYPRINT
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         // SFINAE type trait to detect whether T::const_iterator exists.
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     }  // namespace detail
0078 
0079 
0080     // Holds the delimiter values for a specific character type
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     // Defines the delimiter values for a specific container and character type
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     // Functor to print containers. You can use this directly if you want
0103     // to specificy a non-default delimiters type. The printing logic can
0104     // be customized by specializing the nested template.
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     // Specialization for pairs
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     // Specialization for tuples
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     // Prints a print_container_helper to the specified stream.
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     // Basic is_container template; specialize to derive from std::true_type for all desired container types
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     // Default delimiters
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     // Delimiters for (multi)set and unordered_(multi)set
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     // Delimiters for pair and tuple
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     // Type-erasing helper class for easy use of custom delimiters.
0325     // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
0326     // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
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     // A wrapper for a C-style array given as pointer-plus-size.
0371     // Usage: std::cout << pretty_print_array(arr, n) << std::'\n';
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     // A wrapper for hash-table based containers that offer local iterators to each bucket.
0390     // Usage: std::cout << bucket_print(m, 4) << std::'\n';  (Prints bucket 5 of container m.)
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 }   // namespace pretty_print
0416 
0417 
0418 // Global accessor functions for the convenience wrappers
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 } // namespace Rivet
0434 
0435 
0436 
0437 // Main magic entry point: An overload snuck into namespace std.
0438 // Can we do better?
0439 
0440 namespace std
0441 {
0442 
0443 // Prints a container to the stream using default delimiters
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 /// @endcond
0455 
0456 #endif  // H_PRETTY_PRINT