tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

EnumTypeTraits.h (4694B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /* Type traits for enums. */
      7 
      8 #ifndef mozilla_EnumTypeTraits_h
      9 #define mozilla_EnumTypeTraits_h
     10 
     11 #include <cstddef>
     12 #include <type_traits>
     13 
     14 namespace mozilla {
     15 
     16 namespace detail {
     17 
     18 template <size_t EnumSize, bool EnumSigned, size_t StorageSize,
     19          bool StorageSigned>
     20 struct EnumFitsWithinHelper;
     21 
     22 // Signed enum, signed storage.
     23 template <size_t EnumSize, size_t StorageSize>
     24 struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
     25    : public std::integral_constant<bool, (EnumSize <= StorageSize)> {};
     26 
     27 // Signed enum, unsigned storage.
     28 template <size_t EnumSize, size_t StorageSize>
     29 struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
     30    : public std::integral_constant<bool, false> {};
     31 
     32 // Unsigned enum, signed storage.
     33 template <size_t EnumSize, size_t StorageSize>
     34 struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
     35    : public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)> {};
     36 
     37 // Unsigned enum, unsigned storage.
     38 template <size_t EnumSize, size_t StorageSize>
     39 struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
     40    : public std::integral_constant<bool, (EnumSize <= StorageSize)> {};
     41 
     42 }  // namespace detail
     43 
     44 /*
     45 * Type trait that determines whether the enum type T can fit within the
     46 * integral type Storage without data loss. This trait should be used with
     47 * caution with an enum type whose underlying type has not been explicitly
     48 * specified: for such enums, the C++ implementation is free to choose a type
     49 * no smaller than int whose range encompasses all possible values of the enum.
     50 * So for an enum with only small non-negative values, the underlying type may
     51 * be either int or unsigned int, depending on the whims of the implementation.
     52 */
     53 template <typename T, typename Storage>
     54 struct EnumTypeFitsWithin
     55    : public detail::EnumFitsWithinHelper<
     56          sizeof(T),
     57          std::is_signed<typename std::underlying_type<T>::type>::value,
     58          sizeof(Storage), std::is_signed<Storage>::value> {
     59  static_assert(std::is_enum<T>::value, "must provide an enum type");
     60  static_assert(std::is_integral<Storage>::value,
     61                "must provide an integral type");
     62 };
     63 
     64 /**
     65 * Get the underlying value of an enum, but typesafe.
     66 * TODO: Replace with std::to_underlying when available.
     67 *
     68 * example:
     69 *
     70 *   enum class Pet : int16_t {
     71 *     Cat,
     72 *     Dog,
     73 *     Fish
     74 *   };
     75 *   enum class Plant {
     76 *     Flower,
     77 *     Tree,
     78 *     Vine
     79 *   };
     80 *   UnderlyingValue(Pet::Fish) -> int16_t(2)
     81 *   UnderlyingValue(Plant::Tree) -> int(1)
     82 */
     83 template <typename T>
     84 inline constexpr auto UnderlyingValue(const T v) {
     85  static_assert(std::is_enum_v<T>);
     86  return static_cast<typename std::underlying_type<T>::type>(v);
     87 }
     88 
     89 /*
     90 * Specialize either MaxContiguousEnumValue or MaxEnumValue to provide the
     91 * highest enum member value for an enum class. Note that specializing
     92 * MaxContiguousEnumValue will make MaxEnumValue just take its value from the
     93 * MaxContiguousEnumValue specialization.
     94 *
     95 * Specialize MinContiguousEnumValue and MaxContiguousEnumValue to provide both
     96 * lowest and highest enum member values for an enum class with contiguous
     97 * values.
     98 *
     99 * Each specialization of these structs should define "static constexpr" member
    100 * variable named "value".
    101 *
    102 * example:
    103 *
    104 *   enum ExampleEnum
    105 *   {
    106 *     CAT = 0,
    107 *     DOG,
    108 *     HAMSTER
    109 *   };
    110 *
    111 *   template <>
    112 *   struct MaxEnumValue<ExampleEnum>
    113 *   {
    114 *     static constexpr ExampleEnumvalue = HAMSTER;
    115 *   };
    116 */
    117 
    118 template <typename T>
    119 struct MinContiguousEnumValue : std::integral_constant<T, T(0)> {};
    120 
    121 template <typename T>
    122 struct MaxContiguousEnumValue;
    123 
    124 template <typename T>
    125 struct MaxEnumValue : MaxContiguousEnumValue<T> {};
    126 
    127 // Provides the min and max values for a contiguous enum (requires at least
    128 // MaxContiguousEnumValue to be defined).
    129 template <typename T>
    130 struct ContiguousEnumValues {
    131  static constexpr auto min = MinContiguousEnumValue<T>::value;
    132  static constexpr auto max = MaxContiguousEnumValue<T>::value;
    133 };
    134 
    135 // Provides the total number of values for a contiguous enum (requires at least
    136 // MaxContiguousEnumValue to be defined).
    137 template <typename T>
    138 struct ContiguousEnumSize {
    139  static constexpr size_t value =
    140      UnderlyingValue(ContiguousEnumValues<T>::max) + 1 -
    141      UnderlyingValue(ContiguousEnumValues<T>::min);
    142 };
    143 
    144 }  // namespace mozilla
    145 
    146 #endif /* mozilla_EnumTypeTraits_h */