FST  openfst-1.8.3
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 <iostream>
28 #include <iterator>
29 #include <memory>
30 #include <numeric>
31 #include <string>
32 #include <string_view>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 #if defined(__GNUC__) || defined(__clang__)
38 #define OPENFST_DEPRECATED(message) __attribute__((deprecated(message)))
39 #elif defined(_MSC_VER)
40 #define OPENFST_DEPRECATED(message) [[deprecated(message)]]
41 #else
42 #define OPENFST_DEPRECATED(message)
43 #endif
44 
45 namespace fst {
46 
47 // Downcasting.
48 
49 template <typename To, typename From>
50 inline To down_cast(From *f) {
51  return static_cast<To>(f);
52 }
53 
54 template <typename To, typename From>
55 inline To down_cast(From &f) {
56  return static_cast<To>(f);
57 }
58 
59 // Bitcasting.
60 template <class Dest, class Source>
61 inline Dest bit_cast(const Source &source) {
62  static_assert(sizeof(Dest) == sizeof(Source),
63  "Bitcasting unsafe for specified types");
64  Dest dest;
65  memcpy(&dest, &source, sizeof(dest));
66  return dest;
67 }
68 
69 template <typename T>
70 T UnalignedLoad(const void *p) {
71  T t;
72  memcpy(&t, p, sizeof t);
73  return t;
74 }
75 
76 namespace internal {
77 
78 // TODO(kbg): Remove this once we migrate to C++20.
79 template <typename T>
80 struct type_identity {
81  using type = T;
82 };
83 
84 template <typename T>
86 
87 } // namespace internal
88 
89 template <typename To>
90 constexpr To implicit_cast(typename internal::type_identity_t<To> to) {
91  return to;
92 }
93 
94 // Checksums.
95 class CheckSummer {
96  public:
97  CheckSummer();
98 
99  void Reset();
100 
101  void Update(std::string_view data);
102 
103  std::string Digest() { return check_sum_; }
104 
105  private:
106  static constexpr int kCheckSumLength = 32;
107  int count_;
108  std::string check_sum_;
109 
110  CheckSummer(const CheckSummer &) = delete;
111  CheckSummer &operator=(const CheckSummer &) = delete;
112 };
113 
114 // Defines make_unique_for_overwrite using a standard definition that should be
115 // compatible with the C++20 definition. That is, all compiling uses of
116 // `std::make_unique_for_overwrite` should have the same result with
117 // `fst::make_unique_for_overwrite`. Note that the reverse doesn't
118 // necessarily hold.
119 // TODO(kbg): Remove these once we migrate to C++20.
120 
121 template <typename T>
122 std::unique_ptr<T> make_unique_for_overwrite() {
123  return std::unique_ptr<T>(new T);
124 }
125 
126 template <typename T>
127 std::unique_ptr<T> make_unique_for_overwrite(size_t n) {
128  return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
129 }
130 
131 template <typename T>
132 std::unique_ptr<T> WrapUnique(T *ptr) {
133  return std::unique_ptr<T>(ptr);
134 }
135 
136 // Range utilities
137 
138 // A range adaptor for a pair of iterators.
139 //
140 // This just wraps two iterators into a range-compatible interface. Nothing
141 // fancy at all.
142 template <typename IteratorT>
144  public:
145  using iterator = IteratorT;
146  using const_iterator = IteratorT;
147  using value_type = typename std::iterator_traits<IteratorT>::value_type;
148 
149  iterator_range() : begin_iterator_(), end_iterator_() {}
150  iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
151  : begin_iterator_(std::move(begin_iterator)),
152  end_iterator_(std::move(end_iterator)) {}
153 
154  IteratorT begin() const { return begin_iterator_; }
155  IteratorT end() const { return end_iterator_; }
156 
157  private:
158  IteratorT begin_iterator_, end_iterator_;
159 };
160 
161 // Convenience function for iterating over sub-ranges.
162 //
163 // This provides a bit of syntactic sugar to make using sub-ranges
164 // in for loops a bit easier. Analogous to std::make_pair().
165 template <typename T>
167  return iterator_range<T>(std::move(x), std::move(y));
168 }
169 
170 // String munging.
171 
172 namespace internal {
173 
174 // Computes size of joined string.
175 template <class S>
176 size_t GetResultSize(const std::vector<S> &elements, size_t s_size) {
177  const auto lambda = [](size_t partial, const S &right) {
178  return partial + right.size();
179  };
180  return std::accumulate(elements.begin(), elements.end(), 0, lambda) +
181  elements.size() * s_size - s_size;
182 }
183 
184 } // namespace internal
185 
186 template <class S>
187 std::string StringJoin(const std::vector<S> &elements, std::string_view delim) {
188  std::string result;
189  if (elements.empty()) return result;
190  const size_t s_size = delim.size();
191  result.reserve(internal::GetResultSize(elements, s_size));
192  auto it = elements.begin();
193  result.append(it->data(), it->size());
194  for (++it; it != elements.end(); ++it) {
195  result.append(delim.data(), s_size);
196  result.append(it->data(), it->size());
197  }
198  return result;
199 }
200 
201 template <class S>
202 std::string StringJoin(const std::vector<S> &elements, char delim) {
203  const std::string_view view_delim(&delim, 1);
204  return StringJoin(elements, view_delim);
205 }
206 
207 struct SkipEmpty {};
208 
209 struct ByAnyChar {
210  public:
211  explicit ByAnyChar(std::string_view sp) : delimiters(sp) {}
212 
213  std::string delimiters;
214 };
215 
216 namespace internal {
217 
219  public:
220  using const_iterator = std::vector<std::string_view>::const_iterator;
221  using value_type = std::string_view;
222 
223  StringSplitter(std::string_view string, std::string delim,
224  bool skip_empty = false)
225  : string_(std::move(string)),
226  delim_(std::move(delim)),
227  skip_empty_(skip_empty),
228  vec_(SplitToSv()) {}
229 
230  inline operator // NOLINT(google-explicit-constructor)
231  std::vector<std::string_view>() && {
232  return std::move(vec_);
233  }
234 
235  inline operator // NOLINT(google-explicit-constructor)
236  std::vector<std::string>() {
237  std::vector<std::string> str_vec(vec_.begin(), vec_.end());
238  return str_vec;
239  }
240 
241  const_iterator begin() const { return vec_.begin(); }
242  const_iterator end() const { return vec_.end(); }
243 
244  private:
245  std::vector<std::string_view> SplitToSv();
246 
247  std::string_view string_;
248  std::string delim_;
249  bool skip_empty_;
250  std::vector<std::string_view> vec_;
251 };
252 
253 } // namespace internal
254 
255 // `StrSplit` replacements. Only support splitting on `char` or
256 // `ByAnyChar` (notable not on a multi-char string delimiter), and with or
257 // without `SkipEmpty`.
258 internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim);
259 internal::StringSplitter StrSplit(std::string_view full, char delim);
260 internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim,
261  SkipEmpty);
262 internal::StringSplitter StrSplit(std::string_view full, char delim, SkipEmpty);
263 
264 void StripTrailingAsciiWhitespace(std::string *full);
265 
266 std::string_view StripTrailingAsciiWhitespace(std::string_view full);
267 
268 class StringOrInt {
269  public:
270  template <typename T, typename = std::enable_if_t<
271  std::is_convertible_v<T, std::string_view>>>
272  StringOrInt(T s) : str_(std::string(s)) {} // NOLINT
273 
274  StringOrInt(int i) { // NOLINT
275  str_ = std::to_string(i);
276  }
277 
278  const std::string &Get() const { return str_; }
279 
280  private:
281  std::string str_;
282 };
283 
284 // TODO(kbg): Make this work with variadic template, maybe.
285 
286 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2) {
287  return s1.Get() + s2.Get();
288 }
289 
290 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2,
291  const StringOrInt &s3) {
292  return s1.Get() + StrCat(s2, s3);
293 }
294 
295 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2,
296  const StringOrInt &s3, const StringOrInt &s4) {
297  return s1.Get() + StrCat(s2, s3, s4);
298 }
299 
300 inline std::string StrCat(const StringOrInt &s1, const StringOrInt &s2,
301  const StringOrInt &s3, const StringOrInt &s4,
302  const StringOrInt &s5) {
303  return s1.Get() + StrCat(s2, s3, s4, s5);
304 }
305 
306 // TODO(agutkin): Remove this once we migrate to C++20, where `starts_with`
307 // is available.
308 inline bool StartsWith(std::string_view text, std::string_view prefix) {
309  return prefix.empty() ||
310  (text.size() >= prefix.size() &&
311  memcmp(text.data(), prefix.data(), prefix.size()) == 0);
312 }
313 
314 inline bool ConsumePrefix(std::string_view *s, std::string_view expected) {
315  if (!StartsWith(*s, expected)) return false;
316  s->remove_prefix(expected.size());
317  return true;
318 }
319 
320 } // namespace fst
321 
322 #endif // FST_COMPAT_H_
std::vector< std::string_view >::const_iterator const_iterator
Definition: compat.h:220
std::string delimiters
Definition: compat.h:213
Dest bit_cast(const Source &source)
Definition: compat.h:61
StringOrInt(int i)
Definition: compat.h:274
IteratorT const_iterator
Definition: compat.h:146
std::string_view value_type
Definition: compat.h:221
size_t GetResultSize(const std::vector< S > &elements, size_t s_size)
Definition: compat.h:176
typename type_identity< T >::type type_identity_t
Definition: compat.h:85
iterator_range< T > make_range(T x, T y)
Definition: compat.h:166
T UnalignedLoad(const void *p)
Definition: compat.h:70
const std::string & Get() const
Definition: compat.h:278
typename std::iterator_traits< IteratorT >::value_type value_type
Definition: compat.h:147
IteratorT begin() const
Definition: compat.h:154
To down_cast(From *f)
Definition: compat.h:50
std::unique_ptr< T > WrapUnique(T *ptr)
Definition: compat.h:132
StringOrInt(T s)
Definition: compat.h:272
void StripTrailingAsciiWhitespace(std::string *full)
Definition: compat.cc:105
internal::StringSplitter StrSplit(std::string_view full, ByAnyChar delim)
Definition: compat.cc:77
bool ConsumePrefix(std::string_view *s, std::string_view expected)
Definition: compat.h:314
std::unique_ptr< T > make_unique_for_overwrite()
Definition: compat.h:122
constexpr To implicit_cast(typename internal::type_identity_t< To > to)
Definition: compat.h:90
std::string StringJoin(const std::vector< S > &elements, std::string_view delim)
Definition: compat.h:187
const_iterator end() const
Definition: compat.h:242
IteratorT iterator
Definition: compat.h:145
StringSplitter(std::string_view string, std::string delim, bool skip_empty=false)
Definition: compat.h:223
bool StartsWith(std::string_view text, std::string_view prefix)
Definition: compat.h:308
std::string StrCat(const StringOrInt &s1, const StringOrInt &s2)
Definition: compat.h:286
ByAnyChar(std::string_view sp)
Definition: compat.h:211
IteratorT end() const
Definition: compat.h:155
std::string Digest()
Definition: compat.h:103
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
Definition: compat.h:150
const_iterator begin() const
Definition: compat.h:241