Proton  1.1.1
Make porting easy from Python to C++11
base.hpp
Go to the documentation of this file.
1 #ifndef PROTON_H
2 #define PROTON_H
3 
4 /** @file base.hpp
5  * @brief the basic header for Proton Library
6  */
7 
8 #include <iostream>
9 #include <ctime>
10 #include <cstring>
11 #include <iomanip>
12 #include <cstdio>
13 #include <algorithm>
14 #include <type_traits>
15 
16 /** The main proton namespace.
17  */
18 namespace proton{
19 
20 /** The implementation namespace of proton.
21  * Any thing in this namespace should not be considered as a part of interfaces of Proton.
22  */
23 namespace detail{
24 
25 inline const char* filename(const char* pathname)
26 {
27  const char* p = strrchr(pathname, '\\');
28  if(!p)
29  p = strrchr(pathname,'/');
30  if(!p)
31  return pathname;
32  else
33  return p;
34 }
35 
36 inline void output_ts(std::ostream& o, const char* type, const char* fn, long ln)
37 {
38  std::ios_base::fmtflags ff=o.flags();
39  time_t now=time(NULL);
40  struct tm* ti=localtime(&now);
41  o << std::dec << std::right << "[";
42  o << ti->tm_year+1900 << "-" << ti->tm_mon+1 << "-" << ti->tm_mday;
43  o << " " << std::setw(2) << ti->tm_hour << ":" << std::setw(2) << ti->tm_min
44  << ":" << std::setw(2) << ti->tm_sec << "] "
45  << type << " " << filename(fn) << "#" << ln;
46  o.flags(ff);
47 }
48 
49 }
50 
51 /**
52  * @addtogroup debug Debug utilities
53  * Macros, global variables, classes for debug.
54  * @{
55  */
56 
57 extern int debug_level; ///< The level controls output of PROTON_LOG().
58 extern bool log_console; ///< true: PROTON_LOG/PROTON_THROW_IF/PROTON_ERR will output to console, false: no console output for these macros.
59 extern int wait_on_err; ///< 0: nonstop, 1: stop on PROTON_ERR, 2: stop on PROTON_THROW_IF assert
60 
61 /** Control debug macros.
62  * 1: enable PROTON_LOG/PROTON_THROW_IF/PROTON_ERR, 0: disable them.
63  */
64 #ifndef PROTON_DEBUG_OPT
65 #define PROTON_DEBUG_OPT 1
66 #endif
67 
68 #if PROTON_DEBUG_OPT
69 
70 /** Log messages to cerr.
71  * Output messages when lvl <= proton::debug_level.
72  * @param lvl the log level.
73  * @param out messages to be outputed, they can be concatenated using "<<".
74  */
75 #define PROTON_LOG( lvl, out )\
76  {\
77  if ( proton::log_console && (lvl) <= proton::debug_level ) {\
78  proton::detail::output_ts(std::cerr, "PROTON_LOG", __FILE__, __LINE__);\
79  std::cerr << " : " << out << std::endl;\
80  }\
81  }
82 
83 /** Proton's inverse assert.
84  * Throw if cond is true, and output the reason.
85  * If proton::wait_on_err >= 2, it will hold the program and wait for any key.
86  * You can use gdb to attach the process to check what's happened.
87  * @param cond the condition to check, throw proton::err("assert") if it's true.
88  * @param out the message describing what's happened.
89  */
90 #define PROTON_THROW_IF(cond, out)\
91  {\
92  if (cond) {\
93  if(proton::log_console){\
94  proton::detail::output_ts(std::cerr, "BAD", __FILE__, __LINE__);\
95  std::cerr << " : " << out << std::endl;\
96  }\
97  if(proton::wait_on_err>=2){\
98  std::cout << "Assert failed. Waiting, press any key to continue..." << std::endl;\
99  getchar();\
100  }\
101  throw proton::err("assert");\
102  }\
103  }
104 #else
105 #define PROTON_LOG( lvl, out )
106 #define PROTON_THROW_IF(cond, out)
107 #endif
108 
109 /** Throw an err.
110  * Throw a proton::err("err"), and output a message.
111  * If proton::wait_on_err >= 1, it will hold the program and wait for any key.
112  * You can use gdb to attach the process to check what's happened.
113  * @param out the message describing what's happened.
114  */
115 #define PROTON_ERR(out)\
116  {\
117  if(proton::log_console){\
118  proton::detail::output_ts(std::cerr, "ERR", __FILE__, __LINE__);\
119  std::cerr << " : " << out << std::endl;\
120  }\
121  if(proton::wait_on_err>=1){\
122  std::cout << "An error has happened. Waiting, press any key to continue..." << std::endl;\
123  ::getchar();\
124  }\
125  throw proton::err("err");\
126  }
127 
128 /** The exception class.
129  * The exception class used by PROTON_THROW_IF and PROTON_ERR.
130  */
131 class err: public std::exception{
132 protected:
133  const char* _msg;
134 public:
135  /** ctor
136  * @param msg the message showed in what().
137  */
138  err(const char* msg) throw():_msg(msg)
139  {}
140 
141  err(const err& e) throw():_msg(e._msg)
142  {}
143 
144  err& operator=(const err& e) throw()
145  {
146  _msg=e._msg;
147  return *this;
148  }
149 
150  /** get message
151  * @return the message used in ctor.
152  */
153  const char* what()const throw()
154  {
155  return _msg;
156  }
157 };
158 
159 inline std::ostream& operator<<(std::ostream& o, const err& e)
160 {
161  o << e.what();
162  return o;
163 }
164 
165 /**
166  * @}
167  */
168 
169 namespace detail{
170 
171 template<typename T>struct min_t{
172  typedef typename std::remove_reference<decltype(*(((T*)1)->begin()))>::type item_t;
173  static const item_t& result(const T& v)
174  {
175  return *std::min_element(v.begin(), v.end());
176  }
177 };
178 
179 template<typename T>struct max_t{
180  typedef typename std::remove_reference<decltype(*(((T*)1)->begin()))>::type item_t;
181  static const item_t& result(const T& v)
182  {
183  return *std::max_element(v.begin(), v.end());
184  }
185 };
186 
187 template<typename T>struct has_t{
188 // typedef decltype(*(((T*)1)->begin())) item_t;
189  template<typename V>static bool result(const T& x, V&& v)
190  {
191  return std::find(x.begin(), x.end(), v)!=x.end();
192  }
193 };
194 
195 template<typename T>struct len_t{
196 // typedef decltype(*(((T*)1)->begin())) item_t;
197  static size_t result(const T& x)
198  {
199  return x.size();
200  }
201 };
202 
203 }
204 
205 /** @addtogroup seq
206  * @{
207  */
208 
209 /** smallest item.
210  */
211 template<typename T>
212 const typename detail::min_t<T>::item_t& min(const T& v)
213 {
214  return detail::min_t<T>::result(v);
215 }
216 
217 /** largest item.
218  */
219 template<typename T>
220 const typename detail::max_t<T>::item_t& max(const T& v)
221 {
222  return detail::max_t<T>::result(v);
223 }
224 
225 /** check if x has val.
226  * @param x the container
227  * @param v the value
228  * @return true: has, false: not
229  */
230 template <typename T, typename V>
231 bool has(const T& x, V&& v)
232 {
233  return detail::has_t<T>::result(x, v);
234 }
235 
236 /** get length.
237  */
238 template<typename T>
239 size_t len(const T& v)
240 {
241  return detail::len_t<T>::result(v);
242 }
243 
244 /**
245  * @}
246  */
247 }; // namespace proton
248 
249 #endif // PROTON_H