Factor out 3 copies of identical code into wxInputStreamPeeker
Resolve the long standing "NOTE" comments about having the same code in wxAnimationDecoder::CanRead(), wxImage::CanRead() and GetImageCount() by extracting the common logic into a helper wxInputStreamPeeker class and using it from all places. This loses the possibility to log a debug message if rewinding the stream fails, but this is probably not very valuable and the actual error should be already logged by SeekI() itself when it fails on a seekable stream. No real changes.
This commit is contained in:
@@ -96,24 +96,8 @@ public:
|
|||||||
|
|
||||||
bool CanRead( wxInputStream& stream ) const
|
bool CanRead( wxInputStream& stream ) const
|
||||||
{
|
{
|
||||||
// NOTE: this code is the same of wxImageHandler::CallDoCanRead
|
return wxInputStreamPeeker(stream).
|
||||||
|
CallIfCanSeek(&wxAnimationDecoder::DoCanRead, this);
|
||||||
if ( !stream.IsSeekable() )
|
|
||||||
return false; // can't test unseekable stream
|
|
||||||
|
|
||||||
wxFileOffset posOld = stream.TellI();
|
|
||||||
bool ok = DoCanRead(stream);
|
|
||||||
|
|
||||||
// restore the old position to be able to test other formats and so on
|
|
||||||
if ( stream.SeekI(posOld) == wxInvalidOffset )
|
|
||||||
{
|
|
||||||
wxLogDebug(wxT("Failed to rewind the stream in wxAnimationDecoder!"));
|
|
||||||
|
|
||||||
// reading would fail anyhow as we're not at the right position
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual wxAnimationDecoder *Clone() const = 0;
|
virtual wxAnimationDecoder *Clone() const = 0;
|
||||||
|
|||||||
@@ -682,6 +682,53 @@ protected:
|
|||||||
wxDECLARE_NO_COPY_CLASS(wxWrapperInputStream);
|
wxDECLARE_NO_COPY_CLASS(wxWrapperInputStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxPeekInputStream(): read some data from a stream and then rewind it back
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This semi-private class is used in wx code to read some data, using the
|
||||||
|
// provided method of the class T, from a stream if it's seekable and then
|
||||||
|
// rewind it back.
|
||||||
|
class wxInputStreamPeeker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxInputStreamPeeker(wxInputStream& stream)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_ofsOrig(stream.IsSeekable() ? stream.TellI() : wxInvalidOffset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the given function if the stream is seekable, otherwise return 0.
|
||||||
|
template <typename R, typename T>
|
||||||
|
R CallIfCanSeek(R (T::*func)(wxInputStream&), T* obj)
|
||||||
|
{
|
||||||
|
return RewindAndReturn(CanSeek() ? (obj->*func)(m_stream) : R(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload for const methods.
|
||||||
|
template <typename R, typename T>
|
||||||
|
R CallIfCanSeek(R (T::*func)(wxInputStream&) const, const T* obj)
|
||||||
|
{
|
||||||
|
return RewindAndReturn(CanSeek() ? (obj->*func)(m_stream) : R(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CanSeek() const { return m_ofsOrig != wxInvalidOffset; }
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
R RewindAndReturn(R retval)
|
||||||
|
{
|
||||||
|
if ( CanSeek() && m_stream.SeekI(m_ofsOrig) == wxInvalidOffset )
|
||||||
|
return R(0);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxInputStream& m_stream;
|
||||||
|
const wxFileOffset m_ofsOrig;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxInputStreamPeeker);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
|
|||||||
@@ -3445,25 +3445,8 @@ wxIMPLEMENT_ABSTRACT_CLASS(wxImageHandler, wxObject);
|
|||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
int wxImageHandler::GetImageCount( wxInputStream& stream )
|
int wxImageHandler::GetImageCount( wxInputStream& stream )
|
||||||
{
|
{
|
||||||
// NOTE: this code is the same of wxAnimationDecoder::CanRead and
|
return wxInputStreamPeeker(stream).
|
||||||
// wxImageHandler::CallDoCanRead
|
CallIfCanSeek(&wxImageHandler::DoGetImageCount, this);
|
||||||
|
|
||||||
if ( !stream.IsSeekable() )
|
|
||||||
return false; // can't test unseekable stream
|
|
||||||
|
|
||||||
wxFileOffset posOld = stream.TellI();
|
|
||||||
int n = DoGetImageCount(stream);
|
|
||||||
|
|
||||||
// restore the old position to be able to test other formats and so on
|
|
||||||
if ( stream.SeekI(posOld) == wxInvalidOffset )
|
|
||||||
{
|
|
||||||
wxLogDebug(wxT("Failed to rewind the stream in wxImageHandler!"));
|
|
||||||
|
|
||||||
// reading would fail anyhow as we're not at the right position
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxImageHandler::CanRead( const wxString& name )
|
bool wxImageHandler::CanRead( const wxString& name )
|
||||||
@@ -3481,25 +3464,8 @@ bool wxImageHandler::CanRead( const wxString& name )
|
|||||||
|
|
||||||
bool wxImageHandler::CallDoCanRead(wxInputStream& stream)
|
bool wxImageHandler::CallDoCanRead(wxInputStream& stream)
|
||||||
{
|
{
|
||||||
// NOTE: this code is the same of wxAnimationDecoder::CanRead and
|
return wxInputStreamPeeker(stream)
|
||||||
// wxImageHandler::GetImageCount
|
.CallIfCanSeek(&wxImageHandler::DoCanRead, this);
|
||||||
|
|
||||||
if ( !stream.IsSeekable() )
|
|
||||||
return false; // can't test unseekable stream
|
|
||||||
|
|
||||||
wxFileOffset posOld = stream.TellI();
|
|
||||||
bool ok = DoCanRead(stream);
|
|
||||||
|
|
||||||
// restore the old position to be able to test other formats and so on
|
|
||||||
if ( stream.SeekI(posOld) == wxInvalidOffset )
|
|
||||||
{
|
|
||||||
wxLogDebug(wxT("Failed to rewind the stream in wxImageHandler!"));
|
|
||||||
|
|
||||||
// reading would fail anyhow as we're not at the right position
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
|
|||||||
Reference in New Issue
Block a user