_rope.h
来自「stl的源码」· C头文件 代码 · 共 1,929 行 · 第 1/5 页
H
1,929 行
typedef _STLP_TYPENAME _STLP_PRIV _BasicCharType<_CharT>::_Ret _IsBasicCharType;#if 0 /* Please tell why this code is necessary if you uncomment it. * Problem with it is that rope implementation expect that _S_rounded_up_size(n) * returns a size > n in order to store the terminating null charater. When * instanciation type is not a char or wchar_t this is not guaranty resulting in * memory overrun. */ static size_t _S_rounded_up_size_aux(size_t __n, __true_type const& /*_IsBasicCharType*/) { // Allow slop for in-place expansion. return (__n + _S_alloc_granularity) & ~(_S_alloc_granularity - 1); } static size_t _S_rounded_up_size_aux(size_t __n, __false_type const& /*_IsBasicCharType*/) { // Allow slop for in-place expansion. return (__n + _S_alloc_granularity - 1) & ~(_S_alloc_granularity - 1); }#endif // fbp : moved from RopeLeaf static size_t _S_rounded_up_size(size_t __n) //{ return _S_rounded_up_size_aux(__n, _IsBasicCharType()); } { return (__n + _S_alloc_granularity) & ~(_S_alloc_granularity - 1); } static void _S_free_string( _CharT* __s, size_t __len, allocator_type __a) { _STLP_STD::_Destroy_Range(__s, __s + __len); // This has to be a static member, so this gets a bit messy# ifndef _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE __a.deallocate(__s, _S_rounded_up_size(__len)); //*ty 03/24/2001 - restored not to use __stl_alloc_rebind() since it is not defined under _STLP_MEMBER_TEMPLATE_CLASSES# else __stl_alloc_rebind (__a, (_CharT*)0).deallocate(__s, _S_rounded_up_size(__len));# endif } // Deallocate data section of a leaf. // This shouldn't be a member function. // But its hard to do anything else at the // moment, because it's templatized w.r.t. // an allocator. // Does nothing if __GC is defined. void _M_free_c_string(); void _M_free_tree(); // Deallocate t. Assumes t is not 0. void _M_unref_nonnil() { if (_M_decr() == 0) _M_free_tree(); } void _M_ref_nonnil() { _M_incr(); } static void _S_unref(_Self* __t) { if (0 != __t) { __t->_M_unref_nonnil(); } } static void _S_ref(_Self* __t) { if (0 != __t) __t->_M_incr(); } //static void _S_free_if_unref(_Self* __t) { // if (0 != __t && 0 == __t->_M_ref_count) __t->_M_free_tree(); //}};template<class _CharT, class _Alloc>struct _Rope_RopeLeaf : public _Rope_RopeRep<_CharT,_Alloc> {public: _CharT* _M_data; /* Not necessarily 0 terminated. */ /* The allocated size is */ /* _S_rounded_up_size(size), except */ /* in the GC case, in which it */ /* doesn't matter. */private: typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; typedef typename _RopeRep::_IsBasicCharType _IsBasicCharType; void _M_init(__true_type const& /*_IsBasicCharType*/) { this->_M_c_string = _M_data; } void _M_init(__false_type const& /*_IsBasicCharType*/) {}public: _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) typedef typename _RopeRep::allocator_type allocator_type; _Rope_RopeLeaf( _CharT* __d, size_t _p_size, allocator_type __a) : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_leaf, 0, true, _p_size, __a), _M_data(__d) { _STLP_ASSERT(_p_size > 0) _M_init(_IsBasicCharType()); }# ifdef _STLP_NO_ARROW_OPERATOR _Rope_RopeLeaf() {} _Rope_RopeLeaf(const _Rope_RopeLeaf<_CharT, _Alloc>& ) {}# endif// The constructor assumes that d has been allocated with // the proper allocator and the properly padded size. // In contrast, the destructor deallocates the data: ~_Rope_RopeLeaf() { if (_M_data != this->_M_c_string) { this->_M_free_c_string(); } _RopeRep::_S_free_string(_M_data, this->_M_size._M_data, this->get_allocator()); }};template<class _CharT, class _Alloc>struct _Rope_RopeConcatenation : public _Rope_RopeRep<_CharT, _Alloc> {private: typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;public: _RopeRep* _M_left; _RopeRep* _M_right; _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) typedef typename _RopeRep::allocator_type allocator_type; _Rope_RopeConcatenation(_RopeRep* __l, _RopeRep* __r, allocator_type __a) : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_concat, (max)(__l->_M_depth, __r->_M_depth) + 1, false, __l->_M_size._M_data + __r->_M_size._M_data, __a), _M_left(__l), _M_right(__r) {}# ifdef _STLP_NO_ARROW_OPERATOR _Rope_RopeConcatenation() {} _Rope_RopeConcatenation(const _Rope_RopeConcatenation<_CharT, _Alloc>&) {}# endif ~_Rope_RopeConcatenation() { this->_M_free_c_string(); _M_left->_M_unref_nonnil(); _M_right->_M_unref_nonnil(); }};template <class _CharT, class _Alloc>struct _Rope_RopeFunction : public _Rope_RopeRep<_CharT, _Alloc> {private: typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;public: char_producer<_CharT>* _M_fn; /* * Char_producer is owned by the * rope and should be explicitly * deleted when the rope becomes * inaccessible. */ bool _M_delete_when_done; _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) typedef typename _Rope_RopeRep<_CharT,_Alloc>::allocator_type allocator_type;# ifdef _STLP_NO_ARROW_OPERATOR _Rope_RopeFunction() {} _Rope_RopeFunction(const _Rope_RopeFunction<_CharT, _Alloc>& ) {}# endif _Rope_RopeFunction(char_producer<_CharT>* __f, size_t _p_size, bool __d, allocator_type __a) : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_function, 0, true, _p_size, __a), _M_fn(__f) , _M_delete_when_done(__d) { _STLP_ASSERT(_p_size > 0) } ~_Rope_RopeFunction() { this->_M_free_c_string(); if (_M_delete_when_done) { delete _M_fn; } }};/* * Substring results are usually represented using just * concatenation nodes. But in the case of very long flat ropes * or ropes with a functional representation that isn't practical. * In that case, we represent the __result as a special case of * RopeFunction, whose char_producer points back to the rope itself. * In all cases except repeated substring operations and * deallocation, we treat the __result as a RopeFunction. */template<class _CharT, class _Alloc>struct _Rope_RopeSubstring : public char_producer<_CharT>, public _Rope_RopeFunction<_CharT,_Alloc> {public: // XXX this whole class should be rewritten. typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; _RopeRep *_M_base; // not 0 size_t _M_start; /* virtual */ void operator()(size_t __start_pos, size_t __req_len, _CharT* __buffer) { typedef _Rope_RopeFunction<_CharT,_Alloc> _RopeFunction; typedef _Rope_RopeLeaf<_CharT,_Alloc> _RopeLeaf; switch (_M_base->_M_tag) { case _RopeRep::_S_function: case _RopeRep::_S_substringfn: { char_producer<_CharT>* __fn = __STATIC_CAST(_RopeFunction*, _M_base)->_M_fn; _STLP_ASSERT(__start_pos + __req_len <= this->_M_size._M_data) _STLP_ASSERT(_M_start + this->_M_size._M_data <= _M_base->_M_size._M_data) (*__fn)(__start_pos + _M_start, __req_len, __buffer); } break; case _RopeRep::_S_leaf: { _CharT* __s = __STATIC_CAST(_RopeLeaf*, _M_base)->_M_data; _STLP_PRIV __ucopy_n(__s + __start_pos + _M_start, __req_len, __buffer); } break; default: _STLP_ASSERT(false) ; } } _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) typedef typename _RopeRep::allocator_type allocator_type; _Rope_RopeSubstring(_RopeRep* __b, size_t __s, size_t __l, allocator_type __a) : _Rope_RopeFunction<_CharT,_Alloc>(this, __l, false, __a), _M_base(__b), _M_start(__s) { _STLP_ASSERT(__l > 0) _STLP_ASSERT(__s + __l <= __b->_M_size._M_data) _M_base->_M_ref_nonnil(); this->_M_tag = _RopeRep::_S_substringfn; } virtual ~_Rope_RopeSubstring() { _M_base->_M_unref_nonnil(); }};/* * Self-destructing pointers to Rope_rep. * These are not conventional smart pointers. Their * only purpose in life is to ensure that unref is called * on the pointer either at normal exit or if an exception * is raised. It is the caller's responsibility to * adjust reference counts when these pointers are initialized * or assigned to. (This convention significantly reduces * the number of potentially expensive reference count * updates.) */template<class _CharT, class _Alloc>struct _Rope_self_destruct_ptr { _Rope_RopeRep<_CharT,_Alloc>* _M_ptr; ~_Rope_self_destruct_ptr() { _Rope_RopeRep<_CharT,_Alloc>::_S_unref(_M_ptr); }# ifdef _STLP_USE_EXCEPTIONS _Rope_self_destruct_ptr() : _M_ptr(0) {}# else _Rope_self_destruct_ptr() {}# endif _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT,_Alloc>* __p) : _M_ptr(__p) {} _Rope_RopeRep<_CharT,_Alloc>& operator*() { return *_M_ptr; } _Rope_RopeRep<_CharT,_Alloc>* operator->() { return _M_ptr; } operator _Rope_RopeRep<_CharT,_Alloc>*() { return _M_ptr; } _Rope_self_destruct_ptr<_CharT, _Alloc>& operator= (_Rope_RopeRep<_CharT,_Alloc>* __x) { _M_ptr = __x; return *this; }};/* * Dereferencing a nonconst iterator has to return something * that behaves almost like a reference. It's not possible to * return an actual reference since assignment requires extra * work. And we would get into the same problems as with the * CD2 version of basic_string. */template<class _CharT, class _Alloc>class _Rope_char_ref_proxy { typedef _Rope_char_ref_proxy<_CharT, _Alloc> _Self; friend class rope<_CharT,_Alloc>; friend class _Rope_iterator<_CharT,_Alloc>; friend class _Rope_char_ptr_proxy<_CharT,_Alloc>; typedef _Rope_self_destruct_ptr<_CharT,_Alloc> _Self_destruct_ptr; typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; typedef rope<_CharT,_Alloc> _My_rope; size_t _M_pos; _CharT _M_current; bool _M_current_valid; _My_rope* _M_root; // The whole rope.public: _Rope_char_ref_proxy(_My_rope* __r, size_t __p) : _M_pos(__p), _M_current_valid(false), _M_root(__r) {} _Rope_char_ref_proxy(const _Self& __x) : _M_pos(__x._M_pos), _M_current_valid(false), _M_root(__x._M_root) {} // Don't preserve cache if the reference can outlive the // expression. We claim that's not possible without calling // a copy constructor or generating reference to a proxy // reference. We declare the latter to have undefined semantics. _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c) : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) {} inline operator _CharT () const; _Self& operator= (_CharT __c); _Rope_char_ptr_proxy<_CharT, _Alloc> operator& () const; _Self& operator= (const _Self& __c) { return operator=((_CharT)__c); }};#ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDERtemplate<class _CharT, class __Alloc>inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a, _Rope_char_ref_proxy <_CharT, __Alloc > __b) { _CharT __tmp = __a; __a = __b; __b = __tmp;}#else// There is no really acceptable way to handle this. The default// definition of swap doesn't work for proxy references.// It can't really be made to work, even with ugly hacks, since// the only unusual operation it uses is the copy constructor, which// is needed for other purposes. We provide a macro for// full specializations, and instantiate the most common case.# define _ROPE_SWAP_SPECIALIZATION(_CharT, __Alloc) \ inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a, \ _Rope_char_ref_proxy <_CharT, __Alloc > __b) { \ _CharT __tmp = __a; \ __a = __b; \ __b = __tmp; \ }_ROPE_SWAP_SPECIALIZATION(char, allocator<char>)# ifndef _STLP_NO_WCHAR_T_ROPE_SWAP_SPECIALIZATION(wchar_t, allocator<wchar_t>)# endif#endif /* !_STLP_FUNCTION_TMPL_PARTIAL_ORDER */template<class _CharT, class _Alloc>class _Rope_char_ptr_proxy { // XXX this class should be rewritten.public: typedef _Rope_char_ptr_proxy<_CharT, _Alloc> _Self; friend class _Rope_char_ref_proxy<_CharT,_Alloc>; size_t _M_pos; rope<_CharT,_Alloc>* _M_root; // The whole rope. _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x) : _M_pos(__x._M_pos), _M_root(__x._M_root) {} _Rope_char_ptr_proxy(const _Self& __x) : _M_pos(__x._M_pos), _M_root(__x._M_root) {} _Rope_char_ptr_proxy() {} _Rope_char_ptr_proxy(_CharT* __x) : _M_pos(0), _M_root(0) { _STLP_ASSERT(0 == __x) } _Self& operator= (const _Self& __x) { _M_pos = __x._M_pos; _M_root = __x._M_root; return *this; } _Rope_char_ref_proxy<_CharT,_Alloc> operator*() const { return _Rope_char_ref_proxy<_CharT,_Alloc>(_M_root, _M_pos); }};/* * Rope iterators: * Unlike in the C version, we cache only part of the stack * for rope iterators, since they must be efficiently copyable. * When we run out of cache, we have to reconstruct the iterator * value. * Pointers from iterators are not included in reference counts. * Iterators are assumed to be thread private. Ropes can * be shared. */template<class _CharT, class _Alloc>class _Rope_iterator_base/* : public random_access_iterator<_CharT, ptrdiff_t> */{ friend class rope<_CharT,_Alloc>; typedef _Rope_iterator_base<_CharT, _Alloc> _Self; typedef _Rope_RopeConcatenation<_CharT,_Alloc> _RopeConcat;public: typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; enum { _S_path_cache_len = 4 }; // Must be <= 9 because of _M_path_direction. enum { _S_iterator_buf_len = 15 }; size_t _M_current_pos; // The whole rope. _RopeRep* _M_root; // Starting position for current leaf size_t _M_leaf_pos; // Buffer possibly containing current char. _CharT* _M_buf_start; // Pointer to current char in buffer, != 0 ==> buffer valid. _CharT* _M_buf_ptr;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?