PureFSM
logger.hpp
Go to the documentation of this file.
1 /**
2  * @file logger.hpp
3  *
4  * File logger.hpp provides logger types and utilities for PureFSM.
5  */
6 #ifndef PUREFSM_LOGGER_HPP
7 #define PUREFSM_LOGGER_HPP
8 
9 #include <ostream>
10 
11 namespace pure {
12 
13  /**
14  * @brief Logger utilities namespace
15  *
16  * See @ref fsm_logger
17  */
18  namespace logger {
19 
20  /**
21  * @fn type_name
22  *
23  * @tparam T type
24  *
25  * @brief Compile-time reflection
26  *
27  * Returns a string that is a name of a type T. Compiler dependent.
28  * If the compiler does not supports compile-time function signature
29  * reflection, the function will be returning an empty string.
30  *
31  * See @ref fsm_logger
32  */
33 
34 #if defined(__GNUC__) || defined(__MINGW32__) || defined(__clang__) ||
35  defined(__INTEL_COMPILER) || (defined(__ICC) && (__ICC >= 600)) ||
36  (defined(__DMC__) && __DMC__ >= 0x810)
37 
38  template <typename T>
39  std::string type_name() {
40  using size_type = typename std::string::size_type;
41  char const* str = __PRETTY_FUNCTION__;
42  while (*str != '=') ++str;
43  str += 2;
44  size_type size = 0;
45  while (str[size] != ';' && str[size] != ']') ++size;
46  return std::string(str, size);
47  }
48 
49 #elif defined(__MSC_VER) || defined(__FUNCSIG__)
50 
51  template <typename T>
52  std::string type_name() {
53  using size_type = typename std::string::size_type;
54  const std::string s = __FUNCSIG__;
55  const std::string fname = "type_name<";
56  const std::string rest = ">(void)";
59  return std::string(s, pos, count);
60  }
61 
62 #else
63 
64  #warning
65  "Your compiler does not support the reflection required by the logger"
66 
67  template <typename T>
69  return {};
70  }
71 
72 #endif
73 
74  } // namespace logger
75 
76  template <std::ostream& stream>
77  class stdout_logger {
78  public:
79  stdout_logger() = default;
80 
81  template <typename T>
82  inline void write(const char* str) {
83  stream << str << logger::type_name<T>() << std::endl;
84  }
85 
86  inline void write(const char* str) { stream << str << std::endl; }
87  };
88 
89  class user_logger {
90  private:
91  std::ostream& stream;
92  public:
93  user_logger() = delete;
94 
95  /**
96  * @brief Constructs user_logger with a stream given
97  */
98  user_logger(std::ostream& stream) : stream(stream) {}
99 
100  /**
101  * @brief Constructs user_logger from a reference to another user_logger
102  */
103  user_logger(user_logger const& other) : stream(other.stream) {}
104 
105  /**
106  * @brief Constructs user_logger from another user_logger
107  */
108  user_logger(user_logger&& other) : stream(other.stream) {}
109 
110  template <typename T>
111  inline void write(const char* str) {
112  stream << str << logger::type_name<T>() << std::endl;
113  }
114 
115  inline void write(const char* str) { stream << str << std::endl; }
116  };
117 
118 } // namespace pure
119 
120 #endif