Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
10 KiB

  1. // MLStrBuf.h : Declaration and implementation of the IMLangStringBufW/A classes
  2. #ifndef __MLSTRBUF_H_
  3. #define __MLSTRBUF_H_
  4. #include <mlang.h>
  5. /////////////////////////////////////////////////////////////////////////////
  6. // CMLStrBufTempl
  7. template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
  8. class CMLStrBufTempl : public IMLSB, public MEM, public ACCESS
  9. {
  10. public:
  11. CMLStrBufTempl(CHTYPE* psz = NULL, long cch = 0, void* pv = NULL, long cb = 0) : ACCESS(psz, cch, pv, cb)
  12. #ifdef DEBUG
  13. {m_nLockCount = 0;}
  14. #else
  15. {}
  16. #endif
  17. ~CMLStrBufTempl(void) {ASSERT(!m_nLockCount);}
  18. // IUnknown
  19. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
  20. STDMETHOD_(ULONG, AddRef)(void) {return AddRefI();}
  21. STDMETHOD_(ULONG, Release)(void) {return ReleaseI();}
  22. // IMLangStringBufW/A
  23. STDMETHOD(GetStatus)(long* plFlags, long* pcchBuf);
  24. STDMETHOD(LockBuf)(long cchOffset, long cchMaxLock, CHTYPE** ppszBuf, long* pcchBuf);
  25. STDMETHOD(UnlockBuf)(const CHTYPE* pszBuf, long cchOffset, long cchWrite);
  26. STDMETHOD(Insert)(long cchOffset, long cchMaxInsert, long* pcchActual) {ASSERT(!m_nLockCount); return InsertI(cchOffset, cchMaxInsert, pcchActual);}
  27. STDMETHOD(Delete)(long cchOffset, long cchDelete) {ASSERT(!m_nLockCount); return DeleteI(cchOffset, cchDelete);}
  28. protected:
  29. #ifdef DEBUG
  30. int m_nLockCount;
  31. #endif
  32. };
  33. template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
  34. HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::QueryInterface(REFIID riid, void **ppvObj)
  35. {
  36. if (IsEqualIID(riid, IID_IUnknown) ||
  37. (sizeof(CHTYPE) == sizeof(CHAR) && IsEqualIID(riid, IID_IMLangStringBufA)) ||
  38. (sizeof(CHTYPE) == sizeof(WCHAR) && IsEqualIID(riid, IID_IMLangStringBufW)))
  39. {
  40. *ppvObj = this;
  41. AddRef();
  42. return S_OK;
  43. }
  44. else
  45. {
  46. *ppvObj = NULL;
  47. return E_NOINTERFACE;
  48. }
  49. }
  50. template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
  51. HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::GetStatus(long* plFlags, long* pcchBuf)
  52. {
  53. if (plFlags)
  54. *plFlags = GetFlags();
  55. if (pcchBuf)
  56. *pcchBuf = m_cchStr;
  57. return S_OK;
  58. }
  59. template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
  60. HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::LockBuf(long cchOffset, long cchMaxLock, CHTYPE** ppszBuf, long* pcchBuf)
  61. {
  62. ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
  63. ASSERT(cchMaxLock >= 1 && cchMaxLock <= m_cchStr - cchOffset);
  64. #ifdef DEBUG
  65. m_nLockCount++;
  66. #endif
  67. if (ppszBuf)
  68. *ppszBuf = m_pszBuf + cchOffset;
  69. if (pcchBuf)
  70. *pcchBuf = cchMaxLock;
  71. return S_OK;
  72. }
  73. template <class CHTYPE, class IMLSB, class MEM, class ACCESS>
  74. HRESULT CMLStrBufTempl<CHTYPE, IMLSB, MEM, ACCESS>::UnlockBuf(const CHTYPE* pszBuf, long cchOffset, long cchWrite)
  75. {
  76. ASSERT(m_nLockCount > 0);
  77. ASSERT(cchOffset >= 0 && pszBuf + cchOffset >= m_pszBuf && pszBuf + cchOffset < m_pszBuf + m_cchStr);
  78. ASSERT(cchWrite == 0);
  79. #ifdef DEBUG
  80. m_nLockCount--;
  81. #endif
  82. return S_OK;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CMLStrBufConst
  86. template <class CHTYPE>
  87. class CMLStrBufConst
  88. {
  89. protected:
  90. CMLStrBufConst(CHTYPE* psz, long cch, void*, long) : m_pszBuf(psz), m_cchStr(cch) {}
  91. long GetFlags(void) const {return MLSTR_READ;}
  92. HRESULT InsertI(long cchOffset, long cchMaxInsert, long* pcchActual) {ASSERT(FALSE); if (pcchActual) *pcchActual = 0; return E_FAIL;}
  93. HRESULT DeleteI(long cchOffset, long cchDelete) {ASSERT(FALSE); return E_FAIL;}
  94. CHTYPE* const m_pszBuf;
  95. const long m_cchStr;
  96. };
  97. /////////////////////////////////////////////////////////////////////////////
  98. // CMLStrBufVariable
  99. template <class CHTYPE>
  100. class CMLStrBufVariable
  101. {
  102. protected:
  103. 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;}
  104. ~CMLStrBufVariable(void) {if (m_pszBuf) MemFree(m_pszBuf);}
  105. long GetFlags(void) const {return MLSTR_READ | MLSTR_WRITE;}
  106. HRESULT InsertI(long cchOffset, long cchMaxInsert, long* pcchActual);
  107. HRESULT DeleteI(long cchOffset, long cchDelete);
  108. virtual LPVOID MemAlloc(ULONG) {return NULL;}
  109. virtual LPVOID MemRealloc(LPVOID, ULONG) {return NULL;}
  110. virtual void MemFree(LPVOID) {}
  111. virtual long RoundBufSize(long cchStr) {return (cchStr + 15) / 16;}
  112. CHTYPE* m_pszBuf;
  113. long m_cchBuf;
  114. long m_cchOffset;
  115. long m_cchStr;
  116. };
  117. template <class CHTYPE>
  118. HRESULT CMLStrBufVariable<CHTYPE>::InsertI(long cchOffset, long cchMaxInsert, long* pcchActual)
  119. {
  120. ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
  121. ASSERT(cchMaxInsert >= 0);
  122. long lShiftLeft = 0;
  123. long lShiftRight = 0;
  124. if (cchOffset < m_cchStr - cchOffset &&
  125. cchMaxInsert <= m_cchOffset)
  126. {
  127. lShiftLeft = cchMaxInsert;
  128. }
  129. else if (cchMaxInsert <= m_cchBuf - m_cchOffset - m_cchStr)
  130. {
  131. lShiftRight = cchMaxInsert;
  132. }
  133. else if (cchMaxInsert <= m_cchOffset)
  134. {
  135. lShiftLeft = cchMaxInsert;
  136. }
  137. else if (cchMaxInsert <= m_cchBuf - m_cchStr)
  138. {
  139. lShiftLeft = m_cchOffset;
  140. lShiftRight = cchMaxInsert - m_cchOffset;
  141. }
  142. else
  143. {
  144. void* pBuf;
  145. const long cchNew = RoundBufSize(m_cchOffset + m_cchStr + cchMaxInsert);
  146. if (!m_pszBuf)
  147. pBuf = MemAlloc(sizeof(*m_pszBuf) * cchNew);
  148. else
  149. pBuf = MemRealloc(m_pszBuf, sizeof(*m_pszBuf) * cchNew);
  150. if (pBuf)
  151. {
  152. m_pszBuf = (WCHAR*)pBuf;
  153. m_cchBuf = cchNew;
  154. lShiftRight = cchMaxInsert;
  155. }
  156. else
  157. {
  158. lShiftRight = m_cchBuf - m_cchOffset - m_cchStr;
  159. lShiftLeft = cchMaxInsert - lShiftRight;
  160. if (!pcchActual)
  161. return E_OUTOFMEMORY;
  162. }
  163. }
  164. if (lShiftLeft > 0)
  165. {
  166. if (cchOffset)
  167. ::memmove(m_pszBuf + m_cchOffset - lShiftLeft, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
  168. m_cchOffset -= lShiftLeft;
  169. m_cchStr += lShiftLeft;
  170. }
  171. if (lShiftRight > 0)
  172. {
  173. if (m_cchStr - cchOffset)
  174. ::memmove(m_pszBuf + m_cchOffset + lShiftRight, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * (m_cchStr - cchOffset));
  175. m_cchStr += lShiftRight;
  176. }
  177. if (pcchActual)
  178. *pcchActual = lShiftLeft + lShiftRight;
  179. return S_OK;
  180. }
  181. template <class CHTYPE>
  182. HRESULT CMLStrBufVariable<CHTYPE>::DeleteI(long cchOffset, long cchDelete)
  183. {
  184. ASSERT(cchOffset >= 0 && cchOffset < m_cchStr);
  185. ASSERT(cchDelete >= 0 && cchDelete < m_cchStr - cchOffset);
  186. long cchShrink = m_cchBuf - RoundBufSize(RoundBufSize(m_cchStr - cchDelete) + 1);
  187. cchShrink = max(cchShrink, 0);
  188. const long cchRight = m_cchStr - cchOffset - cchDelete;
  189. if (cchOffset < cchRight && m_cchBuf - m_cchOffset - m_cchStr >= cchShrink)
  190. {
  191. if (cchOffset)
  192. ::memmove(m_pszBuf + m_cchOffset + cchDelete, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
  193. m_cchOffset += cchDelete;
  194. m_cchStr -= cchDelete;
  195. }
  196. else if (m_cchBuf - m_cchOffset - m_cchStr + cchDelete >= cchShrink)
  197. {
  198. if (cchRight)
  199. ::memmove(m_pszBuf + m_cchOffset + cchOffset, m_pszBuf + m_cchOffset + cchDelete, sizeof(*m_pszBuf) * cchRight);
  200. m_cchStr -= cchDelete;
  201. }
  202. else
  203. {
  204. if (cchOffset)
  205. ::memmove(m_pszBuf, m_pszBuf + m_cchOffset, sizeof(*m_pszBuf) * cchOffset);
  206. if (cchRight)
  207. ::memmove(m_pszBuf + cchOffset, m_pszBuf + m_cchOffset + cchDelete, sizeof(*m_pszBuf) * cchRight);
  208. m_cchOffset = 0;
  209. m_cchStr -= cchDelete;
  210. }
  211. if (cchShrink)
  212. {
  213. void* pBuf = MemRealloc(m_pszBuf, sizeof(*m_pszBuf) * (m_cchBuf - cchShrink));
  214. if (pBuf)
  215. {
  216. m_pszBuf = (WCHAR*)pBuf;
  217. m_cchBuf -= cchShrink;
  218. }
  219. else
  220. {
  221. return E_OUTOFMEMORY;
  222. }
  223. }
  224. return S_OK;
  225. }
  226. /////////////////////////////////////////////////////////////////////////////
  227. // CMLStrBufStack
  228. class CMLStrBufStack
  229. {
  230. protected:
  231. #ifdef DEBUG
  232. inline CMLStrBufStack(void) {m_cRef = 0;}
  233. #else
  234. inline CMLStrBufStack(void) {}
  235. #endif
  236. inline ~CMLStrBufStack(void) {ASSERT(!m_cRef);}
  237. ULONG AddRefI(void)
  238. {
  239. #ifdef DEBUG
  240. m_cRef++;
  241. return m_cRef;
  242. #else
  243. ASSERT(FALSE);
  244. return 0;
  245. #endif
  246. }
  247. ULONG ReleaseI(void)
  248. {
  249. #ifdef DEBUG
  250. m_cRef--;
  251. ASSERT(m_cRef >= 0);
  252. return m_cRef;
  253. #else
  254. ASSERT(FALSE);
  255. return 0;
  256. #endif
  257. }
  258. #ifdef DEBUG
  259. int m_cRef;
  260. #endif
  261. };
  262. /////////////////////////////////////////////////////////////////////////////
  263. // CMLStrBufHeap
  264. class CMLStrBufHeap
  265. {
  266. protected:
  267. inline CMLStrBufHeap(void) {m_cRef = 0;}
  268. inline ~CMLStrBufHeap(void) {ASSERT(!m_cRef);}
  269. ULONG AddRefI(void) {m_cRef++; return m_cRef;}
  270. ULONG ReleaseI(void) {m_cRef--; const int cRef = m_cRef; if (!cRef) delete this; return cRef;}
  271. int m_cRef;
  272. };
  273. typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufStack, CMLStrBufConst<WCHAR> > CMLStrBufConstStackW;
  274. typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufStack, CMLStrBufConst<CHAR> > CMLStrBufConstStackA;
  275. typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufStack, CMLStrBufVariable<WCHAR> > CMLStrBufStackW;
  276. typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufStack, CMLStrBufVariable<CHAR> > CMLStrBufStackA;
  277. typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufHeap, CMLStrBufConst<WCHAR> > CMLStrBufConstW;
  278. typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufHeap, CMLStrBufConst<CHAR> > CMLStrBufConstA;
  279. typedef CMLStrBufTempl<WCHAR, IMLangStringBufW, CMLStrBufHeap, CMLStrBufVariable<WCHAR> > CMLStrBufW;
  280. typedef CMLStrBufTempl<CHAR, IMLangStringBufA, CMLStrBufHeap, CMLStrBufVariable<CHAR> > CMLStrBufA;
  281. #ifdef UNICODE
  282. typedef CMLStrBufConstStackW CMLStrBufConstStackT;
  283. typedef CMLStrBufStackW CMLStrBufStackT;
  284. typedef CMLStrBufConstW CMLStrBufConstT;
  285. typedef CMLStrBufW CMLStrBufT;
  286. #else
  287. typedef CMLStrBufConstStackA CMLStrBufConstStackT;
  288. typedef CMLStrBufStackA CMLStrBufStackT;
  289. typedef CMLStrBufConstA CMLStrBufConstT;
  290. typedef CMLStrBufA CMLStrBufT;
  291. #endif
  292. #endif //__MLSTRBUF_H_