Loading...
Searching...
No Matches
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
81{
82public:
83 enum _ImmortalTag { Immortal };
84
86 constexpr TfToken() noexcept = default;
87
89 TfToken(TfToken const& rhs) noexcept : _rep(rhs._rep) { _AddRef(); }
90
92 TfToken(TfToken && rhs) noexcept : _rep(rhs._rep) {
94 }
95
97 TfToken& operator= (TfToken const& rhs) noexcept {
98 if (&rhs != this) {
99 rhs._AddRef();
100 _RemoveRef();
101 _rep = rhs._rep;
102 }
103 return *this;
104 }
105
107 TfToken& operator= (TfToken && rhs) noexcept {
108 if (&rhs != this) {
109 _RemoveRef();
110 _rep = rhs._rep;
111 rhs._rep = TfPointerAndBits<const _Rep>();
112 }
113 return *this;
114 }
115
117 ~TfToken() { _RemoveRef(); }
118
120 //
121 // This constructor involves a string hash and a lookup in the global
122 // table, and so should not be done more often than necessary. When
123 // possible, create a token once and reuse it many times.
124 //
125 // Any content in \p s past an embedded NUL is ignored, and is not stored;
126 // see the class documentation.
127 TF_API explicit TfToken(std::string const& s);
140 TF_API TfToken(std::string const& s, _ImmortalTag);
141
143 //
144 // This constructor involves a string hash and a lookup in the global
145 // table, and so should not be done more often than necessary. When
146 // possible, create a token once and reuse it many times.
147 TF_API explicit TfToken(char const* s);
157 TF_API TfToken(char const* s, _ImmortalTag);
158
160 //
161 // If a token has previous been created for the given string, this
162 // will return it. Otherwise, the empty token will be returned.
163 //
164 // Lookup uses the same identity rule as construction, so any content in
165 // \p s past an embedded NUL is ignored.
166 TF_API static TfToken Find(std::string const& s);
167
169 //
170 // The hash is based on the token's storage identity; this is immutable
171 // as long as the token is in use anywhere in the process.
172 //
173 inline size_t Hash() const;
174
176 struct HashFunctor {
177 size_t operator()(TfToken const& token) const { return token.Hash(); }
178 };
179
185 typedef TfHashSet<TfToken, TfToken::HashFunctor> HashSet;
186
193 typedef std::set<TfToken, TfTokenFastArbitraryLessThan> Set;
194
200 size_t size() const {
201 _Rep const *rep = _rep.Get();
202 return rep ? rep->_str.size() : 0;
203 }
204
216 char const* GetText() const {
217 _Rep const *rep = _rep.Get();
218 return rep ? rep->_str.c_str() : "";
219 }
220
222 char const *data() const {
223 return GetText();
224 }
225
232 std::string const& GetString() const {
233 _Rep const *rep = _rep.Get();
234 return rep ? rep->_str : _GetEmptyString();
235 }
236
238 inline void Swap(TfToken &other) {
239 std::swap(_rep, other._rep);
240 }
241
243 bool operator==(TfToken const& o) const {
244 // Equal if pointers & bits are equal, or if just pointers are.
245 return _rep.Get() == o._rep.Get();
246 }
247
249 bool operator!=(TfToken const& o) const {
250 return !(*this == o);
251 }
252
259 TF_API bool operator==(std::string const& o) const;
260
263 TF_API bool operator==(const char *o) const;
264
266 friend bool operator==(std::string const& o, TfToken const& t) {
267 return t == o;
268 }
269
271 friend bool operator==(const char *o, TfToken const& t) {
272 return t == o;
273 }
274
277 bool operator!=(std::string const& o) const {
278 return !(*this == o);
279 }
280
282 friend bool operator!=(std::string const& o, TfToken const& t) {
283 return !(t == o);
284 }
285
288 bool operator!=(char const* o) const {
289 return !(*this == o);
290 }
291
293 friend bool operator!=(char const* o, TfToken const& t) {
294 return !(t == o);
295 }
296
300 inline bool operator<(TfToken const& r) const {
301 auto ll = _rep.GetLiteral(), rl = r._rep.GetLiteral();
302 if (!ll || !rl) {
303 // One or both are zero -- return true if ll is zero and rl is not.
304 return !ll && rl;
305 }
306 if (ll == rl) {
307 return false;
308 }
309 auto lrep = _rep.Get(), rrep = r._rep.Get();
310 uint64_t lcc = lrep->_compareCode, rcc = rrep->_compareCode;
311 return lcc < rcc || (lcc == rcc && lrep->_str < rrep->_str);
312 }
313
315 inline bool operator>(TfToken const& o) const {
316 return o < *this;
317 }
318
321 inline bool operator>=(TfToken const& o) const {
322 return !(*this < o);
323 }
324
327 inline bool operator<=(TfToken const& o) const {
328 return !(*this > o);
329 }
330
332 operator std::string const& () const { return GetString(); }
333
335 bool IsEmpty() const { return _rep.GetLiteral() == 0; }
336
341 bool IsImmortal() const {
342 if (!_rep.BitsAs<bool>()) {
343 return true;
344 }
345 // There is no synchronization or ordering constraints between this read
346 // and other reads/writes, so relaxed memory order suffices.
347 bool immortal = !(_rep->_refCount.load(std::memory_order_relaxed) & 1);
348 if (immortal) {
349 // Our belief is wrong, update our cache of countedness.
350 _rep.SetBits(false);
351 }
352 return immortal;
353 }
354
356 friend TF_API std::ostream &operator <<(std::ostream &stream, TfToken const&);
357
359 template <class HashState>
360 friend void
361 TfHashAppend(HashState &h, TfToken const &token) {
362 h.Append(token._rep.Get());
363 }
364
365private:
366 // Add global swap overload.
367 friend void swap(TfToken &lhs, TfToken &rhs) {
368 lhs.Swap(rhs);
369 }
370
371 void _AddRef() const {
372 if (!_rep.BitsAs<bool>()) {
373 // Not counted, do nothing.
374 return;
375 }
376 // We believe this rep is refCounted.
377 if (!_rep->IncrementAndCheckCounted()) {
378 // Our belief is wrong, update our cache of countedness.
379 _rep.SetBits(false);
380 }
381 }
382
383 void _RemoveRef() const {
384 if (!_rep.BitsAs<bool>()) {
385 // Not counted, do nothing.
386 return;
387 }
388 // Decrement the refcount.
389 _rep->Decrement();
390 }
391
392 struct _Rep {
393 _Rep() = default;
394
395 // A rep's identity in the token table is its NUL-terminated c-string
396 // (see Tf_TokenRegistry::_Eq), so _str must hold exactly that.
397 // Building it from the c-string trims any content past an embedded NUL,
398 // which keeps _str.size() == strlen(_cstr) and makes a token's
399 // observable content independent of whether a char * or std::string
400 // happened to intern it.
401 explicit _Rep(char const *str,
402 unsigned setNum,
403 uint64_t compareCode)
404 : _refCount(0)
405 , _setNum(setNum)
406 , _compareCode(compareCode)
407 , _str(str)
408 , _cstr(_str.c_str()) {}
409
410 explicit _Rep(std::string const &str,
411 unsigned setNum,
412 uint64_t compareCode)
413 : _Rep(str.c_str(), setNum, compareCode) {}
414
415 // Make sure we reacquire _cstr from _str on copy and assignment
416 // to avoid holding on to a dangling pointer. However, if rhs'
417 // _cstr member doesn't come from its _str, just copy it directly
418 // over. This is to support lightweight _Rep objects used for
419 // internal lookups.
420 _Rep(_Rep const &rhs)
421 : _refCount(rhs._refCount.load(std::memory_order_relaxed))
422 , _setNum(rhs._setNum)
423 , _compareCode(rhs._compareCode)
424 , _str(rhs._str)
425 , _cstr(rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr) {}
426
427 _Rep &operator=(_Rep const &rhs) {
428 _refCount = rhs._refCount.load(std::memory_order_relaxed);
429 _setNum = rhs._setNum;
430 _compareCode = rhs._compareCode;
431 _str = rhs._str;
432 _cstr = (rhs._str.c_str() == rhs._cstr ? _str.c_str() : rhs._cstr);
433 return *this;
434 }
435
436 inline bool IncrementAndCheckCounted() const {
437 // Refcounts are manipulated by add/sub 2, since the lowest-order
438 // bit indicates whether or not the rep is counted.
439 return _refCount.fetch_add(2, std::memory_order_relaxed) & 1;
440 }
441
442 inline void Decrement() const {
443 // Refcounts are manipulated by add/sub 2, since the lowest-order
444 // bit indicates whether or not the rep is counted.
445 _refCount.fetch_sub(2, std::memory_order_release);
446 }
447
448 mutable std::atomic_uint _refCount;
449 unsigned _setNum;
450 uint64_t _compareCode;
451 std::string _str;
452 char const *_cstr;
453 };
454
455 friend struct TfTokenFastArbitraryLessThan;
456 friend struct Tf_TokenRegistry;
457
458 TF_API static std::string const& _GetEmptyString();
459
460 mutable TfPointerAndBits<const _Rep> _rep;
461};
462
463inline size_t
465{
466 return TfHash()(*this);
467}
468
472 inline bool operator()(TfToken const &lhs, TfToken const &rhs) const {
473 return lhs._rep.Get() < rhs._rep.Get();
474 }
475};
476
478TF_API std::vector<TfToken>
479TfToTokenVector(const std::vector<std::string> &sv);
480
482TF_API std::vector<std::string>
483TfToStringVector(const std::vector<TfToken> &tv);
484
486inline size_t hash_value(const TfToken& x) { return x.Hash(); }
487
489typedef std::vector<TfToken> TfTokenVector;
490
491PXR_NAMESPACE_CLOSE_SCOPE
492
493#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:81
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:293
TfToken(TfToken &&rhs) noexcept
Move constructor.
Definition token.h:92
size_t size() const
Return the size of the string that this token represents.
Definition token.h:200
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:222
bool operator!=(char const *o) const
Inequality operator for char strings.
Definition token.h:288
bool operator<=(TfToken const &o) const
Less-than-or-equal operator that compares tokenized strings lexicographically.
Definition token.h:327
bool operator>(TfToken const &o) const
Greater-than operator that compares tokenized strings lexicographically.
Definition token.h:315
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:282
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:271
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:193
TfToken & operator=(TfToken const &rhs) noexcept
Copy assignment.
Definition token.h:97
bool operator!=(TfToken const &o) const
Equality operator.
Definition token.h:249
char const * GetText() const
Return the text that this token represents.
Definition token.h:216
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:238
TF_API bool operator==(std::string const &o) const
Compare this token's interned string to o.
bool operator==(TfToken const &o) const
Equality operator.
Definition token.h:243
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:266
bool IsEmpty() const
Returns true iff this token contains the empty string "".
Definition token.h:335
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:232
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:321
constexpr TfToken() noexcept=default
Create the empty token, containing the empty string.
TF_API bool operator==(const char *o) const
Compare this token's interned string to o.
bool operator<(TfToken const &r) const
Less-than operator that compares tokenized strings lexicographically.
Definition token.h:300
~TfToken()
Destructor.
Definition token.h:117
size_t Hash() const
Return a size_t hash for this token.
Definition token.h:464
TfHashSet< TfToken, TfToken::HashFunctor > HashSet
Predefined type for TfHashSet of tokens, since it's so awkward to manually specify.
Definition token.h:185
bool IsImmortal() const
Returns true iff this is an immortal token.
Definition token.h:341
friend void TfHashAppend(HashState &h, TfToken const &token)
TfHash support.
Definition token.h:361
bool operator!=(std::string const &o) const
Inequality operator for string's.
Definition token.h:277
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:176
Fast but non-lexicographical (in fact, arbitrary) less-than comparison for TfTokens.
Definition token.h:471
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
Definition token.h:486
std::vector< TfToken > TfTokenVector
Convenience types.
Definition token.h:489
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.