PageRenderTime 41ms CodeModel.GetById 12ms app.highlight 22ms RepoModel.GetById 2ms 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
  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/*!
 22 * \file Log_.hpp
 23 *
 24 * \date 01/10/2011
 25 */
 26
 27#ifndef TITE_CORE_LOG__HPP
 28#define TITE_CORE_LOG__HPP
 29
 30#include <algorithm>
 31#include <ctime>
 32#include <string>
 33#include <vector>
 34
 35#include <tite/core/log/ILogListener.hpp>
 36
 37/*!
 38 * \namespace tite
 39 *
 40 * \brief The TiTE namespace.
 41 */
 42namespace tite
 43{
 44    /*!
 45     * \namespace core
 46     *
 47     * \brief The TiTE core namespace.
 48     */
 49    namespace core
 50    {
 51        /*!
 52         * \class Log_ Log_.hpp
 53         *
 54         * \brief A simple, efficient generic logging class. 
 55         *
 56         * \note The Container template parameter expects an STL-style container.
 57         *
 58         * \author Jason Omahen
 59         * \version 0.02, 12/18/2010
 60         */
 61        template<
 62            typename T, 
 63            typename Listener = ILogListener,
 64            template <typename, typename> class Container = stdext::vector, 
 65            typename Allocator = stdext::allocator<T> 
 66        >
 67        class Log_
 68        {
 69            // Log_ helper functions to provide a simple interface
 70            friend Log_& log_I(void);
 71    #if defined(DEBUG) || defined(_DEBUG)
 72            friend Log_& log_D(void);
 73    #endif
 74            friend Log_& log_W(void);
 75            friend Log_& log_C(void);
 76            friend Log_& log_F(void);
 77        
 78        public:
 79            typedef T log_elem_t;
 80            typedef Listener listener_t;
 81            typedef listener_t* listener_ptr_t;
 82            typedef listener_t *const listener_const_ptr_t;
 83
 84            Log_(void);
 85            ~Log_(void);
 86
 87            void log(const stdext::string & message, log_levels::LogLevel messageLevel);
 88
 89            void addListener(listener_const_ptr_t pLogListener);
 90            void removeListener(listener_const_ptr_t pLogListener);
 91
 92            template<typename U> 
 93                Log_& operator<<(const U & u);
 94
 95        private:
 96            char* _getLocalTime(void);
 97            void _prepare(log_levels::LogLevel l);
 98            void _writeToBuffer(const stdext::string & message);
 99
100            std::time_t m_rawTime;
101            log_levels::LogLevel m_currentLogLevel;
102
103            Container<T, Allocator> m_logBuffer;
104            Container<listener_ptr_t, Allocator> m_logListeners;
105        };
106    
107        /*!
108         * \brief Log_ ctor.
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            : m_currentLogLevel(log_levels::None)
118        {
119            log("[Log Singleton] Starting up ...\n", log_levels::Info);
120        }
121
122        /*!
123         * \brief Log_ dtor.
124         */
125        template<
126            typename T, 
127            typename Listener,
128            template <typename, typename> class Container, 
129            typename Allocator
130        >
131        Log_<T, Listener, Container, Allocator>::~Log_(void)
132        {
133            log("[Log Singleton] Shutting down ...\n", log_levels::Warning);
134
135            for (Container<listener_ptr_t, Allocator>::iterator it = m_logListeners.begin(); it != m_logListeners.end(); ++it)
136                safe_delete(&(*it));
137        }
138    
139        /*!
140         * \brief Logs a message at the specified log level.
141         *
142         * \param message       Contents to log.
143         * \param messageLevel  Message type.
144         */
145        template<
146            typename T, 
147            typename Listener,
148            template <typename, typename> class Container, 
149            typename Allocator
150        >
151        void Log_<T, Listener, Container, Allocator>::log(const std::string & message, log_levels::LogLevel messageLevel)
152        {
153            _prepare(messageLevel);
154            _writeToBuffer(message);
155        }
156
157        template<
158            typename T, 
159            typename Listener,
160            template <typename, typename> class Container, 
161            typename Allocator
162        >
163        void Log_<T, Listener, Container, Allocator>::addListener(typename Log_<T, Listener, Container, Allocator>::listener_const_ptr_t pLogListener)
164        {
165            if (pLogListener)
166                m_logListeners.push_back(pLogListener);
167        }
168
169        template<
170            typename T, 
171            typename Listener,
172            template <typename, typename> class Container, 
173            typename Allocator
174        >
175        void Log_<T, Listener, Container, Allocator>::removeListener(typename Log_<T, Listener, Container, Allocator>::listener_const_ptr_t pLogListener)
176        {
177            m_logListeners.erase(stdext::remove(m_logListeners.begin(), 
178                                                m_logListeners.end(), 
179                                                pLogListener), 
180                                 m_logListeners.end());
181        }
182
183        /*!
184         * \brief Overloaded "stream" insertion operator; writes contents directly
185         *        to the log buffer.
186         *
187         * \note Use in conjunction with the log_X helper functions for increased 
188         *       clarity and simplicity.
189         *
190         * \param u  std::string-convertable message to log.
191         *
192         * \return Modified Log_ object after message was logged.
193         */
194        template<
195            typename T, 
196            typename Listener,
197            template <typename, typename> class Container, 
198            typename Allocator
199        >
200            template<typename U>
201            Log_<T, Listener, Container, Allocator>& Log_<T, Listener, Container, Allocator>::operator<<(const U & u)
202            {
203                _writeToBuffer(u);
204                return *this;
205            }
206
207        /*!
208         * \brief Formats the computer's local date/time into an ASCII string.
209         *
210         * \return The local date/time.
211         */
212        template<
213            typename T, 
214            typename Listener,
215            template <typename, typename> class Container, 
216            typename Allocator
217        >
218        char* Log_<T, Listener, Container, Allocator>::_getLocalTime(void)
219        {
220            std::time(&m_rawTime);
221            return std::asctime(std::localtime(&m_rawTime));
222        }
223
224        /*!
225         * \brief Prepares the logging buffer for a specific LogLevel.
226         *
227         * \param l  Logging level.
228         */
229        template<
230            typename T, 
231            typename Listener,
232            template <typename, typename> class Container, 
233            typename Allocator
234        >
235        void Log_<T, Listener, Container, Allocator>::_prepare(log_levels::LogLevel l)
236        {
237            stdext::string header, time(_getLocalTime());
238        
239            // Remove \n character from the time string
240            time.pop_back();
241
242            switch (l)
243            {
244            case log_levels::Info:
245                header = "[INFO.]";
246                break;
247            case log_levels::Debug:
248                header = "[DEBUG]";
249                break;
250            case log_levels::Warning:
251                header = "[WARN!]";
252                break;
253            case log_levels::Critical:
254            case log_levels::Fatal:
255                header = "[FATAL]";
256                break;
257            }
258            header += "[" + time + "]  ";
259
260            // Write the prefix message
261            m_currentLogLevel = l;
262            _writeToBuffer(header);
263        }
264
265        /*!
266         * \brief Commits the message to the internal logging buffer.
267         *
268         * \param message  Contents to log.
269         */
270        template<
271            typename T, 
272            typename Listener,
273            template <typename, typename> class Container, 
274            typename Allocator
275        >
276        void Log_<T, Listener, Container, Allocator>::_writeToBuffer(const stdext::string & message)
277        {
278            // A buffer may be completely unnecessary now... waste memory for already processed
279            // messages? Eh... let's rethink this!
280            m_logBuffer.insert(m_logBuffer.end(), message.begin(), message.end());
281            stdext::for_each(m_logListeners.begin(), 
282                             m_logListeners.end(), 
283                             stdext::bind(&Listener::logMessage, 
284                                          stdext::placeholders::_1, 
285                                          stdext::cref(message), 
286                                          m_currentLogLevel));
287        }
288    }// End of core namespace
289}// End of tite namespace
290
291#endif /* TITE_CORE_LOG__HPP */