save::State Decoder::doDecoding(db::Consumer& consumer, TagSet& tags) { uint16_t flags = m_strm.uint16(); uint16_t idn = flags & 0x0fff; if (idn) { m_position.setup(idn); } else { mstl::string fen; m_strm.get(fen); m_position.setup(fen); tags.set(tag::SetUp, "1"); // bad PGN design tags.set(tag::Fen, fen); } if (!consumer.startGame(tags, m_position.board())) return save::UnsupportedVariant; Byte* dataSection = m_strm.base() + m_strm.uint24(); ByteStream text, data; if (flags & 0x8000) { unsigned size = ByteStream::uint24(dataSection); text.setup(dataSection + 3, size); data.setup(text.end(), m_strm.end()); } else { data.setup(dataSection, m_strm.end()); } if (flags & 0x7000) { EngineList engines; decodeEngines(data, engines); consumer.swapEngines(engines); } consumer.startMoveSection(); decodeRun(m_strm.uint16(), consumer); decodeVariation(consumer, data, text); consumer.finishMoveSection(result::fromString(tags.value(tag::Result))); if (data.remaining()) decodeTags(data, tags); return consumer.finishGame(tags); }
void Decoder::decodeTags(ByteStream& strm, TagSet& tags) { //M_ASSERT(strm.remaining()); mstl::string name; mstl::string value; for (tag::ID id = tag::ID(strm.get()); id; id = tag::ID(strm.get())) { if (id == tag::ExtraTag) { name.clear(); value.clear(); strm.get(name); strm.get(value); tags.setExtra(name, value); } else { value.clear(); strm.get(value); tags.set(id, value); if (tag::isRatingTag(id)) tags.setSignificance(id, 0); } #define SCI_TAGS_FIX #ifdef SCI_TAGS_FIX if (strm.remaining() == 0) return; #endif } }
save::State Consumer::endGame(TagSet const& tags) { TagSet const* tagSet = &tags; TagSet* myTags = 0; if (m_text.tellp() > 0 && m_lastCommentPos == plyCount() && !tags.contains(tag::Termination)) { result::ID result = result::fromString(tags.value(tag::Result)); if (result == result::White || result == result::Black) { Byte const* s = m_text.data() + m_text.tellp() - 1; while (s > m_text.base() && s[-1]) --s; if ( ::strcasecmp(reinterpret_cast<char const*>(s), "time") == 0 || ::strcasecmp(reinterpret_cast<char const*>(s), "time/") == 0 || ::strcasecmp(reinterpret_cast<char const*>(s), "time!") == 0 || ::strcasecmp(reinterpret_cast<char const*>(s), "time forfeit") == 0) { myTags = new TagSet(tags); myTags->set(tag::Termination, termination::toString(termination::TimeForfeit)); tagSet = myTags; } } } unsigned dataOffset = m_strm.tellp(); encodeTextSection(); encodeDataSection(engines()); encodeTags(*tagSet, allowedTags(), allowExtraTags()); ByteStream::set(m_strm.base() + m_streamPos, uint24_t(dataOffset)); m_stream.provide(); save::State state = m_codec.addGame(m_stream, *tagSet, *this); if (myTags) delete myTags; return state; }