ATL Internals 2ed复习.chapter 2

String Data Types, Conversion Classes, and Helper Functions

对于字符串表示,不同的系统有不同的方法

C/C++使用在字串末尾加Nul

VB,Java,Pascal在字串头部标识字串长度

COM使用OLECHAR作为字符类型,COM的字符串为Nul结尾的OLECHARs,用LPOLESTR表示。如果向COM interface传递text参数,应该使用LPOLESTR

 

Unicode,=wchar_t, 16-bit,L()宏

MBCS,=unsigned char,1~2Bytes

ANSI,=[signed] char

TCHAR/_TCHAR,由编译条件决定定义类型,_T()宏

OLECHAR,Win32=wchar_t,Win16=char,Mac OS=char,Solaris OS=wchar_t

BSTR,头部标识长度的OLECHAR串,无法使用转换宏,转换类进行变换

 

使用转换类防止内存提前释放

LPOLESTR ConvertString(LPTSTR lpsz) { return CT2OLE(lpsz);}

转换宏,转换类区别

转换类都有C开头

转换宏永远使用栈分配,更快,需要USE_CONVERSION宏,可能在loop中造成程序内存崩溃

转换类更加安全

 

The CComBSTR Smart BSTR Class

BSTR特点

对于非C语言交互,应该使用BSTR作为字符串参数

BSTR包括一串字符串和一个前置整数,BSTR指向字符串,字符串以Nul结尾,前置整数为字符串Byte长度,不包括末尾Nul

BSTR必须使用SysAllocString,SysFreeString,copy必须真实复制字符串而不仅仅是指针

BSTR=NULL表示一个空的字符串

 

The CComBSTR Class

CComBSTR() { m_str = NULL; }           
~CComBSTR() { ::SysFreeString(m_str); }

构造函数变形

CComBSTR(LPCOLESTR pSrc) {              
    if (pSrc == NULL) m_str = NULL;     
    else {                              
        m_str = ::SysAllocString(pSrc); 
        if (m_str == NULL)              
                AtlThrow(E_OUTOFMEMORY);
    }                                   
}                                       
CComBSTR(int nSize, LPCOLESTR sz);

nSize为目标字符串的字符数,不包含末尾Nul

CComBSTR(const CComBSTR& src) {
    m_str = src.Copy();        
    ...                        
}                              
BSTR Copy() const {                             
    if (!*this) { return NULL; }                
    return ::SysAllocStringByteLen((char*)m_str,
        ::SysStringByteLen(m_str));             
}                                               
CComBSTR(LPCSTR pSrc) {         
     ...                        
     m_str = A2WBSTR(pSrc);     
     ...                        
}                               
CComBSTR(int nSize, LPCSTR sz) {
     ...                        
     m_str = A2WBSTR(sz, nSize);
     ...                        
}                               

CComBSTR(REFGUID src);例子

// Define a GUID as a binary constant
static const GUID GUID_Sample = { 0x8a44e110, 0xf134, 0x11d1,
    { 0x96, 0xb1, 0xBA, 0xDB, 0xAD, 0xBA, 0xDB, 0xAD } };

// Convert the binary GUID to its string representation
CComBSTR str6 (GUID_Sample) ;
// str6 contains "{8A44E110-F134-11d1-96B1-BADBADBADBAD}"

 
Assignment
CComBSTR& operator=(const CComBSTR& src) {               
    if (m_str != src.m_str) {                            
        ::SysFreeString(m_str);                          
        m_str = src.Copy();                              
        if (!!src && !*this) { AtlThrow(E_OUTOFMEMORY); }
    }                                                    
    return *this;                                        
}                                                        
CComBSTR& operator=(LPCOLESTR pSrc) {               
    if (pSrc != m_str) {                            
        ::SysFreeString(m_str);                     
        if (pSrc != NULL) {                         
            m_str = ::SysAllocString(pSrc);         
            if (!*this) { AtlThrow(E_OUTOFMEMORY); }
        } else {                                    
            m_str = NULL;                           
        }                                           
    }                                               
    return *this;                                   
}                                                   
HRESULT AssignBSTR(const BSTR bstrSrc) {                   
    HRESULT hr = S_OK;                                     
    if (m_str != bstrSrc) {                                
        ::SysFreeString(m_str);                            
        if (bstrSrc != NULL) {                             
            m_str = ::SysAllocStringByteLen((char*)bstrSrc,
                ::SysStringByteLen(bstrSrc));              
                                                    
            if (!*this) { hr = E_OUTOFMEMORY; }            
        } else {                                           
            m_str = NULL;                                  
        }                                                  
    }                                                      
                                                           
                                                           
    return hr;                                             
}                                                          
CComBSTR& operator=(LPCSTR pSrc) {                          
    ::SysFreeString(m_str);                                 
    m_str = A2WBSTR(pSrc);                                  
    if (!*this && pSrc != NULL) { AtlThrow(E_OUTOFMEMORY); }
    return *this;                                           
}                                                           
 
bool LoadString(HINSTANCE hInst, UINT nID) ;
bool LoadString(UINT nID) ;                 

CComBSTR Operations

operator BSTR() const { return m_str; }

#ifndef ATL_CCOMBSTR_ADDRESS_OF_ASSERT    
// Temp disable CComBSTR::operator& Assert
#define ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT 
#endif                                    
                                          
BSTR* operator&() {                       
#ifndef ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT 
    ATLASSERT(!*this);                    
#endif                                    
    return &m_str;                        
}                                         
HRESULT CopyTo(BSTR* pbstr);
BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; }
void Attach(BSTR src) {        
    if (m_str != src) {        
        ::SysFreeString(m_str);
        m_str = src;           
    }                          
}                              


 

void Empty() { ::SysFreeString(m_str); m_str = NULL; }
HRESULT BSTRToArray(LPSAFEARRAY *ppArray) {          
    return VectorFromBstr(m_str, ppArray);           
}                                                    
                                                     
HRESULT ArrayToBSTR(const SAFEARRAY *pSrc) {         
    ::SysFreeString(m_str);                          
    return BstrFromVector((LPSAFEARRAY)pSrc, &m_str);
}                                                    

 

String Concatenation Using CComBSTR

HRESULT Append(LPCOLESTR lpsz, int nLen);             
HRESULT Append(LPCOLESTR lpsz);                       
HRESULT Append(LPCSTR);                               
HRESULT Append(char ch);                              
HRESULT Append(wchar_t ch);                           
                                                      
HRESULT Append(const CComBSTR& bstrSrc);          
CComBSTR& operator+=(const CComBSTR& bstrSrc);
                                                      
HRESULT AppendBSTR(BSTR p);                           

HRESULT AppendBytes(const char* lpsz, int nLen);

注意AppendBytes does not perform a conversion from ANSI to Unicode.

Character Case Conversion

HRESULT ToLower() {                                        
        if (m_str != NULL) {                               
#ifdef _UNICODE                                            
               // Convert in place                         
               CharLowerBuff(m_str, Length());             
#else                                                      
            UINT _acp = _AtlGetConversionACP();            
            ...                                            
            int nRet = WideCharToMultiByte(                
                _acp, 0, m_str, Length(),                  
                pszA, _convert, NULL, NULL);               
            ...                                            
                                                           
            CharLowerBuff(pszA, nRet);                     
                                                           
            nRet = MultiByteToWideChar(_acp, 0, pszA, nRet,
                                    pszW, _convert);       
                ...                                        
                                                           
            BSTR b = ::SysAllocStringByteLen(              
                (LPCSTR) (LPWSTR) pszW,                    
                nRet * sizeof(OLECHAR));                   
            if (b == NULL)                                 
                    return E_OUTOFMEMORY;                  
            SysFreeString(m_str);                          
            m_str = b;                                     
#endif                                                     
                                     
            }                                              
            return S_OK;                                   
}                                                          
CComBSTR Comparison Operators
bool operator!() const { return (m_str == NULL); }


 

bool operator<(const CComBSTR& bstrSrc) const {
    return VarBstrCmp(m_str, bstrSrc.m_str,    
        LOCALE_USER_DEFAULT, 0) ==             
    VARCMP_LT;                                 
}                                              
bool operator>(LPCSTR pszSrc) const {
        CComBSTR bstr2(pszSrc);      
        return operator>(bstr2);     
}                                    
bool operator<(LPCOLESTR pszSrc) const {
    CComBSTR bstr2(pszSrc);             
    return operator>(bstr2);            
}                                       
bool operator>(LPOLESTR pszSrc) const { 
    return operator>((LPCOLESTR)pszSrc);
}                                       


CComBSTR Persistence Support

HRESULT WriteToStream(IStream* pStream) {             
    ATLASSERT(pStream != NULL);                       
    if(pStream == NULL)                               
        return E_INVALIDARG;                          
                                                      
    ULONG cb;                                         
    ULONG cbStrLen = ULONG(m_str ?                    
        SysStringByteLen(m_str)+sizeof(OLECHAR) : 0); 
    HRESULT hr = pStream->Write((void*) &cbStrLen,    
        sizeof(cbStrLen), &cb);                       
    if (FAILED(hr))                                   
        return hr;                                    
    return cbStrLen ?                                 
        pStream->Write((void*) m_str, cbStrLen, &cb) :
        S_OK;                                         
}                                                     
 
HRESULT ReadFromStream(IStream* pStream) {                      
    ATLASSERT(pStream != NULL);                                 
    ATLASSERT(!*this); // should be empty                       
    ULONG cbStrLen = 0;                                         
    HRESULT hr = pStream->Read((void*) &cbStrLen,               
        sizeof(cbStrLen), NULL);                                
    if ((hr == S_OK) && (cbStrLen != 0)) {                      
        //subtract size for terminating NULL which we wrote out 
        //since SysAllocStringByteLen overallocates for the NULL
        m_str = SysAllocStringByteLen(NULL,                     
            cbStrLen-sizeof(OLECHAR));                          
        if (!*this) hr = E_OUTOFMEMORY;                         
        else hr = pStream->Read((void*) m_str, cbStrLen, NULL); 
        ...                                                     
    }                                                           
    if (hr == S_FALSE) hr = E_FAIL;                             
    return hr;                                                  
}                                                               


注意在Read前,应该保证obj为Empty

CComBSTR注意点

typedef /* [wire_marshal] */ OLECHAR __RPC_FAR *BSTR;两者有时可以混用

将BSTR数据传入LPOLESTR的输入函数中,会导致字串缩短

将BSTR传给[out]OLECHAR**函数,会导致内存泄漏

不要将OLESTR*传给[in]BSTR,因为SysStringLen无法工作正确

将BSTR传给CComBSTR构造函数应该注意

BSTR bstrInput =
  SysAllocStringLen (
    OLESTR ("This is part one\0and here's part two"),
    36) ;

CComBSTR str8 (bstrInput) ; // Wrong! Unexpected behavior here
                            // Note: str2 contains only
                            // "This is part one"

CComBSTR str9 (::SysStringLen (bstrInput),
    bstrInput); // Correct!
// str9 contains "This is part one\0and here's part two"


同理Assignment应该注意

// BSTR bstrInput contains
// "This is part one\0and here's part two"
CComBSTR str10;
str10 = bstrInput; // Wrong! Unexpected behavior here
                   // str10 now contains "This is part one"
str10.Empty();                // Insure object is initially empty
str10.AppendBSTR (bstrInput); // This works!

The CString Class

大部分和MFC中一样

Working with BSTRs and CString

BSTR AllocSysString() const {                                   
    BSTR bstrResult = StringTraits::AllocSysString( GetString(),
        GetLength() );                                          
    if( bstrResult == NULL ) {                                  
        ThrowMemoryException();                                 
    }                                                           
                                                         
    return( bstrResult );                                       
}                                                               
                                                                
BSTR SetSysString( BSTR* pbstr ) const {                        
    ATLASSERT( AtlIsValidAddress( pbstr, sizeof( BSTR ) ) );    
                                                                
    if( !StringTraits::ReAllocSysString( GetString(), pbstr,    
        GetLength() ) ) {                                       
        ThrowMemoryException();                                 
    }                                                           
                                                                
    ATLASSERT( *pbstr != NULL );                                
    return( *pbstr );                                           
}                                                               


注意2个函数都是const,对CString中的数据没有影响

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值