mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-08-04 01:36:10 -04:00
259 lines
6.9 KiB
C++
259 lines
6.9 KiB
C++
//=======================================================================
|
|
// Copyright Baptiste Wicht 2013-2016.
|
|
// 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 ALGORITHMS_H
|
|
#define ALGORITHMS_H
|
|
|
|
#include <type_traits.hpp>
|
|
#include <utility.hpp>
|
|
#include <types.hpp>
|
|
#include <enable_if.hpp>
|
|
|
|
namespace std {
|
|
|
|
/*!
|
|
* \brief Copies all elements in the range [first, last).
|
|
*
|
|
* The behavior is undefined if d_first is within the range [first, last)
|
|
*
|
|
* \param first The beginning of the range
|
|
* \param last The end of the range
|
|
* \param d_first The output iterator
|
|
*/
|
|
template<typename InputIterator, typename OutputIterator>
|
|
void copy(InputIterator first, InputIterator last, OutputIterator d_first){
|
|
if(first != last){
|
|
*d_first = *first;
|
|
|
|
while(++first != last){
|
|
*++d_first = *first;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Copy bytes bytes of memory from in to out
|
|
* \param out Pointer to the output
|
|
* \param in Pointer to the input
|
|
* \param bytes The number of bytes
|
|
*/
|
|
inline void memcpy(char* out, const char* in, size_t bytes){
|
|
if(!bytes){
|
|
return;
|
|
}
|
|
|
|
// Copy as much as possible 64 bits at at time
|
|
if(bytes >= 8){
|
|
auto* out64 = reinterpret_cast<uint64_t*>(out);
|
|
auto* in64 = reinterpret_cast<const uint64_t*>(in);
|
|
|
|
const size_t l = bytes / 8;
|
|
|
|
for(size_t i = 0; i < l; ++i){
|
|
out64[i] = in64[i];
|
|
}
|
|
|
|
bytes -= l * 8;
|
|
out += l * 8;
|
|
in += l * 8;
|
|
}
|
|
|
|
// Finish up byte by byte
|
|
while(bytes >= 1){
|
|
*out++ = *in++;
|
|
--bytes;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Copies exactly count values from the range beginning at first to the range beginning at result, if count>0. Does nothing otherwise.
|
|
* \param first The beginning of the input range
|
|
* \param count The number fo elements to copy
|
|
* \param out The output iterator
|
|
*/
|
|
template<typename InputIterator, typename OutputIterator, std::enable_if_t<!std::has_trivial_assign<typename std::iterator_traits<OutputIterator>::value_type>::value, int> = 42>
|
|
void copy_n(InputIterator first, size_t count, OutputIterator out){
|
|
if(count > 0){
|
|
*out = *first;
|
|
|
|
while(--count){
|
|
*++out = *++first;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Copies exactly count values from the range beginning at first to the range beginning at result, if count>0. Does nothing otherwise.
|
|
* \param first The beginning of the input range
|
|
* \param count The number fo elements to copy
|
|
* \param out The output iterator
|
|
*/
|
|
template<typename InputIterator, typename OutputIterator, std::enable_if_t<std::has_trivial_assign<typename std::iterator_traits<OutputIterator>::value_type>::value, int> = 42>
|
|
void copy_n(InputIterator first, size_t count, OutputIterator out){
|
|
memcpy(reinterpret_cast<char*>(out), reinterpret_cast<const char*>(first), count * sizeof(decltype(*out)));
|
|
}
|
|
|
|
/*!
|
|
* \brief Moves exactly count values from the range beginning at first to the range beginning at result, if count>0. Does nothing otherwise.
|
|
* \param first The beginning of the input range
|
|
* \param count The number fo elements to move
|
|
* \param out The output iterator
|
|
*/
|
|
template<typename InputIterator, typename OutputIterator>
|
|
void move_n(InputIterator in, size_t n, OutputIterator out){
|
|
if(n > 0){
|
|
*out = std::move(*in);
|
|
|
|
while(--n){
|
|
*++out = std::move(*++in);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Clear bytes bytes of memory from out
|
|
* \param out Pointer to the output
|
|
* \param bytes The number of bytes
|
|
*/
|
|
inline void memclr(char* out, size_t bytes){
|
|
if(!bytes){
|
|
return;
|
|
}
|
|
|
|
// Copy as much as possible 64 bits at at time
|
|
if(bytes >= 8){
|
|
auto* out64 = reinterpret_cast<uint64_t*>(out);
|
|
|
|
const size_t l = bytes / 8;
|
|
|
|
for(size_t i = 0; i < l; ++i){
|
|
out64[i] = 0;
|
|
}
|
|
|
|
bytes -= l * 8;
|
|
out += l * 8;
|
|
}
|
|
|
|
// Finish up byte by byte
|
|
while(bytes >= 1){
|
|
*out++ = 0;
|
|
--bytes;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Assigns the given value to the elements in the range [first, last).
|
|
* \param first The beginning of the range
|
|
* \param last The end of the range
|
|
* \param value The value to write
|
|
*/
|
|
template<typename ForwardIterator, typename T>
|
|
void fill(ForwardIterator first, ForwardIterator last, const T& value){
|
|
if(first != last){
|
|
*first = value;
|
|
|
|
while(++first != last){
|
|
*first = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Assigns the given value to the first count elements in the range beginning at
|
|
* first if count > 0. Does nothing otherwise.
|
|
* \param first The beginning of the range
|
|
* \param count The number of elements
|
|
* \param value The value to write
|
|
*/
|
|
template<typename ForwardIterator, typename T, std::enable_if_t<!std::has_trivial_assign<typename std::iterator_traits<ForwardIterator>::value_type>::value, int> = 42>
|
|
void fill_n(ForwardIterator first, size_t count, const T& value){
|
|
if(count > 0){
|
|
*first = value;
|
|
|
|
while(--count){
|
|
*++first = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Assigns the given value to the first count elements in the range beginning at
|
|
* first if count > 0. Does nothing otherwise.
|
|
* \param first The beginning of the range
|
|
* \param count The number of elements
|
|
* \param value The value to write
|
|
*/
|
|
template<typename ForwardIterator, typename T, std::enable_if_t<std::has_trivial_assign<typename std::iterator_traits<ForwardIterator>::value_type>::value, int> = 42>
|
|
void fill_n(ForwardIterator first, size_t count, const T& value){
|
|
if(!value){
|
|
memclr(reinterpret_cast<char*>(first), count * sizeof(decltype(*first)));
|
|
} else {
|
|
if(count > 0){
|
|
*first = value;
|
|
|
|
while(--count){
|
|
*++first = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename Iterator1, typename Iterator2>
|
|
size_t compare_n(Iterator1 it1, Iterator2 it2, size_t count){
|
|
if(count > 0){
|
|
while(count--){
|
|
if(*it1 != *it2){
|
|
return *it1- *it2;
|
|
} else {
|
|
++it1;
|
|
++it2;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
template<typename Iterator1, typename Iterator2>
|
|
bool equal_n(Iterator1 it1, Iterator2 it2, size_t n){
|
|
return compare_n(it1, it2, n) == 0;
|
|
}
|
|
|
|
template<typename Iterator, typename Functor>
|
|
void for_each(Iterator it, Iterator end, Functor func){
|
|
while(it != end){
|
|
func(*it);
|
|
|
|
++it;
|
|
}
|
|
}
|
|
|
|
template<class Iterator, class T>
|
|
T accumulate(Iterator it, Iterator end, T init){
|
|
while(it != end){
|
|
init = init + *it;
|
|
|
|
++it;
|
|
}
|
|
|
|
return init;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr const T& min(const T& a, const T& b){
|
|
return a <= b ? a : b;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr const T& max(const T& a, const T& b){
|
|
return a >= b ? a : b;
|
|
}
|
|
|
|
} //end of namespace std
|
|
|
|
#endif
|