initial commit

This commit is contained in:
Johannes Kapfhammer 2019-10-06 16:45:29 +02:00
commit 44aa8d060a
7 changed files with 1027 additions and 0 deletions

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# `#include <soi>`
Include soi and you're ready to go!
## dbg(...)
You can debug any expressions using the macro dbg().
## Configuration
You can set the following environment variables to customize the behaviour.
`SOI_H_COLOR`: By default, colored output is shown in case a terminal is connected.
You can force colors with `SOI_H_COLOR=1` and shut them off with `SOI_H_COLOR=0`.
`SOI_H_EOFCHECK`: By default, it is *not* checked, whether you have read all the
input. In case you pipe the input from a file or want to issue a proper EOF
character (Control D under linux or Control Z under Windows), you can enable
this check using `SOI_H_COLOR=1`.
## Template
Using this header is as simple as:
```
#include <soi>
signed main() {
// your code goes here
}
```
It requires at least c++11 to function.

16
example.cpp Normal file
View File

@ -0,0 +1,16 @@
// compile-command: "g++ -Iinclude -D_GLIBCXX_DEBUG -fsanitize=address,undefined -g3 -ggdb3 -std=c++17 example.cpp -o example && SOI_H_COLOR=1 SOI_H_EOFCHECK=1 ./example <<< ''"
#include <soi>
signed main() {
dbg("hi");
string s="world";
dbg(s);
dbg(false);
dbg(true);
dbg('c');
vector<int> pi{3,1,4,1,5,9,2,6};
dbg(pi);
dbg(vector<int>{3,1,4,1,5,9,2,6});
dbg(pi);
cout << "hi\n";
}

444
include/prettyprint.hpp Normal file
View File

@ -0,0 +1,444 @@
// Copyright Louis Delacroix 2010 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// A pretty printing library for C++
//
// The global operator<< overload hs been removed
#ifndef SOI_H_PRETTY_PRINT
#define SOI_H_PRETTY_PRINT
#include <cstddef>
#include <iterator>
#include <memory>
#include <ostream>
#include <set>
#include <tuple>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <valarray>
namespace pretty_print
{
namespace detail
{
// SFINAE type trait to detect whether T::const_iterator exists.
struct sfinae_base
{
using yes = char;
using no = yes[2];
};
template <typename T>
struct has_const_iterator : private sfinae_base
{
private:
template <typename C> static yes & test(typename C::const_iterator*);
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:
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
template <typename TChar>
struct delimiters_values
{
using char_type = TChar;
const char_type * prefix;
const char_type * delimiter;
const char_type * postfix;
};
// Defines the delimiter values for a specific container and character type
template <typename T, typename TChar>
struct delimiters
{
using type = delimiters_values<TChar>;
static const type values;
};
// Functor to print containers. You can use this directly if you want
// to specificy a non-default delimiters type. The printing logic can
// be customized by specializing the nested template.
template <typename T,
typename TChar = char,
typename TCharTraits = ::std::char_traits<TChar>,
typename TDelimiters = delimiters<T, TChar>>
struct print_container_helper
{
using delimiters_type = TDelimiters;
using ostream_type = std::basic_ostream<TChar, TCharTraits>;
template <typename U>
struct printer
{
static void print_body(const U & c, ostream_type & stream)
{
using std::begin;
using std::end;
auto it = begin(c);
const auto the_end = end(c);
if (it != the_end)
{
for ( ; ; )
{
stream << *it;
if (++it == the_end) break;
if (delimiters_type::values.delimiter != NULL)
stream << delimiters_type::values.delimiter;
}
}
}
};
print_container_helper(const T & container)
: container_(container)
{ }
inline void operator()(ostream_type & stream) const
{
if (delimiters_type::values.prefix != NULL)
stream << delimiters_type::values.prefix;
printer<T>::print_body(container_, stream);
if (delimiters_type::values.postfix != NULL)
stream << delimiters_type::values.postfix;
}
private:
const T & container_;
};
// Specialization for pairs
template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename T1, typename T2>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>>
{
using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
static void print_body(const std::pair<T1, T2> & c, ostream_type & stream)
{
stream << c.first;
if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
stream << c.second;
}
};
// Specialization for tuples
template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
template <typename ...Args>
struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>>
{
using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
using element_type = std::tuple<Args...>;
template <std::size_t I> struct Int { };
static void print_body(const element_type & c, ostream_type & stream)
{
tuple_print(c, stream, Int<0>());
}
static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>)
{
}
static void tuple_print(const element_type & c, ostream_type & stream,
typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type)
{
stream << std::get<0>(c);
tuple_print(c, stream, Int<1>());
}
template <std::size_t N>
static void tuple_print(const element_type & c, ostream_type & stream, Int<N>)
{
if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
stream << std::get<N>(c);
tuple_print(c, stream, Int<N + 1>());
}
};
// Prints a print_container_helper to the specified stream.
template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
inline std::basic_ostream<TChar, TCharTraits> & operator<<(
std::basic_ostream<TChar, TCharTraits> & stream,
const print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
{
helper(stream);
return stream;
}
// Basic is_container template; specialize to derive from std::true_type for all desired container types
template <typename T>
struct is_container : public std::integral_constant<bool,
detail::has_const_iterator<T>::value &&
detail::has_begin_end<T>::beg_value &&
detail::has_begin_end<T>::end_value> { };
template <typename T, std::size_t N>
struct is_container<T[N]> : std::true_type { };
template <std::size_t N>
struct is_container<char[N]> : std::false_type { };
template <typename T>
struct is_container<std::valarray<T>> : std::true_type { };
template <typename T1, typename T2>
struct is_container<std::pair<T1, T2>> : std::true_type { };
template <typename ...Args>
struct is_container<std::tuple<Args...>> : std::true_type { };
// Default delimiters
template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
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
template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
template <typename T, typename TComp, typename TAllocator>
const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
template <typename T, typename TComp, typename TAllocator>
const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
template <typename T, typename TComp, typename TAllocator>
struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
template <typename T, typename TComp, typename TAllocator>
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>
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>
const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
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; };
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"}" };
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; };
template <typename T, typename THash, typename TEqual, typename TAllocator>
const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
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; };
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"}" };
// 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> const delimiters_values<char> delimiters<std::pair<T1, T2>, 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 ...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.
// Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
// Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
struct custom_delims_base
{
virtual ~custom_delims_base() { }
virtual std::ostream & stream(::std::ostream &) = 0;
virtual std::wostream & stream(::std::wostream &) = 0;
};
template <typename T, typename Delims>
struct custom_delims_wrapper : custom_delims_base
{
custom_delims_wrapper(const T & t_) : t(t_) { }
std::ostream & stream(std::ostream & s)
{
return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
}
std::wostream & stream(std::wostream & s)
{
return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
}
private:
const T & t;
};
template <typename Delims>
struct custom_delims
{
template <typename Container>
custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
std::unique_ptr<custom_delims_base> base;
};
template <typename TChar, typename TCharTraits, typename Delims>
inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p)
{
return p.base->stream(s);
}
// A wrapper for a C-style array given as pointer-plus-size.
// Usage: std::cout << pretty_print_array(arr, n) << std::endl;
template<typename T>
struct array_wrapper_n
{
typedef const T * const_iterator;
typedef T value_type;
array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
inline const_iterator begin() const { return _array; }
inline const_iterator end() const { return _array + _n; }
private:
const T * const _array;
size_t _n;
};
// A wrapper for hash-table based containers that offer local iterators to each bucket.
// Usage: std::cout << bucket_print(m, 4) << std::endl; (Prints bucket 5 of container m.)
template <typename T>
struct bucket_print_wrapper
{
typedef typename T::const_local_iterator const_iterator;
typedef typename T::size_type size_type;
const_iterator begin() const
{
return m_map.cbegin(n);
}
const_iterator end() const
{
return m_map.cend(n);
}
bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
private:
const T & m_map;
const size_type n;
};
} // namespace pretty_print
/*
// Global accessor functions for the convenience wrappers
template<typename T>
inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
{
return pretty_print::array_wrapper_n<T>(a, n);
}
template <typename T> pretty_print::bucket_print_wrapper<T>
bucket_print(const T & m, typename T::size_type n)
{
return pretty_print::bucket_print_wrapper<T>(m, n);
}
// Main magic entry point: An overload snuck into namespace std.
// Can we do better?
namespace std
{
// Prints a container to the stream using default delimiters
template<typename T, typename TChar, typename TCharTraits>
inline typename enable_if< ::pretty_print::is_container<T>::value,
basic_ostream<TChar, TCharTraits> &>::type
operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
{
return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
}
}
*/
#endif // SOI_H_PRETTY_PRINT

103
include/soi Normal file
View File

@ -0,0 +1,103 @@
// -*- c++ -*-
/*
Students: please don't try to understand the details of headers just
yet. All will be explained. This header is primarily used so that you don't
have to understand every concept all at once.
*/
#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <memory>
#include <ostream>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>
#include "soi-dbg.hpp"
namespace soi_h {
void check_for_eof() {
if (!(std::cin >> std::ws).eof())
std::cerr << "WARNING: didn't read the whole input\n";
}
void noninteractive_check_eof() {
// make symbol 0x1A (Ctrl+Z) a whitespace
struct console_ctype : std::ctype<char> {
static const mask* get_table() {
static const std::array<mask, table_size> table = []() {
std::array<mask, table_size> table;
std::copy(classic_table(), classic_table() + table_size, table.begin());
table['\x1a'] |= space;
return table;
}();
return table.data();
}
console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {}
};
std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype));
check_for_eof();
}
bool should_check_for_eof() {
if (const char* eofcheck_enabled = std::getenv("SOI_H_EOFCHECK")) {
if (!std::strcmp(eofcheck_enabled, "1"))
return true;
if (!std::strcmp(eofcheck_enabled, "0"))
return false;
}
return false;
}
void initialize_debug() {
std::cout << std::unitbuf; // enable automatic flushing
std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::ios::sync_with_stdio(false);
if (should_check_for_eof() &&
std::atexit(noninteractive_check_eof) != 0) {
std::cerr << "WARNING: soi.h -- registration of sanity check at exit failed\n";
}
soi_h::detail::dbg_init();
}
struct soi_h_initializer {
soi_h_initializer(bool release) {
if (release) {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
} else {
initialize_debug();
}
}
};
#ifdef SOI_RELEASE
soi_h_initializer soi_h_initializer_{true};
#else
soi_h_initializer soi_h_initializer_{false};
#endif
} // end namespace soi_h
#include "soi-deprecate.hpp"
#define int int64_t
using namespace std;

294
include/soi-dbg.hpp Normal file
View File

@ -0,0 +1,294 @@
// Copyright Johannes Kapfhammer 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// A debug macro: allows debugging with dbg(<expression>);
// initialize with dbg_init() to enable colorized output
//
#ifndef SOI_H_DBG
#define SOI_H_DBG
#include <cstddef>
#include <stdexcept>
#include <cstring>
#include <ostream>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
#include "soi-pretty.hpp"
namespace soi_h {
namespace detail {
// ----------------------------------------------------------------------------
// detecting the type name: https://stackoverflow.com/a/20170989
#ifndef _MSC_VER
# if __cplusplus < 201103
# define CONSTEXPR11_TN
# define CONSTEXPR14_TN
# define NOEXCEPT_TN
# elif __cplusplus < 201402
# define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN
# define NOEXCEPT_TN noexcept
# else
# define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN constexpr
# define NOEXCEPT_TN noexcept
# endif
#else // _MSC_VER
# if _MSC_VER < 1900
# define CONSTEXPR11_TN
# define CONSTEXPR14_TN
# define NOEXCEPT_TN
# elif _MSC_VER < 2000
# define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN
# define NOEXCEPT_TN noexcept
# else
# define CONSTEXPR11_TN constexpr
# define CONSTEXPR14_TN constexpr
# define NOEXCEPT_TN noexcept
# endif
#endif // _MSC_VER
class static_string {
const char* const p_;
const std::size_t sz_;
public:
typedef const char* const_iterator;
template <std::size_t N>
CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN
: p_(a)
, sz_(N-1)
{}
CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN
: p_(p)
, sz_(N)
{}
CONSTEXPR11_TN const char* data() const NOEXCEPT_TN {return p_;}
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 end() const NOEXCEPT_TN {return p_ + sz_;}
CONSTEXPR11_TN char operator[](std::size_t n) const
{
return n < sz_ ? p_[n] : throw std::out_of_range("static_string");
}
};
struct static_string_no_std {
bool is_debug;
bool is_std;
static_string type;
CONSTEXPR11_TN static_string_no_std(bool is_debug,
bool is_std,
static_string type)
: is_debug(is_debug), is_std(is_std), type(type) {}
};
inline
std::ostream&
operator<<(std::ostream& os, static_string const& s)
{
return os.write(s.data(), s.size());
}
inline
std::ostream&
operator<<(std::ostream& os, static_string_no_std const& s) {
if (s.is_debug) {
const int k = sizeof("std::__debug::") - 1;
return os.write(s.type.data()+k, s.type.size()-k);
} else if (s.is_std) {
const int k = sizeof("std::") - 1;
return os.write(s.type.data()+k, s.type.size()-k);
} else {
return os.write(s.type.data(), s.type.size());
}
}
template <class T>
CONSTEXPR14_TN
static_string
type_name()
{
const int k = sizeof("constexpr soi_h::detail:: T =")/sizeof(char);
#ifdef __clang__
static_string p = __PRETTY_FUNCTION__;
return static_string(p.data() + 31 + k, p.size() - 31 - k - 1);
#elif defined(__GNUC__)
static_string p = __PRETTY_FUNCTION__;
# if __cplusplus < 201402
return static_string(p.data() + 36 + k, p.size() - 36 - k - 1);
# else
return static_string(p.data() + 46 + k, p.size() - 46 - k - 1);
# endif
#elif defined(_MSC_VER)
static_string p = __FUNCSIG__;
return static_string(p.data() + 38 + k, p.size() - 38 - k - 7);
#endif
}
template <class T>
CONSTEXPR14_TN
static_string_no_std
sanitized_type_name() {
CONSTEXPR14_TN static_string t = type_name<T>();
CONSTEXPR14_TN bool is_std =
t.size() >= sizeof("std::") &&
t[ 0] == 's' &&
t[ 1] == 't' &&
t[ 2] == 'd' &&
t[ 3] == ':' &&
t[ 4] == ':';
CONSTEXPR14_TN bool is_debug =
is_std &&
t.size() >= sizeof("std::__debug::") &&
t[ 5] == '_' &&
t[ 6] == '_' &&
t[ 7] == 'd' &&
t[ 8] == 'e' &&
t[ 9] == 'b' &&
t[10] == 'u' &&
t[11] == 'g';
return static_string_no_std(is_debug, is_std, t);
}
// ----------------------------------------------------------------------------
// colorized output
bool tty_supports_colors() {
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
return isatty(STDERR_FILENO);
#else
return true;
#endif
}
int has_environment_color_overwrite() {
if (const char* color_enabled = std::getenv("SOI_H_COLOR")) {
if (!std::strcmp(color_enabled, "1"))
return 1;
if (!std::strcmp(color_enabled, "0"))
return 0;
}
return -1;
}
bool are_colors_enabled() {
int c = has_environment_color_overwrite();
if (c == -1)
return tty_supports_colors();
return static_cast<bool>(c);
}
// ----------------------------------------------------------------------------
// init and static variables
static bool colors_enabled = false;
static const char* ANSI_DEBUG = "";
static const char* ANSI_EXPRESSION = "";
static const char* ANSI_VALUE = "";
static const char* ANSI_TYPE = "";
static const char* ANSI_MESSAGE = "";
static const char* ANSI_RESET = "";
void dbg_init(bool with_colors) {
if (with_colors) {
bool colors_enabled = true;
ANSI_DEBUG = "\x1b[02m";
ANSI_EXPRESSION = "\x1b[36m";
ANSI_VALUE = "\x1b[01m";
ANSI_TYPE = "\x1b[32m";
ANSI_MESSAGE = "\x1b[31m\x1b[01m";
ANSI_RESET = "\x1b[0m";
} else {
bool colors_enabled = false;
ANSI_DEBUG = "";
ANSI_EXPRESSION = "";
ANSI_VALUE = "";
ANSI_TYPE = "";
ANSI_MESSAGE = "";
ANSI_RESET = "";
}
}
void dbg_init() {
dbg_init(are_colors_enabled());
}
// ----------------------------------------------------------------------------
// printer
template <typename T>
T&& dbg_print(T&& value,
static_string_no_std const& type,
char const* file,
int line,
char const* function_name,
char const* expression) {
const T& ref = value;
std::stringstream value_buffer; // avoid nesting of dbg macros within print functinos
soi_h::pretty_print(value_buffer, ref);
std::cerr << ANSI_DEBUG
<< "[" << file << ":" << line
<< " (" << function_name << ")] " << ANSI_RESET
<< ANSI_EXPRESSION << expression << ANSI_RESET
<< " = "
<< ANSI_VALUE << value_buffer.rdbuf() << ANSI_RESET
<< " (" << ANSI_TYPE << type << ANSI_RESET << ")"
<< '\n';
return std::forward<T>(value);
}
template<unsigned int N>
auto dbg_print(const char (&msg)[N],
static_string_no_std const&,
char const* file,
int line,
char const* function_name,
char const* expression) -> decltype(msg) {
std::cerr << ANSI_DEBUG
<< "[" << file << ":" << line
<< " (" << function_name << ")] " << ANSI_RESET
<< ANSI_MESSAGE << msg << ANSI_RESET
<< '\n';
return msg;
}
template <typename T>
T&& identity(T&& t) {
return std::forward<T>(t);
}
} // end namespace detail
} // end namespace dbg_macro
#ifdef SOI_H_RELEASE
#define dbg(...) dbg_macro::identity(__VA_ARGS__)
#else
#define dbg(...) \
soi_h::detail::dbg_print((__VA_ARGS__), \
soi_h::detail::sanitized_type_name<decltype(__VA_ARGS__)>(), \
__FILE__, \
__LINE__, \
__func__, \
#__VA_ARGS__)
#endif
#endif // SOI_H_DBG

62
include/soi-deprecate.hpp Normal file
View File

@ -0,0 +1,62 @@
#pragma GCC diagnostic error "-Wdeprecated-declarations"
struct 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 printf printf_is_evil
#define fprintf fprintf_is_evil
#define sprintf sprintf_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 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 fscanf fscanf_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 fscanf(std::FILE *stream, const char *format, ...);
[[deprecated("scanf is evil. Use cin.")]] int sscanf(const char *buffer, const char *format, ...);
#define puts puts_is_evil
#define fputs fputs_is_evil
#define fgets fgets_is_evil
#define freopen freopen_is_evil
#define fopen fopen_is_evil
#define fclose fclose_is_evil
#define fflush fflush_is_evil
#define getchar getchar_is_evil
#define fgetc fgetc_is_evil
#define getc getc_is_evil
#define setbuf setbuf_is_evil
#define setvbuf setvbuf_is_evil
#define fread fread_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 fputs(const char *str, FILE *stream);
[[deprecated("<cstdio> is evil. Use cin/cout.")]] char *fgets(char *str, int count, 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.")]] 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 fgetc(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.")]] int 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 calloc calloc_is_evil
#define realloc realloc_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 *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("delete is evil. Use a vector.")]] void operator delete(void *ptr) noexcept;

76
include/soi-pretty.hpp Normal file
View File

@ -0,0 +1,76 @@
// Copyright Johannes Kapfhammer 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// pretty printing with c++
//
#ifndef SOI_H_PRETTY
#define SOI_H_PRETTY
#include "prettyprint.hpp"
namespace soi_h {
template<typename T, typename TChar, typename TCharTraits>
inline typename std::enable_if< ::pretty_print::is_container<T>::value,
std::basic_ostream<TChar, TCharTraits> &>::type
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T & container) {
return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
}
template<typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const bool& x) {
return stream << (x ? "true" : "false");
}
namespace detail {
template<typename TChar, typename TCharTraits>
void escape_char(std::basic_ostream<TChar, TCharTraits> & stream, char c) {
switch (c) {
case '\a': stream << "\\a"; break;
case '\b': stream << "\\b"; break;
case '\t': stream << "\\t"; break;
case '\n': stream << "\\n"; break;
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;
}
}
}
template<typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const std::string& x) {
stream << "\"";
for (char c : x)
detail::escape_char(stream, c);
return stream << "\"";
}
template<typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits> &
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, char c) {
stream << "'";
detail::escape_char(stream, c);
return stream << "'";
}
template<typename T, typename TChar, typename TCharTraits>
inline typename std::enable_if< !::pretty_print::is_container<T>::value,
std::basic_ostream<TChar, TCharTraits> &>::type
pretty_print(std::basic_ostream<TChar, TCharTraits> & stream, const T& x) {
return stream << x;
}
}
#endif // SOI_H_PRETTY