Loading...
Searching...
No Matches
token.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#ifndef PXR_BASE_TF_TOKEN_H
25#define PXR_BASE_TF_TOKEN_H
26
31
32#include "pxr/pxr.h"
33
34#include "pxr/base/tf/api.h"
36#include "pxr/base/tf/hash.h"
37#include "pxr/base/tf/hashset.h"
38#include "pxr/base/tf/pointerAndBits.h"
39
40#include <atomic>
41#include <iosfwd>
42#include <string>
43#include <vector>
44#include <set>
45
46PXR_NAMESPACE_OPEN_SCOPE
47
49
88{
89public:
90 enum _ImmortalTag { Immortal };
91
93 constexpr TfToken() noexcept = default;
94
96 TfToken(TfToken const& rhs) noexcept : _rep(rhs._rep) { _AddRef(); }
97
99 TfToken(TfToken && rhs) noexcept : _rep(rhs._rep) {
100 rhs._rep = TfPointerAndBits<const _Rep>();
101 }
102
104 TfToken& operator= (TfToken const& rhs) noexcept {
105 if (&rhs != this) {
106 rhs._AddRef();
107 _RemoveRef();
108 _rep = rhs._rep;
109 }
110 return *this;
111 }
112
114 TfToken& operator= (TfToken && rhs) noexcept {
115 if (&rhs != this) {
116 _RemoveRef();
117 _rep = rhs._rep;
118 rhs._rep = TfPointerAndBits<const _Rep>();
119 }
120 return *this;
121 }
122
124 ~TfToken() { _RemoveRef(); }
125
127 //
128 // This constructor involves a string hash and a lookup in the global
129 // table, and so should not be done more often than necessary. When
130 // possible, create a token once and reuse it many times.
131 TF_API explicit TfToken(std::string const& s);
133 // Create a token for \p s, and make it immortal. If \p s exists in the
134 // token table already and is not immortal, make it immortal. Immortal
135 // tokens are faster to copy than mortal tokens, but they will never expire
136 // and release their memory.
137 TF_API TfToken(std::string const& s, _ImmortalTag);
138
140 //
141 // This constructor involves a string hash and a lookup in the global
142 // table, and so should not be done more often than necessary. When
143 // possible, create a token once and reuse it many times.
144 TF_API explicit TfToken(char const* s);
146 // Create a token for \p s, and make it immortal. If \p s exists in the
147 // token table already and is not immortal, make it immortal. Immortal
148 // tokens are faster to copy than mortal tokens, but they will never expire
149 // and release their memory.
150 TF_API TfToken(char const* s, _ImmortalTag);
151
153 //
154 // If a token has previous been created for the given string, this
155 // will return it. Otherwise, the empty token will be returned.
156 TF_API static TfToken Find(std::string const& s);
157
159 //
160 // The hash is based on the token's storage identity; this is immutable
161 // as long as the token is in use anywhere in the process.
162 //
163 inline size_t Hash() const;
164
166 struct HashFunctor {
167 size_t operator()(TfToken const& token) const { return token.Hash(); }
168 };
169
175 typedef TfHashSet<TfToken, TfToken::HashFunctor> HashSet;
176
183 typedef std::set<TfToken, TfTokenFastArbitraryLessThan> Set;
184
186 size_t size() const {
187 _Rep const *rep = _rep.Get();
188 return rep ? rep->_str.size() : 0;
189 }
190
196 char const* GetText() const {
197 _Rep const *rep = _rep.Get();
198 return rep ? rep->_str.c_str() : "";
199 }
200
202 char const *data() const {
203 return GetText();
204 }
205
207 std::string const& GetString() const {
208 _Rep const *rep = _rep.Get();
209 return rep ? rep->_str : _GetEmptyString();
210 }
211
213 inline void Swap(TfToken &other) {
214 std::swap(_rep, other._rep);
215 }
216
218 bool operator==(TfToken const& o) const {
219 // Equal if pointers & bits are equal, or if just pointers are.
220 return _rep.Get() == o._rep.Get();
221 }
222
224 bool operator!=(TfToken const& o) const {
225 return !(*this == o);
226 }
227
230 TF_API bool operator==(std::string const& o) const;
231
234 TF_API bool operator==(const char *) const;
235
237 friend bool operator==(std::string const& o, TfToken const& t) {
238 return t == o;
239 }
240
242 friend bool operator==(const char *o, TfToken const& t) {
243 return t == o;
244 }
245
248 bool operator!=(std::string const& o) const {
249 return !(*this == o);
250 }
251
253 friend bool operator!=(std::string const& o, TfToken const& t) {
254 return !(t == o);
255 }
256
259 bool operator!=(char const* o) const {
260 return !(*this == o);
261 }
262
264 friend bool operator!=(char const* o, TfToken const& t) {
265 return !(t == o);
266 }
267
270 inline bool operator<(TfToken const& r) const {
271 auto ll = _rep.GetLiteral(), rl = r._rep.GetLiteral();
272 if (!ll || !rl) {
273 // One or both are zero -- return true if ll is zero and rl is not.
274 return !ll && rl;
275 }
276 if (ll == rl) {
277 return false;
278 }
279 auto lrep = _rep.Get(), rrep = r._rep.Get();
280 uint64_t lcc = lrep->_compareCode, rcc = rrep->_compareCode;
281 return lcc < rcc || (lcc == rcc && lrep->_str < rrep->_str);
282 }
283
285 inline bool operator>(TfToken const& o) const {
286 return o < *this;
287 }
288
291 inline bool operator>=(TfToken const& o) const {
292 return !(*this < o);
293 }
294
297 inline bool operator<=(TfToken const& o) const {
298 return !(*this > o);
299 }
300
302 operator std::string const& () const { return GetString(); }
303
305 bool IsEmpty() const { return _rep.GetLiteral() == 0; }
306
311 bool IsImmortal() const {
312 if (!_rep.BitsAs<bool>()) {
313 return true;
314 }
315 // There is no synchronization or ordering constraints between this read
316 // and other reads/writes, so relaxed memory order suffices.
317 bool immortal = !(_rep->_refCount.load(std::memory_order_relaxed) & 1);
318 if (immortal) {
319 // Our belief is wrong, update our cache of countedness.
320 _rep.SetBits(false);
321 }
322 return immortal;
323 }
324
326 friend TF_API std::ostream &operator <<(std::ostream &stream, TfToken const&);
327
329 template <class HashState>
330 friend void
331 TfHashAppend(HashState &h, TfToken const &token) {
332 h.Append(token._rep.Get());
333 }
334
335private:
336 // Add global swap overload.
337 friend void swap(TfToken &lhs, TfToken &rhs) {
338 lhs.Swap(rhs);
339 }
340
341 void _AddRef() const {
342 if (!_rep.BitsAs<bool>()) {
343 // Not counted, do nothing.
344 return;
345 }
346 // We believe this rep is refCounted.
347 if (!_rep->IncrementAndCheckCounted()) {
348 // Our belief is wrong, update our cache of countedness.
349 _rep.SetBits(false);
350 }
351 }
352
353 void _RemoveRef() const {
354 if (!_rep.BitsAs<bool>()) {
355 // Not counted, do nothing.
356 return;
357 }
358 // Decrement the refcount.
359 _rep->Decrement();
360 }
361
362 struct _Rep {
363 _Rep() = default;
364
365 explicit _Rep(std::string &&str,
366 unsigned setNum,
367 uint64_t compareCode)
368 : _setNum(setNum)
369 , _compareCode(compareCode)
370 , _str(std::move(str))
371 , _cstr(_str.c_str()) {}
372
373 explicit _Rep(std::string const &str,
374 unsigned setNum,
375 uint64_t compareCode)
376 : _Rep(std::string(str), setNum, compareCode) {}
377
378 explicit _Rep(char const *str,
379 unsigned setNum,
380 uint64_t compareCode)
381 : _Rep(std::string(str), setNum, compareCode) {}
382
383 // Make sure we reacquire _cstr from _str on copy and assignment
384 // to avoid holding on to a dangling pointer. However, if rhs'
385 // _cstr member doesn't come from its _str, just copy it directly
386 // over. This is to support lightweight _Rep objects used for
387 // internal lookups.
388 _Rep(_Rep const &rhs)
389 : _refCount(rhs._refCount.load(std::memory_order_relaxed))
390 , _setNum(rhs._setNum)
391 , _compareCode(rhs._compareCode)
392 , _str(rhs._str)
393 , _cstr(rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr) {}
394
395 _Rep &operator=(_Rep const &rhs) {
396 _refCount = rhs._refCount.load(std::memory_order_relaxed);
397 _setNum = rhs._setNum;
398 _compareCode = rhs._compareCode;
399 _str = rhs._str;
400 _cstr = (rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr);
401 return *this;
402 }
403
404 inline bool IncrementAndCheckCounted() const {
405 // Refcounts are manipulated by add/sub 2, since the lowest-order
406 // bit indicates whether or not the rep is counted.
407 return _refCount.fetch_add(2, std::memory_order_relaxed) & 1;
408 }
409
410 inline void Decrement() const {
411 // Refcounts are manipulated by add/sub 2, since the lowest-order
412 // bit indicates whether or not the rep is counted.
413 _refCount.fetch_sub(2, std::memory_order_release);
414 }
415
416 mutable std::atomic_uint _refCount;
417 unsigned _setNum;
418 uint64_t _compareCode;
419 std::string _str;
420 char const *_cstr;
421 };
422
423 friend struct TfTokenFastArbitraryLessThan;
424 friend struct Tf_TokenRegistry;
425
426 TF_API static std::string const& _GetEmptyString();
427
428 mutable TfPointerAndBits<const _Rep> _rep;
429};
430
431inline size_t
433{
434 return TfHash()(*this);
435}
436
440 inline bool operator()(TfToken const &lhs, TfToken const &rhs) const {
441 return lhs._rep.Get() < rhs._rep.Get();
442 }
443};
444
446TF_API std::vector<TfToken>
447TfToTokenVector(const std::vector<std::string> &sv);
448
450TF_API std::vector<std::string>
451TfToStringVector(const std::vector<TfToken> &tv);
452
454inline size_t hash_value(const TfToken& x) { return x.Hash(); }
455
457typedef std::vector<TfToken> TfTokenVector;
458
459PXR_NAMESPACE_CLOSE_SCOPE
460
461#endif // PXR_BASE_TF_TOKEN_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:477
This class stores a T * and a small integer in the space of a T *.
void SetBits(Integral val) noexcept
Set the stored bits. No static range checking is performed.
constexpr uintptr_t GetLiteral() const noexcept
Retrieve the raw underlying value.
constexpr T * Get() const noexcept
Retrieve the pointer.
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:88
static TF_API TfToken Find(std::string const &s)
Find the token for the given string, if one exists.
friend bool operator!=(char const *o, TfToken const &t)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: token.h:264
std::set< TfToken, TfTokenFastArbitraryLessThan > Set
Predefined type for set of tokens, for when faster lookup is desired, without paying the memory or in...
Definition: token.h:183
TfToken(TfToken &&rhs) noexcept
Move constructor.
Definition: token.h:99
size_t size() const
Return the size of the string that this token represents.
Definition: token.h:186
TF_API TfToken(std::string const &s, _ImmortalTag)
This is an overloaded member function, provided for convenience. It differs from the above function o...
char const * data() const
Synonym for GetText().
Definition: token.h:202
bool operator!=(char const *o) const
Inequality operator for char strings.
Definition: token.h:259
bool operator<=(TfToken const &o) const
Less-than-or-equal operator that compares tokenized strings lexicographically.
Definition: token.h:297
TfHashSet< TfToken, TfToken::HashFunctor > HashSet
Predefined type for TfHashSet of tokens, since it's so awkward to manually specify.
Definition: token.h:175
bool operator>(TfToken const &o) const
Greater-than operator that compares tokenized strings lexicographically.
Definition: token.h:285
friend bool operator!=(std::string const &o, TfToken const &t)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: token.h:253
TF_API TfToken(char const *s, _ImmortalTag)
This is an overloaded member function, provided for convenience. It differs from the above function o...
friend bool operator==(const char *o, TfToken const &t)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: token.h:242
TfToken & operator=(TfToken const &rhs) noexcept
Copy assignment.
Definition: token.h:104
bool operator!=(TfToken const &o) const
Equality operator.
Definition: token.h:224
char const * GetText() const
Return the text that this token represents.
Definition: token.h:196
friend TF_API std::ostream & operator<<(std::ostream &stream, TfToken const &)
Stream insertion.
void Swap(TfToken &other)
Swap this token with another.
Definition: token.h:213
TF_API bool operator==(std::string const &o) const
Equality operator for char strings.
bool operator==(TfToken const &o) const
Equality operator.
Definition: token.h:218
friend bool operator==(std::string const &o, TfToken const &t)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: token.h:237
bool IsEmpty() const
Returns true iff this token contains the empty string "".
Definition: token.h:305
TF_API TfToken(std::string const &s)
Acquire a token for the given string.
std::string const & GetString() const
Return the string that this token represents.
Definition: token.h:207
TF_API bool operator==(const char *) const
Equality operator for char strings.
TF_API TfToken(char const *s)
Acquire a token for the given string.
bool operator>=(TfToken const &o) const
Greater-than-or-equal operator that compares tokenized strings lexicographically.
Definition: token.h:291
constexpr TfToken() noexcept=default
Create the empty token, containing the empty string.
bool operator<(TfToken const &r) const
Less-than operator that compares tokenized strings lexicographically.
Definition: token.h:270
~TfToken()
Destructor.
Definition: token.h:124
size_t Hash() const
Return a size_t hash for this token.
Definition: token.h:432
bool IsImmortal() const
Returns true iff this is an immortal token.
Definition: token.h:311
friend void TfHashAppend(HashState &h, TfToken const &token)
TfHash support.
Definition: token.h:331
bool operator!=(std::string const &o) const
Inequality operator for string's.
Definition: token.h:248
Stripped down version of diagnostic.h that doesn't define std::string.
STL namespace.
Functor to use for hash maps from tokens to other things.
Definition: token.h:166
Fast but non-lexicographical (in fact, arbitrary) less-than comparison for TfTokens.
Definition: token.h:439
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
Definition: token.h:454
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:457
TF_API std::vector< std::string > TfToStringVector(const std::vector< TfToken > &tv)
Convert the vector of TfToken tv into a vector of strings.
TF_API std::vector< TfToken > TfToTokenVector(const std::vector< std::string > &sv)
Convert the vector of strings sv into a vector of TfToken.