|
|
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: ///////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.