aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/array.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/array.h')
-rw-r--r--include/EASTL/array.h530
1 files changed, 530 insertions, 0 deletions
diff --git a/include/EASTL/array.h b/include/EASTL/array.h
new file mode 100644
index 0000000..590aa94
--- /dev/null
+++ b/include/EASTL/array.h
@@ -0,0 +1,530 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Implements a templated array class as per the C++ standard TR1 (technical
+// report 1, which is a list of proposed C++ library amendments).
+// The primary distinctions between this array and TR1 array are:
+// - array::size_type is defined as eastl_size_t instead of size_t in order
+// to save memory and run faster on 64 bit systems.
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_ARRAY_H
+#define EASTL_ARRAY_H
+
+
+#include <EASTL/internal/config.h>
+#include <EASTL/iterator.h>
+#include <EASTL/algorithm.h>
+#include <EASTL/utility.h>
+#include <stddef.h>
+
+#if EASTL_EXCEPTIONS_ENABLED
+ EA_DISABLE_ALL_VC_WARNINGS()
+ #include <stdexcept> // std::out_of_range, std::length_error.
+ EA_RESTORE_ALL_VC_WARNINGS()
+#endif
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
+#endif
+
+
+
+namespace eastl
+{
+
+ ///////////////////////////////////////////////////////////////////////
+ /// array
+ ///
+ /// Implements a templated array class as per the C++ standard TR1.
+ /// This class allows you to use a built-in C style array like an STL vector.
+ /// It does not let you change its size, as it is just like a C built-in array.
+ /// Our implementation here strives to remove function call nesting, as that
+ /// makes it hard for us to profile debug builds due to function call overhead.
+ /// Note that this is intentionally a struct with public data, as per the
+ /// C++ standard update proposal requirements.
+ ///
+ /// Example usage:
+ /// array<int, 5> a = { { 0, 1, 2, 3, 4 } }; // Strict compilers such as GCC require the double brackets.
+ /// a[2] = 4;
+ /// for(array<int, 5>::iterator i = a.begin(); i < a.end(); ++i)
+ /// *i = 0;
+ ///
+ template <typename T, size_t N = 1>
+ struct array
+ {
+ public:
+ typedef array<T, N> this_type;
+ typedef T value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef eastl::reverse_iterator<iterator> reverse_iterator;
+ typedef eastl::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef eastl_size_t size_type; // See config.h for the definition of eastl_size_t, which defaults to size_t.
+ typedef ptrdiff_t difference_type;
+
+ public:
+ enum
+ {
+ count = N
+ };
+
+ // Note that the member data is intentionally public.
+ // This allows for aggregate initialization of the
+ // object (e.g. array<int, 5> a = { 0, 3, 2, 4 }; )
+ value_type mValue[N ? N : 1];
+
+ public:
+ // We intentionally provide no constructor, destructor, or assignment operator.
+
+ void fill(const value_type& value);
+
+ // Unlike the swap function for other containers, array::swap takes linear time,
+ // may exit via an exception, and does not cause iterators to become associated with the other container.
+ void swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value);
+
+ EA_CPP14_CONSTEXPR iterator begin() EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_iterator begin() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR iterator end() EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_iterator end() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_iterator cend() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR reverse_iterator rbegin() EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR reverse_iterator rend() EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR bool empty() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR size_type size() const EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR size_type max_size() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR T* data() EA_NOEXCEPT;
+ EA_CPP14_CONSTEXPR const T* data() const EA_NOEXCEPT;
+
+ EA_CPP14_CONSTEXPR reference operator[](size_type i);
+ EA_CPP14_CONSTEXPR const_reference operator[](size_type i) const;
+ EA_CPP14_CONSTEXPR const_reference at(size_type i) const;
+ EA_CPP14_CONSTEXPR reference at(size_type i);
+
+ EA_CPP14_CONSTEXPR reference front();
+ EA_CPP14_CONSTEXPR const_reference front() const;
+
+ EA_CPP14_CONSTEXPR reference back();
+ EA_CPP14_CONSTEXPR const_reference back() const;
+
+ bool validate() const;
+ int validate_iterator(const_iterator i) const;
+
+ }; // class array
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // template deduction guides
+ ///////////////////////////////////////////////////////////////////////////
+ #ifdef __cpp_deduction_guides
+ template <class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;
+ #endif
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // array
+ ///////////////////////////////////////////////////////////////////////
+
+
+ template <typename T, size_t N>
+ inline void array<T, N>::fill(const value_type& value)
+ {
+ eastl::fill_n(&mValue[0], N, value);
+ }
+
+
+ template <typename T, size_t N>
+ inline void array<T, N>::swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value)
+ {
+ eastl::swap_ranges(&mValue[0], &mValue[N], &x.mValue[0]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::iterator
+ array<T, N>::begin() EA_NOEXCEPT
+ {
+ return &mValue[0];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
+ array<T, N>::begin() const EA_NOEXCEPT
+ {
+ return &mValue[0];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
+ array<T, N>::cbegin() const EA_NOEXCEPT
+ {
+ return &mValue[0];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::iterator
+ array<T, N>::end() EA_NOEXCEPT
+ {
+ return &mValue[N];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
+ array<T, N>::end() const EA_NOEXCEPT
+ {
+ return &mValue[N];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
+ array<T, N>::cend() const EA_NOEXCEPT
+ {
+ return &mValue[N];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator
+ array<T, N>::rbegin() EA_NOEXCEPT
+ {
+ return reverse_iterator(&mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
+ array<T, N>::rbegin() const EA_NOEXCEPT
+ {
+ return const_reverse_iterator(&mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
+ array<T, N>::crbegin() const EA_NOEXCEPT
+ {
+ return const_reverse_iterator(&mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator
+ array<T, N>::rend() EA_NOEXCEPT
+ {
+ return reverse_iterator(&mValue[0]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
+ array<T, N>::rend() const EA_NOEXCEPT
+ {
+ return const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
+ array<T, N>::crend() const EA_NOEXCEPT
+ {
+ return const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::size_type
+ array<T, N>::size() const EA_NOEXCEPT
+ {
+ return (size_type)N;
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::size_type
+ array<T, N>::max_size() const EA_NOEXCEPT
+ {
+ return (size_type)N;
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool array<T, N>::empty() const EA_NOEXCEPT
+ {
+ return (N == 0);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
+ array<T, N>::operator[](size_type i)
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ EASTL_FAIL_MSG("array::operator[] -- out of range");
+ #endif
+
+ EA_ANALYSIS_ASSUME(i < N);
+ return mValue[i];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
+ array<T, N>::operator[](size_type i) const
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ EASTL_FAIL_MSG("array::operator[] -- out of range");
+
+ #endif
+
+ EA_ANALYSIS_ASSUME(i < N);
+ return mValue[i];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
+ array<T, N>::front()
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(empty())) // We don't allow the user to reference an empty container.
+ EASTL_FAIL_MSG("array::front -- empty array");
+ #endif
+
+ return mValue[0];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
+ array<T, N>::front() const
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(empty())) // We don't allow the user to reference an empty container.
+ EASTL_FAIL_MSG("array::front -- empty array");
+ #endif
+
+ return mValue[0];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
+ array<T, N>::back()
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(empty())) // We don't allow the user to reference an empty container.
+ EASTL_FAIL_MSG("array::back -- empty array");
+ #endif
+
+ return mValue[N - 1];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
+ array<T, N>::back() const
+ {
+ #if EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(empty())) // We don't allow the user to reference an empty container.
+ EASTL_FAIL_MSG("array::back -- empty array");
+ #endif
+
+ return mValue[N - 1];
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline T* array<T, N>::data() EA_NOEXCEPT
+ {
+ return mValue;
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline const T* array<T, N>::data() const EA_NOEXCEPT
+ {
+ return mValue;
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference array<T, N>::at(size_type i) const
+ {
+ #if EASTL_EXCEPTIONS_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ throw std::out_of_range("array::at -- out of range");
+ #elif EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ EASTL_FAIL_MSG("array::at -- out of range");
+ #endif
+
+ EA_ANALYSIS_ASSUME(i < N);
+ return static_cast<const_reference>(mValue[i]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline typename array<T, N>::reference array<T, N>::at(size_type i)
+ {
+ #if EASTL_EXCEPTIONS_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ throw std::out_of_range("array::at -- out of range");
+ #elif EASTL_ASSERT_ENABLED
+ if(EASTL_UNLIKELY(i >= N))
+ EASTL_FAIL_MSG("array::at -- out of range");
+ #endif
+
+ EA_ANALYSIS_ASSUME(i < N);
+ return static_cast<reference>(mValue[i]);
+ }
+
+
+ template <typename T, size_t N>
+ inline bool array<T, N>::validate() const
+ {
+ return true; // There is nothing to do.
+ }
+
+
+ template <typename T, size_t N>
+ inline int array<T, N>::validate_iterator(const_iterator i) const
+ {
+ if(i >= mValue)
+ {
+ if(i < (mValue + N))
+ return (isf_valid | isf_current | isf_can_dereference);
+
+ if(i <= (mValue + N))
+ return (isf_valid | isf_current);
+ }
+
+ return isf_none;
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // global operators
+ ///////////////////////////////////////////////////////////////////////
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator==(const array<T, N>& a, const array<T, N>& b)
+ {
+ return eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator<(const array<T, N>& a, const array<T, N>& b)
+ {
+ return eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator!=(const array<T, N>& a, const array<T, N>& b)
+ {
+ return !eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator>(const array<T, N>& a, const array<T, N>& b)
+ {
+ return eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator<=(const array<T, N>& a, const array<T, N>& b)
+ {
+ return !eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ EA_CPP14_CONSTEXPR inline bool operator>=(const array<T, N>& a, const array<T, N>& b)
+ {
+ return !eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);
+ }
+
+
+ template <typename T, size_t N>
+ inline void swap(array<T, N>& a, array<T, N>& b)
+ {
+ eastl::swap_ranges(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // to_array
+ ///////////////////////////////////////////////////////////////////////
+ namespace internal
+ {
+ template<class T, size_t N, size_t... I>
+ EA_CONSTEXPR auto to_array(T (&a)[N], index_sequence<I...>)
+ {
+ return eastl::array<eastl::remove_cv_t<T>, N>{{a[I]...}};
+ }
+
+ template<class T, size_t N, size_t... I>
+ EA_CONSTEXPR auto to_array(T (&&a)[N], index_sequence<I...>)
+ {
+ return eastl::array<eastl::remove_cv_t<T>, N>{{eastl::move(a[I])...}};
+ }
+ }
+
+ template<class T, size_t N>
+ EA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&a)[N])
+ {
+ static_assert(eastl::is_constructible_v<T, T&>, "element type T must be copy-initializable");
+ static_assert(!eastl::is_array_v<T>, "passing multidimensional arrays to to_array is ill-formed");
+ return internal::to_array(a, eastl::make_index_sequence<N>{});
+ }
+
+ template<class T, size_t N>
+ EA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&&a)[N])
+ {
+ static_assert(eastl::is_move_constructible_v<T>, "element type T must be move-constructible");
+ static_assert(!eastl::is_array_v<T>, "passing multidimensional arrays to to_array is ill-formed");
+ return internal::to_array(eastl::move(a), eastl::make_index_sequence<N>{});
+ }
+
+
+} // namespace eastl
+
+
+#endif // Header include guard
+
+
+
+
+
+
+
+
+
+