| /* | |
| * 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) |