📄 stl_rope.h
字号:
_RopeFunction* __space = typename _Base::_FAllocator(__a).allocate(1); return new(__space) _RopeFunction(__f, __size, __d, __a); } static _RopeSubstring* _S_new_RopeSubstring( _Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s, size_t __l, allocator_type __a) { _RopeSubstring* __space = typename _Base::_SAllocator(__a).allocate(1); return new(__space) _RopeSubstring(__b, __s, __l, __a); } static _RopeLeaf* _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s, size_t __size, allocator_type __a)# define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \ _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a) { if (0 == __size) return 0; _CharT* __buf = __a.allocate(_S_rounded_up_size(__size)); uninitialized_copy_n(__s, __size, __buf); _S_cond_store_eos(__buf[__size]); try { return _S_new_RopeLeaf(__buf, __size, __a); } catch(...) { _RopeRep::__STL_FREE_STRING(__buf, __size, __a); __throw_exception_again; } } // Concatenation of nonempty strings. // Always builds a concatenation node. // Rebalances if the result is too deep. // Result has refcount 1. // Does not increment left and right ref counts even though // they are referenced. static _RopeRep* _S_tree_concat(_RopeRep* __left, _RopeRep* __right); // Concatenation helper functions static _RopeLeaf* _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __slen); // Concatenate by copying leaf. // should take an arbitrary iterator // result has refcount 1.# ifndef __GC static _RopeLeaf* _S_destr_leaf_concat_char_iter (_RopeLeaf* __r, const _CharT* __iter, size_t __slen); // A version that potentially clobbers __r if __r->_M_ref_count == 1.# endif private: static size_t _S_char_ptr_len(const _CharT* __s); // slightly generalized strlen rope(_RopeRep* __t, const allocator_type& __a = allocator_type()) : _Base(__t,__a) { } // Copy __r to the _CharT buffer. // Returns __buffer + __r->_M_size. // Assumes that buffer is uninitialized. static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer); // Again, with explicit starting position and length. // Assumes that buffer is uninitialized. static _CharT* _S_flatten(_RopeRep* __r, size_t __start, size_t __len, _CharT* __buffer); static const unsigned long _S_min_len[_RopeRep::_S_max_rope_depth + 1]; static bool _S_is_balanced(_RopeRep* __r) { return (__r->_M_size >= _S_min_len[__r->_M_depth]); } static bool _S_is_almost_balanced(_RopeRep* __r) { return (__r->_M_depth == 0 || __r->_M_size >= _S_min_len[__r->_M_depth - 1]); } static bool _S_is_roughly_balanced(_RopeRep* __r) { return (__r->_M_depth <= 1 || __r->_M_size >= _S_min_len[__r->_M_depth - 2]); } // Assumes the result is not empty. static _RopeRep* _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right) { _RopeRep* __result = _S_concat(__left, __right); if (_S_is_balanced(__result)) __result->_M_is_balanced = true; return __result; } // The basic rebalancing operation. Logically copies the // rope. The result has refcount of 1. The client will // usually decrement the reference count of __r. // The result is within height 2 of balanced by the above // definition. static _RopeRep* _S_balance(_RopeRep* __r); // Add all unbalanced subtrees to the forest of balanceed trees. // Used only by balance. static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest); // Add __r to forest, assuming __r is already balanced. static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest); // Print to stdout, exposing structure static void _S_dump(_RopeRep* __r, int __indent = 0); // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp. static int _S_compare(const _RopeRep* __x, const _RopeRep* __y); public: bool empty() const { return 0 == _M_tree_ptr; } // Comparison member function. This is public only for those // clients that need a ternary comparison. Others // should use the comparison operators below. int compare(const rope& __y) const { return _S_compare(_M_tree_ptr, __y._M_tree_ptr); } rope(const _CharT* __s, const allocator_type& __a = allocator_type()) : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s), __a),__a) { } rope(const _CharT* __s, size_t __len, const allocator_type& __a = allocator_type()) : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, __a), __a) { } // Should perhaps be templatized with respect to the iterator type // and use Sequence_buffer. (It should perhaps use sequence_buffer // even now.) rope(const _CharT *__s, const _CharT *__e, const allocator_type& __a = allocator_type()) : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, __a), __a) { } rope(const const_iterator& __s, const const_iterator& __e, const allocator_type& __a = allocator_type()) : _Base(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos), __a) { } rope(const iterator& __s, const iterator& __e, const allocator_type& __a = allocator_type()) : _Base(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos), __a) { } rope(_CharT __c, const allocator_type& __a = allocator_type()) : _Base(__a) { _CharT* __buf = _Data_allocate(_S_rounded_up_size(1)); std::_Construct(__buf, __c); try { _M_tree_ptr = _S_new_RopeLeaf(__buf, 1, __a); } catch(...) { _RopeRep::__STL_FREE_STRING(__buf, 1, __a); __throw_exception_again; } } rope(size_t __n, _CharT __c, const allocator_type& __a = allocator_type()); rope(const allocator_type& __a = allocator_type()) : _Base(0, __a) {} // Construct a rope from a function that can compute its members rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_tree_ptr = (0 == __len) ? 0 : _S_new_RopeFunction(__fn, __len, __delete_fn, __a); } rope(const rope& __x, const allocator_type& __a = allocator_type()) : _Base(__x._M_tree_ptr, __a) { _S_ref(_M_tree_ptr); } ~rope() { _S_unref(_M_tree_ptr); } rope& operator=(const rope& __x) { _RopeRep* __old = _M_tree_ptr; _M_tree_ptr = __x._M_tree_ptr; _S_ref(_M_tree_ptr); _S_unref(__old); return(*this); } void clear() { _S_unref(_M_tree_ptr); _M_tree_ptr = 0; } void push_back(_CharT __x) { _RopeRep* __old = _M_tree_ptr; _M_tree_ptr = _S_destr_concat_char_iter(_M_tree_ptr, &__x, 1); _S_unref(__old); } void pop_back() { _RopeRep* __old = _M_tree_ptr; _M_tree_ptr = _S_substring(_M_tree_ptr, 0, _M_tree_ptr->_M_size - 1); _S_unref(__old); } _CharT back() const { return _S_fetch(_M_tree_ptr, _M_tree_ptr->_M_size - 1); } void push_front(_CharT __x) { _RopeRep* __old = _M_tree_ptr; _RopeRep* __left = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, get_allocator()); try { _M_tree_ptr = _S_concat(__left, _M_tree_ptr); _S_unref(__old); _S_unref(__left); } catch(...) { _S_unref(__left); __throw_exception_again; } } void pop_front() { _RopeRep* __old = _M_tree_ptr; _M_tree_ptr = _S_substring(_M_tree_ptr, 1, _M_tree_ptr->_M_size); _S_unref(__old); } _CharT front() const { return _S_fetch(_M_tree_ptr, 0); } void balance() { _RopeRep* __old = _M_tree_ptr; _M_tree_ptr = _S_balance(_M_tree_ptr); _S_unref(__old); } void copy(_CharT* __buffer) const { _Destroy(__buffer, __buffer + size()); _S_flatten(_M_tree_ptr, __buffer); } // This is the copy function from the standard, but // with the arguments reordered to make it consistent with the // rest of the interface. // Note that this guaranteed not to compile if the draft standard // order is assumed. size_type copy(size_type __pos, size_type __n, _CharT* __buffer) const { size_t __size = size(); size_t __len = (__pos + __n > __size? __size - __pos : __n); _Destroy(__buffer, __buffer + __len); _S_flatten(_M_tree_ptr, __pos, __len, __buffer); return __len; } // Print to stdout, exposing structure. May be useful for // performance debugging. void dump() { _S_dump(_M_tree_ptr); } // Convert to 0 terminated string in new allocated memory. // Embedded 0s in the input do not terminate the copy. const _CharT* c_str() const; // As above, but lso use the flattened representation as the // the new rope representation. const _CharT* replace_with_c_str(); // Reclaim memory for the c_str generated flattened string. // Intentionally undocumented, since it's hard to say when this // is safe for multiple threads. void delete_c_str () { if (0 == _M_tree_ptr) return; if (_RopeRep::_S_leaf == _M_tree_ptr->_M_tag && ((_RopeLeaf*)_M_tree_ptr)->_M_data == _M_tree_ptr->_M_c_string) { // Representation shared return; }# ifndef __GC _M_tree_ptr->_M_free_c_string();# endif _M_tree_ptr->_M_c_string = 0; } _CharT operator[] (size_type __pos) const { return _S_fetch(_M_tree_ptr, __pos); } _CharT at(size_type __pos) const { // if (__pos >= size()) throw out_of_range; // XXX return (*this)[__pos]; } const_iterator begin() const { return(const_iterator(_M_tree_ptr, 0)); } // An easy way to get a const iterator from a non-const container. const_iterator const_begin() const { return(const_iterator(_M_tree_ptr, 0)); } const_iterator end() const { return(const_iterator(_M_tree_ptr, size())); } const_iterator const_end() con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -