1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/*
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2013 Apple Inc. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * modification, are permitted provided that the following conditions
6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * are met:
7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#ifndef WTF_EnumClass_h
27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define WTF_EnumClass_h
28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
29591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/Compiler.h"
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
31926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)namespace WTF {
32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
33926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// How to define a type safe enum list using the ENUM_CLASS macros?
34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// ===============================================================
35926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// To get an enum list like this:
36926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     enum class MyEnums {
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         Value1,
39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         Value2,
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         ...
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         ValueN
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     };
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
44926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// ... write this:
45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     ENUM_CLASS(MyEnums) {
47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         Value1,
48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         Value2,
49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         ...
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         ValueN
51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     } ENUM_CLASS_END(MyEnums);
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The ENUM_CLASS macros will use C++11's enum class if the compiler supports it.
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Otherwise, it will use the EnumClass template below.
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#if COMPILER_SUPPORTS(CXX_STRONG_ENUMS)
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define ENUM_CLASS(__enumName) \
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    enum class __enumName
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define ENUM_CLASS_END(__enumName)
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#else // !COMPILER_SUPPORTS(CXX_STRONG_ENUMS)
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// How to define a type safe enum list using the EnumClass template?
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// ================================================================
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Definition should be a struct that encapsulates an enum list.
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// The enum list should be names Enums.
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Here's an example of how to define a type safe enum named MyEnum using
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// the EnumClass template:
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     struct MyEnumDefinition {
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         enum Enums {
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//             ValueDefault,
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//             Value1,
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//             ...
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//             ValueN
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//         };
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     };
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     typedef EnumClass<MyEnumDefinition, MyEnumDefinition::ValueDefault> MyEnum;
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// With that, you can now use MyEnum enum values as follow:
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     MyEnum value1; // value1 is assigned MyEnum::ValueDefault by default.
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)//     MyEnum value2 = MyEnum::Value1; // value2 is assigned MyEnum::Value1;
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <typename Definition>
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class EnumClass : public Definition {
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    typedef enum Definition::Enums Value;
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)public:
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE EnumClass() { }
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE EnumClass(Value value) : m_value(value) { }
94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE Value value() const { return m_value; }
96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator==(const EnumClass other) { return m_value == other.m_value; }
98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator!=(const EnumClass other) { return m_value != other.m_value; }
99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator<(const EnumClass other) { return m_value < other.m_value; }
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator<=(const EnumClass other) { return m_value <= other.m_value; }
101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator>(const EnumClass other) { return m_value > other.m_value; }
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator>=(const EnumClass other) { return m_value >= other.m_value; }
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator==(const Value value) { return m_value == value; }
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator!=(const Value value) { return m_value != value; }
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator<(const Value value) { return m_value < value; }
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator<=(const Value value) { return m_value <= value; }
108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator>(const Value value) { return m_value > value; }
109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE bool operator>=(const Value value) { return m_value >= value; }
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ALWAYS_INLINE operator Value() { return m_value; }
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)private:
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Value m_value;
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define ENUM_CLASS(__enumName) \
118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    struct __enumName ## Definition { \
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        enum Enums
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define ENUM_CLASS_END(__enumName) \
122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ; \
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }; \
124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    typedef EnumClass< __enumName ## Definition > __enumName
125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#endif // !COMPILER_SUPPORTS(CXX_STRONG_ENUMS)
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} // namespace WTF
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#if !COMPILER_SUPPORTS(CXX_STRONG_ENUMS)
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)using WTF::EnumClass;
132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#endif
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#endif // WTF_EnumClass_h
135