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/api.h>
34 #include <cxxtools/char.h>
35 
36 #include <string>
37 #include <iterator>
38 #include <stdexcept>
39 #include <iosfwd>
40 
41 #include <cxxtools/config.h>
42 
43 namespace std {
44 
48 template <>
49 class CXXTOOLS_API basic_string< cxxtools::Char > {
50  public:
52  typedef size_t size_type;
53  typedef char_traits< cxxtools::Char > traits_type;
54  typedef std::allocator<cxxtools::Char> allocator_type;
55  typedef allocator_type::difference_type difference_type;
56  typedef allocator_type::reference reference;
57  typedef allocator_type::const_reference const_reference;
58  typedef allocator_type::pointer pointer;
59  typedef allocator_type::const_pointer const_pointer;
60  typedef value_type* iterator;
61  typedef const value_type* const_iterator;
62 
63 #if defined(HAVE_REVERSE_ITERATOR)
64  typedef std::reverse_iterator<iterator> reverse_iterator;
65  typedef const std::reverse_iterator<const_iterator> const_reverse_iterator;
66 # define HAVE_STRING_REVERSE_ITERATOR
67 #elif defined(HAVE_REVERSE_ITERATOR_4)
68  typedef std::reverse_iterator<iterator, difference_type, value_type, pointer, reference> reverse_iterator;
69  typedef std::reverse_iterator<const_iterator, difference_type, value_type, pointer, reference> const_reverse_iterator;
70 # define HAVE_STRING_REVERSE_ITERATOR
71 #endif
72 
73  static const size_type npos = static_cast<size_type>(-1);
74 
75  public:
76  explicit basic_string( const allocator_type& a = allocator_type());
77 
78  basic_string(const cxxtools::Char* str, const allocator_type& a = allocator_type());
79 
80  basic_string(const wchar_t* str, const allocator_type& a = allocator_type());
81 
82  basic_string(const wchar_t* str, size_type n, const allocator_type& a = allocator_type());
83 
84  explicit basic_string(const std::string& str, const allocator_type& a = allocator_type());
85 
86  explicit basic_string(const char* str, const allocator_type& a = allocator_type());
87 
88  basic_string(const char* str, size_type n, const allocator_type& a = allocator_type());
89 
90  basic_string(const cxxtools::Char* str, size_type n, const allocator_type& a = allocator_type());
91 
92  basic_string(size_type n, cxxtools::Char c, const allocator_type& a = allocator_type());
93 
94  basic_string(const basic_string& str);
95 
96  basic_string(const basic_string& str, const allocator_type& a);
97 
98  basic_string(const basic_string& str, size_type pos, const allocator_type& a = allocator_type());
99 
100  basic_string(const basic_string& str, size_type pos, size_type n, const allocator_type& a = allocator_type());
101 
102  basic_string(const cxxtools::Char* begin, const cxxtools::Char* end, const allocator_type& a = allocator_type());
103 
104  template <typename InputIterator>
105  basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type());
106 
107  ~basic_string();
108 
109  public:
110  iterator begin()
111  { return privdata_rw(); }
112 
113  iterator end()
114  { return privdata_rw() + length(); }
115 
116  const_iterator begin() const
117  { return privdata_ro(); }
118 
119  const_iterator end() const
120  { return privdata_ro() + length(); }
121 
122 #ifdef HAVE_STRING_REVERSE_ITERATOR
123  reverse_iterator rbegin()
124  { return reverse_iterator( this->end() ); }
125 
126  reverse_iterator rend()
127  { return reverse_iterator( this->begin() ); }
128 
129  const_reverse_iterator rbegin() const
130  { return const_reverse_iterator( this->end() ); }
131 
132  const_reverse_iterator rend() const
133  { return const_reverse_iterator( this->begin() ); }
134 #endif
135 
136  reference operator[](size_type n)
137  { return privdata_rw()[n]; }
138 
139  const_reference operator[](size_type n) const
140  { return privdata_ro()[n]; }
141 
143  { return privdata_rw()[n]; }
144 
146  { return privdata_ro()[n]; }
147 
148  public:
149  void push_back(cxxtools::Char ch)
150  { this->append(1, ch); }
151 
152  void resize( size_t n, cxxtools::Char ch = value_type() );
153 
154  void reserve(size_t n = 0);
155 
156  void swap(basic_string& str);
157 
158  allocator_type get_allocator() const
159  { return _data; }
160 
161  size_type copy(cxxtools::Char* a, size_type n, size_type pos = 0) const;
162 
163  basic_string substr(size_type pos, size_type n) const
164  { return basic_string(*this, pos, n); }
165 
166  basic_string substr(size_type pos = 0) const
167  { return basic_string(*this, pos); }
168 
169  public:
170  size_type length() const
171  { return isShortString() ? shortStringLength() : longStringLength(); }
172 
173  size_type size() const
174  { return length(); }
175 
176  bool empty() const
177  { return length() == 0; }
178 
179  size_type max_size() const
180  { return ( size_type(-1) / sizeof(cxxtools::Char) ) - 1; }
181 
182  size_type capacity() const
183  { return isShortString() ? shortStringCapacity() : longStringCapacity(); }
184 
185  const cxxtools::Char* data() const
186  { return privdata_ro(); }
187 
188  const cxxtools::Char* c_str() const
189  { return privdata_ro(); }
190 
191  basic_string& assign(const basic_string& str);
192 
193  basic_string& assign(const basic_string& str, size_type pos, size_type n);
194 
195  basic_string& assign(const string& str);
196 
197  basic_string& assign(const string& str, size_type pos, size_type n);
198 
199  basic_string& assign(const wchar_t* str);
200 
201  basic_string& assign(const wchar_t* str, size_type n);
202 
203  basic_string& assign(const cxxtools::Char* str);
204 
205  basic_string& assign(const cxxtools::Char* str, size_type length);
206 
207  basic_string& assign(const char* str);
208 
209  basic_string& assign(const char* str, size_type length);
210 
211  basic_string& assign(size_type n, cxxtools::Char c);
212 
213  template <typename InputIterator>
214  basic_string& assign(InputIterator begin, InputIterator end);
215 
216  basic_string& append(const cxxtools::Char* str);
217 
218  basic_string& append(const cxxtools::Char* str, size_type n);
219 
220  basic_string& append(size_type n, cxxtools::Char ch);
221 
222  basic_string& append(const basic_string& str);
223 
224  basic_string& append(const basic_string& str, size_type pos, size_type n);
225 
226  template <typename InputIterator>
227  basic_string& append(InputIterator begin, InputIterator end);
228 
229  basic_string& append(const cxxtools::Char* begin, const cxxtools::Char* end);
230 
231  basic_string& insert(size_type pos, const cxxtools::Char* str);
232 
233  basic_string& insert(size_type pos, const cxxtools::Char* str, size_type n);
234 
235  basic_string& insert(size_type pos, size_type n, cxxtools::Char ch);
236 
237  basic_string& insert(size_type pos, const basic_string& str);
238 
239  basic_string& insert(size_type pos, const basic_string& str, size_type pos2, size_type n);
240 
241  basic_string& insert(iterator p, cxxtools::Char ch);
242 
243  basic_string& insert(iterator p, size_type n, cxxtools::Char ch);
244 
245  // unimplemented
246  //template <typename InputIterator>
247  //basic_string& insert(iterator p, InputIterator first, InputIterator last);
248 
249  void clear()
250  { setLength(0); }
251 
252  basic_string& erase(size_type pos = 0, size_type n = npos);
253 
254  iterator erase(iterator pos);
255 
256  iterator erase(iterator first, iterator last);
257 
258  basic_string& replace(size_type pos, size_type n, const cxxtools::Char* str);
259 
260  basic_string& replace(size_type pos, size_type n, const cxxtools::Char* str, size_type n2);
261 
262  basic_string& replace(size_type pos, size_type n, size_type n2, cxxtools::Char ch);
263 
264  basic_string& replace(size_type pos, size_type n, const basic_string& str);
265 
266  basic_string& replace(size_type pos, size_type n, const basic_string& str, size_type pos2, size_type n2);
267 
268  basic_string& replace(iterator i1, iterator i2, const cxxtools::Char* str);
269 
270  basic_string& replace(iterator i1, iterator i2, const cxxtools::Char* str, size_type n);
271 
272  basic_string& replace(iterator i1, iterator i2, size_type n, cxxtools::Char ch);
273 
274  basic_string& replace(iterator i1, iterator i2, const basic_string& str);
275 
276  //template<InputIterator>
277  //basic_string& replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2);
278 
279  int compare(const basic_string& str) const;
280 
281  int compare(const cxxtools::Char* str) const;
282 
283  int compare(const cxxtools::Char* str, size_type n) const;
284 
285  int compare(const wchar_t* str) const;
286 
287  int compare(const wchar_t* str, size_type n) const;
288 
289  int compare(const std::string& str) const
290  { return compare(str.data(), str.length()); }
291 
292  int compare(const char* str) const;
293 
294  int compare(const char* str, size_type n) const;
295 
296  int compare(size_type pos, size_type n, const basic_string& str) const;
297 
298  int compare(size_type pos, size_type n, const basic_string& str, size_type pos2, size_type n2) const;
299 
300  int compare(size_type pos, size_type n, const cxxtools::Char* str) const;
301 
302  int compare(size_type pos, size_type n, const cxxtools::Char* str, size_type n2) const;
303 
304  size_type find(const basic_string& str, size_type pos = 0) const;
305 
306  size_type find(const cxxtools::Char* str, size_type pos, size_type n) const;
307 
308  size_type find(const cxxtools::Char* str, size_type pos = 0) const;
309 //
310  size_type find(cxxtools::Char ch, size_type pos = 0) const;
311 
312  size_type rfind(const basic_string& str, size_type pos = npos) const;
313 
314  size_type rfind(const cxxtools::Char* str, size_type pos, size_type n) const;
315 
316  size_type rfind(const cxxtools::Char* str, size_type pos = npos) const;
317 
318  size_type rfind(cxxtools::Char ch, size_type pos = npos) const;
319 
320  size_type find_first_of(const basic_string& str, size_type pos = 0) const
321  { return this->find_first_of( str.data(), pos, str.size() ); }
322 
323  size_type find_first_of(const cxxtools::Char* s, size_type pos, size_type n) const;
324 
325  size_type find_first_of(const cxxtools::Char* str, size_type pos = 0) const
326  { return this->find_first_of( str, pos, traits_type::length(str) ); }
327 
328  size_type find_first_of(const cxxtools::Char ch, size_type pos = 0) const
329  { return this->find(ch, pos); }
330 
331  size_type find_last_of(const basic_string& str, size_type pos = npos) const
332  { return this->find_last_of( str.data(), pos, str.size() ); }
333 
334  size_type find_last_of(const cxxtools::Char* s, size_type pos, size_type n) const;
335 
336  size_type find_last_of(const cxxtools::Char* str, size_type pos = npos) const
337  { return this->find_last_of( str, pos, traits_type::length(str) ); }
338 
339  size_type find_last_of(const cxxtools::Char ch, size_type pos = npos) const
340  { return this->rfind(ch, pos); }
341 
342  size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
343  { return this->find_first_not_of( str.data(), pos, str.size() ); }
344 
345  size_type find_first_not_of(const cxxtools::Char* s, size_type pos, size_type n) const;
346 
347  size_type find_first_not_of(const cxxtools::Char* str, size_type pos = 0) const
348  {
349  // requires_string(str);
350  return this->find_first_not_of( str, pos, traits_type::length(str) );
351  }
352 
353  size_type find_first_not_of(const cxxtools::Char ch, size_type pos = 0) const;
354 
355  size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
356  { return this->find_last_not_of( str.data(), pos, str.size() ); }
357 
358  size_type find_last_not_of(const cxxtools::Char* tok, size_type pos, size_type n) const;
359 
360  size_type find_last_not_of(const cxxtools::Char* str, size_type pos = npos) const
361  {
362  //requires_string(s);
363  return this->find_last_not_of( str, pos, traits_type::length(str) );
364  }
365 
366  // untested
367  size_type find_last_not_of(cxxtools::Char ch, size_type pos = npos) const;
368 
369  public:
370  std::string narrow(char dfault = '?') const;
371 
372  static basic_string widen(const char* str);
373 
374  static basic_string widen(const std::string& str);
375 
376  template <typename OutIterT>
377  OutIterT toUtf16(OutIterT to) const;
378 
379  template <typename InIterT>
380  static basic_string fromUtf16(InIterT from, InIterT fromEnd);
381 
382  public:
383  basic_string& operator=(const basic_string& str)
384  { return this->assign(str); }
385 
386  basic_string& operator=(const string& str)
387  { return this->assign(str); }
388 
389  basic_string& operator=(const char* str)
390  { return this->assign(str); }
391 
392  basic_string& operator=(const cxxtools::Char* str)
393  { return this->assign(str); }
394 
395  basic_string& operator=(cxxtools::Char c)
396  { return this->assign(1, c); }
397 
398  basic_string& operator+=(const basic_string& str)
399  { return this->append(str); }
400 
401  basic_string& operator+=(const cxxtools::Char* str)
402  { return this->append(str); }
403 
404  basic_string& operator+=(cxxtools::Char c)
405  { return this->append(1, c); }
406 
407  private:
408  struct Ptr
409  {
410  cxxtools::Char* _begin;
411  cxxtools::Char* _end;
412  cxxtools::Char* _capacity;
413  };
414 
415  static const unsigned _minN = (sizeof(Ptr) / sizeof(uint32_t)) + 1;
416  static const unsigned _shortStringSize = _minN < 8 ? 8 : _minN;
417 
418  struct Data : public allocator_type
419  {
420  Data(const allocator_type& a)
421  : allocator_type(a)
422  {
423  u.shortdata[0] = 0;
424  u.shortdata[_shortStringSize - 1] = _shortStringSize - 1;
425  }
426 
427  union
428  {
429  Ptr ptr;
430  uint32_t shortdata[_shortStringSize];
431  } u;
432 
433  } _data;
434 
435  private:
436  const cxxtools::Char* privdata_ro() const
437  { return isShortString() ? shortStringData() : longStringData(); }
438  cxxtools::Char* privdata_rw()
439  { return isShortString() ? shortStringData() : longStringData(); }
440 
441  void privreserve(size_t n);
442 
443  bool isShortString() const { return shortStringMagic() != 0xffff; }
444  void markLongString() { shortStringMagic() = 0xffff; }
445  const cxxtools::Char* shortStringData() const { return reinterpret_cast<const cxxtools::Char*>(&_data.u.shortdata[0]); }
446  cxxtools::Char* shortStringData() { return reinterpret_cast<cxxtools::Char*>(&_data.u.shortdata[0]); }
447  uint32_t shortStringMagic() const { return _data.u.shortdata[_shortStringSize - 1]; }
448  uint32_t& shortStringMagic() { return _data.u.shortdata[_shortStringSize - 1]; }
449  size_type shortStringLength() const { return _shortStringSize - 1 - shortStringMagic(); }
450  size_type shortStringCapacity() const { return _shortStringSize - 1; }
451  void setShortStringLength(size_type n) { shortStringData()[n] = cxxtools::Char::null(); shortStringMagic() = _shortStringSize - n - 1; }
452  void shortStringAssign(const cxxtools::Char* str, size_type n)
453  {
454  traits_type::copy(shortStringData(), str, n);
455  shortStringData()[n] = cxxtools::Char::null();
456  shortStringMagic() = _shortStringSize - n - 1;
457  }
458  void shortStringAssign(const wchar_t* str, size_type n)
459  {
460  for (size_type nn = 0; nn < n; ++nn)
461  shortStringData()[nn] = str[nn];
462  shortStringData()[n] = cxxtools::Char::null();
463  shortStringMagic() = _shortStringSize - n - 1;
464  }
465 
466  const cxxtools::Char* longStringData() const { return _data.u.ptr._begin; }
467  cxxtools::Char* longStringData() { return _data.u.ptr._begin; }
468  size_type longStringLength() const { return _data.u.ptr._end - _data.u.ptr._begin; }
469  size_type longStringCapacity() const { return _data.u.ptr._capacity - _data.u.ptr._begin; }
470  void setLength(size_type n)
471  {
472  if (isShortString())
473  setShortStringLength(n);
474  else
475  {
476  _data.u.ptr._end = _data.u.ptr._begin + n;
477  _data.u.ptr._begin[n] = cxxtools::Char::null();
478  }
479  }
480  };
481 
483  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
484 
486  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
487 
489  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
490 
492  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
493 
495  { basic_string<cxxtools::Char> temp; temp += a; temp += b; return temp; }
496 
497  // operator ==
499  { return a.compare(b) == 0; }
500 
502  { return b.compare(a) == 0; }
503 
505  { return a.compare(b) == 0; }
506 
507  inline bool operator==(const basic_string<cxxtools::Char>& a, const wchar_t* b)
508  { return a.compare(b) == 0; }
509 
510  inline bool operator==(const wchar_t* b, const basic_string<cxxtools::Char>& a)
511  { return a.compare(b) == 0; }
512 
513  inline bool operator==(const basic_string<cxxtools::Char>& a, const char* b)
514  { return a.compare(b) == 0; }
515 
516  inline bool operator==(const char* b, const basic_string<cxxtools::Char>& a)
517  { return a.compare(b) == 0; }
518 
519  inline bool operator==(const basic_string<cxxtools::Char>& a, const std::string& b)
520  { return a.compare(b) == 0; }
521 
522  inline bool operator==(const std::string& b, const basic_string<cxxtools::Char>& a)
523  { return a.compare(b) == 0; }
524 
525  // operator !=
527  { return a.compare(b) != 0; }
528 
530  { return b.compare(a) != 0; }
531 
533  { return a.compare(b) != 0; }
534 
535  inline bool operator!=(const basic_string<cxxtools::Char>& a, const wchar_t* b)
536  { return a.compare(b) != 0; }
537 
538  // operator <
539  inline bool operator<(const basic_string<cxxtools::Char>& a, const basic_string<cxxtools::Char>& b)
540  { return a.compare(b) < 0; }
541 
542  inline bool operator<(const cxxtools::Char* a, const basic_string<cxxtools::Char>& b)
543  { return b.compare(a) > 0; }
544 
545  inline bool operator<(const basic_string<cxxtools::Char>& a, const cxxtools::Char* b)
546  { return a.compare(b) < 0; }
547 
548  inline bool operator<(const basic_string<cxxtools::Char>& a, const wchar_t* b)
549  { return a.compare(b) < 0; }
550 
551  // operator >
553  { return a.compare(b) > 0; }
554 
555  inline bool operator>(const cxxtools::Char* a, const basic_string<cxxtools::Char>& b)
556  { return b.compare(a) < 0; }
557 
558  inline bool operator>(const basic_string<cxxtools::Char>& a, const cxxtools::Char* b)
559  { return a.compare(b) > 0; }
560 
561  inline bool operator>(const basic_string<cxxtools::Char>& a, const wchar_t* b)
562  { return a.compare(b) > 0; }
563 
564  CXXTOOLS_API ostream& operator<< (ostream& out, const basic_string<cxxtools::Char>& str);
565 
566 } // namespace std
567 
568 
569 namespace cxxtools {
570 
575 
576 }
577 
578 // Include the implementation header
579 #include <cxxtools/string.tpp>
580 
581 #endif