您的位置:首页 > 其它

文章标题 SGI的base_string解析

2017-06-19 21:34 183 查看

SGI的base_string解析

首先介绍一下SGI的base_string。我用的版本sgi-stl-2.91.57,base_string有两个文件一个std/bastring.h一个std/bastring.cc。base_string使用引用计数节约内存的消耗,这也使得编程变得麻烦一些。base_string内有一个内部类Rep,整个base_string 只有一个静态的Rep成员(用于空字符串)和一个dat(base_string实际字符内存的首地址),对于非空字符串base_string使用隐藏的Rep来实现(在构造base_string时实际上的内存为sizeof(Rep)+base_string的字符容量,也就是Rep数据成员之后就是dat指向的地址)Rep的数据成员是len、res、ref 、selfish(base_string的长度、容量、引用计数、是否为私有标记)<我不懂replace函数为什么不用有的不需要重新分配内存呢?有会的给我讲讲啊!!!>

1. 首先看一下base_string的模板的参数

template <class charT, class traits = string_char_traits<charT>,  class Allocator = alloc >
class basic_string{//...}


关于Alloc这里就不说了,string_char_traits是一个模板,他有两个特化版本参数分别为char和wchar_t。再看base_string有必要看看string_char_traits。因为他用到了string_char_traits里的一些函数。代码很简单直接就能看懂

#ifndef __STRING_CHAR_TRAITS__
#define __STRING_CHAR_TRAITS__

#ifdef __GNUG__
// For string_char_traits <char>
#pragma interface "std/straits.h"
#endif

#include <cstddef>

extern "C++" {
template <class charT>
struct string_char_traits {
typedef charT char_type; // for users to acquire the basic character type

// constraints

static void assign (char_type& c1, const char_type& c2)
{ c1 = c2; }
static bool eq (const char_type& c1, const char_type& c2)
{ return (c1 == c2); }
static bool ne (const char_type& c1, const char_type& c2)
{ return !(c1 == c2); }
static bool lt (const char_type& c1, const char_type& c2)
{ return (c1 < c2); }
static char_type eos () { return char_type(); } // the null character
static bool is_del(char_type a) { return 0; }
// characteristic function for delimiters of charT

// speed-up functions

static int compare (const char_type* s1, const char_type* s2, size_t n)
{
size_t i;
for (i = 0; i < n; ++i)
if (ne (s1[i], s2[i]))
return lt (s1[i], s2[i]) ? -1 : 1;

return 0;
}

static size_t length (const char_type* s)
{
size_t l = 0;
while (ne (*s++, eos ()))
++l;
return l;
}

static char_type* copy (char_type* s1, const char_type* s2, size_t n)
{
for (; n--; )
assign (s1
, s2
);
return s1;
}

static char_type* move (char_type* s1, const char_type* s2, size_t n)
{
char_type a
;
size_t i;
for (i = 0; i < n; ++i)
assign (a[i], s2[i]);
for (i = 0; i < n; ++i)
assign (s1[i], a[i]);
return s1;
}

static char_type* set (char_type* s1, const char_type& c, size_t n)
{
for (; n--; )
assign (s1
, c);
return s1;
}
};

class istream;
class ostream;
#include <cctype>
#include <cstring>

struct string_char_traits <char> {
typedef char char_type;

static void assign (char_type& c1, const char_type& c2)
{ c1 = c2; }
static bool eq (const char_type & c1, const char_type& c2)
{ return (c1 == c2); }
static bool ne (const char_type& c1, const char_type& c2)
{ return (c1 != c2); }
static bool lt (const char_type& c1, const char_type& c2)
{ return (c1 < c2); }
static char_type eos () { return 0; }
static bool is_del(char_type a) { return isspace(a); }

static int compare (const char_type* s1, const char_type* s2, size_t n)
{ return memcmp (s1, s2, n); }
static size_t length (const char_type* s)
{ return strlen (s); }
static char_type* copy (char_type* s1, const char_type* s2, size_t n)
{ return (char_type*) memcpy (s1, s2, n); }
static char_type* move (char_type* s1, const char_type* s2, size_t n)
{ return (char_type*) memmove (s1, s2, n); }
static char_type* set (char_type* s1, const char_type& c, size_t n)
{ return (char_type*) memset (s1, c, n); }
};

#if 0
#include <cwctype>
struct string_char_traits <wchar_t> {
typedef wchar_t char_type;

static void assign (char_type& c1, const char_type& c2)
{ c1 = c2; }
static bool eq (const char_type & c1, const char_type& c2)
{ return (c1 == c2); }
static bool ne (const char_type& c1, const char_type& c2)
{ return (c1 != c2); }
static bool lt (const char_type& c1, const char_type& c2)
{ return (c1 < c2); }
static char_type eos () { return 0; }
static bool is_del(char_type a) { return iswspace(a); }

static int compare (const char_type* s1, const char_type* s2, size_t n)
{ return wmemcmp (s1, s2, n); }
static size_t length (const char_type* s)
{ return wcslen (s); }
static char_type* copy (char_type* s1, const char_type* s2, size_t n)
{ return wmemcpy (s1, s2, n); }
static char_type* set (char_type* s1, const char_type& c, size_t n)
{ return wmemset (s1, c, n); }
};
#endif
} // extern "C++"
#endif


base-string的头文件

#ifndef __BASTRING__
#define __BASTRING__

#ifdef __GNUG__
#pragma interface
#endif

#include <cstddef>
#include <std/straits.h>

// NOTE : This does NOT conform to the draft standard and is likely to change
#include <alloc.h>

extern "C++" {
class istream; class ostream;

#include <iterator>

#ifdef __STL_USE_EXCEPTIONS
//外部函数声明
extern void __out_of_range (const char *);
extern void __length_error (const char *);
//这两个宏用于判断cond; cond必须要能转化为bool类型
//如果cond为真则调用对应的函数
#define OUTOFRANGE(cond) \
do { if (cond) __out_of_range (#cond); } while (0)
#define LENGTHERROR(cond) \
do { if (cond) __length_error (#cond); } while (0)

#else

#include <cassert>
#define OUTOFRANGE(cond) assert (!(cond))
#define LENGTHERROR(cond) assert (!(cond))

#endif
//注意这里的 string_char_traits alloc
template <class charT, class traits = string_char_traits<charT>,
class Allocator = alloc >
class basic_string
{
private:
//内部类
struct Rep {
size_t len, res, ref;//string的字符长度、容量、引用技术
bool selfish;//是否为私有的标记

charT* data () { return reinterpret_cast<charT *>(this + 1); }//返回string的字符首地址 相当于&(*this)+sizeof(Rep)
charT& operator[] (size_t s) { return data () [s]; }//返回string的第s+1个字符
//如果为私有则返回clone() ,否则增加引用计数、返回string元素首地址
charT* grab () { if (selfish) return clone (); ++ref; return data (); }
void release () { if (--ref == 0) delete this; }
//重载operator new(这里不是placement new),而是分配sizeof(Rep)+string的字符所需要的字节数
inline static void * operator new (size_t, size_t);
//收回分配的内存
inline static void operator delete (void *);
inline static Rep* create (size_t);
charT* clone ();

inline void copy (size_t, const charT *, size_t);
inline void move (size_t, const charT *, size_t);
inline void set  (size_t, const charT,   size_t);

inline static bool excess_slop (size_t, size_t);
inline static size_t frob_size (size_t);

private:
Rep &operator= (const Rep &);//禁止复制操作符
};

public:
// types:
typedef      traits                   traits_type;
typedef typename traits::char_type    value_type;
typedef      Allocator                allocator_type;

typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef charT& reference;
typedef const charT& const_reference;
typedef charT* pointer;
typedef const charT* const_pointer;
typedef pointer iterator;//这里看出迭代器只是char*或wchar_t*
typedef const_pointer const_iterator;
typedef ::reverse_iterator<iterator> reverse_iterator;
typedef ::reverse_iterator<const_iterator> const_reverse_iterator;
static const size_type npos = static_cast<size_type>(-1);

private:
//由Rep的data()知道这里是Rep的首地址
Rep *rep() const { return reinterpret_cast<Rep *>(dat)-1; }
void repup (Rep *p) { rep ()->release (); dat = p->data (); }

public:
const charT* data
1ab91
() const
{ return rep ()->data(); }
size_type length () const
{ return rep ()->len; }
size_type size () const
{ return rep ()->len; }
size_type capacity () const
{ return rep ()->res; }
size_type max_size () const
{ return (npos - 1)/sizeof (charT); }       // XXX
bool empty () const
{ return size () == 0; }

// _lib.string.cons_ construct/copy/destroy:
basic_string& operator= (const basic_string& str)
{
if (&str != this) { rep ()->release (); dat = str.rep ()->grab (); }
return *this;
}
//构造函数
explicit basic_string (): dat (nilRep.grab ()) { }
basic_string (const basic_string& str): dat (str.rep ()->grab ()) { }
basic_string (const basic_string& str, size_type pos, size_type n = npos)
: dat (nilRep.grab ()) { assign (str, pos, n); }
basic_string (const charT* s, size_type n)
: dat (nilRep.grab ()) { assign (s, n); }
basic_string (const charT* s)
: dat (nilRep.grab ()) { assign (s); }
basic_string (size_type n, charT c)
: dat (nilRep.grab ()) { assign (n, c); }
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
basic_string(InputIterator begin, InputIterator end)
#else
basic_string(const_iterator begin, const_iterator end)
#endif
: dat (nilRep.grab ()) { assign (begin, end); }
//析构函数
~basic_string ()
{ rep ()->release (); }
//这里看出交换string只是交换dat数据成员,避免大量的复制
void swap (basic_string &s) { charT *d = dat; dat = s.dat; s.dat = d; }
//append函数  调用replace实现
basic_string& append (const basic_string& str, size_type pos = 0,
size_type n = npos)
{ return replace (length (), 0, str, pos, n); }
basic_string& append (const charT* s, size_type n)
{ return replace (length (), 0, s, n); }
basic_string& append (const charT* s)
{ return append (s, traits::length (s)); }
basic_string& append (size_type n, charT c)
{ return replace (length (), 0, n, c); }
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
basic_string& append(InputIterator first, InputIterator last)
#else
basic_string& append(const_iterator first, const_iterator last)
#endif
{ return replace (iend (), iend (), first, last); }
//assign函数  调用replace实现
basic_string& assign (const basic_string& str, size_type pos = 0,
size_type n = npos)
{ return replace (0, npos, str, pos, n); }
basic_string& assign (const charT* s, size_type n)
{ return replace (0, npos, s, n); }
basic_string& assign (const charT* s)
{ return assign (s, traits::length (s)); }
basic_string& assign (size_type n, charT c)
{ return replace (0, npos, n, c); }
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
basic_string& assign(InputIterator first, InputIterator last)
#else
basic_string& assign(const_iterator first, const_iterator last)
#endif
{ return replace (ibegin (), iend (), first, last); }

basic_string& operator= (const charT* s)
{ return assign (s); }
basic_string& operator= (charT c)
{ return assign (1, c); }

basic_string& operator+= (const basic_string& rhs)
{ return append (rhs); }
basic_string& operator+= (const charT* s)
{ return append (s); }
basic_string& operator+= (charT c)
{ return append (1, c); }

basic_string& insert (size_type pos1, const basic_string& str,
size_type pos2 = 0, size_type n = npos)
{ return replace (pos1, 0, str, pos2, n); }
basic_string& insert (size_type pos, const charT* s, size_type n)
{ return replace (pos, 0, s, n); }
basic_string& insert (size_type pos, const charT* s)
{ return insert (pos, s, traits::length (s)); }
basic_string& insert (size_type pos, size_type n, charT c)
{ return replace (pos, 0, n, c); }
iterator insert(iterator p, charT c)
{ size_type __o = p - ibegin ();
insert (p - ibegin (), 1, c); selfish ();
return ibegin () + __o; }
iterator insert(iterator p, size_type n, charT c)
{ size_type __o = p - ibegin ();
insert (p - ibegin (), n, c); selfish ();
return ibegin () + __o; }
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
void insert(iterator p, InputIterator first, InputIterator last)
#else
void insert(iterator p, const_iterator first, const_iterator last)
#endif
{ replace (p, p, first, last); }

basic_string& erase (size_type pos = 0, size_type n = npos)
{ return replace (pos, n, (size_type)0, (charT)0); }
iterator erase(iterator p)
{ size_type __o = p - begin();
replace (__o, 1, (size_type)0, (charT)0); selfish ();
return ibegin() + __o; }
iterator erase(iterator f, iterator l)
{ size_type __o = f - ibegin();
replace (__o, l-f, (size_type)0, (charT)0);selfish ();
return ibegin() + __o; }

basic_string& replace (size_type pos1, size_type n1, const basic_string& str,
size_type pos2 = 0, size_type n2 = npos);
basic_string& replace (size_type pos, size_type n1, const charT* s,
size_type n2);
basic_string& replace (size_type pos, size_type n1, const charT* s)
{ return replace (pos, n1, s, traits::length (s)); }
basic_string& replace (size_type pos, size_type n1, size_type n2, charT c);
basic_string& replace (size_type pos, size_type n, charT c)
{ return replace (pos, n, 1, c); }
basic_string& replace (iterator i1, iterator i2, const basic_string& str)
{ return replace (i1 - ibegin (), i2 - i1, str); }
basic_string& replace (iterator i1, iterator i2, const charT* s, size_type n)
{ return replace (i1 - ibegin (), i2 - i1, s, n); }
basic_string& replace (iterator i1, iterator i2, const charT* s)
{ return replace (i1 - ibegin (), i2 - i1, s); }
basic_string& replace (iterator i1, iterator i2, size_type n, charT c)
{ return replace (i1 - ibegin (), i2 - i1, n, c); }
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
basic_string& replace(iterator i1, iterator i2,
InputIterator j1, InputIterator j2);
#else
basic_string& replace(iterator i1, iterator i2,
const_iterator j1, const_iterator j2);
#endif

private:
//返回char() 或 wchar_t()
static charT eos () { return traits::eos (); }
void unique () { if (rep ()->ref > 1) alloc (length (), true); }
void selfish () { unique (); rep ()->selfish = true; }//很重要的函数

public:
charT operator[] (size_type pos) const
{
if (pos == length ())
return eos ();
return data ()[pos];//不明白为什么不用dat
}
//返回reference所以需要selfish()
reference operator[] (size_type pos)
{ selfish (); return (*rep ())[pos]; }//注意上面的data()、这里的*rep()、下面的*this
//这里有两种情况:1、当ref = 1 时三个应该是一样的
//2、当ref > 1时 selfish() -> unique()当ref>1时 -> alloc()重新分配内存 -> repup()用于更新dat
//(*rep ())[pos]会调用Rep::operator []哪里最后就会用到更新的dat
reference at (size_type pos)
{
OUTOFRANGE (pos >= length ());
return (*this)[pos];//调用上面的因为第一个为const,所以这里不需要selfish()
}
const_reference at (size_type pos) const
{
OUTOFRANGE (pos >= length ());
return data ()[pos];
}

private:
void terminate () const//应该就是给string最后一个字符的后面赋值为cahr() 或 wchar_t()
//basic_string内部字符串的有效范围是[0, length)
// 这里仅仅是在字符串的外面修改了一个“本来随机”的字符串为“结尾符”,
// 并没有修改原本有效的数据,也没有修改字符串的有效长度!
{ traits::assign ((*rep ())[length ()], eos ()); }

public:
const charT* c_str () const//返回C的字符串
{ if (length () == 0) return ""; terminate (); return data (); }
void resize (size_type n, charT c);
void resize (size_type n)
{ resize (n, eos ()); }
void reserve (size_type) { }

size_type copy (charT* s, size_type n, size_type pos = 0) const;

size_type find (const basic_string& str, size_type pos = 0) const
{ return find (str.data(), pos, str.length()); }
size_type find (const charT* s, size_type pos, size_type n) const;
size_type find (const charT* s, size_type pos = 0) const
{ return find (s, pos, traits::length (s)); }
size_type find (charT c, size_type pos = 0) const;

size_type rfind (const basic_string& str, size_type pos = npos) const
{ return rfind (str.data(), pos, str.length()); }
size_type rfind (const charT* s, size_type pos, size_type n) const;
size_type rfind (const charT* s, size_type pos = npos) const
{ return rfind (s, pos, traits::length (s)); }
size_type rfind (charT c, size_type pos = npos) const;

size_type find_first_of (const basic_string& str, size_type pos = 0) const
{ return find_first_of (str.data(), pos, str.length()); }
size_type find_first_of (const charT* s, size_type pos, size_type n) const;
size_type find_first_of (const charT* s, size_type pos = 0) const
{ return find_first_of (s, pos, traits::length (s)); }
size_type find_first_of (charT c, size_type pos = 0) const
{ return find (c, pos); }

size_type find_last_of (const basic_string& str, size_type pos = npos) const
{ return find_last_of (str.data(), pos, str.length()); }
size_type find_last_of (const charT* s, size_type pos, size_type n) const;
size_type find_last_of (const charT* s, size_type pos = npos) const
{ return find_last_of (s, pos, traits::length (s)); }
size_type find_last_of (charT c, size_type pos = npos) const
{ return rfind (c, pos); }

size_type find_first_not_of (const basic_string& str, size_type pos = 0) const
{ return find_first_not_of (str.data(), pos, str.length()); }
size_type find_first_not_of (const charT* s, size_type pos, size_type n) const;
size_type find_first_not_of (const charT* s, size_type pos = 0) const
{ return find_first_not_of (s, pos, traits::length (s)); }
size_type find_first_not_of (charT c, size_type pos = 0) const;

size_type find_last_not_of (const basic_string& str, size_type pos = npos) const
{ return find_last_not_of (str.data(), pos, str.length()); }
size_type find_last_not_of (const charT* s, size_type pos, size_type n) const;
size_type find_last_not_of (const charT* s, size_type pos = npos) const
{ return find_last_not_of (s, pos, traits::length (s)); }
size_type find_last_not_of (charT c, size_type pos = npos) const;

basic_string substr (size_type pos = 0, size_type n = npos) const
{ return basic_string (*this, pos, n); }//调用构造函数

int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const;
// There is no 'strncmp' equivalent for charT pointers.
int compare (const charT* s, size_type pos, size_type n) const;
int compare (const charT* s, size_type pos = 0) const
{ return compare (s, pos, traits::length (s)); }

iterator begin () { selfish (); return &(*this)[0]; }//为啥不直接return &(*this)[0]呢?里面也有 selfish ()啊
iterator end () { selfish (); return &(*this)[length ()]; }

private:
iterator ibegin () const { return &(*rep ())[0]; }
iterator iend () const { return &(*rep ())[length ()]; }

public:
const_iterator begin () const { return ibegin (); }
const_iterator end () const { return iend (); }

reverse_iterator       rbegin() { return reverse_iterator (end ()); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator (end ()); }
reverse_iterator       rend() { return reverse_iterator (begin ()); }
const_reverse_iterator rend() const
{ return const_reverse_iterator (begin ()); }

private:
void alloc (size_type size, bool save);//重新分配内存
static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len);
inline bool check_realloc (size_type s) const;//是否需要重新分配内存

static Rep nilRep;//静态Rep用于空string
charT *dat;//唯一的一个数据成员
};
//replace 的一个实现
#ifdef __STL_MEMBER_TEMPLATES
template <class charT, class traits, class Allocator>
template <class InputIterator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
#else
template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2)
#endif
{
//将[i1 i2) 换成[j1 j2)的内容
const size_type len = length ();//string的长度
size_type pos = i1 - ibegin ();//replace的偏移地址
size_type n1 = i2 - i1;//replace的个数
size_type n2 = j2 - j1;

OUTOFRANGE (pos > len);
if (n1 > len - pos)
n1 = len - pos;//replace的个数大于实际可以replace的个数的时候 实际replace (len-pos)个字符
LENGTHERROR (len - n1 > max_size () - n2);//保证replace后的字符个数不会大于max_size()
size_t newlen = len - n1 + n2;

if (check_realloc (newlen))//是否要重新分配内存
{
Rep *p = Rep::create (newlen);
p->copy (0, data (), pos);
p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
for (; j1 != j2; ++j1, ++pos)
traits::assign ((*p)[pos], *j1);
repup (p);
}
else
{
rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
for (; j1 != j2; ++j1, ++pos)
traits::assign ((*rep ())[pos], *j1);
}
rep ()->len = newlen;

return *this;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
basic_string <charT, traits, Allocator> str (lhs);
str.append (rhs);
return str;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
basic_string <charT, traits, Allocator> str (lhs);
str.append (rhs);
return str;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs)
{
basic_string <charT, traits, Allocator> str (1, lhs);
str.append (rhs);
return str;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
basic_string <charT, traits, Allocator> str (lhs);
str.append (rhs);
return str;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs)
{
basic_string <charT, traits, Allocator> str (lhs);
str.append (1, rhs);
return str;
}

template <class charT, class traits, class Allocator>
inline bool
operator== (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) >= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
return (rhs.compare (lhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
return (lhs.compare (rhs) >= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const basic_string <charT, traits, Allocator>& lhs,
const basic_string <charT, traits, Allocator>& rhs)
{
return (lhs.compare (rhs) >= 0);
}

class istream; class ostream;
template <class charT, class traits, class Allocator> istream&
operator>> (istream&, basic_string <charT, traits, Allocator>&);
template <class charT, class traits, class Allocator> ostream&
operator<< (ostream&, const basic_string <charT, traits, Allocator>&);
template <class charT, class traits, class Allocator> istream&
getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n');

} // extern "C++"

#include <std/bastring.cc>

#endif


base_string的源文件

extern "C++" {
template <class charT, class traits, class Allocator>
inline void * basic_string <charT, traits, Allocator>::Rep::
operator new (size_t s, size_t extra)
{//分配内存 Rep的大小 + string的字符
return Allocator::allocate(s + extra * sizeof (charT));
}

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
operator delete (void * ptr)
{//归还上面分配的内存
Allocator::deallocate(ptr, sizeof(Rep) +
reinterpret_cast<Rep *>(ptr)->res *
sizeof (charT));
}

template <class charT, class traits, class Allocator>
inline size_t basic_string <charT, traits, Allocator>::Rep::
frob_size (size_t s)
{//string字符容量分配的大小
size_t i = 16;
while (i < s) i *= 2;
return i;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>::Rep *
basic_string <charT, traits, Allocator>::Rep::
create (size_t extra)
{
extra = frob_size (extra + 1);
Rep *p = new (extra) Rep;//调用上面的operator new
p->res = extra;//初始化,len会在new (extra) Rep调用Rep的构造函数是初始化为0
p->ref = 1;
p->selfish = false;
return p;
}

template <class charT, class traits, class Allocator>
charT * basic_string <charT, traits, Allocator>::Rep::
clone ()
{
Rep *p = Rep::create (len);
p->copy (0, data (), len);
p->len = len;
return p->data ();
}

template <class charT, class traits, class Allocator>
inline bool basic_string <charT, traits, Allocator>::Rep::
excess_slop (size_t s, size_t r)
{
return 2 * (s <= 16 ? 16 : s) < r;
}

template <class charT, class traits, class Allocator>
inline bool basic_string <charT, traits, Allocator>::
check_realloc (basic_string::size_type s) const
{
s += sizeof (charT);
rep ()->selfish = false;
return (rep ()->ref > 1//ref大于1
|| s > capacity ()//新的分配的字符内存大于容量
|| Rep::excess_slop (s, capacity ()));//新分配的字符内存*2还小于容量(用于减小多余的内存)
}//重新分配内存的三个条件

template <class charT, class traits, class Allocator>
void basic_string <charT, traits, Allocator>::
alloc (basic_string::size_type size, bool save)
{
if (! check_realloc (size))
return;

Rep *p = Rep::create (size);

if (save)
{
p->copy (0, data (), length ());
p->len = length ();
}
else
p->len = 0;

repup (p);
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (size_type pos1, size_type n1,
const basic_string& str, size_type pos2, size_type n2)
{
const size_t len2 = str.length ();

if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2)
return operator= (str);//正好满足operator= 的条件

OUTOFRANGE (pos2 > len2);

if (n2 > len2 - pos2)
n2 = len2 - pos2;

return replace (pos1, n1, str.data () + pos2, n2);
}

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
copy (size_t pos, const charT *s, size_t n)
{
if (n)
traits::copy (data () + pos, s, n);
}

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
move (size_t pos, const charT *s, size_t n)
{
if (n)
traits::move (data () + pos, s, n);
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (size_type pos, size_type n1, const charT* s, size_type n2)
{
const size_type len = length ();
OUTOFRANGE (pos > len);
if (n1 > len - pos)
n1 = len - pos;
LENGTHERROR (len - n1 > max_size () - n2);
size_t newlen = len - n1 + n2;

if (check_realloc (newlen))
{
Rep *p = Rep::create (newlen);
p->copy (0, data (), pos);
p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
p->copy (pos, s, n2);
repup (p);
}
else
{
rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
rep ()->copy (pos, s, n2);
}
rep ()->len = newlen;

return *this;
}

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
set (size_t pos, const charT c, size_t n)
{
traits::set  (data () + pos, c, n);
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
replace (size_type pos, size_type n1, size_type n2, charT c)
{
const size_t len = length ();
OUTOFRANGE (pos > len);
if (n1 > len - pos)
n1 = len - pos;
LENGTHERROR (len - n1 > max_size () - n2);
size_t newlen = len - n1 + n2;

if (check_realloc (newlen))
{
Rep *p = Rep::create (newlen);
p->copy (0, data (), pos);
p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
p->set  (pos, c, n2);
repup (p);
}
else
{
rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
rep ()->set  (pos, c, n2);
}
rep ()->len = newlen;

return *this;
}

template <class charT, class traits, class Allocator>
void basic_string <charT, traits, Allocator>::
resize (size_type n, charT c)
{
LENGTHERROR (n > max_size ());

if (n > length ())
append (n - length (), c);
else
erase (n);
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
copy (charT* s, size_type n, size_type pos) const
{
OUTOFRANGE (pos > length ());

if (n > length () - pos)
n = length () - pos;

traits::copy (s, data () + pos, n);
return n;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find (const charT* s, size_type pos, size_type n) const
{
size_t xpos = pos;
for (; xpos + n <= length (); ++xpos)
if (traits::eq (data () [xpos], *s)
&& traits::compare (data () + xpos, s, n) == 0)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
_find (const charT* ptr, charT c, size_type xpos, size_type len)
{
for (; xpos < len; ++xpos)
if (traits::eq (ptr [xpos], c))
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find (charT c, size_type pos) const
{
return _find (data (), c, pos, length ());
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
rfind (const charT* s, size_type pos, size_type n) const
{
if (n > length ())
return npos;

size_t xpos = length () - n;
if (xpos > pos)
xpos = pos;

for (++xpos; xpos-- > 0; )
if (traits::eq (data () [xpos], *s)
&& traits::compare (data () + xpos, s, n) == 0)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
rfind (charT c, size_type pos) const
{
if (1 > length ())
return npos;

size_t xpos = length () - 1;
if (xpos > pos)
xpos = pos;

for (++xpos; xpos-- > 0; )
if (traits::eq (data () [xpos], c))
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_of (const charT* s, size_type pos, size_type n) const
{
size_t xpos = pos;
for (; xpos < length (); ++xpos)
if (_find (s, data () [xpos], 0, n) != npos)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_of (const charT* s, size_type pos, size_type n) const
{
if (length() == 0)
return npos;
size_t xpos = length () - 1;
if (xpos > pos)
xpos = pos;
for (++xpos; xpos-- > 0;)
if (_find (s, data () [xpos], 0, n) != npos)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_not_of (const charT* s, size_type pos, size_type n) const
{
size_t xpos = pos;
for (; xpos < length (); ++xpos)
if (_find (s, data () [xpos], 0, n) == npos)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_not_of (charT c, size_type pos) const
{
size_t xpos = pos;
for (; xpos < length (); ++xpos)
if (traits::ne (data () [xpos], c))
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_not_of (const charT* s, size_type pos, size_type n) const
{
if (length() == 0)
return npos;
size_t xpos = length () - 1;
if (xpos > pos)
xpos = pos;
for (++xpos; xpos-- > 0;)
if (_find (s, data () [xpos], 0, n) == npos)
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_not_of (charT c, size_type pos) const
{
if (length() == 0)
return npos;
size_t xpos = length () - 1;
if (xpos > pos)
xpos = pos;
for (++xpos; xpos-- > 0;)
if (traits::ne (data () [xpos], c))
return xpos;
return npos;
}

template <class charT, class traits, class Allocator>
int basic_string <charT, traits, Allocator>::
compare (const basic_string& str, size_type pos, size_type n) const
{
OUTOFRANGE (pos > length ());

size_t rlen = length () - pos;
if (rlen > n)
rlen = n;
if (rlen > str.length ())
rlen = str.length ();
int r = traits::compare (data () + pos, str.data (), rlen);
if (r != 0)
return r;
if (rlen == n)
return 0;
return (length () - pos) - str.length ();
}

template <class charT, class traits, class Allocator>
int basic_string <charT, traits, Allocator>::
compare (const charT* s, size_type pos, size_type n) const
{
OUTOFRANGE (pos > length ());

size_t rlen = length () - pos;
if (rlen > n)
rlen = n;
int r = traits::compare (data () + pos, s, rlen);
if (r != 0)
return r;
return (length () - pos) - n;
}

#include <iostream.h>

template <class charT, class traits, class Allocator>
istream &
operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
{
int w = is.width (0);
if (is.ipfx0 ())
{
register streambuf *sb = is.rdbuf ();
s.resize (0);
while (1)
{
int ch = sb->sbumpc ();
if (ch == EOF)
{
is.setstate (ios::eofbit);
break;
}
else if (traits::is_del (ch))
{
sb->sungetc ();
break;
}
s += ch;
if (--w == 1)
break;
}
}

is.isfx ();
if (s.length () == 0)
is.setstate (ios::failbit);

return is;
}

template <class charT, class traits, class Allocator>
ostream &
operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
{
return o.write (s.data (), s.length ());
}

template <class charT, class traits, class Allocator>
istream&
getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
{
if (is.ipfx1 ())
{
_IO_size_t count = 0;
streambuf *sb = is.rdbuf ();
s.resize (0);

while (1)
{
int ch = sb->sbumpc ();
if (ch == EOF)
{
is.setstate (count == 0
? (ios::failbit|ios::eofbit)
: ios::eofbit);
break;
}

++count;

if (ch == delim)
break;

s += ch;

if (s.length () == s.npos - 1)
{
is.setstate (ios::failbit);
break;
}
}
}

// We need to be friends with istream to do this.
// is._gcount = count;
is.isfx ();

return is;
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::Rep
basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };

template <class charT, class traits, class Allocator>
const basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::npos;

} // extern "C++"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: