libcruft-util/cruft/util/iterator/transform.hpp

86 lines
2.5 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "../view.hpp"
#include <algorithm>
#include <utility>
namespace cruft::iterator {
///////////////////////////////////////////////////////////////////////////
template <typename OutputIt, typename FunctionT>
OutputIt
_transform_by_block (
const cruft::view<OutputIt> &,
OutputIt cursor,
FunctionT &&
) {
return cursor;
}
//-------------------------------------------------------------------------
template <typename OutputIt, typename FunctionT, typename InputT, typename ...TailT>
OutputIt
_transform_by_block (
const cruft::view<OutputIt> &dst,
OutputIt cursor,
FunctionT &&func,
const InputT &_src,
TailT &&...tail
) {
auto remain = _src;
if (cursor != dst.begin ()) {
auto infill = std::distance (cursor, dst.end ());
if (remain.size () < static_cast<size_t> (infill)) {
return _transform_by_block (
dst,
std::copy_n (remain.begin (), remain.size (), cursor),
std::forward<FunctionT> (func),
std::forward<TailT> (tail)...
);
}
std::copy_n (remain.begin (), infill, cursor);
func (dst);
cursor = dst.begin ();
remain = { remain.begin () + infill, remain.end () };
}
while (remain.size () >= dst.size ()) {
std::copy_n (remain.begin (), dst.size (), dst.begin ());
func (dst);
remain = { remain.begin () + dst.size (), remain.end () };
}
return _transform_by_block (
dst,
std::copy (remain.begin (), remain.end (), cursor),
std::forward<FunctionT> (func),
std::forward<TailT> (tail)...
);
}
//-------------------------------------------------------------------------
template <typename OutputIt, typename FunctionT, typename ...Args>
OutputIt
transform_by_block (const cruft::view<OutputIt> &dst, FunctionT &&func, Args &&...src)
{
return _transform_by_block (
dst,
dst.begin (),
std::forward<FunctionT> (func),
std::forward<Args> (src)...
);
}
};