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