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