SPIN Framework

include/spinLogWX.h

00001 // -----------------------------------------------------------------------------
00002 // |    ___  ___  _  _ _     ___                                        _      |
00003 // |   / __>| . \| || \ |   | __>_ _  ___ ._ _ _  ___  _ _ _  ___  _ _ | |__   |
00004 // |   \__ \|  _/| ||   |   | _>| '_><_> || ' ' |/ ._>| | | |/ . \| '_>| / /   |
00005 // |   <___/|_|  |_||_\_|   |_| |_|  <___||_|_|_|\___.|__/_/ \___/|_|  |_\_\   |
00006 // |                                                                           |
00007 // |---------------------------------------------------------------------------|
00008 //
00009 // http://spinframework.sourceforge.net
00010 // Copyright (C) 2009 Mike Wozniewski, Zack Settel
00011 //
00012 // Developed/Maintained by:
00013 //    Mike Wozniewski (http://www.mikewoz.com)
00014 //    Zack Settel (http://www.sheefa.net/zack)
00015 // 
00016 // Principle Partners:
00017 //    Shared Reality Lab, McGill University (http://www.cim.mcgill.ca/sre)
00018 //    La Societe des Arts Technologiques (http://www.sat.qc.ca)
00019 //
00020 // Funding by:
00021 //    NSERC/Canada Council for the Arts - New Media Initiative
00022 //    Heritage Canada
00023 //    Ministere du Developpement economique, de l'Innovation et de l'Exportation
00024 //
00025 // -----------------------------------------------------------------------------
00026 //  This file is part of the SPIN Framework.
00027 //
00028 //  SPIN Framework is free software: you can redistribute it and/or modify
00029 //  it under the terms of the GNU Lesser General Public License as published by
00030 //  the Free Software Foundation, either version 3 of the License, or
00031 //  (at your option) any later version.
00032 //
00033 //  SPIN Framework is distributed in the hope that it will be useful,
00034 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00035 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00036 //  GNU Lesser General Public License for more details.
00037 //
00038 //  You should have received a copy of the GNU Lesser General Public License
00039 //  along with SPIN Framework. If not, see <http://www.gnu.org/licenses/>.
00040 // -----------------------------------------------------------------------------
00041 
00042 #ifndef SPINLOGWX_H_
00043 #define SPINLOGWX_H_
00044 
00045 #include <iostream>
00046 #include <fstream>
00047 #include <time.h>
00048 #include <stdio.h>
00049 
00050 #include <wx/log.h>
00051 #include <wx/string.h>
00052 
00053 // code from http://www.advogato.org/person/elanthis/diary/363.html
00054 
00055 namespace spin
00056 {
00057 
00058 
00059 enum LogPriority
00060 {
00061     INFO, // regular unimportant log messages
00062     DEV, // debugging fluff
00063     ERROR, // it's dead, jim
00064 };
00065 
00066 class logbuf : public streambuf
00067 {
00068     
00069 public:
00070     
00071     // create a buffer and initialize our logfile
00072     logbuf(const char* logpath) :
00073         priority(INFO), buf(0), buflen(1024), bFILE(true), bCOUT(false)
00074     {
00075         // create our buffer
00076         buf = new char_type[buflen];
00077         setp(buf, buf + buflen);
00078 
00079         // open the log file
00080         logfile.open(logpath, ios::app);
00081 
00082         if (!logfile.is_open())
00083         {
00084             std::cout << "Error: Could not open log file: " << logpath << std::endl;
00085             exit(1);
00086         }
00087 
00088     }
00089 
00090     // free our buffer
00091     ~logbuf()
00092     {
00093         sync();
00094         delete[] buf;
00095     }
00096 
00097     // set the priority to be used on the next call to sync()
00098     void set_priority(LogPriority p)
00099     {
00100         priority = p;
00101     }
00102 
00103     // logging modes:
00104     bool bCOUT;
00105     bool bFILE;
00106     bool bWXLG;
00107 
00108     
00109 private:
00110     
00111     // spit out the time, priority, and the log buffer to cerr and logfile
00112     int sync()
00113     {
00114         // nifty time formatting functions from the C standard library
00115         time_t t = time(NULL);
00116         tm* tmp = localtime(&t);
00117         char shortTime[128];
00118         char longTime[128];
00119         strftime(shortTime, sizeof(shortTime), "%H:%M:%S", tmp);
00120         strftime(longTime, sizeof(longTime), "%Y-%m-%d %H:%M:%S", tmp);
00121 
00122         // now we stream the time, then the priority, then the message
00123         if (bCOUT) std::cout << shortTime << ' ';
00124         if (bFILE) logfile << longTime << ' ';
00125 
00126         switch (priority)
00127         {
00128         case INFO:
00129             if (bCOUT) std::cout << "[INFO:] ";
00130             if (bFILE) logfile << "[INFO:] ";
00131             break;
00132         case DEV:
00133             if (bCOUT) std::cout << "[DEBUG] ";
00134             if (bFILE) logfile << "[DEBUG] ";
00135             break;
00136         case ERROR:
00137             if (bCOUT) std::cout << "[ERROR] ";
00138             if (bFILE) logfile << "[ERROR] ";
00139             break;
00140         }
00141 
00142 
00143         if (bCOUT) std::cout.write(pbase(), pptr() - pbase());
00144         if (bFILE) logfile.write(pbase(), pptr() - pbase());
00145         
00146         if (bWXLG)
00147         {
00148             char wxBuf[1024];
00149             strncpy( wxBuf, pbase(), pptr()-pbase() );
00150             wxBuf[pptr()-pbase()-1] = '\0'; // remove the \n that comes from std::endl
00151             wxLogMessage(wxString(wxBuf,wxConvUTF8));
00152         }
00153         
00154         // flush output
00155         if (bCOUT) std::cout.flush();
00156         if (bFILE) logfile.flush();
00157 
00158         // reset our priority to INFO
00159         priority = INFO;
00160 
00161         // reset the buffer
00162         setp(pbase(), epptr());
00163         return 0;
00164     }
00165 
00166     // we ran out of space, so grow the buffer
00167     int overflow(int c)
00168     {
00169         // allocate a new buffer and copy our current data into it, then swap
00170         // it with the old buffer
00171         char_type newbuf[buflen + 1024];
00172         memcpy(newbuf, buf, buflen);
00173         delete[] buf;
00174         buf = newbuf;
00175 
00176         // now we need to stuff c into the buffer
00177         sputc(c);
00178         return 0;
00179     }
00180 
00181     // our log file
00182     ofstream logfile;
00183 
00184     // current priority
00185     LogPriority priority;
00186 
00187     // our buffer
00188     char_type* buf;
00189     unsigned long buflen;
00190 };
00191 
00192 
00193 class spinLog : public std::ostream
00194 {
00195 
00196 public:
00197     // we initialize the ostream to use our logbuf
00198     spinLog(const char* logpath) : std::ostream(new logbuf(logpath))
00199     {
00200         buf = (logbuf*) rdbuf();
00201     }
00202 
00203     // set priority
00204     void set_priority(LogPriority pr)
00205     {
00206         buf->set_priority(pr);
00207     }
00208     
00209     void enable_cout(bool b)
00210     {
00211         buf->bCOUT = b;
00212     }
00213     
00214     void enable_logfile(bool b)
00215     {
00216         buf->bFILE = b;
00217     }
00218     
00219     void enable_wxlog(bool b)
00220     {
00221         buf->bWXLG = b;
00222     }
00223 
00224     
00225 private:
00226     // our logbuf object
00227     logbuf *buf;
00228 };
00229 
00230 // set the priority for a spinLog/logbuf this must be a global function and not
00231 // a member to work around C++'s type resolution of overloaded functions
00232 static spinLog& operator<<(spinLog& vlog, LogPriority pr)
00233 {
00234     vlog.set_priority(pr);
00235     return vlog;
00236 }
00237 
00238 } // end of namespace spin
00239 
00240 
00241 #endif