|
23 | 23 | #include <algorithm> |
24 | 24 | #include <iomanip> |
25 | 25 | #include <fstream> |
| 26 | +#include <set> |
26 | 27 |
|
27 | 28 | #include <fmt/format.h> |
28 | 29 | #include <nlohmann/json.hpp> |
@@ -63,29 +64,27 @@ namespace { |
63 | 64 | }; |
64 | 65 | } |
65 | 66 |
|
66 | | - using Comparator = std::function<bool(const cs::Entry &lhs, const cs::Entry &rhs)>; |
| 67 | + using Hash = std::function<std::string(const cs::Entry &entry)>; |
67 | 68 |
|
68 | | - bool compare_by_output(const cs::Entry &lhs, const cs::Entry &rhs) { |
69 | | - // compare entries by the source and the output attribute only. |
70 | | - return (lhs.file == rhs.file) && (lhs.output == rhs.output); |
| 69 | + std::string hash_by_output(const cs::Entry &entry) { |
| 70 | + return fmt::format("{}<->{}", |
| 71 | + entry.file.string(), |
| 72 | + entry.output.value_or(fs::path()).string()); |
71 | 73 | } |
72 | 74 |
|
73 | | - bool compare_by_all(const cs::Entry &lhs, const cs::Entry &rhs) { |
74 | | - // compare entries by all possible attributes except the output field. |
75 | | - return (lhs.file == rhs.file) |
76 | | - && (lhs.directory == rhs.directory) |
77 | | - && (std::equal( |
78 | | - std::next(lhs.arguments.begin()), |
79 | | - lhs.arguments.end(), |
80 | | - std::next(rhs.arguments.begin()))); |
| 75 | + std::string hash_by_all(const cs::Entry &entry) { |
| 76 | + return fmt::format("{}<->{}<->{}", |
| 77 | + entry.file.string(), |
| 78 | + entry.directory.string(), |
| 79 | + fmt::join(std::next(entry.arguments.begin()), entry.arguments.end(), ",")); |
81 | 80 | } |
82 | 81 |
|
83 | | - Comparator select_comparator(const cs::Entries &lhs, const cs::Entries &rhs) { |
84 | | - // Select comparator based on the input values. |
| 82 | + Hash select_hash(const cs::Entries &lhs, const cs::Entries &rhs) { |
| 83 | + // Select hash function based on the input values. |
85 | 84 | const bool lhs_outputs = std::all_of(lhs.begin(), lhs.end(), [](auto entry) { return entry.output; }); |
86 | 85 | const bool rhs_outputs = std::all_of(rhs.begin(), rhs.end(), [](auto entry) { return entry.output; }); |
87 | 86 | // if all entries have the output field, it can compare by the output field. |
88 | | - return (lhs_outputs && rhs_outputs) ? compare_by_output : compare_by_all; |
| 87 | + return (lhs_outputs && rhs_outputs) ? hash_by_output : hash_by_all; |
89 | 88 | } |
90 | 89 | } |
91 | 90 |
|
@@ -239,14 +238,24 @@ namespace cs { |
239 | 238 | Entries merge(const Entries &lhs, const Entries &rhs) { |
240 | 239 | Entries result; |
241 | 240 | // create a predicate which decides if the entry is already in the result. |
242 | | - auto comparator = select_comparator(lhs, rhs); |
243 | | - auto not_in_result = [&result, &comparator](const auto &it) { |
244 | | - return std::none_of(result.begin(), result.end(), |
245 | | - [&comparator, &it](const auto &already_in) { return comparator(already_in, it); }); |
246 | | - }; |
247 | | - // apply the predicate. |
248 | | - std::copy_if(lhs.begin(), lhs.end(), std::back_inserter(result), not_in_result); |
249 | | - std::copy_if(rhs.begin(), rhs.end(), std::back_inserter(result), not_in_result); |
| 241 | + auto hasher = select_hash(lhs, rhs); |
| 242 | + std::set<std::string> in_results_hashes; |
| 243 | + // copy the elements into the result list depending if it already there. |
| 244 | + for (const auto &entry : lhs) { |
| 245 | + auto hash = hasher(entry); |
| 246 | + if (in_results_hashes.find(hash) == in_results_hashes.end()) { |
| 247 | + in_results_hashes.insert(hash); |
| 248 | + result.push_back(entry); |
| 249 | + } |
| 250 | + } |
| 251 | + for (const auto &entry : rhs) { |
| 252 | + auto hash = hasher(entry); |
| 253 | + if (in_results_hashes.find(hash) == in_results_hashes.end()) { |
| 254 | + in_results_hashes.insert(hash); |
| 255 | + result.push_back(entry); |
| 256 | + } |
| 257 | + } |
| 258 | + |
250 | 259 | return result; |
251 | 260 | } |
252 | 261 |
|
|
0 commit comments