blob: a4bbd40596f169a5574c4120a99fdbec9e74865a [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_LIB_BOOT_OPTIONS_ENUM_H_
#define ZIRCON_KERNEL_LIB_BOOT_OPTIONS_ENUM_H_
#include <lib/boot-options/types.h>
#include <stdio.h>
#include <optional>
#include <string_view>
// This is specialized for each Enum type with a generic lambda that calls
// either EnumParser::Case or EnumPrinter::Case once for each enum value.
template <typename T>
constexpr bool Enum = false; // Will cause errors since it's not callable.
#if BOOT_OPTIONS_TESTONLY_OPTIONS
template <>
constexpr auto Enum<TestEnum> = [](auto&& Switch) {
Switch //
.Case("default", TestEnum::kDefault)
.Case("value1", TestEnum::kValue1)
.Case("value2", TestEnum::kValue2);
};
#endif
template <>
constexpr auto Enum<OomBehavior> = [](auto&& Switch) {
Switch //
.Case("reboot", OomBehavior::kReboot)
.Case("jobkill", OomBehavior::kJobKill);
};
#if BOOT_OPTIONS_GENERATOR || defined(__x86_64__)
template <>
constexpr auto Enum<IntelHwpPolicy> = [](auto&& Switch) {
Switch //
.Case("bios-specified", IntelHwpPolicy::kBiosSpecified)
.Case("performance", IntelHwpPolicy::kPerformance)
.Case("balanced", IntelHwpPolicy::kBalanced)
.Case("power-save", IntelHwpPolicy::kPowerSave)
.Case("stable-performance", IntelHwpPolicy::kStablePerformance);
};
#endif // BOOT_OPTIONS_GENERATOR || defined(__x86_64__)
// Helpers for enum overrides.
template <typename F, typename T>
class EnumEnumerator {
public:
EnumEnumerator(F call, T value) : call_(std::move(call)), value_(std::move(value)) {}
constexpr EnumEnumerator& Case(std::string_view name, T value) {
call_(name);
return *this;
}
private:
F call_;
T value_;
};
template <typename T>
class EnumParser {
public:
EnumParser(std::string_view name, T* result) : name_(name), result_(result) {}
~EnumParser() {
if (result_) {
printf("WARN: Ignored unknown value '%.*s' for multiple-choice option\n",
static_cast<int>(name_.size()), name_.data());
printf("WARN: Valid choices are:");
Enum<T>(EnumEnumerator{[](std::string_view name) {
printf(" %.*s", static_cast<int>(name.size()), name.data());
},
*result_});
printf("\n");
}
}
constexpr EnumParser& Case(std::string_view name, T value) {
if (result_ && name == name_) {
*result_ = value;
result_ = nullptr;
}
return *this;
}
private:
std::string_view name_;
T* result_ = nullptr;
};
template <typename T>
class EnumPrinter {
public:
EnumPrinter(T value, FILE* out) : value_(std::move(value)), out_(out) {}
EnumPrinter& Case(std::string_view name, T value) {
if (value_ && *value_ == value) {
value_.reset();
fprintf(out_, "%.*s", static_cast<int>(name.size()), name.data());
}
return *this;
}
~EnumPrinter() {
if (value_) {
fprintf(out_, "<unknown.enum.value.%#lx>", static_cast<unsigned long int>(*value_));
}
}
private:
std::optional<T> value_;
FILE* out_ = nullptr;
};
// Deduction guides.
template <typename F, typename T>
EnumEnumerator(F, T) -> EnumEnumerator<F, T>;
template <typename T>
EnumParser(std::string_view, T*) -> EnumParser<T>;
template <typename T>
EnumPrinter(const T&, FILE*) -> EnumPrinter<T>;
#endif // ZIRCON_KERNEL_LIB_BOOT_OPTIONS_ENUM_H_