| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef VERIBLE_COMMON_UTIL_ALGORITHM_H_ |
| #define VERIBLE_COMMON_UTIL_ALGORITHM_H_ |
| |
| #include <algorithm> // for std::copy |
| #include <utility> // for std::pair |
| |
| namespace verible { |
| |
| // Same as std::set_symmetric_difference(), except that instead of outputting |
| // elements from both input sequences into the same output iterator, the |
| // differences go into separate output iterators. This allows the algorithm |
| // to work on heterogeneous types. |
| // CompareSigned, instead of returning a bool like operator<, must return a |
| // negative value if left<right, 0 if left==right, positive value if |
| // left>right. This change to Compare from the original algorithm is |
| // necessary because this comparison cannot be used commutatively to |
| // determine equality due to its heterogeneity. |
| // Respective input sequences must be ordered (in relation to their own |
| // element types). |
| // We don't provide a variant of set_symmetric_difference_split with a default |
| // comparator, because a default heterogeneous signed-compare is not intuitive. |
| template <class InputIt1, class InputIt2, class OutputIt1, class OutputIt2, |
| class CompareSigned> |
| std::pair<OutputIt1, OutputIt2> set_symmetric_difference_split( |
| InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, |
| OutputIt1 diff1, OutputIt2 diff2, CompareSigned comp) { |
| while (first1 != last1) { |
| if (first2 == last2) { |
| return std::make_pair(std::copy(first1, last1, diff1), diff2); |
| } |
| const auto sign = comp(*first1, *first2); |
| if (sign < 0) { |
| *diff1++ = *first1++; |
| } else if (sign > 0) { |
| *diff2++ = *first2++; |
| } else { // sign == 0 |
| ++first1; |
| ++first2; |
| } |
| } |
| return std::make_pair(diff1, std::copy(first2, last2, diff2)); |
| } |
| |
| // Assigns to the output all iterators at which the predicate evaluates true, |
| // like repeated calls to std::find_if(). |
| // Run time: O(N) because every element in [iter, end) is visited exactly once. |
| // Predicate may also be stateful. |
| // This can be very useful for partitioning ranges into sub-ranges, |
| // by finding boundaries at which to sub-divide. |
| template <class InputIter, class OutputIter, class Predicate> |
| void find_all(InputIter iter, InputIter end, OutputIter output, |
| Predicate pred) { |
| for (; iter != end; ++iter) { |
| if (pred(*iter)) *output = iter; |
| } |
| } |
| |
| // Adapts std::lexicographical_compare to work on two sequences (including |
| // containers, ranges, spans, views). |
| struct LexicographicalLess { |
| // Enable heterogenous lookup. |
| using is_transparent = void; |
| |
| // Compare two sequences lexicographically, element-by-element. |
| template <class T1, class T2> |
| bool operator()(const T1& left, const T2& right) const { |
| return std::lexicographical_compare(left.begin(), left.end(), right.begin(), |
| right.end()); |
| } |
| }; |
| |
| } // namespace verible |
| |
| #endif // VERIBLE_COMMON_UTIL_ALGORITHM_H_ |