//===-- include/flang/Common/enum-class.h -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// The macro
// ENUM_CLASS(className, enum1, enum2, ..., enumN)
// defines
// enum class className { enum1, enum2, ... , enumN };
// as well as the introspective utilities
// static constexpr std::size_t className_enumSize{N};
// static inline std::string_view EnumToString(className);
#ifndef FORTRAN_COMMON_ENUM_CLASS_H_
#define FORTRAN_COMMON_ENUM_CLASS_H_
#include <array>
#include <string>
namespace Fortran::common {
constexpr std::size_t CountEnumNames(const char *p) {
std::size_t n{0};
std::size_t any{0};
for (; *p; ++p) {
if (*p == ',') {
n += any;
any = 0;
} else if (*p != ' ') {
any = 1;
}
}
return n + any;
}
template <std::size_t ITEMS>
constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
std::array<std::string_view, ITEMS> result{""};
std::size_t at{0};
const char *start{nullptr};
for (; *p; ++p) {
if (*p == ',' || *p == ' ') {
if (start) {
result[at++] =
std::string_view{start, static_cast<std::size_t>(p - start)};
start = nullptr;
}
} else if (!start) {
start = p;
}
}
if (start) {
result[at] = std::string_view{start, static_cast<std::size_t>(p - start)};
}
return result;
}
#define ENUM_CLASS(NAME, ...) \
enum class NAME { __VA_ARGS__ }; \
[[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \
::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \
[[maybe_unused]] static inline std::string_view EnumToString(NAME e) { \
static const constexpr auto names{ \
::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
return names[static_cast<std::size_t>(e)]; \
}
} // namespace Fortran::common
#endif // FORTRAN_COMMON_ENUM_CLASS_H_