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:460
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.