From 2e0f59f18916b26d875a4231430605fbb6e5e69d Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 5 Jan 2015 18:01:57 +0100 Subject: [PATCH] Refactoring in map reading code - part 2/2 --- include/implem/mapstreamraw.inl | 74 +++++++++++++++++++++++++++++ include/mapreaders/mapstreamraw.hpp | 65 +++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 include/implem/mapstreamraw.inl create mode 100644 include/mapreaders/mapstreamraw.hpp diff --git a/include/implem/mapstreamraw.inl b/include/implem/mapstreamraw.inl new file mode 100644 index 0000000..40e5d1d --- /dev/null +++ b/include/implem/mapstreamraw.inl @@ -0,0 +1,74 @@ +namespace dk { + namespace implem { + ///--------------------------------------------------------------------- + ///Only enabled if Device::MapDimensions is defined and is the same + ///as D. The function's name is set to give a hint to the user as to + ///why the error has occurred (they are trying to construct a + ///TileMapData with a set dimension that is different from the one + ///hardcoded in the device being passed in). The actual name could be + ///something like get_device_dimensions(). + ///--------------------------------------------------------------------- + template + inline + typename std::enable_if::type err_mismatching_dimension (const Device*) noexcept { + return Device::MapDimensions; + } + + ///--------------------------------------------------------------------- + ///Only enabled if Device::MapDimensions is not defined. The function's + ///name is set to give a hint to the user as to why the error has + ///occurred (they are trying to construct a TileMapData with a set + ///dimension that is different from the one hardcoded in the device + ///being passed in). The actual name could be something like + ///get_device_dimensions(). + ///--------------------------------------------------------------------- + template + inline + typename std::enable_if::result == false, std::size_t>::type err_mismatching_dimension (const Device*) noexcept { + return 0; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + inline + typename std::enable_if>::type retrieve_map_size_from_device (Device* parDevice) { + return parDevice->mapSize(); + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + inline + typename std::enable_if::result == false, Vector>::type retrieve_map_size_from_device (Device* parDevice) { + return get_map_size_from_device(parDevice); + } + } //namespace implem + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + template + MapStreamRaw::MapStreamRaw (Device& parDevice) : + MapStreamBase(implem::retrieve_map_size_from_device(&parDevice)), + m_istream(&parDevice), + m_deviceHasDim(D == implem::err_mismatching_dimension(&parDevice)) + { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + std::size_t MapStreamRaw::dataBlockRequested (char* parOut, std::size_t parOutSize, const coords& parFrom, const coords& parTo) { + DK_ASSERT(parOut); + + const std::size_t totalBlocks = implem::area(parTo - parFrom); + const std::size_t storableBlocks = parOutSize / sizeof(T); + const std::size_t readMem = sizeof(T) * std::min(storableBlocks, totalBlocks); + + const std::streamoff readPos = static_cast(implem::area(parFrom)); + m_istream.seekg(readPos, std::ios_base::beg); + m_istream.read(parOut, readMem); + return readMem; + } +} //namespace dk diff --git a/include/mapreaders/mapstreamraw.hpp b/include/mapreaders/mapstreamraw.hpp new file mode 100644 index 0000000..542ca1f --- /dev/null +++ b/include/mapreaders/mapstreamraw.hpp @@ -0,0 +1,65 @@ +#ifndef id56E2396E102B4E10B20466D6B57A4C66 +#define id56E2396E102B4E10B20466D6B57A4C66 + +#include "mapreaders/mapstreambase.hpp" +#include "implem/helpers.hpp" +#include +#include +#include +#include + +namespace dk { + namespace implem { + template + class HasMapDimensions { + class yes { char m; }; + class nope { yes m[2]; }; + static yes deduce ( int a, int b = T::MapDimensions ); + static nope deduce ( ... ); + public: + enum { + result = (sizeof(yes) == sizeof(deduce(1))) + }; + }; + + template + typename std::enable_if::type err_mismatching_dimension ( const Device* ) noexcept a_pure; + + template + typename std::enable_if::result == false, std::size_t>::type err_mismatching_dimension ( const Device* ) noexcept a_pure; + + template + typename std::enable_if>::type retrieve_map_size_from_device ( Device* parDevice ); + + template + typename std::enable_if::result == false, Vector>::type retrieve_map_size_from_device ( Device* parDevice ); + } //namespace implem + + //Customization point - specialize to enable map size retrieval for Device + template + typename Device::coords get_map_size_from_device ( const Device* parDevice ); + + template + class MapStreamRaw : public MapStreamBase { + public: + typedef typename MapStreamBase::coords coords; + + MapStreamRaw ( void ) = delete; + template + explicit MapStreamRaw ( Device& parDevice ); + virtual ~MapStreamRaw ( void ) noexcept = default; + + virtual bool isReadable ( void ) const { return true; } + virtual bool isWriteable ( void ) const { return false; } + + private: + virtual std::size_t dataBlockRequested ( char* parOut, std::size_t parOutSize, const coords& parFrom, const coords& parTo ); + + std::istream m_istream; + const bool m_deviceHasDim; + }; +} //namespace dk + +#include "implem/mapstreamraw.inl" + +#endif