libmoost
|
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__