PageRenderTime 38ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/include/tite/core/log/detail/Log_.hpp

http://tite.googlecode.com/
C++ Header | 291 lines | 177 code | 27 blank | 87 comment | 5 complexity | e68bb19e167d9091ee7dc9b36819ff8a MD5 | raw file
Possible License(s): GPL-3.0
  1. /****************************************************************************
  2. ** Tite Interactive Text Engine (TiTE)
  3. ** Copyright (C) 2010 Eisoft Group
  4. **
  5. ** This file is part of TiTE.
  6. **
  7. ** TiTE is free software: you can redistribute it and/or modify
  8. ** it under the terms of the GNU General Public License as published by
  9. ** the Free Software Foundation, either version 3 of the License, or
  10. ** (at your option) any later version.
  11. **
  12. ** TiTE is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ** GNU General Public License for more details.
  16. **
  17. ** You should have received a copy of the GNU General Public License
  18. ** along with TiTE. If not, see <http://www.gnu.org/licenses/>.
  19. ****************************************************************************/
  20. /*!
  21. * \file Log_.hpp
  22. *
  23. * \date 01/10/2011
  24. */
  25. #ifndef TITE_CORE_LOG__HPP
  26. #define TITE_CORE_LOG__HPP
  27. #include <algorithm>
  28. #include <ctime>
  29. #include <string>
  30. #include <vector>
  31. #include <tite/core/log/ILogListener.hpp>
  32. /*!
  33. * \namespace tite
  34. *
  35. * \brief The TiTE namespace.
  36. */
  37. namespace tite
  38. {
  39. /*!
  40. * \namespace core
  41. *
  42. * \brief The TiTE core namespace.
  43. */
  44. namespace core
  45. {
  46. /*!
  47. * \class Log_ Log_.hpp
  48. *
  49. * \brief A simple, efficient generic logging class.
  50. *
  51. * \note The Container template parameter expects an STL-style container.
  52. *
  53. * \author Jason Omahen
  54. * \version 0.02, 12/18/2010
  55. */
  56. template<
  57. typename T,
  58. typename Listener = ILogListener,
  59. template <typename, typename> class Container = stdext::vector,
  60. typename Allocator = stdext::allocator<T>
  61. >
  62. class Log_
  63. {
  64. // Log_ helper functions to provide a simple interface
  65. friend Log_& log_I(void);
  66. #if defined(DEBUG) || defined(_DEBUG)
  67. friend Log_& log_D(void);
  68. #endif
  69. friend Log_& log_W(void);
  70. friend Log_& log_C(void);
  71. friend Log_& log_F(void);
  72. public:
  73. typedef T log_elem_t;
  74. typedef Listener listener_t;
  75. typedef listener_t* listener_ptr_t;
  76. typedef listener_t *const listener_const_ptr_t;
  77. Log_(void);
  78. ~Log_(void);
  79. void log(const stdext::string & message, log_levels::LogLevel messageLevel);
  80. void addListener(listener_const_ptr_t pLogListener);
  81. void removeListener(listener_const_ptr_t pLogListener);
  82. template<typename U>
  83. Log_& operator<<(const U & u);
  84. private:
  85. char* _getLocalTime(void);
  86. void _prepare(log_levels::LogLevel l);
  87. void _writeToBuffer(const stdext::string & message);
  88. std::time_t m_rawTime;
  89. log_levels::LogLevel m_currentLogLevel;
  90. Container<T, Allocator> m_logBuffer;
  91. Container<listener_ptr_t, Allocator> m_logListeners;
  92. };
  93. /*!
  94. * \brief Log_ ctor.
  95. */
  96. template<
  97. typename T,
  98. typename Listener,
  99. template <typename, typename> class Container,
  100. typename Allocator
  101. >
  102. Log_<T, Listener, Container, Allocator>::Log_(void)
  103. : m_currentLogLevel(log_levels::None)
  104. {
  105. log("[Log Singleton] Starting up ...\n", log_levels::Info);
  106. }
  107. /*!
  108. * \brief Log_ dtor.
  109. */
  110. template<
  111. typename T,
  112. typename Listener,
  113. template <typename, typename> class Container,
  114. typename Allocator
  115. >
  116. Log_<T, Listener, Container, Allocator>::~Log_(void)
  117. {
  118. log("[Log Singleton] Shutting down ...\n", log_levels::Warning);
  119. for (Container<listener_ptr_t, Allocator>::iterator it = m_logListeners.begin(); it != m_logListeners.end(); ++it)
  120. safe_delete(&(*it));
  121. }
  122. /*!
  123. * \brief Logs a message at the specified log level.
  124. *
  125. * \param message Contents to log.
  126. * \param messageLevel Message type.
  127. */
  128. template<
  129. typename T,
  130. typename Listener,
  131. template <typename, typename> class Container,
  132. typename Allocator
  133. >
  134. void Log_<T, Listener, Container, Allocator>::log(const std::string & message, log_levels::LogLevel messageLevel)
  135. {
  136. _prepare(messageLevel);
  137. _writeToBuffer(message);
  138. }
  139. template<
  140. typename T,
  141. typename Listener,
  142. template <typename, typename> class Container,
  143. typename Allocator
  144. >
  145. void Log_<T, Listener, Container, Allocator>::addListener(typename Log_<T, Listener, Container, Allocator>::listener_const_ptr_t pLogListener)
  146. {
  147. if (pLogListener)
  148. m_logListeners.push_back(pLogListener);
  149. }
  150. template<
  151. typename T,
  152. typename Listener,
  153. template <typename, typename> class Container,
  154. typename Allocator
  155. >
  156. void Log_<T, Listener, Container, Allocator>::removeListener(typename Log_<T, Listener, Container, Allocator>::listener_const_ptr_t pLogListener)
  157. {
  158. m_logListeners.erase(stdext::remove(m_logListeners.begin(),
  159. m_logListeners.end(),
  160. pLogListener),
  161. m_logListeners.end());
  162. }
  163. /*!
  164. * \brief Overloaded "stream" insertion operator; writes contents directly
  165. * to the log buffer.
  166. *
  167. * \note Use in conjunction with the log_X helper functions for increased
  168. * clarity and simplicity.
  169. *
  170. * \param u std::string-convertable message to log.
  171. *
  172. * \return Modified Log_ object after message was logged.
  173. */
  174. template<
  175. typename T,
  176. typename Listener,
  177. template <typename, typename> class Container,
  178. typename Allocator
  179. >
  180. template<typename U>
  181. Log_<T, Listener, Container, Allocator>& Log_<T, Listener, Container, Allocator>::operator<<(const U & u)
  182. {
  183. _writeToBuffer(u);
  184. return *this;
  185. }
  186. /*!
  187. * \brief Formats the computer's local date/time into an ASCII string.
  188. *
  189. * \return The local date/time.
  190. */
  191. template<
  192. typename T,
  193. typename Listener,
  194. template <typename, typename> class Container,
  195. typename Allocator
  196. >
  197. char* Log_<T, Listener, Container, Allocator>::_getLocalTime(void)
  198. {
  199. std::time(&m_rawTime);
  200. return std::asctime(std::localtime(&m_rawTime));
  201. }
  202. /*!
  203. * \brief Prepares the logging buffer for a specific LogLevel.
  204. *
  205. * \param l Logging level.
  206. */
  207. template<
  208. typename T,
  209. typename Listener,
  210. template <typename, typename> class Container,
  211. typename Allocator
  212. >
  213. void Log_<T, Listener, Container, Allocator>::_prepare(log_levels::LogLevel l)
  214. {
  215. stdext::string header, time(_getLocalTime());
  216. // Remove \n character from the time string
  217. time.pop_back();
  218. switch (l)
  219. {
  220. case log_levels::Info:
  221. header = "[INFO.]";
  222. break;
  223. case log_levels::Debug:
  224. header = "[DEBUG]";
  225. break;
  226. case log_levels::Warning:
  227. header = "[WARN!]";
  228. break;
  229. case log_levels::Critical:
  230. case log_levels::Fatal:
  231. header = "[FATAL]";
  232. break;
  233. }
  234. header += "[" + time + "] ";
  235. // Write the prefix message
  236. m_currentLogLevel = l;
  237. _writeToBuffer(header);
  238. }
  239. /*!
  240. * \brief Commits the message to the internal logging buffer.
  241. *
  242. * \param message Contents to log.
  243. */
  244. template<
  245. typename T,
  246. typename Listener,
  247. template <typename, typename> class Container,
  248. typename Allocator
  249. >
  250. void Log_<T, Listener, Container, Allocator>::_writeToBuffer(const stdext::string & message)
  251. {
  252. // A buffer may be completely unnecessary now... waste memory for already processed
  253. // messages? Eh... let's rethink this!
  254. m_logBuffer.insert(m_logBuffer.end(), message.begin(), message.end());
  255. stdext::for_each(m_logListeners.begin(),
  256. m_logListeners.end(),
  257. stdext::bind(&Listener::logMessage,
  258. stdext::placeholders::_1,
  259. stdext::cref(message),
  260. m_currentLogLevel));
  261. }
  262. }// End of core namespace
  263. }// End of tite namespace
  264. #endif /* TITE_CORE_LOG__HPP */