File: vtkStringToken.h

package info (click to toggle)
vtk9 9.3.0%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 267,116 kB
  • sloc: cpp: 2,195,914; ansic: 285,452; python: 104,858; sh: 4,061; yacc: 4,035; java: 3,977; xml: 2,771; perl: 2,189; lex: 1,762; objc: 153; makefile: 150; javascript: 90; tcl: 59
file content (202 lines) | stat: -rw-r--r-- 7,729 bytes parent folder | download
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
// 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 "vtkSmartPointer.h"

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

VTK_ABI_NAMESPACE_BEGIN
class vtkStringManager;

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

  /// Construct a token from a string literal.
  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.
  inline 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; }
  /// Return the string corresponding to the token.
  const std::string& Data() 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
  inline static constexpr Hash StringHash(const char* data, std::size_t size) noexcept
  {
    return vtkStringToken::hash_32_fnv1a_const(data, size);
  }

  /// Return the database of strings and their tokens (hashes).
  static const vtkStringManager* GetManager();

protected:
  Hash Id;
  static vtkSmartPointer<vtkStringManager> Manager;

  static vtkStringManager* GetManagerInternal();

  // ----
  // Adapted from https://notes.underscorediscovery.com/constexpr-fnv1a/index.html
  // which declared the source as public domain or equivalent. Retrieved on 2022-07-22.
  static constexpr uint32_t hash32a_const = 0x811c9dc5;
  static constexpr uint32_t hash32b_const = 0x1000193;
  static constexpr uint64_t hash64a_const = 0xcbf29ce484222325;
  static constexpr uint64_t hash64b_const = 0x100000001b3;

  // Compute a 32-bit hash of a string.
  // Unlike the original, this version handles embedded null characters so that
  // unicode multi-byte sequences can be hashed.
  inline static constexpr uint32_t hash_32_fnv1a_const(
    const char* const str, std::size_t size, const uint32_t value = hash32a_const) noexcept
  {
    return (!str || size <= 0)
      ? value
      : hash_32_fnv1a_const(&str[1], size - 1, (value ^ uint32_t(str[0])) * hash32b_const);
  }

#if 0
  // Compute a 64-bit hash of a string.
  inline static constexpr uint64_t hash_64_fnv1a_const(
    const char* const str, std::size_t size, const uint64_t value = hash64a_const) noexcept
  {
    return (!str || size <= 0) ? value :
      hash_64_fnv1a_const(&str[1], size - 1, (value ^ uint64_t(str[0])) * hash64b_const);
  }
#endif
};
VTK_ABI_NAMESPACE_END

#ifndef __VTK_WRAP__
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.
inline 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.
/// ```
inline 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
#endif // __VTK_WRAP__

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