#pragma once
#include <executorch/runtime/core/error.h>
#include <executorch/runtime/core/span.h>
#include <array>
#include <cstddef>
#include <cstring>
#include <variant>
namespace executorch {
namespace runtime {
static constexpr size_t kMaxOptionKeyLength = 64;
static constexpr size_t kMaxOptionValueLength = 256;
using OptionValue =
std::variant<bool, int, std::array<char, kMaxOptionValueLength>>;
struct BackendOption {
char key[kMaxOptionKeyLength]{};
OptionValue value;
};
template <size_t MaxCapacity>
class BackendOptions {
public:
BackendOptions(const BackendOptions& other) : size_(other.size_) {
for (size_t i = 0; i < size_; ++i) {
options_[i] = other.options_[i];
}
}
BackendOptions& operator=(const BackendOptions& other) {
if (this != &other) {
size_ = other.size_;
for (size_t i = 0; i < size_; ++i) {
options_[i] = other.options_[i];
}
}
return *this;
}
BackendOptions() : size_(0) {}
executorch::runtime::Span<BackendOption> view() {
return executorch::runtime::Span<BackendOption>(options_, size_);
}
template <size_t N>
Error set_option(const char (&key)[N], bool value) noexcept {
static_assert(N <= kMaxOptionKeyLength, "Option key is too long");
return set_option_impl(key, value);
}
template <size_t N>
Error set_option(const char (&key)[N], int value) noexcept {
static_assert(N <= kMaxOptionKeyLength, "Option key is too long");
return set_option_impl(key, value);
}
template <size_t N>
Error set_option(const char (&key)[N], const char* value) noexcept {
static_assert(N <= kMaxOptionKeyLength, "Option key is too long");
std::array<char, kMaxOptionValueLength> arr{};
strncpy(arr.data(), value, kMaxOptionValueLength - 1);
arr[kMaxOptionValueLength - 1] = '\0'; return set_option_impl(key, arr);
}
template <typename T, size_t KeyLen>
Error get_option(const char (&key)[KeyLen], T& out) const {
static_assert(KeyLen <= kMaxOptionKeyLength, "Option key is too long");
for (size_t i = 0; i < size_; ++i) {
if (std::strcmp(options_[i].key, key) == 0) {
if constexpr (std::is_same_v<T, const char*>) {
if (auto* arr = std::get_if<std::array<char, kMaxOptionValueLength>>(
&options_[i].value)) {
out = arr->data(); return Error::Ok;
}
}
else if (auto* val = std::get_if<T>(&options_[i].value)) {
out = *val;
return Error::Ok;
}
return Error::InvalidArgument;
}
}
return Error::NotFound;
}
private:
BackendOption options_[MaxCapacity]{}; size_t size_;
template <typename T>
Error set_option_impl(const char* key, T value) {
for (size_t i = 0; i < size_; ++i) {
if (strcmp(options_[i].key, key) == 0) {
options_[i].value = value;
return Error::Ok;
}
}
if (size_ < MaxCapacity) {
BackendOption new_option;
const size_t key_len = std::strlen(key);
const size_t copy_len = std::min(key_len, kMaxOptionKeyLength - 1);
std::memcpy(new_option.key, key, copy_len);
new_option.key[copy_len] = '\0';
new_option.value = value; options_[size_++] = new_option; return Error::Ok;
}
return Error::InvalidArgument;
}
};
} }