Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 1
// SGI's rope class -*- C++ -*-
2
 
3
// Copyright (C) 2001-2015 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
// .
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 
49
#include 
50
#include 
51
#include 
52
#include 
53
#include 
54
#include 
55
#include 
56
#include 
57
 
58
# ifdef __GC
59
#   define __GC_CONST const
60
# else
61
#   define __GC_CONST   // constant except for deallocation
62
# endif
63
 
64
#include  // For uninitialized_copy_n
65
 
66
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
67
{
68
  namespace __detail
69
  {
70
    enum { _S_max_rope_depth = 45 };
71
    enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
72
  } // namespace __detail
73
 
74
  using std::size_t;
75
  using std::ptrdiff_t;
76
  using std::allocator;
77
  using std::_Destroy;
78
 
79
_GLIBCXX_BEGIN_NAMESPACE_VERSION
80
 
81
  // See libstdc++/36832.
82
  template
83
    void
84
    _Destroy_const(_ForwardIterator __first,
85
		   _ForwardIterator __last, _Allocator __alloc)
86
    {
87
      for (; __first != __last; ++__first)
88
	__alloc.destroy(&*__first);
89
    }
90
 
91
  template
92
    inline void
93
    _Destroy_const(_ForwardIterator __first,
94
		   _ForwardIterator __last, allocator<_Tp>)
95
    { _Destroy(__first, __last); }
96
 
97
  // The _S_eos function is used for those functions that
98
  // convert to/from C-like strings to detect the end of the string.
99
 
100
  // The end-of-C-string character.
101
  // This is what the draft standard says it should be.
102
  template 
103
    inline _CharT
104
    _S_eos(_CharT*)
105
    { return _CharT(); }
106
 
107
  // Test for basic character types.
108
  // For basic character types leaves having a trailing eos.
109
  template 
110
    inline bool
111
    _S_is_basic_char_type(_CharT*)
112
    { return false; }
113
 
114
  template 
115
    inline bool
116
    _S_is_one_byte_char_type(_CharT*)
117
    { return false; }
118
 
119
  inline bool
120
  _S_is_basic_char_type(char*)
121
  { return true; }
122
 
123
  inline bool
124
  _S_is_one_byte_char_type(char*)
125
  { return true; }
126
 
127
  inline bool
128
  _S_is_basic_char_type(wchar_t*)
129
  { return true; }
130
 
131
  // Store an eos iff _CharT is a basic character type.
132
  // Do not reference _S_eos if it isn't.
133
  template 
134
    inline void
135
    _S_cond_store_eos(_CharT&) { }
136
 
137
  inline void
138
  _S_cond_store_eos(char& __c)
139
  { __c = 0; }
140
 
141
  inline void
142
  _S_cond_store_eos(wchar_t& __c)
143
  { __c = 0; }
144
 
145
  // char_producers are logically functions that generate a section of
146
  // a string.  These can be converted to ropes.  The resulting rope
147
  // invokes the char_producer on demand.  This allows, for example,
148
  // files to be viewed as ropes without reading the entire file.
149
  template 
150
    class char_producer
151
    {
152
    public:
153
      virtual ~char_producer() { };
154
 
155
      virtual void
156
      operator()(size_t __start_pos, size_t __len,
157
		 _CharT* __buffer) = 0;
158
      // Buffer should really be an arbitrary output iterator.
159
      // That way we could flatten directly into an ostream, etc.
160
      // This is thoroughly impossible, since iterator types don't
161
      // have runtime descriptions.
162
    };
163
 
164
  // Sequence buffers:
165
  //
166
  // Sequence must provide an append operation that appends an
167
  // array to the sequence.  Sequence buffers are useful only if
168
  // appending an entire array is cheaper than appending element by element.
169
  // This is true for many string representations.
170
  // This should  perhaps inherit from ostream
171
  // and be implemented correspondingly, so that they can be used
172
  // for formatted.  For the sake of portability, we don't do this yet.
173
  //
174
  // For now, sequence buffers behave as output iterators.  But they also
175
  // behave a little like basic_ostringstream and a
176
  // little like containers.
177
 
178
  template
179
    class sequence_buffer
180
    : public std::iterator
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
      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
      sequence_buffer(sequence_buffer& __x)
211
      {
212
	__x.flush();
213
	_M_prefix = __x._M_prefix;
214
	_M_buf_count = 0;
215
      }
216
 
217
      sequence_buffer(_Sequence& __s)
218
      : _M_prefix(&__s), _M_buf_count(0) { }
219
 
220
      sequence_buffer&
221
      operator=(sequence_buffer& __x)
222
      {
223
	__x.flush();
224
	_M_prefix = __x._M_prefix;
225
	_M_buf_count = 0;
226
	return *this;
227
      }
228
 
229
      sequence_buffer&
230
      operator=(const sequence_buffer& __x)
231
      {
232
	_M_prefix = __x._M_prefix;
233
	_M_buf_count = __x._M_buf_count;
234
	std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
235
	return *this;
236
      }
237
 
238
      void
239
      push_back(value_type __x)
240
      {
241
	if (_M_buf_count < _Buf_sz)
242
	  {
243
	    _M_buffer[_M_buf_count] = __x;
244
	    ++_M_buf_count;
245
	  }
246
	else
247
	  {
248
	    flush();
249
	    _M_buffer[0] = __x;
250
	    _M_buf_count = 1;
251
	  }
252
      }
253
 
254
      void
255
      append(value_type* __s, size_t __len)
256
      {
257
	if (__len + _M_buf_count <= _Buf_sz)
258
	  {
259
	    size_t __i = _M_buf_count;
260
	    for (size_t __j = 0; __j < __len; __i++, __j++)
261
	      _M_buffer[__i] = __s[__j];
262
	    _M_buf_count += __len;
263
	  }
264
	else if (0 == _M_buf_count)
265
	  _M_prefix->append(__s, __s + __len);
266
	else
267
	  {
268
	    flush();
269
	    append(__s, __len);
270
	  }
271
      }
272
 
273
      sequence_buffer&
274
      write(value_type* __s, size_t __len)
275
      {
276
	append(__s, __len);
277
	return *this;
278
      }
279
 
280
      sequence_buffer&
281
      put(value_type __x)
282
      {
283
	push_back(__x);
284
	return *this;
285
      }
286
 
287
      sequence_buffer&
288
      operator=(const value_type& __rhs)
289
      {
290
	push_back(__rhs);
291
	return *this;
292
      }
293
 
294
      sequence_buffer&
295
      operator*()
296
      { return *this; }
297
 
298
      sequence_buffer&
299
      operator++()
300
      { return *this; }
301
 
302
      sequence_buffer
303
      operator++(int)
304
      { return *this; }
305
    };
306
 
307
  // The following should be treated as private, at least for now.
308
  template
309
    class _Rope_char_consumer
310
    {
311
    public:
312
      // If we had member templates, these should not be virtual.
313
      // For now we need to use run-time parametrization where
314
      // compile-time would do.  Hence this should all be private
315
      // for now.
316
      // The symmetry with char_producer is accidental and temporary.
317
      virtual ~_Rope_char_consumer() { };
318
 
319
      virtual bool
320
      operator()(const _CharT* __buffer, size_t __len) = 0;
321
    };
322
 
323
  // First a lot of forward declarations.  The standard seems to require
324
  // much stricter "declaration before use" than many of the implementations
325
  // that preceded it.
326
  template >
327
    class rope;
328
 
329
  template
330
    struct _Rope_RopeConcatenation;
331
 
332
  template
333
    struct _Rope_RopeLeaf;
334
 
335
  template
336
    struct _Rope_RopeFunction;
337
 
338
  template
339
    struct _Rope_RopeSubstring;
340
 
341
  template
342
    class _Rope_iterator;
343
 
344
  template
345
    class _Rope_const_iterator;
346
 
347
  template
348
    class _Rope_char_ref_proxy;
349
 
350
  template
351
    class _Rope_char_ptr_proxy;
352
 
353
  template
354
    bool
355
    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
356
	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);
357
 
358
  template
359
    _Rope_const_iterator<_CharT, _Alloc>
360
    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
361
	      ptrdiff_t __n);
362
 
363
  template
364
    _Rope_const_iterator<_CharT, _Alloc>
365
    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
366
	      ptrdiff_t __n);
367
 
368
  template
369
    _Rope_const_iterator<_CharT, _Alloc>
370
    operator+(ptrdiff_t __n,
371
	      const _Rope_const_iterator<_CharT, _Alloc>& __x);
372
 
373
  template
374
    bool
375
    operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
376
	       const _Rope_const_iterator<_CharT, _Alloc>& __y);
377
 
378
  template
379
    bool
380
    operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
381
	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
382
 
383
  template
384
    ptrdiff_t
385
    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
386
	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
387
 
388
  template
389
    _Rope_iterator<_CharT, _Alloc>
390
    operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
391
 
392
  template
393
    _Rope_iterator<_CharT, _Alloc>
394
    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
395
 
396
  template
397
    _Rope_iterator<_CharT, _Alloc>
398
    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);
399
 
400
  template
401
    bool
402
    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
403
	       const _Rope_iterator<_CharT, _Alloc>& __y);
404
 
405
  template
406
    bool
407
    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
408
	      const _Rope_iterator<_CharT, _Alloc>& __y);
409
 
410
  template
411
    ptrdiff_t
412
    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
413
	      const _Rope_iterator<_CharT, _Alloc>& __y);
414
 
415
  template
416
    rope<_CharT, _Alloc>
417
    operator+(const rope<_CharT, _Alloc>& __left,
418
	      const rope<_CharT, _Alloc>& __right);
419
 
420
  template
421
    rope<_CharT, _Alloc>
422
    operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);
423
 
424
  template
425
    rope<_CharT, _Alloc>
426
    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);
427
 
428
  // Some helpers, so we can use power on ropes.
429
  // See below for why this isn't local to the implementation.
430
 
431
  // This uses a nonstandard refcount convention.
432
  // The result has refcount 0.
433
  template
434
    struct _Rope_Concat_fn
435
    : public std::binary_function, rope<_CharT, _Alloc>,
436
				  rope<_CharT, _Alloc> >
437
    {
438
      rope<_CharT, _Alloc>
439
      operator()(const rope<_CharT, _Alloc>& __x,
440
		 const rope<_CharT, _Alloc>& __y)
441
      { return __x + __y; }
442
    };
443
 
444
  template 
445
    inline rope<_CharT, _Alloc>
446
    identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
447
    { return rope<_CharT, _Alloc>(); }
448
 
449
  // Class _Refcount_Base provides a type, _RC_t, a data member,
450
  // _M_ref_count, and member functions _M_incr and _M_decr, which perform
451
  // atomic preincrement/predecrement.  The constructor initializes
452
  // _M_ref_count.
453
  struct _Refcount_Base
454
  {
455
    // The type _RC_t
456
    typedef size_t _RC_t;
457
 
458
    // The data member _M_ref_count
459
    volatile _RC_t _M_ref_count;
460
 
461
    // Constructor
462
#ifdef __GTHREAD_MUTEX_INIT
463
    __gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT;
464
#else
465
    __gthread_mutex_t _M_ref_count_lock;
466
#endif
467
 
468
    _Refcount_Base(_RC_t __n) : _M_ref_count(__n)
469
    {
470
#ifndef __GTHREAD_MUTEX_INIT
471
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
472
      __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
473
#else
474
#error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
475
#endif
476
#endif
477
    }
478
 
479
#ifndef __GTHREAD_MUTEX_INIT
480
    ~_Refcount_Base()
481
    { __gthread_mutex_destroy(&_M_ref_count_lock); }
482
#endif
483
 
484
    void
485
    _M_incr()
486
    {
487
      __gthread_mutex_lock(&_M_ref_count_lock);
488
      ++_M_ref_count;
489
      __gthread_mutex_unlock(&_M_ref_count_lock);
490
    }
491
 
492
    _RC_t
493
    _M_decr()
494
    {
495
      __gthread_mutex_lock(&_M_ref_count_lock);
496
      volatile _RC_t __tmp = --_M_ref_count;
497
      __gthread_mutex_unlock(&_M_ref_count_lock);
498
      return __tmp;
499
    }
500
  };
501
 
502
  //
503
  // What follows should really be local to rope.  Unfortunately,
504
  // that doesn't work, since it makes it impossible to define generic
505
  // equality on rope iterators.  According to the draft standard, the
506
  // template parameters for such an equality operator cannot be inferred
507
  // from the occurrence of a member class as a parameter.
508
  // (SGI compilers in fact allow this, but the __result wouldn't be
509
  // portable.)
510
  // Similarly, some of the static member functions are member functions
511
  // only to avoid polluting the global namespace, and to circumvent
512
  // restrictions on type inference for template functions.
513
  //
514
 
515
  //
516
  // The internal data structure for representing a rope.  This is
517
  // private to the implementation.  A rope is really just a pointer
518
  // to one of these.
519
  //
520
  // A few basic functions for manipulating this data structure
521
  // are members of _RopeRep.  Most of the more complex algorithms
522
  // are implemented as rope members.
523
  //
524
  // Some of the static member functions of _RopeRep have identically
525
  // named functions in rope that simply invoke the _RopeRep versions.
526
 
527
#define __ROPE_DEFINE_ALLOCS(__a) \
528
        __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \
529
        typedef _Rope_RopeConcatenation<_CharT,__a> __C; \
530
        __ROPE_DEFINE_ALLOC(__C,_C) \
531
        typedef _Rope_RopeLeaf<_CharT,__a> __L; \
532
        __ROPE_DEFINE_ALLOC(__L,_L) \
533
        typedef _Rope_RopeFunction<_CharT,__a> __F; \
534
        __ROPE_DEFINE_ALLOC(__F,_F) \
535
        typedef _Rope_RopeSubstring<_CharT,__a> __S; \
536
        __ROPE_DEFINE_ALLOC(__S,_S)
537
 
538
  //  Internal rope nodes potentially store a copy of the allocator
539
  //  instance used to allocate them.  This is mostly redundant.
540
  //  But the alternative would be to pass allocator instances around
541
  //  in some form to nearly all internal functions, since any pointer
542
  //  assignment may result in a zero reference count and thus require
543
  //  deallocation.
544
 
545
#define __STATIC_IF_SGI_ALLOC  /* not static */
546
 
547
  template 
548
    struct _Rope_rep_base
549
    : public _Alloc
550
    {
551
      typedef _Alloc allocator_type;
552
 
553
      allocator_type
554
      get_allocator() const
555
      { return *static_cast(this); }
556
 
557
      allocator_type&
558
      _M_get_allocator()
559
      { return *static_cast<_Alloc*>(this); }
560
 
561
      const allocator_type&
562
      _M_get_allocator() const
563
      { return *static_cast(this); }
564
 
565
      _Rope_rep_base(size_t __size, const allocator_type&)
566
      : _M_size(__size) { }
567
 
568
      size_t _M_size;
569
 
570
# define __ROPE_DEFINE_ALLOC(_Tp, __name) \
571
        typedef typename \
572
          _Alloc::template rebind<_Tp>::other __name##Alloc; \
573
        static _Tp* __name##_allocate(size_t __n) \
574
          { return __name##Alloc().allocate(__n); } \
575
        static void __name##_deallocate(_Tp *__p, size_t __n) \
576
          { __name##Alloc().deallocate(__p, __n); }
577
      __ROPE_DEFINE_ALLOCS(_Alloc)
578
# undef __ROPE_DEFINE_ALLOC
579
    };
580
 
581
  template
582
    struct _Rope_RopeRep
583
    : public _Rope_rep_base<_CharT, _Alloc>
584
# ifndef __GC
585
	     , _Refcount_Base
586
# endif
587
    {
588
    public:
589
      __detail::_Tag _M_tag:8;
590
      bool _M_is_balanced:8;
591
      unsigned char _M_depth;
592
      __GC_CONST _CharT* _M_c_string;
593
#ifdef __GTHREAD_MUTEX_INIT
594
      __gthread_mutex_t _M_c_string_lock = __GTHREAD_MUTEX_INIT;
595
#else
596
      __gthread_mutex_t _M_c_string_lock;
597
#endif
598
                        /* Flattened version of string, if needed.  */
599
                        /* typically 0.                             */
600
                        /* If it's not 0, then the memory is owned  */
601
                        /* by this node.                            */
602
                        /* In the case of a leaf, this may point to */
603
                        /* the same memory as the data field.       */
604
      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
605
        allocator_type;
606
 
607
      using _Rope_rep_base<_CharT, _Alloc>::get_allocator;
608
      using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator;
609
 
610
      _Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_t __size,
611
		    const allocator_type& __a)
612
      : _Rope_rep_base<_CharT, _Alloc>(__size, __a),
613
#ifndef __GC
614
	_Refcount_Base(1),
615
#endif
616
	_M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
617
#ifdef __GTHREAD_MUTEX_INIT
618
      { }
619
#else
620
      { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }
621
      ~_Rope_RopeRep()
622
      { __gthread_mutex_destroy (&_M_c_string_lock); }
623
#endif
624
#ifdef __GC
625
      void
626
      _M_incr () { }
627
#endif
628
      static void
629
      _S_free_string(__GC_CONST _CharT*, size_t __len,
630
		     allocator_type& __a);
631
#define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);
632
                        // Deallocate data section of a leaf.
633
                        // This shouldn't be a member function.
634
                        // But its hard to do anything else at the
635
                        // moment, because it's templatized w.r.t.
636
                        // an allocator.
637
                        // Does nothing if __GC is defined.
638
#ifndef __GC
639
      void _M_free_c_string();
640
      void _M_free_tree();
641
      // Deallocate t. Assumes t is not 0.
642
      void
643
      _M_unref_nonnil()
644
      {
645
	if (0 == _M_decr())
646
	  _M_free_tree();
647
      }
648
 
649
      void
650
      _M_ref_nonnil()
651
      { _M_incr(); }
652
 
653
      static void
654
      _S_unref(_Rope_RopeRep* __t)
655
      {
656
	if (0 != __t)
657
	  __t->_M_unref_nonnil();
658
      }
659
 
660
      static void
661
      _S_ref(_Rope_RopeRep* __t)
662
      {
663
	if (0 != __t)
664
	  __t->_M_incr();
665
      }
666
 
667
      static void
668
      _S_free_if_unref(_Rope_RopeRep* __t)
669
      {
670
	if (0 != __t && 0 == __t->_M_ref_count)
671
	  __t->_M_free_tree();
672
      }
673
#   else /* __GC */
674
      void _M_unref_nonnil() { }
675
      void _M_ref_nonnil() { }
676
      static void _S_unref(_Rope_RopeRep*) { }
677
      static void _S_ref(_Rope_RopeRep*) { }
678
      static void _S_free_if_unref(_Rope_RopeRep*) { }
679
#   endif
680
protected:
681
      _Rope_RopeRep&
682
      operator=(const _Rope_RopeRep&);
683
 
684
      _Rope_RopeRep(const _Rope_RopeRep&);
685
    };
686
 
687
  template
688
    struct _Rope_RopeLeaf
689
    : public _Rope_RopeRep<_CharT, _Alloc>
690
    {
691
    public:
692
      // Apparently needed by VC++
693
      // The data fields of leaves are allocated with some
694
      // extra space, to accommodate future growth and for basic
695
      // character types, to hold a trailing eos character.
696
      enum { _S_alloc_granularity = 8 };
697
 
698
      static size_t
699
      _S_rounded_up_size(size_t __n)
700
      {
701
        size_t __size_with_eos;
702
 
703
        if (_S_is_basic_char_type((_CharT*)0))
704
	  __size_with_eos = __n + 1;
705
	else
706
	  __size_with_eos = __n;
707
#ifdef __GC
708
	return __size_with_eos;
709
#else
710
	// Allow slop for in-place expansion.
711
	return ((__size_with_eos + size_t(_S_alloc_granularity) - 1)
712
		&~ (size_t(_S_alloc_granularity) - 1));
713
#endif
714
      }
715
      __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */
716
                                  /* The allocated size is         */
717
                                  /* _S_rounded_up_size(size), except */
718
                                  /* in the GC case, in which it   */
719
                                  /* doesn't matter.               */
720
      typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
721
        allocator_type;
722
 
723
      _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size,
724
		     const allocator_type& __a)
725
      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true,
726
				      __size, __a), _M_data(__d)
727
      {
728
        if (_S_is_basic_char_type((_CharT *)0))
729
	  {
730
            // already eos terminated.
731
            this->_M_c_string = __d;
732
	  }
733
      }
734
      // The constructor assumes that d has been allocated with
735
      // the proper allocator and the properly padded size.
736
      // In contrast, the destructor deallocates the data:
737
#ifndef __GC
738
      ~_Rope_RopeLeaf() throw()
739
      {
740
        if (_M_data != this->_M_c_string)
741
	  this->_M_free_c_string();
742
 
743
	this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
744
      }
745
#endif
746
protected:
747
      _Rope_RopeLeaf&
748
      operator=(const _Rope_RopeLeaf&);
749
 
750
      _Rope_RopeLeaf(const _Rope_RopeLeaf&);
751
    };
752
 
753
  template
754
    struct _Rope_RopeConcatenation
755
    : public _Rope_RopeRep<_CharT, _Alloc>
756
    {
757
    public:
758
      _Rope_RopeRep<_CharT, _Alloc>* _M_left;
759
      _Rope_RopeRep<_CharT, _Alloc>* _M_right;
760
 
761
      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
762
        allocator_type;
763
 
764
      _Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l,
765
			      _Rope_RopeRep<_CharT, _Alloc>* __r,
766
			      const allocator_type& __a)
767
	: _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat,
768
				      std::max(__l->_M_depth,
769
					       __r->_M_depth) + 1,
770
				      false,
771
				      __l->_M_size + __r->_M_size, __a),
772
        _M_left(__l), _M_right(__r)
773
      { }
774
#ifndef __GC
775
      ~_Rope_RopeConcatenation() throw()
776
      {
777
	this->_M_free_c_string();
778
	_M_left->_M_unref_nonnil();
779
	_M_right->_M_unref_nonnil();
780
      }
781
#endif
782
protected:
783
      _Rope_RopeConcatenation&
784
      operator=(const _Rope_RopeConcatenation&);
785
 
786
      _Rope_RopeConcatenation(const _Rope_RopeConcatenation&);
787
    };
788
 
789
  template
790
    struct _Rope_RopeFunction
791
    : public _Rope_RopeRep<_CharT, _Alloc>
792
    {
793
    public:
794
      char_producer<_CharT>* _M_fn;
795
#ifndef __GC
796
      bool _M_delete_when_done; // Char_producer is owned by the
797
                                // rope and should be explicitly
798
                                // deleted when the rope becomes
799
                                // inaccessible.
800
#else
801
      // In the GC case, we either register the rope for
802
      // finalization, or not.  Thus the field is unnecessary;
803
      // the information is stored in the collector data structures.
804
      // We do need a finalization procedure to be invoked by the
805
      // collector.
806
      static void
807
      _S_fn_finalization_proc(void * __tree, void *)
808
      { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
809
#endif
810
    typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
811
      allocator_type;
812
 
813
      _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size,
814
                        bool __d, const allocator_type& __a)
815
      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a)
816
	, _M_fn(__f)
817
#ifndef __GC
818
	, _M_delete_when_done(__d)
819
#endif
820
      {
821
#ifdef __GC
822
	if (__d)
823
	  {
824
	    GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::
825
				  _S_fn_finalization_proc, 0, 0, 0);
826
	  }
827
#endif
828
      }
829
#ifndef __GC
830
      ~_Rope_RopeFunction() throw()
831
      {
832
	this->_M_free_c_string();
833
	if (_M_delete_when_done)
834
	  delete _M_fn;
835
      }
836
# endif
837
    protected:
838
      _Rope_RopeFunction&
839
      operator=(const _Rope_RopeFunction&);
840
 
841
      _Rope_RopeFunction(const _Rope_RopeFunction&);
842
    };
843
  // Substring results are usually represented using just
844
  // concatenation nodes.  But in the case of very long flat ropes
845
  // or ropes with a functional representation that isn't practical.
846
  // In that case, we represent the __result as a special case of
847
  // RopeFunction, whose char_producer points back to the rope itself.
848
  // In all cases except repeated substring operations and
849
  // deallocation, we treat the __result as a RopeFunction.
850
  template
851
    struct _Rope_RopeSubstring
852
    : public _Rope_RopeFunction<_CharT, _Alloc>,
853
      public char_producer<_CharT>
854
    {
855
    public:
856
      // XXX this whole class should be rewritten.
857
      _Rope_RopeRep<_CharT,_Alloc>* _M_base;      // not 0
858
      size_t _M_start;
859
 
860
      virtual void
861
      operator()(size_t __start_pos, size_t __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_t __s,
891
                          size_t __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
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
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
      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, 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, 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
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
1011
    class _Rope_char_ptr_proxy
1012
    {
1013
      // XXX this class should be rewritten.
1014
      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1015
      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
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
1056
    class _Rope_iterator_base
1057
    : public std::iterator
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
      size_t _M_current_pos;
1068
      _RopeRep* _M_root;     // The whole rope.
1069
      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, size_t __pos)
1111
      : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }
1112
 
1113
      void _M_incr(size_t __n);
1114
      void _M_decr(size_t __n);
1115
    public:
1116
      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)
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
1134
    class _Rope_iterator;
1135
 
1136
  template
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, 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, 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)
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+=(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-=(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
        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
        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
1258
        friend _Rope_const_iterator<_CharT2, _Alloc2>
1259
        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1260
		  ptrdiff_t __n);
1261
 
1262
      template
1263
        friend _Rope_const_iterator<_CharT2, _Alloc2>
1264
        operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1265
		  ptrdiff_t __n);
1266
 
1267
      template
1268
        friend _Rope_const_iterator<_CharT2, _Alloc2>
1269
        operator+(ptrdiff_t __n,
1270
		  const _Rope_const_iterator<_CharT2, _Alloc2>& __x);
1271
 
1272
      reference
1273
      operator[](size_t __n)
1274
      { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,
1275
					      this->_M_current_pos + __n); }
1276
 
1277
      template
1278
        friend bool
1279
        operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1280
		   const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1281
 
1282
      template
1283
        friend bool
1284
        operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1285
		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1286
 
1287
      template
1288
        friend ptrdiff_t
1289
        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1290
		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1291
    };
1292
 
1293
  template
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, 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, 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)
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+=(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-=(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
        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
        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[](ptrdiff_t __n)
1436
      { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1437
						    this->_M_current_pos
1438
						    + __n); }
1439
 
1440
      template
1441
        friend bool
1442
        operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1443
		   const _Rope_iterator<_CharT2, _Alloc2>& __y);
1444
 
1445
      template
1446
        friend bool
1447
        operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1448
		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1449
 
1450
      template
1451
        friend ptrdiff_t
1452
        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1453
		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1454
 
1455
      template
1456
        friend _Rope_iterator<_CharT2, _Alloc2>
1457
        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1458
 
1459
      template
1460
        friend _Rope_iterator<_CharT2, _Alloc2>
1461
        operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1462
 
1463
      template
1464
        friend _Rope_iterator<_CharT2, _Alloc2>
1465
        operator+(ptrdiff_t __n, const _Rope_iterator<_CharT2, _Alloc2>& __x);
1466
    };
1467
 
1468
 
1469
  template 
1470
    struct _Rope_base
1471
    : public _Alloc
1472
    {
1473
      typedef _Alloc allocator_type;
1474
 
1475
      allocator_type
1476
      get_allocator() const
1477
      { return *static_cast(this); }
1478
 
1479
      allocator_type&
1480
      _M_get_allocator()
1481
      { return *static_cast<_Alloc*>(this); }
1482
 
1483
      const allocator_type&
1484
      _M_get_allocator() const
1485
      { return *static_cast(this); }
1486
 
1487
      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1488
      // The one in _Base may not be visible due to template rules.
1489
 
1490
      _Rope_base(_RopeRep* __t, const allocator_type&)
1491
      : _M_tree_ptr(__t) { }
1492
 
1493
      _Rope_base(const allocator_type&) { }
1494
 
1495
      // The only data member of a rope:
1496
      _RopeRep *_M_tree_ptr;
1497
 
1498
#define __ROPE_DEFINE_ALLOC(_Tp, __name) \
1499
        typedef typename \
1500
          _Alloc::template rebind<_Tp>::other __name##Alloc; \
1501
        static _Tp* __name##_allocate(size_t __n) \
1502
          { return __name##Alloc().allocate(__n); } \
1503
        static void __name##_deallocate(_Tp *__p, size_t __n) \
1504
          { __name##Alloc().deallocate(__p, __n); }
1505
      __ROPE_DEFINE_ALLOCS(_Alloc)
1506
#undef __ROPE_DEFINE_ALLOC
1507
 
1508
	protected:
1509
      _Rope_base&
1510
      operator=(const _Rope_base&);
1511
 
1512
      _Rope_base(const _Rope_base&);
1513
    };
1514
 
1515
  /**
1516
   *  This is an SGI extension.
1517
   *  @ingroup SGIextensions
1518
   *  @doctodo
1519
   */
1520
  template 
1521
    class rope : public _Rope_base<_CharT, _Alloc>
1522
    {
1523
    public:
1524
      typedef _CharT value_type;
1525
      typedef ptrdiff_t difference_type;
1526
      typedef size_t size_type;
1527
      typedef _CharT const_reference;
1528
      typedef const _CharT* const_pointer;
1529
      typedef _Rope_iterator<_CharT, _Alloc> iterator;
1530
      typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator;
1531
      typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1532
      typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer;
1533
 
1534
      friend class _Rope_iterator<_CharT, _Alloc>;
1535
      friend class _Rope_const_iterator<_CharT, _Alloc>;
1536
      friend struct _Rope_RopeRep<_CharT, _Alloc>;
1537
      friend class _Rope_iterator_base<_CharT, _Alloc>;
1538
      friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
1539
      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1540
      friend struct _Rope_RopeSubstring<_CharT, _Alloc>;
1541
 
1542
    protected:
1543
      typedef _Rope_base<_CharT, _Alloc> _Base;
1544
      typedef typename _Base::allocator_type allocator_type;
1545
      using _Base::_M_tree_ptr;
1546
      using _Base::get_allocator;
1547
      using _Base::_M_get_allocator;
1548
      typedef __GC_CONST _CharT* _Cstrptr;
1549
 
1550
      static _CharT _S_empty_c_str[1];
1551
 
1552
      static bool
1553
      _S_is0(_CharT __c)
1554
      { return __c == _S_eos((_CharT*)0); }
1555
 
1556
      enum { _S_copy_max = 23 };
1557
                // For strings shorter than _S_copy_max, we copy to
1558
                // concatenate.
1559
 
1560
      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1561
      typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;
1562
      typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;
1563
      typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;
1564
      typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;
1565
 
1566
      // Retrieve a character at the indicated position.
1567
      static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
1568
 
1569
#ifndef __GC
1570
      // Obtain a pointer to the character at the indicated position.
1571
      // The pointer can be used to change the character.
1572
      // If such a pointer cannot be produced, as is frequently the
1573
      // case, 0 is returned instead.
1574
      // (Returns nonzero only if all nodes in the path have a refcount
1575
      // of 1.)
1576
      static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
1577
#endif
1578
 
1579
      static bool
1580
      _S_apply_to_pieces(// should be template parameter
1581
			 _Rope_char_consumer<_CharT>& __c,
1582
			 const _RopeRep* __r,
1583
			 size_t __begin, size_t __end);
1584
                         // begin and end are assumed to be in range.
1585
 
1586
#ifndef __GC
1587
      static void
1588
      _S_unref(_RopeRep* __t)
1589
      { _RopeRep::_S_unref(__t); }
1590
 
1591
      static void
1592
      _S_ref(_RopeRep* __t)
1593
      { _RopeRep::_S_ref(__t); }
1594
 
1595
#else /* __GC */
1596
      static void _S_unref(_RopeRep*) { }
1597
      static void _S_ref(_RopeRep*) { }
1598
#endif
1599
 
1600
#ifdef __GC
1601
      typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
1602
#else
1603
      typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
1604
#endif
1605
 
1606
      // _Result is counted in refcount.
1607
      static _RopeRep* _S_substring(_RopeRep* __base,
1608
                                    size_t __start, size_t __endp1);
1609
 
1610
      static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
1611
					   const _CharT* __iter, size_t __slen);
1612
      // Concatenate rope and char ptr, copying __s.
1613
      // Should really take an arbitrary iterator.
1614
      // Result is counted in refcount.
1615
      static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
1616
						 const _CharT* __iter,
1617
						 size_t __slen)
1618
	// As above, but one reference to __r is about to be
1619
	// destroyed.  Thus the pieces may be recycled if all
1620
	// relevant reference counts are 1.
1621
#ifdef __GC
1622
	// We can't really do anything since refcounts are unavailable.
1623
      { return _S_concat_char_iter(__r, __iter, __slen); }
1624
#else
1625
      ;
1626
#endif
1627
 
1628
      static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
1629
      // General concatenation on _RopeRep.  _Result
1630
      // has refcount of 1.  Adjusts argument refcounts.
1631
 
1632
   public:
1633
      void
1634
      apply_to_pieces(size_t __begin, size_t __end,
1635
		      _Rope_char_consumer<_CharT>& __c) const
1636
      { _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); }
1637
 
1638
   protected:
1639
 
1640
      static size_t
1641
      _S_rounded_up_size(size_t __n)
1642
      { return _RopeLeaf::_S_rounded_up_size(__n); }
1643
 
1644
      static size_t
1645
      _S_allocated_capacity(size_t __n)
1646
      {
1647
	if (_S_is_basic_char_type((_CharT*)0))
1648
	  return _S_rounded_up_size(__n) - 1;
1649
	else
1650
	  return _S_rounded_up_size(__n);
1651
 
1652
      }
1653
 
1654
      // Allocate and construct a RopeLeaf using the supplied allocator
1655
      // Takes ownership of s instead of copying.
1656
      static _RopeLeaf*
1657
      _S_new_RopeLeaf(__GC_CONST _CharT *__s,
1658
		      size_t __size, allocator_type& __a)
1659
      {
1660
	_RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);
1661
	return new(__space) _RopeLeaf(__s, __size, __a);
1662
      }
1663
 
1664
      static _RopeConcatenation*
1665
      _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,
1666
			       allocator_type& __a)
1667
      {
1668
	_RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);
1669
	return new(__space) _RopeConcatenation(__left, __right, __a);
1670
      }
1671
 
1672
      static _RopeFunction*
1673
      _S_new_RopeFunction(char_producer<_CharT>* __f,
1674
			  size_t __size, bool __d, allocator_type& __a)
1675
      {
1676
	_RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);
1677
	return new(__space) _RopeFunction(__f, __size, __d, __a);
1678
      }
1679
 
1680
      static _RopeSubstring*
1681
      _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,
1682
			   size_t __l, allocator_type& __a)
1683
      {
1684
	_RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);
1685
	return new(__space) _RopeSubstring(__b, __s, __l, __a);
1686
      }
1687
 
1688
      static _RopeLeaf*
1689
      _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,
1690
					size_t __size, allocator_type& __a)
1691
#define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \
1692
                _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a)
1693
      {
1694
	if (0 == __size)
1695
	  return 0;
1696
	_CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
1697
 
1698
	__uninitialized_copy_n_a(__s, __size, __buf, __a);
1699
	_S_cond_store_eos(__buf[__size]);
1700
	__try
1701
	  { return _S_new_RopeLeaf(__buf, __size, __a); }
1702
	__catch(...)
1703
	  {
1704
	    _RopeRep::__STL_FREE_STRING(__buf, __size, __a);
1705
	    __throw_exception_again;
1706
	  }
1707
      }
1708
 
1709
      // Concatenation of nonempty strings.
1710
      // Always builds a concatenation node.
1711
      // Rebalances if the result is too deep.
1712
      // Result has refcount 1.
1713
      // Does not increment left and right ref counts even though
1714
      // they are referenced.
1715
      static _RopeRep*
1716
      _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
1717
 
1718
      // Concatenation helper functions
1719
      static _RopeLeaf*
1720
      _S_leaf_concat_char_iter(_RopeLeaf* __r,
1721
			       const _CharT* __iter, size_t __slen);
1722
      // Concatenate by copying leaf.
1723
      // should take an arbitrary iterator
1724
      // result has refcount 1.
1725
#ifndef __GC
1726
      static _RopeLeaf*
1727
      _S_destr_leaf_concat_char_iter(_RopeLeaf* __r,
1728
				     const _CharT* __iter, size_t __slen);
1729
      // A version that potentially clobbers __r if __r->_M_ref_count == 1.
1730
#endif
1731
 
1732
    private:
1733
 
1734
      static size_t _S_char_ptr_len(const _CharT* __s);
1735
      // slightly generalized strlen
1736
 
1737
      rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
1738
      : _Base(__t, __a) { }
1739
 
1740
 
1741
      // Copy __r to the _CharT buffer.
1742
      // Returns __buffer + __r->_M_size.
1743
      // Assumes that buffer is uninitialized.
1744
      static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);
1745
 
1746
      // Again, with explicit starting position and length.
1747
      // Assumes that buffer is uninitialized.
1748
      static _CharT* _S_flatten(_RopeRep* __r,
1749
				size_t __start, size_t __len,
1750
				_CharT* __buffer);
1751
 
1752
      static const unsigned long
1753
      _S_min_len[__detail::_S_max_rope_depth + 1];
1754
 
1755
      static bool
1756
      _S_is_balanced(_RopeRep* __r)
1757
      { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
1758
 
1759
      static bool
1760
      _S_is_almost_balanced(_RopeRep* __r)
1761
      { return (__r->_M_depth == 0
1762
		|| __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
1763
 
1764
      static bool
1765
      _S_is_roughly_balanced(_RopeRep* __r)
1766
      { return (__r->_M_depth <= 1
1767
		|| __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
1768
 
1769
      // Assumes the result is not empty.
1770
      static _RopeRep*
1771
      _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right)
1772
      {
1773
	_RopeRep* __result = _S_concat(__left, __right);
1774
	if (_S_is_balanced(__result))
1775
	  __result->_M_is_balanced = true;
1776
	return __result;
1777
      }
1778
 
1779
      // The basic rebalancing operation.  Logically copies the
1780
      // rope.  The result has refcount of 1.  The client will
1781
      // usually decrement the reference count of __r.
1782
      // The result is within height 2 of balanced by the above
1783
      // definition.
1784
      static _RopeRep* _S_balance(_RopeRep* __r);
1785
 
1786
      // Add all unbalanced subtrees to the forest of balanced trees.
1787
      // Used only by balance.
1788
      static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);
1789
 
1790
      // Add __r to forest, assuming __r is already balanced.
1791
      static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
1792
 
1793
      // Print to stdout, exposing structure
1794
      static void _S_dump(_RopeRep* __r, int __indent = 0);
1795
 
1796
      // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.
1797
      static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);
1798
 
1799
    public:
1800
      bool
1801
      empty() const
1802
      { return 0 == this->_M_tree_ptr; }
1803
 
1804
      // Comparison member function.  This is public only for those
1805
      // clients that need a ternary comparison.  Others
1806
      // should use the comparison operators below.
1807
      int
1808
      compare(const rope& __y) const
1809
      { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }
1810
 
1811
      rope(const _CharT* __s, const allocator_type& __a = allocator_type())
1812
      : _Base(__a)
1813
      {
1814
	this->_M_tree_ptr =
1815
	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
1816
					   _M_get_allocator());
1817
      }
1818
 
1819
      rope(const _CharT* __s, size_t __len,
1820
	   const allocator_type& __a = allocator_type())
1821
      : _Base(__a)
1822
      {
1823
	this->_M_tree_ptr =
1824
	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator());
1825
      }
1826
 
1827
      // Should perhaps be templatized with respect to the iterator type
1828
      // and use Sequence_buffer.  (It should perhaps use sequence_buffer
1829
      // even now.)
1830
      rope(const _CharT* __s, const _CharT* __e,
1831
	   const allocator_type& __a = allocator_type())
1832
      : _Base(__a)
1833
      {
1834
	this->_M_tree_ptr =
1835
	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator());
1836
      }
1837
 
1838
      rope(const const_iterator& __s, const const_iterator& __e,
1839
	   const allocator_type& __a = allocator_type())
1840
      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1841
			   __e._M_current_pos), __a)
1842
      { }
1843
 
1844
      rope(const iterator& __s, const iterator& __e,
1845
	   const allocator_type& __a = allocator_type())
1846
      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1847
			   __e._M_current_pos), __a)
1848
      { }
1849
 
1850
      rope(_CharT __c, const allocator_type& __a = allocator_type())
1851
      : _Base(__a)
1852
      {
1853
	_CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));
1854
 
1855
	_M_get_allocator().construct(__buf, __c);
1856
	__try
1857
	  {
1858
	    this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1,
1859
						_M_get_allocator());
1860
	  }
1861
	__catch(...)
1862
	  {
1863
	    _RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator());
1864
	    __throw_exception_again;
1865
	  }
1866
      }
1867
 
1868
      rope(size_t __n, _CharT __c,
1869
	   const allocator_type& __a = allocator_type());
1870
 
1871
      rope(const allocator_type& __a = allocator_type())
1872
      : _Base(0, __a) { }
1873
 
1874
      // Construct a rope from a function that can compute its members
1875
      rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn,
1876
	   const allocator_type& __a = allocator_type())
1877
      : _Base(__a)
1878
      {
1879
	this->_M_tree_ptr = (0 == __len)
1880
	  ? 0
1881
	  : _S_new_RopeFunction(__fn, __len, __delete_fn, _M_get_allocator());
1882
      }
1883
 
1884
      rope(const rope& __x, const allocator_type& __a = allocator_type())
1885
      : _Base(__x._M_tree_ptr, __a)
1886
      { _S_ref(this->_M_tree_ptr); }
1887
 
1888
      ~rope() throw()
1889
      { _S_unref(this->_M_tree_ptr); }
1890
 
1891
      rope&
1892
      operator=(const rope& __x)
1893
      {
1894
	_RopeRep* __old = this->_M_tree_ptr;
1895
	this->_M_tree_ptr = __x._M_tree_ptr;
1896
	_S_ref(this->_M_tree_ptr);
1897
	_S_unref(__old);
1898
	return *this;
1899
      }
1900
 
1901
      void
1902
      clear()
1903
      {
1904
	_S_unref(this->_M_tree_ptr);
1905
	this->_M_tree_ptr = 0;
1906
      }
1907
 
1908
      void
1909
      push_back(_CharT __x)
1910
      {
1911
	_RopeRep* __old = this->_M_tree_ptr;
1912
	this->_M_tree_ptr
1913
	  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);
1914
	_S_unref(__old);
1915
      }
1916
 
1917
      void
1918
      pop_back()
1919
      {
1920
	_RopeRep* __old = this->_M_tree_ptr;
1921
	this->_M_tree_ptr = _S_substring(this->_M_tree_ptr,
1922
					 0, this->_M_tree_ptr->_M_size - 1);
1923
	_S_unref(__old);
1924
      }
1925
 
1926
      _CharT
1927
      back() const
1928
      { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }
1929
 
1930
      void
1931
      push_front(_CharT __x)
1932
      {
1933
	_RopeRep* __old = this->_M_tree_ptr;
1934
	_RopeRep* __left =
1935
	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator());
1936
	__try
1937
	  {
1938
	    this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
1939
	    _S_unref(__old);
1940
	    _S_unref(__left);
1941
	  }
1942
	__catch(...)
1943
	  {
1944
	    _S_unref(__left);
1945
	    __throw_exception_again;
1946
	  }
1947
      }
1948
 
1949
      void
1950
      pop_front()
1951
      {
1952
	_RopeRep* __old = this->_M_tree_ptr;
1953
	this->_M_tree_ptr
1954
	  = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
1955
	_S_unref(__old);
1956
      }
1957
 
1958
      _CharT
1959
      front() const
1960
      { return _S_fetch(this->_M_tree_ptr, 0); }
1961
 
1962
      void
1963
      balance()
1964
      {
1965
	_RopeRep* __old = this->_M_tree_ptr;
1966
	this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
1967
	_S_unref(__old);
1968
      }
1969
 
1970
      void
1971
      copy(_CharT* __buffer) const
1972
      {
1973
	_Destroy_const(__buffer, __buffer + size(), _M_get_allocator());
1974
	_S_flatten(this->_M_tree_ptr, __buffer);
1975
      }
1976
 
1977
      // This is the copy function from the standard, but
1978
      // with the arguments reordered to make it consistent with the
1979
      // rest of the interface.
1980
      // Note that this guaranteed not to compile if the draft standard
1981
      // order is assumed.
1982
      size_type
1983
      copy(size_type __pos, size_type __n, _CharT* __buffer) const
1984
      {
1985
	size_t __size = size();
1986
	size_t __len = (__pos + __n > __size? __size - __pos : __n);
1987
 
1988
	_Destroy_const(__buffer, __buffer + __len, _M_get_allocator());
1989
	_S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);
1990
	return __len;
1991
      }
1992
 
1993
      // Print to stdout, exposing structure.  May be useful for
1994
      // performance debugging.
1995
      void
1996
      dump()
1997
      { _S_dump(this->_M_tree_ptr); }
1998
 
1999
      // Convert to 0 terminated string in new allocated memory.
2000
      // Embedded 0s in the input do not terminate the copy.
2001
      const _CharT* c_str() const;
2002
 
2003
      // As above, but also use the flattened representation as
2004
      // the new rope representation.
2005
      const _CharT* replace_with_c_str();
2006
 
2007
      // Reclaim memory for the c_str generated flattened string.
2008
      // Intentionally undocumented, since it's hard to say when this
2009
      // is safe for multiple threads.
2010
      void
2011
      delete_c_str ()
2012
      {
2013
	if (0 == this->_M_tree_ptr)
2014
	  return;
2015
	if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag &&
2016
	    ((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==
2017
	    this->_M_tree_ptr->_M_c_string)
2018
	  {
2019
	    // Representation shared
2020
	    return;
2021
	  }
2022
#ifndef __GC
2023
	this->_M_tree_ptr->_M_free_c_string();
2024
#endif
2025
	this->_M_tree_ptr->_M_c_string = 0;
2026
      }
2027
 
2028
      _CharT
2029
      operator[] (size_type __pos) const
2030
      { return _S_fetch(this->_M_tree_ptr, __pos); }
2031
 
2032
      _CharT
2033
      at(size_type __pos) const
2034
      {
2035
	// if (__pos >= size()) throw out_of_range;  // XXX
2036
	return (*this)[__pos];
2037
      }
2038
 
2039
      const_iterator
2040
      begin() const
2041
      { return(const_iterator(this->_M_tree_ptr, 0)); }
2042
 
2043
      // An easy way to get a const iterator from a non-const container.
2044
      const_iterator
2045
      const_begin() const
2046
      { return(const_iterator(this->_M_tree_ptr, 0)); }
2047
 
2048
      const_iterator
2049
      end() const
2050
      { return(const_iterator(this->_M_tree_ptr, size())); }
2051
 
2052
      const_iterator
2053
      const_end() const
2054
      { return(const_iterator(this->_M_tree_ptr, size())); }
2055
 
2056
      size_type
2057
      size() const
2058
      {	return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }
2059
 
2060
      size_type
2061
      length() const
2062
      {	return size(); }
2063
 
2064
      size_type
2065
      max_size() const
2066
      {
2067
	return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1;
2068
	//  Guarantees that the result can be sufficiently
2069
	//  balanced.  Longer ropes will probably still work,
2070
	//  but it's harder to make guarantees.
2071
      }
2072
 
2073
      typedef std::reverse_iterator const_reverse_iterator;
2074
 
2075
      const_reverse_iterator
2076
      rbegin() const
2077
      { return const_reverse_iterator(end()); }
2078
 
2079
      const_reverse_iterator
2080
      const_rbegin() const
2081
      {	return const_reverse_iterator(end()); }
2082
 
2083
      const_reverse_iterator
2084
      rend() const
2085
      { return const_reverse_iterator(begin()); }
2086
 
2087
      const_reverse_iterator
2088
      const_rend() const
2089
      {	return const_reverse_iterator(begin()); }
2090
 
2091
      template
2092
        friend rope<_CharT2, _Alloc2>
2093
        operator+(const rope<_CharT2, _Alloc2>& __left,
2094
		  const rope<_CharT2, _Alloc2>& __right);
2095
 
2096
      template
2097
        friend rope<_CharT2, _Alloc2>
2098
        operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);
2099
 
2100
      template
2101
        friend rope<_CharT2, _Alloc2>
2102
        operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);
2103
 
2104
      // The symmetric cases are intentionally omitted, since they're
2105
      // presumed to be less common, and we don't handle them as well.
2106
 
2107
      // The following should really be templatized.  The first
2108
      // argument should be an input iterator or forward iterator with
2109
      // value_type _CharT.
2110
      rope&
2111
      append(const _CharT* __iter, size_t __n)
2112
      {
2113
	_RopeRep* __result =
2114
	  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n);
2115
	_S_unref(this->_M_tree_ptr);
2116
	this->_M_tree_ptr = __result;
2117
	return *this;
2118
      }
2119
 
2120
      rope&
2121
      append(const _CharT* __c_string)
2122
      {
2123
	size_t __len = _S_char_ptr_len(__c_string);
2124
	append(__c_string, __len);
2125
	return(*this);
2126
      }
2127
 
2128
      rope&
2129
      append(const _CharT* __s, const _CharT* __e)
2130
      {
2131
	_RopeRep* __result =
2132
	  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s);
2133
	_S_unref(this->_M_tree_ptr);
2134
	this->_M_tree_ptr = __result;
2135
	return *this;
2136
      }
2137
 
2138
      rope&
2139
      append(const_iterator __s, const_iterator __e)
2140
      {
2141
	_Self_destruct_ptr __appendee(_S_substring(__s._M_root,
2142
						   __s._M_current_pos,
2143
						   __e._M_current_pos));
2144
	_RopeRep* __result = _S_concat(this->_M_tree_ptr,
2145
				       (_RopeRep*)__appendee);
2146
	_S_unref(this->_M_tree_ptr);
2147
	this->_M_tree_ptr = __result;
2148
	return *this;
2149
      }
2150
 
2151
      rope&
2152
      append(_CharT __c)
2153
      {
2154
	_RopeRep* __result =
2155
	  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1);
2156
	_S_unref(this->_M_tree_ptr);
2157
	this->_M_tree_ptr = __result;
2158
	return *this;
2159
      }
2160
 
2161
      rope&
2162
      append()
2163
      { return append(_CharT()); }  // XXX why?
2164
 
2165
      rope&
2166
      append(const rope& __y)
2167
      {
2168
	_RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr);
2169
	_S_unref(this->_M_tree_ptr);
2170
	this->_M_tree_ptr = __result;
2171
	return *this;
2172
      }
2173
 
2174
      rope&
2175
      append(size_t __n, _CharT __c)
2176
      {
2177
	rope<_CharT,_Alloc> __last(__n, __c);
2178
	return append(__last);
2179
      }
2180
 
2181
      void
2182
      swap(rope& __b)
2183
      {
2184
	_RopeRep* __tmp = this->_M_tree_ptr;
2185
	this->_M_tree_ptr = __b._M_tree_ptr;
2186
	__b._M_tree_ptr = __tmp;
2187
      }
2188
 
2189
    protected:
2190
      // Result is included in refcount.
2191
      static _RopeRep*
2192
      replace(_RopeRep* __old, size_t __pos1,
2193
	      size_t __pos2, _RopeRep* __r)
2194
      {
2195
	if (0 == __old)
2196
	  {
2197
	    _S_ref(__r);
2198
	    return __r;
2199
	  }
2200
	_Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));
2201
	_Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));
2202
	_RopeRep* __result;
2203
 
2204
	if (0 == __r)
2205
	  __result = _S_concat(__left, __right);
2206
	else
2207
	  {
2208
	    _Self_destruct_ptr __left_result(_S_concat(__left, __r));
2209
	    __result = _S_concat(__left_result, __right);
2210
	  }
2211
	return __result;
2212
      }
2213
 
2214
    public:
2215
      void
2216
      insert(size_t __p, const rope& __r)
2217
      {
2218
	_RopeRep* __result =
2219
	  replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr);
2220
	_S_unref(this->_M_tree_ptr);
2221
	this->_M_tree_ptr = __result;
2222
      }
2223
 
2224
      void
2225
      insert(size_t __p, size_t __n, _CharT __c)
2226
      {
2227
	rope<_CharT,_Alloc> __r(__n,__c);
2228
	insert(__p, __r);
2229
      }
2230
 
2231
      void
2232
      insert(size_t __p, const _CharT* __i, size_t __n)
2233
      {
2234
	_Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
2235
	_Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
2236
						__p, size()));
2237
	_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n));
2238
	// _S_ destr_concat_char_iter should be safe here.
2239
	// But as it stands it's probably not a win, since __left
2240
	// is likely to have additional references.
2241
	_RopeRep* __result = _S_concat(__left_result, __right);
2242
	_S_unref(this->_M_tree_ptr);
2243
	this->_M_tree_ptr = __result;
2244
      }
2245
 
2246
      void
2247
      insert(size_t __p, const _CharT* __c_string)
2248
      {	insert(__p, __c_string, _S_char_ptr_len(__c_string)); }
2249
 
2250
      void
2251
      insert(size_t __p, _CharT __c)
2252
      { insert(__p, &__c, 1); }
2253
 
2254
      void
2255
      insert(size_t __p)
2256
      {
2257
	_CharT __c = _CharT();
2258
	insert(__p, &__c, 1);
2259
      }
2260
 
2261
      void
2262
      insert(size_t __p, const _CharT* __i, const _CharT* __j)
2263
      {
2264
	rope __r(__i, __j);
2265
	insert(__p, __r);
2266
      }
2267
 
2268
      void
2269
      insert(size_t __p, const const_iterator& __i,
2270
	     const const_iterator& __j)
2271
      {
2272
	rope __r(__i, __j);
2273
	insert(__p, __r);
2274
      }
2275
 
2276
      void
2277
      insert(size_t __p, const iterator& __i,
2278
	     const iterator& __j)
2279
      {
2280
	rope __r(__i, __j);
2281
	insert(__p, __r);
2282
      }
2283
 
2284
      // (position, length) versions of replace operations:
2285
 
2286
      void
2287
      replace(size_t __p, size_t __n, const rope& __r)
2288
      {
2289
	_RopeRep* __result =
2290
	  replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);
2291
	_S_unref(this->_M_tree_ptr);
2292
	this->_M_tree_ptr = __result;
2293
      }
2294
 
2295
      void
2296
      replace(size_t __p, size_t __n,
2297
	      const _CharT* __i, size_t __i_len)
2298
      {
2299
	rope __r(__i, __i_len);
2300
	replace(__p, __n, __r);
2301
      }
2302
 
2303
      void
2304
      replace(size_t __p, size_t __n, _CharT __c)
2305
      {
2306
	rope __r(__c);
2307
	replace(__p, __n, __r);
2308
      }
2309
 
2310
      void
2311
      replace(size_t __p, size_t __n, const _CharT* __c_string)
2312
      {
2313
	rope __r(__c_string);
2314
	replace(__p, __n, __r);
2315
      }
2316
 
2317
      void
2318
      replace(size_t __p, size_t __n,
2319
	      const _CharT* __i, const _CharT* __j)
2320
      {
2321
	rope __r(__i, __j);
2322
	replace(__p, __n, __r);
2323
      }
2324
 
2325
      void
2326
      replace(size_t __p, size_t __n,
2327
	      const const_iterator& __i, const const_iterator& __j)
2328
      {
2329
	rope __r(__i, __j);
2330
	replace(__p, __n, __r);
2331
      }
2332
 
2333
      void
2334
      replace(size_t __p, size_t __n,
2335
	      const iterator& __i, const iterator& __j)
2336
      {
2337
	rope __r(__i, __j);
2338
	replace(__p, __n, __r);
2339
      }
2340
 
2341
      // Single character variants:
2342
      void
2343
      replace(size_t __p, _CharT __c)
2344
      {
2345
	iterator __i(this, __p);
2346
	*__i = __c;
2347
      }
2348
 
2349
      void
2350
      replace(size_t __p, const rope& __r)
2351
      { replace(__p, 1, __r); }
2352
 
2353
      void
2354
      replace(size_t __p, const _CharT* __i, size_t __i_len)
2355
      { replace(__p, 1, __i, __i_len); }
2356
 
2357
      void
2358
      replace(size_t __p, const _CharT* __c_string)
2359
      {	replace(__p, 1, __c_string); }
2360
 
2361
      void
2362
      replace(size_t __p, const _CharT* __i, const _CharT* __j)
2363
      {	replace(__p, 1, __i, __j); }
2364
 
2365
      void
2366
      replace(size_t __p, const const_iterator& __i,
2367
	      const const_iterator& __j)
2368
      { replace(__p, 1, __i, __j); }
2369
 
2370
      void
2371
      replace(size_t __p, const iterator& __i,
2372
	      const iterator& __j)
2373
      { replace(__p, 1, __i, __j); }
2374
 
2375
      // Erase, (position, size) variant.
2376
      void
2377
      erase(size_t __p, size_t __n)
2378
      {
2379
	_RopeRep* __result = replace(this->_M_tree_ptr, __p,
2380
				     __p + __n, 0);
2381
	_S_unref(this->_M_tree_ptr);
2382
	this->_M_tree_ptr = __result;
2383
      }
2384
 
2385
      // Erase, single character
2386
      void
2387
      erase(size_t __p)
2388
      { erase(__p, __p + 1); }
2389
 
2390
      // Insert, iterator variants.
2391
      iterator
2392
      insert(const iterator& __p, const rope& __r)
2393
      {
2394
	insert(__p.index(), __r);
2395
	return __p;
2396
      }
2397
 
2398
      iterator
2399
      insert(const iterator& __p, size_t __n, _CharT __c)
2400
      {
2401
	insert(__p.index(), __n, __c);
2402
	return __p;
2403
      }
2404
 
2405
      iterator insert(const iterator& __p, _CharT __c)
2406
      {
2407
	insert(__p.index(), __c);
2408
	return __p;
2409
      }
2410
 
2411
      iterator
2412
      insert(const iterator& __p )
2413
      {
2414
	insert(__p.index());
2415
	return __p;
2416
      }
2417
 
2418
      iterator
2419
      insert(const iterator& __p, const _CharT* c_string)
2420
      {
2421
	insert(__p.index(), c_string);
2422
	return __p;
2423
      }
2424
 
2425
      iterator
2426
      insert(const iterator& __p, const _CharT* __i, size_t __n)
2427
      {
2428
	insert(__p.index(), __i, __n);
2429
	return __p;
2430
      }
2431
 
2432
      iterator
2433
      insert(const iterator& __p, const _CharT* __i,
2434
	     const _CharT* __j)
2435
      {
2436
	insert(__p.index(), __i, __j);
2437
	return __p;
2438
      }
2439
 
2440
      iterator
2441
      insert(const iterator& __p,
2442
	     const const_iterator& __i, const const_iterator& __j)
2443
      {
2444
	insert(__p.index(), __i, __j);
2445
	return __p;
2446
      }
2447
 
2448
      iterator
2449
      insert(const iterator& __p,
2450
	     const iterator& __i, const iterator& __j)
2451
      {
2452
	insert(__p.index(), __i, __j);
2453
	return __p;
2454
      }
2455
 
2456
      // Replace, range variants.
2457
      void
2458
      replace(const iterator& __p, const iterator& __q, const rope& __r)
2459
      {	replace(__p.index(), __q.index() - __p.index(), __r); }
2460
 
2461
      void
2462
      replace(const iterator& __p, const iterator& __q, _CharT __c)
2463
      { replace(__p.index(), __q.index() - __p.index(), __c); }
2464
 
2465
      void
2466
      replace(const iterator& __p, const iterator& __q,
2467
	      const _CharT* __c_string)
2468
      { replace(__p.index(), __q.index() - __p.index(), __c_string); }
2469
 
2470
      void
2471
      replace(const iterator& __p, const iterator& __q,
2472
	      const _CharT* __i, size_t __n)
2473
      { replace(__p.index(), __q.index() - __p.index(), __i, __n); }
2474
 
2475
      void
2476
      replace(const iterator& __p, const iterator& __q,
2477
	      const _CharT* __i, const _CharT* __j)
2478
      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2479
 
2480
      void
2481
      replace(const iterator& __p, const iterator& __q,
2482
	      const const_iterator& __i, const const_iterator& __j)
2483
      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2484
 
2485
      void
2486
      replace(const iterator& __p, const iterator& __q,
2487
	      const iterator& __i, const iterator& __j)
2488
      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2489
 
2490
      // Replace, iterator variants.
2491
      void
2492
      replace(const iterator& __p, const rope& __r)
2493
      { replace(__p.index(), __r); }
2494
 
2495
      void
2496
      replace(const iterator& __p, _CharT __c)
2497
      { replace(__p.index(), __c); }
2498
 
2499
      void
2500
      replace(const iterator& __p, const _CharT* __c_string)
2501
      { replace(__p.index(), __c_string); }
2502
 
2503
      void
2504
      replace(const iterator& __p, const _CharT* __i, size_t __n)
2505
      { replace(__p.index(), __i, __n); }
2506
 
2507
      void
2508
      replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
2509
      { replace(__p.index(), __i, __j); }
2510
 
2511
      void
2512
      replace(const iterator& __p, const_iterator __i, const_iterator __j)
2513
      { replace(__p.index(), __i, __j); }
2514
 
2515
      void
2516
      replace(const iterator& __p, iterator __i, iterator __j)
2517
      { replace(__p.index(), __i, __j); }
2518
 
2519
      // Iterator and range variants of erase
2520
      iterator
2521
      erase(const iterator& __p, const iterator& __q)
2522
      {
2523
	size_t __p_index = __p.index();
2524
	erase(__p_index, __q.index() - __p_index);
2525
	return iterator(this, __p_index);
2526
      }
2527
 
2528
      iterator
2529
      erase(const iterator& __p)
2530
      {
2531
	size_t __p_index = __p.index();
2532
	erase(__p_index, 1);
2533
	return iterator(this, __p_index);
2534
      }
2535
 
2536
      rope
2537
      substr(size_t __start, size_t __len = 1) const
2538
      {
2539
	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2540
						 __start,
2541
						 __start + __len));
2542
      }
2543
 
2544
      rope
2545
      substr(iterator __start, iterator __end) const
2546
      {
2547
	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2548
						 __start.index(),
2549
						 __end.index()));
2550
      }
2551
 
2552
      rope
2553
      substr(iterator __start) const
2554
      {
2555
	size_t __pos = __start.index();
2556
	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2557
						 __pos, __pos + 1));
2558
      }
2559
 
2560
      rope
2561
      substr(const_iterator __start, const_iterator __end) const
2562
      {
2563
	// This might eventually take advantage of the cache in the
2564
	// iterator.
2565
	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2566
						 __start.index(),
2567
						 __end.index()));
2568
      }
2569
 
2570
      rope<_CharT, _Alloc>
2571
      substr(const_iterator __start)
2572
      {
2573
	size_t __pos = __start.index();
2574
	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2575
						 __pos, __pos + 1));
2576
      }
2577
 
2578
      static const size_type npos;
2579
 
2580
      size_type find(_CharT __c, size_type __pos = 0) const;
2581
 
2582
      size_type
2583
      find(const _CharT* __s, size_type __pos = 0) const
2584
      {
2585
	size_type __result_pos;
2586
	const_iterator __result =
2587
	  std::search(const_begin() + __pos, const_end(),
2588
		      __s, __s + _S_char_ptr_len(__s));
2589
	__result_pos = __result.index();
2590
#ifndef __STL_OLD_ROPE_SEMANTICS
2591
	if (__result_pos == size())
2592
	  __result_pos = npos;
2593
#endif
2594
	return __result_pos;
2595
      }
2596
 
2597
      iterator
2598
      mutable_begin()
2599
      { return(iterator(this, 0)); }
2600
 
2601
      iterator
2602
      mutable_end()
2603
      { return(iterator(this, size())); }
2604
 
2605
      typedef std::reverse_iterator reverse_iterator;
2606
 
2607
      reverse_iterator
2608
      mutable_rbegin()
2609
      { return reverse_iterator(mutable_end()); }
2610
 
2611
      reverse_iterator
2612
      mutable_rend()
2613
      { return reverse_iterator(mutable_begin()); }
2614
 
2615
      reference
2616
      mutable_reference_at(size_type __pos)
2617
      { return reference(this, __pos); }
2618
 
2619
#ifdef __STD_STUFF
2620
      reference
2621
      operator[] (size_type __pos)
2622
      { return _char_ref_proxy(this, __pos); }
2623
 
2624
      reference
2625
      at(size_type __pos)
2626
      {
2627
	// if (__pos >= size()) throw out_of_range;  // XXX
2628
	return (*this)[__pos];
2629
      }
2630
 
2631
      void resize(size_type __n, _CharT __c) { }
2632
      void resize(size_type __n) { }
2633
      void reserve(size_type __res_arg = 0) { }
2634
 
2635
      size_type
2636
      capacity() const
2637
      { return max_size(); }
2638
 
2639
      // Stuff below this line is dangerous because it's error prone.
2640
      // I would really like to get rid of it.
2641
      // copy function with funny arg ordering.
2642
      size_type
2643
      copy(_CharT* __buffer, size_type __n,
2644
	   size_type __pos = 0) const
2645
      { return copy(__pos, __n, __buffer); }
2646
 
2647
      iterator
2648
      end()
2649
      { return mutable_end(); }
2650
 
2651
      iterator
2652
      begin()
2653
      { return mutable_begin(); }
2654
 
2655
      reverse_iterator
2656
      rend()
2657
      { return mutable_rend(); }
2658
 
2659
      reverse_iterator
2660
      rbegin()
2661
      { return mutable_rbegin(); }
2662
 
2663
#else
2664
      const_iterator
2665
      end()
2666
      { return const_end(); }
2667
 
2668
      const_iterator
2669
      begin()
2670
      { return const_begin(); }
2671
 
2672
      const_reverse_iterator
2673
      rend()
2674
      { return const_rend(); }
2675
 
2676
      const_reverse_iterator
2677
      rbegin()
2678
      { return const_rbegin(); }
2679
 
2680
#endif
2681
    };
2682
 
2683
  template 
2684
    const typename rope<_CharT, _Alloc>::size_type
2685
    rope<_CharT, _Alloc>::npos = (size_type)(-1);
2686
 
2687
  template 
2688
    inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2689
			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2690
    { return (__x._M_current_pos == __y._M_current_pos
2691
	      && __x._M_root == __y._M_root); }
2692
 
2693
  template 
2694
    inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2695
			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2696
    { return (__x._M_current_pos < __y._M_current_pos); }
2697
 
2698
  template 
2699
    inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2700
			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2701
    { return !(__x == __y); }
2702
 
2703
  template 
2704
    inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2705
			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2706
    { return __y < __x; }
2707
 
2708
  template 
2709
    inline bool
2710
    operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2711
	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2712
    { return !(__y < __x); }
2713
 
2714
  template 
2715
    inline bool
2716
    operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2717
	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2718
    { return !(__x < __y); }
2719
 
2720
  template 
2721
    inline ptrdiff_t
2722
    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2723
	      const _Rope_const_iterator<_CharT, _Alloc>& __y)
2724
    { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; }
2725
 
2726
  template 
2727
    inline _Rope_const_iterator<_CharT, _Alloc>
2728
    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2729
    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2730
						  __x._M_current_pos - __n); }
2731
 
2732
  template 
2733
    inline _Rope_const_iterator<_CharT, _Alloc>
2734
    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2735
    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2736
						  __x._M_current_pos + __n); }
2737
 
2738
  template 
2739
    inline _Rope_const_iterator<_CharT, _Alloc>
2740
    operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x)
2741
  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2742
						__x._M_current_pos + __n); }
2743
 
2744
  template 
2745
    inline bool
2746
    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
2747
	       const _Rope_iterator<_CharT, _Alloc>& __y)
2748
    {return (__x._M_current_pos == __y._M_current_pos
2749
	     && __x._M_root_rope == __y._M_root_rope); }
2750
 
2751
  template 
2752
    inline bool
2753
    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
2754
	      const _Rope_iterator<_CharT, _Alloc>& __y)
2755
    { return (__x._M_current_pos < __y._M_current_pos); }
2756
 
2757
  template 
2758
    inline bool
2759
    operator!=(const _Rope_iterator<_CharT, _Alloc>& __x,
2760
	       const _Rope_iterator<_CharT, _Alloc>& __y)
2761
    { return !(__x == __y); }
2762
 
2763
  template 
2764
    inline bool
2765
    operator>(const _Rope_iterator<_CharT, _Alloc>& __x,
2766
	      const _Rope_iterator<_CharT, _Alloc>& __y)
2767
    { return __y < __x; }
2768
 
2769
  template 
2770
    inline bool
2771
    operator<=(const _Rope_iterator<_CharT, _Alloc>& __x,
2772
	       const _Rope_iterator<_CharT, _Alloc>& __y)
2773
    { return !(__y < __x); }
2774
 
2775
  template 
2776
    inline bool
2777
    operator>=(const _Rope_iterator<_CharT, _Alloc>& __x,
2778
	       const _Rope_iterator<_CharT, _Alloc>& __y)
2779
    { return !(__x < __y); }
2780
 
2781
  template 
2782
    inline ptrdiff_t
2783
    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2784
	      const _Rope_iterator<_CharT, _Alloc>& __y)
2785
    { return ((ptrdiff_t)__x._M_current_pos
2786
	      - (ptrdiff_t)__y._M_current_pos); }
2787
 
2788
  template 
2789
    inline _Rope_iterator<_CharT, _Alloc>
2790
    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2791
	      ptrdiff_t __n)
2792
    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2793
					    __x._M_current_pos - __n); }
2794
 
2795
  template 
2796
    inline _Rope_iterator<_CharT, _Alloc>
2797
    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2798
    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2799
					    __x._M_current_pos + __n); }
2800
 
2801
  template 
2802
    inline _Rope_iterator<_CharT, _Alloc>
2803
    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x)
2804
    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2805
					    __x._M_current_pos + __n); }
2806
 
2807
  template 
2808
    inline rope<_CharT, _Alloc>
2809
    operator+(const rope<_CharT, _Alloc>& __left,
2810
	      const rope<_CharT, _Alloc>& __right)
2811
    {
2812
      // Inlining this should make it possible to keep __left and
2813
      // __right in registers.
2814
      typedef rope<_CharT, _Alloc> rope_type;
2815
      return rope_type(rope_type::_S_concat(__left._M_tree_ptr,
2816
					    __right._M_tree_ptr));
2817
    }
2818
 
2819
  template 
2820
    inline rope<_CharT, _Alloc>&
2821
    operator+=(rope<_CharT, _Alloc>& __left,
2822
	       const rope<_CharT, _Alloc>& __right)
2823
    {
2824
      __left.append(__right);
2825
      return __left;
2826
    }
2827
 
2828
  template 
2829
    inline rope<_CharT, _Alloc>
2830
    operator+(const rope<_CharT, _Alloc>& __left,
2831
	      const _CharT* __right)
2832
    {
2833
      typedef rope<_CharT, _Alloc> rope_type;
2834
      size_t __rlen = rope_type::_S_char_ptr_len(__right);
2835
      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2836
						      __right, __rlen));
2837
    }
2838
 
2839
  template 
2840
    inline rope<_CharT, _Alloc>&
2841
    operator+=(rope<_CharT, _Alloc>& __left,
2842
	       const _CharT* __right)
2843
    {
2844
      __left.append(__right);
2845
      return __left;
2846
    }
2847
 
2848
  template 
2849
    inline rope<_CharT, _Alloc>
2850
    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
2851
    {
2852
      typedef rope<_CharT, _Alloc> rope_type;
2853
      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2854
						      &__right, 1));
2855
    }
2856
 
2857
  template 
2858
    inline rope<_CharT, _Alloc>&
2859
    operator+=(rope<_CharT, _Alloc>& __left, _CharT __right)
2860
    {
2861
      __left.append(__right);
2862
      return __left;
2863
    }
2864
 
2865
  template 
2866
    bool
2867
    operator<(const rope<_CharT, _Alloc>& __left,
2868
	      const rope<_CharT, _Alloc>& __right)
2869
    { return __left.compare(__right) < 0; }
2870
 
2871
  template 
2872
    bool
2873
    operator==(const rope<_CharT, _Alloc>& __left,
2874
	       const rope<_CharT, _Alloc>& __right)
2875
    { return __left.compare(__right) == 0; }
2876
 
2877
  template 
2878
    inline bool
2879
    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2880
	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2881
    { return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); }
2882
 
2883
  template 
2884
    inline bool
2885
    operator!=(const rope<_CharT, _Alloc>& __x,
2886
	       const rope<_CharT, _Alloc>& __y)
2887
    { return !(__x == __y); }
2888
 
2889
  template 
2890
    inline bool
2891
    operator>(const rope<_CharT, _Alloc>& __x,
2892
	      const rope<_CharT, _Alloc>& __y)
2893
    { return __y < __x; }
2894
 
2895
  template 
2896
    inline bool
2897
    operator<=(const rope<_CharT, _Alloc>& __x,
2898
	       const rope<_CharT, _Alloc>& __y)
2899
    { return !(__y < __x); }
2900
 
2901
  template 
2902
    inline bool
2903
    operator>=(const rope<_CharT, _Alloc>& __x,
2904
	       const rope<_CharT, _Alloc>& __y)
2905
    { return !(__x < __y); }
2906
 
2907
  template 
2908
    inline bool
2909
    operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2910
	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2911
    { return !(__x == __y); }
2912
 
2913
  template
2914
    std::basic_ostream<_CharT, _Traits>&
2915
    operator<<(std::basic_ostream<_CharT, _Traits>& __o,
2916
	       const rope<_CharT, _Alloc>& __r);
2917
 
2918
  typedef rope crope;
2919
  typedef rope wrope;
2920
 
2921
  inline crope::reference
2922
  __mutable_reference_at(crope& __c, size_t __i)
2923
  { return __c.mutable_reference_at(__i); }
2924
 
2925
  inline wrope::reference
2926
  __mutable_reference_at(wrope& __c, size_t __i)
2927
  { return __c.mutable_reference_at(__i); }
2928
 
2929
  template 
2930
    inline void
2931
    swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y)
2932
    { __x.swap(__y); }
2933
 
2934
_GLIBCXX_END_NAMESPACE_VERSION
2935
} // namespace
2936
 
2937
 
2938
namespace std _GLIBCXX_VISIBILITY(default)
2939
{
2940
namespace tr1
2941
{
2942
_GLIBCXX_BEGIN_NAMESPACE_VERSION
2943
 
2944
  template<>
2945
    struct hash<__gnu_cxx::crope>
2946
    {
2947
      size_t
2948
      operator()(const __gnu_cxx::crope& __str) const
2949
      {
2950
	size_t __size = __str.size();
2951
	if (0 == __size)
2952
	  return 0;
2953
	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2954
      }
2955
    };
2956
 
2957
 
2958
  template<>
2959
    struct hash<__gnu_cxx::wrope>
2960
    {
2961
      size_t
2962
      operator()(const __gnu_cxx::wrope& __str) const
2963
      {
2964
	size_t __size = __str.size();
2965
	if (0 == __size)
2966
	  return 0;
2967
	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2968
      }
2969
    };
2970
 
2971
_GLIBCXX_END_NAMESPACE_VERSION
2972
} // namespace tr1
2973
} // namespace std
2974
 
2975
# include 
2976
 
2977
#endif