mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

platform/cxxsupport/mstd_iterator

Committer:
kenjiArai
Date:
2019-12-31
Revision:
1:9db0e321a9f4

File content as of revision 1:9db0e321a9f4:

/* 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_