windows-nt/Source/XPSP1/NT/shell/ext/mlang/mlstrbuf.h
2020-09-26 16:20:57 +08:00

344 lines
10 KiB
C++

// MLStrBuf.h : Declaration and implementation of the IMLangStringBufW/A classes
#ifndef __MLSTRBUF_H_
#define __MLSTRBUF_H_
#include <mlang.h>
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufTempl
template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
class CMLStrBufTempl : public IMLSB, public MEM, public ACCESS
{
public:
CMLStrBufTempl(CHTYPE* psz = NULL, long cch = 0, void* pv = NULL, long cb = 0) : ACCESS(psz, cch, pv, cb)
#ifdef DEBUG
{m_nLockCount = 0;}
#else
{}
#endif
~CMLStrBufTempl(void) {ASSERT(!m_nLockCount);}
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
STDMETHOD_(ULONG, AddRef)(void) {return AddRefI();}
STDMETHOD_(ULONG, Release)(void) {return ReleaseI();}
// IMLangStringBufW/A
STDMETHOD(GetStatus)(long* plFlags, long* pcchBuf);
STDMETHOD(LockBuf)(long cchOffset, long cchMaxLock, CHTYPE** ppszBuf, long* pcchBuf);
STDMETHOD(UnlockBuf)(const CHTYPE* pszBuf, long cchOffset, long cchWrite);
STDMETHOD(Insert)(long cchOffset, long cchMaxInsert, long* pcchActual) {ASSERT(!m_nLockCount); return InsertI(cchOffset, cchMaxInsert, pcchActual);}
STDMETHOD(Delete)(long cchOffset, long cchDelete) {ASSERT(!m_nLockCount); return DeleteI(cchOffset, cchDelete);}
protected:
#ifdef DEBUG
int m_nLockCount;
#endif
};
template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) ||
(sizeof(CHTYPE) == sizeof(CHAR) && IsEqualIID(riid, IID_IMLangStringBufA)) ||
(sizeof(CHTYPE) == sizeof(WCHAR) && IsEqualIID(riid, IID_IMLangStringBufW)))
{
*ppvObj = this;
AddRef();
return S_OK;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
}
template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::GetStatus(long* plFlags, long* pcchBuf)
{
if (plFlags)
*plFlags = GetFlags();
if (pcchBuf)
*pcchBuf = m_cchStr;
return S_OK;
}
template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::LockBuf(long cchOffset, long cchMaxLock, CHTYPE** ppszBuf, long* pcchBuf)
{
ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
ASSERT(cchMaxLock >= 1 && cchMaxLock <= m_cchStr - cchOffset);
#ifdef DEBUG
m_nLockCount++;
#endif
if (ppszBuf)
*ppszBuf = m_pszBuf + cchOffset;
if (pcchBuf)
*pcchBuf = cchMaxLock;
return S_OK;
}
template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::UnlockBuf(const CHTYPE* pszBuf, long cchOffset, long cchWrite)
{
ASSERT(m_nLockCount > 0);
ASSERT(cchOffset >= 0 && pszBuf + cchOffset >= m_pszBuf && pszBuf + cchOffset < m_pszBuf + m_cchStr);
ASSERT(cchWrite == 0);
#ifdef DEBUG
m_nLockCount--;
#endif
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufConst
template <class CHTYPE>
class CMLStrBufConst
{
protected:
CMLStrBufConst(CHTYPE* psz, long cch, void*, long) : m_pszBuf(psz), m_cchStr(cch) {}
long GetFlags(void) const {return MLSTR_READ;}
HRESULT InsertI(long cchOffset, long cchMaxInsert, long* pcchActual) {ASSERT(FALSE); if (pcchActual) *pcchActual = 0; return E_FAIL;}
HRESULT DeleteI(long cchOffset, long cchDelete) {ASSERT(FALSE); return E_FAIL;}
CHTYPE* const m_pszBuf;
const long m_cchStr;
};
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufVariable
template <class CHTYPE>
class CMLStrBufVariable
{
protected:
CMLStrBufVariable(CHTYPE* psz, long cch, void* pv, long cb) {m_pszBuf = (CHTYPE*)pv; m_cchBuf = cb / sizeof(CHTYPE); m_cchOffset = psz - m_pszBuf; m_cchStr = cch;}
~CMLStrBufVariable(void) {if (m_pszBuf) MemFree(m_pszBuf);}
long GetFlags(void) const {return MLSTR_READ | MLSTR_WRITE;}
HRESULT InsertI(long cchOffset, long cchMaxInsert, long* pcchActual);
HRESULT DeleteI(long cchOffset, long cchDelete);
virtual LPVOID MemAlloc(ULONG) {return NULL;}
virtual LPVOID MemRealloc(LPVOID, ULONG) {return NULL;}
virtual void MemFree(LPVOID) {}
virtual long RoundBufSize(long cchStr) {return (cchStr + 15) / 16;}
CHTYPE* m_pszBuf;
long m_cchBuf;
long m_cchOffset;
long m_cchStr;
};
template <class CHTYPE>
HRESULT CMLStrBufVariable<CHTYPE>::InsertI(long cchOffset, long cchMaxInsert, long* pcchActual)
{
ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
ASSERT(cchMaxInsert >= 0);
long lShiftLeft = 0;
long lShiftRight = 0;
if (cchOffset < m_cchStr - cchOffset &&
cchMaxInsert <= m_cchOffset)
{
lShiftLeft = cchMaxInsert;
}
else if (cchMaxInsert <= m_cchBuf - m_cchOffset - m_cchStr)
{
lShiftRight = cchMaxInsert;
}
else if (cchMaxInsert <= m_cchOffset)
{
lShiftLeft = cchMaxInsert;
}
else if (cchMaxInsert <= m_cchBuf - m_cchStr)
{
lShiftLeft = m_cchOffset;
lShiftRight = cchMaxInsert - m_cchOffset;
}
else
{
void* pBuf;
const long cchNew = RoundBufSize(m_cchOffset + m_cchStr + cchMaxInsert);
if (!m_pszBuf)
pBuf = MemAlloc(sizeof(*m_pszBuf) * cchNew);
else
pBuf = MemRealloc(m_pszBuf, sizeof(*m_pszBuf) * cchNew);
if (pBuf)
{
m_pszBuf = (WCHAR*)pBuf;
m_cchBuf = cchNew;
lShiftRight = cchMaxInsert;
}
else
{
lShiftRight = m_cchBuf - m_cchOffset - m_cchStr;
lShiftLeft = cchMaxInsert - lShiftRight;
if (!pcchActual)
return E_OUTOFMEMORY;
}
}
if (lShiftLeft > 0)
{
if (cchOffset)
::memmove(m_pszBuf + m_cchOffset - lShiftLeft, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
m_cchOffset -= lShiftLeft;
m_cchStr += lShiftLeft;
}
if (lShiftRight > 0)
{
if (m_cchStr - cchOffset)
::memmove(m_pszBuf + m_cchOffset + lShiftRight, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * (m_cchStr - cchOffset));
m_cchStr += lShiftRight;
}
if (pcchActual)
*pcchActual = lShiftLeft + lShiftRight;
return S_OK;
}
template <class CHTYPE>
HRESULT CMLStrBufVariable<CHTYPE>::DeleteI(long cchOffset, long cchDelete)
{
ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
ASSERT(cchDelete >= 0 && cchDelete < m_cchStr - cchOffset);
long cchShrink = m_cchBuf - RoundBufSize(RoundBufSize(m_cchStr - cchDelete) + 1);
cchShrink = max(cchShrink, 0);
const long cchRight = m_cchStr - cchOffset - cchDelete;
if (cchOffset < cchRight && m_cchBuf - m_cchOffset - m_cchStr >= cchShrink)
{
if (cchOffset)
::memmove(m_pszBuf + m_cchOffset + cchDelete, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
m_cchOffset += cchDelete;
m_cchStr -= cchDelete;
}
else if (m_cchBuf - m_cchOffset - m_cchStr + cchDelete >= cchShrink)
{
if (cchRight)
::memmove(m_pszBuf + m_cchOffset + cchOffset, m_pszBuf + m_cchOffset + cchDelete, sizeof(*m_pszBuf) * cchRight);
m_cchStr -= cchDelete;
}
else
{
if (cchOffset)
::memmove(m_pszBuf, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
if (cchRight)
::memmove(m_pszBuf + cchOffset, m_pszBuf + m_cchOffset + cchDelete, sizeof(*m_pszBuf) * cchRight);
m_cchOffset = 0;
m_cchStr -= cchDelete;
}
if (cchShrink)
{
void* pBuf = MemRealloc(m_pszBuf, sizeof(*m_pszBuf) * (m_cchBuf - cchShrink));
if (pBuf)
{
m_pszBuf = (WCHAR*)pBuf;
m_cchBuf -= cchShrink;
}
else
{
return E_OUTOFMEMORY;
}
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufStack
class CMLStrBufStack
{
protected:
#ifdef DEBUG
inline CMLStrBufStack(void) {m_cRef = 0;}
#else
inline CMLStrBufStack(void) {}
#endif
inline ~CMLStrBufStack(void) {ASSERT(!m_cRef);}
ULONG AddRefI(void)
{
#ifdef DEBUG
m_cRef++;
return m_cRef;
#else
ASSERT(FALSE);
return 0;
#endif
}
ULONG ReleaseI(void)
{
#ifdef DEBUG
m_cRef--;
ASSERT(m_cRef >= 0);
return m_cRef;
#else
ASSERT(FALSE);
return 0;
#endif
}
#ifdef DEBUG
int m_cRef;
#endif
};
/////////////////////////////////////////////////////////////////////////////
// CMLStrBufHeap
class CMLStrBufHeap
{
protected:
inline CMLStrBufHeap(void) {m_cRef = 0;}
inline ~CMLStrBufHeap(void) {ASSERT(!m_cRef);}
ULONG AddRefI(void) {m_cRef++; return m_cRef;}
ULONG ReleaseI(void) {m_cRef--; const int cRef = m_cRef; if (!cRef) delete this; return cRef;}
int m_cRef;
};
typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufStack, CMLStrBufConst<WCHAR> > CMLStrBufConstStackW;
typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufStack, CMLStrBufConst<CHAR> > CMLStrBufConstStackA;
typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufStack, CMLStrBufVariable<WCHAR> > CMLStrBufStackW;
typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufStack, CMLStrBufVariable<CHAR> > CMLStrBufStackA;
typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufHeap, CMLStrBufConst<WCHAR> > CMLStrBufConstW;
typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufHeap, CMLStrBufConst<CHAR> > CMLStrBufConstA;
typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufHeap, CMLStrBufVariable<WCHAR> > CMLStrBufW;
typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufHeap, CMLStrBufVariable<CHAR> > CMLStrBufA;
#ifdef UNICODE
typedef CMLStrBufConstStackW CMLStrBufConstStackT;
typedef CMLStrBufStackW CMLStrBufStackT;
typedef CMLStrBufConstW CMLStrBufConstT;
typedef CMLStrBufW CMLStrBufT;
#else
typedef CMLStrBufConstStackA CMLStrBufConstStackT;
typedef CMLStrBufStackA CMLStrBufStackT;
typedef CMLStrBufConstA CMLStrBufConstT;
typedef CMLStrBufA CMLStrBufT;
#endif
#endif //__MLSTRBUF_H_