1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkTypes.h"
9 #if defined(SK_BUILD_FOR_WIN)
10
11 #include "include/core/SkStream.h"
12 #include "src/utils/win/SkIStream.h"
13
14 /**
15 * SkBaseIStream
16 */
SkBaseIStream()17 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
~SkBaseIStream()18 SkBaseIStream::~SkBaseIStream() { }
19
QueryInterface(REFIID iid,void ** ppvObject)20 SK_STDMETHODIMP SkBaseIStream::QueryInterface(REFIID iid, void ** ppvObject) {
21 if (nullptr == ppvObject) {
22 return E_INVALIDARG;
23 }
24 if (iid == __uuidof(IUnknown)
25 || iid == __uuidof(IStream)
26 || iid == __uuidof(ISequentialStream))
27 {
28 *ppvObject = static_cast<IStream*>(this);
29 AddRef();
30 return S_OK;
31 } else {
32 *ppvObject = nullptr;
33 return E_NOINTERFACE;
34 }
35 }
36
SK_STDMETHODIMP_(ULONG)37 SK_STDMETHODIMP_(ULONG) SkBaseIStream::AddRef() {
38 return (ULONG)InterlockedIncrement(&_refcount);
39 }
40
SK_STDMETHODIMP_(ULONG)41 SK_STDMETHODIMP_(ULONG) SkBaseIStream::Release() {
42 ULONG res = (ULONG) InterlockedDecrement(&_refcount);
43 if (0 == res) {
44 delete this;
45 }
46 return res;
47 }
48
49 // ISequentialStream Interface
Read(void * pv,ULONG cb,ULONG * pcbRead)50 SK_STDMETHODIMP SkBaseIStream::Read(void* pv, ULONG cb, ULONG* pcbRead)
51 { return E_NOTIMPL; }
52
Write(void const * pv,ULONG cb,ULONG * pcbWritten)53 SK_STDMETHODIMP SkBaseIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten)
54 { return E_NOTIMPL; }
55
56 // IStream Interface
SetSize(ULARGE_INTEGER)57 SK_STDMETHODIMP SkBaseIStream::SetSize(ULARGE_INTEGER)
58 { return E_NOTIMPL; }
59
CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *)60 SK_STDMETHODIMP SkBaseIStream::CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*)
61 { return E_NOTIMPL; }
62
Commit(DWORD)63 SK_STDMETHODIMP SkBaseIStream::Commit(DWORD)
64 { return E_NOTIMPL; }
65
Revert()66 SK_STDMETHODIMP SkBaseIStream::Revert()
67 { return E_NOTIMPL; }
68
LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)69 SK_STDMETHODIMP SkBaseIStream::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
70 { return E_NOTIMPL; }
71
UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD)72 SK_STDMETHODIMP SkBaseIStream::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
73 { return E_NOTIMPL; }
74
Clone(IStream **)75 SK_STDMETHODIMP SkBaseIStream::Clone(IStream**)
76 { return E_NOTIMPL; }
77
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)78 SK_STDMETHODIMP SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove,
79 DWORD dwOrigin,
80 ULARGE_INTEGER* lpNewFilePointer)
81 { return E_NOTIMPL; }
82
Stat(STATSTG * pStatstg,DWORD grfStatFlag)83 SK_STDMETHODIMP SkBaseIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag)
84 { return E_NOTIMPL; }
85
86
87 /**
88 * SkIStream
89 */
SkIStream(std::unique_ptr<SkStreamAsset> stream)90 SkIStream::SkIStream(std::unique_ptr<SkStreamAsset> stream)
91 : SkBaseIStream()
92 , fSkStream(std::move(stream))
93 , fLocation()
94 {
95 this->fSkStream->rewind();
96 }
97
~SkIStream()98 SkIStream::~SkIStream() {}
99
CreateFromSkStream(std::unique_ptr<SkStreamAsset> stream,IStream ** ppStream)100 HRESULT SkIStream::CreateFromSkStream(std::unique_ptr<SkStreamAsset> stream, IStream** ppStream) {
101 if (nullptr == stream) {
102 return E_INVALIDARG;
103 }
104 *ppStream = new SkIStream(std::move(stream));
105 return S_OK;
106 }
107
108 // ISequentialStream Interface
Read(void * pv,ULONG cb,ULONG * pcbRead)109 SK_STDMETHODIMP SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
110 *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
111 this->fLocation.QuadPart += *pcbRead;
112 return (*pcbRead == cb) ? S_OK : S_FALSE;
113 }
114
Write(void const * pv,ULONG cb,ULONG * pcbWritten)115 SK_STDMETHODIMP SkIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
116 return STG_E_CANTSAVE;
117 }
118
119 // IStream Interface
Seek(LARGE_INTEGER liDistanceToMove,DWORD dwOrigin,ULARGE_INTEGER * lpNewFilePointer)120 SK_STDMETHODIMP SkIStream::Seek(LARGE_INTEGER liDistanceToMove,
121 DWORD dwOrigin,
122 ULARGE_INTEGER* lpNewFilePointer)
123 {
124 HRESULT hr = S_OK;
125
126 switch(dwOrigin) {
127 case STREAM_SEEK_SET: {
128 if (!this->fSkStream->rewind()) {
129 hr = E_FAIL;
130 } else {
131 size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
132 size_t skipped = this->fSkStream->skip(skip);
133 this->fLocation.QuadPart = skipped;
134 if (skipped != skip) {
135 hr = E_FAIL;
136 }
137 }
138 break;
139 }
140 case STREAM_SEEK_CUR: {
141 size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
142 size_t skipped = this->fSkStream->skip(skip);
143 this->fLocation.QuadPart += skipped;
144 if (skipped != skip) {
145 hr = E_FAIL;
146 }
147 break;
148 }
149 case STREAM_SEEK_END: {
150 if (!this->fSkStream->rewind()) {
151 hr = E_FAIL;
152 } else {
153 size_t skip = static_cast<size_t>(this->fSkStream->getLength() +
154 liDistanceToMove.QuadPart);
155 size_t skipped = this->fSkStream->skip(skip);
156 this->fLocation.QuadPart = skipped;
157 if (skipped != skip) {
158 hr = E_FAIL;
159 }
160 }
161 break;
162 }
163 default:
164 hr = STG_E_INVALIDFUNCTION;
165 break;
166 }
167
168 if (lpNewFilePointer) {
169 lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
170 }
171 return hr;
172 }
173
Stat(STATSTG * pStatstg,DWORD grfStatFlag)174 SK_STDMETHODIMP SkIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
175 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
176 return STG_E_INVALIDFLAG;
177 }
178 pStatstg->pwcsName = nullptr;
179 pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
180 pStatstg->clsid = CLSID_NULL;
181 pStatstg->type = STGTY_STREAM;
182 pStatstg->grfMode = STGM_READ;
183 return S_OK;
184 }
185
186
187 /**
188 * SkIWStream
189 */
SkWIStream(SkWStream * stream)190 SkWIStream::SkWIStream(SkWStream* stream)
191 : SkBaseIStream()
192 , fSkWStream(stream)
193 { }
194
~SkWIStream()195 SkWIStream::~SkWIStream() {
196 if (this->fSkWStream) {
197 this->fSkWStream->flush();
198 }
199 }
200
CreateFromSkWStream(SkWStream * stream,IStream ** ppStream)201 HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream, IStream ** ppStream) {
202 *ppStream = new SkWIStream(stream);
203 return S_OK;
204 }
205
206 // ISequentialStream Interface
Write(void const * pv,ULONG cb,ULONG * pcbWritten)207 SK_STDMETHODIMP SkWIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
208 HRESULT hr = S_OK;
209 bool wrote = this->fSkWStream->write(pv, cb);
210 if (wrote) {
211 *pcbWritten = cb;
212 } else {
213 *pcbWritten = 0;
214 hr = S_FALSE;
215 }
216 return hr;
217 }
218
219 // IStream Interface
Commit(DWORD)220 SK_STDMETHODIMP SkWIStream::Commit(DWORD) {
221 this->fSkWStream->flush();
222 return S_OK;
223 }
224
Stat(STATSTG * pStatstg,DWORD grfStatFlag)225 SK_STDMETHODIMP SkWIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
226 if (0 == (grfStatFlag & STATFLAG_NONAME)) {
227 return STG_E_INVALIDFLAG;
228 }
229 pStatstg->pwcsName = nullptr;
230 pStatstg->cbSize.QuadPart = 0;
231 pStatstg->clsid = CLSID_NULL;
232 pStatstg->type = STGTY_STREAM;
233 pStatstg->grfMode = STGM_WRITE;
234 return S_OK;
235 }
236 #endif//defined(SK_BUILD_FOR_WIN)
237