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 | */ |
17 | SkBaseIStream::SkBaseIStream() : _refcount(1) { } |
18 | SkBaseIStream::~SkBaseIStream() { } |
19 | |
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 | |
37 | SK_STDMETHODIMP_(ULONG) SkBaseIStream::AddRef() { |
38 | return (ULONG)InterlockedIncrement(&_refcount); |
39 | } |
40 | |
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 |
50 | SK_STDMETHODIMP SkBaseIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) |
51 | { return E_NOTIMPL; } |
52 | |
53 | SK_STDMETHODIMP SkBaseIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) |
54 | { return E_NOTIMPL; } |
55 | |
56 | // IStream Interface |
57 | SK_STDMETHODIMP SkBaseIStream::SetSize(ULARGE_INTEGER) |
58 | { return E_NOTIMPL; } |
59 | |
60 | SK_STDMETHODIMP SkBaseIStream::CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) |
61 | { return E_NOTIMPL; } |
62 | |
63 | SK_STDMETHODIMP SkBaseIStream::Commit(DWORD) |
64 | { return E_NOTIMPL; } |
65 | |
66 | SK_STDMETHODIMP SkBaseIStream::Revert() |
67 | { return E_NOTIMPL; } |
68 | |
69 | SK_STDMETHODIMP SkBaseIStream::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) |
70 | { return E_NOTIMPL; } |
71 | |
72 | SK_STDMETHODIMP SkBaseIStream::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) |
73 | { return E_NOTIMPL; } |
74 | |
75 | SK_STDMETHODIMP SkBaseIStream::Clone(IStream**) |
76 | { return E_NOTIMPL; } |
77 | |
78 | SK_STDMETHODIMP SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove, |
79 | DWORD dwOrigin, |
80 | ULARGE_INTEGER* lpNewFilePointer) |
81 | { return E_NOTIMPL; } |
82 | |
83 | SK_STDMETHODIMP SkBaseIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) |
84 | { return E_NOTIMPL; } |
85 | |
86 | |
87 | /** |
88 | * SkIStream |
89 | */ |
90 | SkIStream::SkIStream(std::unique_ptr<SkStreamAsset> stream) |
91 | : SkBaseIStream() |
92 | , fSkStream(std::move(stream)) |
93 | , fLocation() |
94 | { |
95 | this->fSkStream->rewind(); |
96 | } |
97 | |
98 | SkIStream::~SkIStream() {} |
99 | |
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 |
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 | |
115 | SK_STDMETHODIMP SkIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) { |
116 | return STG_E_CANTSAVE; |
117 | } |
118 | |
119 | // IStream Interface |
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 | |
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 | */ |
190 | SkWIStream::SkWIStream(SkWStream* stream) |
191 | : SkBaseIStream() |
192 | , fSkWStream(stream) |
193 | { } |
194 | |
195 | SkWIStream::~SkWIStream() { |
196 | if (this->fSkWStream) { |
197 | this->fSkWStream->flush(); |
198 | } |
199 | } |
200 | |
201 | HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream, IStream ** ppStream) { |
202 | *ppStream = new SkWIStream(stream); |
203 | return S_OK; |
204 | } |
205 | |
206 | // ISequentialStream Interface |
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 |
220 | SK_STDMETHODIMP SkWIStream::Commit(DWORD) { |
221 | this->fSkWStream->flush(); |
222 | return S_OK; |
223 | } |
224 | |
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 | |