DoorKeeper/src/asciimapsource.cpp

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