//===--- FlagSet.h - Helper class for opaque flag types ---------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the FlagSet template, a class which makes it easier to // define opaque flag types. // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_FLAGSET_H #define SWIFT_BASIC_FLAGSET_H #include #include namespace swift { /// A template designed to simplify the task of defining a wrapper type /// for a flags bitfield. /// /// Unfortunately, this doesn't currently support functional-style /// building patterns, which means this can't practically be used for /// types that need to be used in constant expressions. template class FlagSet { static_assert(std::is_integral::value, "storage type for FlagSet must be an integral type"); IntType Bits; protected: template static constexpr IntType lowMaskFor() { return IntType((1 << BitWidth) - 1); } template static constexpr IntType maskFor() { return lowMaskFor() << FirstBit; } constexpr FlagSet(IntType bits = 0) : Bits(bits) {} /// Read a single-bit flag. template bool getFlag() const { return Bits & maskFor(); } /// Set a single-bit flag. template void setFlag(bool value) { if (value) { Bits |= maskFor(); } else { Bits &= ~maskFor(); } } /// Read a multi-bit field. template constexpr FieldType getField() const { return FieldType((Bits >> FirstBit) & lowMaskFor()); } /// Assign to a multi-bit field. template void setField(typename std::enable_if::type value) { // Note that we suppress template argument deduction for FieldType. assert(IntType(value) <= lowMaskFor() && "value out of range"); Bits = (Bits & ~maskFor()) | (IntType(value) << FirstBit); } // A convenient macro for defining a getter and setter for a flag. // Intended to be used in the body of a subclass of FlagSet. #define FLAGSET_DEFINE_FLAG_ACCESSORS(BIT, GETTER, SETTER) \ bool GETTER() const { \ return this->template getFlag(); \ } \ void SETTER(bool value) { \ this->template setFlag(value); \ } // A convenient macro for defining a getter and setter for a field. // Intended to be used in the body of a subclass of FlagSet. #define FLAGSET_DEFINE_FIELD_ACCESSORS(BIT, WIDTH, TYPE, GETTER, SETTER) \ constexpr TYPE GETTER() const { \ return this->template getField(); \ } \ void SETTER(TYPE value) { \ this->template setField(value); \ } // A convenient macro to expose equality operators. // These can't be provided directly by FlagSet because that would allow // different flag sets to be compared if they happen to have the same // underlying type. #define FLAGSET_DEFINE_EQUALITY(TYPENAME) \ friend bool operator==(TYPENAME lhs, TYPENAME rhs) { \ return lhs.getOpaqueValue() == rhs.getOpaqueValue(); \ } \ friend bool operator!=(TYPENAME lhs, TYPENAME rhs) { \ return lhs.getOpaqueValue() != rhs.getOpaqueValue(); \ } public: /// Get the bits as an opaque integer value. IntType getOpaqueValue() const { return Bits; } }; } // end namespace swift #endif