log.cpp
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2013, Johannes Meyer, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Flight Systems and Automatic Control group,
00013 //       TU Darmstadt, nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //=================================================================================================
00028 
00029 #include <mex.h>
00030 #include <rosmatlab/log.h>
00031 #include <rosmatlab/exception.h>
00032 #include <rosmatlab/options.h>
00033 
00034 #include <ros/console.h>
00035 #include <boost/algorithm/string.hpp>
00036 #include <cstdarg>
00037 #include <boost/shared_array.hpp>
00038 
00039 namespace rosmatlab {
00040 namespace log {
00041 
00042 #define INITIAL_BUFFER_SIZE 4096
00043 static boost::shared_array<char> g_print_buffer(new char[INITIAL_BUFFER_SIZE]);
00044 static size_t g_print_buffer_size = INITIAL_BUFFER_SIZE;
00045 
00046 static bool getLevel(const std::string& str, Level &level) {
00047   if (boost::iequals(str, "debug")) { level = Debug; return true; }
00048   if (boost::iequals(str, "info"))  { level = Info;  return true; }
00049   if (boost::iequals(str, "warn"))  { level = Warn;  return true; }
00050   if (boost::iequals(str, "error")) { level = Error; return true; }
00051   if (boost::iequals(str, "fatal")) { level = Fatal; return true; }
00052   return false;
00053 }
00054 
00055 static bool getLevel(double dbl, Level &level) {
00056   if (isnan(dbl)) return false;
00057   unsigned int i = static_cast<unsigned int>(dbl);
00058   if (i >= Count) return false;
00059   level = static_cast<Level>(i);
00060   return true;
00061 }
00062 
00063 void log(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
00064 {
00065   Level level = ::ros::console::levels::Info;
00066   std::string name;
00067   std::string message;
00068 
00069   // parse input arguments
00070   if (nrhs == 0) {
00071     return;
00072   } else if (nrhs == 1) {
00073     message = Options::getString(prhs[0]);
00074   } else if (nrhs == 2) {
00075     std::string arg1 = Options::getString(prhs[0]);
00076     if (!getLevel(arg1, level) && !getLevel(Options::getDoubleScalar(prhs[0]), level)) name = arg1;
00077     message = Options::getString(prhs[1]);
00078   } else if (nrhs > 2) {
00079     if (!getLevel(Options::getString(prhs[0]), level) && !getLevel(Options::getDoubleScalar(prhs[0]), level)) {
00080       throw Exception("Could not evaluate first argument as log level (Debug, Info, Warn, Error, Fatal)");
00081     }
00082     name = Options::getString(prhs[1]);
00083     message = Options::getString(prhs[2]);
00084   }
00085 
00086   log(level, name.c_str(), message.c_str());
00087 }
00088 
00089 void log(Level level, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
00090 {
00091   std::string name;
00092   std::string message;
00093 
00094   // parse input arguments
00095   if (nrhs == 0) {
00096     return;
00097   } else if (nrhs == 1) {
00098     message = Options::getString(prhs[0]);
00099   } else if (nrhs == 2) {
00100     name = Options::getString(prhs[0]);
00101     message = Options::getString(prhs[1]);
00102   }
00103 
00104   log(level, name.c_str(), message.c_str());
00105 }
00106 
00107 void log(Level level, const char *name, const char *fmt, ...)
00108 {
00109   std::string file;
00110   std::string function;
00111   int line = 0;
00112 
00113   va_list args;
00114   va_start(args, fmt);
00115   ros::console::vformatToBuffer(g_print_buffer, g_print_buffer_size, fmt, args);
00116   va_end(args);
00117   std::stringstream message(std::string(g_print_buffer.get()));
00118 
00119   // get stack information from matlab
00120   mxArray *stack;
00121   mexCallMATLAB(1, &stack, 0, 0, "dbstack");
00122   if (mxIsStruct(stack) && mxGetNumberOfElements(stack) > 0) {
00123     file     = Options::getString(mxGetField(stack, 0, "file"));
00124     function = Options::getString(mxGetField(stack, 0, "name"));
00125     line     = static_cast<int>(Options::getDoubleScalar(mxGetField(stack, 0, "line")));
00126   }
00127 
00128   // expand logger name
00129   std::string logger_name;
00130   if (name && strlen(name) > 0) {
00131     logger_name = std::string(ROSCONSOLE_DEFAULT_NAME) + "." + name;
00132   } else {
00133     logger_name = std::string(ROSCONSOLE_DEFAULT_NAME);
00134   }
00135 
00136   // ... and finally log the message!
00137   do {
00138     ROSCONSOLE_DEFINE_LOCATION(true, level, logger_name);
00139     if (ROS_UNLIKELY(enabled))
00140     {
00141       ::ros::console::print(0, loc.logger_, loc.level_, message, file.c_str(), line, function.c_str());
00142     }
00143 
00144     if (enabled) {
00145       static const std::string level_strings[] = { "Debug", "Info", "Warn", "Error", "Fatal" };
00146       std::stringstream output;
00147       output << "[" << level_strings[level] << "] [" << ros::WallTime::now() << "] " << message.str();
00148       mexPrintf(output.str().c_str());
00149       mexPrintf("\n");
00150     }
00151   } while(0);
00152 }
00153 
00154 } // namespace log
00155 } // namespace rosmatlab


rosmatlab
Author(s): Johannes Meyer
autogenerated on Fri Jul 25 2014 06:48:12