|  | 
|  | 1 | +#ifndef SRC_DEBUG_UTILS_INL_H_ | 
|  | 2 | +#define SRC_DEBUG_UTILS_INL_H_ | 
|  | 3 | + | 
|  | 4 | +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | 
|  | 5 | + | 
|  | 6 | +#include "debug_utils.h" | 
|  | 7 | + | 
|  | 8 | +#include <type_traits> | 
|  | 9 | + | 
|  | 10 | +namespace node { | 
|  | 11 | + | 
|  | 12 | +struct ToStringHelper { | 
|  | 13 | +  template <typename T> | 
|  | 14 | +  static std::string Convert( | 
|  | 15 | +      const T& value, | 
|  | 16 | +      std::string(T::* to_string)() const = &T::ToString) { | 
|  | 17 | +    return (value.*to_string)(); | 
|  | 18 | +  } | 
|  | 19 | +  template <typename T, | 
|  | 20 | +            typename test_for_number = typename std:: | 
|  | 21 | +                enable_if<std::is_arithmetic<T>::value, bool>::type, | 
|  | 22 | +            typename dummy = bool> | 
|  | 23 | +  static std::string Convert(const T& value) { return std::to_string(value); } | 
|  | 24 | +  static std::string Convert(const char* value) { return value; } | 
|  | 25 | +  static std::string Convert(const std::string& value) { return value; } | 
|  | 26 | +  static std::string Convert(bool value) { return value ? "true" : "false"; } | 
|  | 27 | +}; | 
|  | 28 | + | 
|  | 29 | +template <typename T> | 
|  | 30 | +std::string ToString(const T& value) { | 
|  | 31 | +  return ToStringHelper::Convert(value); | 
|  | 32 | +} | 
|  | 33 | + | 
|  | 34 | +inline std::string SPrintFImpl(const char* format) { | 
|  | 35 | +  const char* p = strchr(format, '%'); | 
|  | 36 | +  if (LIKELY(p == nullptr)) return format; | 
|  | 37 | +  CHECK_EQ(p[1], '%');  // Only '%%' allowed when there are no arguments. | 
|  | 38 | + | 
|  | 39 | +  return std::string(format, p + 1) + SPrintFImpl(p + 2); | 
|  | 40 | +} | 
|  | 41 | + | 
|  | 42 | +template <typename Arg, typename... Args> | 
|  | 43 | +std::string COLD_NOINLINE SPrintFImpl(  // NOLINT(runtime/string) | 
|  | 44 | +    const char* format, Arg&& arg, Args&&... args) { | 
|  | 45 | +  const char* p = strchr(format, '%'); | 
|  | 46 | +  CHECK_NOT_NULL(p);  // If you hit this, you passed in too many arguments. | 
|  | 47 | +  std::string ret(format, p); | 
|  | 48 | +  // Ignore long / size_t modifiers | 
|  | 49 | +  while (strchr("lz", *++p) != nullptr) {} | 
|  | 50 | +  switch (*p) { | 
|  | 51 | +    case '%': { | 
|  | 52 | +      return ret + '%' + SPrintFImpl(p + 1, | 
|  | 53 | +                                     std::forward<Arg>(arg), | 
|  | 54 | +                                     std::forward<Args>(args)...); | 
|  | 55 | +    } | 
|  | 56 | +    default: { | 
|  | 57 | +      return ret + '%' + SPrintFImpl(p, | 
|  | 58 | +                                     std::forward<Arg>(arg), | 
|  | 59 | +                                     std::forward<Args>(args)...); | 
|  | 60 | +    } | 
|  | 61 | +    case 'd': | 
|  | 62 | +    case 'i': | 
|  | 63 | +    case 'u': | 
|  | 64 | +    case 's': ret += ToString(arg); break; | 
|  | 65 | +    case 'p': { | 
|  | 66 | +      CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value); | 
|  | 67 | +      char out[20]; | 
|  | 68 | +      int n = snprintf(out, | 
|  | 69 | +                       sizeof(out), | 
|  | 70 | +                       "%p", | 
|  | 71 | +                       *reinterpret_cast<const void* const*>(&arg)); | 
|  | 72 | +      CHECK_GE(n, 0); | 
|  | 73 | +      ret += out; | 
|  | 74 | +      break; | 
|  | 75 | +    } | 
|  | 76 | +  } | 
|  | 77 | +  return ret + SPrintFImpl(p + 1, std::forward<Args>(args)...); | 
|  | 78 | +} | 
|  | 79 | + | 
|  | 80 | +template <typename... Args> | 
|  | 81 | +std::string COLD_NOINLINE SPrintF(  // NOLINT(runtime/string) | 
|  | 82 | +    const char* format, Args&&... args) { | 
|  | 83 | +  return SPrintFImpl(format, std::forward<Args>(args)...); | 
|  | 84 | +} | 
|  | 85 | + | 
|  | 86 | +}  // namespace node | 
|  | 87 | + | 
|  | 88 | +#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | 
|  | 89 | + | 
|  | 90 | +#endif  // SRC_DEBUG_UTILS_INL_H_ | 
0 commit comments