Add a hash mechanism to BaseMapSource.

This is needed to recognize what type of tiles a layer contains.
Client code has to fill in a map of hash => add_layer<T>() pointers.
As a layer is loaded, the correct add_layer<T>() is called based
on the hash saved with the layer itself.
This commit is contained in:
King_DuckZ 2015-06-07 03:57:18 +02:00
commit fd8a1cbabc
20 changed files with 1647 additions and 40 deletions

View file

@ -3,6 +3,7 @@
#include "doorkeeper/implem/maptypes.hpp"
#include "doorkeeper/primitivetypes.hpp"
#include "doorkeeper/helpers/hashing.hpp"
#include "doorkeeper/implem/coords_utils.hpp"
#include <cstdint>
#include <vector>
@ -33,6 +34,7 @@ namespace dk {
virtual MapTypes mapType ( void ) const = 0;
virtual int layersCount ( void ) const = 0;
virtual void chainedMaps ( std::vector<std::string>& parOut ) const = 0;
virtual HashType layerTypeHash ( int parIndex ) const = 0;
protected:
virtual void fetch_raw ( char* parOut, const coords& parFrom, const coords& parTo, std::size_t parSize ) = 0;

View file

@ -29,9 +29,11 @@ namespace dk {
const coords& map_size ( void ) const { return m_size; }
template <typename T>
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap );
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, int parIndex );
template <typename T>
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, const coords& parSubdiv );
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, const coords& parSubdiv, int parIndex );
template <typename T>
void push_layer_void ( BaseMapSource<D>* parTilemap, int parIndex );
void preload ( const coords& parFrom, const coords& parTo );

View file

@ -13,11 +13,11 @@ namespace dk {
} //namespace dk
namespace dkh {
template <typename T, uint32_t D, typename C>
template <uint32_t D, typename C>
struct MapLoaderPool;
template <typename T, typename C>
using MapLoaderPool2d = MapLoaderPool<T, 2, C>;
template <typename C>
using MapLoaderPool2d = MapLoaderPool<2, C>;
} //namespace dkh
#endif

View file

@ -33,6 +33,7 @@ namespace dkh {
virtual int layersCount ( void ) const;
virtual const coords& tileSize ( void ) const;
virtual void chainedMaps ( std::vector<std::string>& parOut ) const;
virtual dk::HashType layerTypeHash ( int parIndex ) const;
private:
void parse_map_data ( std::istream& parSrc );

View file

@ -0,0 +1,30 @@
#ifndef id4E5F8A0ABA6047BA988D512351B9DD2D
#define id4E5F8A0ABA6047BA988D512351B9DD2D
//#include "doorkeeper/implem/string_bt.hpp"
#include "doorkeeper/implem/compatibility.h"
#include <cstdint>
#include <ciso646>
namespace dk {
namespace implem {
struct HashType {
uint64_t a;
uint64_t b;
uint64_t c;
bool operator< ( const HashType& parOther ) const;
};
HashType hash_string ( const char* parString, std::size_t parLen ) a_pure;
} //namespace implem
typedef dk::implem::HashType HashType;
template <typename T, uint32_t D>
implem::HashType make_signature_hash ( void ) a_pure;
} //namespace dk
#include "doorkeeper/implem/hashing.inl"
#endif

View file

@ -3,6 +3,8 @@
#include "doorkeeper/components/tyler.hpp"
#include "doorkeeper/components/basemapsource.hpp"
#include "doorkeeper/helpers/hashing.hpp"
#include "doorkeeper/components/exception.hpp"
#include <cstdint>
#include <utility>
#include <string>
@ -12,14 +14,16 @@
#include <ciso646>
namespace dkh {
template <typename T, uint32_t D, typename C>
template <uint32_t D>
using PushLayerMapType = std::map<dk::HashType, void(dk::Tyler<D>::*)(dk::BaseMapSource<D>*,int)>;
template <uint32_t D, typename C>
struct MapLoaderPool {
typedef std::unique_ptr<dk::BaseMapSource<D>> BaseMapSourceUPtr;
typedef std::map<std::string, BaseMapSourceUPtr> PoolMapType;
enum { dimensions = D };
typedef C opener_type;
typedef T tile_type;
PoolMapType pool;
C opener;
@ -27,17 +31,25 @@ namespace dkh {
dk::BaseMapSource<D>* operator() ( const std::string& parName );
};
template <typename M>
dk::Tyler<M::dimensions> call_map_load ( M& parFileOpener, const std::string& parOpen );
class UnknownLayerTemplateException : public dk::DoorKeeperException {
};
template <typename M>
dk::Tyler<M::dimensions> call_map_load ( dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen );
dk::Tyler<M::dimensions> call_map_load ( M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher );
template <typename T, uint32_t D, typename C>
dk::Tyler<D> map_load ( C& parFileOpener, const std::string& parOpen );
template <typename M>
dk::Tyler<M::dimensions> call_map_load ( dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher );
template <typename T, uint32_t D, typename C>
dk::Tyler<D>& map_load ( dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen );
template <uint32_t D, typename C>
dk::Tyler<D> map_load ( C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher );
template <uint32_t D, typename C>
dk::Tyler<D>& map_load ( dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher );
namespace implem {
template <uint32_t D>
void call_push_layer ( dk::Tyler<D>& parTyler, const PushLayerMapType<D>& parPusher, dk::BaseMapSource<D>* parReader, int parIndex );
} //namespace implem
} //namespace dkh
#include "doorkeeper/implem/maploader.inl"

View file

@ -5,13 +5,13 @@
#include "doorkeeper/implem/vector.hpp"
#include "doorkeeper/components/basemapsource.hpp"
#include "doorkeeper/implem/maptypes.hpp"
#include "doorkeeper/components/exception.hpp"
#include <fstream>
#include <cstdint>
#include <memory>
#include <map>
#include <string>
#include <ciso646>
#include <exception>
#if !defined(NDEBUG) && !defined(WITH_TYLERMAP_WRITER)
# define WITH_TYLERMAP_WRITER
@ -40,14 +40,18 @@ namespace dkh {
virtual dk::MapTypes mapType ( void ) const;
virtual int layersCount ( void ) const;
virtual void chainedMaps ( std::vector<std::string>& parOut ) const;
virtual dk::HashType layerTypeHash ( int parIndex ) const;
private:
struct LayerInfo;
void parse_map_data ( std::istream& parSrc );
virtual void fetch_raw ( char* parOut, const coords& parFrom, const coords& parTo, std::size_t parSize );
std::unique_ptr<std::istream> m_stream;
std::map<std::string, std::string> m_comments;
std::vector<LayerInfo> m_layers_info;
coords m_map_size;
coords m_tile_size;
pos_type m_stream_start;
@ -70,9 +74,9 @@ namespace dkh {
};
#endif
class InvalidMapFileException : public std::exception {
class InvalidMapFileException : public dk::DoorKeeperException {
};
class InvalidMapDimensionsException : public std::exception {
class InvalidMapDimensionsException : public dk::DoorKeeperException {
};
namespace implem {
@ -83,7 +87,7 @@ namespace dkh {
uint16_t version_minor;
uint8_t layer_count;
uint8_t map_type;
uint8_t map_info_type;
uint8_t hashing_algorithm;
uint8_t dimensions;
uint32_t dimensions_start;
uint32_t comment_start;

View file

@ -28,6 +28,7 @@ typedef DK_COORD_SCALAR_TYPE MAKE_DK_NAME(CoordinateScalarType);
# include <cassert>
# define DK_ASSERT(a) assert(a)
# endif
# define DK_ASSERTIONS_ENABLED
#else
# if !defined(DK_ASSERT)
# define DK_ASSERT(a)

View file

@ -0,0 +1,15 @@
namespace dk {
template <typename T, uint32_t D>
HashType make_signature_hash() {
#if defined(__GNUC__)
//TODO: use bt::string if possible
const char* const pf = __PRETTY_FUNCTION__;
const std::size_t len = sizeof(__PRETTY_FUNCTION__) - 1;
//constexpr bt::string<sizeof(__PRETTY_FUNCTION__)-1> func_pretty(pf);
#else
# error "Unknown compiler"
#endif
//return implem::hash_string(func_pretty.data(), func_pretty.size());
return implem::hash_string(pf, len);
}
} //namespace dk

View file

@ -1,19 +1,21 @@
namespace dkh {
template <typename T, uint32_t D, typename C>
dk::Tyler<D> map_load (C& parFileOpener, const std::string& parOpen) {
template <uint32_t D, typename C>
dk::Tyler<D> map_load (C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher) {
dk::BaseMapSource<D>* reader = parFileOpener(parOpen);
dk::Tyler<D> tyler(reader->tileSize());
tyler.template push_layer<T>(reader);
for (int z = 0; z < reader->layersCount(); ++z) {
implem::call_push_layer<D>(tyler, parPusher, reader, z);
}
std::vector<std::string> submaps;
reader->chainedMaps(submaps);
for (const auto& name : submaps) {
map_load<T, D, C>(tyler, parFileOpener, name);
map_load<D, C>(tyler, parFileOpener, name, parPusher);
}
return std::move(tyler);
}
template <typename T, uint32_t D, typename C>
dk::Tyler<D>& map_load (dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen) {
template <uint32_t D, typename C>
dk::Tyler<D>& map_load (dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher) {
std::stack<std::string, std::vector<std::string>> name_stack;
std::vector<std::string> submaps;
name_stack.push(parOpen);
@ -28,13 +30,15 @@ namespace dkh {
name_stack.emplace(std::move(curr_name));
}
parTyler.template push_layer<T>(reader);
for (int z = 0; z < reader->layersCount(); ++z) {
implem::call_push_layer<D>(parTyler, parPusher, reader, z);
}
} while (not name_stack.empty());
return parTyler;
}
template <typename T, uint32_t D, typename C>
dk::BaseMapSource<D>* MapLoaderPool<T, D, C>::operator() (const std::string& parName) {
template <uint32_t D, typename C>
dk::BaseMapSource<D>* MapLoaderPool<D, C>::operator() (const std::string& parName) {
auto it_found = pool.find(parName);
if (pool.end() != it_found) {
return it_found->second.get();
@ -48,12 +52,23 @@ namespace dkh {
}
template <typename M>
dk::Tyler<M::dimensions> call_map_load (M& parFileOpener, const std::string& parOpen) {
return map_load<typename M::tile_type, M::dimensions, M>(parFileOpener, parOpen);
dk::Tyler<M::dimensions> call_map_load (M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher) {
return map_load<M::dimensions, M>(parFileOpener, parOpen, parPusher);
}
template <typename M>
dk::Tyler<M::dimensions> call_map_load (dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen) {
return map_load<typename M::tile_type, M::dimensions, M>(parTyler, parFileOpener, parOpen);
dk::Tyler<M::dimensions> call_map_load (dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher) {
return map_load<M::dimensions, M>(parTyler, parFileOpener, parOpen, parPusher);
}
namespace implem {
template <uint32_t D>
void call_push_layer (dk::Tyler<D>& parTyler, const PushLayerMapType<D>& parPusher, dk::BaseMapSource<D>* parReader, int parLayerIndex) {
auto it_found = parPusher.find(parReader->layerTypeHash(parLayerIndex));
if (parPusher.end() == it_found)
throw UnknownLayerTemplateException();
(parTyler.*(it_found->second))(parReader, parLayerIndex);
}
} //namespace implem
} //namespace dkh

View file

@ -23,15 +23,18 @@ namespace dk {
///--------------------------------------------------------------------------
template <uint32_t D>
template <typename T>
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap) {
return push_layer<T>(parTilemap, coords(static_cast<CoordinateScalarType>(1)));
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, int parIndex) {
return push_layer<T>(parTilemap, coords(static_cast<CoordinateScalarType>(1)), parIndex);
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <uint32_t D>
template <typename T>
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, const coords& parSubdiv) {
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, const coords& parSubdiv, int parIndex) {
//TODO: store the index
(void)parIndex;
auto newLayer = new Layer<T, D>(m_tilesize / parSubdiv, m_tilesize, parTilemap);
if (m_size == coords(0)) {
m_size = newLayer->mapSize();
@ -47,6 +50,14 @@ namespace dk {
return *newLayer;
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <uint32_t D>
template <typename T>
void Tyler<D>::push_layer_void (BaseMapSource<D>* parTilemap, int parIndex) {
push_layer<T>(parTilemap, parIndex);
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <uint32_t D>

View file

@ -1,4 +1,11 @@
namespace dkh {
template <uint32_t D>
struct TylerMapSource<D>::LayerInfo {
dk::HashType hash;
uint32_t data_start;
uint32_t data_length;
};
template <uint32_t D>
TylerMapSource<D>::TylerMapSource (const char* parFilename) :
m_stream(new std::ifstream(parFilename)),
@ -100,4 +107,11 @@ namespace dkh {
void TylerMapSource<D>::chainedMaps (std::vector<std::string>& parOut) const {
implem::extract_array_from_comments(parOut, "chained_map", m_comments);
}
template <uint32_t D>
dk::HashType TylerMapSource<D>::layerTypeHash (int parIndex) const {
DK_ASSERT(parIndex >= 0);
DK_ASSERT(static_cast<std::size_t>(parIndex) < m_layers_info.size());
return m_layers_info[parIndex].hash;
}
} //namespace dkh