diff --git a/BaseLib/excludeObjectCopy.h b/BaseLib/excludeObjectCopy.h new file mode 100644 index 0000000000000000000000000000000000000000..b5ad58c55259dedf52c2970ed9edf1ff60bba925 --- /dev/null +++ b/BaseLib/excludeObjectCopy.h @@ -0,0 +1,66 @@ +/** + * + * \copyright + * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#ifndef EXCLUDEOBJECTCOPIER_H_ +#define EXCLUDEOBJECTCOPIER_H_ + +#include <vector> +#include <algorithm> + +namespace BaseLib +{ + +/// excludeObjectCopy copies only those objects that position within the source +/// vector is not in the exclude_positions vector. The implementation of the +/// algorithm requires that the given positions in exclude_positions are sorted +/// in ascending order. +/// @param src_vec the vector of source objects +/// @param exclude_positions the positions of objects in the source vector that +/// do not have to be copied +/// @return vector that contains the copied objects +template <typename T> +std::vector<T> excludeObjectCopy(std::vector<T> const& src_vec, + std::vector<std::size_t> const& exclude_positions) +{ + std::vector<T> dest_vec; + if (exclude_positions.empty()) { + dest_vec = src_vec; + return dest_vec; + } + + assert (exclude_positions.back() < src_vec.size()); + + std::copy_n(src_vec.cbegin(), exclude_positions[0], std::back_inserter(dest_vec)); + for (std::size_t i=1; i<exclude_positions.size(); ++i) { + std::copy_n( + src_vec.cbegin()+exclude_positions[i-1]+1, + exclude_positions[i]-(exclude_positions[i-1]+1), + std::back_inserter(dest_vec) + ); + } + std::copy(src_vec.cbegin()+exclude_positions.back()+1, + src_vec.cend(), std::back_inserter(dest_vec)); + + return dest_vec; +} + +template <typename T> +void excludeObjectCopy(std::vector<T> const& src_vec, + std::vector<std::size_t> const& exclude_positions, + std::vector<T> & dest_vec) +{ + dest_vec = excludeObjectCopy(src_vec, exclude_positions); +} + + +} // end namespace BaseLib + +#endif + diff --git a/Tests/BaseLib/excludeObjectCopy.cpp b/Tests/BaseLib/excludeObjectCopy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a832d6b896a2d3b1b15dc037d3436469be244180 --- /dev/null +++ b/Tests/BaseLib/excludeObjectCopy.cpp @@ -0,0 +1,59 @@ +/** + * \date 2015-03-18 + * \brief + * + * \copyright + * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include <algorithm> +#include <cstddef> +#include <vector> + +#include "gtest/gtest.h" + +#include "BaseLib/excludeObjectCopy.h" + +TEST(BaseLib, excludeObjectCopy) +{ + // create and fill vector + std::size_t const size(100); + std::vector<std::size_t> v(size); + std::iota(v.begin(), v.end(), 0); + + std::vector<std::size_t> ex_positions(size/10); + // do not copy first 10 elements + std::iota(ex_positions.begin(), ex_positions.end(), 0); + + std::vector<std::size_t> c1(BaseLib::excludeObjectCopy(v,ex_positions)); + ASSERT_EQ(size-ex_positions.size(), c1.size()); + + for (std::size_t i(0); i<c1.size(); i++) + ASSERT_EQ(c1[i], v[size/10+i]); + + // do not copy element 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 + std::transform(ex_positions.begin(), ex_positions.end(), + ex_positions.begin(), std::bind1st(std::multiplies<size_t>(),2)); + + std::vector<std::size_t> c2(BaseLib::excludeObjectCopy(v,ex_positions)); + ASSERT_EQ(size-ex_positions.size(), c2.size()); + + for (std::size_t i(0); i<ex_positions.size(); i++) + ASSERT_EQ(c2[i], v[2*i+1]); + for (std::size_t i(ex_positions.size()); i<c2.size(); i++) + ASSERT_EQ(c2[i], v[ex_positions.size()+i]); + + // do not copy the last element + ex_positions.clear(); + ex_positions.push_back(99); + + std::vector<std::size_t> c3(BaseLib::excludeObjectCopy(v,ex_positions)); + ASSERT_EQ(size-ex_positions.size(), c3.size()); + + for (std::size_t i(0); i<c3.size(); i++) + ASSERT_EQ(c3[i], v[i]); +}