commit e279976: [Project] Css: Add frozen library from https://github.com/serge-sans-paille/frozen/

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Feb 18 16:56:25 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-02-18 14:14:44 +0000
URL: https://github.com/rspamd/rspamd/commit/e2799764c4cd50a5efa220c76648eae667cd4491

[Project] Css: Add frozen library from https://github.com/serge-sans-paille/frozen/

---
 contrib/DEPENDENCY_INFO.md                         |   3 +-
 contrib/frozen/AUTHORS                             |   3 +
 contrib/frozen/CMakeLists.txt                      |  12 +
 contrib/{google-ced => frozen}/LICENSE             |   2 +-
 contrib/frozen/include/frozen/algorithm.h          | 197 +++++++++++++
 contrib/frozen/include/frozen/bits/algorithms.h    | 229 +++++++++++++++
 contrib/frozen/include/frozen/bits/basic_types.h   | 200 +++++++++++++
 .../frozen/include/frozen/bits/constexpr_assert.h  |  40 +++
 contrib/frozen/include/frozen/bits/defines.h       |  58 ++++
 contrib/frozen/include/frozen/bits/elsa.h          |  50 ++++
 contrib/frozen/include/frozen/bits/exceptions.h    |  39 +++
 contrib/frozen/include/frozen/bits/pmh.h           | 240 +++++++++++++++
 contrib/frozen/include/frozen/bits/version.h       |  30 ++
 contrib/frozen/include/frozen/map.h                | 323 +++++++++++++++++++++
 contrib/frozen/include/frozen/random.h             |  90 ++++++
 contrib/frozen/include/frozen/set.h                | 220 ++++++++++++++
 contrib/frozen/include/frozen/string.h             | 152 ++++++++++
 contrib/frozen/include/frozen/unordered_map.h      | 197 +++++++++++++
 contrib/frozen/include/frozen/unordered_set.h      | 147 ++++++++++
 19 files changed, 2230 insertions(+), 2 deletions(-)

diff --git a/contrib/DEPENDENCY_INFO.md b/contrib/DEPENDENCY_INFO.md
index f5c228d1d..502d7e161 100644
--- a/contrib/DEPENDENCY_INFO.md
+++ b/contrib/DEPENDENCY_INFO.md
@@ -29,4 +29,5 @@
 | fpconv        | ?       | Boost               | YES     | many changes       |
 | fastutf8      | ?       | MIT                 | YES     | many changes       |
 | expected      | v1.0    | Public Domain / CC0 | NO      |                    |
-| robin-hood    | 3.9.1   | MIT                 | NO      |                    |
\ No newline at end of file
+| robin-hood    | 3.9.1   | MIT                 | NO      |                    |
+| frozen        | 1.0.1   | Apache 2            | NO      |                    |
diff --git a/contrib/frozen/AUTHORS b/contrib/frozen/AUTHORS
new file mode 100644
index 000000000..d83d0f86e
--- /dev/null
+++ b/contrib/frozen/AUTHORS
@@ -0,0 +1,3 @@
+serge-sans-paille <sguelton at quarkslab.com>
+Jérôme Dumesnil <jerome.dumesnil at gmail.com>
+Chris Beck <chbeck at tesla.com>
diff --git a/contrib/frozen/CMakeLists.txt b/contrib/frozen/CMakeLists.txt
new file mode 100644
index 000000000..185378d5c
--- /dev/null
+++ b/contrib/frozen/CMakeLists.txt
@@ -0,0 +1,12 @@
+target_sources(frozen-headers INTERFACE
+  "${prefix}/frozen/algorithm.h"
+  "${prefix}/frozen/map.h"
+  "${prefix}/frozen/random.h"
+  "${prefix}/frozen/set.h"
+  "${prefix}/frozen/string.h"
+  "${prefix}/frozen/unordered_map.h"
+  "${prefix}/frozen/unordered_set.h"
+  "${prefix}/frozen/bits/algorithms.h"
+  "${prefix}/frozen/bits/basic_types.h"
+  "${prefix}/frozen/bits/elsa.h"
+  "${prefix}/frozen/bits/pmh.h")
diff --git a/contrib/google-ced/LICENSE b/contrib/frozen/LICENSE
similarity index 99%
copy from contrib/google-ced/LICENSE
copy to contrib/frozen/LICENSE
index d64569567..5b4b9bdc6 100644
--- a/contrib/google-ced/LICENSE
+++ b/contrib/frozen/LICENSE
@@ -187,7 +187,7 @@
       same "printed page" as the copyright notice for easier
       identification within third-party archives.
 
-   Copyright [yyyy] [name of copyright owner]
+   Copyright 2017 Quarkslab
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff --git a/contrib/frozen/include/frozen/algorithm.h b/contrib/frozen/include/frozen/algorithm.h
new file mode 100644
index 000000000..a543eb319
--- /dev/null
+++ b/contrib/frozen/include/frozen/algorithm.h
@@ -0,0 +1,197 @@
+/*
+ * Frozen
+ * Copyright 2016 QuarksLab
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 FROZEN_LETITGO_ALGORITHM_H
+#define FROZEN_LETITGO_ALGORITHM_H
+
+#include "frozen/bits/basic_types.h"
+#include "frozen/bits/version.h"
+#include "frozen/string.h"
+
+namespace frozen {
+
+// 'search' implementation if C++17 is not available
+// https://en.cppreference.com/w/cpp/algorithm/search
+template<class ForwardIterator, class Searcher>
+ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher & searcher)
+{
+  return searcher(first, last).first;
+}
+
+// text book implementation from
+// https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
+
+template <std::size_t size> class knuth_morris_pratt_searcher {
+  bits::carray<std::ptrdiff_t, size> step_;
+  bits::carray<char, size> needle_;
+
+  static constexpr bits::carray<std::ptrdiff_t, size>
+  build_kmp_cache(char const (&needle)[size + 1]) {
+    std::ptrdiff_t cnd = 0;
+    bits::carray<std::ptrdiff_t, size> cache;
+
+    cache.fill(-1);
+    for (std::size_t pos = 1; pos < size; ++pos) {
+      if (needle[pos] == needle[cnd]) {
+        cache[pos] = cache[cnd];
+        cnd += 1;
+      } else {
+        cache[pos] = cnd;
+        cnd = cache[cnd];
+        while (cnd >= 0 && needle[pos] != needle[cnd])
+          cnd = cache[cnd];
+        cnd += 1;
+      }
+    }
+    return cache;
+  }
+
+public:
+  constexpr knuth_morris_pratt_searcher(char const (&needle)[size + 1])
+    : step_{build_kmp_cache(needle)}, needle_(needle) {}
+
+  template <class ForwardIterator>
+  constexpr std::pair<ForwardIterator, ForwardIterator> operator()(ForwardIterator first, ForwardIterator last) const {
+    std::size_t i = 0;
+    ForwardIterator iter = first;
+    while (iter != last) {
+      if (needle_[i] == *iter) {
+        if (i == (size - 1))
+          return { iter - i, iter - i + size };
+        ++i;
+        ++iter;
+      } else {
+        if (step_[i] > -1) {
+          i = step_[i];
+        } else {
+          ++iter;
+          i = 0;
+        }
+      }
+    }
+    return { last, last };
+  }
+};
+
+template <std::size_t N>
+constexpr knuth_morris_pratt_searcher<N - 1> make_knuth_morris_pratt_searcher(char const (&needle)[N]) {
+  return {needle};
+}
+
+// text book implementation from
+// https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm
+
+template <std::size_t size> class boyer_moore_searcher {
+  using skip_table_type = bits::carray<std::ptrdiff_t, sizeof(char) << 8>;
+  using suffix_table_type = bits::carray<std::ptrdiff_t, size>;
+
+  skip_table_type skip_table_;
+  suffix_table_type suffix_table_;
+  bits::carray<char, size> needle_;
+
+  constexpr auto build_skip_table(char const (&needle)[size + 1]) {
+    skip_table_type skip_table;
+
+    skip_table.fill(size);
+    for (std::size_t i = 0; i < size - 1; ++i)
+      skip_table[needle[i]] -= i + 1;
+    return skip_table;
+  }
+
+  constexpr bool is_prefix(char const (&needle)[size + 1], std::size_t pos) {
+    std::size_t suffixlen = size - pos;
+    
+    for (std::size_t i = 0; i < suffixlen; i++) {
+      if (needle[i] != needle[pos + i])
+        return false;
+    }
+    return true;
+  }
+
+  constexpr std::size_t suffix_length(char const (&needle)[size + 1],
+                                      std::size_t pos) {
+    // increment suffix length slen to the first mismatch or beginning
+    // of the word
+    for (std::size_t slen = 0; slen < pos ; slen++)
+      if (needle[pos - slen] != needle[size - 1 - slen])
+        return slen;
+
+    return pos;
+  }
+
+  constexpr auto build_suffix_table(char const (&needle)[size + 1]) {
+    suffix_table_type suffix;
+    std::ptrdiff_t last_prefix_index = size - 1;
+
+    // first loop
+    for (std::ptrdiff_t p = size - 1; p >= 0; p--) {
+      if (is_prefix(needle, p + 1))
+        last_prefix_index = p + 1;
+
+      suffix[p] = last_prefix_index + (size - 1 - p);
+    }
+
+    // second loop
+    for (std::size_t p = 0; p < size - 1; p++) {
+      auto slen = suffix_length(needle, p);
+      if (needle[p - slen] != needle[size - 1 - slen])
+        suffix[size - 1 - slen] = size - 1 - p + slen;
+
+    }
+    return suffix;
+  }
+
+public:
+  constexpr boyer_moore_searcher(char const (&needle)[size + 1])
+    : skip_table_{build_skip_table(needle)},
+      suffix_table_{build_suffix_table(needle)},
+      needle_(needle) {}
+
+  template <class ForwardIterator>
+  constexpr std::pair<ForwardIterator, ForwardIterator> operator()(ForwardIterator first, ForwardIterator last) const {
+    if (size == 0)
+      return { first, first + size };
+
+    ForwardIterator iter = first + size - 1;
+    while (iter < last) {
+      std::ptrdiff_t j = size - 1;
+      while (j > 0 && (*iter == needle_[j])) {
+        --iter;
+        --j;
+      }
+      if (*iter == needle_[0])
+        return { iter, iter + size};
+
+      iter += std::max(skip_table_[*iter], suffix_table_[j]);
+    }
+    return { last, last + size};
+  }
+};
+
+template <std::size_t N>
+constexpr boyer_moore_searcher<N - 1> make_boyer_moore_searcher(char const (&needle)[N]) {
+  return {needle};
+}
+
+} // namespace frozen
+
+#endif
diff --git a/contrib/frozen/include/frozen/bits/algorithms.h b/contrib/frozen/include/frozen/bits/algorithms.h
new file mode 100644
index 000000000..8d1ffbc52
--- /dev/null
+++ b/contrib/frozen/include/frozen/bits/algorithms.h
@@ -0,0 +1,229 @@
+/*
+ * Frozen
+ * Copyright 2016 QuarksLab
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 FROZEN_LETITGO_BITS_ALGORITHMS_H
+#define FROZEN_LETITGO_BITS_ALGORITHMS_H
+
+#include "frozen/bits/basic_types.h"
+
+#include <limits>
+#include <tuple>
+
+namespace frozen {
+
+namespace bits {
+
+auto constexpr next_highest_power_of_two(std::size_t v) {
+  // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+  constexpr auto trip_count = std::numeric_limits<decltype(v)>::digits;
+  v--;
+  for(std::size_t i = 1; i < trip_count; i <<= 1)
+    v |= v >> i;
+  v++;
+  return v;
+}
+
+template<class T>
+auto constexpr log(T v) {
+  std::size_t n = 0;
+  while (v > 1) {
+    n += 1;
+    v >>= 1;
+  }
+  return n;
+}
+
+constexpr std::size_t bit_weight(std::size_t n) {
+  return (n <= 8*sizeof(unsigned int))
+    + (n <= 8*sizeof(unsigned long))
+    + (n <= 8*sizeof(unsigned long long))
+    + (n <= 128);
+}
+
+unsigned int select_uint_least(std::integral_constant<std::size_t, 4>);
+unsigned long select_uint_least(std::integral_constant<std::size_t, 3>);
+unsigned long long select_uint_least(std::integral_constant<std::size_t, 2>);
+template<std::size_t N>
+unsigned long long select_uint_least(std::integral_constant<std::size_t, N>) {
+  static_assert(N < 2, "unsupported type size");
+  return {};
+}
+
+
+template<std::size_t N>
+using select_uint_least_t = decltype(select_uint_least(std::integral_constant<std::size_t, bit_weight(N)>()));
+
+template <typename Iter, typename Compare>
+constexpr auto min_element(Iter begin, const Iter end,
+                           Compare const &compare) {
+  auto result = begin;
+  while (begin != end) {
+    if (compare(*begin, *result)) {
+      result = begin;
+    }
+    ++begin;
+  }
+  return result;
+}
+
+template <class T>
+constexpr void cswap(T &a, T &b) {
+  auto tmp = a;
+  a = b;
+  b = tmp;
+}
+
+template <class T, class U>
+constexpr void cswap(std::pair<T, U> & a, std::pair<T, U> & b) {
+  cswap(a.first, b.first);
+  cswap(a.second, b.second);
+}
+
+template <class... Tys, std::size_t... Is>
+constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b, std::index_sequence<Is...>) {
+  using swallow = int[];
+  (void) swallow{(cswap(std::get<Is>(a), std::get<Is>(b)), 0)...};
+}
+
+template <class... Tys>
+constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b) {
+  cswap(a, b, std::make_index_sequence<sizeof...(Tys)>());
+}
+
+template <typename Iterator, class Compare>
+constexpr Iterator partition(Iterator left, Iterator right, Compare const &compare) {
+  auto pivot = left + (right - left) / 2;
+  auto value = *pivot;
+  cswap(*right, *pivot);
+  for (auto it = left; 0 < right - it; ++it) {
+    if (compare(*it, value)) {
+      cswap(*it, *left);
+      left++;
+    }
+  }
+  cswap(*right, *left);
+  return left;
+}
+
+template <typename Iterator, class Compare>
+constexpr void quicksort(Iterator left, Iterator right, Compare const &compare) {
+  while (0 < right - left) {
+    auto new_pivot = bits::partition(left, right, compare);
+    quicksort(left, new_pivot, compare);
+    left = new_pivot + 1;
+  }
+}
+
+template <typename T, std::size_t N, class Compare>
+constexpr bits::carray<T, N> quicksort(bits::carray<T, N> const &array,
+                                     Compare const &compare) {
+  bits::carray<T, N> res = array;
+  quicksort(res.begin(), res.end() - 1, compare);
+  return res;
+}
+
+template <class T, class Compare> struct LowerBound {
+  T const &value_;
+  Compare const &compare_;
+  constexpr LowerBound(T const &value, Compare const &compare)
+      : value_(value), compare_(compare) {}
+
+  template <class ForwardIt>
+  inline constexpr ForwardIt doit_fast(ForwardIt first,
+                                  std::integral_constant<std::size_t, 0>) {
+    return first;
+  }
+
+  template <class ForwardIt, std::size_t N>
+  inline constexpr ForwardIt doit_fast(ForwardIt first,
+                                  std::integral_constant<std::size_t, N>) {
+    auto constexpr step = N / 2;
+    static_assert(N/2 == N - N / 2 - 1, "power of two minus 1");
+    auto it = first + step;
+    auto next_it = compare_(*it, value_) ? it + 1 : first;
+    return doit_fast(next_it, std::integral_constant<std::size_t, N / 2>{});
+  }
+
+  template <class ForwardIt, std::size_t N>
+  inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, true>) {
+    return doit_fast(first, std::integral_constant<std::size_t, N>{});
+  }
+
+  template <class ForwardIt, std::size_t N>
+  inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, false>) {
+    auto constexpr next_power = next_highest_power_of_two(N);
+    auto constexpr next_start = next_power / 2 - 1;
+    auto it = first + next_start;
+    if (compare_(*it, value_)) {
+      auto constexpr next = N - next_start - 1;
+      return doitfirst(it + 1, std::integral_constant<std::size_t, next>{}, std::integral_constant<bool, next_highest_power_of_two(next) - 1 == next>{});
+    }
+    else
+      return doit_fast(first, std::integral_constant<std::size_t, next_start>{});
+  }
+
+  template <class ForwardIt>
+  inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, 1>, std::integral_constant<bool, false>) {
+    return doit_fast(first, std::integral_constant<std::size_t, 1>{});
+  }
+};
+
+template <std::size_t N, class ForwardIt, class T, class Compare>
+constexpr ForwardIt lower_bound(ForwardIt first, const T &value, Compare const &compare) {
+  return LowerBound<T, Compare>{value, compare}.doitfirst(first, std::integral_constant<std::size_t, N>{}, std::integral_constant<bool, next_highest_power_of_two(N) - 1 == N>{});
+}
+
+template <std::size_t N, class Compare, class ForwardIt, class T>
+constexpr bool binary_search(ForwardIt first, const T &value,
+                             Compare const &compare) {
+  ForwardIt where = lower_bound<N>(first, value, compare);
+  return (!(where == first + N) && !(compare(value, *where)));
+}
+
+
+template<class InputIt1, class InputIt2>
+constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
+{
+  for (; first1 != last1; ++first1, ++first2) {
+    if (!(*first1 == *first2)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+template<class InputIt1, class InputIt2>
+constexpr bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
+{
+  for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
+    if (*first1 < *first2)
+      return true;
+    if (*first2 < *first1)
+      return false;
+  }
+  return (first1 == last1) && (first2 != last2);
+}
+
+} // namespace bits
+} // namespace frozen
+
+#endif
diff --git a/contrib/frozen/include/frozen/bits/basic_types.h b/contrib/frozen/include/frozen/bits/basic_types.h
new file mode 100644
index 000000000..9814bac80
--- /dev/null
+++ b/contrib/frozen/include/frozen/bits/basic_types.h
@@ -0,0 +1,200 @@
+/*
+ * Frozen
+ * Copyright 2016 QuarksLab
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 FROZEN_LETITGO_BASIC_TYPES_H
+#define FROZEN_LETITGO_BASIC_TYPES_H
+
+#include "frozen/bits/exceptions.h"
+
+#include <utility>
+#include <iterator>
+#include <string>
+
+namespace frozen {
+
+namespace bits {
+
+// used as a fake argument for frozen::make_set and frozen::make_map in the case of N=0
+struct ignored_arg {};
+
+template <class T, std::size_t N>
+class cvector {
+  T data [N] = {}; // zero-initialization for scalar type T, default-initialized otherwise
+  std::size_t dsize = 0;
+
+public:
+  // Container typdefs
+  using value_type = T;
+  using reference = value_type &;
+  using const_reference = const value_type &;
+  using pointer = value_type *;
+  using const_pointer = const value_type *;
+  using iterator = pointer;
+  using const_iterator = const_pointer;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  // Constructors
+  constexpr cvector(void) = default;
+  constexpr cvector(size_type count, const T& value) : dsize(count) {
+    for (std::size_t i = 0; i < N; ++i)
+      data[i] = value;
+  }
+
+  // Iterators
+  constexpr iterator begin() noexcept { return data; }
+  constexpr iterator end() noexcept { return data + dsize; }
+
+  // Capacity
+  constexpr size_type size() const { return dsize; }
+
+  // Element access
+  constexpr       reference operator[](std::size_t index) { return data[index]; }
+  constexpr const_reference operator[](std::size_t index) const { return data[index]; }
+
+  constexpr       reference back() { return data[dsize - 1]; }
+  constexpr const_reference back() const { return data[dsize - 1]; }
+
+  // Modifiers
+  constexpr void push_back(const T & a) { data[dsize++] = a; }
+  constexpr void push_back(T && a) { data[dsize++] = std::move(a); }
+  constexpr void pop_back() { --dsize; }
+
+  constexpr void clear() { dsize = 0; }
+};
+
+template <class T, std::size_t N>
+class carray {
+  T data_ [N] = {}; // zero-initialization for scalar type T, default-initialized otherwise
+
+  template <std::size_t M, std::size_t... I>
+  constexpr carray(T const (&init)[M], std::index_sequence<I...>)
+      : data_{init[I]...} {}
+  template <class Iter, std::size_t... I>
+  constexpr carray(Iter iter, std::index_sequence<I...>)
+      : data_{((void)I, *iter++)...} {}
+
+public:
+  // Container typdefs
+  using value_type = T;
+  using reference = value_type &;
+  using const_reference = const value_type &;
+  using pointer = value_type *;
+  using const_pointer = const value_type *;
+  using iterator = pointer;
+  using const_iterator = const_pointer;
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  // Constructors
+  constexpr carray(void) = default;
+  template <std::size_t M>
+  constexpr carray(T const (&init)[M])
+    : carray(init, std::make_index_sequence<N>())
+  {
+    static_assert(M >= N, "Cannot initialize a carray with an smaller array");
+  }
+  constexpr carray(std::initializer_list<T> init)
+    : carray(init.begin(), std::make_index_sequence<N>())
+  {
+    // clang & gcc doesn't recognize init.size() as a constexpr
+    // static_assert(init.size() >= N, "Cannot initialize a carray with an smaller initializer list");
+  }
+
+  // Iterators
+  constexpr iterator begin() noexcept { return data_; }
+  constexpr const_iterator begin() const noexcept { return data_; }
+  constexpr const_iterator cbegin() const noexcept { return data_; }
+  constexpr iterator end() noexcept { return data_ + N; }
+  constexpr const_iterator end() const noexcept { return data_ + N; }
+  constexpr const_iterator cend() const noexcept { return data_ + N; }
+
+  constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+  constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+  constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+  constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+  constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+  constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
+
+  // Capacity
+  constexpr size_type size() const { return N; }
+  constexpr size_type max_size() const { return N; }
+
+  // Element access
+  constexpr       reference operator[](std::size_t index) { return data_[index]; }
+  constexpr const_reference operator[](std::size_t index) const { return data_[index]; }
+
+  constexpr       reference at(std::size_t index) {
+    if (index > N)
+      FROZEN_THROW_OR_ABORT(std::out_of_range("Index (" + std::to_string(index) + ") out of bound (" + std::to_string(N) + ')'));
+    return data_[index];
+  }
+  constexpr const_reference at(std::size_t index) const {
+    if (index > N)
+      FROZEN_THROW_OR_ABORT(std::out_of_range("Index (" + std::to_string(index) + ") out of bound (" + std::to_string(N) + ')'));
+    return data_[index];
+  }
+
+  constexpr       reference front() { return data_[0]; }
+  constexpr const_reference front() const { return data_[0]; }
+
+  constexpr       reference back() { return data_[N - 1]; }
+  constexpr const_reference back() const { return data_[N - 1]; }
+
+  constexpr       value_type* data() noexcept { return data_; }
+  constexpr const value_type* data() const noexcept { return data_; }
+
+  // Modifiers
+  constexpr void fill(const value_type& val) {
+    for (std::size_t i = 0; i < N; ++i)
+      data_[i] = val;
+  }
+};
*** OUTPUT TRUNCATED, 1685 LINES SKIPPED ***


More information about the Commits mailing list