All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
Console.cpp
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 /* Author: Ioan Sucan */
00036 
00037 #include "ompl/util/Console.h"
00038 #include <boost/thread/mutex.hpp>
00039 #include <iostream>
00040 #include <cstdlib>
00041 #include <cstdio>
00042 #include <cstdarg>
00043 
00045 
00046 struct DefaultOutputHandler
00047 {
00048     DefaultOutputHandler(void)
00049     {
00050         output_handler_ = static_cast<ompl::msg::OutputHandler*>(&std_output_handler_);
00051         previous_output_handler_ = output_handler_;
00052     }
00053 
00054     ompl::msg::OutputHandlerSTD std_output_handler_;
00055     ompl::msg::OutputHandler   *output_handler_;
00056     ompl::msg::OutputHandler   *previous_output_handler_;
00057     boost::mutex                lock_; // it is likely the outputhandler does some I/O, so we serialize it
00058 };
00059 
00060 // we use this function because we want to handle static initialization correctly
00061 // however, the first run of this function is not thread safe, due to the use of a static
00062 // variable inside the function. For this reason, we ensure the first call happens during
00063 // static initialization using a proxy class
00064 static DefaultOutputHandler* getDOH(void)
00065 {
00066     static DefaultOutputHandler DOH;
00067     return &DOH;
00068 }
00069 
00070 #define USE_DOH                                                                \
00071     DefaultOutputHandler *doh = getDOH();                                \
00072     boost::mutex::scoped_lock slock(doh->lock_)
00073 
00075 
00076 void ompl::msg::noOutputHandler(void)
00077 {
00078     USE_DOH;
00079     doh->previous_output_handler_ = doh->output_handler_;
00080     doh->output_handler_ = NULL;
00081 }
00082 
00083 void ompl::msg::restorePreviousOutputHandler(void)
00084 {
00085     USE_DOH;
00086     std::swap(doh->previous_output_handler_, doh->output_handler_);
00087 }
00088 
00089 void ompl::msg::useOutputHandler(OutputHandler *oh)
00090 {
00091     USE_DOH;
00092     doh->previous_output_handler_ = doh->output_handler_;
00093     doh->output_handler_ = oh;
00094 }
00095 
00096 ompl::msg::OutputHandler* ompl::msg::getOutputHandler(void)
00097 {
00098     return getDOH()->output_handler_;
00099 }
00100 
00101 ompl::msg::Interface::Interface(const std::string &prefix)
00102 {
00103     setPrefix(prefix);
00104 }
00105 
00106 ompl::msg::Interface::~Interface(void)
00107 {
00108 }
00109 
00110 const std::string& ompl::msg::Interface::getPrefix(void) const
00111 {
00112     return prefix_;
00113 }
00114 
00115 void ompl::msg::Interface::setPrefix(const std::string &prefix)
00116 {
00117     prefix_ = prefix;
00118     if (!prefix_.empty())
00119         prefix_ += ": ";
00120 }
00121 
00123 
00124 // the maximum buffer size to use when printing a message
00125 #define MAX_BUFFER_SIZE 1024
00126 
00127 // macro that combines the set of arguments into a single string
00128 #define COMBINE(m, buf, size)                                                \
00129     va_list __ap;                                                        \
00130     va_start(__ap, m);                                                        \
00131     char buf##_chr[size];                                                \
00132     vsnprintf(buf##_chr, sizeof(buf##_chr), m, __ap);                        \
00133     va_end(__ap);                                                        \
00134     buf##_chr[size - 1] = '\0';                                                \
00135     std::string buf(buf##_chr)
00136 
00137 #define CALL_DOH(fn, arg)                                                \
00138     USE_DOH;                                                                \
00139     if (doh->output_handler_)                                                \
00140         doh->output_handler_->fn(arg)
00141 
00143 
00144 void ompl::msg::Interface::debug(const std::string &text) const
00145 {
00146     CALL_DOH(debug, prefix_ + text);
00147 }
00148 
00149 void ompl::msg::Interface::debug(const char *msg, ...) const
00150 {
00151     COMBINE(msg, buf, MAX_BUFFER_SIZE);
00152     debug(buf);
00153 }
00154 
00155 void ompl::msg::Interface::inform(const std::string &text) const
00156 {
00157     CALL_DOH(inform, prefix_ + text);
00158 }
00159 
00160 void ompl::msg::Interface::inform(const char *msg, ...) const
00161 {
00162     COMBINE(msg, buf, MAX_BUFFER_SIZE);
00163     inform(buf);
00164 }
00165 
00166 void ompl::msg::Interface::warn(const std::string &text) const
00167 {
00168     CALL_DOH(warn, prefix_ + text);
00169 }
00170 
00171 void ompl::msg::Interface::warn(const char *msg, ...) const
00172 {
00173     COMBINE(msg, buf, MAX_BUFFER_SIZE);
00174     warn(buf);
00175 }
00176 
00177 void ompl::msg::Interface::error(const std::string &text) const
00178 {
00179     CALL_DOH(error, prefix_ + text);
00180 }
00181 
00182 void ompl::msg::Interface::error(const char *msg, ...) const
00183 {
00184     COMBINE(msg, buf, MAX_BUFFER_SIZE);
00185     error(buf);
00186 }
00187 
00188 void ompl::msg::OutputHandlerSTD::error(const std::string &text)
00189 {
00190     std::cerr << "Error:   " << text << std::endl;
00191     std::cerr.flush();
00192 }
00193 
00194 void ompl::msg::OutputHandlerSTD::warn(const std::string &text)
00195 {
00196     std::cerr << "Warning: " << text << std::endl;
00197     std::cerr.flush();
00198 }
00199 
00200 void ompl::msg::OutputHandlerSTD::inform(const std::string &text)
00201 {
00202     std::cout << "Info:    " << text << std::endl;
00203     std::cout.flush();
00204 }
00205 
00206 void ompl::msg::OutputHandlerSTD::debug(const std::string &text)
00207 {
00208     std::cout << "Debug:   " << text << std::endl;
00209     std::cout.flush();
00210 }
00211 
00212 ompl::msg::OutputHandlerFile::OutputHandlerFile(const char *filename) : OutputHandler()
00213 {
00214     file_ = fopen(filename, "a");
00215     if (!file_)
00216         std::cerr << "Unable to open log file: '" << filename << "'" << std::endl;
00217 }
00218 
00219 ompl::msg::OutputHandlerFile::~OutputHandlerFile(void)
00220 {
00221     if (file_)
00222         if (fclose(file_) != 0)
00223             std::cerr << "Error closing logfile" << std::endl;
00224 }
00225 
00226 void ompl::msg::OutputHandlerFile::error(const std::string &text)
00227 {
00228     if (file_)
00229     {
00230         fprintf(file_, "Error:   %s\n", text.c_str());
00231         fflush(file_);
00232     }
00233 }
00234 
00235 void ompl::msg::OutputHandlerFile::warn(const std::string &text)
00236 {
00237     if (file_)
00238     {
00239         fprintf(file_, "Warning: %s\n", text.c_str());
00240         fflush(file_);
00241     }
00242 }
00243 
00244 void ompl::msg::OutputHandlerFile::inform(const std::string &text)
00245 {
00246     if (file_)
00247     {
00248         fprintf(file_, "Info:    %s\n", text.c_str());
00249         fflush(file_);
00250     }
00251 }
00252 
00253 void ompl::msg::OutputHandlerFile::debug(const std::string &text)
00254 {
00255     if (file_)
00256     {
00257         fprintf(file_, "Debug:   %s\n", text.c_str());
00258         fflush(file_);
00259     }
00260 }