| 314 | } |
| 315 | |
| 316 | Errata |
| 317 | FeatureGroup::load_as_tuple(Config &cfg, YAML::Node const &node, std::initializer_list<FeatureGroup::Descriptor> const &ex_keys) |
| 318 | { |
| 319 | unsigned idx = 0; |
| 320 | unsigned n_keys = ex_keys.size(); |
| 321 | unsigned n_elts = node.size(); |
| 322 | ExprInfo info[n_keys]; |
| 323 | |
| 324 | // No dependency in tuples, can just walk the keys and load them. |
| 325 | for (auto const &key : ex_keys) { |
| 326 | if (idx >= n_elts) { |
| 327 | if (key._flags[REQUIRED]) { |
| 328 | return Errata(S_ERROR, R"(The list was {} elements long but {} are required.)", n_elts, n_keys); |
| 329 | } |
| 330 | continue; // it was optional, skip it and keep checking for REQUIRED keys. |
| 331 | } |
| 332 | |
| 333 | auto &&[expr, errata] = cfg.parse_expr(node[idx]); |
| 334 | if (!errata.is_ok()) { |
| 335 | return std::move(errata); |
| 336 | } |
| 337 | info[idx]._name = key._name; |
| 338 | info[idx]._expr = std::move(expr); // safe because of the @c reserve |
| 339 | ++idx; |
| 340 | } |
| 341 | // Localize feature info, now that the size is determined. |
| 342 | _expr_info = cfg.alloc_span<ExprInfo>(idx); |
| 343 | index_type i = 0; |
| 344 | for (auto &item : _expr_info) { |
| 345 | new (&item) ExprInfo{std::move(info[i++])}; |
| 346 | } |
| 347 | // No dependencies for tuple loads. |
| 348 | // No feature data because no dependencies. |
| 349 | |
| 350 | return {}; |
| 351 | } |
| 352 | |
| 353 | Feature |
| 354 | FeatureGroup::extract(Context &ctx, swoc::TextView const &name) |
no test coverage detected