121 lines
3.9 KiB
C++
121 lines
3.9 KiB
C++
#include "doorkeeper/helpers/asciimapsource.hpp"
|
|
#include "doorkeeper/implem/compatibility.h"
|
|
#include "doorkeeper/helpers/typename.hpp"
|
|
#include "asciimap_parser.hpp"
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
|
|
namespace dkh {
|
|
///-------------------------------------------------------------------------
|
|
///-------------------------------------------------------------------------
|
|
AsciiMapSource::AsciiMapSource (const char* parFilename, const coords& parSize, dk::MapTypes parMapType, const coords& parTileSize) :
|
|
m_mapSize(parSize),
|
|
m_tileSize(parTileSize),
|
|
m_mapType(parMapType)
|
|
{
|
|
std::ifstream src(parFilename);
|
|
parse_map_data(src);
|
|
}
|
|
|
|
///-------------------------------------------------------------------------
|
|
///-------------------------------------------------------------------------
|
|
AsciiMapSource::AsciiMapSource (const std::string& parFilename, const coords& parSize, dk::MapTypes parMapType, const coords& parTileSize) :
|
|
m_mapSize(parSize),
|
|
m_tileSize(parTileSize),
|
|
m_mapType(parMapType)
|
|
{
|
|
std::ifstream src(parFilename);
|
|
parse_map_data(src);
|
|
}
|
|
|
|
///-------------------------------------------------------------------------
|
|
///-------------------------------------------------------------------------
|
|
AsciiMapSource::AsciiMapSource (std::istream& parData, const coords& parSize, dk::MapTypes parMapType, const coords& parTileSize) :
|
|
m_mapSize(parSize),
|
|
m_tileSize(parTileSize),
|
|
m_mapType(parMapType)
|
|
{
|
|
parse_map_data(parData);
|
|
}
|
|
|
|
///-------------------------------------------------------------------------
|
|
///-------------------------------------------------------------------------
|
|
void AsciiMapSource::parse_map_data (std::istream& parSrc) {
|
|
typedef std::istream_iterator<char> DataIterator;
|
|
typedef boost::spirit::multi_pass<DataIterator> WrappedIterator;
|
|
|
|
parSrc >> std::noskipws;
|
|
|
|
auto first = WrappedIterator(DataIterator(parSrc));
|
|
auto last = WrappedIterator(DataIterator());
|
|
implem::AsciiMapGrammar<WrappedIterator, MapTileType> grammar(first);
|
|
const bool p = boost::spirit::qi::parse(
|
|
first,
|
|
last,
|
|
grammar,
|
|
m_wholedata
|
|
);
|
|
|
|
if (not p or last != first) {
|
|
throw std::runtime_error("Invalid data: can't parse file");
|
|
}
|
|
|
|
coords map_size;
|
|
if (grammar.lengths.empty()) {
|
|
map_size.x() = map_size.y() = 0;
|
|
throw std::runtime_error("Invalid data: can't guess map size");
|
|
}
|
|
|
|
//Only look at the front. Besides a bug in spirit makes the other counts
|
|
//invalid, see
|
|
//http://boost.2283326.n4.nabble.com/Possible-bug-in-line-pos-iterator-td4636592.html
|
|
map_size.x() = grammar.lengths.front();
|
|
map_size.y() = m_wholedata.size() / map_size.x();
|
|
if (map_size != m_mapSize) {
|
|
std::ostringstream oss;
|
|
oss << "Calculated map size is " << map_size <<
|
|
" which is different than the expected size " << m_mapSize;
|
|
throw std::runtime_error(oss.str());
|
|
}
|
|
}
|
|
|
|
const AsciiMapSource::coords& AsciiMapSource::mapSize() const {
|
|
return m_mapSize;
|
|
}
|
|
|
|
const AsciiMapSource::coords& AsciiMapSource::tileSize() const {
|
|
return m_tileSize;
|
|
}
|
|
|
|
void AsciiMapSource::fetch_raw (char* parOut, const coords& parFrom, const coords& parTo, std::size_t parSize) {
|
|
const std::size_t from = parFrom.x() + parFrom.y() * m_mapSize.x();
|
|
const std::size_t to = parTo.x() + parTo.y() * m_mapSize.x() + 1;
|
|
DK_ASSERT(to >= from);
|
|
DK_ASSERT(parSize / sizeof(MapTileType) == to - from);
|
|
std::copy(m_wholedata.begin() + from, m_wholedata.begin() + to, parOut);
|
|
}
|
|
|
|
dk::MapTypes AsciiMapSource::mapType() const {
|
|
return m_mapType;
|
|
}
|
|
|
|
int AsciiMapSource::layersCount() const {
|
|
return 1;
|
|
}
|
|
|
|
void AsciiMapSource::chainedMaps (std::vector<std::string>&) const {
|
|
}
|
|
|
|
dk::HashType AsciiMapSource::layerTypeHash (int parIndex) const {
|
|
#if defined(DK_ASSERTIONS_ENABLED)
|
|
DK_ASSERT(0 == parIndex);
|
|
#else
|
|
(void)parIndex;
|
|
#endif
|
|
return dk::type_name_hash<int>();
|
|
}
|
|
} //namespace dkh
|