string.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2007 Marc Boris Duerner
3  * Copyright (C) 2011 Tommi Maekitalo
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * As a special exception, you may use this file as part of a free
11  * software library without restriction. Specifically, if other files
12  * instantiate templates or use macros or inline functions from this
13  * file, or you compile this file and link it with other files to
14  * produce an executable, this file does not by itself cause the
15  * resulting executable to be covered by the GNU General Public
16  * License. This exception does not however invalidate any other
17  * reasons why the executable file might be covered by the GNU Library
18  * General Public License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28  */
29 
30 #ifndef CXXTOOLS_STRING_H
31 #define CXXTOOLS_STRING_H
32 
33 #include <cxxtools/char.h>
34 
35 #include <string>
36 #include <iterator>
37 #include <stdexcept>
38 #include <iosfwd>
39 
40 #include <cxxtools/config.h>
41 
42 namespace std {
43 
47 template <>
48 class basic_string< cxxtools::Char > {
49  public:
51  typedef size_t size_type;
52  typedef char_traits< cxxtools::Char > traits_type;
53  typedef std::allocator<cxxtools::Char> allocator_type;
54  typedef allocator_type::difference_type difference_type;
55  typedef allocator_type::reference reference;
56  typedef allocator_type::const_reference const_reference;
57  typedef allocator_type::pointer pointer;
58  typedef allocator_type::const_pointer const_pointer;
59  typedef value_type* iterator;
60  typedef const value_type* const_iterator;
61 
62 #if defined(HAVE_REVERSE_ITERATOR)
63  typedef std::reverse_iterator<iterator> reverse_iterator;
64  typedef const std::reverse_iterator<const_iterator> const_reverse_iterator;
65 # define HAVE_STRING_REVERSE_ITERATOR
66 #elif defined(HAVE_REVERSE_ITERATOR_4)
67  typedef std::reverse_iterator<iterator, difference_type, value_type, pointer, reference> reverse_iterator;
68  typedef std::reverse_iterator<const_iterator, difference_type, value_type, pointer, reference> const_reverse_iterator;
69 # define HAVE_STRING_REVERSE_ITERATOR
70 #endif
71 
72  static const size_type npos = static_cast<size_type>(-1);
73 
74  public:
75  explicit basic_string( const allocator_type& a = allocator_type());
76 
77  basic_string(const cxxtools::Char* str, const allocator_type& a = allocator_type());
78 
79  basic_string(const wchar_t* str, const allocator_type& a = allocator_type());
80 
81  basic_string(const wchar_t* str, size_type n, const allocator_type& a = allocator_type());
82 
83  explicit basic_string(const std::string& str, const allocator_type& a = allocator_type());
84 
85  explicit basic_string(const char* str, const allocator_type& a = allocator_type());
86 
87  basic_string(const char* str, size_type n, const allocator_type& a = allocator_type());
88 
89  basic_string(const cxxtools::Char* str, size_type n, const allocator_type& a = allocator_type());
90 
91  basic_string(size_type n, cxxtools::Char c, const allocator_type& a = allocator_type());
92 
93  basic_string(const basic_string& str);
94 
95  basic_string(const basic_string& str, const allocator_type& a);
96 
97  basic_string(const basic_string& str, size_type pos, const allocator_type& a = allocator_type());
98 
99  basic_string(const basic_string& str, size_type pos, size_type n, const allocator_type& a = allocator_type());
100 
101  basic_string(const cxxtools::Char* begin, const cxxtools::Char* end, const allocator_type& a = allocator_type());
102 
103  template <typename InputIterator>
104  basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type());
105 
106 #if __cplusplus >= 201103L
107 
108  basic_string(basic_string&& str) noexcept;
109 
110  basic_string& operator=(basic_string&& str);
111 
112 #endif
113 
114  ~basic_string();
115 
116  public:
118  { return privdata_rw(); }
119 
121  { return privdata_rw() + length(); }
122 
124  { return privdata_ro(); }
125 
127  { return privdata_ro() + length(); }
128 
129 #ifdef HAVE_STRING_REVERSE_ITERATOR
130  reverse_iterator rbegin()
131  { return reverse_iterator( this->end() ); }
132 
133  reverse_iterator rend()
134  { return reverse_iterator( this->begin() ); }
135 
136  const_reverse_iterator rbegin() const
137  { return const_reverse_iterator( this->end() ); }
138 
139  const_reverse_iterator rend() const
140  { return const_reverse_iterator( this->begin() ); }
141 #endif
142 
143  reference operator[](size_type n)
144  { return privdata_rw()[n]; }
145 
146  const_reference operator[](size_type n) const
147  { return privdata_ro()[n]; }
148 
150  { return privdata_rw()[n]; }
151 
153  { return privdata_ro()[n]; }
154 
155  public:
156  void push_back(cxxtools::Char ch)
157  { this->append(1, ch); }
158 
159  void resize( size_t n, cxxtools::Char ch = value_type() );
160 
161  void reserve(size_t n = 0);
162 
163  void swap(basic_string& str);
164 
165  allocator_type get_allocator() const
166  { return _data; }
167 
168  size_type copy(cxxtools::Char* a, size_type n, size_type pos = 0) const;
169 
170  basic_string substr(size_type pos, size_type n) const
171  { return basic_string(*this, pos, n); }
172 
173  basic_string substr(size_type pos = 0) const
174  { return basic_string(*this, pos); }
175 
176  public:
177  size_type length() const
178  { return isShortString() ? shortStringLength() : longStringLength(); }
179 
180  size_type size() const
181  { return length(); }
182 
183  bool empty() const
184  { return length() == 0; }
185 
186  size_type max_size() const
187  { return ( size_type(-1) / sizeof(cxxtools::Char) ) - 1; }
188 
189  size_type capacity() const
190  { return isShortString() ? shortStringCapacity() : longStringCapacity(); }
191 
192  const cxxtools::Char* data() const
193  { return privdata_ro(); }
194 
195  const cxxtools::Char* c_str() const
196  { return privdata_ro(); }
197 
198  basic_string& assign(const basic_string& str);
199 
200  basic_string& assign(const basic_string& str, size_type pos, size_type n);
201 
202  basic_string& assign(const string& str);
203 
204  basic_string& assign(const string& str, size_type pos, size_type n);
205 
206  basic_string& assign(const wchar_t* str);
207 
208  basic_string& assign(const wchar_t* str, size_type n);
209 
210  basic_string& assign(const cxxtools::Char* str);
211 
212  basic_string& assign(const cxxtools::Char* str, size_type length);
213 
214  basic_string& assign(const char* str);
215 
216  basic_string& assign(const char* str, size_type length);
217 
218  basic_string& assign(size_type n, cxxtools::Char c);
219 
220  template <typename InputIterator>
221  basic_string& assign(InputIterator begin, InputIterator end);
222 
223  basic_string& append(const cxxtools::Char* str);
224 
225  basic_string& append(const cxxtools::Char* str, size_type n);
226 
227  basic_string& append(size_type n, cxxtools::Char ch);
228 
229  basic_string& append(const basic_string& str);
230 
231  basic_string& append(const basic_string& str, size_type pos, size_type n);
232 
233  template <typename InputIterator>
234  basic_string& append(InputIterator begin, InputIterator end);
235 
236  basic_string& append(const cxxtools::Char* begin, const cxxtools::Char* end);
237 
238  basic_string& insert(size_type pos, const cxxtools::Char* str);
239 
240  basic_string& insert(size_type pos, const cxxtools::Char* str, size_type n);
241 
242  basic_string& insert(size_type pos, size_type n, cxxtools::Char ch);
243 
244  basic_string& insert(size_type pos, const basic_string& str);
245 
246  basic_string& insert(size_type pos, const basic_string& str, size_type pos2, size_type n);
247 
248  basic_string& insert(iterator p, cxxtools::Char ch);
249 
250  basic_string& insert(iterator p, size_type n, cxxtools::Char ch);
251 
252  // unimplemented
253  //template <typename InputIterator>
254  //basic_string& insert(iterator p, InputIterator first, InputIterator last);
255 
256  void clear()
257  { setLength(0); }
258 
259  basic_string& erase(size_type pos = 0, size_type n = npos);
260 
261  iterator erase(iterator pos);
262 
263  iterator erase(iterator first, iterator last);
264 
265  basic_string& replace(size_type pos, size_type n, const cxxtools::Char* str);
266 
267  basic_string& replace(size_type pos, size_type n, const cxxtools::Char* str, size_type n2);
268 
269  basic_string& replace(size_type pos, size_type n, size_type n2, cxxtools::Char ch);
270 
271  basic_string& replace(size_type pos, size_type n, const basic_string& str);
272 
273  basic_string& replace(size_type pos, size_type n, const basic_string& str, size_type pos2, size_type n2);
274 
275  basic_string& replace(iterator i1, iterator i2, const cxxtools::Char* str);
276 
277  basic_string& replace(iterator i1, iterator i2, const cxxtools::Char* str, size_type n);
278 
279  basic_string& replace(iterator i1, iterator i2, size_type n, cxxtools::Char ch);
280 
281  basic_string& replace(iterator i1, iterator i2, const basic_string& str);
282 
283  //template<InputIterator>
284  //basic_string& replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2);
285 
286  int compare(const basic_string& str) const;
287 
288  int compare(const cxxtools::Char* str) const;
289 
290  int compare(const cxxtools::Char* str, size_type n) const;
291 
292  int compare(const wchar_t* str) const;
293 
294  int compare(const wchar_t* str, size_type n) const;
295 
296  int compare(const std::string& str) const
297  { return compare(str.data(), str.length()); }
298 
299  int compare(const char* str) const;
300 
301  int compare(const char* str, size_type n) const;
302 
303  int compare(size_type pos, size_type n, const basic_string& str) const;
304 
305  int compare(size_type pos, size_type n, const basic_string& str, size_type pos2, size_type n2) const;
306 
307  int compare(size_type pos, size_type n, const cxxtools::Char* str) const;
308 
309  int compare(size_type pos, size_type n, const cxxtools::Char* str, size_type n2) const;
310 
311  size_type find(const basic_string& str, size_type pos = 0) const;
312 
313  size_type find(const cxxtools::Char* str, size_type pos, size_type n) const;
314 
315  size_type find(const cxxtools::Char* str, size_type pos = 0) const;
316 //
317  size_type find(cxxtools::Char ch, size_type pos = 0) const;
318 
319  size_type rfind(const basic_string& str, size_type pos = npos) const;
320 
321  size_type rfind(const cxxtools::Char* str, size_type pos, size_type n) const;
322 
323  size_type rfind(const cxxtools::Char* str, size_type pos = npos) const;
324 
325  size_type rfind(cxxtools::Char ch, size_type pos = npos) const;
326 
327  size_type find_first_of(const basic_string& str, size_type pos = 0) const
328  { return this->find_first_of( str.data(), pos, str.size() ); }
329 
330  size_type find_first_of(const cxxtools::Char* s, size_type pos, size_type n) const;
331 
332  size_type find_first_of(const cxxtools::Char* str, size_type pos = 0) const
333  { return this->find_first_of( str, pos, traits_type::length(str) ); }
334 
335  size_type find_first_of(const cxxtools::Char ch, size_type pos = 0) const
336  { return this->find(ch, pos); }
337 
338  size_type find_last_of(const basic_string& str, size_type pos = npos) const
339  { return this->find_last_of( str.data(), pos, str.size() ); }
340 
341  size_type find_last_of(const cxxtools::Char* s, size_type pos, size_type n) const;
342 
343  size_type find_last_of(const cxxtools::Char* str, size_type pos = npos) const
344  { return this->find_last_of( str, pos, traits_type::length(str) ); }
345 
346  size_type find_last_of(const cxxtools::Char ch, size_type pos = npos) const
347  { return this->rfind(ch, pos); }
348 
349  size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
350  { return this->find_first_not_of( str.data(), pos, str.size() ); }
351 
352  size_type find_first_not_of(const cxxtools::Char* s, size_type pos, size_type n) const;
353 
354  size_type find_first_not_of(const cxxtools::Char* str, size_type pos = 0) const
355  {
356  // requires_string(str);
357  return this->find_first_not_of( str, pos, traits_type::length(str) );
358  }
359 
360  size_type find_first_not_of(const cxxtools::Char ch, size_type pos = 0) const;
361 
362  size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
363  { return this->find_last_not_of( str.data(), pos, str.size() ); }
364 
365  size_type find_last_not_of(const cxxtools::Char* tok, size_type pos, size_type n) const;
366 
367  size_type find_last_not_of(const cxxtools::Char* str, size_type pos = npos) const
368  {
369  //requires_string(s);
370  return this->find_last_not_of( str, pos, traits_type::length(str) );
371  }
372 
373  // untested
374  size_type find_last_not_of(cxxtools::Char ch, size_type pos = npos) const;
375 
376  public:
377  std::string narrow(char dfault = '?') const;
378 
379  static basic_string widen(const char* str);
380 
381  static basic_string widen(const std::string& str);
382 
383  template <typename OutIterT>
384  OutIterT toUtf16(OutIterT to) const;
385 
386  template <typename InIterT>
387  static basic_string fromUtf16(InIterT from, InIterT fromEnd);
388 
389  public:
390  basic_string& operator=(const basic_string& str)
391  { return this->assign(str); }
392 
393  basic_string& operator=(const string& str)
394  { return this->assign(str); }
395 
396  basic_string& operator=(const char* str)
397  { return this->assign(str); }
398 
399  basic_string& operator=(const cxxtools::Char* str)
400  { return this->assign(str); }
401 
402  basic_string& operator=(cxxtools::Char c)
403  { return this->assign(1, c); }
404 
405  basic_string& operator+=(const basic_string& str)
406  { return this->append(str); }
407 
408  basic_string& operator+=(const cxxtools::Char* str)
409  { return this->append(str); }
410 
411  basic_string& operator+=(cxxtools::Char c)
412  { return this->append(1, c); }
413 
414  private:
415  struct Ptr
416  {
417  cxxtools::Char* _begin;
418  cxxtools::Char* _end;
419  cxxtools::Char* _capacity;
420  };
421 
422  static const unsigned _minN = (sizeof(Ptr) / sizeof(uint32_t)) + 1;
423  static const unsigned _shortStringSize = _minN < 8 ? 8 : _minN;
424 
425  struct Data : public allocator_type
426  {
427  Data(const allocator_type& a)
428  : allocator_type(a)
429  {
430  u.shortdata[0] = 0;
431  u.shortdata[_shortStringSize - 1] = _shortStringSize - 1;
432  }
433 
434  union
435  {
436  Ptr ptr;
437  uint32_t shortdata[_shortStringSize];
438  } u;
439 
440  } _data;
441 
442  private:
443  const cxxtools::Char* privdata_ro() const
444  { return isShortString() ? shortStringData() : longStringData(); }
445  cxxtools::Char* privdata_rw()
446  { return isShortString() ? shortStringData() : longStringData(); }
447 
448  void privreserve(size_t n);
449 
450  bool isShortString() const { return shortStringMagic() != 0xffff; }
451  void markLongString() { shortStringMagic() = 0xffff; }
452  const cxxtools::Char* shortStringData() const { return reinterpret_cast<const cxxtools::Char*>(&_data.u.shortdata[0]); }
453  cxxtools::Char* shortStringData() { return reinterpret_cast<cxxtools::Char*>(&_data.u.shortdata[0]); }
454  uint32_t shortStringMagic() const { return _data.u.shortdata[_shortStringSize - 1]; }
455  uint32_t& shortStringMagic() { return _data.u.shortdata[_shortStringSize - 1]; }
456  size_type shortStringLength() const { return _shortStringSize - 1 - shortStringMagic(); }
457  size_type shortStringCapacity() const { return _shortStringSize - 1; }
458  void setShortStringLength(size_type n)
459  {
460  shortStringData()[n] = cxxtools::Char::null();
461  shortStringMagic() = static_cast<uint32_t>(_shortStringSize - n - 1);
462  }
463  void shortStringAssign(const cxxtools::Char* str, size_type n)
464  {
465  traits_type::copy(shortStringData(), str, n);
466  shortStringData()[n] = cxxtools::Char::null();
467  shortStringMagic() = static_cast<uint32_t>(_shortStringSize - n - 1);
468  }
469  void shortStringAssign(const wchar_t* str, size_type n)
470  {
471  for (size_type nn = 0; nn < n; ++nn)
472  shortStringData()[nn] = str[nn];
473  shortStringData()[n] = cxxtools::Char::null();
474  shortStringMagic() = static_cast<uint32_t>(_shortStringSize - n - 1);
475  }
476 
477  const cxxtools::Char* longStringData() const { return _data.u.ptr._begin; }
478  cxxtools::Char* longStringData() { return _data.u.ptr._begin; }
479  size_type longStringLength() const { return _data.u.ptr._end - _data.u.ptr._begin; }
480  size_type longStringCapacity() const { return _data.u.ptr._capacity - _data.u.ptr._begin; }
481  void setLength(size_type n)
482  {
483  if (isShortString())
484  setShortStringLength(n);
485  else
486  {
487  _data.u.ptr._end = _data.u.ptr._begin + n;
488  _data.u.ptr._begin[n] = cxxtools::Char::null();
489  }
490  }
491  };
492 
494  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
495 
497  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
498 
500  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
501 
503  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
504 
506  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
507 
508  // operator ==
510  { return a.compare(b) == 0; }
511 
513  { return b.compare(a) == 0; }
514 
516  { return a.compare(b) == 0; }
517 
518  inline bool operator==(const basic_string<cxxtools::Char>& a, const wchar_t* b)
519  { return a.compare(b) == 0; }
520 
521  inline bool operator==(const wchar_t* b, const basic_string<cxxtools::Char>& a)
522  { return a.compare(b) == 0; }
523 
524  inline bool operator==(const basic_string<cxxtools::Char>& a, const char* b)
525  { return a.compare(b) == 0; }
526 
527  inline bool operator==(const char* b, const basic_string<cxxtools::Char>& a)
528  { return a.compare(b) == 0; }
529 
530  inline bool operator==(const basic_string<cxxtools::Char>& a, const std::string& b)
531  { return a.compare(b) == 0; }
532 
533  inline bool operator==(const std::string& b, const basic_string<cxxtools::Char>& a)
534  { return a.compare(b) == 0; }
535 
536  // operator !=
538  { return a.compare(b) != 0; }
539 
541  { return b.compare(a) != 0; }
542 
544  { return a.compare(b) != 0; }
545 
546  inline bool operator!=(const basic_string<cxxtools::Char>& a, const wchar_t* b)
547  { return a.compare(b) != 0; }
548 
549  // operator <
550  inline bool operator<(const basic_string<cxxtools::Char>& a, const basic_string<cxxtools::Char>& b)
551  { return a.compare(b) < 0; }
552 
553  inline bool operator<(const cxxtools::Char* a, const basic_string<cxxtools::Char>& b)
554  { return b.compare(a) > 0; }
555 
556  inline bool operator<(const basic_string<cxxtools::Char>& a, const cxxtools::Char* b)
557  { return a.compare(b) < 0; }
558 
559  inline bool operator<(const basic_string<cxxtools::Char>& a, const wchar_t* b)
560  { return a.compare(b) < 0; }
561 
562  // operator >
564  { return a.compare(b) > 0; }
565 
566  inline bool operator>(const cxxtools::Char* a, const basic_string<cxxtools::Char>& b)
567  { return b.compare(a) < 0; }
568 
569  inline bool operator>(const basic_string<cxxtools::Char>& a, const cxxtools::Char* b)
570  { return a.compare(b) > 0; }
571 
572  inline bool operator>(const basic_string<cxxtools::Char>& a, const wchar_t* b)
573  { return a.compare(b) > 0; }
574 
575  ostream& operator<< (ostream& out, const basic_string<cxxtools::Char>& str);
576 
577 } // namespace std
578 
579 
580 namespace cxxtools {
581 
586 
587 }
588 
589 // Include the implementation header
590 #include <cxxtools/string.tpp>
591 
592 #endif