diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-16 16:14:50 -0700 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-16 16:14:50 -0700 |
| commit | a9b1541fd6d308a17848ab4eb5396598ffa1a240 (patch) | |
| tree | e0be4643416b779b1e44b271b02a8eafa9efd928 /toolsrc/src | |
| parent | 4e48a1c235d776b5099a61252ff726edb5b6a6b7 (diff) | |
| download | vcpkg-a9b1541fd6d308a17848ab4eb5396598ffa1a240.tar.gz vcpkg-a9b1541fd6d308a17848ab4eb5396598ffa1a240.zip | |
[vcpkg, xml] Parse with string-search instead of regex
Resolves issue with inconsistent regex behavior between platforms.
For example [/s/S]*? does not properly match on Clang. String-searching is
also generally more performant.
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/vcpkg/commands.fetch.cpp | 83 |
1 files changed, 40 insertions, 43 deletions
diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 7a1e6a810..1e31e6bc4 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -41,6 +41,22 @@ namespace vcpkg::Commands::Fetch return result; } + static Optional<std::string> extract_string_between_delimiters(const std::string& input, + const std::string& left_delim, + const std::string& right_delim, + const size_t& starting_offset = 0) + { + const size_t from = input.find(left_delim, starting_offset); + if (from == std::string::npos) return nullopt; + + const size_t substring_start = from + left_delim.length(); + + const size_t to = input.find(right_delim, substring_start); + if (from == std::string::npos) return nullopt; + + return input.substr(substring_start, to - substring_start); + } + static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) { #if defined(_WIN32) @@ -57,33 +73,21 @@ namespace vcpkg::Commands::Fetch static const std::string XML_VERSION = "2"; static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; - const auto maybe_get_string_inside_tags = [](const std::string& input, - const std::regex& regex) -> Optional<std::string> { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - if (!has_match) return nullopt; - return match[1]; - }; - const auto get_string_inside_tags = - [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { - std::smatch match; - const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); - Checks::check_exit( - VCPKG_LINE_INFO, has_match, "Could not find tag <%s> in %s", tag_name, XML_PATH.generic_string()); + [](const std::string& input, const std::string& left_delim, const std::string& right_delim) -> std::string { + Optional<std::string> result = extract_string_between_delimiters(input, left_delim, right_delim); + Checks::check_exit(VCPKG_LINE_INFO, + result.has_value(), + "Could not find tag <%s>.*<%s> in %s", + left_delim, + right_delim, + XML_PATH.generic_string()); - return match[1]; + return *result.get(); }; static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"}; static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO); - static const std::regex VERSION_REGEX{R"###(<version>([\s\S]*?)</version>)###"}; - static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(<exeRelativePath>([\s\S]*?)</exeRelativePath>)###")}; - static const std::regex ARCHIVE_NAME_REGEX{Strings::format(R"###(<archiveName>([\s\S]*?)</archiveName>)###")}; - static const std::regex URL_REGEX{Strings::format(R"###(<url>([\s\S]*?)</url>)###")}; - static const std::regex SHA512_REGEX{Strings::format(R"###(<sha512>([\s\S]*?)</sha512>)###")}; - std::smatch match_xml_version; const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX); Checks::check_exit(VCPKG_LINE_INFO, @@ -98,43 +102,36 @@ namespace vcpkg::Commands::Fetch XML_VERSION, match_xml_version[1]); - const std::regex tool_regex{ - Strings::format(R"###(<tool[\s]+name="%s"[\s]+os="%s">([\s\S]*?)<\/tool>)###", tool, OS_STRING)}; - - std::smatch match_tool; - const bool has_match_tool = std::regex_search(XML.cbegin(), XML.cend(), match_tool, tool_regex); + const std::regex tool_regex{Strings::format(R"###(<tool[\s]+name="%s"[\s]+os="%s">)###", tool, OS_STRING)}; + std::smatch match_tool_entry; + const bool has_tool_entry = std::regex_search(XML.cbegin(), XML.cend(), match_tool_entry, tool_regex); Checks::check_exit(VCPKG_LINE_INFO, - has_match_tool, + has_tool_entry, "Could not find entry for tool [%s] in %s", tool, XML_PATH.generic_string()); - const std::string tool_data_as_string = get_string_inside_tags(XML, tool_regex, tool); - - const std::string required_version_as_string = - get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "version"); - - const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); + const std::string tool_data = get_string_inside_tags(XML, match_tool_entry[0], R"(</tool>)"); + const std::string version_as_string = get_string_inside_tags(tool_data, "<version>", R"(</version>)"); const std::string exe_relative_path = - get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); - - auto archive_name = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_NAME_REGEX); + get_string_inside_tags(tool_data, "<exeRelativePath>", R"(</exeRelativePath>)"); + const std::string url = get_string_inside_tags(tool_data, "<url>", R"(</url>)"); + const std::string sha512 = get_string_inside_tags(tool_data, "<sha512>", R"(</sha512>)"); + auto archive_name = extract_string_between_delimiters(tool_data, "<archiveName>", R"(</archiveName>)"); - const Optional<std::array<int, 3>> required_version = parse_version_string(required_version_as_string); + const Optional<std::array<int, 3>> version = parse_version_string(version_as_string); Checks::check_exit(VCPKG_LINE_INFO, - required_version.has_value(), + version.has_value(), "Could not parse version for tool %s. Version string was: %s", tool, - required_version_as_string); + version_as_string); - const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, required_version_as_string, OS_STRING); + const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING); const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name; const fs::path exe_path = tool_dir_path / exe_relative_path; - const std::string sha512 = get_string_inside_tags(tool_data_as_string, SHA512_REGEX, "sha512"); - - return ToolData{*required_version.get(), + return ToolData{*version.get(), exe_path, url, paths.downloads / archive_name.value_or(exe_relative_path), |
