mirror of https://github.com/ARMmbed/mbed-os.git
461 lines
10 KiB
Plaintext
461 lines
10 KiB
Plaintext
/* mbed Microcontroller Library
|
|
* Copyright (c) 2019 ARM Limited
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef MSTD_ITERATOR_
|
|
#define MSTD_ITERATOR_
|
|
|
|
/* <mstd_iterator>
|
|
*
|
|
* - includes toolchain's <iterator>
|
|
* - For ARM C 5, C++11/14 features:
|
|
* - std::begin, std::end, etc
|
|
* - std::make_reverse_iterator
|
|
* - std::move_iterator, std::make_move_iterator
|
|
* - For all toolchains, C++17/20 backports:
|
|
* - mstd::size
|
|
* - mstd::ssize
|
|
* - mstd::empty
|
|
* - mstd::data
|
|
*/
|
|
|
|
#include <iterator>
|
|
#include <mstd_type_traits>
|
|
|
|
#ifdef __CC_ARM
|
|
|
|
#include <mstd_cstddef> // size_t
|
|
|
|
namespace std {
|
|
|
|
template <typename E>
|
|
struct initializer_list;
|
|
|
|
// [iterator.operations]
|
|
template <typename ForwardIterator>
|
|
ForwardIterator next(ForwardIterator x, typename iterator_traits<ForwardIterator>::difference_type n = 1)
|
|
{
|
|
advance(x, n);
|
|
return x;
|
|
}
|
|
|
|
template <typename BidirectionalIterator>
|
|
BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits<BidirectionalIterator>::difference_type n = 1)
|
|
{
|
|
advance(x, -n);
|
|
return x;
|
|
}
|
|
|
|
// [reverse.iter.make]
|
|
template <typename Iterator>
|
|
reverse_iterator<Iterator> make_reverse_iterator(Iterator i)
|
|
{
|
|
return reverse_iterator<Iterator>(i);
|
|
}
|
|
|
|
// [move.iterators]
|
|
template <typename Iterator>
|
|
class move_iterator {
|
|
Iterator current;
|
|
using R = typename iterator_traits<Iterator>::reference;
|
|
public:
|
|
using iterator_type = Iterator;
|
|
using iterator_category = typename iterator_traits<Iterator>::iterator_category;
|
|
using value_type = typename iterator_traits<Iterator>::value_type;
|
|
using difference_type = typename iterator_traits<Iterator>::difference_type;
|
|
using pointer = Iterator;
|
|
using reference = conditional_t<is_reference<R>::value,
|
|
remove_reference_t<R> &&,
|
|
R>;
|
|
|
|
// [move.iter.op.const]
|
|
constexpr move_iterator() : current() { }
|
|
constexpr explicit move_iterator(Iterator i) : current(i) { }
|
|
|
|
template <typename U>
|
|
constexpr move_iterator(const move_iterator<U> &u) : current(u.base()) { }
|
|
|
|
// [move.iter.op=]
|
|
template <typename U>
|
|
move_iterator &operator=(const move_iterator<U> &u)
|
|
{
|
|
current = u.base();
|
|
return *this;
|
|
}
|
|
|
|
// [move.iter.op.conv]
|
|
constexpr Iterator base() const
|
|
{
|
|
return current;
|
|
}
|
|
|
|
// [move.iter.op.star]
|
|
constexpr reference operator*() const
|
|
{
|
|
return static_cast<reference>(*current);
|
|
}
|
|
|
|
// [move.iter.op.ref]
|
|
constexpr pointer operator->() const
|
|
{
|
|
return current;
|
|
}
|
|
|
|
// [move.iter.op.incr]
|
|
move_iterator &operator++()
|
|
{
|
|
++current;
|
|
return *this;
|
|
}
|
|
|
|
move_iterator operator++(int)
|
|
{
|
|
move_iterator tmp = *this;
|
|
++current;
|
|
return tmp;
|
|
}
|
|
|
|
// [move.iter.op.decr]
|
|
move_iterator &operator--()
|
|
{
|
|
--current;
|
|
return *this;
|
|
}
|
|
|
|
move_iterator operator--(int)
|
|
{
|
|
move_iterator tmp = *this;
|
|
--current;
|
|
return tmp;
|
|
}
|
|
|
|
// [move.iter.op.+]
|
|
constexpr move_iterator operator+(difference_type n) const
|
|
{
|
|
return move_iterator(current + n);
|
|
}
|
|
|
|
// [move.iter.op.+=]
|
|
move_iterator &operator+=(difference_type n)
|
|
{
|
|
current += n;
|
|
return *this;
|
|
}
|
|
|
|
// [move.iter.op.-]
|
|
constexpr move_iterator operator-(difference_type n) const
|
|
{
|
|
return move_iterator(current - n);
|
|
}
|
|
|
|
// [move.iter.op.-=]
|
|
move_iterator &operator-=(difference_type n)
|
|
{
|
|
current -= n;
|
|
return *this;
|
|
}
|
|
|
|
// [move.iter.op.index]
|
|
constexpr auto operator[](difference_type n) const -> decltype(std::move(current[n]))
|
|
{
|
|
return std::move(current[n]);
|
|
}
|
|
};
|
|
|
|
// [move.iter.op.cmp]
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator==(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return x.base() == y.base();
|
|
}
|
|
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator!=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator<(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return x.base() < y.base();
|
|
}
|
|
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator<=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return !(y < x);
|
|
}
|
|
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator>(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return y < x;
|
|
}
|
|
|
|
template <typename Iterator1, typename Iterator2>
|
|
bool operator>=(const move_iterator<Iterator1> &x, const move_iterator<Iterator2> &y)
|
|
{
|
|
return !(x < y);
|
|
}
|
|
|
|
// [move.iter.nonmember]
|
|
template <typename Iterator1, typename Iterator2>
|
|
auto operator-(const move_iterator<Iterator1> &x,
|
|
const move_iterator<Iterator2> &y) -> decltype(x.base() - y.base())
|
|
{
|
|
return x.base() - y.base();
|
|
}
|
|
|
|
template <typename Iterator>
|
|
move_iterator<Iterator> operator+(typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator> &x)
|
|
{
|
|
return x + n;
|
|
}
|
|
|
|
template <typename Iterator>
|
|
constexpr move_iterator<Iterator> make_move_iterator(Iterator i)
|
|
{
|
|
return move_iterator<Iterator>(i);
|
|
}
|
|
|
|
// [iterator.range]
|
|
template <class C>
|
|
constexpr auto begin(C &c) -> decltype(c.begin())
|
|
{
|
|
return c.begin();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto begin(const C &c) -> decltype(c.begin())
|
|
{
|
|
return c.begin();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto end(C &c) -> decltype(c.end())
|
|
{
|
|
return c.end();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto end(const C &c) -> decltype(c.end())
|
|
{
|
|
return c.end();
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
constexpr T *begin(T (&array)[N]) noexcept
|
|
{
|
|
return array;
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
constexpr T *end(T (&array)[N]) noexcept
|
|
{
|
|
return array + N;
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto cbegin(const C &c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c))
|
|
{
|
|
return std::begin(c);
|
|
}
|
|
|
|
|
|
template <class C>
|
|
constexpr auto cend(const C &c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c))
|
|
{
|
|
return std::end(c);
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto rbegin(C &c) -> decltype(c.rbegin())
|
|
{
|
|
return c.rbegin();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto rbegin(const C &c) -> decltype(c.rbegin())
|
|
{
|
|
return c.rbegin();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto rend(C &c) -> decltype(c.rend())
|
|
{
|
|
return c.rend();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto rend(const C &c) -> decltype(c.rend())
|
|
{
|
|
return c.rend();
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
reverse_iterator<T *> rbegin(T (&array)[N])
|
|
{
|
|
return reverse_iterator<T *>(array + N);
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
reverse_iterator<T *> rend(T (&array)[N])
|
|
{
|
|
return reverse_iterator<T *>(array);
|
|
}
|
|
|
|
template <class E>
|
|
reverse_iterator<const E *> rbegin(initializer_list<E> il)
|
|
{
|
|
return reverse_iterator<const E *>(il.end());
|
|
}
|
|
|
|
template <class E>
|
|
reverse_iterator<const E *> rend(initializer_list<E> il)
|
|
{
|
|
return reverse_iterator<const E *>(il.end());
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto crbegin(const C &c) -> decltype(std::rbegin(c))
|
|
{
|
|
return std::rbegin(c);
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto crend(const C &c) -> decltype(std::rend(c))
|
|
{
|
|
return std::rend(c);
|
|
}
|
|
|
|
} // namespace std
|
|
#endif
|
|
|
|
namespace mstd {
|
|
using std::initializer_list;
|
|
using std::iterator_traits;
|
|
// omitting deprecated std::iterator
|
|
using std::input_iterator_tag;
|
|
using std::output_iterator_tag;
|
|
using std::forward_iterator_tag;
|
|
using std::bidirectional_iterator_tag;
|
|
using std::random_access_iterator_tag;
|
|
using std::advance;
|
|
using std::distance;
|
|
using std::next;
|
|
using std::prev;
|
|
using std::reverse_iterator;
|
|
using std::make_reverse_iterator;
|
|
using std::back_insert_iterator;
|
|
using std::back_inserter;
|
|
using std::front_insert_iterator;
|
|
using std::front_inserter;
|
|
using std::insert_iterator;
|
|
using std::inserter;
|
|
using std::move_iterator;
|
|
using std::make_move_iterator;
|
|
using std::istream_iterator;
|
|
using std::ostream_iterator;
|
|
using std::istreambuf_iterator;
|
|
using std::ostreambuf_iterator;
|
|
using std::begin;
|
|
using std::end;
|
|
using std::cbegin;
|
|
using std::cend;
|
|
using std::rbegin;
|
|
using std::rend;
|
|
using std::crbegin;
|
|
using std::crend;
|
|
|
|
#if __cpp_lib_nonmember_container_access >= 201411
|
|
using std::size;
|
|
using std::empty;
|
|
using std::data;
|
|
#else
|
|
// [iterator.container]
|
|
template <class C>
|
|
constexpr auto size(const C &c) -> decltype(c.size())
|
|
{
|
|
return c.size();
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
constexpr size_t size(const T (&)[N]) noexcept
|
|
{
|
|
return N;
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto empty(const C &c) -> decltype(c.empty())
|
|
{
|
|
return c.empty();
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
constexpr bool empty(T (&)[N]) noexcept
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class E>
|
|
constexpr bool empty(initializer_list<E> il)
|
|
{
|
|
return il.size() == 0;
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto data(C &c) -> decltype(c.data())
|
|
{
|
|
return c.data();
|
|
}
|
|
|
|
template <class C>
|
|
constexpr auto data(const C &c) -> decltype(c.data())
|
|
{
|
|
return c.data();
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
constexpr T *data(T (&array)[N]) noexcept
|
|
{
|
|
return array;
|
|
}
|
|
|
|
template <class E>
|
|
constexpr const E *data(initializer_list<E> il)
|
|
{
|
|
return il.begin();
|
|
}
|
|
#endif
|
|
|
|
// C++20
|
|
template <class C>
|
|
constexpr auto ssize(const C &c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>
|
|
{
|
|
return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());
|
|
}
|
|
|
|
template <class T, ptrdiff_t N>
|
|
constexpr ptrdiff_t ssize(const T (&)[N]) noexcept
|
|
{
|
|
return N;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#endif // MSTD_ITERATOR_
|