JSON Voorhees
Killer JSON for C++
string_view.hpp
Go to the documentation of this file.
1 /** \file jsonv/detail/string_view.hpp
2  * The JsonVoorhees implementation of string_view. You should not include this directly; instead, prefer including
3  * \c jsonv/string_view.hpp and manipulating \c JSONV_STRING_REF_TYPE and \c JSONV_STRING_REF_INCLUDE.
4  *
5  * Copyright (c) 2014 by Travis Gockel. All rights reserved.
6  *
7  * This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
8  * as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
9  * version.
10  *
11  * \author Travis Gockel (travis@gockelhut.com)
12 **/
13 #ifndef __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
14 #define __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
15 
16 #include <jsonv/config.hpp>
17 
18 #include <algorithm>
19 #include <cstddef>
20 #include <cstring>
21 #include <iterator>
22 #include <ostream>
23 #include <stdexcept>
24 
25 namespace jsonv
26 {
27 namespace detail
28 {
29 
30 /** A non-owning reference to an \c std::string, as proposed to the C++ Standard Committee by Jeffrey Yasskin in N3921
31  * (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3921.html). Unlike the one proposed, this is not templated
32  * over the \c char type, as this project only deals with UTF-8 encoded strings.
33 **/
35 {
36 public:
37  using value_type = char;
38  using pointer = const value_type*;
39  using reference = const value_type&;
40  using const_reference = const value_type&;
41  using iterator = pointer;
42  using const_iterator = pointer;
43  using reverse_iterator = std::reverse_iterator<iterator>;
44  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
45  using size_type = std::size_t;
46  using difference_type = std::ptrdiff_t;
47 
48  static constexpr size_type npos = size_type(~0);
49 
50 public:
51  constexpr string_view() noexcept :
52  _base(nullptr),
53  _length(0)
54  { }
55 
56  string_view(pointer p) noexcept :
57  _base(p),
58  _length(std::strlen(p))
59  { }
60 
61  constexpr string_view(pointer p, size_type len) noexcept :
62  _base(p),
63  _length(len)
64  { }
65 
66  template <typename UAllocator>
67  string_view(const std::basic_string<value_type, std::char_traits<value_type>, UAllocator>& src)
68  noexcept(noexcept(src.data()) && noexcept(src.length())):
69  _base(src.data()),
70  _length(src.length())
71  { }
72 
73  string_view(const string_view&) noexcept = default;
74  string_view& operator=(const string_view&) noexcept = default;
75 
76  template <typename UAllocator>
77  explicit operator std::basic_string<value_type, std::char_traits<value_type>, UAllocator>() const
78  {
79  return std::basic_string<value_type, std::char_traits<value_type>, UAllocator>(_base, _length);
80  }
81 
82  #ifdef _MSC_VER
83  // MSVC 14 CTP 5 has issues picking up templated cast operators, so provide this one for the sake of convenience
84  explicit operator std::string() const
85  {
86  return std::string(_base, _length);
87  }
88  #endif
89 
90  constexpr size_type size() const noexcept { return _length; }
91  constexpr size_type max_size() const noexcept { return _length; }
92  constexpr size_type length() const noexcept { return _length; }
93 
94  constexpr bool empty() const noexcept { return _length == 0; }
95 
96  constexpr const_reference operator[](size_type idx) const { return _base[idx]; }
97  const_reference at(size_type idx) const
98  {
99  if (idx < _length)
100  return _base[idx];
101  else
102  throw std::out_of_range("jsonv::string_view::at");
103  }
104 
105  constexpr const_reference front() const { return _base[0]; }
106  constexpr const_reference back() const { return _base[_length - 1]; }
107 
108  constexpr pointer data() const { return _base; }
109 
110  constexpr const_iterator begin() const { return _base; }
111  constexpr const_iterator cbegin() const { return _base; }
112  constexpr const_iterator end() const { return _base + _length; }
113  constexpr const_iterator cend() const { return _base + _length; }
114 
115  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
116  const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
117  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
118  const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
119 
120  void clear()
121  {
122  _base = nullptr;
123  _length = 0;
124  }
125 
126  void remove_prefix(size_type n)
127  {
128  if (n <= _length)
129  {
130  _base += n;
131  _length -= n;
132  }
133  else
134  {
135  throw std::range_error("jsonv::string_view::remove_prefix");
136  }
137  }
138 
139  void remove_suffix(size_type n)
140  {
141  if (n <= _length)
142  {
143  _length -= n;
144  }
145  else
146  {
147  throw std::range_error("jsonv::string_view::remove_prefix");
148  }
149  }
150 
151  string_view substr(size_type idx, size_type count = npos) const
152  {
153  count = count == npos ? (_length - idx) : count;
154  if (idx + count <= _length)
155  return string_view(_base + idx, count);
156  else
157  throw std::range_error("jsonv::string_view::substr");
158  }
159 
160  bool starts_with(value_type val) const
161  {
162  return !empty() && front() == val;
163  }
164 
165  bool starts_with(const string_view& sub) const
166  {
167  return sub.length() <= length() && std::equal(sub.begin(), sub.end(), begin());
168  }
169 
170  bool ends_with(value_type val) const
171  {
172  return !empty() && back() == val;
173  }
174 
175  bool ends_with(const string_view& sub) const
176  {
177  return sub.length() <= length() && std::equal(sub.rbegin(), sub.rend(), rbegin());
178  }
179 
180  size_type find(const string_view& sub) const
181  {
182  auto iter = std::search(begin(), end(), sub.begin(), sub.end());
183  return iter == end() ? npos : std::distance(begin(), iter);
184  }
185 
186  size_type find(value_type val) const
187  {
188  auto iter = std::find(begin(), end(), val);
189  return iter == end() ? npos : std::distance(begin(), iter);
190  }
191 
192  size_type rfind(const string_view& sub) const
193  {
194  auto iter = std::search(rbegin(), rend(), sub.rbegin(), sub.rend());
195  return iter == rend() ? npos : std::distance(iter, rend());
196  }
197 
198  size_type rfind(value_type val) const
199  {
200  auto iter = std::find(rbegin(), rend(), val);
201  return iter == rend() ? npos : std::distance(iter, rend());
202  }
203 
204  size_type find_first_of(value_type val) const
205  {
206  return find(val);
207  }
208 
209  size_type find_first_of(const string_view& chars) const
210  {
211  auto iter = std::find_first_of(begin(), end(), chars.begin(), chars.end());
212  return iter == end() ? npos : std::distance(begin(), iter);
213  }
214 
215  size_type find_first_not_of(value_type val) const
216  {
217  auto iter = std::find_if(begin(), end(), [val] (value_type x) { return val != x; });
218  return iter == end() ? npos : std::distance(begin(), iter);
219  }
220 
221  size_type find_first_not_of(const string_view& chars) const
222  {
223  auto iter = std::find_if(begin(), end(),
224  [&chars] (value_type x)
225  {
226  return chars.find(x) == npos;
227  }
228  );
229  return iter == end() ? npos : std::distance(begin(), iter);
230  }
231 
232  size_type find_last_of(value_type val) const
233  {
234  return rfind(val);
235  }
236 
237  size_type find_last_of(const string_view& chars) const
238  {
239  auto iter = std::find_first_of(rbegin(), rend(), chars.begin(), chars.end());
240  return iter == rend() ? npos : std::distance(iter, rend());
241  }
242 
243  size_type find_last_not_of(value_type val) const
244  {
245  auto iter = std::find_if(rbegin(), rend(), [val] (value_type x) { return val != x; });
246  return iter == rend() ? npos : std::distance(iter, rend());
247  }
248 
249  size_type find_last_not_of(const string_view& chars) const
250  {
251  auto iter = std::find_if(rbegin(), rend(),
252  [&chars] (value_type x)
253  {
254  return chars.find(x) == npos;
255  }
256  );
257  return iter == rend() ? npos : std::distance(iter, rend());
258  }
259 
260  bool operator==(const string_view& other) const
261  {
262  return _length == other._length
263  && (_base == other._base || std::equal(begin(), end(), other.begin()));
264  }
265 
266  bool operator!=(const string_view& other) const
267  {
268  return !operator==(other);
269  }
270 
271  bool operator<(const string_view& other) const
272  {
273  return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
274  }
275 
276  bool operator<=(const string_view& other) const
277  {
278  return !(other < *this);
279  }
280 
281  bool operator>(const string_view& other) const
282  {
283  return other < *this;
284  }
285 
286  bool operator>=(const string_view& other) const
287  {
288  return !(*this < other);
289  }
290 
291  friend std::ostream& operator<<(std::ostream& os, const string_view& self)
292  {
293  os.write(self.begin(), self.size());
294  return os;
295  }
296 
297 private:
298  pointer _base;
299  size_type _length;
300 };
301 
302 template <typename UAllocator>
303 bool operator==(const std::basic_string<UAllocator> lhs, const string_view& rhs)
304 {
305  return string_view(lhs) == rhs;
306 }
307 
308 template <typename UAllocator>
309 bool operator!=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
310 {
311  return string_view(lhs) != rhs;
312 }
313 
314 template <typename UAllocator>
315 bool operator<(const std::basic_string<UAllocator> lhs, const string_view& rhs)
316 {
317  return string_view(lhs) < rhs;
318 }
319 
320 template <typename UAllocator>
321 bool operator<=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
322 {
323  return string_view(lhs) <= rhs;
324 }
325 
326 template <typename UAllocator>
327 bool operator>(const std::basic_string<UAllocator> lhs, const string_view& rhs)
328 {
329  return string_view(lhs) > rhs;
330 }
331 
332 template <typename UAllocator>
333 bool operator>=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
334 {
335  return string_view(lhs) >= rhs;
336 }
337 
338 }
339 }
340 
341 #endif/*__JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__*/
Copyright (c) 2014-2019 by Travis Gockel.
A non-owning reference to an std::string, as proposed to the C++ Standard Committee by Jeffrey Yasski...
Definition: string_view.hpp:34