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