FST  openfst-1.8.4
OpenFst Library
compat.h
Go to the documentation of this file.
1 // Copyright 2005-2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the 'License');
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an 'AS IS' BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // See www.openfst.org for extensive documentation on this weighted
16 // finite-state transducer library.
17 
18 #ifndef FST_COMPAT_H_
19 #define FST_COMPAT_H_
20 
21 #include <algorithm>
22 #include <climits>
23 #include <cstddef>
24 #include <cstdint>
25 #include <cstdlib>
26 #include <cstring>
27 #include <initializer_list>
28 #include <iostream>
29 #include <iterator>
30 #include <memory>
31 #include <numeric>
32 #include <sstream>
33 #include <string>
34 #include <string_view>
35 #include <type_traits>
36 #include <utility>
37 #include <vector>
38 
39 #if defined(__GNUC__) || defined(__clang__)
40 #define OPENFST_DEPRECATED(message) __attribute__((deprecated(message)))
41 #elif defined(_MSC_VER)
42 #define OPENFST_DEPRECATED(message) [[deprecated(message)]]
43 #else
44 #define OPENFST_DEPRECATED(message)
45 #endif
46 
47 namespace fst {
48 
49 // Downcasting.
50 
51 template <typename To, typename From>
52 inline To down_cast(From *f) {
53  return static_cast<To>(f);
54 }
55 
56 template <typename To, typename From>
57 inline To down_cast(From &f) {
58  return static_cast<To>(f);
59 }
60 
61 // Bitcasting.
62 template <class Dest, class Source>
63 inline Dest bit_cast(const Source &source) {
64  static_assert(sizeof(Dest) == sizeof(Source),
65  "Bitcasting unsafe for specified types");
66  Dest dest;
67  std::memcpy(&dest, &source, sizeof(dest));
68  return dest;
69 }
70 
71 template <typename T>
72 T UnalignedLoad(const void *p) {
73  T t;
74  std::memcpy(&t, p, sizeof t);
75  return t;
76 }
77 
78 namespace internal {
79 
80 // TODO(kbg): Remove this once we migrate to C++20.
81 template <typename T>
82 struct type_identity {
83  using type = T;
84 };
85 
86 template <typename T>
88 
89 } // namespace internal
90 
91 template <typename To>
92 constexpr To implicit_cast(typename internal::type_identity_t<To> to) {
93  return to;
94 }
95 
96 // Checksums.
97 class CheckSummer {
98  public:
99  CheckSummer();
100 
101  void Reset();
102 
103  void Update(std::string_view data);
104 
105  std::string Digest() { return check_sum_; }
106 
107  private:
108  static constexpr int kCheckSumLength = 32;
109  int count_;
110  std::string check_sum_;
111 
112  CheckSummer(const CheckSummer &) = delete;
113  CheckSummer &operator=(const CheckSummer &) = delete;
114 };
115 
116 // Defines make_unique_for_overwrite using a standard definition that should be
117 // compatible with the C++20 definition. That is, all compiling uses of
118 // `std::make_unique_for_overwrite` should have the same result with
119 // `fst::make_unique_for_overwrite`. Note that the reverse doesn't
120 // necessarily hold.
121 // TODO(kbg): Remove these once we migrate to C++20.
122 
123 template <typename T>
124 std::unique_ptr<T> make_unique_for_overwrite() {
125  return std::unique_ptr<T>(new T);
126 }
127 
128 template <typename T>
129 std::unique_ptr<T> make_unique_for_overwrite(size_t n) {
130  return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
131 }
132 
133 template <typename T>
134 std::unique_ptr<T> WrapUnique(T *ptr) {
135  return std::unique_ptr<T>(ptr);
136 }
137 
138 // Range utilities
139 
140 // A range adaptor for a pair of iterators.
141 //
142 // This just wraps two iterators into a range-compatible interface. Nothing
143 // fancy at all.
144 template <typename IteratorT>
146  public:
147  using iterator = IteratorT;
148  using const_iterator = IteratorT;
149  using value_type = typename std::iterator_traits<IteratorT>::value_type;
150 
151  iterator_range() : begin_iterator_(), end_iterator_() {}
152  iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
153  : begin_iterator_(std::move(begin_iterator)),
154  end_iterator_(std::move(end_iterator)) {}
155 
156  IteratorT begin() const { return begin_iterator_; }
157  IteratorT end() const { return end_iterator_; }
158 
159  private:
160  IteratorT begin_iterator_, end_iterator_;
161 };
162 
163 // Convenience function for iterating over sub-ranges.
164 //
165 // This provides a bit of syntactic sugar to make using sub-ranges
166 // in for loops a bit easier. Analogous to std::make_pair().
167 template <typename T>
169  return iterator_range<T>(std::move(x), std::move(y));
170 }
171 
172 // String munging.
173 
174 namespace internal {
175 
176 // Computes size of joined string.
177 template <class S>
178 size_t GetResultSize(const std::vector<S> &elements, size_t s_size) {
179  const auto lambda = [](size_t partial, const S &right) {
180  return partial + right.size();
181  };
182  return std::accumulate(elements.begin(), elements.end(), 0, lambda) +
183  elements.size() * s_size - s_size;
184 }
185 
186 } // namespace internal
187 
188 inline bool StrContains(std::string_view haystack, std::string_view needle) {
189  return haystack.find(needle) != haystack.npos;
190 }
191 
192 inline bool StrContains(std::string_view haystack, char needle) {
193  return haystack.find(needle) != haystack.npos;
194 }
195 
196 template <class S>
197 std::string StrJoin(const std::vector<S> &elements, std::string_view delim) {
198  std::string result;
199  if (elements.empty()) return result;
200  const size_t s_size = delim.size();
201  result.reserve(internal::GetResultSize(elements, s_size));
202  auto it = elements.begin();
203  result.append(it->data(), it->size());
204  for (++it; it != elements.end(); ++it) {
205  result.append(delim.data(), s_size);
206  result.append(it->data(), it->size());
207  }
208  return result;
209 }
210 
211 template <class S>
212 std::string StrJoin(const std::vector<S> &elements, char delim) {
213  const std::string_view view_delim(&delim, 1);
214  return StrJoin(elements, view_delim);
215 }
216 
217 struct SkipEmpty {};
218 
219 struct ByAnyChar {
220  public:
221  explicit ByAnyChar(std::string_view sp) : delimiters(sp) {}
222 
223  std::string delimiters;
224 };
225 
226 namespace internal {
227 
229  public:
230  using const_iterator = std::vector<std::string_view>::const_iterator;
231  using value_type = std::string_view;
232 
233  StringSplitter(std::string_view string, std::string delim,
234  bool skip_empty = false)
235  : string_(std::move(string)),
236  delim_(std::move(delim)),
237  skip_empty_(skip_empty),
238  vec_(SplitToSv()) {}
239 
240  inline operator // NOLINT(google-explicit-constructor)
241  std::vector<std::string_view>() && {
242  return std::move(vec_);
243  }
244 
245  inline operator // NOLINT(google-explicit-constructor)
246  std::vector<std::string>() {
247  std::vector<std::string> str_vec(vec_.begin(), vec_.end());
248  return str_vec;
249  }
250 
251  const_iterator begin() const { return vec_.begin(); }
252  const_iterator end() const { return vec_.end(); }
253 
254  private:
255  std::vector<std::string_view> SplitToSv();
256 
257  std::string_view string_;
258  std::string delim_;
259  bool skip_empty_;
260  std::vector<std::string_view> vec_;
261 };
262 
263 } // namespace internal
264 
265 // `StrSplit` replacements. Only support splitting on `char` or
266 // `ByAnyChar` (notable not on a multi-char string delimiter), and with or
267 // without `SkipEmpty`.
268 internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim);
269 internal::StringSplitter StrSplit(std::string_view full, char delim);
270 internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim,
271  SkipEmpty);
272 internal::StringSplitter StrSplit(std::string_view full, char delim, SkipEmpty);
273 
274 void StripTrailingAsciiWhitespace(std::string *full);
275 
276 std::string_view StripTrailingAsciiWhitespace(std::string_view full);
277 
278 class StringOrInt {
279  public:
280  template <typename T, typename = std::enable_if_t<
281  std::is_convertible_v<T, std::string_view>>>
282  StringOrInt(T s) : str_(std::string(s)) {} // NOLINT
283 
284  StringOrInt(int i) { // NOLINT
285  str_ = std::to_string(i);
286  }
287 
288  const std::string &Get() const { return str_; }
289 
290  private:
291  std::string str_;
292 };
293 
294 
295 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2) {
296  return s1.Get() + s2.Get();
297 }
298 
299 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2,
300  const StringOrInt &s3) {
301  return s1.Get() + s2.Get() + s3.Get();
302 }
303 
304 // For four or more args, wrap them up into an initializer list and use an
305 // explicit loop.
306 template <typename... Args>
307 std::string StrCat(const StringOrInt &s1, const StringOrInt &s2,
308  const StringOrInt &s3, const Args &...args) {
309  const std::initializer_list<StringOrInt> list{
310  s1, s2, s3, static_cast<const StringOrInt &>(args)...};
311  std::ostringstream ostrm;
312  for (const auto &s : list) ostrm << s.Get();
313  return ostrm.str();
314 }
315 
316 // TODO(agutkin): Remove this once we migrate to C++20, where `starts_with`
317 // is available.
318 inline bool StartsWith(std::string_view text, std::string_view prefix) {
319  return prefix.empty() ||
320  (text.size() >= prefix.size() &&
321  std::memcmp(text.data(), prefix.data(), prefix.size()) == 0);
322 }
323 
324 inline bool ConsumePrefix(std::string_view *s, std::string_view expected) {
325  if (!StartsWith(*s, expected)) return false;
326  s->remove_prefix(expected.size());
327  return true;
328 }
329 
330 } // namespace fst
331 
332 #endif // FST_COMPAT_H_
std::vector< std::string_view >::const_iterator const_iterator
Definition: compat.h:230
std::string delimiters
Definition: compat.h:223
Dest bit_cast(const Source &source)
Definition: compat.h:63
StringOrInt(int i)
Definition: compat.h:284
IteratorT const_iterator
Definition: compat.h:148
std::string_view value_type
Definition: compat.h:231
size_t GetResultSize(const std::vector< S > &elements, size_t s_size)
Definition: compat.h:178
typename type_identity< T >::type type_identity_t
Definition: compat.h:87
iterator_range< T > make_range(T x, T y)
Definition: compat.h:168
T UnalignedLoad(const void *p)
Definition: compat.h:72
const std::string & Get() const
Definition: compat.h:288
typename std::iterator_traits< IteratorT >::value_type value_type
Definition: compat.h:149
IteratorT begin() const
Definition: compat.h:156
To down_cast(From *f)
Definition: compat.h:52
std::unique_ptr< T > WrapUnique(T *ptr)
Definition: compat.h:134
StringOrInt(T s)
Definition: compat.h:282
void StripTrailingAsciiWhitespace(std::string *full)
Definition: compat.cc:105
internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim)
Definition: compat.cc:75
bool ConsumePrefix(std::string_view *s, std::string_view expected)
Definition: compat.h:324
std::unique_ptr< T > make_unique_for_overwrite()
Definition: compat.h:124
constexpr To implicit_cast(typename internal::type_identity_t< To > to)
Definition: compat.h:92
const_iterator end() const
Definition: compat.h:252
IteratorT iterator
Definition: compat.h:147
StringSplitter(std::string_view string, std::string delim, bool skip_empty=false)
Definition: compat.h:233
std::string StrJoin(const std::vector< S > &elements, std::string_view delim)
Definition: compat.h:197
bool StartsWith(std::string_view text, std::string_view prefix)
Definition: compat.h:318
std::string StrCat(const StringOrInt &s1, const StringOrInt &s2)
Definition: compat.h:295
bool StrContains(std::string_view haystack, std::string_view needle)
Definition: compat.h:188
ByAnyChar(std::string_view sp)
Definition: compat.h:221
IteratorT end() const
Definition: compat.h:157
std::string Digest()
Definition: compat.h:105
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
Definition: compat.h:152
const_iterator begin() const
Definition: compat.h:251