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 TF_STATIC_TOKENS_H
31 #define TF_STATIC_TOKENS_H
32 
77 
78 #include "pxr/pxr.h"
79 #include "pxr/base/tf/preprocessorUtils.h"
80 #include "pxr/base/tf/staticData.h"
81 #include "pxr/base/tf/token.h"
82 
83 #include <vector>
84 
85 #include <boost/preprocessor/cat.hpp>
86 #include <boost/preprocessor/control/iif.hpp>
87 #include <boost/preprocessor/control/expr_iif.hpp>
88 #include <boost/preprocessor/logical/and.hpp>
89 #include <boost/preprocessor/logical/not.hpp>
90 #include <boost/preprocessor/punctuation/comma_if.hpp>
91 #include <boost/preprocessor/seq/filter.hpp>
92 #include <boost/preprocessor/seq/for_each.hpp>
93 #include <boost/preprocessor/seq/for_each_i.hpp>
94 #include <boost/preprocessor/seq/size.hpp>
95 #include <boost/preprocessor/seq/push_back.hpp>
96 #include <boost/preprocessor/stringize.hpp>
97 #include <boost/preprocessor/tuple/elem.hpp>
98 
99 PXR_NAMESPACE_OPEN_SCOPE
100 
101 // TF_DECLARE_PUBLIC_TOKENS use these macros to handle two or three arguments.
102 // The three argument version takes an export/import macro (e.g. TF_API)
103 // while the two argument version does not export the tokens.
104 
105 #define _TF_DECLARE_PUBLIC_TOKENS3(key, eiapi, seq) \
106  _TF_DECLARE_TOKENS3(key, seq, eiapi) \
107  extern eiapi TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
108 #define _TF_DECLARE_PUBLIC_TOKENS2(key, seq) \
109  _TF_DECLARE_TOKENS2(key, seq) \
110  extern TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
111 #define _TF_DECLARE_PUBLIC_TOKENS(N) _TF_DECLARE_PUBLIC_TOKENS##N
112 #define _TF_DECLARE_PUBLIC_TOKENS_EVAL(N) _TF_DECLARE_PUBLIC_TOKENS(N)
113 #define _TF_DECLARE_PUBLIC_TOKENS_EXPAND(x) x
114 
118 #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__) )
119 
123 #define TF_DEFINE_PUBLIC_TOKENS(key, seq) \
124  _TF_DEFINE_TOKENS(key, seq) \
125  TfStaticData<_TF_TOKENS_STRUCT_NAME(key)> key
126 
129 #define TF_DEFINE_PRIVATE_TOKENS(key, seq) \
130  namespace { \
131  struct _TF_TOKENS_STRUCT_NAME_PRIVATE(key) { \
132  _TF_TOKENS_STRUCT_NAME_PRIVATE(key)() : \
133  _TF_TOKENS_INITIALIZE_SEQ( \
134  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
135  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
136  { \
137  _TF_TOKENS_ASSIGN_ARRAY_SEQ( \
138  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
139  _TF_TOKENS_BUILD_ALLTOKENS_VECTOR( \
140  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
141  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
142  } \
143  _TF_TOKENS_DECLARE_MEMBERS(seq) \
144  }; \
145  } \
146  static TfStaticData<_TF_TOKENS_STRUCT_NAME_PRIVATE(key)> key
147 
149 // Private Macros
150 
151 // Private macro to generate struct name from key.
152 //
153 // Note that this needs to be a unique struct name for each translation unit.
154 //
155 #define _TF_TOKENS_STRUCT_NAME_PRIVATE(key) \
156  BOOST_PP_CAT(key, _PrivateStaticTokenType)
157 
158 // Private macro to generate struct name from key. This version is used
159 // by the public token declarations, and so key must be unique for the entire
160 // namespace.
161 //
162 #define _TF_TOKENS_STRUCT_NAME(key) \
163  BOOST_PP_CAT(key, _StaticTokenType)
164 
166 // Declaration Macros
167 
168 // Private macro used to generate TfToken member variables. elem can either
169 // be a tuple on the form (name, value) or just a name.
170 //
171 #define _TF_TOKENS_DECLARE_MEMBER(r, data, elem) \
172  TfToken BOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
173  BOOST_PP_TUPLE_ELEM(2, 0, elem), elem) \
174  BOOST_PP_EXPR_IIF(TF_PP_IS_TUPLE(BOOST_PP_TUPLE_ELEM(2, 1, elem)), \
175  [BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(1, 0, \
176  BOOST_PP_TUPLE_ELEM(2, 1, elem)))]);
177 
178 // Private macro used to declare the list of members as TfTokens
179 //
180 #define _TF_TOKENS_DECLARE_MEMBERS(seq) \
181  BOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_DECLARE_MEMBER, ~, \
182  seq _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
183  std::vector<TfToken> allTokens;
184 
185 // Private macro that expands all array elements to make them members
186 // of the sequence.
187 //
188 #define _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq) \
189  BOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_APPEND_ARRAY_ELEMENTS, \
190  ~, \
191  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
192 
193 // Private macro used to generate a struct of TfTokens.
194 //
195 #define _TF_DECLARE_TOKENS3(key, seq, eiapi) \
196  struct _TF_TOKENS_STRUCT_NAME(key) { \
197  eiapi _TF_TOKENS_STRUCT_NAME(key)(); \
198  eiapi ~_TF_TOKENS_STRUCT_NAME(key)(); \
199  _TF_TOKENS_DECLARE_MEMBERS(seq) \
200  };
201 
202 #define _TF_DECLARE_TOKENS2(key, seq) \
203  struct _TF_TOKENS_STRUCT_NAME(key) { \
204  _TF_TOKENS_STRUCT_NAME(key)(); \
205  ~_TF_TOKENS_STRUCT_NAME(key)(); \
206  _TF_TOKENS_DECLARE_MEMBERS(seq) \
207  };
208 
210 // Definition Macros
211 
212 // Private macros to define members in the tokens struct.
213 //
214 #define _TF_TOKENS_DEFINE_MEMBER(r, data, i, elem) \
215  BOOST_PP_COMMA_IF(i) \
216  BOOST_PP_TUPLE_ELEM(1, 0, BOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
217  (_TF_TOKENS_INITIALIZE_MEMBER_TUPLE(elem)), \
218  (_TF_TOKENS_INITIALIZE_MEMBER(elem))))
219 
220 #define _TF_TOKENS_INITIALIZE_MEMBER_TUPLE(elem) \
221  BOOST_PP_TUPLE_ELEM(2, 0, elem)(BOOST_PP_TUPLE_ELEM(2, 1, elem), \
222  TfToken::Immortal) \
223 
224 #define _TF_TOKENS_INITIALIZE_MEMBER(elem) \
225  elem(BOOST_PP_STRINGIZE(elem), TfToken::Immortal)
226 
227 #define _TF_TOKENS_DEFINE_ARRAY_MEMBER(r, data, i, elem) \
228  data[i] = BOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
229  BOOST_PP_TUPLE_ELEM(2, 0, elem), elem);
230 
231 // Private macros to append tokens to the allTokens vector.
232 //
233 #define _TF_TOKENS_APPEND_MEMBER(r, data, i, elem) \
234  BOOST_PP_IIF(TF_PP_IS_TUPLE(elem), \
235  _TF_TOKENS_APPEND_MEMBER_BODY(~, ~, \
236  BOOST_PP_TUPLE_ELEM(2, 0, elem)), \
237  _TF_TOKENS_APPEND_MEMBER_BODY(~, ~, elem))
238 
239 #define _TF_TOKENS_APPEND_MEMBER_BODY(r, data, elem) \
240  allTokens.push_back(elem);
241 
242 #define _TF_TOKENS_BUILD_ALLTOKENS_VECTOR(seq) \
243  BOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_APPEND_MEMBER, ~, seq)
244 
245 // Private macros to generate the list of initialized members.
246 //
247 #define _TF_TOKENS_INITIALIZE_SEQ(seq) \
248  BOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_DEFINE_MEMBER, ~, seq)
249 
250 #define _TF_TOKENS_ASSIGN_ARRAY_SEQ(seq) \
251  BOOST_PP_SEQ_FOR_EACH(_TF_TOKENS_DEFINE_ARRAY_MEMBERS, ~, seq)
252 
253 #define _TF_TOKENS_DEFINE_ARRAY_MEMBERS(r, data, elem) \
254  BOOST_PP_SEQ_FOR_EACH_I(_TF_TOKENS_DEFINE_ARRAY_MEMBER, \
255  BOOST_PP_TUPLE_ELEM(2, 0, elem), \
256  BOOST_PP_TUPLE_ELEM(1, 0, BOOST_PP_TUPLE_ELEM(2, 1, elem)))
257 
258 // Private predicate macros to be used by SEQ_FILTER that determine if an
259 // element of a sequence is an array of tokens or not.
260 //
261 #define _TF_TOKENS_IS_ARRAY(s, data, elem) \
262  BOOST_PP_AND(TF_PP_IS_TUPLE(elem), \
263  TF_PP_IS_TUPLE(BOOST_PP_TUPLE_ELEM(2, 1, elem)))
264 
265 #define _TF_TOKENS_IS_NOT_ARRAY(s, data, elem) \
266  BOOST_PP_NOT(_TF_TOKENS_IS_ARRAY(s, data, elem))
267 
268 // Private macro to append all array elements to a sequence.
269 //
270 #define _TF_TOKENS_APPEND_ARRAY_ELEMENTS(r, data, elem) \
271  BOOST_PP_TUPLE_ELEM(1, 0, BOOST_PP_TUPLE_ELEM(2, 1, elem))
272 
273 // Private macro to define the struct of tokens.
274 //
275 // This works by filtering the incoming seq in two ways. For the body of the
276 // constructor, only array tokens are passed through (because they can't be
277 // initialized via initializer lists). The initializer list's items are all
278 // non-array seq elements _plus_ all array members themshelves. This way,
279 // array tokens are also accessible without using [] which proved to be
280 // a neat shortcut.
281 //
282 #define _TF_DEFINE_TOKENS(key, seq) \
283  _TF_TOKENS_STRUCT_NAME(key)::~_TF_TOKENS_STRUCT_NAME(key)() = default; \
284  _TF_TOKENS_STRUCT_NAME(key)::_TF_TOKENS_STRUCT_NAME(key)() : \
285  _TF_TOKENS_INITIALIZE_SEQ( \
286  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
287  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
288  { \
289  _TF_TOKENS_ASSIGN_ARRAY_SEQ( \
290  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_ARRAY, ~, seq)) \
291  _TF_TOKENS_BUILD_ALLTOKENS_VECTOR( \
292  BOOST_PP_SEQ_FILTER(_TF_TOKENS_IS_NOT_ARRAY, ~, seq) \
293  _TF_TOKENS_EXPAND_ARRAY_ELEMENTS(seq)) \
294  }
295 
296 PXR_NAMESPACE_CLOSE_SCOPE
297 
298 #endif // TF_STATIC_TOKENS_H