| 439 | // When in_str == '"', a `"` inside should have arrived via |
| 440 | // the `\\` escape branch above; a bare `"` here is malformed |
| 441 | // input we pass through unchanged. |
| 442 | if (in_str != '"' && c == '"') { |
| 443 | rewritten += "\\\""; |
| 444 | i++; |
| 445 | continue; |
| 446 | } |
| 447 | rewritten += c; |
| 448 | i++; |
| 449 | continue; |
| 450 | } |
| 451 | if (c == '"' || c == '\'' || c == '`') { |
| 452 | rewritten += '"'; |
| 453 | in_str = c; |
| 454 | i++; |
| 455 | continue; |
| 456 | } |
| 457 | // Try to match a bare-key identifier here. Don't fire if the |
| 458 | // previous emitted char is `"` — that would indicate we're sitting |
| 459 | // right after a JSON string boundary and the "identifier" is |
| 460 | // probably part of a value continuation (e.g. `"k": foo: 1` would |
| 461 | // be malformed JSON anyway, but better to leave it untouched). |
| 462 | std::smatch m; |
| 463 | std::string tail = payload.substr(i); |
| 464 | if (std::regex_search(tail, m, re_bare_key, |
| 465 | std::regex_constants::match_continuous) && |
| 466 | (rewritten.empty() || rewritten.back() != '"')) { |
| 467 | rewritten += '"'; |
| 468 | rewritten += m[1].str(); |
| 469 | rewritten += '"'; |
| 470 | rewritten += m[2].str(); |
| 471 | i += m.length(); |
| 472 | continue; |
| 473 | } |
| 474 | rewritten += c; |
| 475 | i++; |
| 476 | } |
| 477 | |
| 478 | json parsed = json::parse(rewritten, nullptr, false); |
| 479 | if (parsed.is_discarded()) return false; |
| 480 | out = std::move(parsed); |
| 481 | return true; |
| 482 | } |
| 483 | |
| 484 | |
| 485 | // ─── XML parameter parser ─────────────────────────────────────────────── |
| 486 | |
| 487 | static json parse_xml_params(const std::string & region, const std::string & fn_name, |
| 488 | const json & tools) { |
| 489 | json props = find_tool_properties(tools, fn_name); |
no test coverage detected