string.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,411 行 · 第 1/2 页

C
1,411
字号
    char *pStart  = srep->str + pos;
    char *pEnd    = srep->str + thisLen;

    for(; pStart <  pEnd; pos++, pStart++) {
        if(*pStart == c) {
            fpos = pos;
            return 1;
        }
    }
    return 0;
}

int String::rfind(char c, size_t& fpos, size_t pos) const
{
    size_t thisLen = length();

    //
    // operations
    //

    fpos = NPOS;

    if(thisLen == 0)
        return 0;

    if(pos >= thisLen)
        pos = thisLen - 1;

    // pointers are valid because thisLen > 0

    char *pStart  = srep->str + pos;
    char *pBegin  = srep->str;

    for(; pStart >= pBegin; pos--, pStart--) {
        if(*pStart == c) {
            fpos = pos;
            return 1;
        }
    }
    return 0;
}

//
// insert
//
String& String::insert(size_t pos, const String& s)
{
    KEEPOLD;

    //
    // preconditions
    //

    if(pos > length())
        strError("String::insert", "OutOfRange");

    //
    // operations
    //

    if(this == &s)
        return insert(pos, String(s));          // insert into itself
    if(s.srep)
        doReplace(pos, 0, s.srep->str, s.srep->getLen());

    //
    // post conditions
    //

    assert(length() == (s.length() + OLD.length()));
    assert(memcmp(cStr() + pos, s.cStr(), s.length()) == 0);

    return *this;
}

String& String::insert(size_t pos, const char* cb, size_t n)
{
    KEEPOLD;

#ifndef NDEBUG
    char *pOLD = 0;
    if(cb != 0) {
        if(n == NPOS)
            n = strlen(cb);
        pOLD = new char[n];
        assert(pOLD != 0);
        memcpy(pOLD, cb, n);
    }
#endif

    //
    // preconditions
    //

    if(pos > length())
        strError("String::insert", "OutOfRange");
    if(cb == 0)
        strError("String::insert", "InvalidArgument");

    //
    // operations
    //

    if(n == NPOS)
        n = strlen(cb);

    if(n > 0)
        doReplace(pos, 0, cb, n);

    //
    // post conditions
    //

    assert(length() == (n + OLD.length()));

#ifndef NDEBUG
    //
    // this asertion is so complicated
    // because of hacks like: s.insert(1, s.cStr() + 2)
    //
    assert(memcmp(cStr() + pos, pOLD, n) == 0);
    delete [] pOLD;
#endif

    return *this;
}

String& String::insert(size_t pos, char c, size_t rep)
{
    KEEPOLD;

    //
    // preconditions
    //

    if(pos > length())
        strError("String::insert", "OutOfRange");
    //
    // operations
    //

    if(rep == 1)
        doReplace(pos, 0, &c, 1);
    else if(rep > 0)
        insert(pos, String(c, rep));

    //
    // post conditions
    //

    assert(length() == (rep + OLD.length()));
#ifndef NDEBUG
    for(int i = 0; i < rep; i++)
        assert(getAt(i + pos) == c);
#endif /* NDEBUG */

    return *this;
}

//
//  replace
//

String& String::replace(size_t pos, size_t n, const char *cb, size_t len)
{
    KEEPOLD;
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > thisLen)
        strError("String::replace", "OutOfRange");
    if(cb == 0)
        strError("String::replace", "InvalidArgument");

    //
    // operations
    //

    if(len == NPOS)
        len = strlen(cb);

    if((pos + n) > thisLen)
        n = thisLen - pos;

    if(n > 0 || len > 0)
        doReplace(pos, n, cb, len);

    //
    // post conditions
    //

    assert(length() == (OLD.length() - n + len));

    return *this;
}

String& String::replace(size_t pos, size_t n, char c, size_t rep)
{
    // this could be implemented more efficiently

    // we get all assertions and checks in
    // replace(size_t, size_t, const String&);

    replace(pos, n, String(c,rep));
    return *this;
}

String& String::replace(size_t pos, size_t len, const  String& s)
{
    KEEPOLD;
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > thisLen)
        strError("String::replace", "OutOfRange");

    //
    // operations
    //

    if(this == &s) {                         // if argument string is target
        return replace(pos, len, String(s)); // get a copy and call it
                                             // recursively
    }

    if((pos + len) > thisLen)
        len = thisLen - pos;

    doReplace(pos, len, s.getStr(), s.length());

    //
    // post conditions
    //

    assert(length() == (OLD.length() - len + s.length()));

    return *this;
}


//
// remove
//

String& String::remove(size_t pos, size_t n)
{
    KEEPOLD;
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > length())
        strError("String::remove", "OutOfRange");

    //
    // operations
    //

    if(n == NPOS || (pos + n) > thisLen)
        n = thisLen - pos;

    if(n > 0)
        doReplace(pos, n,  "", 0);

    //
    // post conditions
    //

    assert(length() == (OLD.length() - n));

    return *this;
}

String& String::getRemove(char& c, size_t pos)
{
    KEEPOLD;

    //
    // preconditions
    //

    if(pos >= length())
        strError("String::getRemove", "OutOfRange");

    //
    // operations
    //

    c = getAtRaw(pos);

    doReplace(pos, 1,  "", 0);

    //
    // post conditions
    //

    assert(length() == (OLD.length() - 1));
    assert(OLD.getAt(pos) == c);

    return *this;
}

String& String::getRemove(String& s, size_t pos, size_t n)
{
    KEEPOLD;
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > thisLen)
        strError("String::getRemove", "OutOfRange");

    //
    // operations
    //

    if(n == NPOS || (pos + n) > thisLen)
        n = thisLen - pos;

    s = substr(pos, n);
    doReplace(pos, n,  "", 0);

    //
    // post conditions
    //

    assert(length() == (OLD.length() - s.length()));
    assert(s == OLD.substr(pos, n));

    return *this;
}

//
// substring
//
String String::substr(size_t pos, size_t n) const
{
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > thisLen)
        strError("String::substr", "OutOfRange");

    //
    // operations
    //

    if(n == NPOS || (pos + n) > thisLen)
        n = thisLen - pos;

    if(n == 0)
        return String();
    else
        return String(srep->str + pos, n);
}

//
// ANSI C functionality
//
int String::findFirstOf(const String& s, size_t& fpos, size_t pos) const
{
    return findFirstOf(s.getStr(), fpos, pos, s.length());
}

int String::findFirstOf(const char *cb, size_t& fpos, size_t pos, size_t n)
                                                                const
{
    size_t thisLen = length();

    //
    // preconditions
    //

    if(cb == 0)
        strError("String::findFirstOf", "InvalidArgument");

    //
    // operations
    //

    fpos = NPOS;

    if(thisLen == 0 || pos >= thisLen)
        return 0;

    if(n == NPOS)
        n = strlen(cb);

    // pointer are valid because thisLen > 0 => srep != 0

    char *pStart  = srep->str + pos;
    char *pEnd    = srep->str + thisLen;

    for(; pStart <  pEnd; pos++, pStart++) {
        if(memchr(cb, *pStart, n) != 0) {
            fpos = pos;
            return 1;
        }
    }
    return 0;
}

int String::findFirstNotOf(const String& s, size_t& fpos, size_t pos) const
{
    return findFirstNotOf(s.getStr(), fpos, pos, s.length());
}

int String::findFirstNotOf(const char *cb, size_t& fpos, size_t pos, size_t n)
                                                                       const
{
    size_t thisLen = length();

    //
    // preconditions
    //

    if(cb == 0)
        strError("String::findFirstOf", "InvalidArgument");

    //
    // operations
    //

    fpos = NPOS;

    if(thisLen == 0 || pos >= thisLen)
        return 0;
    if(n == NPOS)
        n = strlen(cb);

    // pointer are valid because thisLen > 0 => srep != 0

    char *pStart  = srep->str + pos;
    char *pEnd    = srep->str + thisLen;

    for(; pStart <  pEnd; pos++, pStart++) {
        if(memchr(cb, *pStart, n) == 0) {
            fpos = pos;
            return 1;
        }
    }
    return 0;
}

//
// copy to C buffer
//
size_t String::copy(char *cb, size_t n, size_t pos, size_t len) const
{
    size_t thisLen = length();

    //
    // preconditions
    //

    if(pos > thisLen)
        strError("String::copy", "OutOfRange");
    if(cb == 0)
        strError("String::copy", "InvalidArgument");

    //
    // operations
    //

    if(len > (thisLen - pos))
        len = thisLen - pos;

    if(n < len)
        len = n;
    if(len > 0)
        memcpy(cb, srep->str + pos, len);

    return (len);
}

//
//  get pointer to internal C-String
//
const char* String::cStr() const
{
    const char *p = "";

    //
    // operations
    //

    if(srep)
         p = srep->cPtr();
    return p;
}

//
// capacity
//

void  String::reserve(size_t n) const
{
    size_t thisLen = length();
    String::StringRep* rep;

    // guarantees uniqueness !!

    if(n < thisLen)
        n = thisLen;
    if(n > 0)
        rep = StringRep::getNew(thisLen, n, srep->str);
    else
        rep = 0;
    ((String*)this)->refDec();
    ((String*)this)->srep = rep;  // casting constness away to use
                                  // meaningwise constness
}

//
// friend functions
//
ostream& operator<<(ostream& os, const String& s)
{
    //
    // operations
    //

    if(s.srep) {
        os.write(s.getStr(), s.length());
    }
    return os;
}

const int lBufSize = 32;

istream& operator>>(istream& is, String& s)
{
    char aChar;
    char buffer[lBufSize];
    int bufpos = 0;

    // I am nor very experienced in iostream
    // please give me some comments

    s = "";
    if(is.good()) {
        if(is.flags() & ios::skipws)
            is >> ws;
        if(is) {
            for(;;) {
                is.get(aChar);
                if(!is)
                    break;
                if(isspace(aChar)) {
                    is.putback(aChar);
                    break;
                }
                if(bufpos >= lBufSize) {
                    s.append(buffer, lBufSize);
                    bufpos = 0;
                }
                buffer[bufpos++] = aChar;
            }
        }
    }
    if(bufpos > 0)
        s.append(buffer, bufpos);
    if(is.eof() && s.length() != 0)
        is.clear(0);                    // ??
    return is;
}

istream& getline(istream& is, String& s, char c)
{
    char aChar;
    char buffer[lBufSize];
    int bufpos = 0;

    s = "";
    if(is.good()) {
        for(;;) {
            is.get(aChar);
            if(!is)
                break;
            if(aChar == c) {       // get and consume eol character !!
                break;
            }
            if(bufpos >= lBufSize) {
                s.append(buffer, lBufSize);
                bufpos = 0;
            }
            buffer[bufpos++] = aChar;
        }
    }
    if(bufpos > 0)
        s.append(buffer, bufpos);
    if(is.eof() && s.length() != 0)
        is.clear(0);                // ??
    return is;
}

//
// string add functions
//
String operator+(const String& s1, const String& s2)
{
    //
    // operations
    //

    return String(s1.getStr(), s1.length(), s2.getStr(), s2.length());
}

String operator+(const String& s, const char* cs)
{
    //
    // preconditions
    //

    if(cs == 0)
        strError("operator+", "InvalidArgument");

    //
    // operations
    //
    return String(s.getStr(), s.length(), cs, strlen(cs));
}

String operator+(const char* cs, const String& s)
{
    //
    // preconditions
    //

    if(cs == 0)
        strError("operator+", "InvalidArgument");

    //
    // operations
    //
    return String(cs, strlen(cs), s.getStr(), s.length());
}

String operator+(const String& s, char c)
{
    //
    // operations
    //
    return String(s.getStr(), s.length(), &c, 1);
}

String operator+(char c, const String& s)
{
    //
    // operations
    //
    return String(&c, 1, s.getStr(), s.length());
}

int compare(const String& s1, const String& s2)
{
    return s1.compare(s2);
}

int compare(const String& s, const char* cs)
{
    //
    // preconditions
    //

    if(cs == 0)
        strError("compare", "InvalidArgument");

    //
    // operations
    //

    return s.compare(cs, strlen(cs));
}

int compare(const char *cs, const String& s)
{
    //
    // preconditions
    //

    if(cs == 0)
        strError("compare", "InvalidArgument");

    //
    // operations
    //

    return -s.compare(cs, strlen(cs));
}

⌨️ 快捷键说明

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