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 + -
显示快捷键?