From 2f0bfd605e4246f0a5c92b1f96abf235be80a3ab Mon Sep 17 00:00:00 2001 From: Marc Emmers Date: Fri, 6 Nov 2020 15:05:15 +0100 Subject: [PATCH] Adds basic span implementation --- platform/cxxsupport/mstd_span | 286 ++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 platform/cxxsupport/mstd_span diff --git a/platform/cxxsupport/mstd_span b/platform/cxxsupport/mstd_span new file mode 100644 index 0000000000..925f61465c --- /dev/null +++ b/platform/cxxsupport/mstd_span @@ -0,0 +1,286 @@ +/* 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_SPAN_ +#define MSTD_SPAN_ + +#include +#include + +namespace mstd { + +inline constexpr size_t dynamic_extent = -1; + +namespace detail { +template +class storage { +public: + constexpr storage() noexcept = default; + + constexpr storage(ElementType *ptr, size_t) noexcept : + _data(ptr) + {} + + ElementType* _data; + static constexpr size_t _size = Extent; +}; + +template +class storage { +public: + constexpr storage() noexcept = default; + + constexpr storage(ElementType *ptr, size_t size) noexcept : + _data(ptr), _size(size) + {} + + ElementType* _data; + size_t _size; +}; +} // namespace detail + +template +class span { +public: + using element_type = ElementType; + using value_type = typename mstd::remove_cv_t; + using index_type = size_t; + using difference_type = ptrdiff_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = pointer; + using reverse_iterator = std::reverse_iterator; + + static constexpr index_type extent = Extent; + + // Constructors, copy and assignment + template = 0> + constexpr span() noexcept + {} + + constexpr span(pointer ptr, index_type count) : + _storage(ptr, count) + { + MBED_ASSERT(extent == dynamic_extent || extent == count); + } + + constexpr span(pointer first, pointer last) : + _storage(first, last - first) + { + MBED_ASSERT(first <= last); + MBED_ASSERT(extent == dynamic_extent || extent == last - first); + MBED_ASSERT(extent == 0 || nullptr != first); + } + + template = 0> + constexpr span(element_type (&arr)[N]) noexcept: + _storage(arr, N) + {} + + template = 0> + constexpr span(array& arr) noexcept: + _storage(arr.data(), N) + {} + + template = 0> + constexpr span(const array& arr) noexcept: + _storage(arr.data(), N) + {} + + /* TODO + template + constexpr explicit(extent != dynamic_extent) span(R&& r) + */ + + constexpr span(const span& other) noexcept = default; + + template::value, int> = 0> + constexpr span(const span& s) noexcept: + _storage(s.data(), s.size()) + {} + + ~span() noexcept = default; + + constexpr span& operator=(const span& other) noexcept = default; + + // Subviews + template + constexpr span first() const + { + static_assert(Count <= extent); + MBED_ASSERT(Count <= size()); + return span(data(), Count); + } + + template + constexpr span last() const + { + static_assert(Count <= extent); + MBED_ASSERT(Count <= size()); + return span(data() + (size() - Count), Count); + } + + template + constexpr span subspan() const + { + static_assert(Offset <= extent && (Count == dynamic_extent || Count <= extent - Offset)); + MBED_ASSERT(Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset)); + return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset}; + } + + constexpr span first(index_type count) const + { + MBED_ASSERT(count <= size()); + return span(data(), count); + } + + constexpr span last(index_type count) const + { + MBED_ASSERT(count <= size()); + return span(data() + (size() - count), count); + } + + constexpr span + subspan(index_type offset, index_type count = dynamic_extent) const + { + MBED_ASSERT(offset <= size() && (count == dynamic_extent || count <= size() - offset )); + return span(data() + offset, count == dynamic_extent ? size() - offset : count ); + } + + // Observers + constexpr index_type size() const noexcept + { + return _storage._size; + } + + constexpr index_type size_bytes() const noexcept + { + return size() * sizeof(element_type); + } + + constexpr bool empty() const noexcept + { + return size() == 0; + } + + // Element access + constexpr reference operator[](index_type idx) const + { + MBED_ASSERT(idx < size()); + return *(data() + idx); + } + + constexpr reference front() const + { + MBED_ASSERT(not empty()); + return *data(); + } + + constexpr reference back() const + { + MBED_ASSERT(not empty()); + return *(data() + (size() - 1)); + } + + constexpr pointer data() const noexcept + { + return _storage._data; + } + + // Iterators + constexpr iterator begin() const noexcept + { + return data(); + } + + constexpr iterator end() const noexcept + { + return data() + size(); + } + + constexpr reverse_iterator rbegin() const noexcept + { + return reverse_iterator(end()); + } + + constexpr reverse_iterator rend() const noexcept + { + return reverse_iterator(begin()); + } + +private: + detail::storage _storage; +}; + +template +span +as_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +span +as_writable_bytes(span s) noexcept +{ + static_assert(not is_const::value); + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +constexpr span make_span(ElementType (&arr)[Extent]) +{ + return span(arr); +} + +template +constexpr span make_span(const ElementType (&arr)[Extent]) +{ + return span(arr); +} + +template +constexpr span make_span(array& arr) +{ + return span(arr); +} + +template +constexpr span make_span(const array& arr) +{ + return span(arr); +} + +/* TODO +template +constexpr span make_span(R&& cont) +{ + return {cont}; +} +*/ + +} // namespace mstd + +#endif // MSTD_MUTEX_ \ No newline at end of file