00001
00002
00003
00004
00005
00006
00007 #ifndef H_PRETTY_PRINT
00008 #define H_PRETTY_PRINT
00009
00010
00011 #include <ostream>
00012 #include <utility>
00013 #include <iterator>
00014 #include <set>
00015
00016 #ifndef NO_TR1
00017 # include <tr1/tuple>
00018 # include <tr1/unordered_set>
00019 #endif
00020
00021 namespace pretty_print
00022 {
00023
00024 template <bool, typename S, typename T> struct conditional { };
00025 template <typename S, typename T> struct conditional<true, S, T> { typedef S type; };
00026 template <typename S, typename T> struct conditional<false, S, T> { typedef T type; };
00027
00028 template <bool, typename T> struct enable_if { };
00029 template <typename T> struct enable_if<true, T> { typedef T type; };
00030
00031
00032
00033 template<typename T>
00034 struct has_const_iterator
00035 {
00036 private:
00037 typedef char yes;
00038 typedef struct { char array[2]; } no;
00039
00040 template<typename C> static yes test(typename C::const_iterator*);
00041 template<typename C> static no test(...);
00042 public:
00043 static const bool value = sizeof(test<T>(0)) == sizeof(yes);
00044 typedef T type;
00045 };
00046
00047
00048
00049 template <typename T>
00050 struct has_begin_end
00051 {
00052 struct Dummy { typedef void const_iterator; };
00053 typedef typename conditional<has_const_iterator<T>::value, T, Dummy>::type TType;
00054 typedef typename TType::const_iterator iter;
00055
00056 struct Fallback { iter begin() const; iter end() const; };
00057 struct Derived : TType, Fallback { };
00058
00059 template<typename C, C> struct ChT;
00060
00061 template<typename C> static char (&f(ChT<iter (Fallback::*)() const, &C::begin>*))[1];
00062 template<typename C> static char (&f(...))[2];
00063 template<typename C> static char (&g(ChT<iter (Fallback::*)() const, &C::end>*))[1];
00064 template<typename C> static char (&g(...))[2];
00065
00066 static bool const beg_value = sizeof(f<Derived>(0)) == 2;
00067 static bool const end_value = sizeof(g<Derived>(0)) == 2;
00068 };
00069
00070
00071
00072 template<typename T> struct is_container { static const bool value = has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value; };
00073
00074 template<typename T, std::size_t N> struct is_container<T[N]> { static const bool value = true; };
00075
00076 template<std::size_t N> struct is_container<char[N]> { static const bool value = false; };
00077
00078
00079
00080
00081 template<typename TChar>
00082 struct delimiters_values
00083 {
00084 typedef TChar char_type;
00085 const TChar * prefix;
00086 const TChar * delimiter;
00087 const TChar * postfix;
00088 };
00089
00090
00091
00092
00093 template<typename T, typename TChar>
00094 struct delimiters
00095 {
00096 typedef delimiters_values<TChar> type;
00097 static const type values;
00098 };
00099
00100
00101
00102
00103 template<typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
00104 template<typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
00105 template<typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
00106 template<typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
00107
00108
00109
00110
00111 template<typename T, typename TComp, typename TAllocator>
00112 struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
00113
00114 template<typename T, typename TComp, typename TAllocator>
00115 const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
00116
00117 template<typename T, typename TComp, typename TAllocator>
00118 struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00119
00120 template<typename T, typename TComp, typename TAllocator>
00121 const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00122
00123 template<typename T, typename TComp, typename TAllocator>
00124 struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
00125
00126 template<typename T, typename TComp, typename TAllocator>
00127 const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
00128
00129 template<typename T, typename TComp, typename TAllocator>
00130 struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00131
00132 template<typename T, typename TComp, typename TAllocator>
00133 const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00134
00135 #ifndef NO_TR1
00136 template<typename T, typename THash, typename TEqual, typename TAllocator>
00137 struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
00138
00139 template<typename T, typename THash, typename TEqual, typename TAllocator>
00140 const delimiters_values<char> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
00141
00142 template<typename T, typename THash, typename TEqual, typename TAllocator>
00143 struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00144
00145 template<typename T, typename THash, typename TEqual, typename TAllocator>
00146 const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00147
00148 template<typename T, typename THash, typename TEqual, typename TAllocator>
00149 struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
00150
00151 template<typename T, typename THash, typename TEqual, typename TAllocator>
00152 const delimiters_values<char> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
00153
00154 template<typename T, typename THash, typename TEqual, typename TAllocator>
00155 struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00156
00157 template<typename T, typename THash, typename TEqual, typename TAllocator>
00158 const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00159 #endif
00160
00161
00162
00163
00164 template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
00165 template<typename T1, typename T2> const delimiters_values<char> delimiters< ::std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
00166 template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
00167 template<typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
00168
00169
00170
00171
00172 template <typename T> struct get_iterator { typedef typename T::const_iterator iter; };
00173 template <typename T, std::size_t N> struct get_iterator<T[N]> { typedef const T * iter; };
00174
00175 template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type begin(const T & c) { return c.begin(); }
00176 template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type end(const T & c) { return c.end(); }
00177 template <typename T, size_t N> const T * begin(const T(&x)[N]) { return &x[0]; }
00178 template <typename T, size_t N> const T * end (const T(&x)[N]) { return &x[0] + N; }
00179
00180
00181
00182 template<typename T, typename TChar = char, typename TCharTraits = ::std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar> >
00183 struct print_container_helper
00184 {
00185 typedef TChar char_type;
00186 typedef TDelimiters delimiters_type;
00187 typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
00188 typedef typename get_iterator<T>::iter TIter;
00189
00190 print_container_helper(const T & container)
00191 : _container(container)
00192 {
00193 }
00194
00195 inline void operator()(ostream_type & stream) const
00196 {
00197 if (delimiters_type::values.prefix != NULL)
00198 stream << delimiters_type::values.prefix;
00199
00200 if (pretty_print::begin(_container) != pretty_print::end(_container))
00201 for (TIter it = pretty_print::begin(_container), it_end = pretty_print::end(_container); ; )
00202 {
00203 stream << *it;
00204
00205 if (++it == it_end) break;
00206
00207 if (delimiters_type::values.delimiter != NULL)
00208 stream << delimiters_type::values.delimiter;
00209 }
00210
00211 if (delimiters_type::values.postfix != NULL)
00212 stream << delimiters_type::values.postfix;
00213 }
00214
00215 private:
00216 const T & _container;
00217 };
00218
00219
00220
00221
00222
00223
00224 struct custom_delims_base
00225 {
00226 virtual ~custom_delims_base() { }
00227 virtual ::std::ostream & stream(::std::ostream &) = 0;
00228 virtual ::std::wostream & stream(::std::wostream &) = 0;
00229 };
00230
00231 template<typename T, typename Delims>
00232 struct custom_delims_wrapper : public custom_delims_base
00233 {
00234 custom_delims_wrapper(const T & t_) : t(t_) { }
00235
00236 ::std::ostream & stream(::std::ostream & s)
00237 {
00238 return s << ::pretty_print::print_container_helper<T, char, ::std::char_traits<char>, Delims>(t);
00239 }
00240 ::std::wostream & stream(::std::wostream & s)
00241 {
00242 return s << ::pretty_print::print_container_helper<T, wchar_t, ::std::char_traits<wchar_t>, Delims>(t);
00243 }
00244
00245 private:
00246 const T & t;
00247 };
00248
00249 template<typename Delims>
00250 struct custom_delims
00251 {
00252 template<typename Container> custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
00253 ~custom_delims() { delete base; }
00254 custom_delims_base * base;
00255 };
00256
00257 }
00258
00259 template<typename TChar, typename TCharTraits, typename Delims>
00260 inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const pretty_print::custom_delims<Delims> & p)
00261 {
00262 return p.base->stream(s);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 namespace std
00275 {
00276
00277
00278 template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
00279 inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream,
00280 const ::pretty_print::print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
00281 {
00282 helper(stream);
00283 return stream;
00284 }
00285
00286
00287
00288 template<typename T, typename TChar, typename TCharTraits>
00289 inline typename ::pretty_print::enable_if< ::pretty_print::is_container<T>::value, basic_ostream<TChar, TCharTraits>&>::type
00290 operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
00291 {
00292 return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
00293 }
00294
00295
00296 template<typename T1, typename T2, typename TChar, typename TCharTraits>
00297 inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const pair<T1, T2> & value)
00298 {
00299 if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix != NULL)
00300 stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix;
00301
00302 stream << value.first;
00303
00304 if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter != NULL)
00305 stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter;
00306
00307 stream << value.second;
00308
00309 if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix != NULL)
00310 stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix;
00311
00312 return stream;
00313 }
00314 }
00315
00316
00317 #ifndef NO_TR1
00318
00319
00320
00321 namespace pretty_print
00322 {
00323 struct tuple_dummy_t { };
00324
00325 typedef std::pair<tuple_dummy_t, tuple_dummy_t> tuple_dummy_pair;
00326
00327 template<typename Tuple, size_t N, typename TChar, typename TCharTraits>
00328 struct pretty_tuple_helper
00329 {
00330 static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
00331 {
00332 pretty_tuple_helper<Tuple, N - 1, TChar, TCharTraits>::print(stream, value);
00333
00334 if (delimiters<tuple_dummy_pair, TChar>::values.delimiter != NULL)
00335 stream << delimiters<tuple_dummy_pair, TChar>::values.delimiter;
00336
00337 stream << std::tr1::get<N - 1>(value);
00338 }
00339 };
00340
00341 template<typename Tuple, typename TChar, typename TCharTraits>
00342 struct pretty_tuple_helper<Tuple, 1, TChar, TCharTraits>
00343 {
00344 static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
00345 {
00346 stream << ::std::tr1::get<0>(value);
00347 }
00348 };
00349 }
00350
00351
00352
00353
00354
00355
00356
00357 #define TUPLE_PARAMS \
00358 typename T0, typename T1, typename T2, typename T3, typename T4, \
00359 typename T5, typename T6, typename T7, typename T8, typename T9
00360 #define TUPLE_ARGS T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
00361
00362
00363 namespace std
00364 {
00365 template<typename TChar, typename TCharTraits, TUPLE_PARAMS>
00366 inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const tr1::tuple<TUPLE_ARGS> & value)
00367 {
00368 if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix != NULL)
00369 stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix;
00370
00371 ::pretty_print::pretty_tuple_helper<const tr1::tuple<TUPLE_ARGS> &, tr1::tuple_size<tr1::tuple<TUPLE_ARGS> >::value, TChar, TCharTraits>::print(stream, value);
00372
00373 if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix != NULL)
00374 stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix;
00375
00376 return stream;
00377 }
00378 }
00379
00380 #endif // NO_TR1
00381
00382
00383
00384
00385 namespace pretty_print
00386 {
00387 template<typename T>
00388 struct array_wrapper_n
00389 {
00390 typedef const T * const_iterator;
00391 typedef T value_type;
00392
00393 array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
00394 inline const_iterator begin() const { return _array; }
00395 inline const_iterator end() const { return _array + _n; }
00396
00397 private:
00398 const T * const _array;
00399 size_t _n;
00400 };
00401 }
00402
00403 template<typename T>
00404 inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
00405 {
00406 return pretty_print::array_wrapper_n<T>(a, n);
00407 }
00408
00409
00410 #endif