Simple logging library that outputs over the PC serial link to add logging to a file simply `include "xenonym_logging.h" ` then you can add logging with which looks slighly like c++ std::cout logging by using the LOG define or the LOGGER define thus; LOG << "this message will begin a new line" or LOGGER << "this message will append to the end of the previous log"; there is also a simple `LOGFUNC( "funcname" );` define that will log the entry and exit from a function and indent the stream so its easy to see where you are. if you want to disable the logging from a file without removing your logging all you need do is ~#define LOGGING_DISABLED and the logging will compile to nothing. also has simple manipulators hex,dec to change the output radix and eol to start a new line. i.e. <<code>> #include "xenonym_logging.h" using namespace xenonym; class Devr : public Base { public: Devr( int i ) : Base(i) { LOGFUNC( "mylib::Devr" ); ... do stuff .. LOG << "param is still " << logging::dec << i; .... do more stuff .... } virtual uint16_t something( uint16_t msg ) { LOGFUNC( "Derv::something" ); uint16_t reply = proccess( msg ); LOG << "sent:0x" << logging::hex << msg << " reply:0x"<< reply << logging::dec; return reply; } }; <</code>>

xenonym_logging.h

Committer:
xenonym
Date:
2011-08-04
Revision:
2:f3c036aca508
Parent:
1:41f6c5ec11c2

File content as of revision 2:f3c036aca508:

#ifndef xenonym_logging_header /* { */
#define xenonym_logging_header

#include <Serial.h>

/**
 * by default you will get logging, if you do no want if for a certain file define this 
 * and when it compiles all the logging should get compiled away as the nullLogger has
 * a big set of empty inline no-virtual functions.
 */
#ifdef LOGGING_DISABLED
#define LOGGER xenonym::logging::NullLogger::logger
#else
#define LOGGER xenonym::logging::RealLogger::logger
#endif

/**
 * LOGGERALWAYS and LOGALWAYS are always logged, due to the design there is always a logger object in you app
 * its just not used if you disable logging.
 * this allows you to log critial messages when logging is disabled for the module.
 */
#define LOGGERALWAYS xenonym::logging::RealLogger::logger
#define LOGALWAYS xenonym::logging::RealLogger::logger << xenonym::logging::eol

/**
 * to get the indents right easily the simplist solution is to send an end-of-line (eol) 
 * at the BEGINNING of each log line;
 *  if you want the log at the end of the previous line use LOGGER << instead of the more common LOG << 
 */
#define LOG LOGGER << xenonym::logging::eol

/**
 * if logging is disabled then we do not want to create any scope logging objects.
 */
#ifdef LOGGING_DISABLED
#define LOGFUNC( x )
#define LOGSCOPE( n, x )
#else
#define LOGFUNC( x ) xenonym::logging::Func func( x, __FILE__, __LINE__ )
#define LOGSCOPE( n, x ) xenonym::logging::Scope n( x, __FILE__, __LINE__ )
#endif


namespace xenonym
{
    namespace logging
    {
        class LogManipulator
        {
        public:
            virtual void log ( unsigned i ) = 0;
            virtual void log ( int i ) = 0;
            virtual void log ( long long i ) = 0;
            virtual void log ( unsigned long long i ) = 0;
            virtual void log ( char c ) = 0;
            virtual void log ( char const * str ) = 0;
            virtual void set_radix ( int i ) = 0;
            virtual void set_indent ( int i ) = 0;
            virtual int  get_indent () = 0;
        };
        
        typedef void (*manipFunc)( LogManipulator & );
        
        class NullLogger
        {
        public:
            NullLogger & operator<< ( unsigned i ) { return *this; }
            NullLogger & operator<< ( int i ) { return *this; }
            NullLogger & operator<< ( long long i ) { return *this; }
            NullLogger & operator<< ( unsigned long long int i ) { return *this; }
            NullLogger & operator<< ( char i ) { return *this; }
            NullLogger & operator<< ( char const * str ) { return *this; }
            NullLogger & operator<< ( manipFunc manipulator ) { return *this; }
            static NullLogger logger;
        };
        
        class RealLogManipulator;
        class RealLogger
        {
        private:
             friend class RealLogManipulator;
             mbed::Serial m_comms;
             int m_radix;
             int m_indent;
        public:
            RealLogger();
            RealLogger & operator<< ( unsigned i );
            RealLogger & operator<< ( int i );
            RealLogger & operator<< ( long long i );
            RealLogger & operator<< ( unsigned long long int i );
            RealLogger & operator<< ( char i );
            RealLogger & operator<< ( char const * str );
            RealLogger & operator<< ( manipFunc manipulator );
            static RealLogger logger;
        };
        
        /**
         * will sent an end of line and then indent the log stream as required
         * N.B. LOG << "\n" will NOT output the indent to the log stream.
         */
        void eol( LogManipulator & );
        void hex( LogManipulator & );
        void dec( LogManipulator & );
        void indent( LogManipulator & );
        void outdent( LogManipulator & );
        
        class Locn
        {
        protected:
            char const * m_file;
            int          m_line;
        public:
            Locn(char const * const file, int line );
            virtual ~Locn();
        };
        class Scope : public Locn
        {
        public:
            Scope(char const * const file, int line );
            virtual ~Scope();
        };
        
        class Func : public Locn
        {
        private:
            char const * m_name;
        public:
            Func(char const * const name, char const * const file, int line );
            virtual ~Func();
        };
        
    } // namespace logging;
} // namespace xenonym;

#endif /* } xenonym_logging_header */