Annotation of mstools/mfc/src/string.cpp, revision 1.1.1.1

1.1       root        1: // This is a part of the Microsoft Foundation Classes C++ library. 
                      2: // Copyright (C) 1992 Microsoft Corporation 
                      3: // All rights reserved. 
                      4: //  
                      5: // This source code is only intended as a supplement to the 
                      6: // Microsoft Foundation Classes Reference and Microsoft 
                      7: // QuickHelp documentation provided with the library. 
                      8: // See these sources for detailed information regarding the 
                      9: // Microsoft Foundation Classes product. 
                     10: 
                     11: 
                     12: #include "afx.h"
                     13: #pragma hdrstop
                     14: #include <limits.h>
                     15: 
                     16: #ifdef AFX_CORE_SEG
                     17: #pragma code_seg(AFX_CORE_SEG)
                     18: #endif
                     19: 
                     20: #ifdef _DEBUG
                     21: #undef THIS_FILE
                     22: static char BASED_CODE THIS_FILE[] = __FILE__;
                     23: #endif
                     24: 
                     25: #define new DEBUG_NEW
                     26: 
                     27: /////////////////////////////////////////////////////////////////////////////
                     28: // static class data, special inlines
                     29: 
                     30: char _afxChNil = '\0';
                     31: 
                     32: // For an empty string, m_???Data will point here
                     33: // (note: avoids a lot of NULL pointer tests when we call standard
                     34: //  C runtime libraries
                     35: 
                     36: extern const CString NEAR afxEmptyString;
                     37: const CString NEAR afxEmptyString;
                     38: 
                     39: void CString::Init()
                     40: {
                     41:        m_nDataLength = m_nAllocLength = 0;
                     42:        m_pchData = &_afxChNil;
                     43: }
                     44: 
                     45: //////////////////////////////////////////////////////////////////////////////
                     46: // Construction/Destruction
                     47: 
                     48: CString::CString()
                     49: {
                     50:        Init();
                     51: }
                     52: 
                     53: CString::CString(const CString& stringSrc)
                     54: {
                     55:        // if constructing a CString from another CString, we make a copy of the
                     56:        // original string data to enforce value semantics (i.e. each string
                     57:        // gets a copy of it's own
                     58: 
                     59:        stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
                     60: }
                     61: 
                     62: void CString::AllocBuffer(int nLen)
                     63:  // always allocate one extra character for '\0' termination
                     64:  // assumes [optimistically] that data length will equal allocation length
                     65: {
                     66:        ASSERT(nLen >= 0);
                     67:        ASSERT(nLen < INT_MAX - 1); // max size (enough room for 1 extra)
                     68: 
                     69:        if (nLen == 0)
                     70:        {
                     71:                Init();
                     72:        }
                     73:        else
                     74:        {
                     75:                m_pchData = new char[nLen+1];       // may throw an exception
                     76:                m_pchData[nLen] = '\0';
                     77:                m_nDataLength = nLen;
                     78:                m_nAllocLength = nLen;
                     79:        }
                     80: }
                     81: 
                     82: void CString::Empty()
                     83: {
                     84:        if (m_pchData != &_afxChNil)
                     85:        {
                     86:                delete [] m_pchData;
                     87:                Init();
                     88:        }
                     89:        ASSERT(m_nDataLength == 0);
                     90:        ASSERT(m_nAllocLength == 0);
                     91: }
                     92: 
                     93: CString::~CString()
                     94:  //  free any attached data
                     95: {
                     96:        if (m_pchData != &_afxChNil)
                     97:                delete [] m_pchData;        // NOTE: not type safe
                     98: }
                     99: 
                    100: //////////////////////////////////////////////////////////////////////////////
                    101: // Helpers for the rest of the implementation
                    102: 
                    103: static inline int SafeStrlen(const char* psz)
                    104:        { return (psz == NULL) ? NULL : strlen(psz); }
                    105: 
                    106: void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
                    107:         int nExtraLen) const
                    108: {
                    109:        // will clone the data attached to this string
                    110:        // allocating 'nExtraLen' characters
                    111:        // Places results in uninitialized string 'dest'
                    112:        // Will copy the part or all of original data to start of new string
                    113: 
                    114:        int nNewLen = nCopyLen + nExtraLen;
                    115: 
                    116:        if (nNewLen == 0)
                    117:        {
                    118:                dest.Init();
                    119:        }
                    120:        else
                    121:        {
                    122:                dest.AllocBuffer(nNewLen);
                    123:                memcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen);
                    124:        }
                    125: }
                    126: 
                    127: //////////////////////////////////////////////////////////////////////////////
                    128: // More sophisticated construction
                    129: 
                    130: CString::CString(const char* psz)
                    131: {
                    132:        int nLen;
                    133:        if ((nLen = SafeStrlen(psz)) == 0)
                    134:                Init();
                    135:        else
                    136:        {
                    137:                AllocBuffer(nLen);
                    138:                memcpy(m_pchData, psz, nLen);
                    139:        }
                    140: }
                    141: 
                    142: //////////////////////////////////////////////////////////////////////////////
                    143: // Diagnostic support
                    144: 
                    145: #ifdef _DEBUG 
                    146: 
                    147: CDumpContext&
                    148: operator <<(CDumpContext& dc, const CString& string)
                    149: {
                    150:        dc << string.m_pchData;
                    151:        return dc;
                    152: }
                    153: 
                    154: #endif //_DEBUG
                    155: 
                    156: //////////////////////////////////////////////////////////////////////////////
                    157: // Assignment operators
                    158: //  All assign a new value to the string
                    159: //      (a) first see if the buffer is big enough
                    160: //      (b) if enough room, copy on top of old buffer, set size and type
                    161: //      (c) otherwise free old string data, and create a new one
                    162: //
                    163: //  All routines return the new string (but as a 'const CString&' so that
                    164: //      assigning it again will cause a copy, eg: s1 = s2 = "hi there".
                    165: //
                    166: 
                    167: void CString::AssignCopy(int nSrcLen, const char* pszSrcData)
                    168: {
                    169:        // check if it will fit
                    170:        if (nSrcLen > m_nAllocLength)
                    171:        {
                    172:                // it won't fit, allocate another one
                    173:                Empty();
                    174:                AllocBuffer(nSrcLen);
                    175:        }
                    176:        if (nSrcLen != 0)
                    177:                memcpy(m_pchData, pszSrcData, nSrcLen);
                    178:        m_nDataLength = nSrcLen;
                    179:        m_pchData[nSrcLen] = '\0';
                    180: }
                    181: 
                    182: const CString&
                    183: CString::operator =(const CString& stringSrc)
                    184: {
                    185:        AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
                    186:        return *this;
                    187: }
                    188: 
                    189: const CString&
                    190: CString::operator =(const char* psz)
                    191: {
                    192:        AssignCopy(SafeStrlen(psz), psz);
                    193:        return *this;
                    194: }
                    195: 
                    196: 
                    197: //////////////////////////////////////////////////////////////////////////////
                    198: // concatenation
                    199: 
                    200: // NOTE: "operator +" is done as friend functions for simplicity
                    201: //      There are three variants:
                    202: //          CString + CString
                    203: // and for ? = char, const char*
                    204: //          CString + ?
                    205: //          ? + CString
                    206: 
                    207: void
                    208: CString::ConcatCopy(int nSrc1Len, const char* pszSrc1Data,
                    209:                int nSrc2Len, const char* pszSrc2Data)
                    210: {
                    211:   // -- master concatenation routine
                    212:   // Concatenate two sources
                    213:   // -- assume that 'this' is a new CString object
                    214: 
                    215:        int nNewLen = nSrc1Len + nSrc2Len;
                    216:        AllocBuffer(nNewLen);
                    217:        memcpy(m_pchData, pszSrc1Data, nSrc1Len);
                    218:        memcpy(&m_pchData[nSrc1Len], pszSrc2Data, nSrc2Len);
                    219: }
                    220: 
                    221: CString
                    222: operator +(const CString& string1, const CString& string2)
                    223: {
                    224:        CString s;
                    225:        s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
                    226:                string2.m_nDataLength, string2.m_pchData);
                    227:        return s;
                    228: }
                    229: 
                    230: CString
                    231: operator +(const CString& string, const char* psz)
                    232: {
                    233:        CString s;
                    234:        s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(psz), psz);
                    235:        return s;
                    236: }
                    237: 
                    238: 
                    239: CString
                    240: operator +(const char* psz, const CString& string)
                    241: {
                    242:        CString s;
                    243:        s.ConcatCopy(SafeStrlen(psz), psz, string.m_nDataLength, string.m_pchData);
                    244:        return s;
                    245: }
                    246: 
                    247: //////////////////////////////////////////////////////////////////////////////
                    248: // concatenate in place
                    249: 
                    250: void
                    251: CString::ConcatInPlace(int nSrcLen, const char* pszSrcData)
                    252: {
                    253:        //  -- the main routine for += operators
                    254: 
                    255:        // if the buffer is too small, or we have a width mis-match, just
                    256:        //   allocate a new buffer (slow but sure)
                    257:        if (m_nDataLength + nSrcLen > m_nAllocLength)
                    258:        {
                    259:                // we have to grow the buffer, use the Concat in place routine
                    260:                char* pszOldData = m_pchData;
                    261:                ConcatCopy(m_nDataLength, pszOldData, nSrcLen, pszSrcData);
                    262:                ASSERT(pszOldData != NULL);
                    263:                if (pszOldData != &_afxChNil)
                    264:                        delete [] pszOldData;
                    265:        }
                    266:        else
                    267:        {
                    268:                // fast concatenation when buffer big enough
                    269:                memcpy(&m_pchData[m_nDataLength], pszSrcData, nSrcLen);
                    270:                m_nDataLength += nSrcLen;
                    271:        }
                    272:        ASSERT(m_nDataLength <= m_nAllocLength);
                    273:        m_pchData[m_nDataLength] = '\0';
                    274: }
                    275: 
                    276: const CString&
                    277: CString::operator +=(const char* psz)
                    278: {
                    279:        ConcatInPlace(SafeStrlen(psz), psz);
                    280:        return *this;
                    281: }
                    282: 
                    283: const CString&
                    284: CString::operator +=(const CString& string)
                    285: {
                    286:        ConcatInPlace(string.m_nDataLength, string.m_pchData);
                    287:        return *this;
                    288: }
                    289: 
                    290: 
                    291: ///////////////////////////////////////////////////////////////////////////////

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.