mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			184 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
/*
 | 
						|
 *  Created by Phil Nash on 21/02/2017.
 | 
						|
 *  Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved.
 | 
						|
 *
 | 
						|
 * Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
						|
 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 */
 | 
						|
#ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
 | 
						|
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
 | 
						|
 | 
						|
#include "catch_matchers.h"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
namespace Catch {
 | 
						|
namespace Matchers {
 | 
						|
 | 
						|
    namespace Vector {
 | 
						|
        namespace Detail {
 | 
						|
            template <typename InputIterator, typename T>
 | 
						|
            size_t count(InputIterator first, InputIterator last, T const& item) {
 | 
						|
                size_t cnt = 0;
 | 
						|
                for (; first != last; ++first) {
 | 
						|
                    if (*first == item) {
 | 
						|
                        ++cnt;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return cnt;
 | 
						|
            }
 | 
						|
            template <typename InputIterator, typename T>
 | 
						|
            bool contains(InputIterator first, InputIterator last, T const& item) {
 | 
						|
                for (; first != last; ++first) {
 | 
						|
                    if (*first == item) {
 | 
						|
                        return true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                for (auto const& el : v) {
 | 
						|
                    if (el == m_comparator) {
 | 
						|
                        return true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
 | 
						|
            T const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct ContainsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                // !TBD: see note in EqualsMatcher
 | 
						|
                if (m_comparator.size() > v.size())
 | 
						|
                    return false;
 | 
						|
                for (auto const& comparator : m_comparator) {
 | 
						|
                    auto present = false;
 | 
						|
                    for (const auto& el : v) {
 | 
						|
                        if (el == comparator) {
 | 
						|
                            present = true;
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if (!present) {
 | 
						|
                        return false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
 | 
						|
            std::vector<T> const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct EqualsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                // !TBD: This currently works if all elements can be compared using !=
 | 
						|
                // - a more general approach would be via a compare template that defaults
 | 
						|
                // to using !=. but could be specialised for, e.g. std::vector<T> etc
 | 
						|
                // - then just call that directly
 | 
						|
                if (m_comparator.size() != v.size())
 | 
						|
                    return false;
 | 
						|
                for (std::size_t i = 0; i < v.size(); ++i)
 | 
						|
                    if (m_comparator[i] != v[i])
 | 
						|
                        return false;
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Equals: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
            std::vector<T> const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
            UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
 | 
						|
            bool match(std::vector<T> const& vec) const override {
 | 
						|
                // Note: This is a reimplementation of std::is_permutation,
 | 
						|
                //       because I don't want to include <algorithm> inside the common path
 | 
						|
                if (m_target.size() != vec.size()) {
 | 
						|
                    return false;
 | 
						|
                }
 | 
						|
                auto lfirst = m_target.begin(), llast = m_target.end();
 | 
						|
                auto rfirst = vec.begin(), rlast = vec.end();
 | 
						|
                // Cut common prefix to optimize checking of permuted parts
 | 
						|
                while (lfirst != llast && *lfirst != *rfirst) {
 | 
						|
                    ++lfirst; ++rfirst;
 | 
						|
                }
 | 
						|
                if (lfirst == llast) {
 | 
						|
                    return true;
 | 
						|
                }
 | 
						|
 | 
						|
                for (auto mid = lfirst; mid != llast; ++mid) {
 | 
						|
                    // Skip already counted items
 | 
						|
                    if (Detail::contains(lfirst, mid, *mid)) {
 | 
						|
                        continue;
 | 
						|
                    }
 | 
						|
                    size_t num_vec = Detail::count(rfirst, rlast, *mid);
 | 
						|
                    if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
 | 
						|
                        return false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
 | 
						|
            std::string describe() const override {
 | 
						|
                return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
 | 
						|
            }
 | 
						|
        private:
 | 
						|
            std::vector<T> const& m_target;
 | 
						|
        };
 | 
						|
 | 
						|
    } // namespace Vector
 | 
						|
 | 
						|
    // The following functions create the actual matcher objects.
 | 
						|
    // This allows the types to be inferred
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
 | 
						|
        return Vector::ContainsMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
 | 
						|
        return Vector::ContainsElementMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
 | 
						|
        return Vector::EqualsMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
 | 
						|
        return Vector::UnorderedEqualsMatcher<T>(target);
 | 
						|
    }
 | 
						|
 | 
						|
} // namespace Matchers
 | 
						|
} // namespace Catch
 | 
						|
 | 
						|
#endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
 |