string.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,635 行 · 第 1/3 页

CPP
1,635
字号
            }
        } while ( cursor-- > c_str() );
    }

    return npos;
}

size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
{
    return rfind(wxStringBase(sz, n), nStart);
}

size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
{
    if ( nStart == npos )
    {
        nStart = length();
    }
    else
    {
        wxASSERT( nStart <= length() );
    }

    const wxChar *actual;
    for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 );
          actual > c_str(); --actual )
    {
        if ( *(actual - 1) == ch )
            return (actual - 1) - c_str();
    }

    return npos;
}

size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
{
    wxASSERT(nStart <= length());

    size_t len = wxStrlen(sz);

    size_t i;
    for(i = nStart; i < this->length(); ++i)
    {
        if (wxTmemchr(sz, *(c_str() + i), len))
            break;
    }

    if(i == this->length())
        return npos;
    else
        return i;
}

size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
                                   size_t n) const
{
    return find_first_of(wxStringBase(sz, n), nStart);
}

size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
{
    if ( nStart == npos )
    {
        nStart = length() - 1;
    }
    else
    {
        wxASSERT_MSG( nStart <= length(),
                        _T("invalid index in find_last_of()") );
    }

    size_t len = wxStrlen(sz);

    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
    {
        if ( wxTmemchr(sz, *p, len) )
            return p - c_str();
    }

    return npos;
}

size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart,
                                   size_t n) const
{
    return find_last_of(wxStringBase(sz, n), nStart);
}

size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
{
    if ( nStart == npos )
    {
        nStart = length();
    }
    else
    {
        wxASSERT( nStart <= length() );
    }

    size_t len = wxStrlen(sz);

    size_t i;
    for(i = nStart; i < this->length(); ++i)
    {
        if (!wxTmemchr(sz, *(c_str() + i), len))
            break;
    }

    if(i == this->length())
         return npos;
     else
        return i;
}

size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
                                       size_t n) const
{
    return find_first_not_of(wxStringBase(sz, n), nStart);
}

size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
{
    wxASSERT( nStart <= length() );

    for ( const wxChar *p = c_str() + nStart; *p; p++ )
    {
        if ( *p != ch )
            return p - c_str();
    }

    return npos;
}

size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
{
    if ( nStart == npos )
    {
        nStart = length() - 1;
    }
    else
    {
        wxASSERT( nStart <= length() );
    }

    size_t len = wxStrlen(sz);

    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
    {
        if ( !wxTmemchr(sz, *p,len) )
             return p - c_str();
    }

    return npos;
}

size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
                                      size_t n) const
{
    return find_last_not_of(wxStringBase(sz, n), nStart);
}

size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
{
    if ( nStart == npos )
    {
        nStart = length() - 1;
    }
    else
    {
        wxASSERT( nStart <= length() );
    }

    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
    {
        if ( *p != ch )
            return p - c_str();
    }

    return npos;
}

wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
                                    const wxChar *sz)
{
  wxASSERT_MSG( nStart <= length(),
                _T("index out of bounds in wxStringBase::replace") );
  size_t strLen = length() - nStart;
  nLen = strLen < nLen ? strLen : nLen;

  wxStringBase strTmp;
  strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs

  //This is kind of inefficient, but its pretty good considering...
  //we don't want to use character access operators here because on STL
  //it will freeze the reference count of strTmp, which means a deep copy
  //at the end when swap is called
  //
  //Also, we can't use append with the full character pointer and must
  //do it manually because this string can contain null characters
  for(size_t i1 = 0; i1 < nStart; ++i1)
      strTmp.append(1, this->c_str()[i1]);

  //its safe to do the full version here because
  //sz must be a normal c string
  strTmp.append(sz);

  for(size_t i2 = nStart + nLen; i2 < length(); ++i2)
      strTmp.append(1, this->c_str()[i2]);

  swap(strTmp);
  return *this;
}

wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
                                    size_t nCount, wxChar ch)
{
  return replace(nStart, nLen, wxStringBase(nCount, ch).c_str());
}

wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
                                    const wxStringBase& str,
                                    size_t nStart2, size_t nLen2)
{
  return replace(nStart, nLen, str.substr(nStart2, nLen2));
}

wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
                                    const wxChar* sz, size_t nCount)
{
  return replace(nStart, nLen, wxStringBase(sz, nCount).c_str());
}

wxStringBase wxStringBase::substr(size_t nStart, size_t nLen) const
{
  if ( nLen == npos )
    nLen = length() - nStart;
  return wxStringBase(*this, nStart, nLen);
}

// assigns one string to another
wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
{
  wxASSERT( stringSrc.GetStringData()->IsValid() );

  // don't copy string over itself
  if ( m_pchData != stringSrc.m_pchData ) {
    if ( stringSrc.GetStringData()->IsEmpty() ) {
      Reinit();
    }
    else {
      // adjust references
      GetStringData()->Unlock();
      m_pchData = stringSrc.m_pchData;
      GetStringData()->Lock();
    }
  }

  return *this;
}

// assigns a single character
wxStringBase& wxStringBase::operator=(wxChar ch)
{
  if ( !AssignCopy(1, &ch) ) {
    wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
  }
  return *this;
}

// assigns C string
wxStringBase& wxStringBase::operator=(const wxChar *psz)
{
  if ( !AssignCopy(wxStrlen(psz), psz) ) {
    wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") );
  }
  return *this;
}

// helper function: does real copy
bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
{
  if ( nSrcLen == 0 ) {
    Reinit();
  }
  else {
    if ( !AllocBeforeWrite(nSrcLen) ) {
      // allocation failure handled by caller
      return false;
    }
    memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
    GetStringData()->nDataLength = nSrcLen;
    m_pchData[nSrcLen] = wxT('\0');
  }
  return true;
}

// ---------------------------------------------------------------------------
// string concatenation
// ---------------------------------------------------------------------------

// add something to this string
bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
                              size_t nMaxLen)
{
  STATISTICS_ADD(SummandLength, nSrcLen);

  nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen;

  // concatenating an empty string is a NOP
  if ( nSrcLen > 0 ) {
    wxStringData *pData = GetStringData();
    size_t nLen = pData->nDataLength;
    size_t nNewLen = nLen + nSrcLen;

    // alloc new buffer if current is too small
    if ( pData->IsShared() ) {
      STATISTICS_ADD(ConcatHit, 0);

      // we have to allocate another buffer
      wxStringData* pOldData = GetStringData();
      if ( !AllocBuffer(nNewLen) ) {
          // allocation failure handled by caller
          return false;
      }
      memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
      pOldData->Unlock();
    }
    else if ( nNewLen > pData->nAllocLength ) {
      STATISTICS_ADD(ConcatHit, 0);

      reserve(nNewLen);
      // we have to grow the buffer
      if ( capacity() < nNewLen ) {
          // allocation failure handled by caller
          return false;
      }
    }
    else {
      STATISTICS_ADD(ConcatHit, 1);

      // the buffer is already big enough
    }

    // should be enough space
    wxASSERT( nNewLen <= GetStringData()->nAllocLength );

    // fast concatenation - all is done in our buffer
    memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));

    m_pchData[nNewLen] = wxT('\0');          // put terminating '\0'
    GetStringData()->nDataLength = nNewLen; // and fix the length
  }
  //else: the string to append was empty
  return true;
}

// ---------------------------------------------------------------------------
// simple sub-string extraction
// ---------------------------------------------------------------------------

// helper function: clone the data attached to this string
bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
{
  if ( nCopyLen == 0 ) {
    dest.Init();
  }
  else {
    if ( !dest.AllocBuffer(nCopyLen) ) {
      // allocation failure handled by caller
      return false;
    }
    memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
  }
  return true;
}

#endif // !wxUSE_STL

#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)

#if !wxUSE_STL
    #define STRINGCLASS wxStringBase
#else
    #define STRINGCLASS wxString
#endif

static inline int wxDoCmp(const wxChar* s1, size_t l1,
                          const wxChar* s2, size_t l2)
{
    if( l1 == l2 )
        return wxTmemcmp(s1, s2, l1);
    else if( l1 < l2 )
    {
        int ret = wxTmemcmp(s1, s2, l1);
        return ret == 0 ? -1 : ret;
    }
    else
    {
        int ret = wxTmemcmp(s1, s2, l2);
        return ret == 0 ? +1 : ret;
    }
}

int STRINGCLASS::compare(const wxStringBase& str) const
{
    return ::wxDoCmp(data(), length(), str.data(), str.length());
}

int STRINGCLASS::compare(size_t nStart, size_t nLen,
                         const wxStringBase& str) const
{
    wxASSERT(nStart <= length());
    size_type strLen = length() - nStart;
    nLen = strLen < nLen ? strLen : nLen;
    return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
}

int STRINGCLASS::compare(size_t nStart, size_t nLen,
                         const wxStringBase& str,
                         size_t nStart2, size_t nLen2) const
{
    wxASSERT(nStart <= length());
    wxASSERT(nStart2 <= str.length());
    size_type strLen  =     length() - nStart,
              strLen2 = str.length() - nStart2;
    nLen  = strLen  < nLen  ? strLen  : nLen;
    nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
    return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
}

int STRINGCLASS::compare(const wxChar* sz) const
{
    size_t nLen = wxStrlen(sz);
    return ::wxDoCmp(data(), length(), sz, nLen);
}

int STRINGCLASS::compare(size_t nStart, size_t nLen,
                         const wxChar* sz, size_t nCount) const
{
    wxASSERT(nStart <= length());
    size_type strLen = length() - nStart;
    nLen = strLen < nLen ? strLen : nLen;
    if( nCount == npos )
        nCount = wxStrlen(sz);

    return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
}

#undef STRINGCLASS

#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)

// ===========================================================================
// wxString class core
// ===========================================================================

// ---------------------------------------------------------------------------
// construction and conversion
// ---------------------------------------------------------------------------

#if wxUSE_UNICODE

// from multibyte string
wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
{
    // if nLength != npos, then we have to make a NULL-terminated copy
    // of first nLength bytes of psz first because the input buffer to MB2WC
    // must always be NULL-terminated:
    wxCharBuffer inBuf((const char *)NULL);
    if (nLength != npos)
    {
        wxASSERT( psz != NULL );
        wxCharBuffer tmp(nLength);
        memcpy(tmp.data(), psz, nLength);
        tmp.data()[nLength] = '\0';
        inBuf = tmp;
        psz = inBuf.data();
    }

    // first get the size of the buffer we need
    size_t nLen;
    if ( psz )
    {
        // calculate the needed size ourselves or use the provided one
        if (nLength == npos)
            nLen = strlen(psz);
        else
            nLen = nLength;
    }
    else
    {
        // nothing to convert
        nLen = 0;
    }


    // anything to do?
    if ( (nLen != 0) && (nLen != (size_t)-1) )
    {
        //Convert string
        size_t nRealSize;
        wxWCharBuffer theBuffer = conv.cMB2WC(psz, nLen, &nRealSize);

        //Copy
        if (nRealSize)
            assign( theBuffer.data() , nRealSize - 1 );
    }
}

//Convert wxString in Unicode mode to a multi-byte string
const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
{
    size_t dwOutSize;
    return conv.cWC2MB(c_str(), length(), &dwOutSize);
}

#else // ANSI

#if wxUSE_WCHAR_T
// from wide string
wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
{
    // if nLength != npos, then we have to make a NULL-terminated copy
    // of first nLength chars of psz first because the input buffer to WC2MB
    // must always be NULL-terminated:
    wxWCharBuffer inBuf((const wchar_t *)NULL);
    if (nLength != npos)
    {
        wxASSERT( pwz != NULL );
        wxWCharBuffer tmp(nLength);
        memcpy(tmp.data(), pwz, nLength * sizeof(wchar_t));
        tmp.data()[nLength] = '\0';
        inBuf = tmp;
        pwz = inBuf.data();
    }

    // first get the size of the buffer we need
    size_t nLen;
    if ( pwz )
    {
        // calculate the needed size ourselves or use the provided one
        if (nLength == npos)
            nLen = wxWcslen(pwz);
        else
            nLen = nLength;

⌨️ 快捷键说明

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