MemoryStream.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "WebKitDLL.h"
  27. #include "MemoryStream.h"
  28. using std::min;
  29. using namespace WebCore;
  30. // MemoryStream ---------------------------------------------------------------
  31. MemoryStream::MemoryStream(PassRefPtr<SharedBuffer> buffer)
  32. : m_refCount(0)
  33. , m_buffer(buffer)
  34. , m_pos(0)
  35. {
  36. gClassCount++;
  37. gClassNameCount.add("MemoryStream");
  38. }
  39. MemoryStream::~MemoryStream()
  40. {
  41. gClassCount--;
  42. gClassNameCount.remove("MemoryStream");
  43. }
  44. COMPtr<MemoryStream> MemoryStream::createInstance(PassRefPtr<SharedBuffer> buffer)
  45. {
  46. return new MemoryStream(buffer);
  47. }
  48. // IUnknown -------------------------------------------------------------------
  49. HRESULT STDMETHODCALLTYPE MemoryStream::QueryInterface(REFIID riid, void** ppvObject)
  50. {
  51. *ppvObject = 0;
  52. if (IsEqualGUID(riid, IID_IUnknown))
  53. *ppvObject = static_cast<IUnknown*>(this);
  54. else if (IsEqualGUID(riid, IID_ISequentialStream))
  55. *ppvObject = static_cast<ISequentialStream*>(this);
  56. else if (IsEqualGUID(riid, IID_IStream))
  57. *ppvObject = static_cast<IStream*>(this);
  58. else
  59. return E_NOINTERFACE;
  60. AddRef();
  61. return S_OK;
  62. }
  63. ULONG STDMETHODCALLTYPE MemoryStream::AddRef(void)
  64. {
  65. return ++m_refCount;
  66. }
  67. ULONG STDMETHODCALLTYPE MemoryStream::Release(void)
  68. {
  69. ULONG newRef = --m_refCount;
  70. if (!newRef)
  71. delete(this);
  72. return newRef;
  73. }
  74. // ISequentialStream ----------------------------------------------------------
  75. HRESULT STDMETHODCALLTYPE MemoryStream::Read(
  76. /* [length_is][size_is][out] */ void* pv,
  77. /* [in] */ ULONG cb,
  78. /* [out] */ ULONG* pcbRead)
  79. {
  80. *pcbRead = 0;
  81. if (!m_buffer)
  82. return E_FAIL;
  83. if (m_pos >= m_buffer->size())
  84. return S_FALSE;
  85. if (m_pos + cb < m_buffer->size())
  86. *pcbRead = cb;
  87. else
  88. *pcbRead = (ULONG) (m_buffer->size() - m_pos);
  89. memcpy(pv, m_buffer->data() + m_pos, *pcbRead);
  90. m_pos += *pcbRead;
  91. return S_OK;
  92. }
  93. HRESULT STDMETHODCALLTYPE MemoryStream::Write(
  94. /* [size_is][in] */ const void* /*pv*/,
  95. /* [in] */ ULONG /*cb*/,
  96. /* [out] */ ULONG* /*pcbWritten*/)
  97. {
  98. // we use this for read-only streams
  99. return STG_E_ACCESSDENIED;
  100. }
  101. // IStream --------------------------------------------------------------------
  102. HRESULT STDMETHODCALLTYPE MemoryStream::Seek(
  103. /* [in] */ LARGE_INTEGER dlibMove,
  104. /* [in] */ DWORD dwOrigin,
  105. /* [out] */ ULARGE_INTEGER* plibNewPosition)
  106. {
  107. if (!m_buffer)
  108. return E_FAIL;
  109. size_t proposedPos = m_pos;
  110. size_t lowPartNeg;
  111. switch (dwOrigin) {
  112. case STREAM_SEEK_SET:
  113. proposedPos = dlibMove.LowPart;
  114. if (dlibMove.HighPart)
  115. return E_FAIL;
  116. break;
  117. case STREAM_SEEK_CUR:
  118. if (!dlibMove.HighPart) {
  119. if (dlibMove.LowPart > (m_buffer->size() - m_pos))
  120. return E_FAIL;
  121. proposedPos += dlibMove.LowPart;
  122. } else if (dlibMove.HighPart == -1) {
  123. lowPartNeg = (~dlibMove.LowPart)+1;
  124. if (lowPartNeg > m_pos)
  125. return E_FAIL;
  126. proposedPos = m_pos - lowPartNeg;
  127. } else
  128. return E_FAIL;
  129. break;
  130. case STREAM_SEEK_END:
  131. if (dlibMove.HighPart != -1)
  132. return E_FAIL;
  133. lowPartNeg = (~dlibMove.LowPart)+1;
  134. if (lowPartNeg > m_buffer->size())
  135. return E_FAIL;
  136. proposedPos = m_buffer->size() - lowPartNeg;
  137. break;
  138. default:
  139. return E_FAIL;
  140. }
  141. if (proposedPos >= m_buffer->size())
  142. return E_FAIL;
  143. if (plibNewPosition) {
  144. plibNewPosition->HighPart = 0;
  145. plibNewPosition->LowPart = (DWORD) m_pos;
  146. }
  147. return S_OK;
  148. }
  149. HRESULT STDMETHODCALLTYPE MemoryStream::SetSize(
  150. /* [in] */ ULARGE_INTEGER /*libNewSize*/)
  151. {
  152. return STG_E_INVALIDFUNCTION;
  153. }
  154. HRESULT STDMETHODCALLTYPE MemoryStream::CopyTo(
  155. /* [unique][in] */ IStream* pstm,
  156. /* [in] */ ULARGE_INTEGER cb,
  157. /* [out] */ ULARGE_INTEGER* pcbRead,
  158. /* [out] */ ULARGE_INTEGER* pcbWritten)
  159. {
  160. if (!m_buffer)
  161. return E_FAIL;
  162. if (cb.HighPart) {
  163. cb.HighPart = 0;
  164. cb.LowPart = (DWORD)-1;
  165. }
  166. ULONG written;
  167. ULONG read = min(cb.LowPart, (ULONG)(m_buffer->size()-m_pos));
  168. HRESULT hr = pstm->Write(m_buffer->data()+m_pos, read, &written);
  169. if (pcbWritten) {
  170. pcbWritten->HighPart = 0;
  171. pcbWritten->LowPart = written;
  172. }
  173. if (pcbRead) {
  174. pcbRead->HighPart = 0;
  175. pcbRead->LowPart = read;
  176. }
  177. return hr;
  178. }
  179. HRESULT STDMETHODCALLTYPE MemoryStream::Commit(
  180. /* [in] */ DWORD /*grfCommitFlags*/)
  181. {
  182. return S_OK;
  183. }
  184. HRESULT STDMETHODCALLTYPE MemoryStream::Revert( void)
  185. {
  186. return S_OK;
  187. }
  188. HRESULT STDMETHODCALLTYPE MemoryStream::LockRegion(
  189. /* [in] */ ULARGE_INTEGER /*libOffset*/,
  190. /* [in] */ ULARGE_INTEGER /*cb*/,
  191. /* [in] */ DWORD /*dwLockType*/)
  192. {
  193. return STG_E_INVALIDFUNCTION;
  194. }
  195. HRESULT STDMETHODCALLTYPE MemoryStream::UnlockRegion(
  196. /* [in] */ ULARGE_INTEGER /*libOffset*/,
  197. /* [in] */ ULARGE_INTEGER /*cb*/,
  198. /* [in] */ DWORD /*dwLockType*/)
  199. {
  200. return STG_E_INVALIDFUNCTION;
  201. }
  202. HRESULT STDMETHODCALLTYPE MemoryStream::Stat(
  203. /* [out] */ STATSTG* pstatstg,
  204. /* [in] */ DWORD /*grfStatFlag*/)
  205. {
  206. if (!pstatstg)
  207. return E_POINTER;
  208. if (!m_buffer)
  209. return E_FAIL;
  210. memset(pstatstg, 0, sizeof(STATSTG));
  211. pstatstg->type = STGTY_STREAM;
  212. pstatstg->cbSize.LowPart = (DWORD) m_buffer->size();
  213. return S_OK;
  214. }
  215. HRESULT STDMETHODCALLTYPE MemoryStream::Clone(
  216. /* [out] */ IStream** ppstm)
  217. {
  218. MemoryStream::createInstance(m_buffer).copyRefTo(ppstm);
  219. // FIXME: MSDN says we should be returning STG_E_INSUFFICIENT_MEMORY instead of E_OUTOFMEMORY here.
  220. return (*ppstm) ? S_OK : E_OUTOFMEMORY;
  221. }