Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/nodejs/src/node_options-inl.h
$ cat -n /usr/include/nodejs/src/node_options-inl.h 1 #ifndef SRC_NODE_OPTIONS_INL_H_ 2 #define SRC_NODE_OPTIONS_INL_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include
7 #include "node_options.h" 8 #include "util.h" 9 10 namespace node { 11 12 PerIsolateOptions* PerProcessOptions::get_per_isolate_options() { 13 return per_isolate.get(); 14 } 15 16 EnvironmentOptions* PerIsolateOptions::get_per_env_options() { 17 return per_env.get(); 18 } 19 20 namespace options_parser { 21 22 template
23 void OptionsParser
::AddOption(const char* name, 24 const char* help_text, 25 bool Options::* field, 26 OptionEnvvarSettings env_setting, 27 bool default_is_true) { 28 options_.emplace(name, 29 OptionInfo{kBoolean, 30 std::make_shared
>(field), 31 env_setting, 32 help_text, 33 default_is_true}); 34 } 35 36 template
37 void OptionsParser
::AddOption(const char* name, 38 const char* help_text, 39 uint64_t Options::* field, 40 OptionEnvvarSettings env_setting) { 41 options_.emplace( 42 name, 43 OptionInfo{kUInteger, 44 std::make_shared
>(field), 45 env_setting, 46 help_text}); 47 } 48 49 template
50 void OptionsParser
::AddOption(const char* name, 51 const char* help_text, 52 int64_t Options::* field, 53 OptionEnvvarSettings env_setting) { 54 options_.emplace( 55 name, 56 OptionInfo{kInteger, 57 std::make_shared
>(field), 58 env_setting, 59 help_text}); 60 } 61 62 template
63 void OptionsParser
::AddOption(const char* name, 64 const char* help_text, 65 std::string Options::* field, 66 OptionEnvvarSettings env_setting) { 67 options_.emplace( 68 name, 69 OptionInfo{kString, 70 std::make_shared
>(field), 71 env_setting, 72 help_text}); 73 } 74 75 template
76 void OptionsParser
::AddOption( 77 const char* name, 78 const char* help_text, 79 std::vector
Options::* field, 80 OptionEnvvarSettings env_setting) { 81 options_.emplace(name, OptionInfo { 82 kStringList, 83 std::make_shared
>>(field), 84 env_setting, 85 help_text 86 }); 87 } 88 89 template
90 void OptionsParser
::AddOption(const char* name, 91 const char* help_text, 92 HostPort Options::* field, 93 OptionEnvvarSettings env_setting) { 94 options_.emplace( 95 name, 96 OptionInfo{kHostPort, 97 std::make_shared
>(field), 98 env_setting, 99 help_text}); 100 } 101 102 template
103 void OptionsParser
::AddOption(const char* name, 104 const char* help_text, 105 NoOp no_op_tag, 106 OptionEnvvarSettings env_setting) { 107 options_.emplace(name, OptionInfo{kNoOp, nullptr, env_setting, help_text}); 108 } 109 110 template
111 void OptionsParser
::AddOption(const char* name, 112 const char* help_text, 113 V8Option v8_option_tag, 114 OptionEnvvarSettings env_setting) { 115 options_.emplace(name, 116 OptionInfo{kV8Option, nullptr, env_setting, help_text}); 117 } 118 119 template
120 void OptionsParser
::AddAlias(const char* from, 121 const char* to) { 122 aliases_[from] = { to }; 123 } 124 125 template
126 void OptionsParser
::AddAlias(const char* from, 127 const std::vector
& to) { 128 aliases_[from] = to; 129 } 130 131 template
132 void OptionsParser
::AddAlias( 133 const char* from, 134 const std::initializer_list
& to) { 135 AddAlias(from, std::vector
(to)); 136 } 137 138 template
139 void OptionsParser
::Implies(const char* from, 140 const char* to) { 141 auto it = options_.find(to); 142 CHECK_NE(it, options_.end()); 143 CHECK(it->second.type == kBoolean || it->second.type == kV8Option); 144 implications_.emplace( 145 from, Implication{it->second.type, to, it->second.field, true}); 146 } 147 148 template
149 void OptionsParser
::ImpliesNot(const char* from, 150 const char* to) { 151 auto it = options_.find(to); 152 CHECK_NE(it, options_.end()); 153 CHECK_EQ(it->second.type, kBoolean); 154 implications_.emplace( 155 from, Implication{it->second.type, to, it->second.field, false}); 156 } 157 158 template
159 template
160 auto OptionsParser
::Convert( 161 std::shared_ptr
original, 162 ChildOptions* (Options::* get_child)()) { 163 // If we have a field on ChildOptions, and we want to access it from an 164 // Options instance, we call get_child() on the original Options and then 165 // access it, i.e. this class implements a kind of function chaining. 166 struct AdaptedField : BaseOptionField { 167 void* LookupImpl(Options* options) const override { 168 return original->LookupImpl((options->*get_child)()); 169 } 170 171 AdaptedField( 172 std::shared_ptr
original, 173 ChildOptions* (Options::* get_child)()) 174 : original(original), get_child(get_child) {} 175 176 std::shared_ptr
original; 177 ChildOptions* (Options::* get_child)(); 178 }; 179 180 return std::shared_ptr
( 181 new AdaptedField(original, get_child)); 182 } 183 template
184 template
185 auto OptionsParser
::Convert( 186 typename OptionsParser
::OptionInfo original, 187 ChildOptions* (Options::* get_child)()) { 188 return OptionInfo{original.type, 189 Convert(original.field, get_child), 190 original.env_setting, 191 original.help_text, 192 original.default_is_true}; 193 } 194 195 template
196 template
197 auto OptionsParser
::Convert( 198 typename OptionsParser
::Implication original, 199 ChildOptions* (Options::* get_child)()) { 200 return Implication{ 201 original.type, 202 original.name, 203 Convert(original.target_field, get_child), 204 original.target_value, 205 }; 206 } 207 208 template
209 template
210 void OptionsParser
::Insert( 211 const OptionsParser
& child_options_parser, 212 ChildOptions* (Options::* get_child)()) { 213 aliases_.insert(std::begin(child_options_parser.aliases_), 214 std::end(child_options_parser.aliases_)); 215 216 for (const auto& pair : child_options_parser.options_) 217 options_.emplace(pair.first, Convert(pair.second, get_child)); 218 219 for (const auto& pair : child_options_parser.implications_) 220 implications_.emplace(pair.first, Convert(pair.second, get_child)); 221 } 222 223 inline std::string NotAllowedInEnvErr(const std::string& arg) { 224 return arg + " is not allowed in NODE_OPTIONS"; 225 } 226 227 inline std::string RequiresArgumentErr(const std::string& arg) { 228 return arg + " requires an argument"; 229 } 230 231 inline std::string NegationImpliesBooleanError(const std::string& arg) { 232 return arg + " is an invalid negation because it is not a boolean option"; 233 } 234 235 // We store some of the basic information around a single Parse call inside 236 // this struct, to separate storage of command line arguments and their 237 // handling. In particular, this makes it easier to introduce 'synthetic' 238 // arguments that get inserted by expanding option aliases. 239 struct ArgsInfo { 240 // Generally, the idea here is that the first entry in `*underlying` stores 241 // the "0th" argument (the program name), then `synthetic_args` are inserted, 242 // followed by the remainder of `*underlying`. 243 std::vector
* underlying; 244 std::vector
synthetic_args; 245 246 std::vector
* exec_args; 247 248 ArgsInfo(std::vector
* args, 249 std::vector
* exec_args) 250 : underlying(args), exec_args(exec_args) {} 251 252 size_t remaining() const { 253 // -1 to account for the program name. 254 return underlying->size() - 1 + synthetic_args.size(); 255 } 256 257 bool empty() const { return remaining() == 0; } 258 const std::string& program_name() const { return underlying->at(0); } 259 260 std::string& first() { 261 return synthetic_args.empty() ? underlying->at(1) : synthetic_args.front(); 262 } 263 264 std::string pop_first() { 265 std::string ret = std::move(first()); 266 if (synthetic_args.empty()) { 267 // Only push arguments to `exec_args` that were also originally passed 268 // on the command line (i.e. not generated through alias expansion). 269 // '--' is a special case here since its purpose is to end `exec_argv`, 270 // which is why we do not include it. 271 if (exec_args != nullptr && ret != "--") 272 exec_args->push_back(ret); 273 underlying->erase(underlying->begin() + 1); 274 } else { 275 synthetic_args.erase(synthetic_args.begin()); 276 } 277 return ret; 278 } 279 }; 280 281 template
282 void OptionsParser
::Parse( 283 std::vector
* const orig_args, 284 std::vector
* const exec_args, 285 std::vector
* const v8_args, 286 Options* const options, 287 OptionEnvvarSettings required_env_settings, 288 std::vector
* const errors) const { 289 ArgsInfo args(orig_args, exec_args); 290 291 // The first entry is the process name. Make sure it ends up in the V8 argv, 292 // since V8::SetFlagsFromCommandLine() expects that to hold true for that 293 // array as well. 294 if (v8_args->empty()) 295 v8_args->push_back(args.program_name()); 296 297 while (!args.empty() && errors->empty()) { 298 if (args.first().size() <= 1 || args.first()[0] != '-') break; 299 300 // We know that we're either going to consume this 301 // argument or fail completely. 302 const std::string arg = args.pop_first(); 303 304 if (arg == "--") { 305 if (required_env_settings == kAllowedInEnvvar) 306 errors->push_back(NotAllowedInEnvErr("--")); 307 break; 308 } 309 310 // Only allow --foo=bar notation for options starting with double dashes. 311 // (E.g. -e=a is not allowed as shorthand for --eval=a, which would 312 // otherwise be the result of alias expansion.) 313 const std::string::size_type equals_index = 314 arg[0] == '-' && arg[1] == '-' ? arg.find('=') : std::string::npos; 315 std::string name = 316 equals_index == std::string::npos ? arg : arg.substr(0, equals_index); 317 318 // Store the 'original name' of the argument. This name differs from 319 // 'name' in that it contains a possible '=' sign and is not affected 320 // by alias expansion. 321 std::string original_name = name; 322 if (equals_index != std::string::npos) 323 original_name += '='; 324 325 auto missing_argument = [&]() { 326 errors->push_back(RequiresArgumentErr(original_name)); 327 }; 328 329 // Normalize by replacing `_` with `-` in options. 330 for (std::string::size_type i = 2; i < name.size(); ++i) { 331 if (name[i] == '_') 332 name[i] = '-'; 333 } 334 335 // Convert --no-foo to --foo and keep in mind that we're negating. 336 bool is_negation = false; 337 if (name.find("--no-") == 0) { 338 name.erase(2, 3); // remove no- 339 is_negation = true; 340 } 341 342 { 343 auto it = aliases_.end(); 344 // Expand aliases: 345 // - If `name` can be found in `aliases_`. 346 // - If `name` + '=' can be found in `aliases_`. 347 // - If `name` + "
" can be found in `aliases_`, and we have 348 // a subsequent argument that does not start with '-' itself. 349 while ((it = aliases_.find(name)) != aliases_.end() || 350 (equals_index != std::string::npos && 351 (it = aliases_.find(name + '=')) != aliases_.end()) || 352 (!args.empty() && 353 !args.first().empty() && 354 args.first()[0] != '-' && 355 (it = aliases_.find(name + "
")) != aliases_.end())) { 356 const std::string prev_name = std::move(name); 357 const std::vector
& expansion = it->second; 358 359 // Use the first entry in the expansion as the new 'name'. 360 name = expansion.front(); 361 362 if (expansion.size() > 1) { 363 // The other arguments, if any, are going to be handled later. 364 args.synthetic_args.insert( 365 args.synthetic_args.begin(), 366 expansion.begin() + 1, 367 expansion.end()); 368 } 369 370 if (name == prev_name) break; 371 } 372 } 373 374 auto it = options_.find(name); 375 376 if ((it == options_.end() || 377 it->second.env_setting == kDisallowedInEnvvar) && 378 required_env_settings == kAllowedInEnvvar) { 379 errors->push_back(NotAllowedInEnvErr(original_name)); 380 break; 381 } 382 383 { 384 std::string implied_name = name; 385 if (is_negation) { 386 // Implications for negated options are defined with "--no-". 387 implied_name.insert(2, "no-"); 388 } 389 auto implications = implications_.equal_range(implied_name); 390 for (auto imp = implications.first; imp != implications.second; ++imp) { 391 if (imp->second.type == kV8Option) { 392 v8_args->push_back(imp->second.name); 393 } else { 394 *imp->second.target_field->template Lookup
(options) = 395 imp->second.target_value; 396 } 397 } 398 } 399 400 if (it == options_.end()) { 401 v8_args->push_back(arg); 402 continue; 403 } 404 405 const OptionInfo& info = it->second; 406 407 // Some V8 options can be negated and they are validated by V8 later. 408 if (is_negation && info.type != kBoolean && info.type != kV8Option) { 409 errors->push_back(NegationImpliesBooleanError(arg)); 410 break; 411 } 412 413 std::string value; 414 if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option) { 415 if (equals_index != std::string::npos) { 416 value = arg.substr(equals_index + 1); 417 if (value.empty()) { 418 missing_argument(); 419 break; 420 } 421 } else { 422 if (args.empty()) { 423 missing_argument(); 424 break; 425 } 426 427 value = args.pop_first(); 428 429 if (!value.empty() && value[0] == '-') { 430 missing_argument(); 431 break; 432 } else { 433 if (!value.empty() && value[0] == '\\' && value[1] == '-') 434 value = value.substr(1); // Treat \- as escaping an -. 435 } 436 } 437 } 438 439 switch (info.type) { 440 case kBoolean: 441 *Lookup
(info.field, options) = !is_negation; 442 break; 443 case kInteger: 444 *Lookup
(info.field, options) = std::atoll(value.c_str()); 445 break; 446 case kUInteger: 447 *Lookup
(info.field, options) = 448 std::strtoull(value.c_str(), nullptr, 10); 449 break; 450 case kString: 451 *Lookup
(info.field, options) = value; 452 break; 453 case kStringList: 454 Lookup
>(info.field, options) 455 ->emplace_back(std::move(value)); 456 break; 457 case kHostPort: 458 Lookup
(info.field, options) 459 ->Update(SplitHostPort(value, errors)); 460 break; 461 case kNoOp: 462 break; 463 case kV8Option: 464 v8_args->push_back(arg); 465 break; 466 default: 467 UNREACHABLE(); 468 } 469 } 470 options->CheckOptions(errors, orig_args); 471 } 472 473 } // namespace options_parser 474 } // namespace node 475 476 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 477 478 #endif // SRC_NODE_OPTIONS_INL_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™