GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/debug_utils-inl.h Lines: 70 74 94.6 %
Date: 2020-06-24 22:13:30 Branches: 269 785 34.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
835
  static std::string Convert(
16
      const T& value,
17
      std::string(T::* to_string)() const = &T::ToString) {
18
835
    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
6180
  static std::string Convert(const T& value) { return std::to_string(value); }
25
2302
  static std::string Convert(const char* value) {
26
2302
    return value != nullptr ? value : "(null)";
27
  }
28
4836
  static std::string Convert(const std::string& value) { return value; }
29
5
  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
6
  static std::string BaseConvert(const T& value) {
34
6
    auto v = static_cast<uint64_t>(value);
35
    char ret[3 * sizeof(T)];
36
6
    char* ptr = ret + 3 * sizeof(T) - 1;
37
6
    *ptr = '\0';
38
6
    const char* digits = "0123456789abcdef";
39





9
    do {
40
9
      unsigned digit = v & ((1 << BASE_BITS) - 1);
41
12
      *--ptr =
42
3
          (BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]);
43
    } while ((v >>= BASE_BITS) != 0);
44
6
    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
14158
std::string ToString(const T& value) {
56
14158
  return ToStringHelper::Convert(value);
57
}
58
59
template <unsigned BASE_BITS, typename T>
60
6
std::string ToBaseString(const T& value) {
61
6
  return ToStringHelper::BaseConvert<BASE_BITS>(value);
62
}
63
64
7140
inline std::string SPrintFImpl(const char* format) {
65
7140
  const char* p = strchr(format, '%');
66
7140
  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
14167
std::string COLD_NOINLINE SPrintFImpl(  // NOLINT(runtime/string)
74
    const char* format, Arg&& arg, Args&&... args) {
75
14167
  const char* p = strchr(format, '%');
76























14167
  CHECK_NOT_NULL(p);  // If you hit this, you passed in too many arguments.
77
28334
  std::string ret(format, p);
78
  // Ignore long / size_t modifiers
79























14167
  while (strchr("lz", *++p) != nullptr) {}
80


















































































14167
  switch (*p) {
81
    case '%': {
82
      return ret + '%' + SPrintFImpl(p + 1,
83
                                     std::forward<Arg>(arg),
84
1
                                     std::forward<Args>(args)...);
85
    }
86
    default: {
87
      return ret + '%' + SPrintFImpl(p,
88
                                     std::forward<Arg>(arg),
89
                                     std::forward<Args>(args)...);
90
    }
91
    case 'd':
92
    case 'i':
93
    case 'u':
94
    case 's':
95
14158
      ret += ToString(arg);
96
14158
      break;
97
    case 'o':
98
2
      ret += ToBaseString<3>(arg);
99
2
      break;
100
    case 'x':
101
2
      ret += ToBaseString<4>(arg);
102
2
      break;
103
    case 'X':
104
2
      ret += node::ToUpper(ToBaseString<4>(arg));
105
2
      break;
106
    case 'p': {
107
      CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value);
108
      char out[20];
109
2
      int n = snprintf(out,
110
                       sizeof(out),
111
                       "%p",
112
2
                       *reinterpret_cast<const void* const*>(&arg));
113


2
      CHECK_GE(n, 0);
114
2
      ret += out;
115
2
      break;
116
    }
117
  }
118
14166
  return ret + SPrintFImpl(p + 1, std::forward<Args>(args)...);
119
}
120
121
template <typename... Args>
122
7139
std::string COLD_NOINLINE SPrintF(  // NOLINT(runtime/string)
123
    const char* format, Args&&... args) {
124
7139
  return SPrintFImpl(format, std::forward<Args>(args)...);
125
}
126
127
template <typename... Args>
128
1829
void COLD_NOINLINE FPrintF(FILE* file, const char* format, Args&&... args) {
129
1829
  FWrite(file, SPrintF(format, std::forward<Args>(args)...));
130
1829
}
131
132
template <typename... Args>
133
inline void FORCE_INLINE Debug(EnabledDebugList* list,
134
                               DebugCategory cat,
135
                               const char* format,
136
                               Args&&... args) {
137




















45219
  if (!UNLIKELY(list->enabled(cat))) return;
138
597
  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


9436
  if (!UNLIKELY(list->enabled(cat))) return;
145
99
  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
44957
  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
9390
  Debug(env->enabled_debug_list(), cat, message);
158
}
159
160
template <typename... Args>
161
127
inline void Debug(Environment* env,
162
                  DebugCategory cat,
163
                  const std::string& format,
164
                  Args&&... args) {
165
127
  Debug(env->enabled_debug_list(),
166
        cat,
167
        format.c_str(),
168
        std::forward<Args>(args)...);
169
127
}
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
127
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
180
                                               const char* format,
181
                                               Args&&... args) {
182
336
  Debug(async_wrap->env(),
183
127
        static_cast<DebugCategory>(async_wrap->provider_type()),
184
127
        async_wrap->diagnostic_name() + " " + format + "\n",
185
        std::forward<Args>(args)...);
186
127
}
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
1191531
  DebugCategory cat = static_cast<DebugCategory>(async_wrap->provider_type());
194


































1191531
  if (!UNLIKELY(async_wrap->env()->enabled_debug_list()->enabled(cat))) return;
195

127
  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
180
  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_