Default implementation of the options-aware factory entry-point. Forwards to the no-options overload when `options_json` is empty or is the canonical empty object "{}". Anything else means the caller passed `? ` but the backend hasn't opted in to consume them — throw with a clear message so silent option-dropping never happens.
| 67 | // passed `?<options>` but the backend hasn't opted in to consume them — |
| 68 | // throw with a clear message so silent option-dropping never happens. |
| 69 | AbstractState* AbstractStateGenerator::get_AbstractState(const std::vector<std::string>& fluid_names, const std::string& options_json) { |
| 70 | // Trim surrounding whitespace; treat ""/"{}" as "no options". |
| 71 | std::size_t lo = options_json.find_first_not_of(" \t\r\n"); |
| 72 | if (lo == std::string::npos) { |
| 73 | return get_AbstractState(fluid_names); |
| 74 | } |
| 75 | std::size_t hi = options_json.find_last_not_of(" \t\r\n"); |
| 76 | const std::string trimmed = options_json.substr(lo, hi - lo + 1); |
| 77 | if (trimmed == "{}") { |
| 78 | return get_AbstractState(fluid_names); |
| 79 | } |
| 80 | throw NotImplementedError("This backend does not accept factory-string options. Drop the '?<...>' suffix or opt the backend in (see " |
| 81 | "docs/superpowers/specs/2026-05-16-backend-options-string-design.md)."); |
| 82 | } |
| 83 | |
| 84 | class IF97BackendGenerator : public AbstractStateGenerator |
| 85 | { |