Implement proper Size() handling in custom rwops

This commit is contained in:
Dmitry Marakasov 2017-04-21 18:16:49 +03:00
parent 5f6191dfc1
commit f28e873d17
4 changed files with 62 additions and 0 deletions

View File

@ -82,6 +82,19 @@ public:
ContainerRWops(C& container) : container_(container), position_(0) { ContainerRWops(C& container) : container_(container), position_(0) {
} }
////////////////////////////////////////////////////////////
/// \brief Get the size of the data stream
///
/// \returns Size of the data stream on success, -1 if unknown
///
/// \see SDL2pp::RWops::Size
/// \see http://wiki.libsdl.org/SDL_RWsize
///
////////////////////////////////////////////////////////////
virtual Sint64 Size() override {
return static_cast<Sint64>(container_.size());
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Seek within the container /// \brief Seek within the container
/// ///

View File

@ -26,6 +26,13 @@
namespace SDL2pp { namespace SDL2pp {
Sint64 RWops::StdSizeFuncWrapper(SDL_RWops* context) {
assert(context != nullptr);
SDL_RWops* sdl_rwops = reinterpret_cast<SDL_RWops*>(context->hidden.unknown.data1);
assert(sdl_rwops != nullptr);
return sdl_rwops->size(sdl_rwops);
}
Sint64 RWops::StdSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) { Sint64 RWops::StdSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) {
assert(context != nullptr); assert(context != nullptr);
SDL_RWops* sdl_rwops = reinterpret_cast<SDL_RWops*>(context->hidden.unknown.data1); SDL_RWops* sdl_rwops = reinterpret_cast<SDL_RWops*>(context->hidden.unknown.data1);
@ -63,6 +70,13 @@ int RWops::StdCloseFuncWrapper(SDL_RWops* context) {
return ret; return ret;
} }
Sint64 RWops::CustomSizeFuncWrapper(SDL_RWops* context) {
assert(context != nullptr);
CustomRWops* custom_rwops = reinterpret_cast<CustomRWops*>(context->hidden.unknown.data1);
assert(custom_rwops != nullptr);
return custom_rwops->Size();
}
Sint64 RWops::CustomSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) { Sint64 RWops::CustomSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) {
assert(context != nullptr); assert(context != nullptr);
CustomRWops* custom_rwops = reinterpret_cast<CustomRWops*>(context->hidden.unknown.data1); CustomRWops* custom_rwops = reinterpret_cast<CustomRWops*>(context->hidden.unknown.data1);
@ -136,6 +150,7 @@ RWops::RWops(SDL_RWops* rwops) {
if (rwops_ == nullptr) if (rwops_ == nullptr)
throw Exception("SDL_AllocRW"); throw Exception("SDL_AllocRW");
rwops_->size = StdSizeFuncWrapper;
rwops_->seek = StdSeekFuncWrapper; rwops_->seek = StdSeekFuncWrapper;
rwops_->read = StdReadFuncWrapper; rwops_->read = StdReadFuncWrapper;
rwops_->write = StdWriteFuncWrapper; rwops_->write = StdWriteFuncWrapper;

View File

@ -53,6 +53,16 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual ~CustomRWops() {} virtual ~CustomRWops() {}
////////////////////////////////////////////////////////////
/// \brief Get the size of the data stream
///
/// \returns Size of the data stream on success, -1 if unknown
///
/// \see http://wiki.libsdl.org/SDL_RWsize
///
////////////////////////////////////////////////////////////
virtual Sint64 Size() = 0;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Seek within the data stream /// \brief Seek within the data stream
/// ///
@ -148,11 +158,13 @@ protected:
SDL_RWops* rwops_; ///< Managed SDL_RWops object SDL_RWops* rwops_; ///< Managed SDL_RWops object
private: private:
static Sint64 StdSizeFuncWrapper(SDL_RWops* context);
static Sint64 StdSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence); static Sint64 StdSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence);
static size_t StdReadFuncWrapper(SDL_RWops* context, void *ptr, size_t size, size_t maxnum); static size_t StdReadFuncWrapper(SDL_RWops* context, void *ptr, size_t size, size_t maxnum);
static size_t StdWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum); static size_t StdWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum);
static int StdCloseFuncWrapper(SDL_RWops* context); static int StdCloseFuncWrapper(SDL_RWops* context);
static Sint64 CustomSizeFuncWrapper(SDL_RWops* context);
static Sint64 CustomSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence); static Sint64 CustomSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence);
static size_t CustomReadFuncWrapper(SDL_RWops* context, void *ptr, size_t size, size_t maxnum); static size_t CustomReadFuncWrapper(SDL_RWops* context, void *ptr, size_t size, size_t maxnum);
static size_t CustomWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum); static size_t CustomWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum);
@ -272,6 +284,7 @@ public:
if (rwops_ == nullptr) if (rwops_ == nullptr)
throw Exception("SDL_AllocRW"); throw Exception("SDL_AllocRW");
rwops_->size = CustomSizeFuncWrapper;
rwops_->seek = CustomSeekFuncWrapper; rwops_->seek = CustomSeekFuncWrapper;
rwops_->read = CustomReadFuncWrapper; rwops_->read = CustomReadFuncWrapper;
rwops_->write = CustomWriteFuncWrapper; rwops_->write = CustomWriteFuncWrapper;

View File

@ -24,6 +24,7 @@
#include <SDL2pp/RWops.hh> #include <SDL2pp/RWops.hh>
#include <cassert>
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include <type_traits> #include <type_traits>
@ -147,6 +148,26 @@ public:
StreamRWops(S& stream) : stream_(stream) { StreamRWops(S& stream) : stream_(stream) {
} }
////////////////////////////////////////////////////////////
/// \brief Get the size of the data stream
///
/// \returns Size of the data stream on success, -1 if unknown
///
/// \see SDL2pp::RWops::Size
/// \see http://wiki.libsdl.org/SDL_RWsize
///
////////////////////////////////////////////////////////////
virtual Sint64 Size() override {
Sint64 old_pos = TellHelper<S>();
if (old_pos == -1) // not seekable?
return -1;
SeekHelper<S>(0, std::ios_base::end);
Sint64 size = TellHelper<S>();
SeekHelper<S>(old_pos, std::ios_base::beg);
assert(TellHelper<S>() == old_pos); // make sure we're back to where we were
return size;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Seek within the stream /// \brief Seek within the stream
/// ///