📄 rope
字号:
_RopeSubstring* __space = typename _Base::_SAlloc(__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[_Rope_constants::_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 == this->_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(this->_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 = this->_Data_allocate(_S_rounded_up_size(1));
std::_Construct(__buf, __c);
try {
this->_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)
{
this->_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(this->_M_tree_ptr);
}
~rope() throw()
{ _S_unref(this->_M_tree_ptr); }
rope& operator=(const rope& __x)
{
_RopeRep* __old = this->_M_tree_ptr;
this->_M_tree_ptr = __x._M_tree_ptr;
_S_ref(this->_M_tree_ptr);
_S_unref(__old);
return *this;
}
void clear()
{
_S_unref(this->_M_tree_ptr);
this->_M_tree_ptr = 0;
}
void push_back(_CharT __x)
{
_RopeRep* __old = this->_M_tree_ptr;
this->_M_tree_ptr
= _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);
_S_unref(__old);
}
void pop_back()
{
_RopeRep* __old = this->_M_tree_ptr;
this->_M_tree_ptr =
_S_substring(this->_M_tree_ptr,
0,
this->_M_tree_ptr->_M_size - 1);
_S_unref(__old);
}
_CharT back() const
{
return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1);
}
void push_front(_CharT __x)
{
_RopeRep* __old = this->_M_tree_ptr;
_RopeRep* __left =
__STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, this->get_allocator());
try {
this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
_S_unref(__old);
_S_unref(__left);
}
catch(...)
{
_S_unref(__left);
__throw_exception_again;
}
}
void pop_front()
{
_RopeRep* __old = this->_M_tree_ptr;
this->_M_tree_ptr
= _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
_S_unref(__old);
}
_CharT front() const
{
return _S_fetch(this->_M_tree_ptr, 0);
}
void balance()
{
_RopeRep* __old = this->_M_tree_ptr;
this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
_S_unref(__old);
}
void copy(_CharT* __buffer) const {
_Destroy(__buffer, __buffer + size());
_S_flatten(this->_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(this->_M_tree_ptr, __pos, __len, __buffer);
return __len;
}
// Print to stdout, exposing structure. May be useful for
// performance debugging.
void dump() {
_S_dump(this->_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 == this->_M_tree_ptr) return;
if (_Rope_constants::_S_leaf == this->_M_tree_ptr->_M_tag &&
((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==
this->_M_tree_ptr->_M_c_string) {
// Representation shared
return;
}
# ifndef __GC
this->_M_tree_ptr->_M_free_c_string();
# endif
this->_M_tree_ptr->_M_c_string = 0;
}
_CharT operator[] (size_type __pos) const {
return _S_fetch(this->_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(this->_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(this->_M_tree_ptr, 0));
}
const_iterator end() const {
return(const_iterator(this->_M_tree_ptr, size()));
}
const_iterator const_end() const {
return(const_iterator(this->_M_tree_ptr, size()));
}
size_type size() const {
return(0 == this->_M_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -