| 15318 | } |
| 15319 | |
| 15320 | inline void url_aggregator::consume_prepared_path(std::string_view input) { |
| 15321 | ada_log("url_aggregator::consume_prepared_path ", input); |
| 15322 | /*** |
| 15323 | * This is largely duplicated code from helpers::parse_prepared_path, which is |
| 15324 | * unfortunate. This particular function is nearly identical, except that it |
| 15325 | * is a method on url_aggregator. The idea is that the trivial path (which is |
| 15326 | * very common) merely appends to the buffer. This is the same trivial path as |
| 15327 | * with helpers::parse_prepared_path, except that we have the additional check |
| 15328 | * for is_at_path(). Otherwise, we grab a copy of the current path and we |
| 15329 | * modify it, and then insert it back into the buffer. |
| 15330 | */ |
| 15331 | uint8_t accumulator = checkers::path_signature(input); |
| 15332 | // Let us first detect a trivial case. |
| 15333 | // If it is special, we check that we have no dot, no %, no \ and no |
| 15334 | // character needing percent encoding. Otherwise, we check that we have no %, |
| 15335 | // no dot, and no character needing percent encoding. |
| 15336 | constexpr uint8_t need_encoding = 1; |
| 15337 | constexpr uint8_t backslash_char = 2; |
| 15338 | constexpr uint8_t dot_char = 4; |
| 15339 | constexpr uint8_t percent_char = 8; |
| 15340 | bool special = type != ada::scheme::NOT_SPECIAL; |
| 15341 | bool may_need_slow_file_handling = (type == ada::scheme::type::FILE && |
| 15342 | checkers::is_windows_drive_letter(input)); |
| 15343 | bool trivial_path = |
| 15344 | (special ? (accumulator == 0) |
| 15345 | : ((accumulator & (need_encoding | dot_char | percent_char)) == |
| 15346 | 0)) && |
| 15347 | (!may_need_slow_file_handling); |
| 15348 | if (accumulator == dot_char && !may_need_slow_file_handling) { |
| 15349 | // '4' means that we have at least one dot, but nothing that requires |
| 15350 | // percent encoding or decoding. The only part that is not trivial is |
| 15351 | // that we may have single dots and double dots path segments. |
| 15352 | // If we have such segments, then we either have a path that begins |
| 15353 | // with '.' (easy to check), or we have the sequence './'. |
| 15354 | // Note: input cannot be empty, it must at least contain one character ('.') |
| 15355 | // Note: we know that '\' is not present. |
| 15356 | if (input[0] != '.') { |
| 15357 | size_t slashdot = 0; |
| 15358 | bool dot_is_file = true; |
| 15359 | for (;;) { |
| 15360 | slashdot = input.find("/.", slashdot); |
| 15361 | if (slashdot == std::string_view::npos) { // common case |
| 15362 | break; |
| 15363 | } else { // uncommon |
| 15364 | // only three cases matter: /./, /.. or a final / |
| 15365 | slashdot += 2; |
| 15366 | dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' || |
| 15367 | input[slashdot] == '/'); |
| 15368 | } |
| 15369 | } |
| 15370 | trivial_path = dot_is_file; |
| 15371 | } |
| 15372 | } |
| 15373 | if (trivial_path && is_at_path()) { |
| 15374 | ada_log("parse_path trivial"); |
| 15375 | buffer += '/'; |
| 15376 | buffer += input; |
| 15377 | return; |
no test coverage detected