GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: debug_utils-inl.h Lines: 74 79 93.7 %
Date: 2021-09-16 04:12:46 Branches: 187 255 73.3 %

Line Branch Exec Source
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
#include "env.h"
8
9
#include <type_traits>
10
11
namespace node {
12
13
struct ToStringHelper {
14
  template <typename T>
15
827
  static std::string Convert(
16
      const T& value,
17
      std::string(T::* to_string)() const = &T::ToString) {
18
827
    return (value.*to_string)();
19
  }
20
  template <typename T,
21
            typename test_for_number = typename std::
22
                enable_if<std::is_arithmetic<T>::value, bool>::type,
23
            typename dummy = bool>
24
13694
  static std::string Convert(const T& value) { return std::to_string(value); }
25
2549
  static std::string Convert(const char* value) {
26
2549
    return value != nullptr ? value : "(null)";
27
  }
28
5342
  static std::string Convert(const std::string& value) { return value; }
29
53
  static std::string Convert(bool value) { return value ? "true" : "false"; }
30
  template <unsigned BASE_BITS,
31
            typename T,
32
            typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
33
12
  static std::string BaseConvert(const T& value) {
34
12
    auto v = static_cast<uint64_t>(value);
35
    char ret[3 * sizeof(T)];
36
12
    char* ptr = ret + 3 * sizeof(T) - 1;
37
12
    *ptr = '\0';
38
12
    const char* digits = "0123456789abcdef";
39
6
    do {
40
18
      unsigned digit = v & ((1 << BASE_BITS) - 1);
41
24
      *--ptr =
42
12
          (BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]);
43
18
    } while ((v >>= BASE_BITS) != 0);
44
12
    return ptr;
45
  }
46
  template <unsigned BASE_BITS,
47
            typename T,
48
            typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
49
  static std::string BaseConvert(T value) {
50
    return Convert(std::forward<T>(value));
51
  }
52
};
53
54
template <typename T>
55
23750
std::string ToString(const T& value) {
56
23750
  return ToStringHelper::Convert(value);
57
}
58
59
template <unsigned BASE_BITS, typename T>
60
12
std::string ToBaseString(const T& value) {
61
12
  return ToStringHelper::BaseConvert<BASE_BITS>(value);
62
}
63
64
9119
inline std::string SPrintFImpl(const char* format) {
65
9119
  const char* p = strchr(format, '%');
66
9119
  if (LIKELY(p == nullptr)) return format;
67
1
  CHECK_EQ(p[1], '%');  // Only '%%' allowed when there are no arguments.
68
69
1
  return std::string(format, p + 1) + SPrintFImpl(p + 2);
70
}
71
72
template <typename Arg, typename... Args>
73
29823
std::string COLD_NOINLINE SPrintFImpl(  // NOLINT(runtime/string)
74
    const char* format, Arg&& arg, Args&&... args) {
75
29823
  const char* p = strchr(format, '%');
76
29823
  CHECK_NOT_NULL(p);  // If you hit this, you passed in too many arguments.
77
89469
  std::string ret(format, p);
78
  // Ignore long / size_t modifiers
79
29945
  while (strchr("lz", *++p) != nullptr) {}
80

29823
  switch (*p) {
81
2
    case '%': {
82
      return ret + '%' + SPrintFImpl(p + 1,
83
                                     std::forward<Arg>(arg),
84
2
                                     std::forward<Args>(args)...);
85
    }
86
    default: {
87
      return ret + '%' + SPrintFImpl(p,
88
                                     std::forward<Arg>(arg),
89
                                     std::forward<Args>(args)...);
90
    }
91
29805
    case 'd':
92
    case 'i':
93
    case 'u':
94
    case 's':
95
29805
      ret += ToString(arg);
96
29805
      break;
97
4
    case 'o':
98
4
      ret += ToBaseString<3>(arg);
99
4
      break;
100
4
    case 'x':
101
4
      ret += ToBaseString<4>(arg);
102
4
      break;
103
4
    case 'X':
104
4
      ret += node::ToUpper(ToBaseString<4>(arg));
105
4
      break;
106
4
    case 'p': {
107
      CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value);
108
      char out[20];
109
4
      int n = snprintf(out,
110
                       sizeof(out),
111
                       "%p",
112
                       *reinterpret_cast<const void* const*>(&arg));
113
4
      CHECK_GE(n, 0);
114
4
      ret += out;
115
4
      break;
116
    }
117
  }
118
29821
  return ret + SPrintFImpl(p + 1, std::forward<Args>(args)...);
119
}
120
121
template <typename... Args>
122
11822
std::string COLD_NOINLINE SPrintF(  // NOLINT(runtime/string)
123
    const char* format, Args&&... args) {
124
11822
  return SPrintFImpl(format, std::forward<Args>(args)...);
125
}
126
127
template <typename... Args>
128
4690
void COLD_NOINLINE FPrintF(FILE* file, const char* format, Args&&... args) {
129
4690
  FWrite(file, SPrintF(format, std::forward<Args>(args)...));
130
4690
}
131
132
template <typename... Args>
133
inline void FORCE_INLINE Debug(EnabledDebugList* list,
134
                               DebugCategory cat,
135
                               const char* format,
136
                               Args&&... args) {
137




















103605
  if (!UNLIKELY(list->enabled(cat))) return;
138
945
  FPrintF(stderr, format, std::forward<Args>(args)...);
139
}
140
141
inline void FORCE_INLINE Debug(EnabledDebugList* list,
142
                               DebugCategory cat,
143
                               const char* message) {
144

5491
  if (!UNLIKELY(list->enabled(cat))) return;
145
75
  FPrintF(stderr, "%s", message);
146
}
147
148
template <typename... Args>
149
inline void FORCE_INLINE
150
Debug(Environment* env, DebugCategory cat, const char* format, Args&&... args) {
151
72242
  Debug(env->enabled_debug_list(), cat, format, std::forward<Args>(args)...);
152
}
153
154
inline void FORCE_INLINE Debug(Environment* env,
155
                               DebugCategory cat,
156
                               const char* message) {
157
10896
  Debug(env->enabled_debug_list(), cat, message);
158
}
159
160
template <typename... Args>
161
236
inline void Debug(Environment* env,
162
                  DebugCategory cat,
163
                  const std::string& format,
164
                  Args&&... args) {
165
236
  Debug(env->enabled_debug_list(),
166
        cat,
167
        format.c_str(),
168
        std::forward<Args>(args)...);
169
}
170
171
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that
172
// the FORCE_INLINE flag on them doesn't apply to the contents of this function
173
// as well.
174
// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing
175
// this function for speed and it should rather focus on keeping it out of
176
// hot code paths. In particular, we want to keep the string concatenating code
177
// out of the function containing the original `Debug()` call.
178
template <typename... Args>
179
236
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
180
                                               const char* format,
181
                                               Args&&... args) {
182
622
  Debug(async_wrap->env(),
183
236
        static_cast<DebugCategory>(async_wrap->provider_type()),
184
236
        async_wrap->diagnostic_name() + " " + format + "\n",
185
        std::forward<Args>(args)...);
186
}
187
188
template <typename... Args>
189
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
190
                               const char* format,
191
                               Args&&... args) {
192
  DCHECK_NOT_NULL(async_wrap);
193
1224342
  DebugCategory cat = static_cast<DebugCategory>(async_wrap->provider_type());
194




































1224342
  if (!UNLIKELY(async_wrap->env()->enabled_debug_list()->enabled(cat))) return;
195
118
  UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...);
196
}
197
198
template <typename... Args>
199
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
200
                               const std::string& format,
201
                               Args&&... args) {
202
  Debug(async_wrap, format.c_str(), std::forward<Args>(args)...);
203
}
204
205
namespace per_process {
206
207
template <typename... Args>
208
inline void FORCE_INLINE Debug(DebugCategory cat,
209
                               const char* format,
210
                               Args&&... args) {
211
31284
  Debug(&enabled_debug_list, cat, format, std::forward<Args>(args)...);
212
}
213
214
inline void FORCE_INLINE Debug(DebugCategory cat, const char* message) {
215
  Debug(&enabled_debug_list, cat, message);
216
}
217
218
}  // namespace per_process
219
}  // namespace node
220
221
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
222
223
#endif  // SRC_DEBUG_UTILS_INL_H_