File: vtkStringToken.h

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 205,916 kB
  • sloc: cpp: 2,336,565; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 178; javascript: 165; objc: 153; tcl: 59
file content (249 lines) | stat: -rw-r--r-- 9,093 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#ifndef vtkStringToken_h
#define vtkStringToken_h
/**
 * @class   vtkStringToken
 * @brief   Represent a string by its integer hash.
 *
 * This class does not inherit vtkObject; it is a lightweight
 * object for representing a string as a 32-bit integer token.
 * Tokens can be constructed at compile-time (via the ""_token
 * string-literal operator below) or run-time (via the constructor).
 *
 * Equality comparisons are simple integer tests, while
 * inequality operators attempt to locate the original source
 * strings and compare them alphanumerically to preserve
 * lexicographic ordering.
 *
 * This class can be used inside ordered and unordered
 * STL containers.
 */

#include <token/Token.h>

#include "vtkCompiler.h"     // for VTK_COMPILER_GCC
#include "vtkSmartPointer.h" // for ivar

//clang-format off
#include <vtk_nlohmannjson.h>
#include VTK_NLOHMANN_JSON(json.hpp)
//clang-format on

#include <cstdint>       // for `std::uint*_t`
#include <unordered_set> // for membership API

VTK_ABI_NAMESPACE_BEGIN

class VTKCOMMONCORE_EXPORT vtkStringToken
{
public:
  using Hash = std::uint32_t;

  /// Construct a token from a string literal.
  VTK_WRAPEXCLUDE vtkStringToken(const char* data = nullptr, std::size_t size = std::string::npos);
  /// Construct a token from a std::string.
  vtkStringToken(const std::string& data);
  /// Construct a token given its hash value.
  /// NOTE: This will NOT insert a string into the manager as other constructors do.
  constexpr vtkStringToken(Hash tokenId) noexcept
    : Id(tokenId)
  {
  }

  /// Return the token's ID (usually its hash but possibly not in the case of collisions).
  Hash GetId() const { return this->Id; }
  /// A Python-wrappable (but less strongly typed) alternative to GetId()
  unsigned int GetHash() const { return static_cast<unsigned int>(this->Id); }
  /// Return the string corresponding to the token.
  const std::string& Data() const;

  /// Return whether the token is valid or not.
  ///
  /// Valid tokens are those whose hash is not equal to the hash of an empty string.
  bool IsValid() const;
  /// Return whether a string is available for the token's hash ID.
  bool HasData() const;

  /// Fast equality comparison (compares hashes, not strings).
  bool operator==(const vtkStringToken& other) const;
  /// Fast inequality comparison (compares hashes, not strings).
  bool operator!=(const vtkStringToken& other) const;

  /// Slow, but unsurprising string comparison (preserves lexical string ordering).
  bool operator<(const vtkStringToken& other) const;
  bool operator>(const vtkStringToken& other) const;
  bool operator<=(const vtkStringToken& other) const;
  bool operator>=(const vtkStringToken& other) const;

  /// Return the hash of a string
  /// This is used internally but also by the ""_token() literal operator
  static constexpr Hash StringHash(const char* data, std::size_t size) noexcept
  {
    return token_NAMESPACE::Token::stringHash(data, size);
  }

  /// Return the hash code used to indicate an invalid (empty) token.
  static Hash InvalidHash();

  /// Methods to manage groups of tokens underneath a parent.
  ///
  /// Grouping tokens provides applications a way to create and discover
  /// dynamic enumerations or sets of strings.
  /// For example, you might tokenize `car` and add tokens for car parts
  /// such `body`, `motor`, and `wheels` as children of `car`.
  /// Another library might then add more children such as `windshield`
  /// and `hood`; the application can present all of these children by
  /// asking for all the children of `car`.
  ///@{
  /// Add \a member as a child of this token.
  ///
  /// If true is returned, the \a member was added.
  /// If false is returned, the \a member was already part of the group
  /// or one of the tokens (this token or \a member) was invalid.
  bool AddChild(vtkStringToken member);
  /// Remove a \a member from this token's children.
  ///
  /// If this returns false, \a member was not a child of this token.
  bool RemoveChild(vtkStringToken member);
  /// Return all the children of this token.
  std::unordered_set<vtkStringToken> Children(bool recursive = true);
  /// Return all the tokens that have children.
  static std::unordered_set<vtkStringToken> AllGroups();
  ///@}

protected:
  Hash Id;
};

/// Convert a JSON value into a string token.
///
/// The value \a jj must be an integer or string.
/// If it is a string, it will be hashed into a token.
/// If it is an integer, it will be treated as a hash.
inline void VTKCOMMONCORE_EXPORT from_json(const nlohmann::json& jj, vtkStringToken& tt)
{
  if (jj.is_number_integer())
  {
    tt = vtkStringToken(jj.get<vtkStringToken::Hash>());
  }
  else if (jj.is_string())
  {
    tt = jj.get<std::string>();
  }
  else
  {
    throw std::runtime_error("String tokens must be JSON integers or strings.");
  }
}

/// Convert a string token into a JSON value.
///
/// If \a tt has a valid string, \a jj will be set to the string.
/// Otherwise, \a jj will be set to the integer hash held by \a tt.
inline void VTKCOMMONCORE_EXPORT to_json(nlohmann::json& jj, const vtkStringToken& tt)
{
  if (tt.HasData())
  {
    jj = tt.Data();
  }
  else
  {
    jj = tt.GetId();
  }
}

VTK_ABI_NAMESPACE_END

namespace vtk
{
namespace literals
{
VTK_ABI_NAMESPACE_BEGIN

/// Construct the hash of a string literal, like so:
///
/// ```c++
/// using namespace vtk::literals;
/// vtkStringToken::Hash t = "test"_hash;
/// bool ok = false;
/// switch (t)
/// {
///   case "foo"_hash: ok = false;
///   case "test"_hash: ok = true;
/// }
/// std::cout << t << "\n"; // Prints a hash-code.
/// std::cout << ok << "\n"; // Prints a true value.
/// ```
///
/// As the example above shows, it is possible to use
/// hashed strings in switch statements since the hashing
/// occurs at build time. This is more efficient than
/// a sequence of if-conditionals performing string
/// comparisons.
constexpr VTKCOMMONCORE_EXPORT vtkStringToken::Hash operator""_hash(
  const char* data, std::size_t size)
{
  return vtkStringToken::StringHash(data, size);
}

/// Construct a token from a string literal, like so:
///
/// ```c++
/// using namespace vtk::literals;
/// vtkStringToken t = "test"_token;
/// std::cout << t.id() << "\n"; // Prints a hash-code.
/// // std::cout << t.value() << "\n"; // Prints "test" if someone else constructed the token from a
/// ctor; else throws exception.
/// ```
constexpr VTKCOMMONCORE_EXPORT vtkStringToken operator""_token(const char* data, std::size_t size)
{
  return vtkStringToken(vtkStringToken::StringHash(data, size));
}

VTK_ABI_NAMESPACE_END
} // namespace literals
} // namespace vtk

VTK_ABI_NAMESPACE_BEGIN
bool VTKCOMMONCORE_EXPORT operator==(const std::string& a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator!=(const std::string& a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator>(const std::string& a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator<(const std::string& a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator>=(const std::string& a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator<=(const std::string& a, const vtkStringToken& b);

bool VTKCOMMONCORE_EXPORT operator==(const vtkStringToken& a, const std::string& b);
bool VTKCOMMONCORE_EXPORT operator!=(const vtkStringToken& a, const std::string& b);
bool VTKCOMMONCORE_EXPORT operator>(const vtkStringToken& a, const std::string& b);
bool VTKCOMMONCORE_EXPORT operator<(const vtkStringToken& a, const std::string& b);
bool VTKCOMMONCORE_EXPORT operator>=(const vtkStringToken& a, const std::string& b);
bool VTKCOMMONCORE_EXPORT operator<=(const vtkStringToken& a, const std::string& b);

bool VTKCOMMONCORE_EXPORT operator==(const char* a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator!=(const char* a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator>(const char* a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator<(const char* a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator>=(const char* a, const vtkStringToken& b);
bool VTKCOMMONCORE_EXPORT operator<=(const char* a, const vtkStringToken& b);

bool VTKCOMMONCORE_EXPORT operator==(const vtkStringToken& a, const char* b);
bool VTKCOMMONCORE_EXPORT operator!=(const vtkStringToken& a, const char* b);
bool VTKCOMMONCORE_EXPORT operator>(const vtkStringToken& a, const char* b);
bool VTKCOMMONCORE_EXPORT operator<(const vtkStringToken& a, const char* b);
bool VTKCOMMONCORE_EXPORT operator>=(const vtkStringToken& a, const char* b);
bool VTKCOMMONCORE_EXPORT operator<=(const vtkStringToken& a, const char* b);
VTK_ABI_NAMESPACE_END

namespace std
{
/// vtkStringTokens provide a specialization of std::hash so they can be used in unordered
/// containers.
template <>
struct VTKCOMMONCORE_EXPORT hash<vtkStringToken>
{
  std::size_t operator()(const vtkStringToken& t) const { return t.GetId(); }
};
} // namespace std

#endif // vtkStringToken_h