Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
enum_utils.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#if defined(__GNUC__) || defined(__clang__)
7# pragma GCC diagnostic push
8# pragma GCC diagnostic ignored "-Wshadow"
9#elifdef _MSC_VER
10# pragma warning(push)
11# pragma warning(disable : 4458) // declaration hides class member
12#endif
13
14#include <magic_enum.hpp>
15#include <magic_enum_format.hpp>
16
17#if defined(__GNUC__) || defined(__clang__)
18# pragma GCC diagnostic pop
19#elifdef _MSC_VER
20# pragma warning(pop)
21#endif
22
23#include "utils/utf8_string.h"
24
25#include <QObject>
26#include <QVariant>
27
28#include <fmt/format.h>
29
30using namespace magic_enum::bitwise_operators;
31
32#define ENUM_INT_TO_VALUE_CONST(_enum, _int) \
33 (magic_enum::enum_value<_enum, _int> ())
34#define ENUM_INT_TO_VALUE(_enum, _int) (magic_enum::enum_value<_enum> (_int))
35#define ENUM_VALUE_TO_INT(_val) (magic_enum::enum_integer (_val))
36
37#define ENUM_ENABLE_BITSET(_enum) \
38 template <> struct magic_enum::customize::enum_range<_enum> \
39 { \
40 static constexpr bool is_flags = true; \
41 }
42#define ENUM_BITSET(_enum, _val) (magic_enum::containers::bitset<_enum> (_val))
43#define ENUM_BITSET_TEST(_val, _other_val) \
44 /* (ENUM_BITSET (_enum, _val).test (_other_val)) */ \
45 (static_cast<std::underlying_type_t<decltype (_val)>> (_val) \
46 & static_cast<std::underlying_type_t<decltype (_val)>> (_other_val))
47
50#define ENUM_BITSET_TO_STRING(_enum, _val) \
51 (ENUM_BITSET (_enum, _val).to_string ().data ())
52
53#define ENUM_COUNT(_enum) (magic_enum::enum_count<_enum> ())
54#define ENUM_NAME(_val) (magic_enum::enum_name (_val).data ())
55#define ENUM_NAME_FROM_INT(_enum, _int) \
56 ENUM_NAME (ENUM_INT_TO_VALUE (_enum, _int))
57
58#define VA_ARGS_SIZE(...) \
59 std::tuple_size<decltype (std::make_tuple (__VA_ARGS__))>::value
60
61#define DEFINE_ENUM_FORMATTER(enum_type, enum_name, ...) \
62 namespace fmt \
63 { \
64 template <> struct formatter<enum_type> \
65 { \
66 bool translate_ = false; \
67 template <typename ParseContext> constexpr auto parse (ParseContext &ctx) \
68 { \
69 auto it = ctx.begin (); \
70 translate_ = (it != ctx.end () && *it == 't'); \
71 return it + translate_; \
72 } \
73\
74 template <typename FormatContext> \
75 auto format (const enum_type &val, FormatContext &ctx) const \
76 { \
77 static constexpr std::array<const char *, VA_ARGS_SIZE (__VA_ARGS__)> \
78 enum_strings = { __VA_ARGS__ }; \
79 const auto idx = magic_enum::enum_index (val); \
80 const char * str = idx.has_value () ? enum_strings.at (*idx) : "unknown"; \
81 return format_to ( \
82 ctx.out (), FMT_STRING ("{}"), \
83 translate_ \
84 ? zrythm::utils::Utf8String::from_qstring (QObject::tr (str)).c_str () \
85 : str); \
86 } \
87 }; \
88 } \
89\
90 inline const char * const * enum_name##_get_strings () \
91 { \
92 static constexpr std::array<const char *, VA_ARGS_SIZE (__VA_ARGS__)> \
93 enum_strings = { __VA_ARGS__ }; \
94 return enum_strings.data (); \
95 } \
96\
97 inline zrythm::utils::Utf8String \
98 enum_name##_to_string (enum_type val, bool translate = false) \
99 { \
100 if (translate) \
101 { \
102 return zrythm::utils::Utf8String::from_utf8_encoded_string ( \
103 fmt::format ("{:t}", val)); \
104 } \
105 return zrythm::utils::Utf8String::from_utf8_encoded_string ( \
106 fmt::format ("{}", val)); \
107 } \
108\
109 inline enum_type enum_name##_from_string ( \
110 const zrythm::utils::Utf8String &str, bool translate = false) \
111 { \
112 for (size_t i = 0; i < VA_ARGS_SIZE (__VA_ARGS__); ++i) \
113 { \
114 const auto eval = magic_enum::enum_value<enum_type> (i); \
115 if (str == enum_name##_to_string (eval, translate)) \
116 { \
117 return eval; \
118 } \
119 } \
120 throw std::runtime_error ( \
121 fmt::format ("Enum value from '{}' not found", str)); \
122 return static_cast<enum_type> (0); \
123 } \
124\
125 inline constexpr size_t enum_name##_count () \
126 { \
127 return VA_ARGS_SIZE (__VA_ARGS__); \
128 } \
129\
130 inline QVariantList enum_name##_to_qml_list () \
131 { \
132 static constexpr std::array<const char *, VA_ARGS_SIZE (__VA_ARGS__)> \
133 enum_strings = { __VA_ARGS__ }; \
134 QVariantList list; \
135 for (size_t i = 0; i < enum_strings.size (); ++i) \
136 { \
137 QVariantMap entry; \
138 entry[QStringLiteral ("display")] = QObject::tr (enum_strings[i]); \
139 entry[QStringLiteral ("name")] = QString::fromUtf8 (enum_strings[i]); \
140 entry[QStringLiteral ("value")] = \
141 static_cast<int> (magic_enum::enum_value<enum_type> (i)); \
142 list.append (entry); \
143 } \
144 return list; \
145 }