From c6f3ec5fef73457618b908ec68c6fc70674cdb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 9 Mar 2022 13:59:11 +0100 Subject: [PATCH] Containers: rework slicing APIs for more consistency. The bulk of work is mainly in how these are presented and documented, with just two of them being deprecated in favor of better-named variants: - except() is now exceptSuffix(), since that's how I named the new StringView API that removes a string suffix, and it just makes much more sense that way. Too bad it took me so long to realize a good name. - As a consequence, suffix() is now exceptPrefix(), again consistent with the StringView API, because both take a prefix length and not suffix length. This means, once enough time passes (say, a year after a release the deprecated API gets removed, and then again a year), it can be reintroduced taking a *suffix* length, since that's what it should have been since the beginning. But again, I realized the inconsistency way too late. To ensure nothing is broken, existing code is not adapted to these changes -- only a new test is added for a new suffix() which could be added without clashes. Adapting the code will be done in the next commit. --- doc/corrade-changelog.dox | 18 +- doc/snippets/Containers.cpp | 9 +- src/Corrade/Containers/Array.h | 159 +++++++++--- src/Corrade/Containers/ArrayView.h | 244 ++++++++++++------ src/Corrade/Containers/StaticArray.h | 221 +++++++++++----- src/Corrade/Containers/StridedArrayView.h | 130 +++++++--- src/Corrade/Containers/String.cpp | 44 +++- src/Corrade/Containers/String.h | 84 ++++-- src/Corrade/Containers/StringView.h | 88 +++++-- src/Corrade/Containers/Test/ArrayTest.cpp | 12 +- src/Corrade/Containers/Test/ArrayViewTest.cpp | 10 + 11 files changed, 741 insertions(+), 278 deletions(-) diff --git a/doc/corrade-changelog.dox b/doc/corrade-changelog.dox index cd4b7e259..83391c1ee 100644 --- a/doc/corrade-changelog.dox +++ b/doc/corrade-changelog.dox @@ -343,6 +343,22 @@ namespace Corrade { other APIs returning a @cpp bool @ce as well as the new @ref Containers::String and @ref Containers::BasicStringView "StringView" APIs, which all use `isSomething()` instead. +- @ref Containers::Array, @relativeref{Containers,ArrayView}, + @relativeref{Containers,StaticArray}, + @relativeref{Containers,StaticArrayView} and + @relativeref{Containers,StridedArrayView} slicing APIs were reworked for + more consistency. In particular: + - @cpp except() @ce is deprecated in favor of + @relativeref{Containers::ArrayView,exceptSuffix()}, being consistent + with the new @ref Containers::StringView::exceptSuffix(StringView) const + API + - @cpp suffix() @ce is deprecated in favor of + @relativeref{Containers::ArrayView,exceptPrefix()}, being consistent + with the new @ref Containers::StringView::exceptPrefix(StringView) const + API, as both take a prefix length, and not suffix length. The + @cpp suffix() @ce API, taking a suffix length instead of an offset, is + scheduled to be reintroduced once enough time passes after the + deprecated API gets removed to avoid silent breakages in existing code. - @cpp Utility::Directory::isSandboxed() @ce is deprecated in favor of @ref Utility::System::isSandboxed(), as that's the better place for this API to live in @@ -851,7 +867,7 @@ Released 2019-10-24, tagged as @ref Containers::Array::slice() const and @ref Containers::StaticArray::slice() const variants that take both being and end offsets at compile time (and thus also more range checking at compile time) -- Added @ref Containers::ArrayView::except() and similar APIs to +- Added @cpp Containers::ArrayView::except() @ce and similar APIs to @ref Containers::StaticArrayView, @ref Containers::Array, @ref Containers::StaticArray and @ref Containers::StridedArrayView. It's like @ref Containers::ArrayView::prefix() but taking a count of items to diff --git a/doc/snippets/Containers.cpp b/doc/snippets/Containers.cpp index 492491a47..0bfbb01f7 100644 --- a/doc/snippets/Containers.cpp +++ b/doc/snippets/Containers.cpp @@ -410,11 +410,12 @@ if(view.size() > 2 && view[2] < 3) view[2] += 5; int data[]{0, 10, 20, 30, 40, 50, 60}; Containers::ArrayView view = data; -Containers::ArrayView a = view.slice(3, 5); // {30, 40, 50} -Containers::ArrayView b = view.prefix(4); // {0, 10, 20, 30} -Containers::ArrayView c = view.suffix(2); // {50, 60} -Containers::ArrayView d = view.except(2); // {0, 10, 20, 30, 40} +Containers::ArrayView a = view.slice(3, 5); // {30, 40, 50} +Containers::ArrayView b = view.prefix(4); // {0, 10, 20, 30} +Containers::ArrayView c = view.exceptPrefix(4); // {40, 50, 60} +Containers::ArrayView d = view.exceptSuffix(2); // {0, 10, 20, 30, 40} /* [ArrayView-usage-slicing] */ +/** @todo add suffix(2) above once it actually takes two last items */ static_cast(a); static_cast(b); static_cast(c); diff --git a/src/Corrade/Containers/Array.h b/src/Corrade/Containers/Array.h index c71da520c..f43aee4e4 100644 --- a/src/Corrade/Containers/Array.h +++ b/src/Corrade/Containers/Array.h @@ -567,7 +567,7 @@ class Array { const T& back() const; /**< @overload */ /** - * @brief Array slice + * @brief View on a slice * * Equivalent to @ref ArrayView::slice(T*, T*) const and overloads. */ @@ -588,28 +588,28 @@ class Array { } /** - * @brief Fixed-size array slice + * @brief Fixed-size view on a slice * * Equivalent to @ref ArrayView::slice(T*) const and overloads. */ - template StaticArrayView slice(T* begin) { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(T* begin) { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(const T* begin) const { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(const T* begin) const { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(std::size_t begin) { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(std::size_t begin) { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(std::size_t begin) const { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(std::size_t begin) const { + return ArrayView(*this).template slice(begin); } /** - * @brief Fixed-size array slice + * @brief Fixed-size view on a slice * @m_since{2019,10} * * Equivalent to @ref ArrayView::slice() const. @@ -627,9 +627,9 @@ class Array { } /** - * @brief Array prefix + * @brief View on a prefix until a pointer * - * Equivalent to @ref ArrayView::prefix(T*) const and overloads. + * Equivalent to @ref ArrayView::prefix(T*) const. */ ArrayView prefix(T* end) { return ArrayView(*this).prefix(end); @@ -638,61 +638,134 @@ class Array { ArrayView prefix(const T* end) const { return ArrayView(*this).prefix(end); } - /** @overload */ - ArrayView prefix(std::size_t end) { - return ArrayView(*this).prefix(end); + + /** + * @brief View on a suffix after a pointer + * + * Equivalent to @ref ArrayView::suffix(T*) const. + */ + ArrayView suffix(T* begin) { + return ArrayView(*this).suffix(begin); } /** @overload */ - ArrayView prefix(std::size_t end) const { - return ArrayView(*this).prefix(end); + ArrayView suffix(const T* begin) const { + return ArrayView(*this).suffix(begin); } - /** @overload */ - template StaticArrayView prefix() { - return ArrayView(*this).template prefix(); + /** + * @brief View on the first @p count items + * + * Equivalent to @ref ArrayView::prefix(std::size_t) const. + */ + ArrayView prefix(std::size_t count) { + return ArrayView(*this).prefix(count); } /** @overload */ - template StaticArrayView prefix() const { - return ArrayView(*this).template prefix(); + ArrayView prefix(std::size_t count) const { + return ArrayView(*this).prefix(count); } + /* Here will be suffix(std::size_t count), view on the last count + items, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. + The fixed-size suffix() below could be added already as it + doesn't clash with anything. */ + /** - * @brief Array suffix + * @brief Fixed-size view on the first @p count items * - * Equivalent to @ref ArrayView::suffix(T*) const and overloads. + * Equivalent to @ref ArrayView::prefix() const. */ - ArrayView suffix(T* begin) { - return ArrayView(*this).suffix(begin); + template StaticArrayView prefix() { + return ArrayView(*this).template prefix(); } /** @overload */ - ArrayView suffix(const T* begin) const { - return ArrayView(*this).suffix(begin); + template StaticArrayView prefix() const { + return ArrayView(*this).template prefix(); } - /** @overload */ - ArrayView suffix(std::size_t begin) { - return ArrayView(*this).suffix(begin); + + /** + * @brief Fixed-size view on the last @p count items + * @m_since_latest + * + * Equivalent to @ref ArrayView::suffix() const. + */ + template StaticArrayView suffix() { + return ArrayView(*this).template suffix(); } - /** @overload */ - ArrayView suffix(std::size_t begin) const { - return ArrayView(*this).suffix(begin); + /** + * @overload + * @m_since_latest + */ + template StaticArrayView suffix() const { + return ArrayView(*this).template suffix(); } /** - * @brief Array prefix except the last @p count items - * @m_since{2019,10} + * @brief View except the first @p count items + * @m_since_latest * - * Equivalent to @ref ArrayView::except(). + * Equivalent to @ref ArrayView::exceptPrefix(std::size_t) const. */ - ArrayView except(std::size_t count) { - return ArrayView(*this).except(count); + ArrayView exceptPrefix(std::size_t count) { + return ArrayView(*this).exceptPrefix(count); } /** * @overload - * @m_since{2019,10} + * @m_since_latest + */ + ArrayView exceptPrefix(std::size_t count) const { + return ArrayView(*this).exceptPrefix(count); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") ArrayView suffix(std::size_t begin) { + return ArrayView(*this).exceptPrefix(begin); + } + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") ArrayView suffix(std::size_t begin) const { + return ArrayView(*this).exceptPrefix(begin); + } + #endif + + /** + * @brief View except the last @p count items + * @m_since_latest + * + * Equivalent to @ref ArrayView::exceptSuffix(). + */ + ArrayView exceptSuffix(std::size_t count) { + return ArrayView(*this).exceptSuffix(count); + } + /** + * @overload + * @m_since_latest + */ + ArrayView exceptSuffix(std::size_t count) const { + return ArrayView(*this).exceptSuffix(count); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") ArrayView except(std::size_t count) { + return ArrayView(*this).exceptSuffix(count); + } + /** + * @overload + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. */ - ArrayView except(std::size_t count) const { - return ArrayView(*this).except(count); + CORRADE_DEPRECATED("use exceptSuffix() instead") ArrayView except(std::size_t count) const { + return ArrayView(*this).exceptSuffix(count); } + #endif /** * @brief Release data storage diff --git a/src/Corrade/Containers/ArrayView.h b/src/Corrade/Containers/ArrayView.h index dc29ede58..3bdfc2810 100644 --- a/src/Corrade/Containers/ArrayView.h +++ b/src/Corrade/Containers/ArrayView.h @@ -115,16 +115,16 @@ mutable as well. Except for the usual element access via @ref begin(), @ref end() and @ref operator T*() that provides also access via @cpp [] @ce, there's a -collection of slicing functions --- @ref slice(), @ref prefix(), @ref suffix() -and @ref except(): +collection of slicing functions --- @ref slice(), @ref prefix(), @ref suffix(), +@ref exceptPrefix() and @ref exceptSuffix(): @snippet Containers.cpp ArrayView-usage-slicing -All of these accept both an index and a pointer as the begin/end arguments. As -a special case, if @ref prefix() and @ref suffix() are called with -@cpp nullptr @ce, they return a zero-sized @cpp nullptr @ce view. Both are -useful when doing various kinds of searches and propagating failure states, for -example as shown below: +The @ref slice(), @ref prefix(), @ref suffix() APIs accept also a pointer as +the begin/end arguments. As a special case, if @ref prefix() and @ref suffix() +are called with @cpp nullptr @ce, they return a zero-sized @cpp nullptr @ce +view. Both are useful when doing various kinds of searches and propagating +failure states, for example as shown below: @snippet Containers.cpp ArrayView-usage-slicing2 @@ -418,7 +418,8 @@ template class ArrayView { * @brief View slice * * Both arguments are expected to be in range. - * @see @ref prefix(), @ref suffix(), @ref except() + * @see @ref prefix(), @ref suffix(), @ref exceptPrefix(), + * @ref exceptSuffix(), @ref slice(std::size_t, std::size_t) const */ constexpr ArrayView slice(T* begin, T* end) const; @@ -426,19 +427,19 @@ template class ArrayView { constexpr ArrayView slice(std::size_t begin, std::size_t end) const; /** - * @brief Static view slice + * @brief Fixed-size view slice * - * Both @p begin and @cpp begin + viewSize @ce are expected to be in + * Both @p begin and @cpp begin + count @ce are expected to be in * range. * @see @ref prefix() const */ - template constexpr StaticArrayView slice(T* begin) const; + template constexpr StaticArrayView slice(T* begin) const; /** @overload */ - template constexpr StaticArrayView slice(std::size_t begin) const; + template constexpr StaticArrayView slice(std::size_t begin) const; /** - * @brief Static view slice + * @brief Fixed-size view slice * @m_since{2019,10} * * At compile time expects that @cpp begin < end_ @ce, at runtime that @@ -448,72 +449,112 @@ template class ArrayView { template constexpr StaticArrayView slice() const; /** - * @brief View prefix + * @brief View prefix until a pointer * * Equivalent to @cpp data.slice(data.begin(), end) @ce. If @p end is * @cpp nullptr @ce, returns zero-sized @cpp nullptr @ce array. - * @see @ref slice(T*, T*) const, @ref suffix(T*) const + * @see @ref slice(T*, T*) const, @ref suffix(T*) const, + * @ref prefix(std::size_t) const */ constexpr ArrayView prefix(T* end) const { return end ? slice(_data, end) : nullptr; } /** - * @brief View prefix + * @brief View suffix until a pointer * - * Equivalent to @cpp data.slice(0, end) @ce. + * Equivalent to @cpp data.slice(begin, data.end()) @ce. If @p begin is + * @cpp nullptr @ce and the original array isn't, returns zero-sized + * @cpp nullptr @ce array. + * @see @ref slice(T*, T*) const, @ref prefix(T*) const + * @todoc link to suffix(std::size_t) once it takes count and not begin + */ + constexpr ArrayView suffix(T* begin) const { + return _data && !begin ? nullptr : slice(begin, _data + _size); + } + + /** + * @brief View on the first @p count items + * + * Equivalent to @cpp data.slice(0, count) @ce. * @see @ref slice(std::size_t, std::size_t) const, - * @ref suffix(std::size_t) const, @ref except() + * @ref exceptPrefix(), @ref prefix(T*) const + * @todoc link to suffix(std::size_t) once it takes count and not begin */ - constexpr ArrayView prefix(std::size_t end) const { - return slice(0, end); + constexpr ArrayView prefix(std::size_t count) const { + return slice(0, count); } + /* Here will be suffix(std::size_t count), view on the last count + items, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. + The fixed-size suffix() below could be added already as it + doesn't clash with anything. */ + /** - * @brief Static view prefix + * @brief Fixed-size view on the first @p count items * - * Equivalent to @cpp data.slice<0, end_>() @ce. - * @see @ref slice() const + * Equivalent to @cpp data.slice<0, count>() @ce. + * @see @ref slice() const, @ref suffix() const */ - template constexpr StaticArrayView prefix() const { - return slice<0, end_>(); + template constexpr StaticArrayView prefix() const { + return slice<0, count>(); } /** - * @brief View suffix + * @brief Fixed-size view on the last @p count items + * @m_since_latest * - * Equivalent to @cpp data.slice(begin, data.end()) @ce. If @p begin is - * @cpp nullptr @ce and the original array isn't, returns zero-sized - * @cpp nullptr @ce array. - * @see @ref slice(T*, T*) const, @ref prefix(T*) const + * Equivalent to @cpp data.slice(data.size() - count) @ce. + * @see @ref slice() const, @ref prefix() const */ - constexpr ArrayView suffix(T* begin) const { - return _data && !begin ? nullptr : slice(begin, _data + _size); + template constexpr StaticArrayView suffix() const { + return slice(_size - count); } /** - * @brief View suffix + * @brief View except the first @p count items + * @m_since_latest * - * Equivalent to @cpp data.slice(begin, data.size()) @ce. + * Equivalent to @cpp data.slice(count, data.size()) @ce. * @see @ref slice(std::size_t, std::size_t) const, - * @ref prefix(std::size_t) const, @ref except() + * @ref prefix(std::size_t) const, @ref exceptSuffix() + */ + constexpr ArrayView exceptPrefix(std::size_t count) const { + return slice(count, _size); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. */ - constexpr ArrayView suffix(std::size_t begin) const { + CORRADE_DEPRECATED("use exceptPrefix() instead") constexpr ArrayView suffix(std::size_t begin) const { return slice(begin, _size); } + #endif /** - * @brief View prefix except the last @p count items - * @m_since{2019,10} + * @brief View except the last @p count items + * @m_since_latest * * Equivalent to @cpp data.slice(0, data.size() - count) @ce. - * @see @ref slice(std::size_t, std::size_t) const, - * @ref prefix(std::size_t) const, @ref suffix(std::size_t) const + * @see @ref slice(std::size_t, std::size_t) const, @ref exceptPrefix() + * @todoc link to suffix(std::size_t) once it takes count and not begin */ - constexpr ArrayView except(std::size_t count) const { + constexpr ArrayView exceptSuffix(std::size_t count) const { return slice(0, _size - count); } + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") constexpr ArrayView except(std::size_t count) const { + return slice(0, _size - count); + } + #endif + private: friend T*& Implementation::dataRef<>(ArrayView&); #ifndef CORRADE_NO_PYTHON_COMPATIBILITY @@ -916,8 +957,8 @@ owning version of this container is a @ref StaticArray. The general API is similar to what's shown in @ref Containers-ArrayView-usage "ArrayView usage docs", except that here are -additional compile-time overloads of @ref slice(), @ref prefix(), @ref suffix() -and @ref except(). +additional compile-time overloads of @ref slice(), @ref prefix(), +@ref suffix(), @ref exceptPrefix() and @ref exceptSuffix(). @snippet Containers.cpp StaticArrayView-usage @@ -1103,16 +1144,16 @@ template class StaticArrayView { } /** @copydoc ArrayView::slice(T*) const */ - template constexpr StaticArrayView slice(T* begin) const { - return ArrayView(*this).template slice(begin); + template constexpr StaticArrayView slice(T* begin) const { + return ArrayView(*this).template slice(begin); } /** @overload */ - template constexpr StaticArrayView slice(std::size_t begin) const { - return ArrayView(*this).template slice(begin); + template constexpr StaticArrayView slice(std::size_t begin) const { + return ArrayView(*this).template slice(begin); } /** - * @brief Static view slice + * @brief Fixed-size view slice * @m_since{2019,10} * * Expects (at compile time) that @cpp begin < end_ @ce and @p end_ is @@ -1124,56 +1165,107 @@ template class StaticArrayView { constexpr ArrayView prefix(T* end) const { return ArrayView(*this).prefix(end); } - /** @overload */ - constexpr ArrayView prefix(std::size_t end) const { - return ArrayView(*this).prefix(end); + + /** @copydoc ArrayView::suffix(T*) const */ + constexpr ArrayView suffix(T* begin) const { + return ArrayView(*this).suffix(begin); + } + + /** @copydoc ArrayView::prefix(std::size_t) const */ + constexpr ArrayView prefix(std::size_t count) const { + return ArrayView(*this).prefix(count); } + /* Here will be suffix(std::size_t count), view on the last count + items, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. */ + /** - * @brief Static view prefix + * @brief Fixed-size view on the first @p count items * - * Equivalent to @cpp data.slice<0, end_>() @ce. + * Equivalent to @cpp data.slice<0, count>() @ce. * @see @ref slice() const + * @todoc link to suffix() const once it takes count and not begin */ - template constexpr StaticArrayView prefix() const { - return slice<0, end_>(); + template constexpr StaticArrayView prefix() const { + return slice<0, count>(); } - /** @copydoc ArrayView::suffix(T*) const */ - constexpr ArrayView suffix(T* begin) const { - return ArrayView(*this).suffix(begin); + /* Here will be suffix(), view on the last count items, once + the deprecated suffix() is gone and enough time passes to + not cause silent breakages in existing code. */ + + /** @copydoc ArrayView::exceptPrefix(std::size_t) const */ + constexpr ArrayView exceptPrefix(std::size_t count) const { + return ArrayView(*this).exceptPrefix(count); } - /** @overload */ - constexpr ArrayView suffix(std::size_t begin) const { + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") constexpr ArrayView suffix(std::size_t begin) const { return ArrayView(*this).suffix(begin); } + #endif /** - * @brief Static view suffix - * @m_since{2019,10} + * @brief Fixed-size view except the first @p count items + * @m_since_latest * - * Equivalent to @cpp data.slice() @ce. + * Equivalent to @cpp data.slice() @ce. * @see @ref slice() const */ - template constexpr StaticArrayView suffix() const { + template constexpr StaticArrayView exceptPrefix() const { + return slice(); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + template CORRADE_DEPRECATED("use exceptPrefix() instead") constexpr StaticArrayView suffix() const { return slice(); } + #endif + + /** @copydoc ArrayView::exceptSuffix(std::size_t) const */ + constexpr ArrayView exceptSuffix(std::size_t count) const { + return ArrayView(*this).exceptSuffix(count); + } - /** @copydoc ArrayView::except(std::size_t) const */ - constexpr ArrayView except(std::size_t count) const { + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") constexpr ArrayView except(std::size_t count) const { return ArrayView(*this).except(count); } + #endif /** - * @brief Static view prefix except the last @p count items + * @brief Fixed-size view except the last @p count items + * @m_since_latest * * Equivalent to @cpp data.slice<0, Size - count>() @ce. * @see @ref slice() const */ - template constexpr StaticArrayView except() const { + template constexpr StaticArrayView exceptSuffix() const { return slice<0, size_ - count>(); } + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + template CORRADE_DEPRECATED("use exceptSuffix() instead") constexpr StaticArrayView except() const { + return slice<0, size_ - count>(); + } + #endif + private: T* _data; }; @@ -1328,26 +1420,26 @@ template T& StaticArrayView::back() const return _data[size_ - 1]; } -template template constexpr StaticArrayView ArrayView::slice(T* begin) const { - return CORRADE_CONSTEXPR_ASSERT(_data <= begin && begin + viewSize <= _data + _size, +template template constexpr StaticArrayView ArrayView::slice(T* begin) const { + return CORRADE_CONSTEXPR_ASSERT(_data <= begin && begin + count <= _data + _size, "Containers::ArrayView::slice(): slice [" << Utility::Debug::nospace << begin - _data << Utility::Debug::nospace << ":" - << Utility::Debug::nospace << begin + viewSize - _data + << Utility::Debug::nospace << begin + count - _data << Utility::Debug::nospace << "] out of range for" << _size << "elements"), - StaticArrayView{begin}; + StaticArrayView{begin}; } -template template constexpr StaticArrayView ArrayView::slice(std::size_t begin) const { - return CORRADE_CONSTEXPR_ASSERT(begin + viewSize <= _size, +template template constexpr StaticArrayView ArrayView::slice(std::size_t begin) const { + return CORRADE_CONSTEXPR_ASSERT(begin + count <= _size, "Containers::ArrayView::slice(): slice [" << Utility::Debug::nospace << begin << Utility::Debug::nospace << ":" - << Utility::Debug::nospace << begin + viewSize + << Utility::Debug::nospace << begin + count << Utility::Debug::nospace << "] out of range for" << _size << "elements"), - StaticArrayView{_data + begin}; + StaticArrayView{_data + begin}; } template template constexpr StaticArrayView ArrayView::slice() const { diff --git a/src/Corrade/Containers/StaticArray.h b/src/Corrade/Containers/StaticArray.h index f79b02886..4562f0393 100644 --- a/src/Corrade/Containers/StaticArray.h +++ b/src/Corrade/Containers/StaticArray.h @@ -57,8 +57,9 @@ The @ref StaticArray class provides an access and slicing API similar to @ref ArrayView, see @ref Containers-ArrayView-usage "its usage docs" for details. The main difference is that @ref StaticArray doesn't do any heap allocation and thus has no concept of a deleter, and it has additional -compile-time-sized overloads of @ref slice(), @ref prefix(), @ref suffix() and -@ref except(), mirroring the APIs of @ref StaticArrayView. +compile-time-sized overloads of @ref slice(), @ref prefix(), @ref suffix(), +@ref exceptPrefix() and @ref exceptSuffix(), mirroring the APIs of +@ref StaticArrayView. @snippet Containers.cpp StaticArray-usage @@ -343,7 +344,7 @@ template class StaticArray { const T& back() const { return _data[size_ - 1]; } /**< @overload */ /** - * @brief Array slice + * @brief View on a slice * * Equivalent to @ref StaticArrayView::slice(T*, T*) const and * overloads. @@ -365,28 +366,28 @@ template class StaticArray { } /** - * @brief Static array slice + * @brief Fixed-size view on a slice * * Equivalent to @ref StaticArrayView::slice(T*) const and overloads. */ - template StaticArrayView slice(T* begin) { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(T* begin) { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(const T* begin) const { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(const T* begin) const { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(std::size_t begin) { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(std::size_t begin) { + return ArrayView(*this).template slice(begin); } /** @overload */ - template StaticArrayView slice(std::size_t begin) const { - return ArrayView(*this).template slice(begin); + template StaticArrayView slice(std::size_t begin) const { + return ArrayView(*this).template slice(begin); } /** - * @brief Static array slice + * @brief Fixed-size view on a slice * @m_since{2019,10} * * Equivalent to @ref StaticArrayView::slice() const. @@ -404,9 +405,9 @@ template class StaticArray { } /** - * @brief Array prefix + * @brief View on a prefix until a pointer * - * Equivalent to @ref StaticArrayView::prefix(T*) const and overloads. + * Equivalent to @ref StaticArrayView::prefix(T*) const. */ ArrayView prefix(T* end) { return ArrayView(*this).prefix(end); @@ -415,88 +416,184 @@ template class StaticArray { ArrayView prefix(const T* end) const { return ArrayView(*this).prefix(end); } + + /** + * @brief View on a suffix after a pointer + * + * Equivalent to @ref StaticArrayView::suffix(T*) const. + */ + ArrayView suffix(T* begin) { + return ArrayView(*this).suffix(begin); + } /** @overload */ - ArrayView prefix(std::size_t end) { - return ArrayView(*this).prefix(end); + ArrayView suffix(const T* begin) const { + return ArrayView(*this).suffix(begin); + } + + /** + * @brief View on the first @p count items + * + * Equivalent to @ref StaticArrayView::prefix(std::size_t) const. + */ + ArrayView prefix(std::size_t count) { + return ArrayView(*this).prefix(count); } /** @overload */ - ArrayView prefix(std::size_t end) const { - return ArrayView(*this).prefix(end); + ArrayView prefix(std::size_t count) const { + return ArrayView(*this).prefix(count); } + /* Here will be suffix(std::size_t count), view on the last count + items, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. */ + /** - * @brief Static array prefix + * @brief Fixed-size view on the first @p count items * * Equivalent to @ref StaticArrayView::prefix() const and overloads. */ - template StaticArrayView prefix(); - template StaticArrayView prefix() const; /**< @overload */ + template StaticArrayView prefix(); + template StaticArrayView prefix() const; /**< @overload */ + + /* Here will be suffix(), view on the last count items, once + the deprecated suffix() is gone and enough time passes to + not cause silent breakages in existing code. */ /** - * @brief Array suffix + * @brief View except the first @p count items + * @m_since_latest * - * Equivalent to @ref StaticArrayView::suffix(T*) const and overloads. + * Equivalent to @ref StaticArrayView::exceptPrefix(std::size_t) const. */ - ArrayView suffix(T* begin) { - return ArrayView(*this).suffix(begin); + ArrayView exceptPrefix(std::size_t count) { + return ArrayView(*this).exceptPrefix(count); } - /** @overload */ - ArrayView suffix(const T* begin) const { - return ArrayView(*this).suffix(begin); + /** + * @overload + * @m_since_latest + */ + ArrayView exceptPrefix(std::size_t count) const { + return ArrayView(*this).exceptPrefix(count); } - /** @overload */ - ArrayView suffix(std::size_t begin) { + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") ArrayView suffix(std::size_t begin) { return ArrayView(*this).suffix(begin); } - /** @overload */ - ArrayView suffix(std::size_t begin) const { + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") ArrayView suffix(std::size_t begin) const { return ArrayView(*this).suffix(begin); } + #endif /** - * @brief Static array suffix - * @m_since{2019,10} + * @brief Fixed-size view except the first @p count items + * @m_since_latest * - * Equivalent to @ref StaticArrayView::suffix() const. + * Equivalent to @ref StaticArrayView::exceptPrefix() const and + * overloads. */ - template StaticArrayView suffix() { - return StaticArrayView(*this).template suffix(); + template StaticArrayView exceptPrefix() { + return StaticArrayView(*this).template exceptPrefix(); + } + /** + * @overload + * @m_since_latest + */ + template StaticArrayView exceptPrefix() const { + return StaticArrayView(*this).template exceptPrefix(); } + #ifdef CORRADE_BUILD_DEPRECATED /** - * @overload - * @m_since{2019,10} + * @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + template CORRADE_DEPRECATED("use exceptPrefix() instead") StaticArrayView suffix() { + return StaticArrayView(*this).template exceptPrefix(); + } + /** + * @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. */ - template StaticArrayView suffix() const { - return StaticArrayView(*this).template suffix(); + template CORRADE_DEPRECATED("use exceptPrefix() instead") StaticArrayView suffix() const { + return StaticArrayView(*this).template exceptPrefix(); } + #endif /** - * @brief Array prefix except the last @p count items + * @brief View except the last @p count items + * @m_since_latest * - * Equivalent to @ref StaticArrayView::except(std::size_t) const. + * Equivalent to @ref StaticArrayView::exceptSuffix(std::size_t) const. */ - ArrayView except(std::size_t count) { - return ArrayView(*this).except(count); + ArrayView exceptSuffix(std::size_t count) { + return ArrayView(*this).exceptSuffix(count); } - /** @overload */ - ArrayView except(std::size_t count) const { - return ArrayView(*this).except(count); + /** + * @overload + * @m_since_latest + */ + ArrayView exceptSuffix(std::size_t count) const { + return ArrayView(*this).exceptSuffix(count); } + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") ArrayView except(std::size_t count) { + return ArrayView(*this).exceptSuffix(count); + } /** - * @brief Static array prefix except the last @p count items + * @overload + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") ArrayView except(std::size_t count) const { + return ArrayView(*this).exceptSuffix(count); + } + #endif + + /** + * @brief Fixed-size view except the last @p count items + * @m_since_latest * - * Equivalent to @ref StaticArrayView::except() const. + * Equivalent to @ref StaticArrayView::exceptSuffix() const. */ - template StaticArrayView except() { - return StaticArrayView(*this).template except(); + template StaticArrayView exceptSuffix() { + return StaticArrayView(*this).template exceptSuffix(); } - /** @overload */ - template StaticArrayView except() const { - return StaticArrayView(*this).template except(); + /** + * @overload + * @m_since_latest + */ + template StaticArrayView exceptSuffix() const { + return StaticArrayView(*this).template exceptSuffix(); } + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + template CORRADE_DEPRECATED("use exceptSuffix() instead") StaticArrayView except() { + return StaticArrayView(*this).template exceptSuffix(); + } + /** + * @overload + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + template CORRADE_DEPRECATED("use exceptSuffix() instead") StaticArrayView except() const { + return StaticArrayView(*this).template exceptSuffix(); + } + #endif + private: explicit StaticArray(Corrade::DefaultInitT, std::true_type) {} /* GCC 5.3 is not able to initialize non-movable types inside @@ -689,14 +786,14 @@ template StaticArray& StaticArray template StaticArrayView StaticArray::prefix() { - static_assert(viewSize <= size_, "prefix size too large"); - return StaticArrayView{_data}; +template template StaticArrayView StaticArray::prefix() { + static_assert(count <= size_, "prefix size too large"); + return StaticArrayView{_data}; } -template template StaticArrayView StaticArray::prefix() const { - static_assert(viewSize <= size_, "prefix size too large"); - return StaticArrayView{_data}; +template template StaticArrayView StaticArray::prefix() const { + static_assert(count <= size_, "prefix size too large"); + return StaticArrayView{_data}; } namespace Implementation { diff --git a/src/Corrade/Containers/StridedArrayView.h b/src/Corrade/Containers/StridedArrayView.h index cf37ac474..2419afee5 100644 --- a/src/Corrade/Containers/StridedArrayView.h +++ b/src/Corrade/Containers/StridedArrayView.h @@ -275,8 +275,11 @@ Strided array views are very useful for describing and iteration over multi-dimensional data such as 2D (sub)images. In that case, @ref operator[]() and iterator access return a view of one dimension less instead of a direct element reference, and there are @ref slice(const Size&, const Size&) const, -@ref prefix(const Size&) const and @ref suffix(const Size&) const overloads -working on all dimensions at the same time. +@ref prefix(const Size&) const, @ref exceptPrefix(const Size&) const and +@ref exceptSuffix(const Size&) const overloads working on all dimensions at the +same time. + +@todoc link to suffix(const Size&) const once it takes count and not begin @snippet Containers.cpp StridedArrayView-usage-3d @@ -689,16 +692,19 @@ template class StridedArrayView { ElementType back() const; /** - * @brief Array slice + * @brief View slice in the first dimension * * Both arguments are expected to be in range. On multi-dimensional - * views slices just the top-level dimension. - * @see @ref slice(const Size&, const Size&) const + * views slices just the top-level dimension, use + * @ref slice(const Size&, const Size&) const to slice in all + * dimensions. + * @see @ref prefix(), @ref exceptPrefix(), @ref exceptSuffix() + * @todoc link to suffix() once it takes count and not begin */ StridedArrayView slice(std::size_t begin, std::size_t end) const; /** - * @brief Multi-dimensional array slice + * @brief View slice in all dimensions * * Values in both arguments are expected to be in range for given * dimension. If @p newDimensions is smaller than @ref Dimensions, @@ -783,71 +789,129 @@ template class StridedArrayView { #endif /** - * @brief Array prefix + * @brief View on the first @p count items in the first dimension * - * Equivalent to @cpp data.slice(0, end) @ce. + * Equivalent to @cpp data.slice(0, count) @ce. On multi-dimensional + * views slices just the top-level dimension, use + * @ref prefix(const Size&) const to slice in all dimensions. * @see @ref slice(std::size_t, std::size_t) const, - * @ref prefix(const Size&) const + * @ref exceptPrefix(std::size_t) const + * @todoc link to suffix(std::size_t) once it takes count and not begin */ - StridedArrayView prefix(std::size_t end) const { - return slice(0, end); + StridedArrayView prefix(std::size_t count) const { + return slice(0, count); } /** - * @brief Multi-dimensional array prefix + * @brief View on the first @p count items in all dimensions * - * Equivalent to @cpp data.slice({}, end) @ce. + * Equivalent to @cpp data.slice({}, count) @ce. * @see @ref slice(const Size&, const Size&) const, + * @ref exceptPrefix(const Size&) const, * @ref prefix(std::size_t) const + * @todoc link to suffix(const Size&) once it takes count and not begin */ - template StridedArrayView prefix(const Size& end) const { - return slice({}, end); + template StridedArrayView prefix(const Size& count) const { + return slice({}, count); } + /* Here will be suffix(count), view on the last count items, once the + deprecated suffix(begin) are gone and enough time passes to not + cause silent breakages in existing code. */ + /** - * @brief Array suffix + * @brief View except the first @p count items in the first dimension + * @m_since_latest * - * Equivalent to @cpp data.slice(begin, data.size()[0]) @ce. + * Equivalent to @cpp data.slice(count, data.size()[0]) @ce. On + * multi-dimensional views slices just the top-level dimension, use + * @ref exceptPrefix(const Size&) const to slice in all dimensions. * @see @ref slice(std::size_t, std::size_t) const, - * @ref suffix(const Size&) const + * @ref prefix(std::size_t) const, + * @ref exceptSuffix(const Size&) const + */ + StridedArrayView exceptPrefix(std::size_t count) const { + return slice(count, _size._data[0]); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. */ - StridedArrayView suffix(std::size_t begin) const { + CORRADE_DEPRECATED("use exceptPrefix() instead") StridedArrayView suffix(std::size_t begin) const { return slice(begin, _size._data[0]); } + #endif /** - * @brief Multi-dimensional array suffix + * @brief View except the first @p count items in all dimensions + * @m_since_latest * - * Equivalent to @cpp data.slice(begin, data.size()) @ce. + * Equivalent to @cpp data.slice(count, data.size()) @ce. * @see @ref slice(const Size&, const Size&) const, - * @ref suffix(std::size_t) const + * @ref prefix(const Size&) const, + * @ref exceptSuffix(const Size&) const, + * @ref exceptSuffix(std::size_t) const + */ + template StridedArrayView exceptPrefix(const Size& count) const { + return slice(count, _size); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. */ - template StridedArrayView suffix(const Size& begin) const { + template CORRADE_DEPRECATED("use exceptPrefix() instead") StridedArrayView suffix(const Size& begin) const { return slice(begin, _size); } + #endif /** - * @brief Array suffix - * @m_since{2019,10} + * @brief View except the last @p count items in the first dimension + * @m_since_latest * - * Equivalent to @cpp data.slice({}, data.size()[0] - count) @ce. + * Equivalent to @cpp data.slice({}, data.size()[0] - count) @ce. On + * multi-dimensional views slices just the top-level dimension, use + * @ref exceptSuffix(const Size&) const to slice in all dimensions. * @see @ref slice(std::size_t, std::size_t) const, - * @ref suffix(const Size&) const + * @ref exceptPrefix(const Size&) const + * @todoc link to suffix(std::size_t) once it takes count and not begin */ - StridedArrayView except(std::size_t count) const { + StridedArrayView exceptSuffix(std::size_t count) const { return slice({}, _size._data[0] - count); } + #ifdef CORRADE_BUILD_DEPRECATED /** - * @brief Multi-dimensional array suffix - * @m_since{2019,10} + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") StridedArrayView except(std::size_t count) const { + return slice({}, _size._data[0] - count); + } + #endif + + /** + * @brief View except the last @p count items in all dimensions + * @m_since_latest * * Equivalent to @cpp data.slice({}, end) @ce, where * @p end is @cpp data.size()[i] - count[i] @ce for all dimensions. * @see @ref slice(const Size&, const Size&) const, - * @ref except(std::size_t) const + * @ref exceptPrefix(std::size_t) const + * @todoc link to suffix(const Size&) once it takes count and not begin + */ + template StridedArrayView exceptSuffix(const Size& count) const; + + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. */ - template StridedArrayView except(const Size& count) const; + template CORRADE_DEPRECATED("use exceptSuffix() instead") StridedArrayView except(const Size& count) const { + return exceptSuffix(count); + } + #endif /** * @brief Pick every Nth element @@ -2111,7 +2175,7 @@ template template typename std:: } #endif -template template StridedArrayView StridedArrayView::except(const Size& count) const { +template template StridedArrayView StridedArrayView::exceptSuffix(const Size& count) const { Size end{Corrade::NoInit}; for(std::size_t i = 0; i != dimensions; ++i) end._data[i] = _size._data[i] - count._data[i]; diff --git a/src/Corrade/Containers/String.cpp b/src/Corrade/Containers/String.cpp index 94b70192c..f274b6583 100644 --- a/src/Corrade/Containers/String.cpp +++ b/src/Corrade/Containers/String.cpp @@ -465,14 +465,6 @@ StringView String::prefix(const char* const end) const { return StringView{*this}.prefix(end); } -MutableStringView String::prefix(const std::size_t end) { - return MutableStringView{*this}.prefix(end); -} - -StringView String::prefix(const std::size_t end) const { - return StringView{*this}.prefix(end); -} - MutableStringView String::suffix(char* const begin) { return MutableStringView{*this}.suffix(begin); } @@ -481,21 +473,49 @@ StringView String::suffix(const char* const begin) const { return StringView{*this}.suffix(begin); } +MutableStringView String::prefix(const std::size_t count) { + return MutableStringView{*this}.prefix(count); +} + +StringView String::prefix(const std::size_t count) const { + return StringView{*this}.prefix(count); +} + +MutableStringView String::exceptPrefix(const std::size_t begin) { + return MutableStringView{*this}.exceptPrefix(begin); +} + +StringView String::exceptPrefix(const std::size_t begin) const { + return StringView{*this}.exceptPrefix(begin); +} + +#ifdef CORRADE_BUILD_DEPRECATED MutableStringView String::suffix(const std::size_t begin) { - return MutableStringView{*this}.suffix(begin); + return MutableStringView{*this}.exceptPrefix(begin); } StringView String::suffix(const std::size_t begin) const { - return StringView{*this}.suffix(begin); + return StringView{*this}.exceptPrefix(begin); +} +#endif + +MutableStringView String::exceptSuffix(const std::size_t count) { + return MutableStringView{*this}.exceptSuffix(count); +} + +StringView String::exceptSuffix(const std::size_t count) const { + return StringView{*this}.exceptSuffix(count); } +#ifdef CORRADE_BUILD_DEPRECATED MutableStringView String::except(const std::size_t count) { - return MutableStringView{*this}.except(count); + return MutableStringView{*this}.exceptSuffix(count); } StringView String::except(const std::size_t count) const { - return StringView{*this}.except(count); + return StringView{*this}.exceptSuffix(count); } +#endif Array String::split(const char delimiter) & { return MutableStringView{*this}.split(delimiter); diff --git a/src/Corrade/Containers/String.h b/src/Corrade/Containers/String.h index 1509b13ad..3976700bf 100644 --- a/src/Corrade/Containers/String.h +++ b/src/Corrade/Containers/String.h @@ -80,13 +80,15 @@ constexpr AllocatedInitT AllocatedInit{AllocatedInitT::Init{}}; A lightweight non-templated alternative to @ref std::string with support for custom deleters. A non-owning version of this container is a -@ref BasicStringView "StringView". +@ref StringView and a @ref MutableStringView, implemented using a generic +@ref BasicStringView. @section Containers-String-usage Usage -It's recommended to prefer using @ref BasicStringView "StringView" in most -cases, and only create a @ref String instance if you need to extend lifetime of -the data or mutate it. The @ref String is implicitly convertible from C string +It's recommended to prefer using @ref StringView / @ref MutableStringView in +most cases, and only create a @ref String instance if you need to extend +lifetime of the data or perform an operation that can't be done by mutating a +view in-place. The @ref String is implicitly convertible from C string literals, but the designated way to instantiate a string is using the @link operator""_s() @endlink literal. While both expressions are *mostly* equivalent, the implicit conversion has some runtime impact due to @@ -643,7 +645,7 @@ class CORRADE_UTILITY_EXPORT String { char operator[](std::size_t i) const; /**< @overload */ /** - * @brief String slice + * @brief View on a slice * * Equivalent to @ref BasicStringView::slice(). Both arguments are * expected to be in range. If @p end points to (one item after) the @@ -657,32 +659,80 @@ class CORRADE_UTILITY_EXPORT String { StringView slice(std::size_t begin, std::size_t end) const; /**< @overload */ /** - * @brief String prefix + * @brief View on a prefix until a pointer * - * Equivalent to @ref BasicStringView::prefix(). + * Equivalent to @ref BasicStringView::prefix(T*) const. If @p end + * points to (one item after) the end of the original (null-terminated) + * string, the result has @ref StringViewFlag::NullTerminated set. */ MutableStringView prefix(char* end); StringView prefix(const char* end) const; /**< @overload */ - MutableStringView prefix(std::size_t end); /**< @overload */ - StringView prefix(std::size_t end) const; /**< @overload */ /** - * @brief String suffix + * @brief View on a suffix after a pointer * - * Equivalent to @ref BasicStringView::suffix(). + * Equivalent to @ref BasicStringView::suffix(T*) const. The result has + * always @ref StringViewFlag::NullTerminated set. */ MutableStringView suffix(char* begin); StringView suffix(const char* begin) const; /**< @overload */ - MutableStringView suffix(std::size_t begin); /**< @overload */ - StringView suffix(std::size_t begin) const; /**< @overload */ /** - * @brief String suffix + * @brief View on the first @p count bytes * - * Equivalent to @ref BasicStringView::except(). + * Equivalent to @ref BasicStringView::prefix(std::size_t) const. If + * @p count is equal to @ref size(), the result has + * @ref StringViewFlag::NullTerminated set. + */ + MutableStringView prefix(std::size_t count); + StringView prefix(std::size_t count) const; /**< @overload */ + + /* Here will be suffix(std::size_t count), view on the last count + bytes, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. */ + + /** + * @brief View except the first @p count bytes + * + * Equivalent to @ref BasicStringView::exceptPrefix(). The result has + * always @ref StringViewFlag::NullTerminated set. */ - MutableStringView except(std::size_t count); - StringView except(std::size_t count) const; /**< @overload */ + MutableStringView exceptPrefix(std::size_t begin); + StringView exceptPrefix(std::size_t begin) const; /**< @overload */ + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") MutableStringView suffix(std::size_t begin); + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") StringView suffix(std::size_t begin) const; + #endif + + /** + * @brief View except the last @p count bytes + * + * Equivalent to @ref BasicStringView::exceptSuffix(). If + * @p count is @cpp 0 @ce, the result has + * @ref StringViewFlag::NullTerminated set. + */ + MutableStringView exceptSuffix(std::size_t count); + StringView exceptSuffix(std::size_t count) const; /**< @overload */ + + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") MutableStringView except(std::size_t count); + /** + * @overload + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") StringView except(std::size_t count) const; + #endif /** * @brief Split on given character diff --git a/src/Corrade/Containers/StringView.h b/src/Corrade/Containers/StringView.h index 2c564317a..a8c932061 100644 --- a/src/Corrade/Containers/StringView.h +++ b/src/Corrade/Containers/StringView.h @@ -149,10 +149,10 @@ that the conversion will not preserve the global / null-terminated annotations. @subsection Containers-BasicStringView-usage-slicing String view slicing The string view class inherits the slicing APIs of @ref ArrayView --- -@ref slice(), @ref prefix(), @ref suffix() and @ref except() --- and in -addition it provides string-specific utilities. These are are all derived from -the slicing APIs, which means they also return sub-views of the original -string: +@ref slice(), @ref prefix(), @ref suffix(), @ref exceptPrefix() and +@ref exceptSuffix() --- and in addition it provides string-specific utilities. +These are are all derived from the slicing APIs, which means they also return +sub-views of the original string:
  • @ref split() and @ref splitWithoutEmptyParts() split the view on given set @@ -165,8 +165,8 @@ robust while reducing the amount of possible error states
  • @ref trimmed() (and its variants @ref trimmedPrefix() / @ref trimmedSuffix()), commonly used to remove leading and trailing whitespace
  • -
  • @ref exceptPrefix() / @ref exceptSuffix() checks that a view starts (or -ends) with given string and then removes it: +
  • @ref exceptPrefix(StringView) const / @ref exceptSuffix(StringView) const +checks that a view starts (or ends) with given string and then removes it: @snippet Containers.cpp StringView-usage-slicing
  • @@ -458,13 +458,15 @@ template class CORRADE_UTILITY_EXPORT BasicStringView { constexpr T& operator[](std::size_t i) const { return _data[i]; } /** - * @brief String slice + * @brief View slice * * Both arguments are expected to be in range. Propagates the * @ref StringViewFlag::Global flag and if @p end points to (one item * after) the end of the original null-terminated string, the result * has @ref StringViewFlag::NullTerminated also. * @m_keywords{substr()} + * @see @ref prefix(), @ref suffix(), @ref exceptPrefix(), + * @ref exceptSuffix(), @ref slice(std::size_t, std::size_t) const */ constexpr BasicStringView slice(T* begin, T* end) const; @@ -472,58 +474,88 @@ template class CORRADE_UTILITY_EXPORT BasicStringView { constexpr BasicStringView slice(std::size_t begin, std::size_t end) const; /** - * @brief String prefix + * @brief View prefix until a pointer * * Equivalent to @cpp string.slice(string.begin(), end) @ce. If @p end * is @cpp nullptr @ce, returns zero-sized @cpp nullptr @ce view. - * @see @ref slice(T*, T*) const + * @see @ref slice(T*, T*) const, @ref suffix(T*) const, + * @ref prefix(std::size_t) const */ constexpr BasicStringView prefix(T* end) const { return end ? slice(_data, end) : BasicStringView{}; } /** - * @brief String prefix - * - * Equivalent to @cpp string.slice(0, end) @ce. - * @see @ref slice(std::size_t, std::size_t) const - */ - constexpr BasicStringView prefix(std::size_t end) const { - return slice(0, end); - } - - /** - * @brief String suffix + * @brief View suffix until a pointer * * Equivalent to @cpp string.slice(begin, string.end()) @ce. If * @p begin is @cpp nullptr @ce and the original view isn't, returns a * zero-sized @cpp nullptr @ce view. - * @see @ref slice(T*, T*) const + * @see @ref slice(T*, T*) const, @ref prefix(T*) const + * @todoc link to suffix(std::size_t) once it takes count and not begin */ constexpr BasicStringView suffix(T* begin) const { return _data && !begin ? BasicStringView{} : slice(begin, _data + (_sizePlusFlags & ~Implementation::StringViewSizeMask)); } /** - * @brief String suffix + * @brief View on the first @p count bytes + * + * Equivalent to @cpp string.slice(0, count) @ce. + * @see @ref slice(std::size_t, std::size_t) const, + * @ref exceptPrefix(), @ref prefix(T*) const + * @todoc link to suffix(std::size_t) once it takes count and not begin + */ + constexpr BasicStringView prefix(std::size_t count) const { + return slice(0, count); + } + + /* Here will be suffix(std::size_t count), view on the last count + bytes, once the deprecated suffix(std::size_t begin) is gone and + enough time passes to not cause silent breakages in existing code. */ + + /** + * @brief View except the first @p count bytes * - * Equivalent to @cpp string.slice(begin, string.size()) @ce. - * @see @ref slice(std::size_t, std::size_t) const + * Equivalent to @cpp string.slice(count, string.size()) @ce. + * @see @ref slice(std::size_t, std::size_t) const, + * @ref prefix(std::size_t) const, @ref exceptSuffix() */ - constexpr BasicStringView suffix(std::size_t begin) const { + constexpr BasicStringView exceptPrefix(std::size_t count) const { + return slice(count, _sizePlusFlags & ~Implementation::StringViewSizeMask); + } + + #ifdef CORRADE_BUILD_DEPRECATED + /** @copybrief exceptPrefix() + * @m_deprecated_since_latest Use @ref exceptPrefix() instead. + */ + CORRADE_DEPRECATED("use exceptPrefix() instead") constexpr BasicStringView suffix(std::size_t begin) const { return slice(begin, _sizePlusFlags & ~Implementation::StringViewSizeMask); } + #endif /** - * @brief String prefix except the last @p count items + * @brief View except the last @p count bytes * * Equivalent to @cpp string.slice(0, string.size() - count) @ce. - * @see @ref slice(std::size_t, std::size_t) const + * @see @ref slice(std::size_t, std::size_t) const, + * @ref exceptPrefix() + * @todoc link to suffix(std::size_t) once it takes count and not begin */ - constexpr BasicStringView except(std::size_t count) const { + constexpr BasicStringView exceptSuffix(std::size_t count) const { return slice(0, (_sizePlusFlags & ~Implementation::StringViewSizeMask) - count); } + #ifdef CORRADE_BUILD_DEPRECATED + /** + * @copybrief exceptSuffix() + * @m_deprecated_since_latest Use @ref exceptSuffix() instead. + */ + CORRADE_DEPRECATED("use exceptSuffix() instead") constexpr BasicStringView except(std::size_t count) const { + return slice(0, (_sizePlusFlags & ~Implementation::StringViewSizeMask) - count); + } + #endif + /** * @brief Split on given character * diff --git a/src/Corrade/Containers/Test/ArrayTest.cpp b/src/Corrade/Containers/Test/ArrayTest.cpp index c4baa9cfd..4a149b7c2 100644 --- a/src/Corrade/Containers/Test/ArrayTest.cpp +++ b/src/Corrade/Containers/Test/ArrayTest.cpp @@ -730,16 +730,24 @@ void ArrayTest::sliceToStatic() { CORRADE_COMPARE(bc2[2], 4); StaticArrayView<3, int> c = a.prefix<3>(); - CORRADE_COMPARE(c.size(), 3); CORRADE_COMPARE(c[0], 1); CORRADE_COMPARE(c[1], 2); CORRADE_COMPARE(c[2], 3); StaticArrayView<3, const int> cc = ac.prefix<3>(); - CORRADE_COMPARE(cc.size(), 3); CORRADE_COMPARE(cc[0], 1); CORRADE_COMPARE(cc[1], 2); CORRADE_COMPARE(cc[2], 3); + + StaticArrayView<3, int> d = a.suffix<3>(); + CORRADE_COMPARE(d[0], 3); + CORRADE_COMPARE(d[1], 4); + CORRADE_COMPARE(d[2], 5); + + StaticArrayView<3, const int> dc = ac.suffix<3>(); + CORRADE_COMPARE(dc[0], 3); + CORRADE_COMPARE(dc[1], 4); + CORRADE_COMPARE(dc[2], 5); } void ArrayTest::sliceToStaticPointer() { diff --git a/src/Corrade/Containers/Test/ArrayViewTest.cpp b/src/Corrade/Containers/Test/ArrayViewTest.cpp index 6ebde8ba1..02f7dcf49 100644 --- a/src/Corrade/Containers/Test/ArrayViewTest.cpp +++ b/src/Corrade/Containers/Test/ArrayViewTest.cpp @@ -1113,6 +1113,11 @@ void ArrayViewTest::sliceToStatic() { CORRADE_COMPARE(c[1], 2); CORRADE_COMPARE(c[2], 3); + StaticArrayView<3, int> d = a.suffix<3>(); + CORRADE_COMPARE(d[0], 3); + CORRADE_COMPARE(d[1], 4); + CORRADE_COMPARE(d[2], 5); + /* Similarly to above, MSVC 2015 chokes on this due to (I assume) doing pointer arithmetic on _data inside the assert. */ #ifndef CORRADE_MSVC2015_COMPATIBILITY @@ -1131,6 +1136,11 @@ void ArrayViewTest::sliceToStatic() { CORRADE_COMPARE(cc[0], 1); CORRADE_COMPARE(cc[1], 2); CORRADE_COMPARE(cc[2], 3); + + constexpr StaticArrayView<3, const int> cd = ca.suffix<3>(); + CORRADE_COMPARE(cd[0], 3); + CORRADE_COMPARE(cd[1], 4); + CORRADE_COMPARE(cd[2], 5); #endif }