| 11769 | } |
| 11770 | |
| 11771 | ada_really_inline void parse_prepared_path(std::string_view input, |
| 11772 | ada::scheme::type type, |
| 11773 | std::string& path) { |
| 11774 | ada_log("parse_prepared_path ", input); |
| 11775 | uint8_t accumulator = checkers::path_signature(input); |
| 11776 | // Let us first detect a trivial case. |
| 11777 | // If it is special, we check that we have no dot, no %, no \ and no |
| 11778 | // character needing percent encoding. Otherwise, we check that we have no %, |
| 11779 | // no dot, and no character needing percent encoding. |
| 11780 | constexpr uint8_t need_encoding = 1; |
| 11781 | constexpr uint8_t backslash_char = 2; |
| 11782 | constexpr uint8_t dot_char = 4; |
| 11783 | constexpr uint8_t percent_char = 8; |
| 11784 | bool special = type != ada::scheme::NOT_SPECIAL; |
| 11785 | bool may_need_slow_file_handling = (type == ada::scheme::type::FILE && |
| 11786 | checkers::is_windows_drive_letter(input)); |
| 11787 | bool trivial_path = |
| 11788 | (special ? (accumulator == 0) |
| 11789 | : ((accumulator & (need_encoding | dot_char | percent_char)) == |
| 11790 | 0)) && |
| 11791 | (!may_need_slow_file_handling); |
| 11792 | if (accumulator == dot_char && !may_need_slow_file_handling) { |
| 11793 | // '4' means that we have at least one dot, but nothing that requires |
| 11794 | // percent encoding or decoding. The only part that is not trivial is |
| 11795 | // that we may have single dots and double dots path segments. |
| 11796 | // If we have such segments, then we either have a path that begins |
| 11797 | // with '.' (easy to check), or we have the sequence './'. |
| 11798 | // Note: input cannot be empty, it must at least contain one character ('.') |
| 11799 | // Note: we know that '\' is not present. |
| 11800 | if (input[0] != '.') { |
| 11801 | size_t slashdot = 0; |
| 11802 | bool dot_is_file = true; |
| 11803 | for (;;) { |
| 11804 | slashdot = input.find("/.", slashdot); |
| 11805 | if (slashdot == std::string_view::npos) { // common case |
| 11806 | break; |
| 11807 | } else { // uncommon |
| 11808 | // only three cases matter: /./, /.. or a final / |
| 11809 | slashdot += 2; |
| 11810 | dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' || |
| 11811 | input[slashdot] == '/'); |
| 11812 | } |
| 11813 | } |
| 11814 | trivial_path = dot_is_file; |
| 11815 | } |
| 11816 | } |
| 11817 | if (trivial_path) { |
| 11818 | ada_log("parse_path trivial"); |
| 11819 | path += '/'; |
| 11820 | path += input; |
| 11821 | return; |
| 11822 | } |
| 11823 | // We are going to need to look a bit at the path, but let us see if we can |
| 11824 | // ignore percent encoding *and* backslashes *and* percent characters. |
| 11825 | // Except for the trivial case, this is likely to capture 99% of paths out |
| 11826 | // there. |
| 11827 | bool fast_path = |
| 11828 | (special && |
no test coverage detected