<tb@panthema.net>
<http://www.gnu.org/licenses/>
#ifndef BISPANNING_DEBUG_HEADER
#define BISPANNING_DEBUG_HEADER
#include <algorithm>
#include <array>
#include <iostream>
#include <map>
#include <sstream>
#include <sys/time.h>
#include <tuple>
#include <vector>
#define DBGX(dbg, X) do { if (dbg) { std::cout << X; } \
} while (0)
#define DBGXE(dbg, X) do { if (dbg) { std::cerr << X; } \
} while (0)
#define DBG(X) DBGX(debug, X << std::endl)
#define DBGE(X) DBGXE(debug, X << std::endl)
#define DBGE0(X) DBGXE(false, X << std::endl)
#define DBGE1(X) DBGXE(true, X << std::endl)
#define DBGG(X) DBGX(debug, "// " << __FUNCTION__ << "() " << X << std::endl)
#define DBGGE(X) DBGXE(debug, "// " << __FUNCTION__ << "() " << X << std::endl)
#define DBGG0(X) DBGX(false, "// " << __FUNCTION__ << "() " << X << std::endl)
#define DBGG1(X) DBGX(true, "// " << __FUNCTION__ << "() " << X << std::endl)
#define DBG0(X) DBGX(false, X << std::endl)
#define DBG1(X) DBGX(true, X << std::endl)
#define DBG2(dbg, X) DBGX(dbg, X)
#define DBG3(dbg, X) DBGX(dbg, X << std::endl)
#define ASSERT(expr) do { if (!(expr)) { fprintf(stderr, "%s:%u %s: Assertion '%s' failed!\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); abort(); } \
} while (0)
static inline double timestamp()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return tv.tv_sec + tv.tv_usec / 1e6;
}
template <typename T, typename JoinType>
static inline std::string vector_join(const std::vector<T>& v, JoinType join)
{
std::ostringstream oss;
for (typename std::vector<T>::const_iterator i = v.begin();
i != v.end(); ++i)
{
if (i != v.begin()) oss << join;
oss << *i;
}
return oss.str();
}
template <typename T>
static inline std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
os << '[';
for (typename std::vector<T>::const_iterator i = v.begin();
i != v.end(); ++i)
{
if (i != v.begin()) os << ',';
os << *i;
}
return os << ']';
}
template <typename K, typename V>
static inline std::ostream& operator << (std::ostream& os, const std::map<K, V>& m)
{
os << '{';
for (typename std::map<K, V>::const_iterator i = m.begin();
i != m.end(); ++i)
{
if (i != m.begin()) os << ',';
os << i->first << "->" << i->second;
}
return os << '}';
}
template <typename T, size_t N>
static inline std::string array_join(const std::array<T, N>& v, const std::string& join)
{
std::ostringstream oss;
for (typename std::array<T, N>::const_iterator i = v.begin();
i != v.end(); ++i)
{
if (i != v.begin()) oss << join;
oss << *i;
}
return oss.str();
}
template <typename T, size_t N>
static inline std::ostream& operator << (std::ostream& os, const std::array<T, N>& v)
{
os << '[';
for (typename std::array<T, N>::const_iterator i = v.begin();
i != v.end(); ++i)
{
if (i != v.begin()) os << ',';
os << *i;
}
return os << ']';
}
template <typename U, typename V>
static inline std::ostream& operator << (std::ostream& os, const std::pair<U, V>& v)
{
os << '(' << v.first << ',' << v.second << ')';
return os;
}
template <typename Type, unsigned N, unsigned Last>
struct tuple_printer {
static void print(std::ostream& out, const Type& value)
{
out << std::get<N>(value) << ',';
tuple_printer<Type, N + 1, Last>::print(out, value);
}
};
template <typename Type, unsigned N>
struct tuple_printer<Type, N, N>{
static void print(std::ostream& out, const Type& value)
{
out << std::get<N>(value);
}
};
template <typename ... Types>
std::ostream& operator << (std::ostream& out, const std::tuple<Types ...>& value)
{
out << '[';
tuple_printer<std::tuple<Types ...>, 0, sizeof ... (Types)-1>::print(out, value);
out << ']';
return out;
}
template <typename T>
static inline bool vector_contains(const std::vector<T>& v, const T& needle)
{
return std::find(v.begin(), v.end(), needle) != v.end();
}
template <typename T>
static inline std::string to_str(const T& value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
template <typename T>
static inline T from_str(const std::string& str)
{
std::istringstream oss(str);
T t;
oss >> t;
if (!oss.eof()) throw std::runtime_error("Cannot parse: " + str);
return t;
}
bool str_is_numeric(const std::string& str)
{
for (std::string::const_iterator s = str.begin(); s != str.end(); ++s) {
if (!isdigit(*s)) return false;
}
return true;
}
static inline
std::vector<std::string> split(
const std::string& str, char sep,
std::string::size_type limit = std::string::npos)
{
std::vector<std::string> out;
if (limit == 0) return out;
std::string::const_iterator it = str.begin(), last = it;
for ( ; it != str.end(); ++it)
{
if (*it == sep)
{
if (out.size() + 1 >= limit)
{
out.push_back(std::string(last, str.end()));
return out;
}
out.push_back(std::string(last, it));
last = it + 1;
}
}
out.push_back(std::string(last, it));
return out;
}
template <typename Iterator, typename Glue>
static inline
std::string join(const Glue& glue, Iterator first, Iterator last)
{
std::ostringstream oss;
if (first == last) return oss.str();
oss << *first++;
while (first != last) {
oss << glue;
oss << *first++;
}
return oss.str();
}
template <typename Container, typename Glue>
static inline
std::string join(const Glue& glue, const Container& parts)
{
return join(glue, parts.begin(), parts.end());
}
#endif