📄 str.cpp
字号:
// character string manipulation library// Copyright (c) R B Davies 1996// The is a string library that is intended to be compatible with the// "class string" library in the April 1995 draft of the C++ standard.// Parts are based on Tony Hansen s "The C++ Answer Book"#define WANT_STREAM#define WANT_MATH#define WANT_STRING#include "include.h"#include "str.h"//******************************* globals ********************************uint String::npos = (uint)(-1); // also initialised to -1 by StringPackageInitialiseuint String::s_index;StrNull* String::ASN;// string bodiesconst char* String::StringType() const { return px->StringType(); }StrBase* String::Clone() const { return px->Clone(&(StrBase*&)px); }unsigned int String::refcount() const { return px->refcount(); }void String::CleanUp() { if (px) px->Drop(); px = ASN; }StrRep* String::GetStrRep() const { return px->GetStrRep(&(StrBase*&)px); }StrRep* String::GetStrRepW() { return px->GetStrRepW(&px); }char* String::GetData() const { return GetStrRep()->s; }StrRep* String::Protect() const { return px->Protect(&(StrBase*&)px); }bool String::HasCapacity() const { return px->HasCapacity(); }String::String(StrBase* sb) : px(sb) {}String::String() : px(ASN) {}String::String(const String& str) { px = ASN; px = str.Clone(); }String::String(const String& str, uint pos, uint n){ px = ASN; // in case of later failure StrRep* str_p = str.GetStrRep(); uint sz = str.size(); if (pos > sz) Throw(Out_of_range("string index error\n")); sz -= pos; // length of new string if (n < sz) sz = n; if (sz == 0) px = ASN; else px = new StrRepMult(str_p->s+pos, sz);}String::String(const char* s, uint n){ px = ASN; // in case of later failure if (!s) Throw(Invalid_argument("string constructor: char* s = 0\n")); uint sz = 0; const char* S = s; while (*S++) { if (sz >= n) break; sz++; } if (sz == 0) px = ASN; else px = new StrRepMult(s, sz);}String::String(const char* s){ px = ASN; // in case of later failure if (!s) Throw(Invalid_argument("string constructor: char* s = 0\n")); uint sz = strlen(s); if (sz == 0) px = ASN; else px = new StrRepMult(s, sz);}String::String(uint n, char c){ px = ASN; // in case of later failure if (n == npos) Throw(Length_error("string length = npos\n")); if (n == 0) px = ASN; else if (n == 1) px = new CharSingle(c); else px = new CharRepeated(n, c);}String::~String() { if (px) px->Drop(); }// do the operator= separately from assign because we do not ever// want to just copy into existing memory space. ie we do not// maintain capacity when we use operator= .String& String::operator=(const String& str) { StrBase* p = px; px = str.Clone(); p->Drop(); return *this; }String& String::operator=(const char* s){ StrBase* p = px; if (strlen(s) == 0) px = ASN; else px = new StrRepMult(s); p->Drop(); return *this;}String& String::operator=(const char c){ px->Drop(); px = new CharSingle(c); return *this;}uint String::size() const { return px->size(); }uint String::length() const { return px->size(); }uint String::max_size() const { return npos-1; }void String::resize(uint n, char c){ if (n == npos) Throw(Length_error("string length = npos\n")); if (n == 0) { px->Drop(); px = ASN; return; } StrRep* p = GetStrRep(); if (n <= p->sz) px = new StrRepMult(p->s, n); else px = new StrRepMult(p->s, p->sz, n, c); p->Drop();}uint String::capacity() const { return px->capacity(); }void String::reserve(uint res_arg){ if (res_arg == 0) // remove capacity { StrRep* p = new StrRepMult(size()); char* target = p->s; px->Load(target); px->Drop(); px = p; } else if ( res_arg > size() || capacity() != size() ) // need to change storage { if (res_arg < size()) res_arg = size(); StrRep* p = new StrRepCap(size(), res_arg); char* target = p->s; px->Load(target); px->Drop(); px = p; } else px->WithCapacity(&(StrBase*&)px); // convert to string with capacity}void String::clear() { if (px) px->Drop(); px = ASN; }bool String::empty() const { return px->size() == 0; }char String::operator[](uint pos) const{ StrRep* p = GetStrRep(); if (pos >= p->size()) { if (pos == p->size()) return 0; else Throw(Out_of_range("string index error\n")); } return (p->s)[pos];}char& String::operator[](uint pos){ StrRep* p = GetStrRepW(); if (pos >= p->size()) Throw(Out_of_range("string index error\n")); return p->s[pos];}char String::at(uint n) const{ StrRep* p = GetStrRep(); if (n >= p->size()) { if (n == p->size()) return 0; else Throw(Out_of_range("string index error\n")); } return p->s[n];}char& String::at(uint n){ StrRep* p = GetStrRepW(); if (n >= p->size()) Throw(Out_of_range("string index error\n")); return p->s[n];}//******************** the line editing functions ************************String& String::operator+=(const String& rhs) { return append(rhs); }String& String::operator+=(const char* s) { return append(s); }String& String::operator+=(char c){ if (HasCapacity()) return my_append(CharSingle(c)); else { if (size() >= npos - 1) Throw(Length_error("string length >= npos\n")); px = new StrSumRC(px ,c); return *this; }}String& String::my_append(const StrBase& sb){ StrRep* p = GetStrRep(); uint sz = size(); uint rlen =sb.size(); if (sz >= npos - rlen) Throw(Length_error("string length >= npos\n")); rlen += sz; if (rlen > capacity() || refcount() != 0) { // must make new string StrRep* oldp = p; p = new StrRepMult(rlen); memcpy(p->s, oldp->s, sz); oldp->Drop(); px = p; } char* target = p->s+sz; sb.Load(target); p->sz = rlen; return *this;}String& String::append(const String& str){ if (HasCapacity()) return my_append(CharSeq(str)); else { if (size() >= npos - str.size()) Throw(Length_error("string length >= npos\n")); px = new StrSum(px, str.Clone()); return *this; }}String& String::append(const String& str, uint pos, uint n){ if (HasCapacity()) return my_append(CharSeq(str, pos, n)); else { CharSeq CS(str, pos, n); if (size() >= npos - CS.sz) Throw(Length_error("string length >= npos\n")); StrBase* rhs = new StrRep(CS.s, CS.sz); px = new StrSum(px, rhs); return *this; }}String& String::append(const char* s, uint n){ if (HasCapacity()) return my_append(CharSeq((char*)s, n)); else { StrBase* rhs = new StrRep(s, n); if (size() >= npos - rhs->size()) { delete rhs; Throw(Length_error("string length >= npos\n")); } px = new StrSum(px, rhs); return *this; }}String& String::append(const char* s){ if (HasCapacity()) return my_append(CharSeq((char*)s)); else { StrBase* rhs = new StrRep(s); if (size() >= npos - rhs->size()) { delete rhs; Throw(Length_error("string length >= npos\n")); } px = new StrSum(px, rhs); return *this; }}String& String::append(uint n, char c){ if (size() >= npos - n) Throw(Length_error("string length >= npos\n")); if (HasCapacity()) return my_append(CharRepeated(n, c)); else if (n == 1) { px = new StrSumRC(px ,c); } else { StrBase* rhs = new CharRepeated(n, c); px = new StrSum(px, rhs); } return *this;}// assign with argument being all or part of the target string// should not be a problem under HasCapacity since Load uses// memmove.String& String::assign(const String& str){ if (HasCapacity() && str.size() <= capacity()) { StrRep* p = GetStrRep(); char* target = p->s; str.px->Load(target); p->sz = str.size(); } else if (px != str.px) { px->Drop(); px = str.Clone(); } return *this;}String& String::my_assign(const StrBase& sb){ uint sz = sb.size(); StrRep* p; if (HasCapacity() && sz <= capacity()) { p = GetStrRep(); char* target = p->s; sb.Load(target); p->sz = sz; return *this; } else if (sz == 0) p = ASN; else { p = new StrRepMult(sb.size()); char* target = p->s; sb.Load(target); } px->Drop(); px = p; return *this;}String& String::assign(const String& str, uint pos, uint n) { return my_assign(CharSeq(str, pos, n)); }String& String::assign(const char* s, uint n) { return my_assign(CharSeq((char*)s, n)); }String& String::assign(const char* s) { return my_assign(CharSeq((char*)s)); }String& String::assign(uint n, char c) { return my_assign(CharRepeated(n, c)); }String& String::my_insert(uint pos, const StrBase& sb){ uint sz = size(); uint rlen =sb.size(); if (pos > sz) Throw(Out_of_range("string index error\n")); if (sz >= npos - rlen) Throw(Length_error("string length >= npos\n")); StrRep* oldp = GetStrRep(); if (HasCapacity() && sz + rlen <= capacity()) { // must allow for possibility that sb is part of *this char* target = oldp->s + pos; StrRep tail(target, sz-pos); sb.Load(target); tail.Load(target); oldp->sz = sz + rlen; } else { StrRep* p = new StrRepMult(sz + rlen); px = p; char* target = p->s; memcpy(target, oldp->s, pos); target += pos; sb.Load(target); memcpy(target, oldp->s + pos, sz-pos); oldp->Drop(); } return *this;}String& String::insert(uint pos1, const String& str) { return my_insert(pos1, *(str.px)); }String& String::insert(uint pos1, const String& str, uint pos2, uint n) { return my_insert(pos1, CharSeq(str, pos2, n)); }String& String::insert(uint pos, const char* s, uint n) { return my_insert(pos, CharSeq((char*)s, n)); }String& String::insert(uint pos, uint n, char c) { return my_insert(pos, CharRepeated(n, c)); }String& String::erase(uint pos, uint n){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -