KSS Utility
C++ general utilities
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
substring.hpp
Go to the documentation of this file.
1 
2 
13 #ifndef kssutil_substring_hpp
14 #define kssutil_substring_hpp
15 
16 #include <algorithm>
17 #include <memory>
18 #include <stdexcept>
19 #include <string>
20 
21 #include "add_rel_ops.hpp"
22 #include "utility.hpp"
23 
24 namespace kss { namespace util { namespace strings {
25 
42  template <class Char,
43  class Traits = std::char_traits<Char>,
44  class Alloc = std::allocator<Char>>
45  class SubString : public kss::util::AddRelOps<SubString<Char, Traits, Alloc>> {
46  public:
47 
48  using size_type = typename std::basic_string<Char>::size_type;
49  using allocator_type = Alloc;
50  using pointer = typename Alloc::pointer;
51  using const_pointer = typename Alloc::const_pointer;
52  using value_type = Char;
53 
59  SubString(std::basic_string<Char, Traits, Alloc>& str,
60  size_type i,
61  size_type n = std::basic_string<Char, Traits, Alloc>::npos)
62  : _str(str), _allocator(str.get_allocator()), _cstr(nullptr)
63  {
64  size_type len = str.length();
65  _i = (i >= len ? std::basic_string<Char, Traits, Alloc>::npos : i);
66  _n = std::min(n, len - _i);
67 
68  // postconditions
69  constexpr auto npos = std::basic_string<Char, Traits, Alloc>::npos;
70  if (!(_i == i || i == npos)
71  || !(_n <= n)
72  || !(_cstr == nullptr))
73  {
74  _KSSUTIL_POSTCONDITIONS_FAILED
75  }
76  }
77 
83  SubString(std::basic_string<Char, Traits, Alloc>& str,
84  const std::basic_string<Char, Traits, Alloc>& str2,
85  size_type i = 0)
86  : _str(str), _allocator(str.get_allocator()), _cstr(nullptr)
87  {
88  _i = str.find(str2, i);
89  if (_i != std::basic_string<Char, Traits, Alloc>::npos) {
90  _n = str2.length();
91  }
92 
93  // postconditions
94  if (!(_i >= i)
95  || !(_n == str2.length() || _n == 0)
96  || !(_cstr == nullptr))
97  {
98  _KSSUTIL_POSTCONDITIONS_FAILED
99  }
100  }
101 
105  ~SubString() noexcept {
106  freeCStr();
107  }
108 
113  SubString& operator=(const std::basic_string<Char, Traits, Alloc>& str) {
114  return assign(str.data(), str.length());
115  }
116 
122  return assign(str.data(), _n);
123  }
124 
132  return assign(cptr, std::char_traits<Char>::length(cptr));
133  }
134 
140  SubString& operator=(Char ch) {
141  return assign(&ch, size_type(1));
142  }
143 
149  operator std::basic_string<Char, Traits, Alloc>() const {
150  if (_i >= _str.length() || _n == 0) {
151  return std::basic_string<Char, Traits, Alloc>();
152  }
153  else {
154  return std::basic_string<Char, Traits, Alloc>(_str, _i, _n, _allocator);
155  }
156  }
157 
170  if (_cstr == nullptr && _i < _str.length()) {
171  // may already be copied, if not make the copy
173  obj->_cstr = obj->_allocator.allocate(_n + 1);
174  if (_n > 0) {
175  std::uninitialized_copy(data(), data()+_n, obj->_cstr);
176  }
177  obj->_allocator.construct(obj->_cstr+_n, Char(0));
178  }
179  return _cstr;
180  }
181 
188  const_pointer data() const noexcept {
189  return (_i >= _str.length() ? nullptr : _str.data() + _i);
190  }
191 
195  size_type size() const noexcept { return _n; }
196 
200  bool empty() const noexcept { return (_n == 0); }
201 
205  bool operator==(const SubString& rhs) noexcept {
206  if (this == &rhs) {
207  return true;
208  }
209  if (size() != rhs.size()) {
210  return false;
211  }
212  return (Traits::compare(data(), rhs.data(), size()) == 0);
213  }
214 
215  bool operator<(const SubString& rhs) noexcept {
216  if (this == &rhs) {
217  return false;
218  }
219  size_type n = std::min(size(), rhs.size());
220  int retval = Traits::compare(data(), rhs.data(), n);
221  if (retval < 0) {
222  return true;
223  }
224  else if (retval > 0) {
225  return false;
226  }
227  return (size() < rhs.size());
228  }
229 
230  private:
231  std::basic_string<Char>& _str;
232  size_type _i = std::basic_string<Char, Traits, Alloc>::npos;
233  size_type _n = 0;
234  Alloc _allocator;
235  pointer _cstr = nullptr;
236 
237  void freeCStr() {
238  if (_cstr != nullptr) {
239  for (pointer p = _cstr; p < _cstr+_n+1; ++p) {
240  _allocator.destroy(p);
241  }
242  _allocator.deallocate(_cstr, _n+1);
243  _cstr = nullptr;
244  }
245 
246  // postconditions
247  if (!(_cstr == nullptr)) {
248  _KSSUTIL_POSTCONDITIONS_FAILED
249  }
250  }
251 
252  SubString& assign(const const_pointer ptr, size_type new_n) {
253  // preconditions
254  if (!(ptr != nullptr)) {
255  _KSSUTIL_POSTCONDITIONS_FAILED
256  }
257 
258  if (_i >= _str.length()) {
259  throw std::out_of_range("Substring is out of range of the original.");
260  }
261 
262  freeCStr();
263  _str.replace(_i, _n, ptr, new_n);
264  _n = new_n;
265  return *this;
266  }
267  };
268 
272  template <class Char, class Traits, class Alloc>
274  const std::basic_string<Char, Traits, Alloc>& rhs) noexcept
275  {
276  if (lhs.size() != rhs.size()) {
277  return false;
278  }
279  return (Traits::compare(lhs.data(), rhs.data(), lhs.size()) == 0);
280  }
281 
282  template <class Char, class Traits, class Alloc>
283  inline bool operator==(const std::basic_string<Char, Traits, Alloc>& lhs,
284  const SubString<Char, Traits, Alloc>& rhs) noexcept
285  {
286  return (rhs == lhs);
287  }
288 
289  template <class Char, class Traits, class Alloc>
290  bool operator<(const SubString<Char, Traits, Alloc>& lhs,
291  const std::basic_string<Char, Traits, Alloc>& rhs) noexcept
292  {
293  typename SubString<Char, Traits, Alloc>::size_type n = std::min(lhs.size(), rhs.size());
294  int retval = Traits::compare(lhs.data(), rhs.data(), n);
295  if (retval < 0) {
296  return true;
297  }
298  else if (retval > 0) {
299  return false;
300  }
301  return (lhs.size() < rhs.size());
302  }
303 
304  template <class Char, class Traits, class Alloc>
305  bool operator<(const std::basic_string<Char, Traits, Alloc>& lhs,
306  const SubString<Char, Traits, Alloc>& rhs) noexcept
307  {
308  typename SubString<Char, Traits, Alloc>::size_type n = std::min(lhs.size(), rhs.size());
309  int retval = Traits::compare(lhs.data(), rhs.data(), n);
310  if (retval < 0) {
311  return true;
312  }
313  else if (retval > 0) {
314  return false;
315  }
316  return (lhs.size() < rhs.size());
317  }
318 
323  template <class Char, class Traits, class Alloc>
325  typename SubString<Char, Traits, Alloc>::const_pointer rhs) noexcept
326  {
328  Traits::length(rhs);
329  if (lhs.size() != rhsSize) {
330  return false;
331  }
332  return (Traits::compare(lhs.data(), rhs, rhsSize) == 0);
333  }
334 
335  template <class Char, class Traits, class Alloc>
337  const SubString<Char, Traits, Alloc>& rhs) noexcept
338  {
339  return (rhs == lhs);
340  }
341 
342  template <class Char, class Traits, class Alloc>
343  bool operator<(const SubString<Char, Traits, Alloc>& lhs,
344  typename SubString<Char, Traits, Alloc>::const_pointer rhs) noexcept
345  {
346  typename SubString<Char, Traits, Alloc>::size_type rhsSize = Traits::length(rhs);
348  std::min(lhs.size(), rhsSize);
349  int retval = Traits::compare(lhs.data(), rhs, n);
350  if (retval < 0) {
351  return true;
352  }
353  else if (retval > 0) {
354  return false;
355  }
356  return (lhs.size() < rhsSize);
357  }
358 
359  template <class Char, class Traits, class Alloc>
360  bool operator<(typename SubString<Char, Traits, Alloc>::const_pointer lhs,
361  const SubString<Char, Traits, Alloc>& rhs) noexcept
362  {
363  typename SubString<Char, Traits, Alloc>::size_type rhsSize = Traits::length(rhs);
364  typename SubString<Char, Traits, Alloc>::size_type n = std::min(lhs.size(), rhsSize);
365  int retval = Traits::compare(lhs, rhs.data(), n);
366  if (retval < 0) {
367  return true;
368  }
369  else if (retval > 0) {
370  return false;
371  }
372  return (lhs.size() < rhsSize);
373  }
374 
375 
379  typedef SubString<char, std::char_traits<char>, std::allocator<char> > substring_t;
380 
384  typedef SubString<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wsubstring_t;
385 
386 
387 }}}
388 
389 #endif
SubString(std::basic_string< Char, Traits, Alloc > &str, size_type i, size_type n=std::basic_string< Char, Traits, Alloc >::npos)
Definition: substring.hpp:59
typename Alloc::const_pointer const_pointer
Definition: substring.hpp:51
size_type size() const noexcept
Definition: substring.hpp:195
SubString & operator=(const SubString &str)
Definition: substring.hpp:121
bool operator==(const SubString< Char, Traits, Alloc > &lhs, const std::basic_string< Char, Traits, Alloc > &rhs) noexcept
Definition: substring.hpp:273
SubString & operator=(const_pointer cptr)
Definition: substring.hpp:131
bool empty() const noexcept
Definition: substring.hpp:200
Write-through substring.
Definition: substring.hpp:45
typename Alloc::pointer pointer
Definition: substring.hpp:50
typename std::basic_string< Char >::size_type size_type
Definition: substring.hpp:48
bool operator==(const SubString &rhs) noexcept
Definition: substring.hpp:205
Auto-generation of relational operators.
const_pointer data() const noexcept
Definition: substring.hpp:188
const_pointer c_str() const
Definition: substring.hpp:169
SubString< char, std::char_traits< char >, std::allocator< char > > substring_t
Definition: substring.hpp:379
SubString(std::basic_string< Char, Traits, Alloc > &str, const std::basic_string< Char, Traits, Alloc > &str2, size_type i=0)
Definition: substring.hpp:83
SubString & operator=(Char ch)
Definition: substring.hpp:140
Add the operators !=, &lt;=, &gt; and &gt;= assuming the existance of == and &lt;.
Definition: add_rel_ops.hpp:31
bool operator<(const SubString &rhs) noexcept
Definition: substring.hpp:215
SubString & operator=(const std::basic_string< Char, Traits, Alloc > &str)
Definition: substring.hpp:113
SubString< wchar_t, std::char_traits< wchar_t >, std::allocator< wchar_t > > wsubstring_t
Definition: substring.hpp:384