GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/util.h Lines: 30 31 96.8 %
Date: 2016-07-18 Branches: 74 116 63.8 %

Line Exec Source
1
#ifndef SRC_UTIL_H_
2
#define SRC_UTIL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "v8.h"
7
8
#include <assert.h>
9
#include <signal.h>
10
#include <stddef.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
14
#ifdef __APPLE__
15
#include <tr1/type_traits>  // NOLINT(build/c++tr1)
16
#else
17
#include <type_traits>  // std::remove_reference
18
#endif
19
20
namespace node {
21
22
#ifdef __GNUC__
23
#define NO_RETURN __attribute__((noreturn))
24
#else
25
#define NO_RETURN
26
#endif
27
28
// The slightly odd function signature for Assert() is to ease
29
// instruction cache pressure in calls from ASSERT and CHECK.
30
NO_RETURN void Abort();
31
NO_RETURN void Assert(const char* const (*args)[4]);
32
void DumpBacktrace(FILE* fp);
33
34
#ifdef __APPLE__
35
template <typename T> using remove_reference = std::tr1::remove_reference<T>;
36
#else
37
template <typename T> using remove_reference = std::remove_reference<T>;
38
#endif
39
40
#define FIXED_ONE_BYTE_STRING(isolate, string)                                \
41
  (node::OneByteString((isolate), (string), sizeof(string) - 1))
42
43
#define DISALLOW_COPY_AND_ASSIGN(TypeName)                                    \
44
  void operator=(const TypeName&) = delete;                                   \
45
  void operator=(TypeName&&) = delete;                                        \
46
  TypeName(const TypeName&) = delete;                                         \
47
  TypeName(TypeName&&) = delete
48
49
// Windows 8+ does not like abort() in Release mode
50
#ifdef _WIN32
51
#define ABORT_NO_BACKTRACE() raise(SIGABRT)
52
#else
53
#define ABORT_NO_BACKTRACE() abort()
54
#endif
55
56
#define ABORT() node::Abort()
57
58
#ifdef __GNUC__
59
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
60
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
61
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
62
#else
63
#define LIKELY(expr) expr
64
#define UNLIKELY(expr) expr
65
#define PRETTY_FUNCTION_NAME ""
66
#endif
67
68
#define STRINGIFY_(x) #x
69
#define STRINGIFY(x) STRINGIFY_(x)
70
71
#define CHECK(expr)                                                           \
72
  do {                                                                        \
73
    if (UNLIKELY(!(expr))) {                                                  \
74
      static const char* const args[] = { __FILE__, STRINGIFY(__LINE__),      \
75
                                          #expr, PRETTY_FUNCTION_NAME };      \
76
      node::Assert(&args);                                                    \
77
    }                                                                         \
78
  } while (0)
79
80
// FIXME(bnoordhuis) cctests don't link in node::Abort() and node::Assert().
81
#ifdef GTEST_DONT_DEFINE_ASSERT_EQ
82
#undef ABORT
83
#undef CHECK
84
#define ABORT ABORT_NO_BACKTRACE
85
#define CHECK assert
86
#endif
87
88
#ifdef NDEBUG
89
#define ASSERT(expr)
90
#else
91
#define ASSERT(expr) CHECK(expr)
92
#endif
93
94
#define ASSERT_EQ(a, b) ASSERT((a) == (b))
95
#define ASSERT_GE(a, b) ASSERT((a) >= (b))
96
#define ASSERT_GT(a, b) ASSERT((a) > (b))
97
#define ASSERT_LE(a, b) ASSERT((a) <= (b))
98
#define ASSERT_LT(a, b) ASSERT((a) < (b))
99
#define ASSERT_NE(a, b) ASSERT((a) != (b))
100
101
#define CHECK_EQ(a, b) CHECK((a) == (b))
102
#define CHECK_GE(a, b) CHECK((a) >= (b))
103
#define CHECK_GT(a, b) CHECK((a) > (b))
104
#define CHECK_LE(a, b) CHECK((a) <= (b))
105
#define CHECK_LT(a, b) CHECK((a) < (b))
106
#define CHECK_NE(a, b) CHECK((a) != (b))
107
108
#define UNREACHABLE() ABORT()
109
110
#define ASSIGN_OR_RETURN_UNWRAP(ptr, obj, ...)                                \
111
  do {                                                                        \
112
    *ptr =                                                                    \
113
        Unwrap<typename node::remove_reference<decltype(**ptr)>::type>(obj);  \
114
    if (*ptr == nullptr)                                                      \
115
      return __VA_ARGS__;                                                     \
116
  } while (0)
117
118
// TAILQ-style intrusive list node.
119
template <typename T>
120
class ListNode;
121
122
template <typename T>
123
using ListNodeMember = ListNode<T> T::*;
124
125
// VS 2013 doesn't understand dependent templates.
126
#ifdef _MSC_VER
127
#define ListNodeMember(T) ListNodeMember
128
#else
129
#define ListNodeMember(T) ListNodeMember<T>
130
#endif
131
132
// TAILQ-style intrusive list head.
133
template <typename T, ListNodeMember(T) M>
134
class ListHead;
135
136
template <typename T>
137
class ListNode {
138
 public:
139
  inline ListNode();
140
  inline ~ListNode();
141
  inline void Remove();
142
  inline bool IsEmpty() const;
143
144
 private:
145
  template <typename U, ListNodeMember(U) M> friend class ListHead;
146
  ListNode* prev_;
147
  ListNode* next_;
148
  DISALLOW_COPY_AND_ASSIGN(ListNode);
149
};
150
151
template <typename T, ListNodeMember(T) M>
152
class ListHead {
153
 public:
154
  class Iterator {
155
   public:
156
    inline T* operator*() const;
157
    inline const Iterator& operator++();
158
    inline bool operator!=(const Iterator& that) const;
159
160
   private:
161
    friend class ListHead;
162
    inline explicit Iterator(ListNode<T>* node);
163
    ListNode<T>* node_;
164
  };
165
166
16528
  inline ListHead() = default;
167
  inline ~ListHead();
168
  inline void MoveBack(ListHead* that);
169
  inline void PushBack(T* element);
170
  inline void PushFront(T* element);
171
  inline bool IsEmpty() const;
172
  inline T* PopFront();
173
  inline Iterator begin() const;
174
  inline Iterator end() const;
175
176
 private:
177
  ListNode<T> head_;
178
  DISALLOW_COPY_AND_ASSIGN(ListHead);
179
};
180
181
// The helper is for doing safe downcasts from base types to derived types.
182
template <typename Inner, typename Outer>
183
class ContainerOfHelper {
184
 public:
185
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
186
  template <typename TypeName>
187
  inline operator TypeName*() const;
188
 private:
189
  Outer* const pointer_;
190
};
191
192
// Calculate the address of the outer (i.e. embedding) struct from
193
// the interior pointer to a data member.
194
template <typename Inner, typename Outer>
195
inline ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
196
                                                   Inner* pointer);
197
198
// If persistent.IsWeak() == false, then do not call persistent.Reset()
199
// while the returned Local<T> is still in scope, it will destroy the
200
// reference to the object.
201
template <class TypeName>
202
inline v8::Local<TypeName> PersistentToLocal(
203
    v8::Isolate* isolate,
204
    const v8::Persistent<TypeName>& persistent);
205
206
// Unchecked conversion from a non-weak Persistent<T> to Local<TLocal<T>,
207
// use with care!
208
//
209
// Do not call persistent.Reset() while the returned Local<T> is still in
210
// scope, it will destroy the reference to the object.
211
template <class TypeName>
212
inline v8::Local<TypeName> StrongPersistentToLocal(
213
    const v8::Persistent<TypeName>& persistent);
214
215
template <class TypeName>
216
inline v8::Local<TypeName> WeakPersistentToLocal(
217
    v8::Isolate* isolate,
218
    const v8::Persistent<TypeName>& persistent);
219
220
// Convenience wrapper around v8::String::NewFromOneByte().
221
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
222
                                           const char* data,
223
                                           int length = -1);
224
225
// For the people that compile with -funsigned-char.
226
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
227
                                           const signed char* data,
228
                                           int length = -1);
229
230
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
231
                                           const unsigned char* data,
232
                                           int length = -1);
233
234
inline void Wrap(v8::Local<v8::Object> object, void* pointer);
235
236
inline void ClearWrap(v8::Local<v8::Object> object);
237
238
template <typename TypeName>
239
inline TypeName* Unwrap(v8::Local<v8::Object> object);
240
241
inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen);
242
243
// tolower() is locale-sensitive.  Use ToLower() instead.
244
inline char ToLower(char c);
245
246
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
247
inline bool StringEqualNoCase(const char* a, const char* b);
248
249
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
250
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
251
252
// Allocates an array of member type T. For up to kStackStorageSize items,
253
// the stack is used, otherwise malloc().
254
template <typename T, size_t kStackStorageSize = 1024>
255
class MaybeStackBuffer {
256
 public:
257
  const T* out() const {
258
    return buf_;
259
  }
260
261
  T* out() {
262
    return buf_;
263
  }
264
265
  // operator* for compatibility with `v8::String::(Utf8)Value`
266
  T* operator*() {
267
    return buf_;
268
  }
269
270
  const T* operator*() const {
271
    return buf_;
272
  }
273
274
  T& operator[](size_t index) {
275
804
    CHECK_LT(index, length());
276
804
    return buf_[index];
277
  }
278
279
  const T& operator[](size_t index) const {
280
    CHECK_LT(index, length());
281
    return buf_[index];
282
  }
283
284
  size_t length() const {
285
    return length_;
286
  }
287
288
  // Call to make sure enough space for `storage` entries is available.
289
  // There can only be 1 call to AllocateSufficientStorage or Invalidate
290
  // per instance.
291
239268
  void AllocateSufficientStorage(size_t storage) {
292
239268
    if (storage <= kStackStorageSize) {
293
239131
      buf_ = buf_st_;
294
    } else {
295
      // Guard against overflow.
296
      CHECK_LE(storage, sizeof(T) * storage);
297
298
137
      buf_ = static_cast<T*>(malloc(sizeof(T) * storage));
299
137
      CHECK_NE(buf_, nullptr);
300
    }
301
302
    // Remember how much was allocated to check against that in SetLength().
303
239268
    length_ = storage;
304
239268
  }
305
306
  void SetLength(size_t length) {
307
    // length_ stores how much memory was allocated.
308
237487
    CHECK_LE(length, length_);
309
237487
    length_ = length;
310
  }
311
312
237138
  void SetLengthAndZeroTerminate(size_t length) {
313
    // length_ stores how much memory was allocated.
314
237138
    CHECK_LE(length + 1, length_);
315
474276
    SetLength(length);
316
317
    // T() is 0 for integer types, nullptr for pointers, etc.
318
237138
    buf_[length] = T();
319
237138
  }
320
321
  // Make derefencing this object return nullptr.
322
  // Calling this is mutually exclusive with calling
323
  // AllocateSufficientStorage.
324
  void Invalidate() {
325
4
    CHECK_EQ(buf_, buf_st_);
326
4
    length_ = 0;
327
4
    buf_ = nullptr;
328
  }
329
330
240281
  MaybeStackBuffer() : length_(0), buf_(buf_st_) {
331
    // Default to a zero-length, null-terminated buffer.
332
240281
    buf_[0] = T();
333
  }
334
335
82
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
336
82
    AllocateSufficientStorage(storage);
337
  }
338
339
  ~MaybeStackBuffer() {
340
240281
    if (buf_ != buf_st_)
341
141
      free(buf_);
342
240281
  }
343
344
 private:
345
  size_t length_;
346
  T* buf_;
347
  T buf_st_[kStackStorageSize];
348
};
349
350
398738
class Utf8Value : public MaybeStackBuffer<char> {
351
 public:
352
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
353
};
354
355
66
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
356
 public:
357
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
358
};
359
360
76579
class BufferValue : public MaybeStackBuffer<char> {
361
 public:
362
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
363
};
364
365
}  // namespace node
366
367
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
368
369
#endif  // SRC_UTIL_H_