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