libstdc++
rope
Go to the documentation of this file.
1 // SGI's rope class -*- C++ -*-
2 
3 // Copyright (C) 2001-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /*
26  * Copyright (c) 1997
27  * Silicon Graphics Computer Systems, Inc.
28  *
29  * Permission to use, copy, modify, distribute and sell this software
30  * and its documentation for any purpose is hereby granted without fee,
31  * provided that the above copyright notice appear in all copies and
32  * that both that copyright notice and this permission notice appear
33  * in supporting documentation. Silicon Graphics makes no
34  * representations about the suitability of this software for any
35  * purpose. It is provided "as is" without express or implied warranty.
36  */
37 
38 /** @file ext/rope
39  * This file is a GNU extension to the Standard C++ Library (possibly
40  * containing extensions from the HP/SGI STL subset).
41  */
42 
43 #ifndef _ROPE
44 #define _ROPE 1
45 
46 #pragma GCC system_header
47 
48 #include <algorithm>
49 #include <iosfwd>
50 #include <bits/stl_construct.h>
51 #include <bits/stl_uninitialized.h>
52 #include <bits/stl_function.h>
53 #include <bits/stl_numeric.h>
54 #include <bits/allocator.h>
55 #include <bits/gthr.h>
56 #include <ext/alloc_traits.h>
57 #include <tr1/functional>
58 
59 # ifdef __GC
60 # define __GC_CONST const
61 # else
62 # define __GC_CONST // constant except for deallocation
63 # endif
64 
65 #include <ext/memory> // For uninitialized_copy_n
66 
67 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
68 {
69 _GLIBCXX_BEGIN_NAMESPACE_VERSION
70 
71  namespace __detail
72  {
73  enum { _S_max_rope_depth = 45 };
74  enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
75  } // namespace __detail
76 
77  // See libstdc++/36832.
78  template<typename _ForwardIterator, typename _Allocator>
79  void
80  _Destroy_const(_ForwardIterator __first,
81  _ForwardIterator __last, _Allocator __alloc)
82  {
83  for (; __first != __last; ++__first)
84  __alloc.destroy(&*__first);
85  }
86 
87  template<typename _ForwardIterator, typename _Tp>
88  inline void
89  _Destroy_const(_ForwardIterator __first,
90  _ForwardIterator __last, std::allocator<_Tp>)
91  { std::_Destroy(__first, __last); }
92 
93  // The _S_eos function is used for those functions that
94  // convert to/from C-like strings to detect the end of the string.
95 
96  // The end-of-C-string character.
97  // This is what the draft standard says it should be.
98  template <class _CharT>
99  inline _CharT
100  _S_eos(_CharT*)
101  { return _CharT(); }
102 
103  // Test for basic character types.
104  // For basic character types leaves having a trailing eos.
105  template <class _CharT>
106  inline bool
107  _S_is_basic_char_type(_CharT*)
108  { return false; }
109 
110  template <class _CharT>
111  inline bool
112  _S_is_one_byte_char_type(_CharT*)
113  { return false; }
114 
115  inline bool
116  _S_is_basic_char_type(char*)
117  { return true; }
118 
119  inline bool
120  _S_is_one_byte_char_type(char*)
121  { return true; }
122 
123  inline bool
124  _S_is_basic_char_type(wchar_t*)
125  { return true; }
126 
127  // Store an eos iff _CharT is a basic character type.
128  // Do not reference _S_eos if it isn't.
129  template <class _CharT>
130  inline void
131  _S_cond_store_eos(_CharT&) { }
132 
133  inline void
134  _S_cond_store_eos(char& __c)
135  { __c = 0; }
136 
137  inline void
138  _S_cond_store_eos(wchar_t& __c)
139  { __c = 0; }
140 
141  // char_producers are logically functions that generate a section of
142  // a string. These can be converted to ropes. The resulting rope
143  // invokes the char_producer on demand. This allows, for example,
144  // files to be viewed as ropes without reading the entire file.
145  template <class _CharT>
146  class char_producer
147  {
148  public:
149  virtual ~char_producer() { }
150 
151  virtual void
152  operator()(std::size_t __start_pos, std::size_t __len,
153  _CharT* __buffer) = 0;
154  // Buffer should really be an arbitrary output iterator.
155  // That way we could flatten directly into an ostream, etc.
156  // This is thoroughly impossible, since iterator types don't
157  // have runtime descriptions.
158  };
159 
160  // Sequence buffers:
161  //
162  // Sequence must provide an append operation that appends an
163  // array to the sequence. Sequence buffers are useful only if
164  // appending an entire array is cheaper than appending element by element.
165  // This is true for many string representations.
166  // This should perhaps inherit from ostream<sequence::value_type>
167  // and be implemented correspondingly, so that they can be used
168  // for formatted. For the sake of portability, we don't do this yet.
169  //
170  // For now, sequence buffers behave as output iterators. But they also
171  // behave a little like basic_ostringstream<sequence::value_type> and a
172  // little like containers.
173 
174 // Ignore warnings about std::iterator.
175 #pragma GCC diagnostic push
176 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
177 
178  template<class _Sequence, std::size_t _Buf_sz = 100>
179  class sequence_buffer
180  : public std::iterator<std::output_iterator_tag, void, void, void, void>
181  {
182  public:
183  typedef typename _Sequence::value_type value_type;
184  protected:
185  _Sequence* _M_prefix;
186  value_type _M_buffer[_Buf_sz];
187  std::size_t _M_buf_count;
188  public:
189 
190  void
191  flush()
192  {
193  _M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);
194  _M_buf_count = 0;
195  }
196 
197  ~sequence_buffer()
198  { flush(); }
199 
200  sequence_buffer()
201  : _M_prefix(0), _M_buf_count(0) { }
202 
203  sequence_buffer(const sequence_buffer& __x)
204  {
205  _M_prefix = __x._M_prefix;
206  _M_buf_count = __x._M_buf_count;
207  std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
208  }
209 
210  // Non-const "copy" modifies the parameter - yuck
211  sequence_buffer(sequence_buffer& __x)
212  {
213  __x.flush();
214  _M_prefix = __x._M_prefix;
215  _M_buf_count = 0;
216  }
217 
218  sequence_buffer(_Sequence& __s)
219  : _M_prefix(&__s), _M_buf_count(0) { }
220 
221  // Non-const "copy" modifies the parameter - yuck
222  sequence_buffer&
223  operator=(sequence_buffer& __x)
224  {
225  __x.flush();
226  _M_prefix = __x._M_prefix;
227  _M_buf_count = 0;
228  return *this;
229  }
230 
231  sequence_buffer&
232  operator=(const sequence_buffer& __x)
233  {
234  _M_prefix = __x._M_prefix;
235  _M_buf_count = __x._M_buf_count;
236  std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
237  return *this;
238  }
239 
240 #if __cplusplus >= 201103L
241  sequence_buffer(sequence_buffer&& __x) : sequence_buffer(__x) { }
242  sequence_buffer& operator=(sequence_buffer&& __x) { return *this = __x; }
243 #endif
244 
245  void
246  push_back(value_type __x)
247  {
248  if (_M_buf_count < _Buf_sz)
249  {
250  _M_buffer[_M_buf_count] = __x;
251  ++_M_buf_count;
252  }
253  else
254  {
255  flush();
256  _M_buffer[0] = __x;
257  _M_buf_count = 1;
258  }
259  }
260 
261  void
262  append(value_type* __s, std::size_t __len)
263  {
264  if (__len + _M_buf_count <= _Buf_sz)
265  {
266  std::size_t __i = _M_buf_count;
267  for (std::size_t __j = 0; __j < __len; __i++, __j++)
268  _M_buffer[__i] = __s[__j];
269  _M_buf_count += __len;
270  }
271  else if (0 == _M_buf_count)
272  _M_prefix->append(__s, __s + __len);
273  else
274  {
275  flush();
276  append(__s, __len);
277  }
278  }
279 
280  sequence_buffer&
281  write(value_type* __s, std::size_t __len)
282  {
283  append(__s, __len);
284  return *this;
285  }
286 
287  sequence_buffer&
288  put(value_type __x)
289  {
290  push_back(__x);
291  return *this;
292  }
293 
294  sequence_buffer&
295  operator=(const value_type& __rhs)
296  {
297  push_back(__rhs);
298  return *this;
299  }
300 
301  sequence_buffer&
302  operator*()
303  { return *this; }
304 
305  sequence_buffer&
306  operator++()
307  { return *this; }
308 
309  sequence_buffer
310  operator++(int)
311  { return *this; }
312  };
313 #pragma GCC diagnostic pop
314 
315  // The following should be treated as private, at least for now.
316  template<class _CharT>
317  class _Rope_char_consumer
318  {
319  public:
320  // If we had member templates, these should not be virtual.
321  // For now we need to use run-time parametrization where
322  // compile-time would do. Hence this should all be private
323  // for now.
324  // The symmetry with char_producer is accidental and temporary.
325  virtual ~_Rope_char_consumer() { }
326 
327  virtual bool
328  operator()(const _CharT* __buffer, std::size_t __len) = 0;
329  };
330 
331  // First a lot of forward declarations. The standard seems to require
332  // much stricter "declaration before use" than many of the implementations
333  // that preceded it.
334  template<class _CharT, class _Alloc = std::allocator<_CharT> >
335  class rope;
336 
337  template<class _CharT, class _Alloc>
338  struct _Rope_RopeConcatenation;
339 
340  template<class _CharT, class _Alloc>
341  struct _Rope_RopeLeaf;
342 
343  template<class _CharT, class _Alloc>
344  struct _Rope_RopeFunction;
345 
346  template<class _CharT, class _Alloc>
347  struct _Rope_RopeSubstring;
348 
349  template<class _CharT, class _Alloc>
350  class _Rope_iterator;
351 
352  template<class _CharT, class _Alloc>
353  class _Rope_const_iterator;
354 
355  template<class _CharT, class _Alloc>
356  class _Rope_char_ref_proxy;
357 
358  template<class _CharT, class _Alloc>
359  class _Rope_char_ptr_proxy;
360 
361  template<class _CharT, class _Alloc>
362  bool
363  operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
364  const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);
365 
366  template<class _CharT, class _Alloc>
367  _Rope_const_iterator<_CharT, _Alloc>
368  operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
369  std::ptrdiff_t __n);
370 
371  template<class _CharT, class _Alloc>
372  _Rope_const_iterator<_CharT, _Alloc>
373  operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
374  std::ptrdiff_t __n);
375 
376  template<class _CharT, class _Alloc>
377  _Rope_const_iterator<_CharT, _Alloc>
378  operator+(std::ptrdiff_t __n,
379  const _Rope_const_iterator<_CharT, _Alloc>& __x);
380 
381  template<class _CharT, class _Alloc>
382  bool
383  operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
384  const _Rope_const_iterator<_CharT, _Alloc>& __y);
385 
386  template<class _CharT, class _Alloc>
387  bool
388  operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
389  const _Rope_const_iterator<_CharT, _Alloc>& __y);
390 
391  template<class _CharT, class _Alloc>
392  std::ptrdiff_t
393  operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
394  const _Rope_const_iterator<_CharT, _Alloc>& __y);
395 
396  template<class _CharT, class _Alloc>
397  _Rope_iterator<_CharT, _Alloc>
398  operator-(const _Rope_iterator<_CharT, _Alloc>& __x, std::ptrdiff_t __n);
399 
400  template<class _CharT, class _Alloc>
401  _Rope_iterator<_CharT, _Alloc>
402  operator+(const _Rope_iterator<_CharT, _Alloc>& __x, std::ptrdiff_t __n);
403 
404  template<class _CharT, class _Alloc>
405  _Rope_iterator<_CharT, _Alloc>
406  operator+(std::ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);
407 
408  template<class _CharT, class _Alloc>
409  bool
410  operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
411  const _Rope_iterator<_CharT, _Alloc>& __y);
412 
413  template<class _CharT, class _Alloc>
414  bool
415  operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
416  const _Rope_iterator<_CharT, _Alloc>& __y);
417 
418  template<class _CharT, class _Alloc>
419  std::ptrdiff_t
420  operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
421  const _Rope_iterator<_CharT, _Alloc>& __y);
422 
423  template<class _CharT, class _Alloc>
424  rope<_CharT, _Alloc>
425  operator+(const rope<_CharT, _Alloc>& __left,
426  const rope<_CharT, _Alloc>& __right);
427 
428  template<class _CharT, class _Alloc>
429  rope<_CharT, _Alloc>
430  operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);
431 
432  template<class _CharT, class _Alloc>
433  rope<_CharT, _Alloc>
434  operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);
435 
436  // Some helpers, so we can use power on ropes.
437  // See below for why this isn't local to the implementation.
438 
439 // Ignore warnings about std::binary_function.
440 #pragma GCC diagnostic push
441 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
442  // This uses a nonstandard refcount convention.
443  // The result has refcount 0.
444  template<class _CharT, class _Alloc>
445  struct _Rope_Concat_fn
446  : public std::binary_function<rope<_CharT, _Alloc>, rope<_CharT, _Alloc>,
447  rope<_CharT, _Alloc> >
448  {
449  rope<_CharT, _Alloc>
450  operator()(const rope<_CharT, _Alloc>& __x,
451  const rope<_CharT, _Alloc>& __y)
452  { return __x + __y; }
453  };
454 #pragma GCC diagnostic pop
455 
456  template <class _CharT, class _Alloc>
457  inline rope<_CharT, _Alloc>
458  identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
459  { return rope<_CharT, _Alloc>(); }
460 
461  // Class _Refcount_Base provides a type, _RC_t, a data member,
462  // _M_ref_count, and member functions _M_incr and _M_decr, which perform
463  // atomic preincrement/predecrement. The constructor initializes
464  // _M_ref_count.
465  struct _Refcount_Base
466  {
467  // The type _RC_t
468  typedef std::size_t _RC_t;
469 
470  // The data member _M_ref_count
471  _RC_t _M_ref_count;
472 
473  // Constructor
474 #ifdef __GTHREAD_MUTEX_INIT
475  __gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT;
476 #else
477  __gthread_mutex_t _M_ref_count_lock;
478 #endif
479 
480  _Refcount_Base(_RC_t __n) : _M_ref_count(__n)
481  {
482 #ifndef __GTHREAD_MUTEX_INIT
483 #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
484  __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
485 #else
486 #error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
487 #endif
488 #endif
489  }
490 
491 #ifndef __GTHREAD_MUTEX_INIT
492  ~_Refcount_Base()
493  { __gthread_mutex_destroy(&_M_ref_count_lock); }
494 #endif
495 
496  void
497  _M_incr()
498  {
499  __gthread_mutex_lock(&_M_ref_count_lock);
500  ++_M_ref_count;
501  __gthread_mutex_unlock(&_M_ref_count_lock);
502  }
503 
504  _RC_t
505  _M_decr()
506  {
507  __gthread_mutex_lock(&_M_ref_count_lock);
508  _RC_t __tmp = --_M_ref_count;
509  __gthread_mutex_unlock(&_M_ref_count_lock);
510  return __tmp;
511  }
512  };
513 
514  //
515  // What follows should really be local to rope. Unfortunately,
516  // that doesn't work, since it makes it impossible to define generic
517  // equality on rope iterators. According to the draft standard, the
518  // template parameters for such an equality operator cannot be inferred
519  // from the occurrence of a member class as a parameter.
520  // (SGI compilers in fact allow this, but the __result wouldn't be
521  // portable.)
522  // Similarly, some of the static member functions are member functions
523  // only to avoid polluting the global namespace, and to circumvent
524  // restrictions on type inference for template functions.
525  //
526 
527  //
528  // The internal data structure for representing a rope. This is
529  // private to the implementation. A rope is really just a pointer
530  // to one of these.
531  //
532  // A few basic functions for manipulating this data structure
533  // are members of _RopeRep. Most of the more complex algorithms
534  // are implemented as rope members.
535  //
536  // Some of the static member functions of _RopeRep have identically
537  // named functions in rope that simply invoke the _RopeRep versions.
538 
539 #define __ROPE_DEFINE_ALLOCS(__a) \
540  __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \
541  typedef _Rope_RopeConcatenation<_CharT,__a> __C; \
542  __ROPE_DEFINE_ALLOC(__C,_C) \
543  typedef _Rope_RopeLeaf<_CharT,__a> __L; \
544  __ROPE_DEFINE_ALLOC(__L,_L) \
545  typedef _Rope_RopeFunction<_CharT,__a> __F; \
546  __ROPE_DEFINE_ALLOC(__F,_F) \
547  typedef _Rope_RopeSubstring<_CharT,__a> __S; \
548  __ROPE_DEFINE_ALLOC(__S,_S)
549 
550  // Internal rope nodes potentially store a copy of the allocator
551  // instance used to allocate them. This is mostly redundant.
552  // But the alternative would be to pass allocator instances around
553  // in some form to nearly all internal functions, since any pointer
554  // assignment may result in a zero reference count and thus require
555  // deallocation.
556 
557 #define __STATIC_IF_SGI_ALLOC /* not static */
558 
559  template <class _CharT, class _Alloc>
560  struct _Rope_rep_base
561  : public _Alloc
562  {
563  typedef std::size_t size_type;
564  typedef _Alloc allocator_type;
565 
566  allocator_type
567  get_allocator() const
568  { return *static_cast<const _Alloc*>(this); }
569 
570  allocator_type&
571  _M_get_allocator()
572  { return *static_cast<_Alloc*>(this); }
573 
574  const allocator_type&
575  _M_get_allocator() const
576  { return *static_cast<const _Alloc*>(this); }
577 
578  _Rope_rep_base(size_type __size, const allocator_type&)
579  : _M_size(__size) { }
580 
581  size_type _M_size;
582 
583 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
584  typedef typename \
585  __alloc_traits<_Alloc>::template rebind<_Tp>::other __name##Alloc; \
586  static _Tp* __name##_allocate(size_type __n) \
587  { return __name##Alloc().allocate(__n); } \
588  static void __name##_deallocate(_Tp *__p, size_type __n) \
589  { __name##Alloc().deallocate(__p, __n); }
590  __ROPE_DEFINE_ALLOCS(_Alloc)
591 # undef __ROPE_DEFINE_ALLOC
592  };
593 
594  template<class _CharT, class _Alloc>
595  struct _Rope_RopeRep
596  : public _Rope_rep_base<_CharT, _Alloc>
597 # ifndef __GC
598  , _Refcount_Base
599 # endif
600  {
601  public:
602  __detail::_Tag _M_tag:8;
603  bool _M_is_balanced:8;
604  unsigned char _M_depth;
605  __GC_CONST _CharT* _M_c_string;
606 #ifdef __GTHREAD_MUTEX_INIT
607  __gthread_mutex_t _M_c_string_lock = __GTHREAD_MUTEX_INIT;
608 #else
609  __gthread_mutex_t _M_c_string_lock;
610 #endif
611  /* Flattened version of string, if needed. */
612  /* typically 0. */
613  /* If it's not 0, then the memory is owned */
614  /* by this node. */
615  /* In the case of a leaf, this may point to */
616  /* the same memory as the data field. */
617  typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
618  allocator_type;
619  typedef std::size_t size_type;
620 
621  using _Rope_rep_base<_CharT, _Alloc>::get_allocator;
622  using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator;
623 
624  _Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_type __size,
625  const allocator_type& __a)
626  : _Rope_rep_base<_CharT, _Alloc>(__size, __a),
627 #ifndef __GC
628  _Refcount_Base(1),
629 #endif
630  _M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
631 #ifdef __GTHREAD_MUTEX_INIT
632  { }
633 #else
634  { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }
635  ~_Rope_RopeRep()
636  { __gthread_mutex_destroy (&_M_c_string_lock); }
637 #endif
638 #ifdef __GC
639  void
640  _M_incr () { }
641 #endif
642  static void
643  _S_free_string(__GC_CONST _CharT*, size_type __len,
644  allocator_type& __a);
645 #define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);
646  // Deallocate data section of a leaf.
647  // This shouldn't be a member function.
648  // But its hard to do anything else at the
649  // moment, because it's templatized w.r.t.
650  // an allocator.
651  // Does nothing if __GC is defined.
652 #ifndef __GC
653  void _M_free_c_string();
654  void _M_free_tree();
655  // Deallocate t. Assumes t is not 0.
656  void
657  _M_unref_nonnil()
658  {
659  if (0 == _M_decr())
660  _M_free_tree();
661  }
662 
663  void
664  _M_ref_nonnil()
665  { _M_incr(); }
666 
667  static void
668  _S_unref(_Rope_RopeRep* __t)
669  {
670  if (0 != __t)
671  __t->_M_unref_nonnil();
672  }
673 
674  static void
675  _S_ref(_Rope_RopeRep* __t)
676  {
677  if (0 != __t)
678  __t->_M_incr();
679  }
680 
681  static void
682  _S_free_if_unref(_Rope_RopeRep* __t)
683  {
684  if (0 != __t && 0 == __t->_M_ref_count)
685  __t->_M_free_tree();
686  }
687 # else /* __GC */
688  void _M_unref_nonnil() { }
689  void _M_ref_nonnil() { }
690  static void _S_unref(_Rope_RopeRep*) { }
691  static void _S_ref(_Rope_RopeRep*) { }
692  static void _S_free_if_unref(_Rope_RopeRep*) { }
693 # endif
694  protected:
695  _Rope_RopeRep&
696  operator=(const _Rope_RopeRep&);
697 
698  _Rope_RopeRep(const _Rope_RopeRep&);
699  };
700 
701  template<class _CharT, class _Alloc>
702  struct _Rope_RopeLeaf
703  : public _Rope_RopeRep<_CharT, _Alloc>
704  {
705  typedef std::size_t size_type;
706  public:
707  // Apparently needed by VC++
708  // The data fields of leaves are allocated with some
709  // extra space, to accommodate future growth and for basic
710  // character types, to hold a trailing eos character.
711  enum { _S_alloc_granularity = 8 };
712 
713  static size_type
714  _S_rounded_up_size(size_type __n)
715  {
716  size_type __size_with_eos;
717 
718  if (_S_is_basic_char_type((_CharT*)0))
719  __size_with_eos = __n + 1;
720  else
721  __size_with_eos = __n;
722 #ifdef __GC
723  return __size_with_eos;
724 #else
725  // Allow slop for in-place expansion.
726  return ((__size_with_eos + size_type(_S_alloc_granularity) - 1)
727  &~ (size_type(_S_alloc_granularity) - 1));
728 #endif
729  }
730  __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */
731  /* The allocated size is */
732  /* _S_rounded_up_size(size), except */
733  /* in the GC case, in which it */
734  /* doesn't matter. */
735  typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
736  allocator_type;
737 
738  _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_type __size,
739  const allocator_type& __a)
740  : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true,
741  __size, __a), _M_data(__d)
742  {
743  if (_S_is_basic_char_type((_CharT *)0))
744  {
745  // already eos terminated.
746  this->_M_c_string = __d;
747  }
748  }
749  // The constructor assumes that d has been allocated with
750  // the proper allocator and the properly padded size.
751  // In contrast, the destructor deallocates the data:
752 #ifndef __GC
753  ~_Rope_RopeLeaf() throw()
754  {
755  if (_M_data != this->_M_c_string)
756  this->_M_free_c_string();
757 
758  this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
759  }
760 #endif
761  protected:
762  _Rope_RopeLeaf&
763  operator=(const _Rope_RopeLeaf&);
764 
765  _Rope_RopeLeaf(const _Rope_RopeLeaf&);
766  };
767 
768  template<class _CharT, class _Alloc>
769  struct _Rope_RopeConcatenation
770  : public _Rope_RopeRep<_CharT, _Alloc>
771  {
772  public:
773  _Rope_RopeRep<_CharT, _Alloc>* _M_left;
774  _Rope_RopeRep<_CharT, _Alloc>* _M_right;
775 
776  typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
777  allocator_type;
778 
779  _Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l,
780  _Rope_RopeRep<_CharT, _Alloc>* __r,
781  const allocator_type& __a)
782  : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat,
783  std::max(__l->_M_depth,
784  __r->_M_depth) + 1,
785  false,
786  __l->_M_size + __r->_M_size, __a),
787  _M_left(__l), _M_right(__r)
788  { }
789 #ifndef __GC
790  ~_Rope_RopeConcatenation() throw()
791  {
792  this->_M_free_c_string();
793  _M_left->_M_unref_nonnil();
794  _M_right->_M_unref_nonnil();
795  }
796 #endif
797  protected:
798  _Rope_RopeConcatenation&
799  operator=(const _Rope_RopeConcatenation&);
800 
801  _Rope_RopeConcatenation(const _Rope_RopeConcatenation&);
802  };
803 
804  template<class _CharT, class _Alloc>
805  struct _Rope_RopeFunction
806  : public _Rope_RopeRep<_CharT, _Alloc>
807  {
808  public:
809  char_producer<_CharT>* _M_fn;
810 #ifndef __GC
811  bool _M_delete_when_done; // Char_producer is owned by the
812  // rope and should be explicitly
813  // deleted when the rope becomes
814  // inaccessible.
815 #else
816  // In the GC case, we either register the rope for
817  // finalization, or not. Thus the field is unnecessary;
818  // the information is stored in the collector data structures.
819  // We do need a finalization procedure to be invoked by the
820  // collector.
821  static void
822  _S_fn_finalization_proc(void * __tree, void *)
823  { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
824 #endif
825  typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
826  allocator_type;
827 
828  _Rope_RopeFunction(char_producer<_CharT>* __f, std::size_t __size,
829  bool __d, const allocator_type& __a)
830  : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a)
831  , _M_fn(__f)
832 #ifndef __GC
833  , _M_delete_when_done(__d)
834 #endif
835  {
836 #ifdef __GC
837  if (__d)
838  {
839  GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::
840  _S_fn_finalization_proc, 0, 0, 0);
841  }
842 #endif
843  }
844 #ifndef __GC
845  ~_Rope_RopeFunction() throw()
846  {
847  this->_M_free_c_string();
848  if (_M_delete_when_done)
849  delete _M_fn;
850  }
851 # endif
852  protected:
853  _Rope_RopeFunction&
854  operator=(const _Rope_RopeFunction&);
855 
856  _Rope_RopeFunction(const _Rope_RopeFunction&);
857  };
858  // Substring results are usually represented using just
859  // concatenation nodes. But in the case of very long flat ropes
860  // or ropes with a functional representation that isn't practical.
861  // In that case, we represent the __result as a special case of
862  // RopeFunction, whose char_producer points back to the rope itself.
863  // In all cases except repeated substring operations and
864  // deallocation, we treat the __result as a RopeFunction.
865  template<class _CharT, class _Alloc>
866  struct _Rope_RopeSubstring
867  : public _Rope_RopeFunction<_CharT, _Alloc>,
868  public char_producer<_CharT>
869  {
870  typedef std::size_t size_type;
871  public:
872  // XXX this whole class should be rewritten.
873  _Rope_RopeRep<_CharT,_Alloc>* _M_base; // not 0
874  size_type _M_start;
875 
876  virtual void
877  operator()(size_type __start_pos, size_type __req_len,
878  _CharT* __buffer)
879  {
880  switch(_M_base->_M_tag)
881  {
882  case __detail::_S_function:
883  case __detail::_S_substringfn:
884  {
885  char_producer<_CharT>* __fn =
886  ((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;
887  (*__fn)(__start_pos + _M_start, __req_len, __buffer);
888  }
889  break;
890  case __detail::_S_leaf:
891  {
892  __GC_CONST _CharT* __s =
893  ((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data;
894  uninitialized_copy_n(__s + __start_pos + _M_start, __req_len,
895  __buffer);
896  }
897  break;
898  default:
899  break;
900  }
901  }
902 
903  typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
904  allocator_type;
905 
906  _Rope_RopeSubstring(_Rope_RopeRep<_CharT, _Alloc>* __b, size_type __s,
907  size_type __l, const allocator_type& __a)
908  : _Rope_RopeFunction<_CharT, _Alloc>(this, __l, false, __a),
909  char_producer<_CharT>(), _M_base(__b), _M_start(__s)
910  {
911 #ifndef __GC
912  _M_base->_M_ref_nonnil();
913 #endif
914  this->_M_tag = __detail::_S_substringfn;
915  }
916  virtual ~_Rope_RopeSubstring() throw()
917  {
918 #ifndef __GC
919  _M_base->_M_unref_nonnil();
920  // _M_free_c_string(); -- done by parent class
921 #endif
922  }
923  };
924 
925  // Self-destructing pointers to Rope_rep.
926  // These are not conventional smart pointers. Their
927  // only purpose in life is to ensure that unref is called
928  // on the pointer either at normal exit or if an exception
929  // is raised. It is the caller's responsibility to
930  // adjust reference counts when these pointers are initialized
931  // or assigned to. (This convention significantly reduces
932  // the number of potentially expensive reference count
933  // updates.)
934 #ifndef __GC
935  template<class _CharT, class _Alloc>
936  struct _Rope_self_destruct_ptr
937  {
938  _Rope_RopeRep<_CharT, _Alloc>* _M_ptr;
939 
940  ~_Rope_self_destruct_ptr()
941  { _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
942 #if __cpp_exceptions
943  _Rope_self_destruct_ptr() : _M_ptr(0) { }
944 #else
945  _Rope_self_destruct_ptr() { }
946 #endif
947  _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p)
948  : _M_ptr(__p) { }
949 
950  _Rope_RopeRep<_CharT, _Alloc>&
951  operator*()
952  { return *_M_ptr; }
953 
954  _Rope_RopeRep<_CharT, _Alloc>*
955  operator->()
956  { return _M_ptr; }
957 
958  operator _Rope_RopeRep<_CharT, _Alloc>*()
959  { return _M_ptr; }
960 
961  _Rope_self_destruct_ptr&
962  operator=(_Rope_RopeRep<_CharT, _Alloc>* __x)
963  { _M_ptr = __x; return *this; }
964  };
965 #endif
966 
967  // Dereferencing a nonconst iterator has to return something
968  // that behaves almost like a reference. It's not possible to
969  // return an actual reference since assignment requires extra
970  // work. And we would get into the same problems as with the
971  // CD2 version of basic_string.
972  template<class _CharT, class _Alloc>
973  class _Rope_char_ref_proxy
974  {
975  friend class rope<_CharT, _Alloc>;
976  friend class _Rope_iterator<_CharT, _Alloc>;
977  friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
978 #ifdef __GC
979  typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
980 #else
981  typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
982 #endif
983  typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
984  typedef rope<_CharT, _Alloc> _My_rope;
985  std::size_t _M_pos;
986  _CharT _M_current;
987  bool _M_current_valid;
988  _My_rope* _M_root; // The whole rope.
989  public:
990  _Rope_char_ref_proxy(_My_rope* __r, std::size_t __p)
991  : _M_pos(__p), _M_current(), _M_current_valid(false), _M_root(__r) { }
992 
993  _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x)
994  : _M_pos(__x._M_pos), _M_current(__x._M_current),
995  _M_current_valid(false), _M_root(__x._M_root) { }
996 
997  // Don't preserve cache if the reference can outlive the
998  // expression. We claim that's not possible without calling
999  // a copy constructor or generating reference to a proxy
1000  // reference. We declare the latter to have undefined semantics.
1001  _Rope_char_ref_proxy(_My_rope* __r, std::size_t __p, _CharT __c)
1002  : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) { }
1003 
1004  inline operator _CharT () const;
1005 
1006  _Rope_char_ref_proxy&
1007  operator=(_CharT __c);
1008 
1009  _Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const;
1010 
1011  _Rope_char_ref_proxy&
1012  operator=(const _Rope_char_ref_proxy& __c)
1013  { return operator=((_CharT)__c); }
1014  };
1015 
1016  template<class _CharT, class __Alloc>
1017  inline void
1018  swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,
1019  _Rope_char_ref_proxy <_CharT, __Alloc > __b)
1020  {
1021  _CharT __tmp = __a;
1022  __a = __b;
1023  __b = __tmp;
1024  }
1025 
1026  template<class _CharT, class _Alloc>
1027  class _Rope_char_ptr_proxy
1028  {
1029  // XXX this class should be rewritten.
1030  friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1031  std::size_t _M_pos;
1032  rope<_CharT,_Alloc>* _M_root; // The whole rope.
1033  public:
1034  _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x)
1035  : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1036 
1037  _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x)
1038  : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1039 
1040  _Rope_char_ptr_proxy() { }
1041 
1042  _Rope_char_ptr_proxy(_CharT* __x)
1043  : _M_root(0), _M_pos(0) { }
1044 
1045  _Rope_char_ptr_proxy&
1046  operator=(const _Rope_char_ptr_proxy& __x)
1047  {
1048  _M_pos = __x._M_pos;
1049  _M_root = __x._M_root;
1050  return *this;
1051  }
1052 
1053  template<class _CharT2, class _Alloc2>
1054  friend bool
1055  operator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x,
1056  const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y);
1057 
1058  _Rope_char_ref_proxy<_CharT, _Alloc> operator*() const
1059  { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); }
1060  };
1061 
1062  // Rope iterators:
1063  // Unlike in the C version, we cache only part of the stack
1064  // for rope iterators, since they must be efficiently copyable.
1065  // When we run out of cache, we have to reconstruct the iterator
1066  // value.
1067  // Pointers from iterators are not included in reference counts.
1068  // Iterators are assumed to be thread private. Ropes can
1069  // be shared.
1070 
1071 // Ignore warnings about std::iterator
1072 #pragma GCC diagnostic push
1073 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1074  template<class _CharT, class _Alloc>
1075  class _Rope_iterator_base
1076  : public std::iterator<std::random_access_iterator_tag, _CharT>
1077  {
1078  friend class rope<_CharT, _Alloc>;
1079  public:
1080  typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaround
1081  typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1082  // Borland doesn't want this to be protected.
1083  protected:
1084  enum { _S_path_cache_len = 4 }; // Must be <= 9.
1085  enum { _S_iterator_buf_len = 15 };
1086  std::size_t _M_current_pos;
1087  _RopeRep* _M_root; // The whole rope.
1088  std::size_t _M_leaf_pos; // Starting position for current leaf
1089  __GC_CONST _CharT* _M_buf_start;
1090  // Buffer possibly
1091  // containing current char.
1092  __GC_CONST _CharT* _M_buf_ptr;
1093  // Pointer to current char in buffer.
1094  // != 0 ==> buffer valid.
1095  __GC_CONST _CharT* _M_buf_end;
1096  // One past __last valid char in buffer.
1097  // What follows is the path cache. We go out of our
1098  // way to make this compact.
1099  // Path_end contains the bottom section of the path from
1100  // the root to the current leaf.
1101  const _RopeRep* _M_path_end[_S_path_cache_len];
1102  int _M_leaf_index; // Last valid __pos in path_end;
1103  // _M_path_end[0] ... _M_path_end[leaf_index-1]
1104  // point to concatenation nodes.
1105  unsigned char _M_path_directions;
1106  // (path_directions >> __i) & 1 is 1
1107  // iff we got from _M_path_end[leaf_index - __i - 1]
1108  // to _M_path_end[leaf_index - __i] by going to the
1109  // __right. Assumes path_cache_len <= 9.
1110  _CharT _M_tmp_buf[_S_iterator_buf_len];
1111  // Short buffer for surrounding chars.
1112  // This is useful primarily for
1113  // RopeFunctions. We put the buffer
1114  // here to avoid locking in the
1115  // multithreaded case.
1116  // The cached path is generally assumed to be valid
1117  // only if the buffer is valid.
1118  static void _S_setbuf(_Rope_iterator_base& __x);
1119  // Set buffer contents given
1120  // path cache.
1121  static void _S_setcache(_Rope_iterator_base& __x);
1122  // Set buffer contents and
1123  // path cache.
1124  static void _S_setcache_for_incr(_Rope_iterator_base& __x);
1125  // As above, but assumes path
1126  // cache is valid for previous posn.
1127  _Rope_iterator_base() { }
1128 
1129  _Rope_iterator_base(_RopeRep* __root, std::size_t __pos)
1130  : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }
1131 
1132  void _M_incr(std::size_t __n);
1133  void _M_decr(std::size_t __n);
1134  public:
1135  std::size_t
1136  index() const
1137  { return _M_current_pos; }
1138 
1139  _Rope_iterator_base(const _Rope_iterator_base& __x)
1140  {
1141  if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf)
1142  *this = __x;
1143  else
1144  {
1145  _M_current_pos = __x._M_current_pos;
1146  _M_root = __x._M_root;
1147  _M_buf_ptr = 0;
1148  }
1149  }
1150  };
1151 #pragma GCC diagnostic pop
1152 
1153  template<class _CharT, class _Alloc>
1154  class _Rope_iterator;
1155 
1156  template<class _CharT, class _Alloc>
1157  class _Rope_const_iterator
1158  : public _Rope_iterator_base<_CharT, _Alloc>
1159  {
1160  friend class rope<_CharT, _Alloc>;
1161  protected:
1162  typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1163  // The one from the base class may not be directly visible.
1164  _Rope_const_iterator(const _RopeRep* __root, std::size_t __pos)
1165  : _Rope_iterator_base<_CharT, _Alloc>(const_cast<_RopeRep*>(__root),
1166  __pos)
1167  // Only nonconst iterators modify root ref count
1168  { }
1169  public:
1170  typedef _CharT reference; // Really a value. Returning a reference
1171  // Would be a mess, since it would have
1172  // to be included in refcount.
1173  typedef const _CharT* pointer;
1174 
1175  public:
1176  _Rope_const_iterator() { }
1177 
1178  _Rope_const_iterator(const _Rope_const_iterator& __x)
1179  : _Rope_iterator_base<_CharT,_Alloc>(__x) { }
1180 
1181  _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);
1182 
1183  _Rope_const_iterator(const rope<_CharT, _Alloc>& __r, std::size_t __pos)
1184  : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { }
1185 
1186  _Rope_const_iterator&
1187  operator=(const _Rope_const_iterator& __x)
1188  {
1189  if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf)
1190  *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1191  else
1192  {
1193  this->_M_current_pos = __x._M_current_pos;
1194  this->_M_root = __x._M_root;
1195  this->_M_buf_ptr = 0;
1196  }
1197  return(*this);
1198  }
1199 
1200  reference
1201  operator*()
1202  {
1203  if (0 == this->_M_buf_ptr)
1204  this->_S_setcache(*this);
1205  return *this->_M_buf_ptr;
1206  }
1207 
1208  // Without this const version, Rope iterators do not meet the
1209  // requirements of an Input Iterator.
1210  reference
1211  operator*() const
1212  {
1213  return *const_cast<_Rope_const_iterator&>(*this);
1214  }
1215 
1216  _Rope_const_iterator&
1217  operator++()
1218  {
1219  __GC_CONST _CharT* __next;
1220  if (0 != this->_M_buf_ptr
1221  && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end)
1222  {
1223  this->_M_buf_ptr = __next;
1224  ++this->_M_current_pos;
1225  }
1226  else
1227  this->_M_incr(1);
1228  return *this;
1229  }
1230 
1231  _Rope_const_iterator&
1232  operator+=(std::ptrdiff_t __n)
1233  {
1234  if (__n >= 0)
1235  this->_M_incr(__n);
1236  else
1237  this->_M_decr(-__n);
1238  return *this;
1239  }
1240 
1241  _Rope_const_iterator&
1242  operator--()
1243  {
1244  this->_M_decr(1);
1245  return *this;
1246  }
1247 
1248  _Rope_const_iterator&
1249  operator-=(std::ptrdiff_t __n)
1250  {
1251  if (__n >= 0)
1252  this->_M_decr(__n);
1253  else
1254  this->_M_incr(-__n);
1255  return *this;
1256  }
1257 
1258  _Rope_const_iterator
1259  operator++(int)
1260  {
1261  std::size_t __old_pos = this->_M_current_pos;
1262  this->_M_incr(1);
1263  return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1264  // This makes a subsequent dereference expensive.
1265  // Perhaps we should instead copy the iterator
1266  // if it has a valid cache?
1267  }
1268 
1269  _Rope_const_iterator
1270  operator--(int)
1271  {
1272  std::size_t __old_pos = this->_M_current_pos;
1273  this->_M_decr(1);
1274  return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1275  }
1276 
1277  template<class _CharT2, class _Alloc2>
1278  friend _Rope_const_iterator<_CharT2, _Alloc2>
1279  operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1280  std::ptrdiff_t __n);
1281 
1282  template<class _CharT2, class _Alloc2>
1283  friend _Rope_const_iterator<_CharT2, _Alloc2>
1284  operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1285  std::ptrdiff_t __n);
1286 
1287  template<class _CharT2, class _Alloc2>
1288  friend _Rope_const_iterator<_CharT2, _Alloc2>
1289  operator+(std::ptrdiff_t __n,
1290  const _Rope_const_iterator<_CharT2, _Alloc2>& __x);
1291 
1292  reference
1293  operator[](std::size_t __n)
1294  { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,
1295  this->_M_current_pos + __n); }
1296 
1297  template<class _CharT2, class _Alloc2>
1298  friend bool
1299  operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1300  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1301 
1302  template<class _CharT2, class _Alloc2>
1303  friend bool
1304  operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1305  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1306 
1307  template<class _CharT2, class _Alloc2>
1308  friend std::ptrdiff_t
1309  operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1310  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1311  };
1312 
1313  template<class _CharT, class _Alloc>
1314  class _Rope_iterator
1315  : public _Rope_iterator_base<_CharT, _Alloc>
1316  {
1317  friend class rope<_CharT, _Alloc>;
1318  protected:
1319  typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep;
1320  rope<_CharT, _Alloc>* _M_root_rope;
1321 
1322  // root is treated as a cached version of this, and is used to
1323  // detect changes to the underlying rope.
1324 
1325  // Root is included in the reference count. This is necessary
1326  // so that we can detect changes reliably. Unfortunately, it
1327  // requires careful bookkeeping for the nonGC case.
1328  _Rope_iterator(rope<_CharT, _Alloc>* __r, std::size_t __pos)
1329  : _Rope_iterator_base<_CharT, _Alloc>(__r->_M_tree_ptr, __pos),
1330  _M_root_rope(__r)
1331  { _RopeRep::_S_ref(this->_M_root);
1332  if (!(__r -> empty()))
1333  this->_S_setcache(*this);
1334  }
1335 
1336  void _M_check();
1337  public:
1338  typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1339  typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer;
1340 
1341  rope<_CharT, _Alloc>&
1342  container()
1343  { return *_M_root_rope; }
1344 
1345  _Rope_iterator()
1346  {
1347  this->_M_root = 0; // Needed for reference counting.
1348  }
1349 
1350  _Rope_iterator(const _Rope_iterator& __x)
1351  : _Rope_iterator_base<_CharT, _Alloc>(__x)
1352  {
1353  _M_root_rope = __x._M_root_rope;
1354  _RopeRep::_S_ref(this->_M_root);
1355  }
1356 
1357  _Rope_iterator(rope<_CharT, _Alloc>& __r, std::size_t __pos);
1358 
1359  ~_Rope_iterator()
1360  { _RopeRep::_S_unref(this->_M_root); }
1361 
1362  _Rope_iterator&
1363  operator=(const _Rope_iterator& __x)
1364  {
1365  _RopeRep* __old = this->_M_root;
1366 
1367  _RopeRep::_S_ref(__x._M_root);
1368  if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf)
1369  {
1370  _M_root_rope = __x._M_root_rope;
1371  *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1372  }
1373  else
1374  {
1375  this->_M_current_pos = __x._M_current_pos;
1376  this->_M_root = __x._M_root;
1377  _M_root_rope = __x._M_root_rope;
1378  this->_M_buf_ptr = 0;
1379  }
1380  _RopeRep::_S_unref(__old);
1381  return(*this);
1382  }
1383 
1384  reference
1385  operator*()
1386  {
1387  _M_check();
1388  if (0 == this->_M_buf_ptr)
1389  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1390  this->_M_current_pos);
1391  else
1392  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1393  this->_M_current_pos,
1394  *this->_M_buf_ptr);
1395  }
1396 
1397  // See above comment.
1398  reference
1399  operator*() const
1400  {
1401  return *const_cast<_Rope_iterator&>(*this);
1402  }
1403 
1404  _Rope_iterator&
1405  operator++()
1406  {
1407  this->_M_incr(1);
1408  return *this;
1409  }
1410 
1411  _Rope_iterator&
1412  operator+=(std::ptrdiff_t __n)
1413  {
1414  if (__n >= 0)
1415  this->_M_incr(__n);
1416  else
1417  this->_M_decr(-__n);
1418  return *this;
1419  }
1420 
1421  _Rope_iterator&
1422  operator--()
1423  {
1424  this->_M_decr(1);
1425  return *this;
1426  }
1427 
1428  _Rope_iterator&
1429  operator-=(std::ptrdiff_t __n)
1430  {
1431  if (__n >= 0)
1432  this->_M_decr(__n);
1433  else
1434  this->_M_incr(-__n);
1435  return *this;
1436  }
1437 
1438  _Rope_iterator
1439  operator++(int)
1440  {
1441  std::size_t __old_pos = this->_M_current_pos;
1442  this->_M_incr(1);
1443  return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1444  }
1445 
1446  _Rope_iterator
1447  operator--(int)
1448  {
1449  std::size_t __old_pos = this->_M_current_pos;
1450  this->_M_decr(1);
1451  return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1452  }
1453 
1454  reference
1455  operator[](std::ptrdiff_t __n)
1456  { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1457  this->_M_current_pos
1458  + __n); }
1459 
1460  template<class _CharT2, class _Alloc2>
1461  friend bool
1462  operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1463  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1464 
1465  template<class _CharT2, class _Alloc2>
1466  friend bool
1467  operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1468  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1469 
1470  template<class _CharT2, class _Alloc2>
1471  friend std::ptrdiff_t
1472  operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1473  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1474 
1475  template<class _CharT2, class _Alloc2>
1476  friend _Rope_iterator<_CharT2, _Alloc2>
1477  operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1478  std::ptrdiff_t __n);
1479 
1480  template<class _CharT2, class _Alloc2>
1481  friend _Rope_iterator<_CharT2, _Alloc2>
1482  operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1483  std::ptrdiff_t __n);
1484 
1485  template<class _CharT2, class _Alloc2>
1486  friend _Rope_iterator<_CharT2, _Alloc2>
1487  operator+(std::ptrdiff_t __n,
1488  const _Rope_iterator<_CharT2, _Alloc2>& __x);
1489  };
1490 
1491 
1492  template <class _CharT, class _Alloc>
1493  struct _Rope_base
1494  : public _Alloc
1495  {
1496  typedef _Alloc allocator_type;
1497 
1498  allocator_type
1499  get_allocator() const
1500  { return *static_cast<const _Alloc*>(this); }
1501 
1502  allocator_type&
1503  _M_get_allocator()
1504  { return *static_cast<_Alloc*>(this); }
1505 
1506  const allocator_type&
1507  _M_get_allocator() const
1508  { return *static_cast<const _Alloc*>(this); }
1509 
1510  typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1511  // The one in _Base may not be visible due to template rules.
1512 
1513  _Rope_base(_RopeRep* __t, const allocator_type&)
1514  : _M_tree_ptr(__t) { }
1515 
1516  _Rope_base(const allocator_type&) { }
1517 
1518  // The only data member of a rope:
1519  _RopeRep *_M_tree_ptr;
1520 
1521 #define __ROPE_DEFINE_ALLOC(_Tp, __name) \
1522  typedef typename \
1523  __alloc_traits<_Alloc>::template rebind<_Tp>::other __name##Alloc; \
1524  static _Tp* __name##_allocate(std::size_t __n) \
1525  { return __name##Alloc().allocate(__n); } \
1526  static void __name##_deallocate(_Tp *__p, std::size_t __n) \
1527  { __name##Alloc().deallocate(__p, __n); }
1528  __ROPE_DEFINE_ALLOCS(_Alloc)
1529 #undef __ROPE_DEFINE_ALLOC
1530 
1531  protected:
1532  _Rope_base&
1533  operator=(const _Rope_base&);
1534 
1535  _Rope_base(const _Rope_base&);
1536  };
1537 
1538  /**
1539  * This is an SGI extension.
1540  * @ingroup SGIextensions
1541  * @doctodo
1542  */
1543  template <class _CharT, class _Alloc>
1544  class rope : public _Rope_base<_CharT, _Alloc>
1545  {
1546  public:
1547  typedef _CharT value_type;
1548  typedef std::ptrdiff_t difference_type;
1549  typedef std::size_t size_type;
1550  typedef _CharT const_reference;
1551  typedef const _CharT* const_pointer;
1552  typedef _Rope_iterator<_CharT, _Alloc> iterator;
1553  typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator;
1554  typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1555  typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer;
1556 
1557  friend class _Rope_iterator<_CharT, _Alloc>;
1558  friend class _Rope_const_iterator<_CharT, _Alloc>;
1559  friend struct _Rope_RopeRep<_CharT, _Alloc>;
1560  friend class _Rope_iterator_base<_CharT, _Alloc>;
1561  friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
1562  friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1563  friend struct _Rope_RopeSubstring<_CharT, _Alloc>;
1564 
1565  protected:
1566  typedef _Rope_base<_CharT, _Alloc> _Base;
1567  typedef typename _Base::allocator_type allocator_type;
1568  using _Base::_M_tree_ptr;
1569  using _Base::get_allocator;
1570  using _Base::_M_get_allocator;
1571  typedef __GC_CONST _CharT* _Cstrptr;
1572 
1573  static _CharT _S_empty_c_str[1];
1574 
1575  static bool
1576  _S_is0(_CharT __c)
1577  { return __c == _S_eos((_CharT*)0); }
1578 
1579  enum { _S_copy_max = 23 };
1580  // For strings shorter than _S_copy_max, we copy to
1581  // concatenate.
1582 
1583  typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1584  typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;
1585  typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;
1586  typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;
1587  typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;
1588 
1589  // Retrieve a character at the indicated position.
1590  static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
1591 
1592 #ifndef __GC
1593  // Obtain a pointer to the character at the indicated position.
1594  // The pointer can be used to change the character.
1595  // If such a pointer cannot be produced, as is frequently the
1596  // case, 0 is returned instead.
1597  // (Returns nonzero only if all nodes in the path have a refcount
1598  // of 1.)
1599  static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
1600 #endif
1601 
1602  static bool
1603  _S_apply_to_pieces(// should be template parameter
1604  _Rope_char_consumer<_CharT>& __c,
1605  const _RopeRep* __r,
1606  size_type __begin, size_type __end);
1607  // begin and end are assumed to be in range.
1608 
1609 #ifndef __GC
1610  static void
1611  _S_unref(_RopeRep* __t)
1612  { _RopeRep::_S_unref(__t); }
1613 
1614  static void
1615  _S_ref(_RopeRep* __t)
1616  { _RopeRep::_S_ref(__t); }
1617 
1618 #else /* __GC */
1619  static void _S_unref(_RopeRep*) { }
1620  static void _S_ref(_RopeRep*) { }
1621 #endif
1622 
1623 #ifdef __GC
1624  typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
1625 #else
1626  typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
1627 #endif
1628 
1629  // _Result is counted in refcount.
1630  static _RopeRep* _S_substring(_RopeRep* __base,
1631  size_type __start, size_type __endp1);
1632 
1633  static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
1634  const _CharT* __iter,
1635  size_type __slen,
1636  allocator_type& __a);
1637  // Concatenate rope and char ptr, copying __iter.
1638  // Should really take an arbitrary iterator.
1639  // Result is counted in refcount.
1640  static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
1641  const _CharT* __iter,
1642  size_type __slen,
1643  allocator_type& __a)
1644  // As above, but one reference to __r is about to be
1645  // destroyed. Thus the pieces may be recycled if all
1646  // relevant reference counts are 1.
1647 #ifdef __GC
1648  // We can't really do anything since refcounts are unavailable.
1649  { return _S_concat_char_iter(__r, __iter, __slen, __a); }
1650 #else
1651  ;
1652 #endif
1653 
1654  static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
1655  // General concatenation on _RopeRep. _Result
1656  // has refcount of 1. Adjusts argument refcounts.
1657 
1658  public:
1659  void
1660  apply_to_pieces(size_type __begin, size_type __end,
1661  _Rope_char_consumer<_CharT>& __c) const
1662  { _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); }
1663 
1664  protected:
1665 
1666  static size_type
1667  _S_rounded_up_size(size_type __n)
1668  { return _RopeLeaf::_S_rounded_up_size(__n); }
1669 
1670  static size_type
1671  _S_allocated_capacity(size_type __n)
1672  {
1673  if (_S_is_basic_char_type((_CharT*)0))
1674  return _S_rounded_up_size(__n) - 1;
1675  else
1676  return _S_rounded_up_size(__n);
1677 
1678  }
1679 
1680  // Allocate and construct a RopeLeaf using the supplied allocator
1681  // Takes ownership of s instead of copying.
1682  static _RopeLeaf*
1683  _S_new_RopeLeaf(__GC_CONST _CharT *__s,
1684  size_type __size, allocator_type& __a)
1685  {
1686  _RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);
1687  return new(__space) _RopeLeaf(__s, __size, __a);
1688  }
1689 
1690  static _RopeConcatenation*
1691  _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,
1692  allocator_type& __a)
1693  {
1694  _RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);
1695  return new(__space) _RopeConcatenation(__left, __right, __a);
1696  }
1697 
1698  static _RopeFunction*
1699  _S_new_RopeFunction(char_producer<_CharT>* __f,
1700  size_type __size, bool __d, allocator_type& __a)
1701  {
1702  _RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);
1703  return new(__space) _RopeFunction(__f, __size, __d, __a);
1704  }
1705 
1706  static _RopeSubstring*
1707  _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_type __s,
1708  size_type __l, allocator_type& __a)
1709  {
1710  _RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);
1711  return new(__space) _RopeSubstring(__b, __s, __l, __a);
1712  }
1713 
1714  static _RopeLeaf*
1715  _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,
1716  size_type __size, allocator_type& __a)
1717 #define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \
1718  _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a)
1719  {
1720  if (0 == __size)
1721  return 0;
1722  _CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
1723 
1724  __uninitialized_copy_n_a(__s, __size, __buf, __a);
1725  _S_cond_store_eos(__buf[__size]);
1726  __try
1727  { return _S_new_RopeLeaf(__buf, __size, __a); }
1728  __catch(...)
1729  {
1730  _RopeRep::__STL_FREE_STRING(__buf, __size, __a);
1731  __throw_exception_again;
1732  }
1733  }
1734 
1735  // Concatenation of nonempty strings.
1736  // Always builds a concatenation node.
1737  // Rebalances if the result is too deep.
1738  // Result has refcount 1.
1739  // Does not increment left and right ref counts even though
1740  // they are referenced.
1741  static _RopeRep*
1742  _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
1743 
1744  // Concatenation helper functions
1745  static _RopeLeaf*
1746  _S_leaf_concat_char_iter(_RopeLeaf* __r,
1747  const _CharT* __iter, size_type __slen);
1748  // Concatenate by copying leaf.
1749  // should take an arbitrary iterator
1750  // result has refcount 1.
1751 #ifndef __GC
1752  static _RopeLeaf*
1753  _S_destr_leaf_concat_char_iter(_RopeLeaf* __r,
1754  const _CharT* __iter, size_type __slen);
1755  // A version that potentially clobbers __r if __r->_M_ref_count == 1.
1756 #endif
1757 
1758  private:
1759 
1760  static size_type _S_char_ptr_len(const _CharT* __s);
1761  // slightly generalized strlen
1762 
1763  rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
1764  : _Base(__t, __a) { }
1765 
1766 
1767  // Copy __r to the _CharT buffer.
1768  // Returns __buffer + __r->_M_size.
1769  // Assumes that buffer is uninitialized.
1770  static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);
1771 
1772  // Again, with explicit starting position and length.
1773  // Assumes that buffer is uninitialized.
1774  static _CharT* _S_flatten(_RopeRep* __r,
1775  size_type __start, size_type __len,
1776  _CharT* __buffer);
1777 
1778  static const unsigned long
1779  _S_min_len[__detail::_S_max_rope_depth + 1];
1780 
1781  static bool
1782  _S_is_balanced(_RopeRep* __r)
1783  { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
1784 
1785  static bool
1786  _S_is_almost_balanced(_RopeRep* __r)
1787  { return (__r->_M_depth == 0
1788  || __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
1789 
1790  static bool
1791  _S_is_roughly_balanced(_RopeRep* __r)
1792  { return (__r->_M_depth <= 1
1793  || __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
1794 
1795  // Assumes the result is not empty.
1796  static _RopeRep*
1797  _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right)
1798  {
1799  _RopeRep* __result = _S_concat(__left, __right);
1800  if (_S_is_balanced(__result))
1801  __result->_M_is_balanced = true;
1802  return __result;
1803  }
1804 
1805  // The basic rebalancing operation. Logically copies the
1806  // rope. The result has refcount of 1. The client will
1807  // usually decrement the reference count of __r.
1808  // The result is within height 2 of balanced by the above
1809  // definition.
1810  static _RopeRep* _S_balance(_RopeRep* __r);
1811 
1812  // Add all unbalanced subtrees to the forest of balanced trees.
1813  // Used only by balance.
1814  static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);
1815 
1816  // Add __r to forest, assuming __r is already balanced.
1817  static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
1818 
1819  // Print to stdout, exposing structure
1820  static void _S_dump(_RopeRep* __r, int __indent = 0);
1821 
1822  // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.
1823  static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);
1824 
1825  public:
1826  _GLIBCXX_NODISCARD bool
1827  empty() const
1828  { return 0 == this->_M_tree_ptr; }
1829 
1830  // Comparison member function. This is public only for those
1831  // clients that need a ternary comparison. Others
1832  // should use the comparison operators below.
1833  int
1834  compare(const rope& __y) const
1835  { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }
1836 
1837  rope(const _CharT* __s, const allocator_type& __a = allocator_type())
1838  : _Base(__a)
1839  {
1840  this->_M_tree_ptr =
1841  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
1842  _M_get_allocator());
1843  }
1844 
1845  rope(const _CharT* __s, size_type __len,
1846  const allocator_type& __a = allocator_type())
1847  : _Base(__a)
1848  {
1849  this->_M_tree_ptr =
1850  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator());
1851  }
1852 
1853  // Should perhaps be templatized with respect to the iterator type
1854  // and use Sequence_buffer. (It should perhaps use sequence_buffer
1855  // even now.)
1856  rope(const _CharT* __s, const _CharT* __e,
1857  const allocator_type& __a = allocator_type())
1858  : _Base(__a)
1859  {
1860  this->_M_tree_ptr =
1861  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator());
1862  }
1863 
1864  rope(const const_iterator& __s, const const_iterator& __e,
1865  const allocator_type& __a = allocator_type())
1866  : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1867  __e._M_current_pos), __a)
1868  { }
1869 
1870  rope(const iterator& __s, const iterator& __e,
1871  const allocator_type& __a = allocator_type())
1872  : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1873  __e._M_current_pos), __a)
1874  { }
1875 
1876  rope(_CharT __c, const allocator_type& __a = allocator_type())
1877  : _Base(__a)
1878  {
1879  _CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));
1880 
1881  __alloc_traits<allocator_type>::construct(_M_get_allocator(),
1882  __buf, __c);
1883  __try
1884  {
1885  this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1,
1886  _M_get_allocator());
1887  }
1888  __catch(...)
1889  {
1890  _RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator());
1891  __throw_exception_again;
1892  }
1893  }
1894 
1895  rope(size_type __n, _CharT __c,
1896  const allocator_type& __a = allocator_type());
1897 
1898  rope(const allocator_type& __a = allocator_type())
1899  : _Base(0, __a) { }
1900 
1901  // Construct a rope from a function that can compute its members
1902  rope(char_producer<_CharT> *__fn, size_type __len, bool __delete_fn,
1903  const allocator_type& __a = allocator_type())
1904  : _Base(__a)
1905  {
1906  this->_M_tree_ptr = (0 == __len)
1907  ? 0
1908  : _S_new_RopeFunction(__fn, __len, __delete_fn, _M_get_allocator());
1909  }
1910 
1911  rope(const rope& __x, const allocator_type& __a = allocator_type())
1912  : _Base(__x._M_tree_ptr, __a)
1913  { _S_ref(this->_M_tree_ptr); }
1914 
1915  ~rope() throw()
1916  { _S_unref(this->_M_tree_ptr); }
1917 
1918  rope&
1919  operator=(const rope& __x)
1920  {
1921  _RopeRep* __old = this->_M_tree_ptr;
1922  this->_M_tree_ptr = __x._M_tree_ptr;
1923  _S_ref(this->_M_tree_ptr);
1924  _S_unref(__old);
1925  return *this;
1926  }
1927 
1928  void
1929  clear()
1930  {
1931  _S_unref(this->_M_tree_ptr);
1932  this->_M_tree_ptr = 0;
1933  }
1934 
1935  void
1936  push_back(_CharT __x)
1937  {
1938  allocator_type __a = _M_get_allocator();
1939  _RopeRep* __old = this->_M_tree_ptr;
1940  this->_M_tree_ptr
1941  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1, __a);
1942  _S_unref(__old);
1943  }
1944 
1945  void
1946  pop_back()
1947  {
1948  _RopeRep* __old = this->_M_tree_ptr;
1949  this->_M_tree_ptr = _S_substring(this->_M_tree_ptr,
1950  0, this->_M_tree_ptr->_M_size - 1);
1951  _S_unref(__old);
1952  }
1953 
1954  _CharT
1955  back() const
1956  { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }
1957 
1958  void
1959  push_front(_CharT __x)
1960  {
1961  _RopeRep* __old = this->_M_tree_ptr;
1962  _RopeRep* __left =
1963  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator());
1964  __try
1965  {
1966  this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
1967  _S_unref(__old);
1968  _S_unref(__left);
1969  }
1970  __catch(...)
1971  {
1972  _S_unref(__left);
1973  __throw_exception_again;
1974  }
1975  }
1976 
1977  void
1978  pop_front()
1979  {
1980  _RopeRep* __old = this->_M_tree_ptr;
1981  this->_M_tree_ptr
1982  = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
1983  _S_unref(__old);
1984  }
1985 
1986  _CharT
1987  front() const
1988  { return _S_fetch(this->_M_tree_ptr, 0); }
1989 
1990  void
1991  balance()
1992  {
1993  _RopeRep* __old = this->_M_tree_ptr;
1994  this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
1995  _S_unref(__old);
1996  }
1997 
1998  void
1999  copy(_CharT* __buffer) const
2000  {
2001  _Destroy_const(__buffer, __buffer + size(), _M_get_allocator());
2002  _S_flatten(this->_M_tree_ptr, __buffer);
2003  }
2004 
2005  // This is the copy function from the standard, but
2006  // with the arguments reordered to make it consistent with the
2007  // rest of the interface.
2008  // Note that this guaranteed not to compile if the draft standard
2009  // order is assumed.
2010  size_type
2011  copy(size_type __pos, size_type __n, _CharT* __buffer) const
2012  {
2013  size_type __size = size();
2014  size_type __len = (__pos + __n > __size? __size - __pos : __n);
2015 
2016  _Destroy_const(__buffer, __buffer + __len, _M_get_allocator());
2017  _S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);
2018  return __len;
2019  }
2020 
2021  // Print to stdout, exposing structure. May be useful for
2022  // performance debugging.
2023  void
2024  dump()
2025  { _S_dump(this->_M_tree_ptr); }
2026 
2027  // Convert to 0 terminated string in new allocated memory.
2028  // Embedded 0s in the input do not terminate the copy.
2029  const _CharT* c_str() const;
2030 
2031  // As above, but also use the flattened representation as
2032  // the new rope representation.
2033  const _CharT* replace_with_c_str();
2034 
2035  // Reclaim memory for the c_str generated flattened string.
2036  // Intentionally undocumented, since it's hard to say when this
2037  // is safe for multiple threads.
2038  void
2039  delete_c_str ()
2040  {
2041  if (0 == this->_M_tree_ptr)
2042  return;
2043  if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag &&
2044  ((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==
2045  this->_M_tree_ptr->_M_c_string)
2046  {
2047  // Representation shared
2048  return;
2049  }
2050 #ifndef __GC
2051  this->_M_tree_ptr->_M_free_c_string();
2052 #endif
2053  this->_M_tree_ptr->_M_c_string = 0;
2054  }
2055 
2056  _CharT
2057  operator[] (size_type __pos) const
2058  { return _S_fetch(this->_M_tree_ptr, __pos); }
2059 
2060  _CharT
2061  at(size_type __pos) const
2062  {
2063  // if (__pos >= size()) throw out_of_range; // XXX
2064  return (*this)[__pos];
2065  }
2066 
2067  const_iterator
2068  begin() const
2069  { return(const_iterator(this->_M_tree_ptr, 0)); }
2070 
2071  // An easy way to get a const iterator from a non-const container.
2072  const_iterator
2073  const_begin() const
2074  { return(const_iterator(this->_M_tree_ptr, 0)); }
2075 
2076  const_iterator
2077  end() const
2078  { return(const_iterator(this->_M_tree_ptr, size())); }
2079 
2080  const_iterator
2081  const_end() const
2082  { return(const_iterator(this->_M_tree_ptr, size())); }
2083 
2084  size_type
2085  size() const
2086  { return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }
2087 
2088  size_type
2089  length() const
2090  { return size(); }
2091 
2092  size_type
2093  max_size() const
2094  {
2095  return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1;
2096  // Guarantees that the result can be sufficiently
2097  // balanced. Longer ropes will probably still work,
2098  // but it's harder to make guarantees.
2099  }
2100 
2101  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
2102 
2103  const_reverse_iterator
2104  rbegin() const
2105  { return const_reverse_iterator(end()); }
2106 
2107  const_reverse_iterator
2108  const_rbegin() const
2109  { return const_reverse_iterator(end()); }
2110 
2111  const_reverse_iterator
2112  rend() const
2113  { return const_reverse_iterator(begin()); }
2114 
2115  const_reverse_iterator
2116  const_rend() const
2117  { return const_reverse_iterator(begin()); }
2118 
2119  template<class _CharT2, class _Alloc2>
2120  friend rope<_CharT2, _Alloc2>
2121  operator+(const rope<_CharT2, _Alloc2>& __left,
2122  const rope<_CharT2, _Alloc2>& __right);
2123 
2124  template<class _CharT2, class _Alloc2>
2125  friend rope<_CharT2, _Alloc2>
2126  operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);
2127 
2128  template<class _CharT2, class _Alloc2>
2129  friend rope<_CharT2, _Alloc2>
2130  operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);
2131 
2132  // The symmetric cases are intentionally omitted, since they're
2133  // presumed to be less common, and we don't handle them as well.
2134 
2135  // The following should really be templatized. The first
2136  // argument should be an input iterator or forward iterator with
2137  // value_type _CharT.
2138  rope&
2139  append(const _CharT* __iter, size_type __n)
2140  {
2141  allocator_type __a = _M_get_allocator();
2142  _RopeRep* __result =
2143  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n, __a);
2144  _S_unref(this->_M_tree_ptr);
2145  this->_M_tree_ptr = __result;
2146  return *this;
2147  }
2148 
2149  rope&
2150  append(const _CharT* __c_string)
2151  {
2152  size_type __len = _S_char_ptr_len(__c_string);
2153  append(__c_string, __len);
2154  return(*this);
2155  }
2156 
2157  rope&
2158  append(const _CharT* __s, const _CharT* __e)
2159  {
2160  allocator_type __a = _M_get_allocator();
2161  _RopeRep* __result =
2162  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s, __a);
2163  _S_unref(this->_M_tree_ptr);
2164  this->_M_tree_ptr = __result;
2165  return *this;
2166  }
2167 
2168  rope&
2169  append(const_iterator __s, const_iterator __e)
2170  {
2171  _Self_destruct_ptr __appendee(_S_substring(__s._M_root,
2172  __s._M_current_pos,
2173  __e._M_current_pos));
2174  _RopeRep* __result = _S_concat(this->_M_tree_ptr,
2175  (_RopeRep*)__appendee);
2176  _S_unref(this->_M_tree_ptr);
2177  this->_M_tree_ptr = __result;
2178  return *this;
2179  }
2180 
2181  rope&
2182  append(_CharT __c)
2183  {
2184  allocator_type __a = _M_get_allocator();
2185  _RopeRep* __result =
2186  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1, __a);
2187  _S_unref(this->_M_tree_ptr);
2188  this->_M_tree_ptr = __result;
2189  return *this;
2190  }
2191 
2192  rope&
2193  append()
2194  { return append(_CharT()); } // XXX why?
2195 
2196  rope&
2197  append(const rope& __y)
2198  {
2199  _RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr);
2200  _S_unref(this->_M_tree_ptr);
2201  this->_M_tree_ptr = __result;
2202  return *this;
2203  }
2204 
2205  rope&
2206  append(size_type __n, _CharT __c)
2207  {
2208  rope<_CharT,_Alloc> __last(__n, __c);
2209  return append(__last);
2210  }
2211 
2212  void
2213  swap(rope& __b)
2214  {
2215  _RopeRep* __tmp = this->_M_tree_ptr;
2216  this->_M_tree_ptr = __b._M_tree_ptr;
2217  __b._M_tree_ptr = __tmp;
2218  }
2219 
2220  protected:
2221  // Result is included in refcount.
2222  static _RopeRep*
2223  replace(_RopeRep* __old, size_type __pos1,
2224  size_type __pos2, _RopeRep* __r)
2225  {
2226  if (0 == __old)
2227  {
2228  _S_ref(__r);
2229  return __r;
2230  }
2231  _Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));
2232  _Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));
2233  _RopeRep* __result;
2234 
2235  if (0 == __r)
2236  __result = _S_concat(__left, __right);
2237  else
2238  {
2239  _Self_destruct_ptr __left_result(_S_concat(__left, __r));
2240  __result = _S_concat(__left_result, __right);
2241  }
2242  return __result;
2243  }
2244 
2245  public:
2246  void
2247  insert(size_type __p, const rope& __r)
2248  {
2249  _RopeRep* __result =
2250  replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr);
2251  _S_unref(this->_M_tree_ptr);
2252  this->_M_tree_ptr = __result;
2253  }
2254 
2255  void
2256  insert(size_type __p, size_type __n, _CharT __c)
2257  {
2258  rope<_CharT,_Alloc> __r(__n,__c);
2259  insert(__p, __r);
2260  }
2261 
2262  void
2263  insert(size_type __p, const _CharT* __i, size_type __n)
2264  {
2265  _Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
2266  _Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
2267  __p, size()));
2268  _Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n,
2269  _M_get_allocator()));
2270  // _S_ destr_concat_char_iter should be safe here.
2271  // But as it stands it's probably not a win, since __left
2272  // is likely to have additional references.
2273  _RopeRep* __result = _S_concat(__left_result, __right);
2274  _S_unref(this->_M_tree_ptr);
2275  this->_M_tree_ptr = __result;
2276  }
2277 
2278  void
2279  insert(size_type __p, const _CharT* __c_string)
2280  { insert(__p, __c_string, _S_char_ptr_len(__c_string)); }
2281 
2282  void
2283  insert(size_type __p, _CharT __c)
2284  { insert(__p, &__c, 1); }
2285 
2286  void
2287  insert(size_type __p)
2288  {
2289  _CharT __c = _CharT();
2290  insert(__p, &__c, 1);
2291  }
2292 
2293  void
2294  insert(size_type __p, const _CharT* __i, const _CharT* __j)
2295  {
2296  rope __r(__i, __j);
2297  insert(__p, __r);
2298  }
2299 
2300  void
2301  insert(size_type __p, const const_iterator& __i,
2302  const const_iterator& __j)
2303  {
2304  rope __r(__i, __j);
2305  insert(__p, __r);
2306  }
2307 
2308  void
2309  insert(size_type __p, const iterator& __i,
2310  const iterator& __j)
2311  {
2312  rope __r(__i, __j);
2313  insert(__p, __r);
2314  }
2315 
2316  // (position, length) versions of replace operations:
2317 
2318  void
2319  replace(size_type __p, size_type __n, const rope& __r)
2320  {
2321  _RopeRep* __result =
2322  replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);
2323  _S_unref(this->_M_tree_ptr);
2324  this->_M_tree_ptr = __result;
2325  }
2326 
2327  void
2328  replace(size_type __p, size_type __n,
2329  const _CharT* __i, size_type __i_len)
2330  {
2331  rope __r(__i, __i_len);
2332  replace(__p, __n, __r);
2333  }
2334 
2335  void
2336  replace(size_type __p, size_type __n, _CharT __c)
2337  {
2338  rope __r(__c);
2339  replace(__p, __n, __r);
2340  }
2341 
2342  void
2343  replace(size_type __p, size_type __n, const _CharT* __c_string)
2344  {
2345  rope __r(__c_string);
2346  replace(__p, __n, __r);
2347  }
2348 
2349  void
2350  replace(size_type __p, size_type __n,
2351  const _CharT* __i, const _CharT* __j)
2352  {
2353  rope __r(__i, __j);
2354  replace(__p, __n, __r);
2355  }
2356 
2357  void
2358  replace(size_type __p, size_type __n,
2359  const const_iterator& __i, const const_iterator& __j)
2360  {
2361  rope __r(__i, __j);
2362  replace(__p, __n, __r);
2363  }
2364 
2365  void
2366  replace(size_type __p, size_type __n,
2367  const iterator& __i, const iterator& __j)
2368  {
2369  rope __r(__i, __j);
2370  replace(__p, __n, __r);
2371  }
2372 
2373  // Single character variants:
2374  void
2375  replace(size_type __p, _CharT __c)
2376  {
2377  iterator __i(this, __p);
2378  *__i = __c;
2379  }
2380 
2381  void
2382  replace(size_type __p, const rope& __r)
2383  { replace(__p, 1, __r); }
2384 
2385  void
2386  replace(size_type __p, const _CharT* __i, size_type __i_len)
2387  { replace(__p, 1, __i, __i_len); }
2388 
2389  void
2390  replace(size_type __p, const _CharT* __c_string)
2391  { replace(__p, 1, __c_string); }
2392 
2393  void
2394  replace(size_type __p, const _CharT* __i, const _CharT* __j)
2395  { replace(__p, 1, __i, __j); }
2396 
2397  void
2398  replace(size_type __p, const const_iterator& __i,
2399  const const_iterator& __j)
2400  { replace(__p, 1, __i, __j); }
2401 
2402  void
2403  replace(size_type __p, const iterator& __i,
2404  const iterator& __j)
2405  { replace(__p, 1, __i, __j); }
2406 
2407  // Erase, (position, size) variant.
2408  void
2409  erase(size_type __p, size_type __n)
2410  {
2411  _RopeRep* __result = replace(this->_M_tree_ptr, __p,
2412  __p + __n, 0);
2413  _S_unref(this->_M_tree_ptr);
2414  this->_M_tree_ptr = __result;
2415  }
2416 
2417  // Insert, iterator variants.
2418  iterator
2419  insert(const iterator& __p, const rope& __r)
2420  {
2421  insert(__p.index(), __r);
2422  return __p;
2423  }
2424 
2425  iterator
2426  insert(const iterator& __p, size_type __n, _CharT __c)
2427  {
2428  insert(__p.index(), __n, __c);
2429  return __p;
2430  }
2431 
2432  iterator insert(const iterator& __p, _CharT __c)
2433  {
2434  insert(__p.index(), __c);
2435  return __p;
2436  }
2437 
2438  iterator
2439  insert(const iterator& __p )
2440  {
2441  insert(__p.index());
2442  return __p;
2443  }
2444 
2445  iterator
2446  insert(const iterator& __p, const _CharT* c_string)
2447  {
2448  insert(__p.index(), c_string);
2449  return __p;
2450  }
2451 
2452  iterator
2453  insert(const iterator& __p, const _CharT* __i, size_type __n)
2454  {
2455  insert(__p.index(), __i, __n);
2456  return __p;
2457  }
2458 
2459  iterator
2460  insert(const iterator& __p, const _CharT* __i,
2461  const _CharT* __j)
2462  {
2463  insert(__p.index(), __i, __j);
2464  return __p;
2465  }
2466 
2467  iterator
2468  insert(const iterator& __p,
2469  const const_iterator& __i, const const_iterator& __j)
2470  {
2471  insert(__p.index(), __i, __j);
2472  return __p;
2473  }
2474 
2475  iterator
2476  insert(const iterator& __p,
2477  const iterator& __i, const iterator& __j)
2478  {
2479  insert(__p.index(), __i, __j);
2480  return __p;
2481  }
2482 
2483  // Replace, range variants.
2484  void
2485  replace(const iterator& __p, const iterator& __q, const rope& __r)
2486  { replace(__p.index(), __q.index() - __p.index(), __r); }
2487 
2488  void
2489  replace(const iterator& __p, const iterator& __q, _CharT __c)
2490  { replace(__p.index(), __q.index() - __p.index(), __c); }
2491 
2492  void
2493  replace(const iterator& __p, const iterator& __q,
2494  const _CharT* __c_string)
2495  { replace(__p.index(), __q.index() - __p.index(), __c_string); }
2496 
2497  void
2498  replace(const iterator& __p, const iterator& __q,
2499  const _CharT* __i, size_type __n)
2500  { replace(__p.index(), __q.index() - __p.index(), __i, __n); }
2501 
2502  void
2503  replace(const iterator& __p, const iterator& __q,
2504  const _CharT* __i, const _CharT* __j)
2505  { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2506 
2507  void
2508  replace(const iterator& __p, const iterator& __q,
2509  const const_iterator& __i, const const_iterator& __j)
2510  { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2511 
2512  void
2513  replace(const iterator& __p, const iterator& __q,
2514  const iterator& __i, const iterator& __j)
2515  { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2516 
2517  // Replace, iterator variants.
2518  void
2519  replace(const iterator& __p, const rope& __r)
2520  { replace(__p.index(), __r); }
2521 
2522  void
2523  replace(const iterator& __p, _CharT __c)
2524  { replace(__p.index(), __c); }
2525 
2526  void
2527  replace(const iterator& __p, const _CharT* __c_string)
2528  { replace(__p.index(), __c_string); }
2529 
2530  void
2531  replace(const iterator& __p, const _CharT* __i, size_type __n)
2532  { replace(__p.index(), __i, __n); }
2533 
2534  void
2535  replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
2536  { replace(__p.index(), __i, __j); }
2537 
2538  void
2539  replace(const iterator& __p, const_iterator __i, const_iterator __j)
2540  { replace(__p.index(), __i, __j); }
2541 
2542  void
2543  replace(const iterator& __p, iterator __i, iterator __j)
2544  { replace(__p.index(), __i, __j); }
2545 
2546  // Iterator and range variants of erase
2547  iterator
2548  erase(const iterator& __p, const iterator& __q)
2549  {
2550  size_type __p_index = __p.index();
2551  erase(__p_index, __q.index() - __p_index);
2552  return iterator(this, __p_index);
2553  }
2554 
2555  iterator
2556  erase(const iterator& __p)
2557  {
2558  size_type __p_index = __p.index();
2559  erase(__p_index, 1);
2560  return iterator(this, __p_index);
2561  }
2562 
2563  rope
2564  substr(size_type __start, size_type __len = 1) const
2565  {
2566  return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2567  __start,
2568  __start + __len));
2569  }
2570 
2571  rope
2572  substr(iterator __start, iterator __end) const
2573  {
2574  return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2575  __start.index(),
2576  __end.index()));
2577  }
2578 
2579  rope
2580  substr(iterator __start) const
2581  {
2582  size_type __pos = __start.index();
2583  return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2584  __pos, __pos + 1));
2585  }
2586 
2587  rope
2588  substr(const_iterator __start, const_iterator __end) const
2589  {
2590  // This might eventually take advantage of the cache in the
2591  // iterator.
2592  return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2593  __start.index(),
2594  __end.index()));
2595  }
2596 
2597  rope<_CharT, _Alloc>
2598  substr(const_iterator __start)
2599  {
2600  size_type __pos = __start.index();
2601  return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2602  __pos, __pos + 1));
2603  }
2604 
2605  static const size_type npos;
2606 
2607  size_type find(_CharT __c, size_type __pos = 0) const;
2608 
2609  size_type
2610  find(const _CharT* __s, size_type __pos = 0) const
2611  {
2612  size_type __result_pos;
2613  const_iterator __result =
2614  std::search(const_begin() + __pos, const_end(),
2615  __s, __s + _S_char_ptr_len(__s));
2616  __result_pos = __result.index();
2617 #ifndef __STL_OLD_ROPE_SEMANTICS
2618  if (__result_pos == size())
2619  __result_pos = npos;
2620 #endif
2621  return __result_pos;
2622  }
2623 
2624  iterator
2625  mutable_begin()
2626  { return(iterator(this, 0)); }
2627 
2628  iterator
2629  mutable_end()
2630  { return(iterator(this, size())); }
2631 
2632  typedef std::reverse_iterator<iterator> reverse_iterator;
2633 
2634  reverse_iterator
2635  mutable_rbegin()
2636  { return reverse_iterator(mutable_end()); }
2637 
2638  reverse_iterator
2639  mutable_rend()
2640  { return reverse_iterator(mutable_begin()); }
2641 
2642  reference
2643  mutable_reference_at(size_type __pos)
2644  { return reference(this, __pos); }
2645 
2646 #ifdef __STD_STUFF
2647  reference
2648  operator[] (size_type __pos)
2649  { return _char_ref_proxy(this, __pos); }
2650 
2651  reference
2652  at(size_type __pos)
2653  {
2654  // if (__pos >= size()) throw out_of_range; // XXX
2655  return (*this)[__pos];
2656  }
2657 
2658  void resize(size_type __n, _CharT __c) { }
2659  void resize(size_type __n) { }
2660  void reserve(size_type __res_arg = 0) { }
2661 
2662  size_type
2663  capacity() const
2664  { return max_size(); }
2665 
2666  // Stuff below this line is dangerous because it's error prone.
2667  // I would really like to get rid of it.
2668  // copy function with funny arg ordering.
2669  size_type
2670  copy(_CharT* __buffer, size_type __n,
2671  size_type __pos = 0) const
2672  { return copy(__pos, __n, __buffer); }
2673 
2674  iterator
2675  end()
2676  { return mutable_end(); }
2677 
2678  iterator
2679  begin()
2680  { return mutable_begin(); }
2681 
2682  reverse_iterator
2683  rend()
2684  { return mutable_rend(); }
2685 
2686  reverse_iterator
2687  rbegin()
2688  { return mutable_rbegin(); }
2689 
2690 #else
2691  const_iterator
2692  end()
2693  { return const_end(); }
2694 
2695  const_iterator
2696  begin()
2697  { return const_begin(); }
2698 
2699  const_reverse_iterator
2700  rend()
2701  { return const_rend(); }
2702 
2703  const_reverse_iterator
2704  rbegin()
2705  { return const_rbegin(); }
2706 
2707 #endif
2708  };
2709 
2710  template <class _CharT, class _Alloc>
2711  const typename rope<_CharT, _Alloc>::size_type
2712  rope<_CharT, _Alloc>::npos = (size_type)(-1);
2713 
2714  template <class _CharT, class _Alloc>
2715  inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2716  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2717  { return (__x._M_current_pos == __y._M_current_pos
2718  && __x._M_root == __y._M_root); }
2719 
2720  template <class _CharT, class _Alloc>
2721  inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2722  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2723  { return (__x._M_current_pos < __y._M_current_pos); }
2724 
2725  template <class _CharT, class _Alloc>
2726  inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2727  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2728  { return !(__x == __y); }
2729 
2730  template <class _CharT, class _Alloc>
2731  inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2732  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2733  { return __y < __x; }
2734 
2735  template <class _CharT, class _Alloc>
2736  inline bool
2737  operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2738  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2739  { return !(__y < __x); }
2740 
2741  template <class _CharT, class _Alloc>
2742  inline bool
2743  operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2744  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2745  { return !(__x < __y); }
2746 
2747  template <class _CharT, class _Alloc>
2748  inline std::ptrdiff_t
2749  operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2750  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2751  {
2752  return (std::ptrdiff_t)__x._M_current_pos
2753  - (std::ptrdiff_t)__y._M_current_pos;
2754  }
2755 
2756  template <class _CharT, class _Alloc>
2757  inline _Rope_const_iterator<_CharT, _Alloc>
2758  operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2759  std::ptrdiff_t __n)
2760  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2761  __x._M_current_pos - __n); }
2762 
2763  template <class _CharT, class _Alloc>
2764  inline _Rope_const_iterator<_CharT, _Alloc>
2765  operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2766  std::ptrdiff_t __n)
2767  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2768  __x._M_current_pos + __n); }
2769 
2770  template <class _CharT, class _Alloc>
2771  inline _Rope_const_iterator<_CharT, _Alloc>
2772  operator+(std::ptrdiff_t __n,
2773  const _Rope_const_iterator<_CharT, _Alloc>& __x)
2774  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2775  __x._M_current_pos + __n); }
2776 
2777  template <class _CharT, class _Alloc>
2778  inline bool
2779  operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
2780  const _Rope_iterator<_CharT, _Alloc>& __y)
2781  {return (__x._M_current_pos == __y._M_current_pos
2782  && __x._M_root_rope == __y._M_root_rope); }
2783 
2784  template <class _CharT, class _Alloc>
2785  inline bool
2786  operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
2787  const _Rope_iterator<_CharT, _Alloc>& __y)
2788  { return (__x._M_current_pos < __y._M_current_pos); }
2789 
2790  template <class _CharT, class _Alloc>
2791  inline bool
2792  operator!=(const _Rope_iterator<_CharT, _Alloc>& __x,
2793  const _Rope_iterator<_CharT, _Alloc>& __y)
2794  { return !(__x == __y); }
2795 
2796  template <class _CharT, class _Alloc>
2797  inline bool
2798  operator>(const _Rope_iterator<_CharT, _Alloc>& __x,
2799  const _Rope_iterator<_CharT, _Alloc>& __y)
2800  { return __y < __x; }
2801 
2802  template <class _CharT, class _Alloc>
2803  inline bool
2804  operator<=(const _Rope_iterator<_CharT, _Alloc>& __x,
2805  const _Rope_iterator<_CharT, _Alloc>& __y)
2806  { return !(__y < __x); }
2807 
2808  template <class _CharT, class _Alloc>
2809  inline bool
2810  operator>=(const _Rope_iterator<_CharT, _Alloc>& __x,
2811  const _Rope_iterator<_CharT, _Alloc>& __y)
2812  { return !(__x < __y); }
2813 
2814  template <class _CharT, class _Alloc>
2815  inline std::ptrdiff_t
2816  operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2817  const _Rope_iterator<_CharT, _Alloc>& __y)
2818  { return ((std::ptrdiff_t)__x._M_current_pos
2819  - (std::ptrdiff_t)__y._M_current_pos); }
2820 
2821  template <class _CharT, class _Alloc>
2822  inline _Rope_iterator<_CharT, _Alloc>
2823  operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2824  std::ptrdiff_t __n)
2825  { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2826  __x._M_current_pos - __n); }
2827 
2828  template <class _CharT, class _Alloc>
2829  inline _Rope_iterator<_CharT, _Alloc>
2830  operator+(const _Rope_iterator<_CharT, _Alloc>& __x, std::ptrdiff_t __n)
2831  { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2832  __x._M_current_pos + __n); }
2833 
2834  template <class _CharT, class _Alloc>
2835  inline _Rope_iterator<_CharT, _Alloc>
2836  operator+(std::ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x)
2837  { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2838  __x._M_current_pos + __n); }
2839 
2840  template <class _CharT, class _Alloc>
2841  inline rope<_CharT, _Alloc>
2842  operator+(const rope<_CharT, _Alloc>& __left,
2843  const rope<_CharT, _Alloc>& __right)
2844  {
2845  // Inlining this should make it possible to keep __left and
2846  // __right in registers.
2847  typedef rope<_CharT, _Alloc> rope_type;
2848  return rope_type(rope_type::_S_concat(__left._M_tree_ptr,
2849  __right._M_tree_ptr));
2850  }
2851 
2852  template <class _CharT, class _Alloc>
2853  inline rope<_CharT, _Alloc>&
2854  operator+=(rope<_CharT, _Alloc>& __left,
2855  const rope<_CharT, _Alloc>& __right)
2856  {
2857  __left.append(__right);
2858  return __left;
2859  }
2860 
2861  template <class _CharT, class _Alloc>
2862  inline rope<_CharT, _Alloc>
2863  operator+(const rope<_CharT, _Alloc>& __left,
2864  const _CharT* __right)
2865  {
2866  typedef rope<_CharT, _Alloc> rope_type;
2867  std::size_t __rlen = rope_type::_S_char_ptr_len(__right);
2868  _Alloc __a = __left.get_allocator();
2869  return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2870  __right, __rlen, __a));
2871  }
2872 
2873  template <class _CharT, class _Alloc>
2874  inline rope<_CharT, _Alloc>&
2875  operator+=(rope<_CharT, _Alloc>& __left,
2876  const _CharT* __right)
2877  {
2878  __left.append(__right);
2879  return __left;
2880  }
2881 
2882  template <class _CharT, class _Alloc>
2883  inline rope<_CharT, _Alloc>
2884  operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
2885  {
2886  typedef rope<_CharT, _Alloc> rope_type;
2887  _Alloc __a = __left.get_allocator();
2888  return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2889  &__right, 1, __a));
2890  }
2891 
2892  template <class _CharT, class _Alloc>
2893  inline rope<_CharT, _Alloc>&
2894  operator+=(rope<_CharT, _Alloc>& __left, _CharT __right)
2895  {
2896  __left.append(__right);
2897  return __left;
2898  }
2899 
2900  template <class _CharT, class _Alloc>
2901  bool
2902  operator<(const rope<_CharT, _Alloc>& __left,
2903  const rope<_CharT, _Alloc>& __right)
2904  { return __left.compare(__right) < 0; }
2905 
2906  template <class _CharT, class _Alloc>
2907  bool
2908  operator==(const rope<_CharT, _Alloc>& __left,
2909  const rope<_CharT, _Alloc>& __right)
2910  { return __left.compare(__right) == 0; }
2911 
2912  template <class _CharT, class _Alloc>
2913  inline bool
2914  operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2915  const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2916  { return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); }
2917 
2918  template <class _CharT, class _Alloc>
2919  inline bool
2920  operator!=(const rope<_CharT, _Alloc>& __x,
2921  const rope<_CharT, _Alloc>& __y)
2922  { return !(__x == __y); }
2923 
2924  template <class _CharT, class _Alloc>
2925  inline bool
2926  operator>(const rope<_CharT, _Alloc>& __x,
2927  const rope<_CharT, _Alloc>& __y)
2928  { return __y < __x; }
2929 
2930  template <class _CharT, class _Alloc>
2931  inline bool
2932  operator<=(const rope<_CharT, _Alloc>& __x,
2933  const rope<_CharT, _Alloc>& __y)
2934  { return !(__y < __x); }
2935 
2936  template <class _CharT, class _Alloc>
2937  inline bool
2938  operator>=(const rope<_CharT, _Alloc>& __x,
2939  const rope<_CharT, _Alloc>& __y)
2940  { return !(__x < __y); }
2941 
2942  template <class _CharT, class _Alloc>
2943  inline bool
2944  operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2945  const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2946  { return !(__x == __y); }
2947 
2948  template<class _CharT, class _Traits, class _Alloc>
2949  std::basic_ostream<_CharT, _Traits>&
2950  operator<<(std::basic_ostream<_CharT, _Traits>& __o,
2951  const rope<_CharT, _Alloc>& __r);
2952 
2953  typedef rope<char> crope;
2954  typedef rope<wchar_t> wrope;
2955 
2956  inline crope::reference
2957  __mutable_reference_at(crope& __c, std::size_t __i)
2958  { return __c.mutable_reference_at(__i); }
2959 
2960  inline wrope::reference
2961  __mutable_reference_at(wrope& __c, std::size_t __i)
2962  { return __c.mutable_reference_at(__i); }
2963 
2964  template <class _CharT, class _Alloc>
2965  inline void
2966  swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y)
2967  { __x.swap(__y); }
2968 
2969 _GLIBCXX_END_NAMESPACE_VERSION
2970 } // namespace
2971 
2972 
2973 namespace std _GLIBCXX_VISIBILITY(default)
2974 {
2975 _GLIBCXX_BEGIN_NAMESPACE_VERSION
2976 
2977 namespace tr1
2978 {
2979  template<>
2980  struct hash<__gnu_cxx::crope>
2981  {
2982  size_t
2983  operator()(const __gnu_cxx::crope& __str) const
2984  {
2985  size_t __size = __str.size();
2986  if (0 == __size)
2987  return 0;
2988  return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2989  }
2990  };
2991 
2992 
2993  template<>
2994  struct hash<__gnu_cxx::wrope>
2995  {
2996  size_t
2997  operator()(const __gnu_cxx::wrope& __str) const
2998  {
2999  size_t __size = __str.size();
3000  if (0 == __size)
3001  return 0;
3002  return 13 * __str[0] + 5 * __str[__size - 1] + __size;
3003  }
3004  };
3005 } // namespace tr1
3006 
3007 _GLIBCXX_END_NAMESPACE_VERSION
3008 } // namespace std
3009 
3010 # include <ext/ropeimpl.h>
3011 
3012 #endif