libmoost
/home/mhx/git/github/libmoost/include/moost/utils/demangler.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef MOOST_UTILS_DEMANGLER_HPP__
00029 #define MOOST_UTILS_DEMANGLER_HPP__
00030 
00031 #include <cstring>
00032 #include <string>
00033 
00045 #if (!defined(NDEBUG) || defined(DEMANGLE_NAMES)) && defined(__GNUG__)
00046 #define DEMANGLE_NAMES___
00047 #endif
00048 
00049 #ifdef DEMANGLE_NAMES___
00050 #include <cxxabi.h>
00051 #include "scope_exit.hpp"
00052 #endif
00053 
00054 namespace moost { namespace utils {
00055 
00056    inline
00057       std::string demangle_name(char const * name)
00058    {
00059 #ifdef DEMANGLE_NAMES___
00060       int status = -1;
00061       moost::utils::scope_exit::type<char>::free_malloc res(
00062          abi::__cxa_demangle(name, NULL, NULL, &status)
00063          );
00064       return (status==0)?res->get():name;
00065 #else
00066       return name;
00067 #endif
00068    }
00069 }}
00070 
00071 #ifdef DEMANGLE_NAMES___
00072 
00073 #define DEMANGLE_NAME(name) \
00074    moost::utils::demangle_name(name)
00075 
00076 #else
00077 
00078 #define DEMANGLE_NAME(name) name
00079 
00080 #endif
00081 
00096 namespace moost { namespace utils {
00097    inline
00098       std::string short_function_name(char const * name)
00099    {
00100       // [31/3/2011 ricky] I'm using nasty C string functions here to delay as much as I can the assignment to string
00101       //                   I could just assign to the string then use standard string::find and string::substr/resize
00102       //                   but this is a sub-optimal approach as it will involve more copying and memory usage. This
00103       //                   may not be pretty but it should be quicker.
00104 
00105       // Find the functions opening parameter
00106       char const * end = strchr(name, '(');
00107       char const * start = end;
00108       bool shorterned = false;
00109 
00110       // Find the start of the function name
00111 
00112       if(end)
00113       {
00114          size_t bcnt = 0;
00115          bool start_parse = false;
00116          bool end_tplate = false;
00117 
00118          // we now need to parse back from where we think the function name
00119          // starts to find where it actually starts and where it actually ends.
00120          while(!shorterned && --start!=name)
00121          {
00122             // first of all, there could be space that we should just skip
00123             if(!start_parse)
00124             {
00125                // so far we've only seen white space so we're gonna skip it
00126                start_parse = 0 == isspace(*start);
00127             }
00128 
00129             if(start_parse)
00130             {
00131                // all white space skipped, now let's try and find the start and end of this function name
00132                switch(*start)
00133                {
00134                case '>':
00135                   // we seem to be in a template so we'll skil until it's closed.
00136                   ++ bcnt;
00137                   break;
00138                case '<':
00139                   // when bcnt == 0 we're at the end of all the function template stuff
00140                   if(0 == --bcnt && !end_tplate)
00141                   {
00142                      end = start; // this is the real end of the function name
00143                      end_tplate = true; // any more templates will be part of the class name (if this is a member function)
00144                   }
00145                   break;
00146                default:
00147                   // have we skipped over any template params and white space we don't care about?
00148                   if(isspace(*start) != 0&& 0 == bcnt)
00149                   {
00150                      // We have, job done -- we have a candidate:)
00151                      shorterned = true;
00152                   }
00153                   break;
00154                }
00155             }
00156          }
00157 
00158          // just make sure we didn't get here and failed to find a start and end (if start == name we failed).
00159          shorterned = (start!=name);
00160       }
00161 
00162       // If we found the short name return it otherwise return the original
00163       return shorterned ? std::string(start+1, end - start - 1) : std::string(name); // hopefully NRVO will optimise this return by value
00164    }
00165 
00166 }}
00167 
00168 #endif // MOOST_UTILS_DEMANGLER_HPP__