1 //===-- include/flang/Common/enum-class.h -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // The macro
10 // ENUM_CLASS(className, enum1, enum2, ..., enumN)
11 // defines
12 // enum class className { enum1, enum2, ... , enumN };
13 // as well as the introspective utilities
14 // static constexpr std::size_t className_enumSize{N};
15 // static inline std::string_view EnumToString(className);
16
17 #ifndef FORTRAN_COMMON_ENUM_CLASS_H_
18 #define FORTRAN_COMMON_ENUM_CLASS_H_
19
20 #include <array>
21 #include <string>
22
23 namespace Fortran::common {
24
CountEnumNames(const char * p)25 constexpr std::size_t CountEnumNames(const char *p) {
26 std::size_t n{0};
27 std::size_t any{0};
28 for (; *p; ++p) {
29 if (*p == ',') {
30 n += any;
31 any = 0;
32 } else if (*p != ' ') {
33 any = 1;
34 }
35 }
36 return n + any;
37 }
38
39 template <std::size_t ITEMS>
EnumNames(const char * p)40 constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
41 std::array<std::string_view, ITEMS> result{""};
42 std::size_t at{0};
43 const char *start{nullptr};
44 for (; *p; ++p) {
45 if (*p == ',' || *p == ' ') {
46 if (start) {
47 result[at++] =
48 std::string_view{start, static_cast<std::size_t>(p - start)};
49 start = nullptr;
50 }
51 } else if (!start) {
52 start = p;
53 }
54 }
55 if (start) {
56 result[at] = std::string_view{start, static_cast<std::size_t>(p - start)};
57 }
58 return result;
59 }
60
61 #define ENUM_CLASS(NAME, ...) \
62 enum class NAME { __VA_ARGS__ }; \
63 [[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \
64 ::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \
65 [[maybe_unused]] static inline std::string_view EnumToString(NAME e) { \
66 static const constexpr auto names{ \
67 ::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
68 return names[static_cast<std::size_t>(e)]; \
69 }
70
71 } // namespace Fortran::common
72 #endif // FORTRAN_COMMON_ENUM_CLASS_H_
73