|
|
// AttrStr.cpp : Implementation of CMLStrAttrStrCommonAttrStrCommon
#include "private.h"
#ifdef NEWMLSTR
#include "attrstr.h"
#include "mlsbwalk.h"
/////////////////////////////////////////////////////////////////////////////
// CMLStrAttrStrCommon
CMLStrAttrStrCommon::CMLStrAttrStrCommon(void) : m_pMLStrBufW(NULL), m_pMLStrBufA(NULL), m_lBufFlags(0), m_cchBuf(0), m_locale(0), m_LockInfo(this) { m_dwThreadID = ::GetCurrentThreadId(); }
CMLStrAttrStrCommon::~CMLStrAttrStrCommon(void) { if (m_pMLStrBufW) m_pMLStrBufW->Release(); if (m_pMLStrBufA) m_pMLStrBufA->Release(); }
HRESULT CMLStrAttrStrCommon::SetStrBufCommon(void* pMLStrX, long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufW* pSrcBufW, IMLangStringBufA* pSrcBufA, long* pcchActual, long* plActualLen) { ASSERT_THIS; ASSERT_READ_PTR_OR_NULL(pSrcBufW); ASSERT_READ_PTR_OR_NULL(pSrcBufA); ASSERT(!pSrcBufW || !pSrcBufA); // Either one or both should be NULL
ASSERT_WRITE_PTR_OR_NULL(pcchActual); ASSERT_WRITE_PTR_OR_NULL(plActualLen);
HRESULT hr = CheckThread(); CLock Lock(TRUE, this, hr); long lBufFlags = 0; // '= 0' for in case of both of pSrcBufW and pSrcBufA are NULL
long cchBuf = 0; long cchDestPos; long cchDestLen; long lActualLen = 0;
if (SUCCEEDED(hr) && (!pSrcBufW || SUCCEEDED(hr = pSrcBufW->GetStatus(&lBufFlags, &cchBuf))) && (!pSrcBufA || SUCCEEDED(hr = pSrcBufA->GetStatus(&lBufFlags, &cchBuf))) && SUCCEEDED(hr = RegularizePosLen(&lDestPos, &lDestLen)) && SUCCEEDED(hr = GetCCh(0, lDestPos, &cchDestPos)) && SUCCEEDED(hr = GetCCh(cchDestPos, lDestLen, &cchDestLen))) { if (!cchDestPos && cchDestLen == GetBufCCh()) // Replacing entire string
{ IMLangStringBufW* const pOldBufW = GetMLStrBufW(); IMLangStringBufA* const pOldBufA = GetMLStrBufA();
if (pOldBufW) pOldBufW->Release(); else if (pOldBufA) pOldBufA->Release();
if (pSrcBufW) pSrcBufW->AddRef(); else if (pSrcBufA) pSrcBufA->AddRef();
SetMLStrBufW(pSrcBufW); SetMLStrBufA(pSrcBufA); SetCodePage(uCodePage); SetBufFlags(lBufFlags); SetBufCCh(cchBuf);
if (plActualLen) hr = GetLen(0, GetBufCCh(), &lActualLen); } else { if (pSrcBufW) { CMLStrBufWalkW BufWalk(pSrcBufW, 0, cchBuf, (pcchActual || plActualLen));
while (BufWalk.Lock(hr)) { long cchSet; long lSetLen;
hr = ((IMLangStringWStr*)pMLStrX)->SetWStr(lDestPos, lDestLen, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL); lActualLen += lSetLen; BufWalk.Unlock(hr, cchSet); }
cchBuf = BufWalk.GetDoneCCh();
pSrcBufW->Release(); } else if (pSrcBufA && pMLStrX) { CMLStrBufWalkA BufWalk(pSrcBufA, 0, cchBuf, (pcchActual || plActualLen));
while (BufWalk.Lock(hr)) { long cchSet; long lSetLen;
hr = ((IMLangStringAStr*)pMLStrX)->SetAStr(lDestPos, lDestLen, uCodePage, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL); lActualLen += lSetLen; BufWalk.Unlock(hr, cchSet); }
cchBuf = BufWalk.GetDoneCCh();
pSrcBufA->Release(); } else { hr = GetMLStrAttr()->SetMLStr(lDestPos, lDestLen, NULL, 0, 0); } } }
if (SUCCEEDED(hr)) { if (pcchActual) *pcchActual = cchBuf; if (plActualLen) *plActualLen = lActualLen; } else { if (pcchActual) *pcchActual = 0; if (plActualLen) *plActualLen = 0; }
return hr; }
HRESULT CMLStrAttrStrCommon::UnlockWStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { HRESULT hr; IMLangStringBufW* const pMLStrBufW = GetMLStrBufW(); const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
if (SUCCEEDED(hr = pMLStrBufW->UnlockBuf((WCHAR*)pszSrc, 0, cchSrc)) && (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)) { if (cchSrc < cchLockLen) { if (SUCCEEDED(hr = pMLStrBufW->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc))) SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc)); }
if (SUCCEEDED(hr) && plActualLen) hr = CalcLenW((WCHAR*)pszSrc, cchSrc, plActualLen);
if (pcchActual) *pcchActual = cchSrc; }
return hr; }
HRESULT CMLStrAttrStrCommon::UnlockWStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { HRESULT hr = S_OK;
if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE) { CComQIPtr<IMLStrAttrWStr, &IID_IMLStrAttrWStr> pAttrWStr(GetMLStrAttr()); ASSERT(pAttrWStr); hr = pAttrWStr->SetWStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), (WCHAR*)pszSrc, cchSrc, pcchActual, plActualLen); }
ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
return hr; }
HRESULT CMLStrAttrStrCommon::UnlockAStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { HRESULT hr; IMLangStringBufA* const pMLStrBufA = GetMLStrBufA(); const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
if (SUCCEEDED(hr = pMLStrBufA->UnlockBuf((CHAR*)pszSrc, 0, cchSrc)) && (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)) { if (cchSrc < cchLockLen) { if (SUCCEEDED(hr = pMLStrBufA->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc))) SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc)); }
if (SUCCEEDED(hr) && plActualLen) hr = CalcLenA(GetCodePage(), (CHAR*)pszSrc, cchSrc, plActualLen);
if (pcchActual) *pcchActual = cchSrc; }
return hr; }
HRESULT CMLStrAttrStrCommon::UnlockAStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { HRESULT hr = S_OK;
if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE) { CComQIPtr<IMLStrAttrAStr, &IID_IMLStrAttrAStr> pAttrAStr(GetMLStrAttr()); ASSERT(pAttrAStr); hr = pAttrAStr->SetAStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), GetLockInfo()->GetCodePage(pKey), (CHAR*)pszSrc, cchSrc, pcchActual, plActualLen); }
ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
return hr; }
HRESULT CMLStrAttrStrCommon::UnlockStrCommon(const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen) { HRESULT hr = CheckThread(); void* pLockKey; long lSrcLen;
if (SUCCEEDED(hr)) hr = GetLockInfo()->Find(pszSrc, cchSrc, &pLockKey);
if (SUCCEEDED(hr)) hr = GetLockInfo()->Unlock(pLockKey, pszSrc, cchSrc, (pcchActual) ? &cchSrc : NULL, (plActualLen) ? &lSrcLen : NULL);
if (SUCCEEDED(hr)) { if (pcchActual) *pcchActual = cchSrc; if (plActualLen) *plActualLen = lSrcLen; } else { if (pcchActual) *pcchActual = 0; if (plActualLen) *plActualLen = 0; }
return hr; }
HRESULT CMLStrAttrStrCommon::PrepareMLStrBuf(void) { if (GetMLStrBufW() || GetMLStrBufA()) return S_OK;
IMLangStringBufW* pBuf = new CMLStrAttrStrCommon::CMLStrBufStandardW; if (pBuf) { SetMLStrBufW(pBuf); return S_OK; } else { return E_OUTOFMEMORY; } }
HRESULT CMLStrAttrStrCommon::RegularizePosLen(long* plPos, long* plLen) { HRESULT hr; long lStrLen;
if (SUCCEEDED(hr = GetLen(0, GetBufCCh(), &lStrLen))) hr = ::RegularizePosLen(lStrLen, plPos, plLen);
return hr; }
HRESULT CMLStrAttrStrCommon::GetCCh(long cchOffset, long lLen, long* pcchLen) { if (GetMLStrBufW()) { if (pcchLen) *pcchLen = lLen; // The number of characters is equal to the length
return S_OK; } else if (GetMLStrBufA()) { HRESULT hr = S_OK; CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, GetBufCCh() - cchOffset);
while (lLen > 0 && BufWalk.Lock(hr)) { for (LPCSTR pszTemp = BufWalk.GetStr(); lLen > 0 && *pszTemp; lLen--) pszTemp = ::CharNextExA((WORD)GetCodePage(), pszTemp, 0);
if (!*pszTemp) lLen = 0; // String terminated
BufWalk.Unlock(hr); }
if (pcchLen) { if (SUCCEEDED(hr)) *pcchLen = BufWalk.GetDoneCCh(); else *pcchLen = 0; }
return hr; } else { if (pcchLen) *pcchLen = 0; // No string
return S_OK; } }
HRESULT CMLStrAttrStrCommon::GetLen(long cchOffset, long cchLen, long* plLen) { if (GetMLStrBufW()) { if (plLen) *plLen = cchLen; // The length is equal to the number of characters
return S_OK; } else if (GetMLStrBufA()) { HRESULT hr = S_OK; long lDoneLen = 0; CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, cchLen);
while (BufWalk.Lock(hr)) { long lTempLen;
hr = CalcLenA(GetCodePage(), BufWalk.GetStr(), BufWalk.GetCCh(), &lTempLen); if (hr == S_FALSE) cchLen = 0; // String terminated
lDoneLen += lTempLen;
BufWalk.Unlock(hr); }
if (plLen) { if (SUCCEEDED(hr)) *plLen = lDoneLen; else *plLen = 0; }
return hr; } else { if (plLen) *plLen = 0; // No string
return S_OK; } }
HRESULT CMLStrAttrStrCommon::CalcLenA(UINT uCodePage, const CHAR* psz, long cchLen, long* plLen) { long lLen = 0; const CHAR* const pszEnd = psz + cchLen;
for (; psz < pszEnd && *psz; lLen++) { const CHAR* const pszNew = ::CharNextExA((WORD)uCodePage, psz, 0);
if (pszNew > pszEnd) // Overrun out of buffer
break;
psz = pszNew; }
if (plLen) *plLen = lLen;
if (*psz) return S_OK; else return S_FALSE; }
HRESULT CMLStrAttrStrCommon::CalcCChA(UINT uCodePage, const CHAR* psz, long lLen, long* pcchLen) { const CHAR* const pszStart = psz;
for (; lLen > 0 && *psz; lLen--) psz = ::CharNextExA((WORD)uCodePage, psz, 0);
if (pcchLen) *pcchLen = psz - pszStart;
if (*psz) return S_OK; else return S_FALSE; }
HRESULT CMLStrAttrStrCommon::ConvAStrToWStr(UINT uCodePage, const CHAR* pszSrc, long cchSrc, WCHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen) { HRESULT hr = S_OK; long lWrittenLen; long cchWrittenA;
long cchWrittenW = ::MultiByteToWideChar(uCodePage, 0, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0); if (!cchWrittenW) hr = E_FAIL; // NLS failed
if ((pcchActualA || plActualLen) && SUCCEEDED(hr)) hr = CalcLenW(pszDest, cchWrittenW, &lWrittenLen); // BOGUS: pszDest may be NULL
if (pcchActualA && SUCCEEDED(hr)) hr = CalcCChA(uCodePage, pszSrc, lWrittenLen, &cchWrittenA);
if (SUCCEEDED(hr)) { if (pcchActualA) *pcchActualA = cchWrittenA; if (pcchActualW) *pcchActualW = cchWrittenW; if (plActualLen) *plActualLen = lWrittenLen; } else { if (pcchActualA) *pcchActualA = 0; if (pcchActualW) *pcchActualW = 0; if (plActualLen) *plActualLen = 0; }
return hr; }
HRESULT CMLStrAttrStrCommon::ConvWStrToAStr(BOOL fCanStopAtMiddle, UINT uCodePage, const WCHAR* pszSrc, long cchSrc, CHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen) { HRESULT hr = S_OK; long lWrittenLen; long cchWrittenW;
long cchWrittenA = ::WideCharToMultiByte(uCodePage, (fCanStopAtMiddle) ? 0 : WC_DEFAULTCHAR, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0, NULL, NULL); if (!cchWrittenA) hr = E_FAIL; // NLS failed
if ((pcchActualW || plActualLen) && SUCCEEDED(hr)) { if (pszDest) hr = CalcLenA(uCodePage, pszDest, cchWrittenA, &lWrittenLen); else hr = E_NOTIMPL; // Can't retrieve pcchActualW and plActualLen
}
if (pcchActualW && SUCCEEDED(hr)) hr = CalcCChW(pszSrc, lWrittenLen, &cchWrittenW);
if (SUCCEEDED(hr)) { if (pcchActualA) *pcchActualA = cchWrittenA; if (pcchActualW) *pcchActualW = cchWrittenW; if (plActualLen) *plActualLen = lWrittenLen; } else { if (pcchActualA) *pcchActualA = 0; if (pcchActualW) *pcchActualW = 0; if (plActualLen) *plActualLen = 0; }
return hr; }
/////////////////////////////////////////////////////////////////////////////
// CMLStrAttrStrCommon::CLockInfo
HRESULT CMLStrAttrStrCommon::CLockInfo::UnlockAll(void) { if (m_pLockArray) { for (int n = 0; n < MAX_LOCK_COUNT; n++) { if (m_pLockArray[n].m_psz) Unlock(&m_pLockArray[n], m_pLockArray[n].m_psz, m_pLockArray[n].m_cchLen, NULL, NULL); } }
return S_OK; }
HRESULT CMLStrAttrStrCommon::CLockInfo::Lock(PFNUNLOCKPROC pfnUnlockProc, long lFlags, UINT uCodePage, void* psz, long lPos, long lLen, long cchPos, long cchLen) { HRESULT hr = S_OK; int nIndex;
if (!m_pLockArray) { m_pLockArray = new CLockInfoEntry[MAX_LOCK_COUNT];
if (m_pLockArray) { for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++) m_pLockArray[nIndex].m_psz = NULL; } else { hr = E_OUTOFMEMORY; } }
if (SUCCEEDED(hr)) { for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++) { if (!m_pLockArray[nIndex].m_psz) break; } if (nIndex >= MAX_LOCK_COUNT) hr = MLSTR_E_TOOMANYNESTOFLOCK; }
if (SUCCEEDED(hr)) { m_pLockArray[nIndex].m_psz = psz; m_pLockArray[nIndex].m_pfnUnlockProc = pfnUnlockProc; m_pLockArray[nIndex].m_lFlags = lFlags; m_pLockArray[nIndex].m_uCodePage = uCodePage; m_pLockArray[nIndex].m_lPos = lPos; m_pLockArray[nIndex].m_lLen = lLen; m_pLockArray[nIndex].m_cchPos = cchPos; m_pLockArray[nIndex].m_cchLen = cchLen; }
return hr; }
HRESULT CMLStrAttrStrCommon::CLockInfo::Find(const void* psz, long, void** ppKey) { HRESULT hr = S_OK; int nIndex;
if (m_pLockArray) { for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++) { if (psz == m_pLockArray[nIndex].m_psz) break; } } if (!m_pLockArray || nIndex >= MAX_LOCK_COUNT) hr = E_INVALIDARG;
if (ppKey) { if (SUCCEEDED(hr)) *ppKey = &m_pLockArray[nIndex]; else *ppKey = NULL; }
return hr; }
HRESULT CMLStrAttrStrCommon::CLockInfo::Unlock(void* pKey, const void* psz, long cch, long* pcchActual, long* plActualLen) { CLockInfoEntry* const pEntry = (CLockInfoEntry*)pKey; HRESULT hr;
if (!(pEntry->m_lFlags & MLSTR_WRITE)) { cch = 0; if (plActualLen) *plActualLen = 0; }
hr = (m_pCommon->*(pEntry->m_pfnUnlockProc))(pKey, psz, cch, pcchActual, plActualLen);
if (SUCCEEDED(hr)) hr = EndLock(pEntry->m_lFlags & MLSTR_WRITE);
pEntry->m_psz = NULL; // Remove from lock array anyway
if (FAILED(hr)) { if (pcchActual) *pcchActual = 0; if (plActualLen) *plActualLen = 0; }
return hr; }
/////////////////////////////////////////////////////////////////////////////
// CMLStrAttrStrCommon::CMLStrBufStandardW
long CMLStrAttrStrCommon::CMLStrBufStandardW::RoundBufSize(long cchStr) { for (int n = 8; n < 12; n++) { if (cchStr < (1L << n)) break; } const long cchTick = (1L << (n - 4)); return (cchStr + cchTick - 1) / cchTick * cchTick; }
#endif // NEWMLSTR
|