run clang-format

This commit is contained in:
Johannes Kapfhammer 2019-10-06 18:38:23 +02:00
parent 4d25fc25c4
commit 492a0f3c55
5 changed files with 517 additions and 454 deletions

View File

@ -23,400 +23,446 @@
namespace soi { namespace soi {
template<typename T, typename TChar, typename TCharTraits> template <typename T, typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> & std::basic_ostream<TChar, TCharTraits> &
print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x); print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x);
namespace detail namespace detail {
{
// SFINAE type trait to detect whether T::const_iterator exists. // SFINAE type trait to detect whether T::const_iterator exists.
struct sfinae_base struct sfinae_base {
{ using yes = char;
using yes = char; using no = yes[2];
using no = yes[2];
}; };
template <typename T> template <typename T> struct has_const_iterator : private sfinae_base {
struct has_const_iterator : private sfinae_base
{
private: private:
template <typename C> static yes & test(typename C::const_iterator*); template <typename C> static yes &test(typename C::const_iterator *);
template <typename C> static no & test(...); template <typename C> static no &test(...);
public:
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
using type = T;
};
template <typename T>
struct has_begin_end : private sfinae_base
{
private:
template <typename C>
static yes & f(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
typename C::const_iterator(C::*)() const>::value>::type *);
template <typename C> static no & f(...);
template <typename C>
static yes & g(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
typename C::const_iterator(C::*)() const>::value, void>::type*);
template <typename C> static no & g(...);
public: public:
static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes); static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes); using type = T;
}; };
} // namespace detail template <typename T> struct has_begin_end : private sfinae_base {
private:
template <typename C>
static yes &
f(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (C::*)()
const>(&C::begin)),
typename C::const_iterator (C::*)() const>::value>::type *);
template <typename C> static no &f(...);
template <typename C>
static yes &
g(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator (C::*)()
const>(&C::end)),
typename C::const_iterator (C::*)() const>::value,
void>::type *);
template <typename C> static no &g(...);
public:
static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
};
} // namespace detail
// Holds the delimiter values for a specific character type // Holds the delimiter values for a specific character type
template <typename TChar> template <typename TChar> struct delimiters_values {
struct delimiters_values using char_type = TChar;
{ const char_type *prefix;
using char_type = TChar; const char_type *delimiter;
const char_type * prefix; const char_type *postfix;
const char_type * delimiter;
const char_type * postfix;
}; };
// Defines the delimiter values for a specific container and character type // Defines the delimiter values for a specific container and character type
template <typename T, typename TChar> template <typename T, typename TChar> struct delimiters {
struct delimiters using type = delimiters_values<TChar>;
{ static const type values;
using type = delimiters_values<TChar>;
static const type values;
}; };
// Functor to pretty_print containers. You can use this directly if you want // Functor to pretty_print containers. You can use this directly if you want
// to specificy a non-default delimiters type. The pretty_printing logic can // to specificy a non-default delimiters type. The pretty_printing logic can
// be customized by specializing the nested template. // be customized by specializing the nested template.
template <typename T, template <typename T, typename TChar = char,
typename TChar = char,
typename TCharTraits = ::std::char_traits<TChar>, typename TCharTraits = ::std::char_traits<TChar>,
typename TDelimiters = delimiters<T, TChar>> typename TDelimiters = delimiters<T, TChar>>
struct pretty_print_container_helper struct pretty_print_container_helper {
{ using delimiters_type = TDelimiters;
using delimiters_type = TDelimiters; using ostream_type = std::basic_ostream<TChar, TCharTraits>;
using ostream_type = std::basic_ostream<TChar, TCharTraits>;
template <typename U> template <typename U> struct pretty_printer {
struct pretty_printer static void pretty_print_body(const U &c, ostream_type &stream) {
{ using std::begin;
static void pretty_print_body(const U & c, ostream_type & stream) using std::end;
{
using std::begin;
using std::end;
auto it = begin(c); auto it = begin(c);
const auto the_end = end(c); const auto the_end = end(c);
if (it != the_end) if (it != the_end) {
{ for (;;) {
for ( ; ; ) ::soi::print(stream, *it);
{
::soi::print(stream, *it);
if (++it == the_end) break; if (++it == the_end)
break;
if (delimiters_type::values.delimiter != NULL) if (delimiters_type::values.delimiter != NULL)
::soi::print(stream, delimiters_type::values.delimiter); ::soi::print(stream, delimiters_type::values.delimiter);
}
}
} }
}; }
pretty_print_container_helper(const T & container)
: container_(container)
{ }
inline void operator()(ostream_type & stream) const
{
if (delimiters_type::values.prefix != NULL)
::soi::print(stream, delimiters_type::values.prefix);
pretty_printer<T>::pretty_print_body(container_, stream);
if (delimiters_type::values.postfix != NULL)
::soi::print(stream, delimiters_type::values.postfix);
} }
};
pretty_print_container_helper(const T &container) : container_(container) {}
inline void operator()(ostream_type &stream) const {
if (delimiters_type::values.prefix != NULL)
::soi::print(stream, delimiters_type::values.prefix);
pretty_printer<T>::pretty_print_body(container_, stream);
if (delimiters_type::values.postfix != NULL)
::soi::print(stream, delimiters_type::values.postfix);
}
private: private:
const T & container_; const T &container_;
}; };
// Specialization for pairs // Specialization for pairs
template <typename T, typename TChar, typename TCharTraits, typename TDelimiters> template <typename T, typename TChar, typename TCharTraits,
typename TDelimiters>
template <typename T1, typename T2> template <typename T1, typename T2>
struct pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::pair<T1, T2>> struct pretty_print_container_helper<
{ T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::pair<T1, T2>> {
using ostream_type = typename pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type; using ostream_type =
typename pretty_print_container_helper<T, TChar, TCharTraits,
TDelimiters>::ostream_type;
static void pretty_print_body(const std::pair<T1, T2> & c, ostream_type & stream) static void pretty_print_body(const std::pair<T1, T2> &c,
{ ostream_type &stream) {
::soi::print(stream, c.first); ::soi::print(stream, c.first);
if (pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL) if (pretty_print_container_helper<T, TChar, TCharTraits,
::soi::print(stream, pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter); TDelimiters>::delimiters_type::values
::soi::print(stream, c.second); .delimiter != NULL)
} ::soi::print(
stream,
pretty_print_container_helper<T, TChar, TCharTraits,
TDelimiters>::delimiters_type::values
.delimiter);
::soi::print(stream, c.second);
}
}; };
// Specialization for tuples // Specialization for tuples
template <typename T, typename TChar, typename TCharTraits, typename TDelimiters> template <typename T, typename TChar, typename TCharTraits,
template <typename ...Args> typename TDelimiters>
struct pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::tuple<Args...>> template <typename... Args>
{ struct pretty_print_container_helper<
using ostream_type = typename pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type; T, TChar, TCharTraits, TDelimiters>::pretty_printer<std::tuple<Args...>> {
using element_type = std::tuple<Args...>; using ostream_type =
typename pretty_print_container_helper<T, TChar, TCharTraits,
TDelimiters>::ostream_type;
using element_type = std::tuple<Args...>;
template <std::size_t I> struct Int { }; template <std::size_t I> struct Int {};
static void pretty_print_body(const element_type & c, ostream_type & stream) static void pretty_print_body(const element_type &c, ostream_type &stream) {
{ tuple_pretty_print(c, stream, Int<0>());
tuple_pretty_print(c, stream, Int<0>()); }
}
static void tuple_pretty_print(const element_type &, ostream_type &, Int<sizeof...(Args)>) static void tuple_pretty_print(const element_type &, ostream_type &,
{ Int<sizeof...(Args)>) {}
}
static void tuple_pretty_print(const element_type & c, ostream_type & stream, static void
typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type) tuple_pretty_print(const element_type &c, ostream_type &stream,
{ typename std::conditional<sizeof...(Args) != 0, Int<0>,
::soi::print(stream, std::get<0>(c)); std::nullptr_t>::type) {
tuple_pretty_print(c, stream, Int<1>()); ::soi::print(stream, std::get<0>(c));
} tuple_pretty_print(c, stream, Int<1>());
}
template <std::size_t N> template <std::size_t N>
static void tuple_pretty_print(const element_type & c, ostream_type & stream, Int<N>) static void tuple_pretty_print(const element_type &c, ostream_type &stream,
{ Int<N>) {
if (pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL) if (pretty_print_container_helper<T, TChar, TCharTraits,
::soi::print(stream, pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter); TDelimiters>::delimiters_type::values
.delimiter != NULL)
::soi::print(
stream,
pretty_print_container_helper<T, TChar, TCharTraits,
TDelimiters>::delimiters_type::values
.delimiter);
::soi::print(stream, std::get<N>(c)); ::soi::print(stream, std::get<N>(c));
tuple_pretty_print(c, stream, Int<N + 1>()); tuple_pretty_print(c, stream, Int<N + 1>());
} }
}; };
// Pretty_Prints a pretty_print_container_helper to the specified stream. // Pretty_Prints a pretty_print_container_helper to the specified stream.
template<typename T, typename TChar, typename TCharTraits, typename TDelimiters> template <typename T, typename TChar, typename TCharTraits,
inline std::basic_ostream<TChar, TCharTraits> & pretty_print( typename TDelimiters>
std::basic_ostream<TChar, TCharTraits> & stream, inline std::basic_ostream<TChar, TCharTraits> &
const pretty_print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper) pretty_print(std::basic_ostream<TChar, TCharTraits> &stream,
{ const pretty_print_container_helper<T, TChar, TCharTraits,
helper(stream); TDelimiters> &helper) {
return stream; helper(stream);
return stream;
} }
// Basic is_container template; specialize to derive from std::true_type for all
// Basic is_container template; specialize to derive from std::true_type for all desired container types // desired container types
template <typename T> template <typename T>
struct is_container : public std::integral_constant<bool, struct is_container
detail::has_const_iterator<T>::value && : public std::integral_constant<bool,
detail::has_begin_end<T>::beg_value && detail::has_const_iterator<T>::value &&
detail::has_begin_end<T>::end_value> { }; detail::has_begin_end<T>::beg_value &&
detail::has_begin_end<T>::end_value> {};
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct is_container<T[N]> : std::true_type { }; struct is_container<T[N]> : std::true_type {};
template <std::size_t N> template <std::size_t N> struct is_container<char[N]> : std::false_type {};
struct is_container<char[N]> : std::false_type { };
template <typename T> template <typename T> struct is_container<std::valarray<T>> : std::true_type {};
struct is_container<std::valarray<T>> : std::true_type { };
template <typename T1, typename T2> template <typename T1, typename T2>
struct is_container<std::pair<T1, T2>> : std::true_type { }; struct is_container<std::pair<T1, T2>> : std::true_type {};
template <typename ...Args>
struct is_container<std::tuple<Args...>> : std::true_type { };
template <typename... Args>
struct is_container<std::tuple<Args...>> : std::true_type {};
// Default delimiters // Default delimiters
template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; }; template <typename T> struct delimiters<T, char> {
template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" }; static const delimiters_values<char> values;
template <typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; }; };
template <typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" }; template <typename T>
const delimiters_values<char> delimiters<T, char>::values = {"[", ", ", "]"};
template <typename T> struct delimiters<T, wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename T>
const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = {L"[", L", ",
L"]"};
// Delimiters for (multi)set and unordered_(multi)set // Delimiters for (multi)set and unordered_(multi)set
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; }; struct delimiters<::std::set<T, TComp, TAllocator>, char> {
static const delimiters_values<char> values;
};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" }; const delimiters_values<char>
delimiters<::std::set<T, TComp, TAllocator>, char>::values = {"{", ", ",
"}"};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; struct delimiters<::std::set<T, TComp, TAllocator>, wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; const delimiters_values<wchar_t>
delimiters<::std::set<T, TComp, TAllocator>, wchar_t>::values = {
L"{", L", ", L"}"};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; }; struct delimiters<::std::multiset<T, TComp, TAllocator>, char> {
static const delimiters_values<char> values;
};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" }; const delimiters_values<char> delimiters<::std::multiset<T, TComp, TAllocator>,
char>::values = {"{", ", ", "}"};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; struct delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename T, typename TComp, typename TAllocator> template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; const delimiters_values<wchar_t>
delimiters<::std::multiset<T, TComp, TAllocator>, wchar_t>::values = {
L"{", L", ", L"}"};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; }; struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, char> {
static const delimiters_values<char> values;
};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" }; const delimiters_values<char> delimiters<
::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = {
"{", ", ", "}"};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; struct delimiters<::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; const delimiters_values<wchar_t> delimiters<
::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = {
L"{", L", ", L"}"};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; }; struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>,
char> {
static const delimiters_values<char> values;
};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" }; const delimiters_values<char> delimiters<
::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = {
"{", ", ", "}"};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; }; struct delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>,
wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename T, typename THash, typename TEqual, typename TAllocator> template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<wchar_t> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" }; const delimiters_values<wchar_t>
delimiters<::std::unordered_multiset<T, THash, TEqual, TAllocator>,
wchar_t>::values = {L"{", L", ", L"}"};
// Delimiters for pair and tuple // Delimiters for pair and tuple
template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; }; template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> {
template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" }; static const delimiters_values<char> values;
template <typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; }; };
template <typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" }; template <typename T1, typename T2>
const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = {
template <typename ...Args> struct delimiters<std::tuple<Args...>, char> { static const delimiters_values<char> values; }; "(", ", ", ")"};
template <typename ...Args> const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = { "(", ", ", ")" }; template <typename T1, typename T2>
template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; }; struct delimiters<::std::pair<T1, T2>, wchar_t> {
template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" }; static const delimiters_values<wchar_t> values;
};
template <typename T1, typename T2>
const delimiters_values<wchar_t>
delimiters<::std::pair<T1, T2>, wchar_t>::values = {L"(", L", ", L")"};
template <typename... Args> struct delimiters<std::tuple<Args...>, char> {
static const delimiters_values<char> values;
};
template <typename... Args>
const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = {
"(", ", ", ")"};
template <typename... Args> struct delimiters<::std::tuple<Args...>, wchar_t> {
static const delimiters_values<wchar_t> values;
};
template <typename... Args>
const delimiters_values<wchar_t>
delimiters<::std::tuple<Args...>, wchar_t>::values = {L"(", L", ", L")"};
// Type-erasing helper class for easy use of custom delimiters. // Type-erasing helper class for easy use of custom delimiters.
// Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar. // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t,
// Usage: "cout << pretty_pretty_print::custom_delims<MyDelims>(x)". // and MyDelims needs to be defined for TChar. Usage: "cout <<
// pretty_pretty_print::custom_delims<MyDelims>(x)".
struct custom_delims_base struct custom_delims_base {
{ virtual ~custom_delims_base() {}
virtual ~custom_delims_base() { } virtual std::ostream &stream(::std::ostream &) = 0;
virtual std::ostream & stream(::std::ostream &) = 0; virtual std::wostream &stream(::std::wostream &) = 0;
virtual std::wostream & stream(::std::wostream &) = 0;
}; };
template <typename T, typename Delims> template <typename T, typename Delims>
struct custom_delims_wrapper : custom_delims_base struct custom_delims_wrapper : custom_delims_base {
{ custom_delims_wrapper(const T &t_) : t(t_) {}
custom_delims_wrapper(const T & t_) : t(t_) { }
std::ostream & stream(std::ostream & s) std::ostream &stream(std::ostream &s) {
{ return pretty_print(
return pretty_print(s, pretty_print_container_helper<T, char, std::char_traits<char>, Delims>(t)); s,
} pretty_print_container_helper<T, char, std::char_traits<char>, Delims>(
t));
}
std::wostream & stream(std::wostream & s) std::wostream &stream(std::wostream &s) {
{ return pretty_print(
return pretty_print(s, pretty_print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t)); s, pretty_print_container_helper<T, wchar_t, std::char_traits<wchar_t>,
} Delims>(t));
}
private: private:
const T & t; const T &t;
}; };
template <typename Delims> template <typename Delims> struct custom_delims {
struct custom_delims template <typename Container>
{ custom_delims(const Container &c)
template <typename Container> : base(new custom_delims_wrapper<Container, Delims>(c)) {}
custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
std::unique_ptr<custom_delims_base> base; std::unique_ptr<custom_delims_base> base;
}; };
template <typename TChar, typename TCharTraits, typename Delims> template <typename TChar, typename TCharTraits, typename Delims>
inline std::basic_ostream<TChar, TCharTraits> & pretty_print(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p) inline std::basic_ostream<TChar, TCharTraits> &
{ pretty_print(std::basic_ostream<TChar, TCharTraits> &s,
return p.base->stream(s); const custom_delims<Delims> &p) {
return p.base->stream(s);
} }
// A wrapper for a C-style array given as pointer-plus-size. // A wrapper for a C-style array given as pointer-plus-size.
// Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl; // Usage: std::cout << pretty_pretty_print_array(arr, n) << std::endl;
template<typename T> template <typename T> struct array_wrapper_n {
struct array_wrapper_n typedef const T *const_iterator;
{ typedef T value_type;
typedef const T * const_iterator;
typedef T value_type;
array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { } array_wrapper_n(const T *const a, size_t n) : _array(a), _n(n) {}
inline const_iterator begin() const { return _array; } inline const_iterator begin() const { return _array; }
inline const_iterator end() const { return _array + _n; } inline const_iterator end() const { return _array + _n; }
private: private:
const T * const _array; const T *const _array;
size_t _n; size_t _n;
}; };
// A wrapper for hash-table based containers that offer local iterators to each
// bucket. Usage: std::cout << bucket_pretty_print(m, 4) << std::endl;
// (Pretty_Prints bucket 5 of container m.)
// A wrapper for hash-table based containers that offer local iterators to each bucket. template <typename T> struct bucket_pretty_print_wrapper {
// Usage: std::cout << bucket_pretty_print(m, 4) << std::endl; (Pretty_Prints bucket 5 of container m.) typedef typename T::const_local_iterator const_iterator;
typedef typename T::size_type size_type;
template <typename T> const_iterator begin() const { return m_map.cbegin(n); }
struct bucket_pretty_print_wrapper
{
typedef typename T::const_local_iterator const_iterator;
typedef typename T::size_type size_type;
const_iterator begin() const const_iterator end() const { return m_map.cend(n); }
{
return m_map.cbegin(n);
}
const_iterator end() const bucket_pretty_print_wrapper(const T &m, size_type bucket)
{ : m_map(m), n(bucket) {}
return m_map.cend(n);
}
bucket_pretty_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
private: private:
const T & m_map; const T &m_map;
const size_type n; const size_type n;
}; };
} // namespace soi } // namespace soi
/* /*
// Global accessor functions for the convenience wrappers // Global accessor functions for the convenience wrappers
template<typename T> template<typename T>
inline pretty_pretty_print::array_wrapper_n<T> pretty_pretty_print_array(const T * const a, size_t n) inline pretty_pretty_print::array_wrapper_n<T> pretty_pretty_print_array(const T
* const a, size_t n)
{ {
return pretty_pretty_print::array_wrapper_n<T>(a, n); return pretty_pretty_print::array_wrapper_n<T>(a, n);
} }
@ -433,18 +479,18 @@ return pretty_pretty_print::bucket_pretty_print_wrapper<T>(m, n);
*/ */
namespace soi namespace soi {
{
// Pretty_Prints a container to the stream using default delimiters // Pretty_Prints a container to the stream using default delimiters
template<typename T, typename TChar, typename TCharTraits> template <typename T, typename TChar, typename TCharTraits>
inline typename std::enable_if< ::soi::is_container<T>::value, inline typename std::enable_if<::soi::is_container<T>::value,
std::basic_ostream<TChar, TCharTraits> &>::type std::basic_ostream<TChar, TCharTraits> &>::type
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T & container) pretty_print(std::basic_ostream<TChar, TCharTraits> &stream,
{ const T &container) {
return ::soi::print(stream, ::soi::pretty_print_container_helper<T, TChar, TCharTraits>(container)); return ::soi::print(
} stream,
::soi::pretty_print_container_helper<T, TChar, TCharTraits>(container));
} }
} // namespace soi
#endif // SOI_PRETTY_PRETTY_PRINT
#endif // SOI_PRETTY_PRETTY_PRINT

View File

@ -11,11 +11,11 @@
#define SOI_DBG #define SOI_DBG
#include <cstddef> #include <cstddef>
#include <stdexcept>
#include <cstring> #include <cstring>
#include <ostream>
#include <iostream> #include <iostream>
#include <ostream>
#include <sstream> #include <sstream>
#include <stdexcept>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h> #include <unistd.h>
@ -31,113 +31,99 @@ namespace detail {
// detecting the type name: https://stackoverflow.com/a/20170989 // detecting the type name: https://stackoverflow.com/a/20170989
#ifndef _MSC_VER #ifndef _MSC_VER
# if __cplusplus < 201103 #if __cplusplus < 201103
# define CONSTEXPR11_TN #define CONSTEXPR11_TN
# define CONSTEXPR14_TN #define CONSTEXPR14_TN
# define NOEXCEPT_TN #define NOEXCEPT_TN
# elif __cplusplus < 201402 #elif __cplusplus < 201402
# define CONSTEXPR11_TN constexpr #define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN #define CONSTEXPR14_TN
# define NOEXCEPT_TN noexcept #define NOEXCEPT_TN noexcept
# else #else
# define CONSTEXPR11_TN constexpr #define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN constexpr #define CONSTEXPR14_TN constexpr
# define NOEXCEPT_TN noexcept #define NOEXCEPT_TN noexcept
# endif #endif
#else // _MSC_VER #else // _MSC_VER
# if _MSC_VER < 1900 #if _MSC_VER < 1900
# define CONSTEXPR11_TN #define CONSTEXPR11_TN
# define CONSTEXPR14_TN #define CONSTEXPR14_TN
# define NOEXCEPT_TN #define NOEXCEPT_TN
# elif _MSC_VER < 2000 #elif _MSC_VER < 2000
# define CONSTEXPR11_TN constexpr #define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN #define CONSTEXPR14_TN
# define NOEXCEPT_TN noexcept #define NOEXCEPT_TN noexcept
# else #else
# define CONSTEXPR11_TN constexpr #define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN constexpr #define CONSTEXPR14_TN constexpr
# define NOEXCEPT_TN noexcept #define NOEXCEPT_TN noexcept
# endif #endif
#endif // _MSC_VER #endif // _MSC_VER
class static_string { class static_string {
const char* const p_; const char *const p_;
const std::size_t sz_; const std::size_t sz_;
public: public:
typedef const char* const_iterator; typedef const char *const_iterator;
template <std::size_t N> template <std::size_t N>
CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN : p_(a),
: p_(a) sz_(N - 1) {}
, sz_(N-1)
{}
CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN CONSTEXPR11_TN static_string(const char *p, std::size_t N) NOEXCEPT_TN
: p_(p) : p_(p),
, sz_(N) sz_(N) {}
{}
CONSTEXPR11_TN const char* data() const NOEXCEPT_TN {return p_;} CONSTEXPR11_TN const char *data() const NOEXCEPT_TN { return p_; }
CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN {return sz_;} CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN { return sz_; }
CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN {return p_;} CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; }
CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN {return p_ + sz_;} CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN { return p_ + sz_; }
CONSTEXPR11_TN char operator[](std::size_t n) const CONSTEXPR11_TN char operator[](std::size_t n) const {
{ return n < sz_ ? p_[n] : throw std::out_of_range("static_string");
return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); }
}
}; };
inline inline std::ostream &operator<<(std::ostream &os, static_string const &s) {
std::ostream& return os.write(s.data(), s.size());
operator<<(std::ostream& os, static_string const& s)
{
return os.write(s.data(), s.size());
} }
template <class T> template <class T> CONSTEXPR14_TN static_string type_name() {
CONSTEXPR14_TN const int k = sizeof("constexpr soi::detail:: T") / sizeof(char);
static_string
type_name()
{
const int k = sizeof("constexpr soi::detail:: T")/sizeof(char);
#ifdef __clang__ #ifdef __clang__
static_string p = __PRETTY_FUNCTION__; static_string p = __PRETTY_FUNCTION__;
return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); return static_string(p.data() + 31 + k, p.size() - 31 - k - 1);
#elif defined(__GNUC__) #elif defined(__GNUC__)
static_string p = __PRETTY_FUNCTION__; static_string p = __PRETTY_FUNCTION__;
# if __cplusplus < 201402 #if __cplusplus < 201402
return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); return static_string(p.data() + 36 + k, p.size() - 36 - k - 1);
# else #else
return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); return static_string(p.data() + 46 + k, p.size() - 46 - k - 1);
# endif #endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
static_string p = __FUNCSIG__; static_string p = __FUNCSIG__;
return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); return static_string(p.data() + 38 + k, p.size() - 38 - k - 7);
#endif #endif
} }
constexpr bool is_prefix_of(char const *suffix, char const *s) { constexpr bool is_prefix_of(char const *suffix, char const *s) {
return suffix[0]=='\0' || (suffix[0] == s[0] && is_prefix_of(suffix + 1, s + 1)); return suffix[0] == '\0' ||
(suffix[0] == s[0] && is_prefix_of(suffix + 1, s + 1));
} }
static char const* const type_string = "string"; static char const *const type_string = "string";
template <class T> template <class T> CONSTEXPR14_TN static_string sanitized_type_name() {
CONSTEXPR14_TN
static_string
sanitized_type_name() {
CONSTEXPR14_TN static_string t = type_name<T>(); CONSTEXPR14_TN static_string t = type_name<T>();
CONSTEXPR14_TN std::size_t offset = CONSTEXPR14_TN std::size_t offset =
is_prefix_of("std::__debug::", t.data()) ? sizeof("std::__debug::")-1 : is_prefix_of("std::__debug::", t.data())
is_prefix_of("std::", t.data()) ? sizeof("std::")-1 : ? sizeof("std::__debug::") - 1
0; : is_prefix_of("std::", t.data()) ? sizeof("std::") - 1 : 0;
return return is_prefix_of("std::__cxx11::basic_string<char>", t.data())
is_prefix_of("std::__cxx11::basic_string<char>", t.data()) ? ? static_string(type_string, sizeof(type_string) - 2)
static_string(type_string, sizeof(type_string)-2) : : static_string(t.data() + offset, t.size() - offset);
static_string(t.data()+offset, t.size()-offset);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -152,7 +138,7 @@ bool tty_supports_colors() {
} }
int has_environment_color_overwrite() { int has_environment_color_overwrite() {
if (const char* color_enabled = std::getenv("SOI_COLOR")) { if (const char *color_enabled = std::getenv("SOI_COLOR")) {
if (!std::strcmp(color_enabled, "1")) if (!std::strcmp(color_enabled, "1"))
return 1; return 1;
if (!std::strcmp(color_enabled, "0")) if (!std::strcmp(color_enabled, "0"))
@ -172,12 +158,12 @@ bool are_colors_enabled() {
// init and static variables // init and static variables
static bool colors_enabled = false; static bool colors_enabled = false;
static const char* ANSI_DEBUG = ""; static const char *ANSI_DEBUG = "";
static const char* ANSI_EXPRESSION = ""; static const char *ANSI_EXPRESSION = "";
static const char* ANSI_VALUE = ""; static const char *ANSI_VALUE = "";
static const char* ANSI_TYPE = ""; static const char *ANSI_TYPE = "";
static const char* ANSI_MESSAGE = ""; static const char *ANSI_MESSAGE = "";
static const char* ANSI_RESET = ""; static const char *ANSI_RESET = "";
void dbg_init(bool with_colors) { void dbg_init(bool with_colors) {
if (with_colors) { if (with_colors) {
@ -199,70 +185,51 @@ void dbg_init(bool with_colors) {
} }
} }
void dbg_init() { void dbg_init() { dbg_init(are_colors_enabled()); }
dbg_init(are_colors_enabled());
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// printer // printer
template <typename T> template <typename T>
T&& dbg_print(T&& value, T &&dbg_print(T &&value, static_string const &type, char const *file, int line,
static_string const& type, char const *function_name, char const *expression) {
char const* file, const T &ref = value;
int line, std::stringstream
char const* function_name, value_buffer; // avoid nesting of dbg macros within print functinos
char const* expression) {
const T& ref = value;
std::stringstream value_buffer; // avoid nesting of dbg macros within print functinos
soi::print(value_buffer, ref); soi::print(value_buffer, ref);
std::cerr << ANSI_DEBUG std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name
<< "[" << file << ":" << line << ")] " << ANSI_RESET << ANSI_EXPRESSION << expression
<< " (" << function_name << ")] " << ANSI_RESET << ANSI_RESET << " = " << ANSI_VALUE << value_buffer.rdbuf()
<< ANSI_EXPRESSION << expression << ANSI_RESET << ANSI_RESET << " (" << ANSI_TYPE << type << ANSI_RESET << ")"
<< " = "
<< ANSI_VALUE << value_buffer.rdbuf() << ANSI_RESET
<< " (" << ANSI_TYPE << type << ANSI_RESET << ")"
<< '\n'; << '\n';
return std::forward<T>(value); return std::forward<T>(value);
} }
template<unsigned int N> template <unsigned int N>
auto dbg_print(const char (&msg)[N], auto dbg_print(const char (&msg)[N], static_string const &, char const *file,
static_string const&, int line, char const *function_name, char const *expression)
char const* file, -> decltype(msg) {
int line, std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name
char const* function_name, << ")] " << ANSI_RESET << ANSI_MESSAGE << msg << ANSI_RESET << '\n';
char const* expression) -> decltype(msg) {
std::cerr << ANSI_DEBUG
<< "[" << file << ":" << line
<< " (" << function_name << ")] " << ANSI_RESET
<< ANSI_MESSAGE << msg << ANSI_RESET
<< '\n';
return msg; return msg;
} }
template <typename T> template <typename T> T &&identity(T &&t) { return std::forward<T>(t); }
T&& identity(T&& t) {
return std::forward<T>(t);
}
} // end namespace detail } // end namespace detail
} // end namespace dbg_macro } // namespace soi
#ifdef SOI_RELEASE #ifdef SOI_RELEASE
#define dbg(...) dbg_macro::identity(__VA_ARGS__) #define dbg(...) dbg_macro::identity(__VA_ARGS__)
#else #else
#define dbg(...) \ #define dbg(...) \
soi::detail::dbg_print((__VA_ARGS__), \ soi::detail::dbg_print( \
soi::detail::sanitized_type_name<decltype(__VA_ARGS__)>(), \ (__VA_ARGS__), \
__FILE__, \ soi::detail::sanitized_type_name<decltype(__VA_ARGS__)>(), __FILE__, \
__LINE__, \ __LINE__, __func__, #__VA_ARGS__)
__func__, \
#__VA_ARGS__)
#endif #endif
#endif // SOI_DBG #endif // SOI_DBG

View File

@ -1,24 +1,32 @@
#pragma GCC diagnostic error "-Wdeprecated-declarations" #pragma GCC diagnostic error "-Wdeprecated-declarations"
struct endl_is_evil_t {} endl_is_evil; struct endl_is_evil_t {
[[deprecated("endl is evil. Use '\\n' to print a newline.")]] std::ostream & operator<<(std::ostream &os, endl_is_evil_t); } endl_is_evil;
[[deprecated("endl is evil. Use '\\n' to print a newline.")]] std::ostream &
operator<<(std::ostream &os, endl_is_evil_t);
#define endl endl_is_evil #define endl endl_is_evil
#define printf printf_is_evil #define printf printf_is_evil
#define fprintf fprintf_is_evil #define fprintf fprintf_is_evil
#define sprintf sprintf_is_evil #define sprintf sprintf_is_evil
#define snprintf snprintf_is_evil #define snprintf snprintf_is_evil
[[deprecated("printf is evil. Use cout.")]] int printf(const char *format, ...); [[deprecated("printf is evil. Use cout.")]] int printf(const char *format,
[[deprecated("printf is evil. Use cout.")]] int fprintf(std::FILE *stream, const char *format, ...); ...);
[[deprecated("printf is evil. Use cout.")]] int sprintf(char *buffer, const char *format, ...); [[deprecated("printf is evil. Use cout.")]] int
[[deprecated("printf is evil. Use cout.")]] int snprintf(char *buffer, std::size_t buf_size, const char *format, ...); fprintf(std::FILE *stream, const char *format, ...);
[[deprecated("printf is evil. Use cout.")]] int
sprintf(char *buffer, const char *format, ...);
[[deprecated("printf is evil. Use cout.")]] int
snprintf(char *buffer, std::size_t buf_size, const char *format, ...);
#define scanf scanf_is_evil #define scanf scanf_is_evil
#define fscanf fscanf_is_evil #define fscanf fscanf_is_evil
#define sscanf sscanf_is_evil #define sscanf sscanf_is_evil
[[deprecated("scanf is evil. Use cin.")]] int scanf(const char *format, ...); [[deprecated("scanf is evil. Use cin.")]] int scanf(const char *format, ...);
[[deprecated("scanf is evil. Use cin.")]] int fscanf(std::FILE *stream, const char *format, ...); [[deprecated("scanf is evil. Use cin.")]] int fscanf(std::FILE *stream,
[[deprecated("scanf is evil. Use cin.")]] int sscanf(const char *buffer, const char *format, ...); const char *format, ...);
[[deprecated("scanf is evil. Use cin.")]] int sscanf(const char *buffer,
const char *format, ...);
#define puts puts_is_evil #define puts puts_is_evil
#define fputs fputs_is_evil #define fputs fputs_is_evil
@ -35,28 +43,45 @@ struct endl_is_evil_t {} endl_is_evil;
#define fread fread_is_evil #define fread fread_is_evil
#define fwrite fwrite_is_evil #define fwrite fwrite_is_evil
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int puts(const char *str); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int puts(const char *str);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int fputs(const char *str, FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int fputs(const char *str,
[[deprecated("<cstdio> is evil. Use cin/cout.")]] char *fgets(char *str, int count, FILE *stream); FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *freopen(const char *filename, const char *mode, std::FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] char *
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *fopen(const char *filename, const char *mode); fgets(char *str, int count, FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int fclose(std::FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int fflush(std::FILE *stream); freopen(const char *filename, const char *mode, std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::FILE *
fopen(const char *filename, const char *mode);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int
fclose(std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int
fflush(std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int getchar(); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int getchar();
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int fgetc(std::FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int fgetc(std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int getc(std::FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int getc(std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] void setbuf(std::FILE *stream, char *buffer); [[deprecated("<cstdio> is evil. Use cin/cout.")]] void
[[deprecated("<cstdio> is evil. Use cin/cout.")]] int setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size); setbuf(std::FILE *stream, char *buffer);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::size_t fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream); [[deprecated("<cstdio> is evil. Use cin/cout.")]] int
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::size_t fwrite(const void *buffer, std::size_t size, std::size_t count, std::FILE *stream); setvbuf(std::FILE *stream, char *buffer, int mode, std::size_t size);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::size_t
fread(void *buffer, std::size_t size, std::size_t count, std::FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] std::size_t
fwrite(const void *buffer, std::size_t size, std::size_t count,
std::FILE *stream);
#define malloc malloc_is_evil #define malloc malloc_is_evil
#define calloc calloc_is_evil #define calloc calloc_is_evil
#define realloc realloc_is_evil #define realloc realloc_is_evil
#define free free_is_evil #define free free_is_evil
[[deprecated("malloc/free is evil. Use a vector.")]] void *malloc(std::size_t size); [[deprecated("malloc/free is evil. Use a vector.")]] void *
[[deprecated("malloc/free is evil. Use a vector.")]] void *calloc(std::size_t num, std::size_t size); malloc(std::size_t size);
[[deprecated("malloc/free is evil. Use a vector.")]] void *realloc(void *ptr, std::size_t new_size); [[deprecated("malloc/free is evil. Use a vector.")]] void *
[[deprecated("malloc/free is evil. Use a vector.")]] void *free(void *ptr, std::size_t new_size); calloc(std::size_t num, std::size_t size);
[[deprecated("malloc/free is evil. Use a vector.")]] void *
realloc(void *ptr, std::size_t new_size);
[[deprecated("malloc/free is evil. Use a vector.")]] void *
free(void *ptr, std::size_t new_size);
[[deprecated("new is evil. Use a vector.")]] void *operator new(std::size_t sz); [[deprecated("new is evil. Use a vector.")]] void *
[[deprecated("delete is evil. Use a vector.")]] void operator delete(void *ptr) noexcept; operator new(std::size_t sz);
[[deprecated("delete is evil. Use a vector.")]] void
operator delete(void *ptr) noexcept;

View File

@ -13,63 +13,88 @@
namespace soi { namespace soi {
template<typename TChar, typename TCharTraits> template <typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> & std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const bool& x) { pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, const bool &x) {
return stream << (x ? "true" : "false"); return stream << (x ? "true" : "false");
} }
namespace detail { namespace detail {
template<typename TChar, typename TCharTraits> template <typename TChar, typename TCharTraits>
void escape_char(std::basic_ostream<TChar, TCharTraits> & stream, char c) { void escape_char(std::basic_ostream<TChar, TCharTraits> &stream, char c) {
switch (c) { switch (c) {
case '\a': stream << "\\a"; break; case '\a':
case '\b': stream << "\\b"; break; stream << "\\a";
case '\t': stream << "\\t"; break; break;
case '\n': stream << "\\n"; break; case '\b':
case '\v': stream << "\\v"; break; stream << "\\b";
case '\f': stream << "\\f"; break; break;
case '\r': stream << "\\r"; break; case '\t':
case '\e': stream << "\\e"; break; stream << "\\t";
case '\"': stream << "\\\""; break; break;
case '\'': stream << "\\'"; break; case '\n':
case '\?': stream << "\\?"; break; stream << "\\n";
case '\\': stream << "\\\\"; break; break;
default: stream << c; case '\v':
stream << "\\v";
break;
case '\f':
stream << "\\f";
break;
case '\r':
stream << "\\r";
break;
case '\e':
stream << "\\e";
break;
case '\"':
stream << "\\\"";
break;
case '\'':
stream << "\\'";
break;
case '\?':
stream << "\\?";
break;
case '\\':
stream << "\\\\";
break;
default:
stream << c;
} }
} }
} } // namespace detail
template<typename TChar, typename TCharTraits> template <typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> & std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const std::string& x) { pretty_print(std::basic_ostream<TChar, TCharTraits> &stream,
const std::string &x) {
stream << "\""; stream << "\"";
for (char c : x) for (char c : x)
detail::escape_char(stream, c); detail::escape_char(stream, c);
return stream << "\""; return stream << "\"";
} }
template<typename TChar, typename TCharTraits> template <typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> & std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, char c) { pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, char c) {
stream << "'"; stream << "'";
detail::escape_char(stream, c); detail::escape_char(stream, c);
return stream << "'"; return stream << "'";
} }
template<typename T, typename TChar, typename TCharTraits> template <typename T, typename TChar, typename TCharTraits>
inline typename std::enable_if< !::soi::is_container<T>::value, inline typename std::enable_if<!::soi::is_container<T>::value,
std::basic_ostream<TChar, TCharTraits> &>::type std::basic_ostream<TChar, TCharTraits> &>::type
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x) { pretty_print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x) {
return stream << x; return stream << x;
} }
template <typename T, typename TChar, typename TCharTraits>
template<typename T, typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> & std::basic_ostream<TChar, TCharTraits> &
print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x) { print(std::basic_ostream<TChar, TCharTraits> &stream, const T &x) {
return pretty_print(stream, x); return pretty_print(stream, x);
} }
} } // namespace soi
#endif // SOI_PRETTY #endif // SOI_PRETTY

View File

@ -5,20 +5,20 @@
have to understand every concept all at once. have to understand every concept all at once.
*/ */
#include <fstream>
#include "bits/soi-dbg.hpp" #include "bits/soi-dbg.hpp"
#include <fstream>
namespace soi { namespace soi {
void check_for_eof() { void check_for_eof() {
if (!(std::cin >> std::ws).eof()) if (!(std::cin >> std::ws).eof())
std::cerr << "WARNING: didn't read the whole input\n"; std::cerr << "WARNING: didn't read the whole input\n";
} }
void noninteractive_check_eof() { void noninteractive_check_eof() {
// make symbol 0x1A (Ctrl+Z) a whitespace // make symbol 0x1A (Ctrl+Z) a whitespace
struct console_ctype : std::ctype<char> { struct console_ctype : std::ctype<char> {
static const mask* get_table() { static const mask *get_table() {
static const std::array<mask, table_size> table = []() { static const std::array<mask, table_size> table = []() {
std::array<mask, table_size> table; std::array<mask, table_size> table;
std::copy(classic_table(), classic_table() + table_size, table.begin()); std::copy(classic_table(), classic_table() + table_size, table.begin());
@ -27,14 +27,14 @@ void noninteractive_check_eof() {
}(); }();
return table.data(); return table.data();
} }
console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {} console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {}
}; };
std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype)); std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype));
check_for_eof(); check_for_eof();
} }
bool should_check_for_eof() { bool should_check_for_eof() {
if (const char* eofcheck_enabled = std::getenv("SOI_EOFCHECK")) { if (const char *eofcheck_enabled = std::getenv("SOI_EOFCHECK")) {
if (!std::strcmp(eofcheck_enabled, "1")) if (!std::strcmp(eofcheck_enabled, "1"))
return true; return true;
if (!std::strcmp(eofcheck_enabled, "0")) if (!std::strcmp(eofcheck_enabled, "0"))
@ -48,9 +48,9 @@ void initialize_debug() {
std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit); std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::ios::sync_with_stdio(false); std::ios::sync_with_stdio(false);
if (should_check_for_eof() && if (should_check_for_eof() && std::atexit(noninteractive_check_eof) != 0) {
std::atexit(noninteractive_check_eof) != 0) { std::cerr
std::cerr << "WARNING: soi.h -- registration of sanity check at exit failed\n"; << "WARNING: soi.h -- registration of sanity check at exit failed\n";
} }
soi::detail::dbg_init(); soi::detail::dbg_init();
} }