From f28e873d17c0421cc4304e130663455ce769fab5 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Fri, 21 Apr 2017 18:16:49 +0300 Subject: [PATCH] Implement proper Size() handling in custom rwops --- SDL2pp/ContainerRWops.hh | 13 +++++++++++++ SDL2pp/RWops.cc | 15 +++++++++++++++ SDL2pp/RWops.hh | 13 +++++++++++++ SDL2pp/StreamRWops.hh | 21 +++++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/SDL2pp/ContainerRWops.hh b/SDL2pp/ContainerRWops.hh index 536c8d8..b03463f 100644 --- a/SDL2pp/ContainerRWops.hh +++ b/SDL2pp/ContainerRWops.hh @@ -82,6 +82,19 @@ public: 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(container_.size()); + } + //////////////////////////////////////////////////////////// /// \brief Seek within the container /// diff --git a/SDL2pp/RWops.cc b/SDL2pp/RWops.cc index e742794..cc13aa3 100644 --- a/SDL2pp/RWops.cc +++ b/SDL2pp/RWops.cc @@ -26,6 +26,13 @@ namespace SDL2pp { +Sint64 RWops::StdSizeFuncWrapper(SDL_RWops* context) { + assert(context != nullptr); + SDL_RWops* sdl_rwops = reinterpret_cast(context->hidden.unknown.data1); + assert(sdl_rwops != nullptr); + return sdl_rwops->size(sdl_rwops); +} + Sint64 RWops::StdSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) { assert(context != nullptr); SDL_RWops* sdl_rwops = reinterpret_cast(context->hidden.unknown.data1); @@ -63,6 +70,13 @@ int RWops::StdCloseFuncWrapper(SDL_RWops* context) { return ret; } +Sint64 RWops::CustomSizeFuncWrapper(SDL_RWops* context) { + assert(context != nullptr); + CustomRWops* custom_rwops = reinterpret_cast(context->hidden.unknown.data1); + assert(custom_rwops != nullptr); + return custom_rwops->Size(); +} + Sint64 RWops::CustomSeekFuncWrapper(SDL_RWops* context, Sint64 offset, int whence) { assert(context != nullptr); CustomRWops* custom_rwops = reinterpret_cast(context->hidden.unknown.data1); @@ -136,6 +150,7 @@ RWops::RWops(SDL_RWops* rwops) { if (rwops_ == nullptr) throw Exception("SDL_AllocRW"); + rwops_->size = StdSizeFuncWrapper; rwops_->seek = StdSeekFuncWrapper; rwops_->read = StdReadFuncWrapper; rwops_->write = StdWriteFuncWrapper; diff --git a/SDL2pp/RWops.hh b/SDL2pp/RWops.hh index 21e4ecc..467af1a 100644 --- a/SDL2pp/RWops.hh +++ b/SDL2pp/RWops.hh @@ -53,6 +53,16 @@ public: //////////////////////////////////////////////////////////// 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 /// @@ -148,11 +158,13 @@ protected: SDL_RWops* rwops_; ///< Managed SDL_RWops object private: + static Sint64 StdSizeFuncWrapper(SDL_RWops* context); 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 StdWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum); static int StdCloseFuncWrapper(SDL_RWops* context); + static Sint64 CustomSizeFuncWrapper(SDL_RWops* context); 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 CustomWriteFuncWrapper(SDL_RWops* context, const void *ptr, size_t size, size_t maxnum); @@ -272,6 +284,7 @@ public: if (rwops_ == nullptr) throw Exception("SDL_AllocRW"); + rwops_->size = CustomSizeFuncWrapper; rwops_->seek = CustomSeekFuncWrapper; rwops_->read = CustomReadFuncWrapper; rwops_->write = CustomWriteFuncWrapper; diff --git a/SDL2pp/StreamRWops.hh b/SDL2pp/StreamRWops.hh index 4530eda..905f2e7 100644 --- a/SDL2pp/StreamRWops.hh +++ b/SDL2pp/StreamRWops.hh @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -147,6 +148,26 @@ public: 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(); + if (old_pos == -1) // not seekable? + return -1; + SeekHelper(0, std::ios_base::end); + Sint64 size = TellHelper(); + SeekHelper(old_pos, std::ios_base::beg); + assert(TellHelper() == old_pos); // make sure we're back to where we were + return size; + } + //////////////////////////////////////////////////////////// /// \brief Seek within the stream ///