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.

272 lines
7.7 KiB

  1. #if !defined(_FUSION_INC_FUSIONBYTEBUFFER_H_INCLUDED_)
  2. #define _FUSION_INC_FUSIONBYTEBUFFER_H_INCLUDED_
  3. #pragma once
  4. typedef const BYTE *LPCBYTE;
  5. typedef const BYTE *PCBYTE;
  6. class CGenericByteBufferDefaultAllocator
  7. {
  8. public:
  9. static inline BYTE *Allocate(SIZE_T cb) { return reinterpret_cast<LPBYTE>(::LocalAlloc(LMEM_FIXED, cb)); }
  10. static inline VOID Deallocate(LPBYTE prgb) { ::LocalFree(prgb); }
  11. };
  12. enum ByteComparisonResult
  13. {
  14. BCR_LESS_THAN,
  15. BCR_EQUAL_TO,
  16. BCR_GREATER_THAN
  17. };
  18. template<SIZE_T nInlineBytes = MAX_PATH, class TAllocator = CGenericByteBufferDefaultAllocator> class CGenericByteBuffer
  19. {
  20. public:
  21. CGenericByteBuffer() : m_prgbBuffer(m_rgbInlineBuffer), m_cbBuffer(nInlineBytes), m_cb(0) { }
  22. //
  23. // Note that somewhat counter-intuitively, there is neither an assignment operator,
  24. // copy constructor or constructor taking a TConstantString. This is necessary
  25. // because such a constructor would need to perform a dynamic allocation
  26. // if the path passed in were longer than nInlineBytes which could fail and
  27. // since we do not throw exceptions, constructors may not fail. Instead the caller
  28. // must just perform the default construction and then use the Assign() member
  29. // function, remembering of course to check its return status.
  30. //
  31. ~CGenericByteBuffer()
  32. {
  33. if (m_prgbBuffer != m_rgbInlineBuffer)
  34. {
  35. TAllocator::Deallocate(m_prgbBuffer);
  36. m_prgbBuffer = NULL;
  37. }
  38. }
  39. HRESULT Assign(LPCBYTE prgb, SIZE_T cb)
  40. {
  41. HRESULT hr = NOERROR;
  42. // Only force the buffer to be dynamically grown if the new contents do not
  43. // fit in the old buffer.
  44. if (cb > m_cbBuffer)
  45. {
  46. // Resize the buffer, preserving the old contents in case the copy fails.
  47. hr = this->ResizeBuffer(cb, true);
  48. if (FAILED(hr))
  49. goto Exit;
  50. }
  51. // if we have a dynamically allocated buffer and the string fits in the
  52. // inline buffer, get rid of the dynamically allocated buffer.
  53. if ((m_prgbBuffer != m_rgbInlineBuffer) && (cb <= nInlineBytes))
  54. {
  55. memcpy(m_rgbInlineBuffer, prgb, cb);
  56. TAllocator::Deallocate(m_prgbBuffer);
  57. m_prgbBuffer = m_rgbInlineBuffer;
  58. m_cbBuffer = nInlineBytes;
  59. }
  60. else
  61. {
  62. memcpy(m_prgbBuffer, prgb, cb);
  63. }
  64. hr = NOERROR;
  65. Exit:
  66. return hr;
  67. }
  68. #if defined(_FUSION_INC_FUSIONBLOB_H_INCLUDED_)
  69. HRESULT Assign(const BLOB &rblob) { return this->Assign(rblob.m_pBlobData, rblob.m_cbData); }
  70. #endif
  71. HRESULT Append(LPCBYTE prgb, SIZE_T cb)
  72. {
  73. HRESULT hr = NOERROR;
  74. if ((cb + m_cb) > m_cbBuffer)
  75. {
  76. hr = this->ResizeBuffer(cb + m_cb, true);
  77. if (FAILED(hr))
  78. goto Exit;
  79. }
  80. memcpy(&m_prgbBuffer[m_cb], prgb, cb);
  81. m_cb += cb;
  82. hr = NOERROR;
  83. Exit:
  84. return hr;
  85. }
  86. #if defined(_FUSION_INC_FUSIONBLOB_H_INCLUDED_)
  87. HRESULT Append(const BLOB &rblob) { return this->Append(rblob.m_pBlobData, rblob.m_cbData); }
  88. #endif
  89. HRESULT LeftShift(ULONG cb)
  90. {
  91. HRESULT hr = NOERROR;
  92. if (m_cb < cb)
  93. {
  94. hr = E_INVALIDARG;
  95. goto Exit;
  96. }
  97. // Just do the simple memcpy. Perhaps we should see if can lose the
  98. // allocated buffer, but we might just need it again soon anyways.
  99. memcpy(&m_prgbBuffer[0], &m_prgbBuffer[cb], m_cb - cb);
  100. m_cb -= cb;
  101. hr = NOERROR;
  102. Exit:
  103. return hr;
  104. }
  105. HRESULT TakeValue(CGenericByteBuffer<nInlineBytes, TAllocator> &r)
  106. {
  107. if (r.m_prgbBuffer == r.m_rgbInlineBuffer)
  108. {
  109. // The source has an inline buffer; since we know we're the same type,
  110. // just copy the bits, free our dynamic buffer if appropriate and
  111. // go.
  112. memcpy(m_rgbInlineBuffer, r.m_rgbInlineBuffer, r.m_cb);
  113. m_cbBuffer = r.m_cbBuffer;
  114. m_cb = r.m_cb;
  115. if (m_prgbBuffer != m_rgbInlineBuffer)
  116. {
  117. TAllocator::Deallocate(m_prgbBuffer);
  118. m_prgbBuffer = m_rgbInlineBuffer;
  119. }
  120. }
  121. else
  122. {
  123. // If we have a dynamically allocated buffer, free it...
  124. if (m_prgbBuffer != m_rgbInlineBuffer)
  125. {
  126. TAllocator::Deallocate(m_prgbBuffer);
  127. m_prgbBuffer = NULL;
  128. }
  129. // avast ye mateys, we're taking control of yer buffers!
  130. m_prgbBuffer = r.m_prgbBuffer;
  131. m_cbBuffer = r.m_cbBuffer;
  132. m_cb = r.m_cb;
  133. // Point the other buffer back to its built-in storage...
  134. r.m_prgbBuffer = r.m_rgbInlineBuffer;
  135. r.m_cbBuffer = nInlineBytes;
  136. }
  137. return NOERROR;
  138. }
  139. operator LPCBYTE() const { return m_prgbBuffer; }
  140. VOID Clear(bool fFreeStorage = false)
  141. {
  142. if (fFreeStorage)
  143. {
  144. if (m_prgbBuffer != NULL)
  145. {
  146. if (m_prgbBuffer != m_rgbInlineBuffer)
  147. {
  148. TAllocator::Deallocate(m_prgbBuffer);
  149. m_prgbBuffer = m_rgbInlineBuffer;
  150. m_cbBuffer = nInlineBytes;
  151. }
  152. }
  153. }
  154. m_cb = 0;
  155. }
  156. HRESULT Compare(LPCBYTE prgbCandidate, SIZE_T cbCandidate, ByteComparisonResult &rbcrOut)
  157. {
  158. SIZE_T cbToCompare = (m_cb < cbCandidate) ? m_cb : cbCandidate;
  159. int iResult = memcmp(m_prgbBuffer, prgbCandidate, cbToCompare);
  160. if (iResult < 0)
  161. rbcrOut = BCS_LESS_THAN;
  162. else if (iResult > 0)
  163. rbcrOut = BCS_GREATER_THAN;
  164. else if (m_cb < cbCandidate)
  165. rbcrOut = BCS_LESS_THAN;
  166. else if (m_cb > cbCandidate)
  167. rbcrOut = BCS_GREATER_THAN;
  168. else
  169. rbcrOut = BCS_EQUAL_TO;
  170. return NOERROR;
  171. }
  172. SIZE_T GetBufferCb() const { return m_cbBuffer; }
  173. SIZE_T GetCurrentCb() const { return m_cb; }
  174. LPBYTE GetBufferPtr() { return m_prgbBuffer; }
  175. HRESULT ResizeBuffer(SIZE_T cb, bool fPreserveContents = false)
  176. {
  177. HRESULT hr = NOERROR;
  178. if (cb > m_cbBuffer)
  179. {
  180. LPBYTE prgbBufferNew = TAllocator::Allocate(cb);
  181. if (prgbBufferNew == NULL)
  182. {
  183. hr = E_OUTOFMEMORY;
  184. goto Exit;
  185. }
  186. if (fPreserveContents)
  187. memcpy(prgbBufferNew, m_prgbBuffer, m_cb);
  188. else
  189. m_cb = 0;
  190. if (m_prgbBuffer != m_rgbInlineBuffer)
  191. TAllocator::Deallocate(m_prgbBuffer);
  192. m_prgbBuffer = prgbBufferNew;
  193. m_cbBuffer = cb;
  194. }
  195. else if ((m_prgbBuffer != m_rgbInlineBuffer) && (cb <= nInlineBytes))
  196. {
  197. // The buffer is small enough to fit into the inline buffer, so get rid of
  198. // the dynamically allocated one.
  199. if (fPreserveContents)
  200. {
  201. memcpy(m_rgbInlineBuffer, m_prgbBuffer, nInlineBytes);
  202. m_cb = nInlineBytes;
  203. }
  204. else
  205. m_cb = 0;
  206. TAllocator::Deallocate(m_prgbBuffer);
  207. m_prgbBuffer = m_rgbInlineBuffer;
  208. m_cbBuffer = nInlineBytes;
  209. }
  210. hr = NOERROR;
  211. Exit:
  212. return hr;
  213. }
  214. private:
  215. BYTE m_rgbInlineBuffer[nInlineBytes];
  216. LPBYTE m_prgbBuffer;
  217. SIZE_T m_cbBuffer;
  218. SIZE_T m_cb;
  219. };
  220. // 128 is just an arbitrary size. The current use of this is to buffer attributes
  221. // streaming in from the service, so 64 seems like as good a guess as any.
  222. typedef CGenericByteBuffer<128> CByteBuffer;
  223. #endif