This document is for a version of USD that is under development. See this page for the current release.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
token.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_TOKEN_H
8#define PXR_BASE_TF_TOKEN_H
9
14
15#include "pxr/pxr.h"
16
17#include "pxr/base/tf/api.h"
19#include "pxr/base/tf/hash.h"
20#include "pxr/base/tf/hashset.h"
21#include "pxr/base/tf/pointerAndBits.h"
22
23#include <atomic>
24#include <iosfwd>
25#include <string>
26#include <vector>
27#include <set>
28
29PXR_NAMESPACE_OPEN_SCOPE
30
32
71{
72public:
73 enum _ImmortalTag { Immortal };
74
76 constexpr TfToken() noexcept = default;
77
79 TfToken(TfToken const& rhs) noexcept : _rep(rhs._rep) { _AddRef(); }
80
82 TfToken(TfToken && rhs) noexcept : _rep(rhs._rep) {
84 }
85
87 TfToken& operator= (TfToken const& rhs) noexcept {
88 if (&rhs != this) {
89 rhs._AddRef();
90 _RemoveRef();
91 _rep = rhs._rep;
92 }
93 return *this;
94 }
95
97 TfToken& operator= (TfToken && rhs) noexcept {
98 if (&rhs != this) {
99 _RemoveRef();
100 _rep = rhs._rep;
101 rhs._rep = TfPointerAndBits<const _Rep>();
102 }
103 return *this;
104 }
105
107 ~TfToken() { _RemoveRef(); }
108
110 //
111 // This constructor involves a string hash and a lookup in the global
112 // table, and so should not be done more often than necessary. When
113 // possible, create a token once and reuse it many times.
114 TF_API explicit TfToken(std::string const& s);
116 // Create a token for \p s, and make it immortal. If \p s exists in the
117 // token table already and is not immortal, make it immortal. Immortal
118 // tokens are faster to copy than mortal tokens, but they will never expire
119 // and release their memory.
120 TF_API TfToken(std::string const& s, _ImmortalTag);
121
123 //
124 // This constructor involves a string hash and a lookup in the global
125 // table, and so should not be done more often than necessary. When
126 // possible, create a token once and reuse it many times.
127 TF_API explicit TfToken(char const* s);
129 // Create a token for \p s, and make it immortal. If \p s exists in the
130 // token table already and is not immortal, make it immortal. Immortal
131 // tokens are faster to copy than mortal tokens, but they will never expire
132 // and release their memory.
133 TF_API TfToken(char const* s, _ImmortalTag);
134
136 //
137 // If a token has previous been created for the given string, this
138 // will return it. Otherwise, the empty token will be returned.
139 TF_API static TfToken Find(std::string const& s);
140
142 //
143 // The hash is based on the token's storage identity; this is immutable
144 // as long as the token is in use anywhere in the process.
145 //
146 inline size_t Hash() const;
147
149 struct HashFunctor {
150 size_t operator()(TfToken const& token) const { return token.Hash(); }
151 };
152
158 typedef TfHashSet<TfToken, TfToken::HashFunctor> HashSet;
159
166 typedef std::set<TfToken, TfTokenFastArbitraryLessThan> Set;
167
169 size_t size() const {
170 _Rep const *rep = _rep.Get();
171 return rep ? rep->_str.size() : 0;
172 }
173
179 char const* GetText() const {
180 _Rep const *rep = _rep.Get();
181 return rep ? rep->_str.c_str() : "";
182 }
183
185 char const *data() const {
186 return GetText();
187 }
188
190 std::string const& GetString() const {
191 _Rep const *rep = _rep.Get();
192 return rep ? rep->_str : _GetEmptyString();
193 }
194
196 inline void Swap(TfToken &other) {
197 std::swap(_rep, other._rep);
198 }
199
201 bool operator==(TfToken const& o) const {
202 // Equal if pointers & bits are equal, or if just pointers are.
203 return _rep.Get() == o._rep.Get();
204 }
205
207 bool operator!=(TfToken const& o) const {
208 return !(*this == o);
209 }
210
213 TF_API bool operator==(std::string const& o) const;
214
217 TF_API bool operator==(const char *) const;
218
220 friend bool operator==(std::string const& o, TfToken const& t) {
221 return t == o;
222 }
223
225 friend bool operator==(const char *o, TfToken const& t) {
226 return t == o;
227 }
228
231 bool operator!=(std::string const& o) const {
232 return !(*this == o);
233 }
234
236 friend bool operator!=(std::string const& o, TfToken const& t) {
237 return !(t == o);
238 }
239
242 bool operator!=(char const* o) const {
243 return !(*this == o);
244 }
245
247 friend bool operator!=(char const* o, TfToken const& t) {
248 return !(t == o);
249 }
250
253 inline bool operator<(TfToken const& r) const {
254 auto ll = _rep.GetLiteral(), rl = r._rep.GetLiteral();
255 if (!ll || !rl) {
256 // One or both are zero -- return true if ll is zero and rl is not.
257 return !ll && rl;
258 }
259 if (ll == rl) {
260 return false;
261 }
262 auto lrep = _rep.Get(), rrep = r._rep.Get();
263 uint64_t lcc = lrep->_compareCode, rcc = rrep->_compareCode;
264 return lcc < rcc || (lcc == rcc && lrep->_str < rrep->_str);
265 }
266
268 inline bool operator>(TfToken const& o) const {
269 return o < *this;
270 }
271
274 inline bool operator>=(TfToken const& o) const {
275 return !(*this < o);
276 }
277
280 inline bool operator<=(TfToken const& o) const {
281 return !(*this > o);
282 }
283
285 operator std::string const& () const { return GetString(); }
286
288 bool IsEmpty() const { return _rep.GetLiteral() == 0; }
289
294 bool IsImmortal() const {
295 if (!_rep.BitsAs<bool>()) {
296 return true;
297 }
298 // There is no synchronization or ordering constraints between this read
299 // and other reads/writes, so relaxed memory order suffices.
300 bool immortal = !(_rep->_refCount.load(std::memory_order_relaxed) & 1);
301 if (immortal) {
302 // Our belief is wrong, update our cache of countedness.
303 _rep.SetBits(false);
304 }
305 return immortal;
306 }
307
309 friend TF_API std::ostream &operator <<(std::ostream &stream, TfToken const&);
310
312 template <class HashState>
313 friend void
314 TfHashAppend(HashState &h, TfToken const &token) {
315 h.Append(token._rep.Get());
316 }
317
318private:
319 // Add global swap overload.
320 friend void swap(TfToken &lhs, TfToken &rhs) {
321 lhs.Swap(rhs);
322 }
323
324 void _AddRef() const {
325 if (!_rep.BitsAs<bool>()) {
326 // Not counted, do nothing.
327 return;
328 }
329 // We believe this rep is refCounted.
330 if (!_rep->IncrementAndCheckCounted()) {
331 // Our belief is wrong, update our cache of countedness.
332 _rep.SetBits(false);
333 }
334 }
335
336 void _RemoveRef() const {
337 if (!_rep.BitsAs<bool>()) {
338 // Not counted, do nothing.
339 return;
340 }
341 // Decrement the refcount.
342 _rep->Decrement();
343 }
344
345 struct _Rep {
346 _Rep() = default;
347
348 explicit _Rep(std::string &&str,
349 unsigned setNum,
350 uint64_t compareCode)
351 : _setNum(setNum)
352 , _compareCode(compareCode)
353 , _str(std::move(str))
354 , _cstr(_str.c_str()) {}
355
356 explicit _Rep(std::string const &str,
357 unsigned setNum,
358 uint64_t compareCode)
359 : _Rep(std::string(str), setNum, compareCode) {}
360
361 explicit _Rep(char const *str,
362 unsigned setNum,
363 uint64_t compareCode)
364 : _Rep(std::string(str), setNum, compareCode) {}
365
366 // Make sure we reacquire _cstr from _str on copy and assignment
367 // to avoid holding on to a dangling pointer. However, if rhs'
368 // _cstr member doesn't come from its _str, just copy it directly
369 // over. This is to support lightweight _Rep objects used for
370 // internal lookups.
371 _Rep(_Rep const &rhs)
372 : _refCount(rhs._refCount.load(std::memory_order_relaxed))
373 , _setNum(rhs._setNum)
374 , _compareCode(rhs._compareCode)
375 , _str(rhs._str)
376 , _cstr(rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr) {}
377
378 _Rep &operator=(_Rep const &rhs) {
379 _refCount = rhs._refCount.load(std::memory_order_relaxed);
380 _setNum = rhs._setNum;
381 _compareCode = rhs._compareCode;
382 _str = rhs._str;
383 _cstr = (rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr);
384 return *this;
385 }
386
387 inline bool IncrementAndCheckCounted() const {
388 // Refcounts are manipulated by add/sub 2, since the lowest-order
389 // bit indicates whether or not the rep is counted.
390 return _refCount.fetch_add(2, std::memory_order_relaxed) & 1;
391 }
392
393 inline void Decrement() const {
394 // Refcounts are manipulated by add/sub 2, since the lowest-order
395 // bit indicates whether or not the rep is counted.
396 _refCount.fetch_sub(2, std::memory_order_release);
397 }
398
399 mutable std::atomic_uint _refCount;
400 unsigned _setNum;
401 uint64_t _compareCode;
402 std::string _str;
403 char const *_cstr;
404 };
405
406 friend struct TfTokenFastArbitraryLessThan;
407 friend struct Tf_TokenRegistry;
408
409 TF_API static std::string const& _GetEmptyString();
410
411 mutable TfPointerAndBits<const _Rep> _rep;
412};
413
414inline size_t
416{
417 return TfHash()(*this);
418}
419
423 inline bool operator()(TfToken const &lhs, TfToken const &rhs) const {
424 return lhs._rep.Get() < rhs._rep.Get();
425 }
426};
427
429TF_API std::vector<TfToken>
430TfToTokenVector(const std::vector<std::string> &sv);
431
433TF_API std::vector<std::string>
434TfToStringVector(const std::vector<TfToken> &tv);
435
437inline size_t hash_value(const TfToken& x) { return x.Hash(); }
438
440typedef std::vector<TfToken> TfTokenVector;
441
442PXR_NAMESPACE_CLOSE_SCOPE
443
444#endif // PXR_BASE_TF_TOKEN_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:472
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:71
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:247
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:166
TfToken(TfToken &&rhs) noexcept
Move constructor.
Definition: token.h:82
size_t size() const
Return the size of the string that this token represents.
Definition: token.h:169
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:185
bool operator!=(char const *o) const
Inequality operator for char strings.
Definition: token.h:242
bool operator<=(TfToken const &o) const
Less-than-or-equal operator that compares tokenized strings lexicographically.
Definition: token.h:280
TfHashSet< TfToken, TfToken::HashFunctor > HashSet
Predefined type for TfHashSet of tokens, since it's so awkward to manually specify.
Definition: token.h:158
bool operator>(TfToken const &o) const
Greater-than operator that compares tokenized strings lexicographically.
Definition: token.h:268
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:236
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:225
TfToken & operator=(TfToken const &rhs) noexcept
Copy assignment.
Definition: token.h:87
bool operator!=(TfToken const &o) const
Equality operator.
Definition: token.h:207
char const * GetText() const
Return the text that this token represents.
Definition: token.h:179
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:196
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:201
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:220
bool IsEmpty() const
Returns true iff this token contains the empty string "".
Definition: token.h:288
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:190
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:274
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:253
~TfToken()
Destructor.
Definition: token.h:107
size_t Hash() const
Return a size_t hash for this token.
Definition: token.h:415
bool IsImmortal() const
Returns true iff this is an immortal token.
Definition: token.h:294
friend void TfHashAppend(HashState &h, TfToken const &token)
TfHash support.
Definition: token.h:314
bool operator!=(std::string const &o) const
Inequality operator for string's.
Definition: token.h:231
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:149
Fast but non-lexicographical (in fact, arbitrary) less-than comparison for TfTokens.
Definition: token.h:422
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
Definition: token.h:437
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
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.