• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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