_rope.c

来自「stl的源码」· C语言 代码 · 共 1,408 行 · 第 1/4 页

C
1,408
字号
/* * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Copyright (c) 1999 * Boris Fomitchev * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * *//* NOTE: This is an internal header file, included by other STL headers. *   You should not attempt to use it directly. */// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf// if necessary.  Assumes path_end[leaf_index] and leaf_pos are correct.// Results in a valid buf_ptr if the iterator can be legitimately// dereferenced.#ifndef _STLP_ROPEIMPL_H#define _STLP_ROPEIMPL_H#ifndef _STLP_INTERNAL_ROPE_H#  include <stl/_rope.h>#endif#ifndef _STLP_INTERNAL_CSTDIO#  include <stl/_cstdio.h>#endif#if !defined (_STLP_USE_NO_IOSTREAMS)#  ifndef _STLP_INTERNAL_OSTREAM_H#    include <stl/_ostream.h>#  endif#  ifndef _STLP_INTERNAL_ISTREAM#    include <stl/_istream.h>#  endif#endif#include <stl/_range_errors.h>_STLP_BEGIN_NAMESPACE#if defined ( _STLP_NESTED_TYPE_PARAM_BUG )#  define __allocator__ _Alloc#else#  define __allocator__ allocator_type#endiftemplate<class _CharT, class _Alloc>_Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos)  : _Rope_iterator_base<_CharT,_Alloc>(__r->_M_tree_ptr._M_data, __pos),  _M_root_rope(__r) { _RopeRep::_S_ref(this->_M_root); }template<class _CharT, class _Alloc>_Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos):  _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr._M_data, __pos),  _M_root_rope(&__r) {#if !defined (__DMC__)  _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*this);#else  _Rope_iterator_base<_CharT, _Alloc>* __x = this;  _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*__x);#endif}template<class _CharT, class _Alloc>void _Rope_RopeRep<_CharT, _Alloc>::_M_free_c_string() {  _CharT* __cstr = _M_c_string;  if (0 != __cstr) {    size_t _p_size = _M_size._M_data + 1;    _STLP_STD::_Destroy_Range(__cstr, __cstr + _p_size);    _M_size.deallocate(__cstr, _p_size);  }}// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf// if necessary.  Assumes _M_path_end[leaf_index] and leaf_pos are correct.// Results in a valid buf_ptr if the iterator can be legitimately// dereferenced.template <class _CharT, class _Alloc>void _Rope_iterator_base<_CharT,_Alloc>::_S_setbuf(  _Rope_iterator_base<_CharT,_Alloc>& __x) {  const _RopeRep* __leaf = __x._M_path_end._M_data[__x._M_leaf_index];  size_t __leaf_pos = __x._M_leaf_pos;  size_t __pos = __x._M_current_pos;  switch(__leaf->_M_tag) {  case _RopeRep::_S_leaf:    typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;    __x._M_buf_start = __STATIC_CAST(const _RopeLeaf*, __leaf)->_M_data;    __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos);    __x._M_buf_end = __x._M_buf_start + __leaf->_M_size._M_data;    break;  case _RopeRep::_S_function:  case _RopeRep::_S_substringfn:    {      size_t __len = _S_iterator_buf_len;      size_t __buf_start_pos = __leaf_pos;      size_t __leaf_end = __leaf_pos + __leaf->_M_size._M_data;      typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;      char_producer<_CharT>* __fn = __STATIC_CAST(const _RopeFunction*, __leaf)->_M_fn;      if (__buf_start_pos + __len <= __pos) {        __buf_start_pos = __pos - __len/4;        if (__buf_start_pos + __len > __leaf_end) {          __buf_start_pos = __leaf_end - __len;        }      }      if (__buf_start_pos + __len > __leaf_end) {        __len = __leaf_end - __buf_start_pos;      }      (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf._M_data);      __x._M_buf_ptr = __x._M_tmp_buf._M_data + (__pos - __buf_start_pos);      __x._M_buf_start = __x._M_tmp_buf._M_data;      __x._M_buf_end = __x._M_tmp_buf._M_data + __len;    }    break;  default:      _STLP_ASSERT(0)      ;  }}// Set path and buffer inside a rope iterator.  We assume that// pos and root are already set.template <class _CharT, class _Alloc>void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache(  _Rope_iterator_base<_CharT,_Alloc>& __x) {  const _RopeRep* __path[_RopeRep::_S_max_rope_depth+1];  const _RopeRep* __curr_rope;  int __curr_depth = -1;  /* index into path    */  size_t __curr_start_pos = 0;  size_t __pos = __x._M_current_pos;  unsigned char __dirns = 0; // Bit vector marking right turns in the path  _STLP_ASSERT(__pos <= __x._M_root->_M_size._M_data)  if (__pos >= __x._M_root->_M_size._M_data) {    __x._M_buf_ptr = 0;    return;  }  __curr_rope = __x._M_root;  if (0 != __curr_rope->_M_c_string) {    /* Treat the root as a leaf. */    __x._M_buf_start = __curr_rope->_M_c_string;    __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size._M_data;    __x._M_buf_ptr = __curr_rope->_M_c_string + __pos;    __x._M_path_end._M_data[0] = __curr_rope;    __x._M_leaf_index = 0;    __x._M_leaf_pos = 0;    return;  }  for(;;) {    ++__curr_depth;    _STLP_ASSERT(__curr_depth <= _RopeRep::_S_max_rope_depth)    __path[__curr_depth] = __curr_rope;    switch(__curr_rope->_M_tag) {    case _RopeRep::_S_leaf:    case _RopeRep::_S_function:    case _RopeRep::_S_substringfn:      __x._M_leaf_pos = __curr_start_pos;      goto done;    case _RopeRep::_S_concat:      {        const _RopeConcat* __c = __STATIC_CAST(const _RopeConcat*, __curr_rope);        _RopeRep* __left = __c->_M_left;        size_t __left_len = __left->_M_size._M_data;        __dirns <<= 1;        if (__pos >= __curr_start_pos + __left_len) {          __dirns |= 1;          __curr_rope = __c->_M_right;          __curr_start_pos += __left_len;        } else {          __curr_rope = __left;        }      }      break;    }  }done:    // Copy last section of path into _M_path_end.  {    int __i = -1;    int __j = __curr_depth + 1 - _S_path_cache_len;    if (__j < 0) __j = 0;    while (__j <= __curr_depth) {      __x._M_path_end._M_data[++__i] = __path[__j++];    }    __x._M_leaf_index = __i;  }  __x._M_path_directions = __dirns;  _S_setbuf(__x);}// Specialized version of the above.  Assumes that// the path cache is valid for the previous position.template <class _CharT, class _Alloc>void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache_for_incr(_Rope_iterator_base<_CharT,_Alloc>& __x) {  int __current_index = __x._M_leaf_index;  const _RopeRep* __current_node = __x._M_path_end._M_data[__current_index];  size_t __len = __current_node->_M_size._M_data;  size_t __node_start_pos = __x._M_leaf_pos;  unsigned char __dirns = __x._M_path_directions;  const _RopeConcat* __c;  _STLP_ASSERT(__x._M_current_pos <= __x._M_root->_M_size._M_data)  if (__x._M_current_pos - __node_start_pos < __len) {    /* More stuff in this leaf, we just didn't cache it. */    _S_setbuf(__x);    return;  }  _STLP_ASSERT(__node_start_pos + __len == __x._M_current_pos)    //  node_start_pos is starting position of last_node.  while (--__current_index >= 0) {    if (!(__dirns & 1) /* Path turned left */)      break;    __current_node = __x._M_path_end._M_data[__current_index];    __c = __STATIC_CAST(const _RopeConcat*, __current_node);    // Otherwise we were in the right child.  Thus we should pop    // the concatenation node.    __node_start_pos -= __c->_M_left->_M_size._M_data;    __dirns >>= 1;  }  if (__current_index < 0) {    // We underflowed the cache. Punt.    _S_setcache(__x);    return;  }  __current_node = __x._M_path_end._M_data[__current_index];  __c = __STATIC_CAST(const _RopeConcat*, __current_node);  // current_node is a concatenation node.  We are positioned on the first  // character in its right child.  // node_start_pos is starting position of current_node.  __node_start_pos += __c->_M_left->_M_size._M_data;  __current_node = __c->_M_right;  __x._M_path_end._M_data[++__current_index] = __current_node;  __dirns |= 1;  while (_RopeRep::_S_concat == __current_node->_M_tag) {    ++__current_index;    if (_S_path_cache_len == __current_index) {      int __i;      for (__i = 0; __i < _S_path_cache_len-1; ++__i) {        __x._M_path_end._M_data[__i] = __x._M_path_end._M_data[__i+1];      }      --__current_index;    }    __current_node = __STATIC_CAST(const _RopeConcat*, __current_node)->_M_left;    __x._M_path_end._M_data[__current_index] = __current_node;    __dirns <<= 1;    // node_start_pos is unchanged.  }  __x._M_leaf_index = __current_index;  __x._M_leaf_pos = __node_start_pos;  __x._M_path_directions = __dirns;  _S_setbuf(__x);}template <class _CharT, class _Alloc>void _Rope_iterator_base<_CharT,_Alloc>::_M_incr(size_t __n) {  _M_current_pos += __n;  if (0 != _M_buf_ptr) {    size_t __chars_left = _M_buf_end - _M_buf_ptr;    if (__chars_left > __n) {      _M_buf_ptr += __n;    } else if (__chars_left == __n) {      _M_buf_ptr += __n;      _S_setcache_for_incr(*this);    } else {      _M_buf_ptr = 0;    }  }}template <class _CharT, class _Alloc>void _Rope_iterator_base<_CharT,_Alloc>::_M_decr(size_t __n) {  if (0 != _M_buf_ptr) {    size_t __chars_left = _M_buf_ptr - _M_buf_start;    if (__chars_left >= __n) {      _M_buf_ptr -= __n;    } else {      _M_buf_ptr = 0;    }  }  _M_current_pos -= __n;}template <class _CharT, class _Alloc>void _Rope_iterator<_CharT,_Alloc>::_M_check() {  if (_M_root_rope->_M_tree_ptr._M_data != this->_M_root) {    // _Rope was modified.  Get things fixed up.    _RopeRep::_S_unref(this->_M_root);    this->_M_root = _M_root_rope->_M_tree_ptr._M_data;    _RopeRep::_S_ref(this->_M_root);    this->_M_buf_ptr = 0;  }}//  There are several reasons for not doing this with virtual destructors//  and a class specific delete operator://  - A class specific delete operator can't easily get access to//    allocator instances if we need them.//  - Any virtual function would need a 4 or byte vtable pointer;//    this only requires a one byte tag per object.template <class _CharT, class _Alloc>void _Rope_RopeRep<_CharT,_Alloc>::_M_free_tree() {  switch (_M_tag) {  case _S_leaf:    {      typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;      _RopeLeaf* __l = __STATIC_CAST(_RopeLeaf*, this);      _STLP_STD::_Destroy(__l); // ->_Rope_RopeLeaf<_CharT,_Alloc>::~_Rope_RopeLeaf();      _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size,                             _RopeLeaf).deallocate(__l, 1);      break;    }  case _S_concat:    {      typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;      _RopeConcatenation* __c  = __STATIC_CAST(_RopeConcatenation*, this);      _STLP_STD::_Destroy(__c);      _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size,                             _RopeConcatenation).deallocate(__c, 1);      break;    }  case _S_function:    {      typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;      _RopeFunction* __f = __STATIC_CAST(_RopeFunction*, this);      _STLP_STD::_Destroy(__f);      _STLP_CREATE_ALLOCATOR(allocator_type, (const allocator_type&)_M_size,                             _RopeFunction).deallocate(__f, 1);      break;    }  case _S_substringfn:    {      typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;      _RopeSubstring* __rss = __STATIC_CAST(_RopeSubstring*, this);      _STLP_STD::_Destroy(__rss);      _STLP_CREATE_ALLOCATOR(allocator_type, (const allocator_type&)_M_size,                             _RopeSubstring).deallocate(__rss, 1);      break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?