| 
							- //
 - //    ██████ ██   ██  ██████   ██████
 - //   ██      ██   ██ ██    ██ ██            ** Clean Header-Only Classes **
 - //   ██      ███████ ██    ██ ██
 - //   ██      ██   ██ ██    ██ ██           https://github.com/Tracktion/choc
 - //    ██████ ██   ██  ██████   ██████
 - //
 - //   CHOC is (C)2021 Tracktion Corporation, and is offered under the terms of the ISC license:
 - //
 - //   Permission to use, copy, modify, and/or distribute this software for any purpose with or
 - //   without fee is hereby granted, provided that the above copyright notice and this permission
 - //   notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 - //   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 - //   AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 - //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 - //   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 - //   CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 - 
 - #ifndef CHOC_SPAN_HEADER_INCLUDED
 - #define CHOC_SPAN_HEADER_INCLUDED
 - 
 - #include <vector>
 - #include "DistrhoUtils.hpp"
 - 
 - namespace choc
 - {
 - 
 - //==============================================================================
 - /** This is a temporary stunt-double for std::span, with the intention of it being
 -     deprecated when there's more widespread compiler support for the real std::span.
 - 
 -     This class has fewer bells-and-whistles than a real std::span, but it does have
 -     the advantage of calling CHOC_ASSERT when mistakes are made like out-of-range
 -     accesses, which can be useful for getting clean error handling rather than UB.
 - */
 - template <typename Item>
 - struct span
 - {
 -     span() = default;
 -     span (const span&) = default;
 -     span (span&&) = default;
 -     span& operator= (span&&) = default;
 -     span& operator= (const span&) = default;
 - 
 -     /// Construct from some raw start and end pointers. For an empty span, these
 -     /// can both be nullptr, but if one is a real pointer then the caller must ensure
 -     /// that start <= end.
 -     span (Item* start, Item* end) noexcept  : s (start), e (end) {}
 - 
 -     /// Constructs a span from a pointer and length.
 -     /// The pointer must not be nullptr unless the length is 0.
 -     span (const Item* start, size_t length) noexcept  : span (const_cast<Item*> (start), const_cast<Item*> (start) + length) {}
 - 
 -     /// Constructor taking a raw C++ array.
 -     template <size_t length>
 -     span (Item (&array)[length])  : span (array, length) {}
 - 
 -     /// Constructor which takes some kind of class like std::vector or std::array.
 -     /// Any class that provides data() and size() methods can be passed in.
 -     template <typename VectorOrArray>
 -     span (const VectorOrArray& v)  : span (v.data(), v.size()) {}
 - 
 -     /// Returns true if the span is empty.
 -     bool empty() const                              { return s == e; }
 - 
 -     /// Returns the number of elements.
 -     /// The length() and size() methods are equivalent.
 -     size_t size() const                             { return static_cast<size_t> (e - s); }
 - 
 -     /// Returns the number of elements.
 -     /// The length() and size() methods are equivalent.
 -     size_t length() const                           { return static_cast<size_t> (e - s); }
 - 
 -     /// Returns a raw pointer to the start of the data.
 -     Item* data() const noexcept                     { return s; }
 - 
 -     const Item& front() const                       { DISTRHO_SAFE_ASSERT_RETURN (! empty(), _nullValue()); return *s; }
 -     const Item& back() const                        { DISTRHO_SAFE_ASSERT_RETURN (! empty(), _nullValue()); return *(e - 1); }
 -     Item& front()                                   { DISTRHO_SAFE_ASSERT_RETURN (! empty(), _nullValue()); return *s; }
 -     Item& back()                                    { DISTRHO_SAFE_ASSERT_RETURN (! empty(), _nullValue()); return *(e - 1); }
 - 
 -     const Item& operator[] (size_t index) const     { DISTRHO_SAFE_ASSERT_RETURN (index < length(), _nullValue()); return s[index]; }
 -     Item& operator[] (size_t index)                 { DISTRHO_SAFE_ASSERT_RETURN (index < length(), _nullValue()); return s[index]; }
 - 
 -     /// A handy bonus function for getting a (non-empty) span's tail elements
 -     span tail() const                               { DISTRHO_SAFE_ASSERT_RETURN (! empty(), _nullValue()); return { s + 1, e }; }
 - 
 -     const Item* begin() const noexcept              { return s; }
 -     const Item* end() const noexcept                { return e; }
 -     Item* begin() noexcept                          { return s; }
 -     Item* end() noexcept                            { return e; }
 - 
 -     /// Helper function to return a std::vector copy of the span's elements.
 -     std::vector<typename std::remove_const<Item>::type> createVector() const
 -     {
 -         return std::vector<typename std::remove_const<Item>::type> (s, e);
 -     }
 - 
 -     /// Two spans are considered identical if their elements are all comparable
 -     template <typename OtherSpan>
 -     bool operator== (const OtherSpan& other) const
 -     {
 -         auto sz = size();
 - 
 -         if (sz != other.size())
 -             return false;
 - 
 -         for (decltype (sz) i = 0; i < sz; ++i)
 -             if (s[i] != other.s[i])
 -                 return false;
 - 
 -         return true;
 -     }
 - 
 -     template <typename OtherSpan>
 -     bool operator!= (const OtherSpan& other) const  { return ! operator== (other); }
 - 
 - private:
 -     Item* s = {};
 -     Item* e = {};
 - 
 -     static inline Item& _nullValue() noexcept { static Item e = {}; return e; }
 - };
 - 
 - } // namespace choc
 - 
 - #endif // CHOC_SPAN_HEADER_INCLUDED
 
 
  |