/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkSpan_DEFINED #define SkSpan_DEFINED #include #include #include #include #include "include/private/SkTLogic.h" /** * An SkSpan is a view of a contiguous collection of elements of type T. It can be directly * constructed from a pointer and size. SkMakeSpan can be used to construct one from an array, * or a container (like std::vector). * * With C++17, we could add template deduction guides that eliminate the need for SkMakeSpan: * https://skia-review.googlesource.com/c/skia/+/320264 */ template class SkSpan { public: constexpr SkSpan() : fPtr{nullptr}, fSize{0} {} constexpr SkSpan(T* ptr, size_t size) : fPtr{ptr}, fSize{size} {} template ::value>::type> constexpr SkSpan(const SkSpan& that) : fPtr(that.data()), fSize{that.size()} {} constexpr SkSpan(const SkSpan& o) = default; constexpr SkSpan& operator=(const SkSpan& that) { fPtr = that.fPtr; fSize = that.fSize; return *this; } constexpr T& operator [] (size_t i) const { SkASSERT(i < this->size()); return fPtr[i]; } constexpr T& front() const { return fPtr[0]; } constexpr T& back() const { return fPtr[fSize - 1]; } constexpr T* begin() const { return fPtr; } constexpr T* end() const { return fPtr + fSize; } constexpr auto rbegin() const { return std::make_reverse_iterator(this->end()); } constexpr auto rend() const { return std::make_reverse_iterator(this->begin()); } constexpr T* data() const { return this->begin(); } constexpr size_t size() const { return fSize; } constexpr bool empty() const { return fSize == 0; } constexpr size_t size_bytes() const { return fSize * sizeof(T); } constexpr SkSpan first(size_t prefixLen) const { SkASSERT(prefixLen <= this->size()); return SkSpan{fPtr, prefixLen}; } constexpr SkSpan last(size_t postfixLen) const { SkASSERT(postfixLen <= this->size()); return SkSpan{fPtr + (this->size() - postfixLen), postfixLen}; } constexpr SkSpan subspan(size_t offset, size_t count) const { SkASSERT(offset <= this->size()); SkASSERT(count <= this->size() - offset); return SkSpan{fPtr + offset, count}; } private: T* fPtr; size_t fSize; }; template inline constexpr SkSpan SkMakeSpan(T* p, S s) { return SkSpan{p, SkTo(s)}; } template inline constexpr SkSpan SkMakeSpan(T (&a)[N]) { return SkSpan{a, N}; } template inline auto SkMakeSpan(Container& c) -> SkSpan::type> { return {c.data(), c.size()}; } #endif // SkSpan_DEFINED