dwstring.cpp.svn-base

来自「ffshow源码」· SVN-BASE 代码 · 共 2,010 行 · 第 1/4 页

SVN-BASE
2,010
字号
//=============================================================================// File:       dwstring.cpp// Contents:   Definitions for DwString// Maintainer: Doug Sauder <dwsauder@fwb.gulf.net>// WWW:        http://www.fwb.gulf.net/~dwsauder/mimepp.html//// Copyright (c) 1996, 1997 Douglas W. Sauder// All rights reserved.//// IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT,// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF// THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER// HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.//// DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT// NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A// PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"// BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE,// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.////=============================================================================#include "stdafx.h"#include "dwstring.h"#if defined (DW_DEBUG_VERSION)#define DBG_STMT(x) x;#else#define DBG_STMT(x) ;#endif#if defined (DW_DEBUG_VERSION) || defined (DW_DEVELOPMENT_VERSION)#define DEV_STMT(x) x;#else#define DEV_STMT(x) ;#endiftemplate<class tchar> static int dw_strcasecmp(const tchar* s1, size_t len1, const tchar* s2, size_t len2){    assert(s1 != 0);    assert(s2 != 0);    size_t len = std::min(len1, len2);    for (size_t i=0; i < len; ++i) {        int c1 = tolower(s1[i]);        int c2 = tolower(s2[i]);        if (c1 < c2) {            return -1;        }        else if (c1 > c2) {            return 1;        }    }    if (len1 < len2) {        return -1;    }    else if (len1 > len2) {        return 1;    }    return 0;}template<class tchar> static int dw_strcmp(const tchar* s1, size_t len1, const tchar* s2, size_t len2){    assert(s1 != 0);    assert(s2 != 0);    size_t len = std::min(len1, len2);    for (size_t i=0; i < len; ++i) {        if (s1[i] < s2[i]) {            return -1;        }        else if (s1[i] > s2[i]) {            return 1;        }    }    if (len1 < len2) {        return -1;    }    else if (len1 > len2) {        return 1;    }    return 0;}// Copytemplate<class tchar> inline void mem_copy(const tchar* src, size_t n, tchar* dest){    assert(src != 0);    assert(dest != 0);    assert(src != dest);    if (n == 0 || src == dest || !src || !dest) return;    memmove(dest, src, n*sizeof(tchar));}// Allocate buffer whose size is a power of 2template<class tchar> static tchar* mem_alloc(size_t* aSize){    assert(aSize != 0);    // minimum size is 32    size_t size = 32;    while (size < *aSize) {        size <<= 1;    }    *aSize = 0;    tchar* buf = new tchar[size];    if (buf != 0)        *aSize = size;    return buf;}template<class tchar> static inline DwStringRep<tchar>* new_rep_reference(DwStringRep<tchar>* rep){    assert(rep != 0);    ++rep->mRefCount;    return rep;}template<class tchar> static inline void delete_rep_safely(DwStringRep<tchar>* rep){    assert(rep != 0);#if defined(DW_DEBUG_VERSION) || defined(DW_DEVELOPMENT_VERSION)    if (rep->mRefCount <= 0) {        std::cerr << "Error: attempt to delete a DwStringRep "            "with ref count <= 0" << std::endl;        std::cerr << "(Possibly 'delete' was called twice for same object)"            << std::endl;        abort();    }#endif //  defined(DW_DEBUG_VERSION) || defined(DW_DEVELOPMENT_VERSION)    --rep->mRefCount;    if (rep->mRefCount == 0) {        delete rep;    }}//--------------------------------------------------------------------------//DwStringRep* DwStringRep::theirPool = NULL;//int DwStringRep::theirPoolCount = 0;// DwStringRep takes ownership of the buffer passed as an argumenttemplate<class tchar> DwStringRep<tchar>::DwStringRep(tchar* aBuf, size_t aSize){    assert(aBuf != 0);    mSize = aSize;    mBuffer = aBuf;    mRefCount = 1;    mPageMod = 0;}/*DwStringRep::DwStringRep(FILE* aFile, size_t aSize){    assert(aFile != 0);    static int pagesize = -1;    if (pagesize < 0)	pagesize = getpagesize();    int tell = ftell(aFile);    mPageMod = tell % pagesize;    mSize = aSize;    mRefCount = 1;        mBuffer = (char *)mmap(0, aSize + mPageMod, PROT_READ, MAP_SHARED, fileno(aFile), tell - mPageMod) + mPageMod;    ++mPageMod;    if (mBuffer == MAP_FAILED) {	mBuffer = 0;	mSize = 0;	mPageMod = 0;    }}*/template<class tchar> DwStringRep<tchar>::~DwStringRep(){#if defined (DW_DEBUG_VERSION) || defined (DW_DEVELOPMENT_VERSION)    if (mBuffer == 0) {        std::cerr << "DwStringRep destructor called for bad DwStringRep object"            << std::endl;        std::cerr << "(Possibly 'delete' was called twice for same object)"            << std::endl;        abort();    }#endif //  defined (DW_DEBUG_VERSION) || defined (DW_DEVELOPMENT_VERSION)/*    if (mPageMod) {	--mPageMod;	munmap(mBuffer - mPageMod, mSize + mPageMod);    } else */{	DwString<tchar>::mem_free(mBuffer);    }    //DEV_STMT(mBuffer = 0)}template<class tchar> void DwStringRep<tchar>::CheckInvariants() const{#if defined (DW_DEBUG_VERSION)    assert(mBuffer != 0);    assert(mSize > 0);    assert(mRefCount > 0);#endif // defined (DW_DEBUG_VERSION)}// Efficient memory management.  May be used at some point in the future.#if 0void* DwStringRep::operator new(size_t sz){    void* rep;    if (theirPoolCount > 0) {        --theirPoolCount;        rep = theirPool;        theirPool = theirPool->mNext;    }    else {        rep = new char[sz];    }    return rep;}void DwStringRep::operator delete(void* aRep, size_t){    if (theirPoolCount < 200) {        DwStringRep* rep = (DwStringRep*) aRep;        ++theirPoolCount;        rep->mNext = theirPool;        theirPool = rep;    }    else {        delete [] (char*) aRep;    }}#endif//--------------------------------------------------------------------------template<class tchar> const size_t DwString<tchar>::kEmptyBufferSize = 4;template<> char DwString<char>::sEmptyBuffer[]="    ";template<> wchar_t DwString<wchar_t>::sEmptyBuffer[]=L"    ";template<class tchar> DwStringRep<tchar>* DwString<tchar>::sEmptyRep = NULL;template<class tchar> const size_t DwString<tchar>::npos = (size_t) -1;template<class tchar> void CALLBACK DwString<tchar>::GlobalInitialization( BOOL bLoading, const CLSID *){	if ( !bLoading && sEmptyRep && (sEmptyRep->mRefCount == 1) )	{		delete sEmptyRep;		sEmptyRep = NULL;	}}template<class tchar> DwString<tchar>::DwString(){    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(sEmptyRep->CheckInvariants())    mRep = new_rep_reference(sEmptyRep);    mStart = 0;    mLength = 0;}template<> DwString<char>::DwString(const wchar_t* aCstr){ init1(text<char>(aCstr));}template<> DwString<wchar_t>::DwString(const char* aCstr){ init1(text<wchar_t>(aCstr));}template<class tchar> void DwString<tchar>::init2(const DwString& aStr, size_t aPos, size_t aLen){    assert(aPos <= aStr.mLength);    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(aStr.CheckInvariants())    size_t pos = std::min(aPos, aStr.mLength);    size_t len = std::min(aLen, aStr.mLength - pos);    if (len > 0) {        mRep = new_rep_reference(aStr.mRep);        mStart = aStr.mStart + pos;        mLength = len;    }    else // if (len == 0)     {        mRep = new_rep_reference(sEmptyRep);        mStart = 0;        mLength = 0;    }}template<> DwString<char>::DwString(const DwString<char> &aStr,size_t aPos,size_t aLen){ init2(aStr,aPos,aLen);}template<> DwString<char>::DwString(const DwString<wchar_t> &aStr,size_t aPos,size_t aLen){ init2(aStr.c_str(),aPos,aLen); //TODO: optimize}template<> DwString<wchar_t>::DwString(const DwString<wchar_t> &aStr,size_t aPos,size_t aLen){ init2(aStr,aPos,aLen);}template<> DwString<wchar_t>::DwString(const DwString<char> &aStr,size_t aPos,size_t aLen){ init2(aStr.c_str(),aPos,aLen);}template<class tchar> DwString<tchar>::DwString(const tchar* aBuf, size_t aLen){    assert(aBuf != 0);    assert(aLen != (size_t)-1);    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(sEmptyRep->CheckInvariants())    // Set valid values, in case an exception is thrown    mRep = new_rep_reference(sEmptyRep);    mStart = 0;    mLength = 0;    _replace(0, mLength, aBuf, aLen);}template<class tchar> void DwString<tchar>::init1(const tchar *aCstr){    assert(aCstr != 0);    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(sEmptyRep->CheckInvariants())    // Set valid values, in case an exception is thrown    mRep = new_rep_reference(sEmptyRep);    mStart = 0;    mLength = 0;    size_t len = (aCstr) ? strlen(aCstr) : 0;    _replace(0, mLength, aCstr, len);}template<> DwString<char>::DwString(const char* aCstr){ init1(aCstr);}template<> DwString<wchar_t>::DwString(const wchar_t* aCstr){ init1(aCstr);}template<class tchar> DwString<tchar>::DwString(size_t aLen, tchar aChar){    assert(aLen != (size_t)-1);    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(sEmptyRep->CheckInvariants())    // Set valid values, in case an exception is thrown    mRep = new_rep_reference(sEmptyRep);    mStart = 0;    mLength = 0;    _replace(0, mLength, aLen, aChar);}template<class tchar> DwString<tchar>::DwString(tchar* aBuf, size_t aSize, size_t aStart, size_t aLen){    assert(aBuf != 0);    assert(aSize > 0);    assert(aLen < aSize);    assert(aStart < aSize - aLen);    if (sEmptyRep == 0) {        sEmptyBuffer[0] = 0;        sEmptyRep = new DwStringRep<tchar>(sEmptyBuffer, kEmptyBufferSize);        assert(sEmptyRep != 0);    }    DBG_STMT(sEmptyRep->CheckInvariants())    // Set valid values, in case an exception is thrown    mRep = new_rep_reference(sEmptyRep);    mStart = 0;    mLength = 0;    DwStringRep<tchar>* rep = new DwStringRep<tchar>(aBuf, aSize);    assert(rep != 0);    if (rep != 0) {        mRep = rep;        mStart = aStart;        mLength = aLen;    }    else /* if (rep == 0) */ {        delete [] aBuf;    }}template<class tchar> DwString<tchar>::~DwString(){    assert(mRep != 0);    delete_rep_safely(mRep);    DEV_STMT(mRep = 0)}template<class tchar> size_t DwString<tchar>::max_size() const{    return ((size_t)-1) - 1;}template<class tchar> void DwString<tchar>::resize(size_t aLen, tchar aChar){    // making string shorter?    if (aLen < mLength) {        mLength = aLen;        if (mRep->mRefCount == 1) {            mRep->mBuffer[mStart + aLen] = 0;        }    }    // expanding string    else if (aLen > mLength) {        _replace(mLength, 0, aLen-mLength, aChar);    }}template<class tchar> void DwString<tchar>::resize(size_t aLen){    resize(aLen, 0);}template<class tchar> void DwString<tchar>::reserve(size_t aSize){    if (mRep->mRefCount == 1 && aSize < mRep->mSize && mRep != sEmptyRep) {        return;    }    size_t size = aSize + 1;    tchar* newBuf = mem_alloc<tchar>(&size);    assert(newBuf != 0);    if (newBuf != 0) {        tchar* to = newBuf;        const tchar* from = mRep->mBuffer + mStart;        mem_copy(from, mLength, to);        to[mLength] = 0;        DwStringRep<tchar>* rep= new DwStringRep<tchar>(newBuf, size);        assert(rep != 0);        if (rep != 0) {            delete_rep_safely(mRep);            mRep = rep;            mStart = 0;        }        else {             mem_free(newBuf);        }    }}template<class tchar> void DwString<tchar>::clear(){    assign(_L(""));}template<class tchar> DwString<tchar>& DwString<tchar>::append(const DwString<tchar>& aStr){    return append(aStr, 0, aStr.mLength);}template<class tchar> DwString<tchar>& DwString<tchar>::append(const DwString<tchar>& aStr, size_t aPos, size_t aLen){    assert(aPos <= aStr.mLength);    size_t pos = std::min(aPos, aStr.mLength);    size_t len = std::min(aLen, aStr.mLength - pos);    if (&aStr == this) {        DwString<tchar> temp(aStr);        _replace(mLength, 0, &temp.mRep->mBuffer[temp.mStart+pos], len);    }    else {        _replace(mLength, 0, &aStr.mRep->mBuffer[aStr.mStart+pos], len);    }    return *this;}template<class tchar> DwString<tchar>& DwString<tchar>::append(const tchar* aBuf, size_t aLen)

⌨️ 快捷键说明

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