| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/core/SkTypes.h" |
| #if defined(SK_BUILD_FOR_WIN) |
| |
| #include "include/core/SkStream.h" |
| #include "src/utils/win/SkIStream.h" |
| |
| /** |
| * SkBaseIStream |
| */ |
| SkBaseIStream::SkBaseIStream() : _refcount(1) { } |
| SkBaseIStream::~SkBaseIStream() { } |
| |
| SK_STDMETHODIMP SkBaseIStream::QueryInterface(REFIID iid, void ** ppvObject) { |
| if (nullptr == ppvObject) { |
| return E_INVALIDARG; |
| } |
| if (iid == __uuidof(IUnknown) |
| || iid == __uuidof(IStream) |
| || iid == __uuidof(ISequentialStream)) |
| { |
| *ppvObject = static_cast<IStream*>(this); |
| AddRef(); |
| return S_OK; |
| } else { |
| *ppvObject = nullptr; |
| return E_NOINTERFACE; |
| } |
| } |
| |
| SK_STDMETHODIMP_(ULONG) SkBaseIStream::AddRef() { |
| return (ULONG)InterlockedIncrement(&_refcount); |
| } |
| |
| SK_STDMETHODIMP_(ULONG) SkBaseIStream::Release() { |
| ULONG res = (ULONG) InterlockedDecrement(&_refcount); |
| if (0 == res) { |
| delete this; |
| } |
| return res; |
| } |
| |
| // ISequentialStream Interface |
| SK_STDMETHODIMP SkBaseIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) |
| { return E_NOTIMPL; } |
| |
| // IStream Interface |
| SK_STDMETHODIMP SkBaseIStream::SetSize(ULARGE_INTEGER) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Commit(DWORD) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Revert() |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Clone(IStream**) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove, |
| DWORD dwOrigin, |
| ULARGE_INTEGER* lpNewFilePointer) |
| { return E_NOTIMPL; } |
| |
| SK_STDMETHODIMP SkBaseIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) |
| { return E_NOTIMPL; } |
| |
| |
| /** |
| * SkIStream |
| */ |
| SkIStream::SkIStream(std::unique_ptr<SkStreamAsset> stream) |
| : SkBaseIStream() |
| , fSkStream(std::move(stream)) |
| , fLocation() |
| { |
| this->fSkStream->rewind(); |
| } |
| |
| SkIStream::~SkIStream() {} |
| |
| HRESULT SkIStream::CreateFromSkStream(std::unique_ptr<SkStreamAsset> stream, IStream** ppStream) { |
| if (nullptr == stream) { |
| return E_INVALIDARG; |
| } |
| *ppStream = new SkIStream(std::move(stream)); |
| return S_OK; |
| } |
| |
| // ISequentialStream Interface |
| SK_STDMETHODIMP SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) { |
| *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb)); |
| this->fLocation.QuadPart += *pcbRead; |
| return (*pcbRead == cb) ? S_OK : S_FALSE; |
| } |
| |
| SK_STDMETHODIMP SkIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) { |
| return STG_E_CANTSAVE; |
| } |
| |
| // IStream Interface |
| SK_STDMETHODIMP SkIStream::Seek(LARGE_INTEGER liDistanceToMove, |
| DWORD dwOrigin, |
| ULARGE_INTEGER* lpNewFilePointer) |
| { |
| HRESULT hr = S_OK; |
| |
| switch(dwOrigin) { |
| case STREAM_SEEK_SET: { |
| if (!this->fSkStream->rewind()) { |
| hr = E_FAIL; |
| } else { |
| size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart); |
| size_t skipped = this->fSkStream->skip(skip); |
| this->fLocation.QuadPart = skipped; |
| if (skipped != skip) { |
| hr = E_FAIL; |
| } |
| } |
| break; |
| } |
| case STREAM_SEEK_CUR: { |
| size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart); |
| size_t skipped = this->fSkStream->skip(skip); |
| this->fLocation.QuadPart += skipped; |
| if (skipped != skip) { |
| hr = E_FAIL; |
| } |
| break; |
| } |
| case STREAM_SEEK_END: { |
| if (!this->fSkStream->rewind()) { |
| hr = E_FAIL; |
| } else { |
| size_t skip = static_cast<size_t>(this->fSkStream->getLength() + |
| liDistanceToMove.QuadPart); |
| size_t skipped = this->fSkStream->skip(skip); |
| this->fLocation.QuadPart = skipped; |
| if (skipped != skip) { |
| hr = E_FAIL; |
| } |
| } |
| break; |
| } |
| default: |
| hr = STG_E_INVALIDFUNCTION; |
| break; |
| } |
| |
| if (lpNewFilePointer) { |
| lpNewFilePointer->QuadPart = this->fLocation.QuadPart; |
| } |
| return hr; |
| } |
| |
| SK_STDMETHODIMP SkIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) { |
| if (0 == (grfStatFlag & STATFLAG_NONAME)) { |
| return STG_E_INVALIDFLAG; |
| } |
| pStatstg->pwcsName = nullptr; |
| pStatstg->cbSize.QuadPart = this->fSkStream->getLength(); |
| pStatstg->clsid = CLSID_NULL; |
| pStatstg->type = STGTY_STREAM; |
| pStatstg->grfMode = STGM_READ; |
| return S_OK; |
| } |
| |
| |
| /** |
| * SkIWStream |
| */ |
| SkWIStream::SkWIStream(SkWStream* stream) |
| : SkBaseIStream() |
| , fSkWStream(stream) |
| { } |
| |
| SkWIStream::~SkWIStream() { |
| if (this->fSkWStream) { |
| this->fSkWStream->flush(); |
| } |
| } |
| |
| HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream, IStream ** ppStream) { |
| *ppStream = new SkWIStream(stream); |
| return S_OK; |
| } |
| |
| // ISequentialStream Interface |
| SK_STDMETHODIMP SkWIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) { |
| HRESULT hr = S_OK; |
| bool wrote = this->fSkWStream->write(pv, cb); |
| if (wrote) { |
| *pcbWritten = cb; |
| } else { |
| *pcbWritten = 0; |
| hr = S_FALSE; |
| } |
| return hr; |
| } |
| |
| // IStream Interface |
| SK_STDMETHODIMP SkWIStream::Commit(DWORD) { |
| this->fSkWStream->flush(); |
| return S_OK; |
| } |
| |
| SK_STDMETHODIMP SkWIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) { |
| if (0 == (grfStatFlag & STATFLAG_NONAME)) { |
| return STG_E_INVALIDFLAG; |
| } |
| pStatstg->pwcsName = nullptr; |
| pStatstg->cbSize.QuadPart = 0; |
| pStatstg->clsid = CLSID_NULL; |
| pStatstg->type = STGTY_STREAM; |
| pStatstg->grfMode = STGM_WRITE; |
| return S_OK; |
| } |
| #endif//defined(SK_BUILD_FOR_WIN) |