pstore2
sstring_view.hpp
Go to the documentation of this file.
1 //===- include/pstore/adt/sstring_view.hpp ----------------*- mode: C++ -*-===//
2 //* _ _ _ *
3 //* ___ ___| |_ _ __(_)_ __ __ _ __ _(_) _____ __ *
4 //* / __/ __| __| '__| | '_ \ / _` | \ \ / / |/ _ \ \ /\ / / *
5 //* \__ \__ \ |_| | | | | | | (_| | \ V /| | __/\ V V / *
6 //* |___/___/\__|_| |_|_| |_|\__, | \_/ |_|\___| \_/\_/ *
7 //* |___/ *
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the pstore project, under the Apache License v2.0 with LLVM Exceptions.
11 // See https://github.com/SNSystems/pstore/blob/master/LICENSE.txt for license
12 // information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //===----------------------------------------------------------------------===//
23 
24 #ifndef PSTORE_ADT_SSTRING_VIEW_HPP
25 #define PSTORE_ADT_SSTRING_VIEW_HPP
26 
27 #include <cstring>
28 
29 #include "pstore/support/fnv.hpp"
32 
33 namespace pstore {
34 
35  //* _ _ _ _ _ *
36  //* __| |_ _ _(_)_ _ __ _ | |_ _ _ __ _(_) |_ ___ *
37  //* (_-< _| '_| | ' \/ _` | | _| '_/ _` | | _(_-< *
38  //* /__/\__|_| |_|_||_\__, | \__|_| \__,_|_|\__/__/ *
39  //* |___/ *
40  template <typename StringType>
41  struct string_traits {};
42 
43  template <>
44  struct string_traits<std::string> {
45  static std::size_t length (std::string const & s) noexcept { return s.length (); }
46  static gsl::czstring data (std::string const & s) noexcept { return s.data (); }
47  };
48  template <>
49  struct string_traits<gsl::czstring> {
50  static std::size_t length (gsl::czstring const s) noexcept { return std::strlen (s); }
51  static gsl::czstring data (gsl::czstring const s) noexcept { return s; }
52  };
53  template <std::size_t Size>
54  struct string_traits<char const[Size]> {
55  static std::size_t length (gsl::czstring const s) noexcept { return std::strlen (s); }
56  static gsl::czstring data (gsl::czstring const s) noexcept { return s; }
57  };
58  template <std::size_t Size>
59  struct string_traits<char[Size]> {
60  static std::size_t length (gsl::czstring const s) noexcept { return std::strlen (s); }
61  static gsl::czstring data (gsl::czstring const s) noexcept { return s; }
62  };
63 
64  //* _ _ _ _ _ *
65  //* _ __ ___(_)_ _| |_ ___ _ _ | |_ _ _ __ _(_) |_ ___ *
66  //* | '_ \/ _ \ | ' \ _/ -_) '_| | _| '_/ _` | | _(_-< *
67  //* | .__/\___/_|_||_\__\___|_| \__|_| \__,_|_|\__/__/ *
68  //* |_| *
69  template <typename PointerType>
70  struct pointer_traits {
71  static constexpr bool is_pointer = false;
72  };
73  template <>
74  struct pointer_traits<char const *> {
75  static constexpr bool is_pointer = true;
76  using value_type = char const;
77  static char const * as_raw (char const * const p) noexcept { return p; }
78  };
79 
80  namespace details {
81  template <typename T>
83  static constexpr bool is_pointer = true;
84  using value_type = typename T::element_type;
85  static_assert (std::is_same<value_type, char>::value ||
86  std::is_same<value_type, char const>::value,
87  "pointer element type must be char or char const");
88  static char const * as_raw (T const & p) noexcept { return p.get (); }
89  };
90  } // namespace details
91 
92  template <>
93  struct pointer_traits<std::shared_ptr<char const>>
94  : details::pointer_traits_helper<std::shared_ptr<char const>> {};
95  template <>
96  struct pointer_traits<std::shared_ptr<char>>
97  : details::pointer_traits_helper<std::shared_ptr<char>> {};
98  template <>
99  struct pointer_traits<std::unique_ptr<char const[]>>
100  : details::pointer_traits_helper<std::unique_ptr<char const[]>> {};
101  template <>
102  struct pointer_traits<std::unique_ptr<char[]>>
103  : details::pointer_traits_helper<std::unique_ptr<char[]>> {};
104 
105  //* _ _ _ *
106  //* _____| |_ _ _(_)_ _ __ _ __ _(_)_____ __ __ *
107  //* (_-<_-< _| '_| | ' \/ _` | \ V / / -_) V V / *
108  //* /__/__/\__|_| |_|_||_\__, | \_/|_\___|\_/\_/ *
109  //* |___/ *
112  template <typename PointerType>
113  class sstring_view {
114  public:
116  "PointerType is not a known pointer type!");
117 
118  using value_type = char const;
119  using traits = std::char_traits<value_type>;
120  using pointer = value_type *;
121  using const_pointer = value_type const *;
122  using reference = value_type &;
123  using const_reference = value_type const &;
124  using const_iterator = value_type const *;
125  using iterator = const_iterator;
126  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
128  using reverse_iterator = const_reverse_iterator;
129  using size_type = std::size_t;
130  using difference_type = std::ptrdiff_t;
131  static constexpr auto const npos = static_cast<size_type> (-1);
132 
133  // 7.3, sstring_view constructors and assignment operators
134  constexpr sstring_view () noexcept = default;
135  sstring_view (PointerType ptr, size_type const size) noexcept
136  : ptr_{std::move (ptr)}
137  , size_{size} {}
138  sstring_view (sstring_view const &) = default;
139  sstring_view (sstring_view &&) noexcept = default;
140  ~sstring_view () = default;
141  sstring_view & operator= (sstring_view const &) = default;
142  sstring_view & operator= (sstring_view &&) noexcept = default;
143 
144  // 7.4, sstring_view iterator support
145  const_iterator begin () const noexcept { return data (); }
146  const_iterator end () const noexcept { return begin () + size_; }
147  const_iterator cbegin () const noexcept { return begin (); }
148  const_iterator cend () const noexcept { return end (); }
149  const_reverse_iterator rbegin () const noexcept { return const_reverse_iterator (end ()); }
150  const_reverse_iterator rend () const noexcept { return const_reverse_iterator (begin ()); }
151  const_reverse_iterator crbegin () const noexcept { return const_reverse_iterator (end ()); }
152  const_reverse_iterator crend () const noexcept { return const_reverse_iterator (begin ()); }
153 
154  // 7.5, sstring_view capacity
155  size_type size () const noexcept { return size_; }
156  size_type length () const noexcept { return size_; }
157  size_type max_size () const noexcept { return std::numeric_limits<size_t>::max (); }
158  bool empty () const noexcept { return size_ == 0; }
159 
160  // 7.6, sstring_view element access
161  const_reference operator[] (size_type const pos) const {
162  PSTORE_ASSERT (pos < size_);
163  return (this->data ())[pos];
164  }
165  const_reference at (size_type const pos) const {
166 #ifdef PSTORE_EXCEPTIONS
167  if (pos >= size_) {
168  throw std::out_of_range ("sstring_view access out of range");
169  }
170 #endif
171  return (*this)[pos];
172  }
173  const_reference front () const {
174  PSTORE_ASSERT (size_ > 0);
175  return (*this)[0];
176  }
177  const_reference back () const {
178  PSTORE_ASSERT (size_ > 0);
179  return (*this)[size_ - 1];
180  }
181  const_pointer data () const noexcept { return pointer_traits<PointerType>::as_raw (ptr_); }
182 
183  // 7.7, sstring_view modifiers
184  void clear () noexcept { size_ = 0; }
185 
186  void swap (sstring_view & s) noexcept {
187  std::swap (ptr_, s.ptr_);
188  std::swap (size_, s.size_);
189  }
190 
191  // 7.8, sstring_view string operations
192  explicit operator std::string () const { return this->to_string (); }
193 
194  template <class Allocator = std::allocator<char>>
195  std::basic_string<char, std::char_traits<char>, Allocator>
196  to_string (Allocator const & a = Allocator ()) const {
197  return {data (), size_, a};
198  }
199 
204  sstring_view<gsl::czstring> substr (size_type pos = 0, size_type const n = npos) const {
205  pos = std::min (pos, size_);
206  return {data () + pos, std::min (n, size_ - pos)};
207  }
208 
209  template <typename StringType>
210  int compare (StringType const & s) const;
211 
213  size_type find (value_type ch, size_type pos = 0) const noexcept {
214  for (; pos < size_; ++pos) {
215  if (ptr_[pos] == ch) {
216  return pos;
217  }
218  }
219  return npos;
220  }
221 
222  private:
223  PointerType ptr_ = nullptr;
224  size_type size_ = size_type{0};
225  };
226 
227  template <typename PointerType>
228  struct string_traits<sstring_view<PointerType>> {
229  static std::size_t length (sstring_view<PointerType> const & s) noexcept {
230  return s.length ();
231  }
232  static gsl::czstring data (sstring_view<PointerType> const & s) noexcept {
233  return s.data ();
234  }
235  };
236 
237  template <typename PointerType>
238  constexpr typename sstring_view<PointerType>::size_type sstring_view<PointerType>::npos;
239 
240  // compare
241  // ~~~~~~~
242  template <typename PointerType>
243  template <typename StringType>
244  int sstring_view<PointerType>::compare (StringType const & s) const {
245  auto const slen = string_traits<StringType>::length (s);
246  size_type const common_len = std::min (size (), slen);
247  int result = traits::compare (data (), string_traits<StringType>::data (s), common_len);
248  if (result == 0) {
249  result = (size () == slen) ? 0 : (size () < slen ? -1 : 1);
250  }
251  return result;
252  }
253 
254  // operator==
255  // ~~~~~~~~~~
256  template <typename PointerType1, typename PointerType2>
257  inline bool operator== (sstring_view<PointerType1> const & lhs,
258  sstring_view<PointerType2> const & rhs) noexcept {
259  if (lhs.size () != rhs.size ()) {
260  return false;
261  }
262  return lhs.compare (rhs) == 0;
263  }
264  template <typename PointerType, typename StringType>
265  inline bool operator== (sstring_view<PointerType> const & lhs,
266  StringType const & rhs) noexcept {
267  if (string_traits<sstring_view<PointerType>>::length (lhs) !=
269  return false;
270  }
271  return lhs.compare (rhs) == 0;
272  }
273  template <typename StringType, typename PointerType>
274  inline bool operator== (StringType const & lhs,
275  sstring_view<PointerType> const & rhs) noexcept {
277  string_traits<sstring_view<PointerType>>::length (rhs)) {
278  return false;
279  }
280  return rhs.compare (lhs) == 0;
281  }
282 
283  // operator!=
284  // ~~~~~~~~~~
285  template <typename PointerType1, typename PointerType2>
286  inline bool operator!= (sstring_view<PointerType1> const & lhs,
287  sstring_view<PointerType2> const & rhs) noexcept {
288  return !operator== (lhs, rhs);
289  }
290  template <typename PointerType, typename StringType>
291  inline bool operator!= (sstring_view<PointerType> const & lhs,
292  StringType const & rhs) noexcept {
293  return !operator== (lhs, rhs);
294  }
295  template <typename StringType, typename PointerType>
296  inline bool operator!= (StringType const & lhs,
297  sstring_view<PointerType> const & rhs) noexcept {
298  return !operator== (lhs, rhs);
299  }
300 
301  // operator>=
302  // ~~~~~~~~~~
303  template <typename PointerType1, typename PointerType2>
304  inline bool operator>= (sstring_view<PointerType1> const & lhs,
305  sstring_view<PointerType2> const & rhs) noexcept {
306  return lhs.compare (rhs) >= 0;
307  }
308  template <typename PointerType, typename StringType>
309  inline bool operator>= (sstring_view<PointerType> const & lhs,
310  StringType const & rhs) noexcept {
311  return lhs.compare (rhs) >= 0;
312  }
313  template <typename StringType, typename PointerType>
314  inline bool operator>= (StringType const & lhs,
315  sstring_view<PointerType> const & rhs) noexcept {
316  return rhs.compare (lhs) <= 0;
317  }
318 
319  // operator>
320  // ~~~~~~~~~
321  template <typename PointerType1, typename PointerType2>
322  inline bool operator> (sstring_view<PointerType1> const & lhs,
323  sstring_view<PointerType2> const & rhs) noexcept {
324  return lhs.compare (rhs) > 0;
325  }
326  template <typename PointerType, typename StringType>
327  inline bool operator> (sstring_view<PointerType> const & lhs, StringType const & rhs) noexcept {
328  return lhs.compare (rhs) > 0;
329  }
330  template <typename StringType, typename PointerType>
331  inline bool operator> (StringType const & lhs, sstring_view<PointerType> const & rhs) noexcept {
332  return rhs.compare (lhs) < 0;
333  }
334 
335  // operator<=
336  // ~~~~~~~~~~
337  template <typename PointerType1, typename PointerType2>
338  inline bool operator<= (sstring_view<PointerType1> const & lhs,
339  sstring_view<PointerType2> const & rhs) noexcept {
340  return lhs.compare (rhs) <= 0;
341  }
342  template <typename PointerType, typename StringType>
343  inline bool operator<= (sstring_view<PointerType> const & lhs,
344  StringType const & rhs) noexcept {
345  return lhs.compare (rhs) <= 0;
346  }
347  template <typename StringType, typename PointerType>
348  inline bool operator<= (StringType const & lhs,
349  sstring_view<PointerType> const & rhs) noexcept {
350  return rhs.compare (lhs) >= 0;
351  }
352 
353  // operator<
354  // ~~~~~~~~~
355  template <typename PointerType1, typename PointerType2>
356  inline bool operator< (sstring_view<PointerType1> const & lhs,
357  sstring_view<PointerType2> const & rhs) noexcept {
358  return lhs.compare (rhs) < 0;
359  }
360  template <typename PointerType, typename StringType>
361  inline bool operator< (sstring_view<PointerType> const & lhs, StringType const & rhs) noexcept {
362  return lhs.compare (rhs) < 0;
363  }
364  template <typename StringType, typename PointerType>
365  inline bool operator< (StringType const & lhs, sstring_view<PointerType> const & rhs) noexcept {
366  return rhs.compare (lhs) > 0;
367  }
368 
369  // operator <<
370  // ~~~~~~~~~~~
371  template <typename OStream, typename PointerType>
372  inline OStream & operator<< (OStream & os, sstring_view<PointerType> const & str) {
373  using ustreamsize = std::make_unsigned<std::streamsize>::type;
374  constexpr auto max =
375  static_cast<ustreamsize> (std::numeric_limits<std::streamsize>::max ());
376  auto const size = std::min (str.length (), max);
377  os.write (str.data (), static_cast<std::streamsize> (size));
378  return os;
379  }
380 
381 
385 
386  //* _ _ _ _ *
387  //* _ __ __ _| |_____ _____| |_ _ _(_)_ _ __ _ __ _(_)_____ __ __ *
388  //* | ' \/ _` | / / -_) (_-<_-< _| '_| | ' \/ _` | \ V / / -_) V V / *
389  //* |_|_|_\__,_|_\_\___| /__/__/\__|_| |_|_||_\__, | \_/|_\___|\_/\_/ *
390  //* |___/ *
391  template <typename ValueType>
393  make_shared_sstring_view (std::shared_ptr<ValueType> const & ptr, std::size_t length) {
394  return {ptr, length};
395  }
396 
397  shared_sstring_view make_shared_sstring_view (std::string const & str);
398  shared_sstring_view make_shared_sstring_view (gsl::czstring str);
399 
400  template <typename ValueType>
402  make_unique_sstring_view (std::unique_ptr<ValueType> ptr, std::size_t length) {
403  return {std::move (ptr), length};
404  }
405 
406  template <std::ptrdiff_t Extent>
407  inline raw_sstring_view make_sstring_view (gsl::span<char const, Extent> const & span) {
408  PSTORE_ASSERT (span.size () >= 0);
409  return {span.data (), unsigned_cast (span.size ())};
410  }
411  inline raw_sstring_view make_sstring_view (char const * const ptr, std::size_t const length) {
412  return {ptr, length};
413  }
414  raw_sstring_view make_sstring_view (gsl::czstring str);
415  inline raw_sstring_view make_sstring_view (std::string const & str) {
416  return {str.data (), str.length ()};
417  }
418 
419 } // namespace pstore
420 
421 namespace std {
422 
423  template <typename StringType>
424  struct equal_to<::pstore::sstring_view<StringType>> {
425  template <typename S1, typename S2>
426  bool operator() (S1 const & x, S2 const & y) const {
427  return x == y;
428  }
429  };
430 
431  template <typename StringType>
432  struct hash<::pstore::sstring_view<StringType>> {
433  size_t operator() (::pstore::sstring_view<StringType> const & str) const {
434  return static_cast<size_t> (
435  ::pstore::fnv_64a_buf (::pstore::gsl::make_span (str.begin (), str.end ())));
436  }
437  };
438 
439 } // namespace std
440 
441 #endif // PSTORE_ADT_SSTRING_VIEW_HPP
Definition: sstring_view.hpp:41
Definition: gsl.hpp:58
Definition: chunked_sequence.hpp:607
unsigned_cast() (and its runtime-checked version) allow for simple integral unsigned casts...
transaction< transaction_lock > begin(database &db, transaction_lock &lock)
Creates a new transaction. Every operation performed on a transaction instance can be potentially und...
Definition: transaction.hpp:311
Definition: sstring_view.hpp:82
Definition: sstring_view.hpp:70
Definition: print.cpp:18
sstring_view< gsl::czstring > substr(size_type pos=0, size_type const n=npos) const
Returns a view of the substring [pos, pos + rcount), where rcount is the smaller of n and size() - po...
Definition: sstring_view.hpp:204
const_iterator iterator
Because sstring_view refers to a constant sequence, iterator and const_iterator are the same type...
Definition: sstring_view.hpp:126
Definition: nonpod2.cpp:40
size_type find(value_type ch, size_type pos=0) const noexcept
Finds the first occurrence of ch in this view, starting at position pos.
Definition: sstring_view.hpp:213
Definition: sstring_view.hpp:113
Implements a prefix-style variable-length integer.