1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkTypedEnum_DEFINED
9#define SkTypedEnum_DEFINED
10
11#include "SkPreprocessorSeq.h"
12
13//Compatibility with non-clang compilers.
14#ifndef __has_feature
15    #define __has_feature(x) 0
16#endif
17#ifndef __has_extension
18    #define __has_extension __has_feature
19#endif
20
21//Detect if typed enums are supported.
22#if defined(_MSC_VER) && _MSC_VER >= 1400
23    #define SK_TYPED_ENUMS
24
25#elif defined(__clang__) && __has_extension(cxx_strong_enums)
26    #define SK_TYPED_ENUMS
27
28// Scoped enums are buggy in GCC 4.4.0 through 4.5.1.
29// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38064
30// __cplusplus should actually be accurate now.
31// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
32#elif defined(__GNUC__) && (((__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ >= 40501) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || __cplusplus >= 201103L)
33    #define SK_TYPED_ENUMS
34#endif
35
36//Define what a typed enum looks like.
37#ifdef SK_TYPED_ENUMS
38
39    #define SK_TYPED_ENUM_VALUES(data, elem) \
40        SK_PAIR_FIRST(elem) = SK_PAIR_SECOND(elem),
41
42    #define SK_TYPED_ENUM_IDS(data, elem) \
43        elem,
44
45    #define SK_TYPED_ENUM_IDS_L(data, elem) \
46        elem
47
48    #define SK_TYPED_ENUM(enumName, enumType, enumSeq, idSeq) \
49        enum enumName : enumType { \
50            SK_SEQ_FOREACH(SK_TYPED_ENUM_VALUES, _, enumSeq) \
51        } SK_SEQ_FOREACH_L(SK_TYPED_ENUM_IDS, SK_TYPED_ENUM_IDS_L, _, idSeq);
52
53#else
54
55    #define SK_TYPED_ENUM_VALUES(enumType, elem) \
56        static const enumType SK_PAIR_FIRST(elem) = SK_PAIR_SECOND(elem);
57
58    #define SK_TYPED_ENUM_IDS(enumType, elem) \
59        enumType elem;
60
61    #define SK_TYPED_ENUM(enumName, enumType, enumSeq, idSeq) \
62        typedef enumType enumName; \
63        SK_SEQ_FOREACH(SK_TYPED_ENUM_VALUES, enumType, enumSeq) \
64        SK_SEQ_FOREACH(SK_TYPED_ENUM_IDS, enumType, idSeq)
65
66#endif
67
68#endif
69