好久没有写过程序,最近想学习下界面库的开发,基于directui的界面个人觉得还不错,像金山的源代码和duilib都是不错的。本人想结合二者做一个轻量级的界面库,同时又不依赖于常用的MFC、WTL等。在程序开发中字符串的使用是必须的,C++语音没有原生字符串,STL等标准库又多是模板类,如果开发DLL导出时就出现问题了。今天从WTL库里摘出来一个简单的字符串类,实现了基本功能,可在此基础上进行扩展。
头文件
1 struct CStringDataE 2 { 3 long nRefs; 4 int nDataLength; 5 int nAllocLength; 6 TCHAR* data() { return (TCHAR*)(this + 1); } 7 }; 8 _declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 }; 9 _declspec(selectany) CStringDataE* _atltmpDataNil = (CStringDataE*)&rgInitData; 10 _declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringDataE)); 11 class UI_API CUIString 12 { 13 public: 14 CUIString(void); 15 CUIString(const CUIString& stringSrc); 16 ~CUIString(void); 17 18 CUIString& operator =(const CUIString& stringSrc); 19 CUIString& operator =(TCHAR ch); 20 CUIString& operator =(LPCTSTR lpsz); 21 protected: 22 LPTSTR m_pchData; // pointer to ref counted string data 23 CStringDataE* GetData() const; 24 void Init(); 25 BOOL AllocBuffer(int nLen); 26 void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData); 27 BOOL AllocBeforeWrite(int nLen); 28 void Release(); 29 static const CUIString& PASCAL _GetEmptyString(); 30 };
源文件
1 #include "stdafx.h" 2 #include "UIString.h" 3 #include "tchar.h" 4 #include "limits.h" 5 #include "assert.h" 6 CUIString::CUIString(void) 7 { 8 Init(); 9 } 10 CUIString::CUIString(const CUIString& stringSrc) 11 { 12 assert(stringSrc.GetData()->nRefs != 0); 13 if (stringSrc.GetData()->nRefs >= 0) 14 { 15 assert(stringSrc.GetData() != _atltmpDataNil); 16 m_pchData = stringSrc.m_pchData; 17 InterlockedIncrement(&GetData()->nRefs); 18 } 19 else 20 { 21 Init(); 22 *this = stringSrc.m_pchData; 23 } 24 } 25 // overloaded assignment 26 CUIString& CUIString::operator =(const CUIString& stringSrc) 27 { 28 if (m_pchData != stringSrc.m_pchData) 29 { 30 if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0) 31 { 32 // actual copy necessary since one of the strings is locked 33 AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData); 34 } 35 else 36 { 37 // can just copy references around 38 Release(); 39 assert(stringSrc.GetData() != _atltmpDataNil); 40 m_pchData = stringSrc.m_pchData; 41 InterlockedIncrement(&GetData()->nRefs); 42 } 43 } 44 return *this; 45 } 46 CUIString& CUIString::operator =(TCHAR ch) 47 { 48 assert(!_istlead(ch)); // can't set single lead byte 49 AssignCopy(1, &ch); 50 return *this; 51 } 52 CUIString& CUIString::operator =(LPCTSTR lpsz) 53 { 54 assert(lpsz!= NULL ); 55 AssignCopy(lstrlen(lpsz), lpsz); 56 return *this; 57 } 58 CUIString::~CUIString(void) 59 { 60 if (GetData() != _atltmpDataNil) 61 { 62 if (InterlockedDecrement(&GetData()->nRefs) <= 0) 63 delete[](BYTE*)GetData(); 64 } 65 } 66 67 void CUIString::Init() 68 { 69 m_pchData = _GetEmptyString().m_pchData; 70 } 71 72 BOOL CUIString::AllocBuffer(int nLen) 73 { 74 assert(nLen >= 0); 75 assert(nLen <= INT_MAX - 1); // max size (enough room for 1 extra) 76 if (nLen == 0) 77 { 78 Init(); 79 } 80 else 81 { 82 CStringDataE* pData = NULL; 83 assert(pData = (CStringDataE*)new BYTE[sizeof(CStringDataE) + (nLen + 1) * sizeof(TCHAR)]); 84 if (pData == NULL) 85 return FALSE; 86 pData->nRefs = 1; 87 pData->data()[nLen] = TEXT('