error_handling.h 2.79 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 *  This file is part of the MR utility library.
 *
 *  This code is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This code is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this code; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

Martin Reinecke's avatar
Martin Reinecke committed
19
/* Copyright (C) 2019-2020 Max-Planck-Society
Martin Reinecke's avatar
Martin Reinecke committed
20
21
   Author: Martin Reinecke */

Martin Reinecke's avatar
Martin Reinecke committed
22
23
#ifndef DUCC0_ERROR_HANDLING_H
#define DUCC0_ERROR_HANDLING_H
Martin Reinecke's avatar
Martin Reinecke committed
24

Martin Reinecke's avatar
Martin Reinecke committed
25
#include <sstream>
Martin Reinecke's avatar
Martin Reinecke committed
26
#include <exception>
Martin Reinecke's avatar
Martin Reinecke committed
27

28
#include "mr_util/infra/useful_macros.h"
Martin Reinecke's avatar
Martin Reinecke committed
29

Martin Reinecke's avatar
Martin Reinecke committed
30
31
namespace mr {

Martin Reinecke's avatar
Martin Reinecke committed
32
namespace detail_error_handling {
Martin Reinecke's avatar
Martin Reinecke committed
33

Martin Reinecke's avatar
Martin Reinecke committed
34
#if defined (__GNUC__)
Martin Reinecke's avatar
Martin Reinecke committed
35
#define DUCC0_ERROR_HANDLING_LOC_ ::mr::detail_error_handling::CodeLocation(__FILE__, __LINE__, __PRETTY_FUNCTION__)
Martin Reinecke's avatar
Martin Reinecke committed
36
#else
Martin Reinecke's avatar
Martin Reinecke committed
37
#define DUCC0_ERROR_HANDLING_LOC_ ::mr::detail_error_handling::CodeLocation(__FILE__, __LINE__)
Martin Reinecke's avatar
Martin Reinecke committed
38
39
#endif

Martin Reinecke's avatar
Martin Reinecke committed
40
// to be replaced with std::source_location once generally available
Martin Reinecke's avatar
Martin Reinecke committed
41
42
43
44
45
46
47
48
49
50
class CodeLocation
  {
  private:
    const char *file, *func;
    int line;

  public:
    CodeLocation(const char *file_, int line_, const char *func_=nullptr)
      : file(file_), func(func_), line(line_) {}

Martin Reinecke's avatar
Martin Reinecke committed
51
52
53
54
55
56
57
    inline ::std::ostream &print(::std::ostream &os) const
      {
      os << "\n" << file <<  ": " <<  line;
      if (func) os << " (" << func << ")";
      os << ":\n";
      return os;
      }
Martin Reinecke's avatar
Martin Reinecke committed
58
59
  };

Martin Reinecke's avatar
Martin Reinecke committed
60
inline ::std::ostream &operator<<(::std::ostream &os, const CodeLocation &loc)
Martin Reinecke's avatar
Martin Reinecke committed
61
62
  { return loc.print(os); }

Martin Reinecke's avatar
Martin Reinecke committed
63
64
#if (__cplusplus>=201703L) // hyper-elegant C++2017 version
template<typename ...Args>
Martin Reinecke's avatar
Martin Reinecke committed
65
void streamDump__(::std::ostream &os, Args&&... args)
Martin Reinecke's avatar
Martin Reinecke committed
66
67
  { (os << ... << args); }
#else
Martin Reinecke's avatar
Martin Reinecke committed
68
template<typename T>
Martin Reinecke's avatar
Martin Reinecke committed
69
void streamDump__(::std::ostream &os, const T& value)
Martin Reinecke's avatar
Martin Reinecke committed
70
71
72
  { os << value; }

template<typename T, typename ... Args>
Martin Reinecke's avatar
Martin Reinecke committed
73
void streamDump__(::std::ostream &os, const T& value,
Martin Reinecke's avatar
Martin Reinecke committed
74
75
76
77
78
79
  const Args& ... args)
  {
  os << value;
  streamDump__(os, args...);
  }
#endif
Martin Reinecke's avatar
Martin Reinecke committed
80
template<typename ...Args>
Martin Reinecke's avatar
Martin Reinecke committed
81
[[noreturn]] void DUCC0_NOINLINE fail__(Args&&... args)
Martin Reinecke's avatar
Martin Reinecke committed
82
83
84
85
86
87
88
89
  {
  ::std::ostringstream msg; \
  ::mr::detail_error_handling::streamDump__(msg, args...); \
    throw ::std::runtime_error(msg.str()); \
  }

#define MR_fail(...) \
  do { \
Martin Reinecke's avatar
Martin Reinecke committed
90
    ::mr::detail_error_handling::fail__(DUCC0_ERROR_HANDLING_LOC_, "\n", ##__VA_ARGS__, "\n"); \
Martin Reinecke's avatar
Martin Reinecke committed
91
92
93
94
95
96
97
    } while(0)

#define MR_assert(cond,...) \
  do { \
    if (cond); \
    else { MR_fail("Assertion failure\n", ##__VA_ARGS__); } \
    } while(0)
Martin Reinecke's avatar
Martin Reinecke committed
98

Martin Reinecke's avatar
Martin Reinecke committed
99
}}
Martin Reinecke's avatar
Martin Reinecke committed
100

Martin Reinecke's avatar
Martin Reinecke committed
101
#endif