xref: /llvm-project/flang/include/flang/Common/enum-class.h (revision 3bebf3b4950494ce9d20a7b26bb6676e6a395294)
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