Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/node_http_common-inl.h
1 #ifndef SRC_NODE_HTTP_COMMON_INL_H_ 2 #define SRC_NODE_HTTP_COMMON_INL_H_ 3 4 #include "node_http_common.h" 5 #include "node.h" 6 #include "node_mem-inl.h" 7 #include "env-inl.h" 8 #include "v8.h" 9 10 #include <algorithm> 11 #include "nbytes.h" 12 13 namespace node { 14 15 template <typename T> 16 NgHeaders<T>::NgHeaders(Environment* env, v8::Local<v8::Array> headers) { 17 v8::Local<v8::Value> header_string = 18 headers->Get(env->context(), 0).ToLocalChecked(); 19 v8::Local<v8::Value> header_count = 20 headers->Get(env->context(), 1).ToLocalChecked(); 21 CHECK(header_count->IsUint32()); 22 CHECK(header_string->IsString()); 23 count_ = header_count.As<v8::Uint32>()->Value(); 24 int header_string_len = header_string.As<v8::String>()->Length(); 25 26 if (count_ == 0) { 27 CHECK_EQ(header_string_len, 0); 28 return; 29 } 30 31 buf_.AllocateSufficientStorage((alignof(nv_t) - 1) + 32 count_ * sizeof(nv_t) + 33 header_string_len); 34 35 char* start = nbytes::AlignUp(buf_.out(), alignof(nv_t)); 36 char* header_contents = start + (count_ * sizeof(nv_t)); 37 nv_t* const nva = reinterpret_cast<nv_t*>(start); 38 39 CHECK_LE(header_contents + header_string_len, *buf_ + buf_.length()); 40 CHECK_EQ(header_string.As<v8::String>()->WriteOneByte( 41 env->isolate(), 42 reinterpret_cast<uint8_t*>(header_contents), 43 0, 44 header_string_len, 45 v8::String::NO_NULL_TERMINATION), 46 header_string_len); 47 48 size_t n = 0; 49 char* p; 50 for (p = header_contents; p < header_contents + header_string_len; n++) { 51 if (n >= count_) { 52 static uint8_t zero = '\0'; 53 nva[0].name = nva[0].value = &zero; 54 nva[0].namelen = nva[0].valuelen = 1; 55 count_ = 1; 56 return; 57 } 58 59 nva[n].name = reinterpret_cast<uint8_t*>(p); 60 nva[n].namelen = strlen(p); 61 p += nva[n].namelen + 1; 62 nva[n].value = reinterpret_cast<uint8_t*>(p); 63 nva[n].valuelen = strlen(p); 64 p += nva[n].valuelen + 1; 65 nva[n].flags = *p; 66 p++; 67 } 68 } 69 70 size_t GetClientMaxHeaderPairs(size_t max_header_pairs) { 71 static constexpr size_t min_header_pairs = 1; 72 return std::max(max_header_pairs, min_header_pairs); 73 } 74 75 size_t GetServerMaxHeaderPairs(size_t max_header_pairs) { 76 static constexpr size_t min_header_pairs = 4; 77 return std::max(max_header_pairs, min_header_pairs); 78 } 79 80 template <typename allocator_t> 81 std::string NgHeaderBase<allocator_t>::ToString() const { 82 std::string ret = name(); 83 ret += " = "; 84 ret += value(); 85 return ret; 86 } 87 88 template <typename T> 89 bool NgHeader<T>::IsZeroLength( 90 NgHeader<T>::rcbuf_t* name, 91 NgHeader<T>::rcbuf_t* value) { 92 return IsZeroLength(-1, name, value); 93 } 94 95 template <typename T> 96 bool NgHeader<T>::IsZeroLength( 97 int32_t token, 98 NgHeader<T>::rcbuf_t* name, 99 NgHeader<T>::rcbuf_t* value) { 100 101 if (NgHeader<T>::rcbufferpointer_t::IsZeroLength(value)) 102 return true; 103 104 const char* header_name = T::ToHttpHeaderName(token); 105 return header_name != nullptr || 106 NgHeader<T>::rcbufferpointer_t::IsZeroLength(name); 107 } 108 109 template <typename T> 110 NgHeader<T>::NgHeader( 111 Environment* env, 112 NgHeader<T>::rcbuf_t* name, 113 NgHeader<T>::rcbuf_t* value, 114 uint8_t flags) 115 : NgHeader<T>(env, -1, name, value, flags) {} 116 117 template <typename T> 118 NgHeader<T>::NgHeader( 119 Environment* env, 120 int32_t token, 121 NgHeader<T>::rcbuf_t* name, 122 NgHeader<T>::rcbuf_t* value, 123 uint8_t flags) : env_(env), token_(token), flags_(flags) { 124 if (token == -1) { 125 CHECK_NOT_NULL(name); 126 name_.reset(name, true); // Internalizable 127 } 128 CHECK_NOT_NULL(value); 129 name_.reset(name, true); // Internalizable 130 value_.reset(value); 131 } 132 133 template <typename T> 134 NgHeader<T>::NgHeader(NgHeader<T>&& other) noexcept 135 : env_(other.env_), 136 name_(std::move(other.name_)), 137 value_(std::move(other.value_)), 138 token_(other.token_), 139 flags_(other.flags_) { 140 other.token_ = -1; 141 other.flags_ = 0; 142 other.env_ = nullptr; 143 } 144 145 template <typename T> 146 void NgHeader<T>::MemoryInfo(MemoryTracker* tracker) const { 147 tracker->TrackField("name", name_); 148 tracker->TrackField("value", value_); 149 } 150 151 template <typename T> 152 v8::MaybeLocal<v8::String> NgHeader<T>::GetName( 153 NgHeader<T>::allocator_t* allocator) const { 154 155 // Not all instances will support using token id's for header names. 156 // HTTP/2 specifically does not support it. 157 const char* header_name = T::ToHttpHeaderName(token_); 158 159 // If header_name is not nullptr, then it is a known header with 160 // a statically defined name. We can safely internalize it here. 161 if (header_name != nullptr) { 162 auto& static_str_map = env_->isolate_data()->static_str_map; 163 v8::Eternal<v8::String> eternal = static_str_map[header_name]; 164 if (eternal.IsEmpty()) { 165 v8::Local<v8::String> str = OneByteString(env_->isolate(), header_name); 166 eternal.Set(env_->isolate(), str); 167 return str; 168 } 169 return eternal.Get(env_->isolate()); 170 } 171 return rcbufferpointer_t::External::New(allocator, name_); 172 } 173 174 template <typename T> 175 v8::MaybeLocal<v8::String> NgHeader<T>::GetValue( 176 NgHeader<T>::allocator_t* allocator) const { 177 return rcbufferpointer_t::External::New(allocator, value_); 178 } 179 180 template <typename T> 181 std::string NgHeader<T>::name() const { 182 return name_.str(); 183 } 184 185 template <typename T> 186 std::string NgHeader<T>::value() const { 187 return value_.str(); 188 } 189 190 template <typename T> 191 size_t NgHeader<T>::length() const { 192 return name_.len() + value_.len(); 193 } 194 195 template <typename T> 196 uint8_t NgHeader<T>::flags() const { 197 return flags_; 198 } 199 200 } // namespace node 201 202 #endif // SRC_NODE_HTTP_COMMON_INL_H_