Refactoring in map reading code - part 1/2

Fixed a bug when iterating over a view that was smaller than the map size
Added a class to abstract map readers
This commit is contained in:
King_DuckZ 2015-01-05 18:01:28 +01:00
parent a6afd2eb54
commit 436d738620
12 changed files with 292 additions and 145 deletions

View file

@ -1,4 +1,5 @@
#include "helpers/asciimapsource.hpp"
#include "implem/compatibility.h"
#include "asciimap_parser.hpp"
#include <fstream>
#include <iomanip>
@ -7,32 +8,76 @@
namespace dkh {
namespace {
char extractByte ( AsciiMapSource::MapTileType parVal, std::size_t parByte ) a_pure;
char extractByte (AsciiMapSource::MapTileType parVal, std::size_t parByte) {
return static_cast<char>(
(parVal >> (parByte * 8)) & 0xFF
);
}
} //unnamed namespace
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::AsciiMapSource (const char* parFilename) {
m_bytepos = 0;
std::ifstream src(parFilename);
parse_map_data(src);
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
setg(base, base, base + m_wholedata.size());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::AsciiMapSource (const std::string& parFilename) {
m_bytepos = 0;
std::ifstream src(parFilename);
parse_map_data(src);
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
setg(base, base, base + m_wholedata.size());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::AsciiMapSource (std::istream& parData) {
m_bytepos = 0;
parse_map_data(parData);
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
setg(base, base, base + m_wholedata.size());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::int_type AsciiMapSource::underflow() {
if (m_bytepos == m_wholedata.size() * DataSize)
return traits_type::eof();
const auto index = m_bytepos / DataSize;
const auto byte = m_bytepos % DataSize;
return traits_type::to_int_type(extractByte(m_wholedata[index], byte));
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::int_type AsciiMapSource::uflow() {
if (m_bytepos == m_wholedata.size() * DataSize)
return traits_type::eof();
const auto retval = underflow();
++m_bytepos;
return retval;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::int_type AsciiMapSource::pbackfail (int_type parCh) {
if (0 == m_bytepos or (parCh != traits_type::eof() and parCh != traits_type::to_int_type(extractByte(m_wholedata[m_bytepos / DataSize], m_bytepos % DataSize))))
return traits_type::eof();
--m_bytepos;
DK_ASSERT(underflow() == traits_type::to_int_type(parCh));
return traits_type::to_int_type(parCh);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
std::streamsize AsciiMapSource::showmanyc() {
DK_ASSERT(m_bytepos <= m_wholedata.size() * DataSize);
return m_wholedata.size() * DataSize - m_bytepos;
}
///-------------------------------------------------------------------------
@ -63,4 +108,66 @@ namespace dkh {
m_mapSize.x() = grammar.lengths.front();
m_mapSize.y() = m_wholedata.size() / m_mapSize.x();
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::pos_type AsciiMapSource::seekoff (off_type parOff, std::ios_base::seekdir parDir, std::ios_base::openmode parWhich) {
using std::ios;
if (parWhich & ios::out)
return traits_type::eof();
const std::size_t dataLength = DataSize * m_wholedata.size();
if (parWhich & ios::in) {
std::size_t desiredPos;
switch (parDir) {
case ios::beg:
desiredPos = static_cast<std::size_t>(parOff);
break;
case ios::cur:
desiredPos = static_cast<std::size_t>(m_bytepos + parOff);
break;
case ios::end:
desiredPos = static_cast<std::size_t>(dataLength - parOff);
break;
default:
m_bytepos = static_cast<std::size_t>(dataLength);
return traits_type::eof();
}
if (desiredPos >= dataLength) {
m_bytepos = dataLength;
return traits_type::eof();
}
else {
m_bytepos = desiredPos;
return static_cast<pos_type>(m_bytepos);
}
}
m_bytepos = dataLength;
return traits_type::eof();
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
AsciiMapSource::pos_type AsciiMapSource::seekpos(pos_type parPos, std::ios_base::openmode parWhich) {
using std::ios;
if (parWhich & ios::out)
return traits_type::eof();
const std::size_t dataLength = DataSize * m_wholedata.size();
if (parWhich & ios::in) {
if (static_cast<std::size_t>(parPos) >= dataLength) {
m_bytepos = dataLength;
return traits_type::eof();
}
else {
m_bytepos = static_cast<std::size_t>(parPos);
return static_cast<pos_type>(m_bytepos);
}
}
m_bytepos = static_cast<std::size_t>(parPos);
return static_cast<pos_type>(m_bytepos);
}
} //namespace dkh