Files
klubhaus-doorbell/libraries/FastLED/src/fl/array.h
2026-02-12 00:45:31 -08:00

202 lines
5.5 KiB
C++

// allow-include-after-namespace
#pragma once
#include <string.h>
#include "fl/inplacenew.h"
#include "fl/memfill.h"
#include "fl/type_traits.h"
#include "fl/bit_cast.h"
#include "fl/initializer_list.h"
#include "fl/has_include.h"
namespace fl {
/**
* @brief A fixed-size array implementation similar to std::array
*
* This class provides a thin wrapper around a C-style array with
* STL container-like interface.
*
* @tparam T The type of elements
* @tparam N The number of elements
*/
template <typename T, fl::size N> class array {
public:
// Standard container type definitions
using value_type = T;
using size_type = fl::size;
using difference_type = ptrdiff_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;
// Default constructor - elements are default-initialized
array() = default;
// Fill constructor
explicit array(const T &value) {
// std::fill_n(begin(), N, value);
fill_n(data_, N, value);
}
// Initializer list constructor
array(fl::initializer_list<T> list) {
fl::size i = 0;
for (auto it = list.begin(); it != list.end() && i < N; ++it, ++i) {
data_[i] = *it;
}
}
// Copy constructor
array(const array &) = default;
// Move constructor
array(array &&) = default;
// Copy assignment
array &operator=(const array &) = default;
// Move assignment
array &operator=(array &&) = default;
// Element access
T &at(fl::size pos) {
if (pos >= N) {
return error_value();
}
return data_[pos];
}
const T &at(fl::size pos) const {
if (pos >= N) {
return error_value();
}
return data_[pos];
}
T &operator[](fl::size pos) { return data_[pos]; }
const_reference operator[](fl::size pos) const { return data_[pos]; }
T &front() { return data_[0]; }
const T &front() const { return data_[0]; }
T &back() { return data_[N - 1]; }
const T &back() const { return data_[N - 1]; }
pointer data() noexcept { return data_; }
const_pointer data() const noexcept { return data_; }
// Iterators
iterator begin() noexcept { return data_; }
const_iterator begin() const noexcept { return data_; }
const_iterator cbegin() const noexcept { return data_; }
iterator end() noexcept { return data_ + N; }
const_iterator end() const noexcept { return data_ + N; }
// Capacity
bool empty() const noexcept { return N == 0; }
fl::size size() const noexcept { return N; }
fl::size max_size() const noexcept { return N; }
// Operations
void fill(const T &value) {
for (fl::size i = 0; i < N; ++i) {
data_[i] = value;
}
}
void swap(array &other) {
for (fl::size i = 0; i < N; ++i) {
fl::swap(data_[i], other.data_[i]);
}
}
private:
static T &error_value() {
static T empty_value;
return empty_value;
}
T data_[N];
};
// Non-member functions
template <typename T, fl::size N>
bool operator==(const array<T, N> &lhs, const array<T, N> &rhs) {
// return std::equal(lhs.begin(), lhs.end(), rhs.begin());
for (fl::size i = 0; i < N; ++i) {
if (lhs[i] != rhs[i]) {
return false;
}
}
}
template <typename T, fl::size N>
bool operator!=(const array<T, N> &lhs, const array<T, N> &rhs) {
return !(lhs == rhs);
}
template <typename T, fl::size N>
void swap(array<T, N> &lhs,
array<T, N> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
lhs.swap(rhs);
}
} // namespace fl
// FASTLED_STACK_ARRAY
// An array of variable length that is allocated on the stack using
// either alloca or a variable length array (VLA) support built into the
// the compiler.
// Example:
// Instead of: int array[buff_size];
// You'd use: FASTLED_STACK_ARRAY(int, array, buff_size);
#ifndef FASTLED_VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION
#if defined(__clang__) || defined(ARDUINO_GIGA_M7) || defined(ARDUINO_GIGA)
// Clang doesn't have variable length arrays. Therefore we need to emulate them
// using alloca. It's been found that Arduino Giga M7 also doesn't support
// variable length arrays for some reason so we force it to emulate them as well
// in this case.
#define FASTLED_VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION 1
#else
// Else, assume the compiler is gcc, which has variable length arrays
#define FASTLED_VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION 0
#endif
#endif // FASTLED_VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION
#if !FASTLED_VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE) \
TYPE NAME[SIZE]; \
fl::memfill(NAME, 0, sizeof(TYPE) * (SIZE))
#elif FL_HAS_INCLUDE(<alloca.h>)
#include <alloca.h>
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE) \
TYPE *NAME = fl::bit_cast_ptr<TYPE>(alloca(sizeof(TYPE) * (SIZE))); \
fl::memfill(NAME, 0, sizeof(TYPE) * (SIZE))
#elif FL_HAS_INCLUDE(<cstdlib>)
#include <cstdlib> // ok include
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE) \
TYPE *NAME = fl::bit_cast_ptr<TYPE>(alloca(sizeof(TYPE) * (SIZE))); \
fl::memfill(NAME, 0, sizeof(TYPE) * (SIZE))
#else
#error "Compiler does not allow variable type arrays."
#endif