|
| 1 | +/* |
| 2 | + * Copyright (c) Facebook, Inc. and its affiliates. |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +#pragma once |
| 17 | + |
| 18 | +#include "folly/container/F14Map.h" |
| 19 | +#include "velox/common/base/Exceptions.h" |
| 20 | + |
| 21 | +namespace facebook::velox { |
| 22 | + |
| 23 | +struct Enums { |
| 24 | + /// Helper function to invert a mapping from enum type to name. |
| 25 | + template <typename E> |
| 26 | + static folly::F14FastMap<std::string, E> invertMap( |
| 27 | + const folly::F14FastMap<E, std::string>& mapping) { |
| 28 | + folly::F14FastMap<std::string, E> inverted; |
| 29 | + for (const auto& [key, value] : mapping) { |
| 30 | + bool ok = inverted.emplace(value, key).second; |
| 31 | + VELOX_USER_CHECK( |
| 32 | + ok, "Cannot invert a map with duplicate values: {}", value); |
| 33 | + } |
| 34 | + return inverted; |
| 35 | + } |
| 36 | +}; |
| 37 | + |
| 38 | +} // namespace facebook::velox |
| 39 | + |
| 40 | +/// Helper macros to implement bi-direction mappings between enum values and |
| 41 | +/// names. |
| 42 | +/// |
| 43 | +/// Usage: |
| 44 | +/// |
| 45 | +/// In the header file, define the enum: |
| 46 | +/// |
| 47 | +/// #include "velox/common/Enums.h" |
| 48 | +/// |
| 49 | +/// enum class Foo {...}; |
| 50 | +/// |
| 51 | +/// VELOX_DEFINE_ENUM_NAME(Foo); |
| 52 | +/// |
| 53 | +/// In the cpp file, define the mapping: |
| 54 | +/// |
| 55 | +/// namespace { |
| 56 | +/// folly::F14FastMap<Foo, std::string> fooNames() { |
| 57 | +/// return { |
| 58 | +/// {Foo::kFirst, "FIRST"}, |
| 59 | +/// {Foo::kSecond, "SECOND"}, |
| 60 | +/// ... |
| 61 | +/// }; |
| 62 | +/// } |
| 63 | +/// } // namespace |
| 64 | +/// |
| 65 | +/// VELOX_DECLARE_ENUM_NAME(Foo, fooNames); |
| 66 | +/// |
| 67 | +/// In the client code, use FooName::toName(Foo::kFirst) to get the name of the |
| 68 | +/// enum and FooName::toFoo("FIRST") to get the enum value. |
| 69 | +/// |
| 70 | +/// Use _EMBEDDED_ versions of the macros to define enums embedded in other |
| 71 | +/// classes. |
| 72 | + |
| 73 | +#define VELOX_DECLARE_ENUM_NAME(EnumType) \ |
| 74 | + struct EnumType##Name { \ |
| 75 | + static std::string_view toName(EnumType value); \ |
| 76 | + static EnumType to##EnumType(std::string_view name); \ |
| 77 | + }; |
| 78 | + |
| 79 | +#define VELOX_DEFINE_ENUM_NAME(EnumType, Names) \ |
| 80 | + std::string_view EnumType##Name::toName(EnumType value) { \ |
| 81 | + static const auto kNames = Names(); \ |
| 82 | + auto it = kNames.find(value); \ |
| 83 | + VELOX_CHECK( \ |
| 84 | + it != kNames.end(), \ |
| 85 | + "Invalid enum value: {}", \ |
| 86 | + static_cast<int>(value)); \ |
| 87 | + return it->second.c_str(); \ |
| 88 | + } \ |
| 89 | + \ |
| 90 | + EnumType EnumType##Name::to##EnumType(std::string_view name) { \ |
| 91 | + static const auto kValues = facebook::velox::Enums::invertMap(Names()); \ |
| 92 | + \ |
| 93 | + auto it = kValues.find(name); \ |
| 94 | + VELOX_CHECK(it != kValues.end(), "Invalid enum name: {}", name); \ |
| 95 | + return it->second; \ |
| 96 | + } |
| 97 | + |
| 98 | +#define VELOX_DECLARE_EMBEDDED_ENUM_NAME(EnumType) \ |
| 99 | + static std::string_view toName(EnumType value); \ |
| 100 | + static EnumType to##EnumType(std::string_view name); |
| 101 | + |
| 102 | +#define VELOX_DEFINE_EMBEDDED_ENUM_NAME(Class, EnumType, Names) \ |
| 103 | + std::string_view Class::toName(Class::EnumType value) { \ |
| 104 | + static const auto kNames = Names(); \ |
| 105 | + auto it = kNames.find(value); \ |
| 106 | + VELOX_CHECK( \ |
| 107 | + it != kNames.end(), \ |
| 108 | + "Invalid enum value: {}", \ |
| 109 | + static_cast<int>(value)); \ |
| 110 | + return it->second.c_str(); \ |
| 111 | + } \ |
| 112 | + \ |
| 113 | + Class::EnumType Class::to##EnumType(std::string_view name) { \ |
| 114 | + static const auto kValues = facebook::velox::Enums::invertMap(Names()); \ |
| 115 | + \ |
| 116 | + auto it = kValues.find(name); \ |
| 117 | + VELOX_CHECK(it != kValues.end(), "Invalid enum name: {}", name); \ |
| 118 | + return it->second; \ |
| 119 | + } |
0 commit comments