HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
staticTokens.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 //todo: cleanup: TF_DEFINE_PRIVATE_TOKENS, should use the public versions
25 //todo: cleanup: document each macro extensivly
26 //todo: cleanup: order macros, so that it is easier to see the structure
27 //todo: simply syntax, we should get rid of braces for each array element and
28 // each element
29 
30 #ifndef PXR_BASE_TF_STATIC_TOKENS_H
31 #define PXR_BASE_TF_STATIC_TOKENS_H
32 
33 /// \file tf/staticTokens.h
34 ///
35 /// This file defines some macros that are useful for declaring and using
36 /// static TfTokens. Typically, using static TfTokens is either cumbersome,
37 /// unsafe, or slow. These macros aim to solve many of the common problems.
38 ///
39 /// The following is an example of how they can be used.
40 ///
41 /// In header file:
42 ///
43 /// \code
44 /// #define MF_TOKENS \. <--- please ignore '.'
45 /// (transform) \.
46 /// (moves) \.
47 ///
48 /// // Syntax when string name differs from symbol.
49 /// ((foo, "bar"))
50 ///
51 /// // Syntax when defining an array of tokens. Note that the tokens can
52 /// // be used either with amountTs[i] or directly as tx, ty, tz.
53 /// ((amountTs, ( (tx) (ty) (tz) )))
54 ///
55 /// TF_DECLARE_PUBLIC_TOKENS(MfTokens, MF_TOKENS);
56 /// \endcode
57 ///
58 /// In cpp file:
59 ///
60 /// \code
61 /// TF_DEFINE_PUBLIC_TOKENS(MfTokens, MF_TOKENS);
62 /// \endcode
63 ///
64 /// Access the token by using the key as though it were a pointer, like this:
65 ///
66 /// \code
67 /// MfTokens->transform;
68 /// \endcode
69 ///
70 /// An additional member, allTokens, is a std::vector<TfToken> populated
71 /// with all of the generated token members.
72 ///
73 /// There are PUBLIC and PRIVATE versions of the macros. The PRIVATE ones are
74 /// intended to be used when the tokens will only be used in a single .cpp
75 /// file, in which case they can be made file static. In the case of the
76 /// PRIVATE, you only need to use the DEFINE macro.
77 
78 #include "pxr/pxr.h"
81 #include "pxr/base/tf/staticData.h"
82 #include "pxr/base/tf/token.h"
83 
84 #include <vector>
85 
86 #include <hboost/preprocessor/cat.hpp>
87 #include <hboost/preprocessor/control/iif.hpp>
88 #include <hboost/preprocessor/control/expr_iif.hpp>
89 #include <hboost/preprocessor/logical/and.hpp>
90 #include <hboost/preprocessor/logical/not.hpp>
91 #include <hboost/preprocessor/punctuation/comma_if.hpp>
92 #include <hboost/preprocessor/seq/filter.hpp>
93 #include <hboost/preprocessor/seq/for_each.hpp>
94 #include <hboost/preprocessor/seq/for_each_i.hpp>
95 #include <hboost/preprocessor/seq/size.hpp>
96 #include <hboost/preprocessor/tuple/elem.hpp>
97 
99 
100 // TF_DECLARE_PUBLIC_TOKENS use these macros to handle two or three arguments.
101 // The three argument version takes an export/import macro (e.g. TF_API)
102 // while the two argument version does not export the tokens.
103 
104 #define _TF_DECLARE_PUBLIC_TOKENS3(key, eiapi, seq) \
105  _TF_DECLARE_TOKENS3(key, seq, eiapi) \
106  extern eiapi TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
107 #define _TF_DECLARE_PUBLIC_TOKENS2(key, seq) \
108  _TF_DECLARE_TOKENS2(key, seq) \
109  extern TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
110 #define _TF_DECLARE_PUBLIC_TOKENS(N) _TF_DECLARE_PUBLIC_TOKENS##N
111 #define _TF_DECLARE_PUBLIC_TOKENS_EVAL(N) _TF_DECLARE_PUBLIC_TOKENS(N)
112 #define _TF_DECLARE_PUBLIC_TOKENS_EXPAND(x) x
113 
114 /// Macro to define public tokens. This declares a list of tokens that can be
115 /// used globally. Use in conjunction with TF_DEFINE_PUBLIC_TOKENS.
116 /// \hideinitializer
117 #define TF_DECLARE_PUBLIC_TOKENS(...) _TF_DECLARE_PUBLIC_TOKENS_EXPAND( _TF_DECLARE_PUBLIC_TOKENS_EVAL(_TF_DECLARE_PUBLIC_TOKENS_EXPAND( TF_NUM_ARGS(__VA_ARGS__) ))(__VA_ARGS__) )
118 
119 /// Macro to define public tokens. Use in conjunction with
120 /// TF_DECLARE_PUBLIC_TOKENS.
121 /// \hideinitializer
122 #define TF_DEFINE_PUBLIC_TOKENS(key, seq) \
123  _TF_DEFINE_TOKENS(key, seq) \
124  TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
125 
126 /// Macro to define private tokens.
127 /// \hideinitializer
128 #define TF_DEFINE_PRIVATE_TOKENS(key, seq) \
129  namespace { \
130  struct _TF_TOKENS_STRUCT_NAME_PRIVATE(key) { \
131  _TF_TOKENS_STRUCT_NAME_PRIVATE(key)() : \
132  _TF_TOKENS_INITIALIZE_SEQ( \
133  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
134  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
135  { \
136  _TF_TOKENS_ASSIGN_ARRAY_SEQ( \
137  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
138  _TF_TOKENS_BUILD_ALLTOKENS_VECTOR( \
139  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
140  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
141  } \
142  _TF_TOKENS_DECLARE_MEMBERS(seq) \
143  }; \
144  } \
145  static TfStaticData<_TF_TOKENS_STRUCT_NAME_PRIVATE(key)> key
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 // Private Macros
149 
150 // Private macro to generate struct name from key.
151 //
152 // Note that this needs to be a unique struct name for each translation unit.
153 //
154 #define _TF_TOKENS_STRUCT_NAME_PRIVATE(key) \
155  HBOOST_PP_CAT(key, _PrivateStaticTokenType)
156 
157 // Private macro to generate struct name from key. This version is used
158 // by the public token declarations, and so key must be unique for the entire
159 // namespace.
160 //
161 #define _TF_TOKENS_STRUCT_NAME(key) \
162  HBOOST_PP_CAT(key, _StaticTokenType)
163 
164 ///////////////////////////////////////////////////////////////////////////////
165 // Declaration Macros
166 
167 // Private macro used to generate TfToken member variables. elem can either
168 // be a tuple on the form (name, value) or just a name.
169 //
170 #define _TF_TOKENS_DECLARE_MEMBER(r, data, elem) \
171  TfToken HBOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
172  HBOOST_PP_TUPLE_ELEM(2, 0, elem), elem) \
173  HBOOST_PP_EXPR_IIF(TF_PP_IS_TUPLE(HBOOST_PP_TUPLE_ELEM(2, 1, elem)), \
174  [HBOOST_PP_SEQ_SIZE(HBOOST_PP_TUPLE_ELEM(1, 0, \
175  HBOOST_PP_TUPLE_ELEM(2, 1, elem)))]);
176 
177 // Private macro used to declare the list of members as TfTokens
178 //
179 #define _TF_TOKENS_DECLARE_MEMBERS(seq) \
180  HBOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_DECLARE_MEMBER, ~, \
181  seq _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
182  std::vector<TfToken> allTokens;
183 
184 // Private macro that expands all array elements to make them members
185 // of the sequence.
186 //
187 #define _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq) \
188  HBOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_APPEND_ARRAY_ELEMENTS, \
189  ~, \
190  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
191 
192 // Private macro used to generate a struct of TfTokens.
193 //
194 #define _TF_DECLARE_TOKENS3(key, seq, eiapi) \
195  struct _TF_TOKENS_STRUCT_NAME(key) { \
196  eiapi _TF_TOKENS_STRUCT_NAME(key)(); \
197  eiapi ~_TF_TOKENS_STRUCT_NAME(key)(); \
198  _TF_TOKENS_DECLARE_MEMBERS(seq) \
199  };
200 
201 #define _TF_DECLARE_TOKENS2(key, seq) \
202  struct _TF_TOKENS_STRUCT_NAME(key) { \
203  _TF_TOKENS_STRUCT_NAME(key)(); \
204  ~_TF_TOKENS_STRUCT_NAME(key)(); \
205  _TF_TOKENS_DECLARE_MEMBERS(seq) \
206  };
207 
208 ///////////////////////////////////////////////////////////////////////////////
209 // Definition Macros
210 
211 // Private macros to define members in the tokens struct.
212 //
213 #define _TF_TOKENS_DEFINE_MEMBER(r, data, i, elem) \
214  HBOOST_PP_COMMA_IF(i) \
215  HBOOST_PP_TUPLE_ELEM(1, 0, HBOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
216  (_TF_TOKENS_INITIALIZE_MEMBER_TUPLE(elem)), \
217  (_TF_TOKENS_INITIALIZE_MEMBER(elem))))
218 
219 #define _TF_TOKENS_INITIALIZE_MEMBER_TUPLE(elem) \
220  HBOOST_PP_TUPLE_ELEM(2, 0, elem)(HBOOST_PP_TUPLE_ELEM(2, 1, elem), \
221  TfToken::Immortal) \
222 
223 #define _TF_TOKENS_INITIALIZE_MEMBER(elem) \
224  elem(TF_PP_STRINGIZE(elem), TfToken::Immortal)
225 
226 #define _TF_TOKENS_DEFINE_ARRAY_MEMBER(r, data, i, elem) \
227  data[i] = HBOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
228  HBOOST_PP_TUPLE_ELEM(2, 0, elem), elem);
229 
230 // Private macros to append tokens to the allTokens vector.
231 //
232 #define _TF_TOKENS_APPEND_MEMBER(r, data, i, elem) \
233  HBOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
234  _TF_TOKENS_APPEND_MEMBER_BODY(~, ~, \
235  HBOOST_PP_TUPLE_ELEM(2, 0, elem)), \
236  _TF_TOKENS_APPEND_MEMBER_BODY(~, ~, elem))
237 
238 #define _TF_TOKENS_APPEND_MEMBER_BODY(r, data, elem) \
239  allTokens.push_back(elem);
240 
241 #define _TF_TOKENS_BUILD_ALLTOKENS_VECTOR(seq) \
242  HBOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_APPEND_MEMBER, ~, seq)
243 
244 // Private macros to generate the list of initialized members.
245 //
246 #define _TF_TOKENS_INITIALIZE_SEQ(seq) \
247  HBOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_DEFINE_MEMBER, ~, seq)
248 
249 #define _TF_TOKENS_ASSIGN_ARRAY_SEQ(seq) \
250  HBOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_DEFINE_ARRAY_MEMBERS, ~, seq)
251 
252 #define _TF_TOKENS_DEFINE_ARRAY_MEMBERS(r, data, elem) \
253  HBOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_DEFINE_ARRAY_MEMBER, \
254  HBOOST_PP_TUPLE_ELEM(2, 0, elem), \
255  HBOOST_PP_TUPLE_ELEM(1, 0, HBOOST_PP_TUPLE_ELEM(2, 1, elem)))
256 
257 // Private predicate macros to be used by SEQ_FILTER that determine if an
258 // element of a sequence is an array of tokens or not.
259 //
260 #define _TF_TOKENS_IS_ARRAY(s, data, elem) \
261  HBOOST_PP_AND(TF_PP_IS_TUPLE(elem), \
262  TF_PP_IS_TUPLE(HBOOST_PP_TUPLE_ELEM(2, 1, elem)))
263 
264 #define _TF_TOKENS_IS_NOT_ARRAY(s, data, elem) \
265  HBOOST_PP_NOT(_TF_TOKENS_IS_ARRAY(s, data, elem))
266 
267 // Private macro to append all array elements to a sequence.
268 //
269 #define _TF_TOKENS_APPEND_ARRAY_ELEMENTS(r, data, elem) \
270  HBOOST_PP_TUPLE_ELEM(1, 0, HBOOST_PP_TUPLE_ELEM(2, 1, elem))
271 
272 // Private macro to define the struct of tokens.
273 //
274 // This works by filtering the incoming seq in two ways. For the body of the
275 // constructor, only array tokens are passed through (because they can't be
276 // initialized via initializer lists). The initializer list's items are all
277 // non-array seq elements _plus_ all array members themshelves. This way,
278 // array tokens are also accessible without using [] which proved to be
279 // a neat shortcut.
280 //
281 #define _TF_DEFINE_TOKENS(key, seq) \
282  _TF_TOKENS_STRUCT_NAME(key)::~_TF_TOKENS_STRUCT_NAME(key)() = default; \
283  _TF_TOKENS_STRUCT_NAME(key)::_TF_TOKENS_STRUCT_NAME(key)() : \
284  _TF_TOKENS_INITIALIZE_SEQ( \
285  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
286  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
287  { \
288  _TF_TOKENS_ASSIGN_ARRAY_SEQ( \
289  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
290  _TF_TOKENS_BUILD_ALLTOKENS_VECTOR( \
291  HBOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
292  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
293  }
294 
296 
297 #endif // PXR_BASE_TF_STATIC_TOKENS_H
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91