| ++str_iter; | ++str_iter; | ||||
| } | } | ||||
| auto name = trim(std::string_view(str_begin, str_iter - str_begin)); | |||||
| auto version_str = trim(std::string_view(str_iter, str_end - str_iter)); | |||||
| auto name = trim_view(std::string_view(str_begin, str_iter - str_begin)); | |||||
| auto version_str = trim_view(std::string_view(str_iter, str_end - str_iter)); | |||||
| semver::version version; | semver::version version; | ||||
| try { | try { | ||||
| return std::tuple(sd.manifest.name, sd.manifest.version.to_string()); | return std::tuple(sd.manifest.name, sd.manifest.version.to_string()); | ||||
| } | } | ||||
| auto sdist_compare = [](const sdist& lhs, const sdist& rhs) { | |||||
| return tie_sdist(lhs) < tie_sdist(rhs); | |||||
| }; | |||||
| auto sdist_compare | |||||
| = [](const sdist& lhs, const sdist& rhs) { return tie_sdist(lhs) < tie_sdist(rhs); }; | |||||
| void detail::sort_sdists(std::vector<sdist>& sd) { std::sort(sd.begin(), sd.end(), sdist_compare); } | void detail::sort_sdists(std::vector<sdist>& sd) { std::sort(sd.begin(), sd.end(), sdist_compare); } | ||||
| namespace { | namespace { | ||||
| const sdist* get_sdist(const std::vector<sdist>& sorted_sds, std::string_view name, std::string_view version) { | |||||
| auto found = std::partition_point(sorted_sds.begin(), sorted_sds.end(), [&](const auto& candidate) { | |||||
| return tie_sdist(candidate) < std::tie(name, version); | |||||
| }); | |||||
| const sdist* | |||||
| get_sdist(const std::vector<sdist>& sorted_sds, std::string_view name, std::string_view version) { | |||||
| auto found | |||||
| = std::partition_point(sorted_sds.begin(), sorted_sds.end(), [&](const auto& candidate) { | |||||
| return tie_sdist(candidate) < std::tie(name, version); | |||||
| }); | |||||
| if (found->manifest.name == name && found->manifest.version.to_string() == version) { | if (found->manifest.name == name && found->manifest.version.to_string() == version) { | ||||
| return &*found; | return &*found; | ||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | |||||
| } // namespace | |||||
| void detail::do_find_deps(const std::vector<sdist>& sdists, | void detail::do_find_deps(const std::vector<sdist>& sdists, | ||||
| const dependency& dep, | const dependency& dep, |
| inline std::string_view sview(std::string_view::const_iterator beg, | inline std::string_view sview(std::string_view::const_iterator beg, | ||||
| std::string_view::const_iterator end) { | std::string_view::const_iterator end) { | ||||
| if (beg == end) { | |||||
| return ""; | |||||
| } | |||||
| return std::string_view(&*beg, static_cast<std::size_t>(std::distance(beg, end))); | return std::string_view(&*beg, static_cast<std::size_t>(std::distance(beg, end))); | ||||
| } | } | ||||
| inline std::string_view trim(std::string_view s) { | |||||
| inline std::string_view trim_view(std::string_view s) { | |||||
| auto iter = s.begin(); | auto iter = s.begin(); | ||||
| auto end = s.end(); | auto end = s.end(); | ||||
| while (iter != end && std::isspace(*iter)) { | while (iter != end && std::isspace(*iter)) { | ||||
| return sview(iter, new_end); | return sview(iter, new_end); | ||||
| } | } | ||||
| inline std::string_view trim(const char* str) { return trim(std::string_view(str)); } | |||||
| inline std::string trim(std::string&& s) { return std::string(trim(s)); } | |||||
| inline bool ends_with(std::string_view s, std::string_view key) { | inline bool ends_with(std::string_view s, std::string_view key) { | ||||
| auto found = s.rfind(key); | auto found = s.rfind(key); | ||||
| return found != s.npos && found == s.size() - key.size(); | return found != s.npos && found == s.size() - key.size(); |
| } | } | ||||
| void test_trim() { | void test_trim() { | ||||
| CHECK(trim("foo") == "foo"); | |||||
| CHECK(trim("foo ") == "foo"); | |||||
| CHECK(trim(" ").size() == 0); | |||||
| CHECK(trim_view("foo") == "foo"); | |||||
| CHECK(trim_view("foo ") == "foo"); | |||||
| CHECK(trim_view(" ").size() == 0); | |||||
| } | } | ||||
| void test_contains() { | void test_contains() { |
| for (const auto& pkg_line : package_lines) { | for (const auto& pkg_line : package_lines) { | ||||
| auto items = dds::split(pkg_line, ";"); | auto items = dds::split(pkg_line, ";"); | ||||
| std::transform(items.begin(), items.end(), items.begin(), [](auto s) { return trim(s); }); | |||||
| std::transform(items.begin(), items.end(), items.begin(), [](auto s) { | |||||
| return std::string(trim_view(s)); | |||||
| }); | |||||
| if (items.size() != 2) { | if (items.size() != 2) { | ||||
| throw std::runtime_error( | throw std::runtime_error( | ||||
| fmt::format("Invalid 'Package' field in index file ({}): 'Package: {}'", | fmt::format("Invalid 'Package' field in index file ({}): 'Package: {}'", |
| namespace { | namespace { | ||||
| void parse_line(std::vector<pair>& pairs, const std::string_view whole_line) { | void parse_line(std::vector<pair>& pairs, const std::string_view whole_line) { | ||||
| const auto line = trim(whole_line); | |||||
| const auto line = trim_view(whole_line); | |||||
| if (line.empty() || line[0] == '#') { | if (line.empty() || line[0] == '#') { | ||||
| return; | return; | ||||
| } | } | ||||
| // `iter` now points to the space between the key and value | // `iter` now points to the space between the key and value | ||||
| auto key = sview(begin, iter - 1); // -1 to trim the colon in the key | auto key = sview(begin, iter - 1); // -1 to trim the colon in the key | ||||
| auto value = sview(iter, end); | auto value = sview(iter, end); | ||||
| key = trim(key); | |||||
| value = trim(value); | |||||
| key = trim_view(key); | |||||
| value = trim_view(value); | |||||
| pairs.emplace_back(key, value); | pairs.emplace_back(key, value); | ||||
| } | } | ||||