The C and C++ Include Header Files
/usr/include/nodejs/src/util-inl.h
$ cat -n /usr/include/nodejs/src/util-inl.h 1 // Copyright Joyent, Inc. and other Node contributors. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to permit 8 // persons to whom the Software is furnished to do so, subject to the 9 // following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SRC_UTIL_INL_H_ 23 #define SRC_UTIL_INL_H_ 24 25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 26 27 #include
28 #include
29 #include "util.h" 30 31 // These are defined by
or
on some systems. 32 // To avoid warnings, undefine them before redefining them. 33 #ifdef BSWAP_2 34 # undef BSWAP_2 35 #endif 36 #ifdef BSWAP_4 37 # undef BSWAP_4 38 #endif 39 #ifdef BSWAP_8 40 # undef BSWAP_8 41 #endif 42 43 #if defined(_MSC_VER) 44 #include
45 #define BSWAP_2(x) _byteswap_ushort(x) 46 #define BSWAP_4(x) _byteswap_ulong(x) 47 #define BSWAP_8(x) _byteswap_uint64(x) 48 #else 49 #define BSWAP_2(x) ((x) << 8) | ((x) >> 8) 50 #define BSWAP_4(x) \ 51 (((x) & 0xFF) << 24) | \ 52 (((x) & 0xFF00) << 8) | \ 53 (((x) >> 8) & 0xFF00) | \ 54 (((x) >> 24) & 0xFF) 55 #define BSWAP_8(x) \ 56 (((x) & 0xFF00000000000000ull) >> 56) | \ 57 (((x) & 0x00FF000000000000ull) >> 40) | \ 58 (((x) & 0x0000FF0000000000ull) >> 24) | \ 59 (((x) & 0x000000FF00000000ull) >> 8) | \ 60 (((x) & 0x00000000FF000000ull) << 8) | \ 61 (((x) & 0x0000000000FF0000ull) << 24) | \ 62 (((x) & 0x000000000000FF00ull) << 40) | \ 63 (((x) & 0x00000000000000FFull) << 56) 64 #endif 65 66 namespace node { 67 68 template
69 ListNode
::ListNode() : prev_(this), next_(this) {} 70 71 template
72 ListNode
::~ListNode() { 73 Remove(); 74 } 75 76 template
77 void ListNode
::Remove() { 78 prev_->next_ = next_; 79 next_->prev_ = prev_; 80 prev_ = this; 81 next_ = this; 82 } 83 84 template
85 bool ListNode
::IsEmpty() const { 86 return prev_ == this; 87 } 88 89 template
(T::*M)> 90 ListHead
::Iterator::Iterator(ListNode
* node) : node_(node) {} 91 92 template
(T::*M)> 93 T* ListHead
::Iterator::operator*() const { 94 return ContainerOf(M, node_); 95 } 96 97 template
(T::*M)> 98 const typename ListHead
::Iterator& 99 ListHead
::Iterator::operator++() { 100 node_ = node_->next_; 101 return *this; 102 } 103 104 template
(T::*M)> 105 bool ListHead
::Iterator::operator!=(const Iterator& that) const { 106 return node_ != that.node_; 107 } 108 109 template
(T::*M)> 110 ListHead
::~ListHead() { 111 while (IsEmpty() == false) 112 head_.next_->Remove(); 113 } 114 115 template
(T::*M)> 116 void ListHead
::PushBack(T* element) { 117 ListNode
* that = &(element->*M); 118 head_.prev_->next_ = that; 119 that->prev_ = head_.prev_; 120 that->next_ = &head_; 121 head_.prev_ = that; 122 } 123 124 template
(T::*M)> 125 void ListHead
::PushFront(T* element) { 126 ListNode
* that = &(element->*M); 127 head_.next_->prev_ = that; 128 that->prev_ = &head_; 129 that->next_ = head_.next_; 130 head_.next_ = that; 131 } 132 133 template
(T::*M)> 134 bool ListHead
::IsEmpty() const { 135 return head_.IsEmpty(); 136 } 137 138 template
(T::*M)> 139 T* ListHead
::PopFront() { 140 if (IsEmpty()) 141 return nullptr; 142 ListNode
* node = head_.next_; 143 node->Remove(); 144 return ContainerOf(M, node); 145 } 146 147 template
(T::*M)> 148 typename ListHead
::Iterator ListHead
::begin() const { 149 return Iterator(head_.next_); 150 } 151 152 template
(T::*M)> 153 typename ListHead
::Iterator ListHead
::end() const { 154 return Iterator(const_cast
*>(&head_)); 155 } 156 157 template
158 constexpr uintptr_t OffsetOf(Inner Outer::*field) { 159 return reinterpret_cast
(&(static_cast
(nullptr)->*field)); 160 } 161 162 template
163 ContainerOfHelper
::ContainerOfHelper(Inner Outer::*field, 164 Inner* pointer) 165 : pointer_( 166 reinterpret_cast
( 167 reinterpret_cast
(pointer) - OffsetOf(field))) {} 168 169 template
170 template
171 ContainerOfHelper
::operator TypeName*() const { 172 return static_cast
(pointer_); 173 } 174 175 template
176 constexpr ContainerOfHelper
ContainerOf(Inner Outer::*field, 177 Inner* pointer) { 178 return ContainerOfHelper
(field, pointer); 179 } 180 181 inline v8::Local
OneByteString(v8::Isolate* isolate, 182 const char* data, 183 int length) { 184 return v8::String::NewFromOneByte(isolate, 185 reinterpret_cast
(data), 186 v8::NewStringType::kNormal, 187 length).ToLocalChecked(); 188 } 189 190 inline v8::Local
OneByteString(v8::Isolate* isolate, 191 const signed char* data, 192 int length) { 193 return v8::String::NewFromOneByte(isolate, 194 reinterpret_cast
(data), 195 v8::NewStringType::kNormal, 196 length).ToLocalChecked(); 197 } 198 199 inline v8::Local
OneByteString(v8::Isolate* isolate, 200 const unsigned char* data, 201 int length) { 202 return v8::String::NewFromOneByte( 203 isolate, data, v8::NewStringType::kNormal, length) 204 .ToLocalChecked(); 205 } 206 207 void SwapBytes16(char* data, size_t nbytes) { 208 CHECK_EQ(nbytes % 2, 0); 209 210 #if defined(_MSC_VER) 211 int align = reinterpret_cast
(data) % sizeof(uint16_t); 212 if (align == 0) { 213 // MSVC has no strict aliasing, and is able to highly optimize this case. 214 uint16_t* data16 = reinterpret_cast
(data); 215 size_t len16 = nbytes / sizeof(*data16); 216 for (size_t i = 0; i < len16; i++) { 217 data16[i] = BSWAP_2(data16[i]); 218 } 219 return; 220 } 221 #endif 222 223 uint16_t temp; 224 for (size_t i = 0; i < nbytes; i += sizeof(temp)) { 225 memcpy(&temp, &data[i], sizeof(temp)); 226 temp = BSWAP_2(temp); 227 memcpy(&data[i], &temp, sizeof(temp)); 228 } 229 } 230 231 void SwapBytes32(char* data, size_t nbytes) { 232 CHECK_EQ(nbytes % 4, 0); 233 234 #if defined(_MSC_VER) 235 int align = reinterpret_cast
(data) % sizeof(uint32_t); 236 // MSVC has no strict aliasing, and is able to highly optimize this case. 237 if (align == 0) { 238 uint32_t* data32 = reinterpret_cast
(data); 239 size_t len32 = nbytes / sizeof(*data32); 240 for (size_t i = 0; i < len32; i++) { 241 data32[i] = BSWAP_4(data32[i]); 242 } 243 return; 244 } 245 #endif 246 247 uint32_t temp; 248 for (size_t i = 0; i < nbytes; i += sizeof(temp)) { 249 memcpy(&temp, &data[i], sizeof(temp)); 250 temp = BSWAP_4(temp); 251 memcpy(&data[i], &temp, sizeof(temp)); 252 } 253 } 254 255 void SwapBytes64(char* data, size_t nbytes) { 256 CHECK_EQ(nbytes % 8, 0); 257 258 #if defined(_MSC_VER) 259 int align = reinterpret_cast
(data) % sizeof(uint64_t); 260 if (align == 0) { 261 // MSVC has no strict aliasing, and is able to highly optimize this case. 262 uint64_t* data64 = reinterpret_cast
(data); 263 size_t len64 = nbytes / sizeof(*data64); 264 for (size_t i = 0; i < len64; i++) { 265 data64[i] = BSWAP_8(data64[i]); 266 } 267 return; 268 } 269 #endif 270 271 uint64_t temp; 272 for (size_t i = 0; i < nbytes; i += sizeof(temp)) { 273 memcpy(&temp, &data[i], sizeof(temp)); 274 temp = BSWAP_8(temp); 275 memcpy(&data[i], &temp, sizeof(temp)); 276 } 277 } 278 279 char ToLower(char c) { 280 return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; 281 } 282 283 std::string ToLower(const std::string& in) { 284 std::string out(in.size(), 0); 285 for (size_t i = 0; i < in.size(); ++i) 286 out[i] = ToLower(in[i]); 287 return out; 288 } 289 290 char ToUpper(char c) { 291 return c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c; 292 } 293 294 std::string ToUpper(const std::string& in) { 295 std::string out(in.size(), 0); 296 for (size_t i = 0; i < in.size(); ++i) 297 out[i] = ToUpper(in[i]); 298 return out; 299 } 300 301 bool StringEqualNoCase(const char* a, const char* b) { 302 while (ToLower(*a) == ToLower(*b++)) { 303 if (*a++ == '\0') 304 return true; 305 } 306 return false; 307 } 308 309 bool StringEqualNoCaseN(const char* a, const char* b, size_t length) { 310 for (size_t i = 0; i < length; i++) { 311 if (ToLower(a[i]) != ToLower(b[i])) 312 return false; 313 if (a[i] == '\0') 314 return true; 315 } 316 return true; 317 } 318 319 template
320 inline T MultiplyWithOverflowCheck(T a, T b) { 321 auto ret = a * b; 322 if (a != 0) 323 CHECK_EQ(b, ret / a); 324 325 return ret; 326 } 327 328 // These should be used in our code as opposed to the native 329 // versions as they abstract out some platform and or 330 // compiler version specific functionality. 331 // malloc(0) and realloc(ptr, 0) have implementation-defined behavior in 332 // that the standard allows them to either return a unique pointer or a 333 // nullptr for zero-sized allocation requests. Normalize by always using 334 // a nullptr. 335 template
336 T* UncheckedRealloc(T* pointer, size_t n) { 337 size_t full_size = MultiplyWithOverflowCheck(sizeof(T), n); 338 339 if (full_size == 0) { 340 free(pointer); 341 return nullptr; 342 } 343 344 void* allocated = realloc(pointer, full_size); 345 346 if (UNLIKELY(allocated == nullptr)) { 347 // Tell V8 that memory is low and retry. 348 LowMemoryNotification(); 349 allocated = realloc(pointer, full_size); 350 } 351 352 return static_cast
(allocated); 353 } 354 355 // As per spec realloc behaves like malloc if passed nullptr. 356 template
357 inline T* UncheckedMalloc(size_t n) { 358 if (n == 0) n = 1; 359 return UncheckedRealloc
(nullptr, n); 360 } 361 362 template
363 inline T* UncheckedCalloc(size_t n) { 364 if (n == 0) n = 1; 365 MultiplyWithOverflowCheck(sizeof(T), n); 366 return static_cast
(calloc(n, sizeof(T))); 367 } 368 369 template
370 inline T* Realloc(T* pointer, size_t n) { 371 T* ret = UncheckedRealloc(pointer, n); 372 CHECK_IMPLIES(n > 0, ret != nullptr); 373 return ret; 374 } 375 376 template
377 inline T* Malloc(size_t n) { 378 T* ret = UncheckedMalloc
(n); 379 CHECK_IMPLIES(n > 0, ret != nullptr); 380 return ret; 381 } 382 383 template
384 inline T* Calloc(size_t n) { 385 T* ret = UncheckedCalloc
(n); 386 CHECK_IMPLIES(n > 0, ret != nullptr); 387 return ret; 388 } 389 390 // Shortcuts for char*. 391 inline char* Malloc(size_t n) { return Malloc
(n); } 392 inline char* Calloc(size_t n) { return Calloc
(n); } 393 inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc
(n); } 394 inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc
(n); } 395 396 // This is a helper in the .cc file so including util-inl.h doesn't include more 397 // headers than we really need to. 398 void ThrowErrStringTooLong(v8::Isolate* isolate); 399 400 v8::MaybeLocal
ToV8Value(v8::Local
context, 401 const std::string& str, 402 v8::Isolate* isolate) { 403 if (isolate == nullptr) isolate = context->GetIsolate(); 404 if (UNLIKELY(str.size() >= static_cast
(v8::String::kMaxLength))) { 405 // V8 only has a TODO comment about adding an exception when the maximum 406 // string size is exceeded. 407 ThrowErrStringTooLong(isolate); 408 return v8::MaybeLocal
(); 409 } 410 411 return v8::String::NewFromUtf8( 412 isolate, str.data(), v8::NewStringType::kNormal, str.size()) 413 .FromMaybe(v8::Local
()); 414 } 415 416 template
417 v8::MaybeLocal
ToV8Value(v8::Local
context, 418 const std::vector
& vec, 419 v8::Isolate* isolate) { 420 if (isolate == nullptr) isolate = context->GetIsolate(); 421 v8::EscapableHandleScope handle_scope(isolate); 422 423 MaybeStackBuffer
, 128> arr(vec.size()); 424 arr.SetLength(vec.size()); 425 for (size_t i = 0; i < vec.size(); ++i) { 426 if (!ToV8Value(context, vec[i], isolate).ToLocal(&arr[i])) 427 return v8::MaybeLocal
(); 428 } 429 430 return handle_scope.Escape(v8::Array::New(isolate, arr.out(), arr.length())); 431 } 432 433 template
434 v8::MaybeLocal
ToV8Value(v8::Local
context, 435 const std::unordered_map
& map, 436 v8::Isolate* isolate) { 437 if (isolate == nullptr) isolate = context->GetIsolate(); 438 v8::EscapableHandleScope handle_scope(isolate); 439 440 v8::Local
ret = v8::Map::New(isolate); 441 for (const auto& item : map) { 442 v8::Local
first, second; 443 if (!ToV8Value(context, item.first, isolate).ToLocal(&first) || 444 !ToV8Value(context, item.second, isolate).ToLocal(&second) || 445 ret->Set(context, first, second).IsEmpty()) { 446 return v8::MaybeLocal
(); 447 } 448 } 449 450 return handle_scope.Escape(ret); 451 } 452 453 template
454 v8::MaybeLocal
ToV8Value(v8::Local
context, 455 const T& number, 456 v8::Isolate* isolate) { 457 if (isolate == nullptr) isolate = context->GetIsolate(); 458 459 using Limits = std::numeric_limits
; 460 // Choose Uint32, Int32, or Double depending on range checks. 461 // These checks should all collapse at compile time. 462 if (static_cast
(Limits::max()) <= 463 std::numeric_limits
::max() && 464 static_cast
(Limits::min()) >= 465 std::numeric_limits
::min() && Limits::is_exact) { 466 return v8::Integer::NewFromUnsigned(isolate, static_cast
(number)); 467 } 468 469 if (static_cast
(Limits::max()) <= 470 std::numeric_limits
::max() && 471 static_cast
(Limits::min()) >= 472 std::numeric_limits
::min() && Limits::is_exact) { 473 return v8::Integer::New(isolate, static_cast
(number)); 474 } 475 476 return v8::Number::New(isolate, static_cast
(number)); 477 } 478 479 SlicedArguments::SlicedArguments( 480 const v8::FunctionCallbackInfo
& args, size_t start) { 481 const size_t length = static_cast
(args.Length()); 482 if (start >= length) return; 483 const size_t size = length - start; 484 485 AllocateSufficientStorage(size); 486 for (size_t i = 0; i < size; ++i) 487 (*this)[i] = args[i + start]; 488 } 489 490 template
491 ArrayBufferViewContents
::ArrayBufferViewContents( 492 v8::Local
value) { 493 CHECK(value->IsArrayBufferView()); 494 Read(value.As
()); 495 } 496 497 template
498 ArrayBufferViewContents
::ArrayBufferViewContents( 499 v8::Local
value) { 500 CHECK(value->IsArrayBufferView()); 501 Read(value.As
()); 502 } 503 504 template
505 ArrayBufferViewContents
::ArrayBufferViewContents( 506 v8::Local
abv) { 507 Read(abv); 508 } 509 510 template
511 void ArrayBufferViewContents
::Read(v8::Local
abv) { 512 static_assert(sizeof(T) == 1, "Only supports one-byte data at the moment"); 513 length_ = abv->ByteLength(); 514 if (length_ > sizeof(stack_storage_) || abv->HasBuffer()) { 515 data_ = static_cast
(abv->Buffer()->GetContents().Data()) + 516 abv->ByteOffset(); 517 } else { 518 abv->CopyContents(stack_storage_, sizeof(stack_storage_)); 519 data_ = stack_storage_; 520 } 521 } 522 523 } // namespace node 524 525 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 526 527 #endif // SRC_UTIL_INL_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2024 MyWebUniversity.com ™