blob: 3f5356172cbc1fc62f708ac8fa45ab68bdb2e020 [file] [edit]
// Copyright 2025 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BASE_ALGORITHM_H_
#define V8_BASE_ALGORITHM_H_
#include <algorithm>
#include <iterator>
#include <type_traits>
#include "src/base/memcopy.h"
namespace v8::base {
namespace internal {
template <class InputIt, class OutputIt>
constexpr bool can_use_memcpy_v =
std::contiguous_iterator<InputIt> && std::contiguous_iterator<OutputIt> &&
std::is_same_v<typename std::iterator_traits<InputIt>::value_type,
typename std::iterator_traits<OutputIt>::value_type> &&
std::is_trivially_copyable_v<
typename std::iterator_traits<InputIt>::value_type>;
} // namespace internal
// Version of `std::copy()` that delegates to `base::MemCopy()` when possible.
// Unlike `std::copy()` we don't allow any overlaps as our implementation
// assumes `std::execution::par_unseq` execution policy under the hood.
template <class InputIt, class OutputIt>
OutputIt Copy(InputIt first, InputIt last, OutputIt d_first)
requires(internal::can_use_memcpy_v<InputIt, OutputIt>)
{
using T = typename std::iterator_traits<InputIt>::value_type;
const auto count = std::distance(first, last);
const T* src_ptr = std::to_address(first);
T* dest_ptr = std::to_address(d_first);
base::MemCopy(dest_ptr, src_ptr, count * sizeof(T));
return d_first + count;
}
template <class InputIt, class OutputIt>
constexpr OutputIt Copy(InputIt first, InputIt last, OutputIt d_first)
requires(!internal::can_use_memcpy_v<InputIt, OutputIt>)
{
return std::copy(first, last, d_first);
}
} // namespace v8::base
#endif // V8_BASE_ALGORITHM_H_