TECA
The Toolkit for Extreme Climate Analysis
teca_common.h
Go to the documentation of this file.
1 #ifndef teca_common_h
2 #define teca_common_h
3 
4 /// @file
5 
6 #include "teca_config.h"
7 #include "teca_parallel_id.h"
8 
9 #include <iostream>
10 #include <sstream>
11 #include <unistd.h>
12 #include <cstdio>
13 #include <string>
14 #include <vector>
15 #include <array>
16 
17 /** The call signature for the error handler. The error handler will be passed
18  * a string describing the error.
19  */
20 using p_teca_error_handler = void (*) (const char*);
21 
22 /// global error handling hooks
23 namespace teca_error
24 {
25 /// The global error handler instance.
26 extern p_teca_error_handler error_handler TECA_EXPORT;
27 
28 /** An error handler that flushes stdout and stderr streams, and sends msg to
29  * the stderr before returing. This implements the behavior up to and including
30  * TECA 4.1.0
31  */
33 void error_message(const char *msg);
34 
35 /** An error handler that flushes stdout and stderr streams, and sends msg to
36  * the stderr before aborting. When MPI is in use MPI_Abort is invoked. This
37  * implements the behavior after TECA 4.1.0
38  */
40 void error_message_abort(const char *msg);
41 
42 /** Install a custom error haandler. The error handler must have the following
43  * signature.
44  *
45  * void error_handler(const char *msg);
46  *
47  */
50 
51 /// Install the teca_error::error_message error handler
54 
55 /// Install the teca_error::error_message_abort error handler
58 };
59 
60 /// @cond
61 
62 // the operator<< overloads have to be namespace std in order for
63 // boost to find them. they are needed for mutitoken program options
64 namespace std
65 {
66 /// send a vector to a stream
67 template <typename T>
69 std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec)
70 {
71  if (!vec.empty())
72  {
73  os << vec[0];
74  size_t n = vec.size();
75  for (size_t i = 1; i < n; ++i)
76  os << ", " << vec[i];
77  }
78  return os;
79 }
80 
81 /// send a vector of strings to a stream
83 std::ostream &operator<<(std::ostream &os, const std::vector<std::string> &vec);
84 
85 /// send an array to a stream
86 template <typename T, size_t N>
88 std::ostream &operator<<(std::ostream &os, const std::array<T,N> &vec)
89 {
90  if (N)
91  {
92  os << vec[0];
93  for (size_t i = 1; i < N; ++i)
94  os << ", " << vec[i];
95  }
96  return os;
97 }
98 }
99 
100 #ifndef SWIG
101 /// send a fixed length c-array to the stream
102 template <typename num_t, int len,
103  typename = typename std::enable_if<!std::is_same<num_t,char>::value,bool>::type>
105 std::ostream &operator<<(std::ostream &os, const num_t (& data)[len])
106 {
107  os << data[0];
108  for (int i = 1; i < len; ++i)
109  os << ", " << data[i];
110  return os;
111 }
112 #endif
113 
114 /** Return true if we are writing to a TTY. If we are not then we should not
115  * use ansi color codes.
116  */
117 TECA_EXPORT int have_tty();
118 
119 
120 #define ANSI_RED "\033[1;31;40m"
121 #define ANSI_GREEN "\033[1;32;40m"
122 #define ANSI_YELLOW "\033[1;33;40m"
123 #define ANSI_WHITE "\033[1;37;40m"
124 #define ANSI_OFF "\033[0m"
125 
126 #define BEGIN_HL(_color) (have_tty()?_color:"")
127 #define END_HL (have_tty()?ANSI_OFF:"")
128 
129 /// @endcond
130 
131 
132 /** Send a message into the stream with an ANSI color coded message that
133  * include MPI ranks and thread id.
134  */
135 #define TECA_MESSAGE(_strm, _head, _head_color, _msg) \
136 _strm \
137  << BEGIN_HL(_head_color) << _head << END_HL \
138  << " " << teca_parallel_id() << " [" << __FILE__ << ":" << __LINE__ \
139  << " " << TECA_VERSION_DESCR << "]" << std::endl \
140  << BEGIN_HL(_head_color) << _head << END_HL << " " \
141  << BEGIN_HL(ANSI_WHITE) << "" _msg << END_HL << std::endl;
142 
143 /// Send a message into the stream that include MPI ranks and thread id.
144 #define TECA_MESSAGE_RAW(_strm, _head, _msg) \
145 _strm \
146  << _head << " " << teca_parallel_id() << " [" << __FILE__ \
147  << ":" << __LINE__ << " " << TECA_VERSION_DESCR << "]" << std::endl \
148  << _head << " " << "" _msg << std::endl;
149 
150 /** Constructs an the error message using TECA_MESSAGE and invokes the
151  * error handler.
152  */
153 #define TECA_FATAL_ERROR(_msg) \
154 { \
155  std::ostringstream ess; \
156  TECA_MESSAGE(ess, "ERROR:", ANSI_RED, _msg) \
157  teca_error::error_handler(ess.str().c_str()); \
158 }
159 
160 /// Constructs an error message and sends it to the stderr stream
161 #define TECA_ERROR(_msg) TECA_MESSAGE(std::cerr, "ERROR:", ANSI_RED, _msg)
162 
163 /// Constructs a warning message and sends it to the stderr stream
164 #define TECA_WARNING(_msg) TECA_MESSAGE(std::cerr, "WARNING:", ANSI_YELLOW, _msg)
165 
166 /// Constructs a status message and sends it to the stderr stream
167 #define TECA_STATUS(_msg) TECA_MESSAGE(std::cerr, "STATUS:", ANSI_GREEN, _msg)
168 
169 #endif
global error handling hooks
Definition: teca_common.h:24
TECA_EXPORT void set_error_message_abort_handler()
Install the teca_error::error_message_abort error handler.
TECA_EXPORT void set_error_message_handler()
Install the teca_error::error_message error handler.
TECA_EXPORT void error_message(const char *msg)
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
TECA_EXPORT void set_error_handler(p_teca_error_handler handler)
TECA_EXPORT void error_message_abort(const char *msg)
auto data(V &&... args)
Definition: teca_variant_array_util.h:255
TECA_EXPORT std::ostream & operator<<(std::ostream &os, const teca_calendar_util::time_point &tpt)
send the time_point to a stream in humnan readable form
void(*)(const char *) p_teca_error_handler
Definition: teca_common.h:20