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 } }
void Decoder::decodeTextSection(MoveNode* node, ByteStream& text) { for ( ; node; node = node->next()) { if (node->hasSupplement()) { if (uint8_t flag = node->commentFlag()) { mstl::string buf; Comment comment; if (flag & comm::Ante) { text.get(buf); comment.swap(buf, bool(flag & comm::Ante_Eng), bool(flag & comm::Ante_Oth)); node->setComment(comment, move::Ante); } if (flag & comm::Post) { text.get(buf); comment.swap(buf, bool(flag & comm::Post_Eng), bool(flag & comm::Post_Oth)); node->setComment(comment, move::Post); } } for (unsigned i = 0; i < node->variationCount(); ++i) decodeTextSection(node->variation(i), text); } } }
void Decoder::decodeEngines(ByteStream& strm, EngineList& engines) { uint8_t count = strm.get(); engines.reserve(count); for (unsigned i = 0; i < count; ++i) { mstl::string engine; strm.get(engine); engines.addEngine(engine); } }
void Decoder::decodeVariation(Consumer& consumer, util::ByteStream& data, ByteStream& text) { MarkSet marks; MoveInfoSet moveInfo; Annotation annotation; mstl::string buf; Comment comment; Comment preComment; bool hasNote(false); // satisfies the compiler unsigned pieceNum(0); // satisfies the compiler Move move; Move lastMove; while (true) { Byte b = m_strm.get(); if (__builtin_expect(b > token::Last, 1)) { if (move) { if (hasNote) { consumer.putMove(move, annotation, preComment, comment, marks); if (!moveInfo.isEmpty()) { consumer.putMoveInfo(moveInfo); moveInfo.clear(); } marks.clear(); annotation.clear(); comment.clear(); preComment.clear(); hasNote = false; } else { consumer.putMove(move); } m_position.doMove(move, pieceNum); } else { if (lastMove) { m_position.doMove(lastMove, pieceNum); lastMove.clear(); } if (hasNote) { consumer.putPrecedingComment(comment, annotation, marks); marks.clear(); annotation.clear(); comment.clear(); hasNote = false; } } pieceNum = decodeMove(b, move); } else { switch (b) { case token::End_Marker: if (move) { if (hasNote) { consumer.putMove(move, annotation, preComment, comment, marks); if (!moveInfo.isEmpty()) consumer.putMoveInfo(moveInfo); } else { consumer.putMove(move); } } else if (hasNote) { consumer.putPrecedingComment(comment, annotation, marks); hasNote = false; } switch (m_strm.get()) { case token::Comment: { uint8_t flag = data.get(); buf.clear(); text.get(buf); comment.swap(buf, bool(flag & comm::Ante_Eng), bool(flag & comm::Ante_Oth)); consumer.putTrailingComment(comment); break; } case token::End_Marker: break; default: return; //IO_RAISE(Game, Corrupted, "unexpected token"); } return; case token::Start_Marker: if (move) { if (hasNote) { consumer.putMove(move, annotation, preComment, comment, marks); if (!moveInfo.isEmpty()) { consumer.putMoveInfo(moveInfo); moveInfo.clear(); } marks.clear(); annotation.clear(); comment.clear(); preComment.clear(); hasNote = false; } else { consumer.putMove(move); } lastMove = move; move.clear(); } //M_ASSERT(!hasNote); m_position.push(); m_position.board().undoMove(lastMove); consumer.startVariation(); decodeVariation(consumer, data, text); consumer.finishVariation(); m_position.pop(); break; case token::Nag: { nag::ID nag = nag::ID(m_strm.get()); if (nag == 0) { move.setLegalMove(false); } else { annotation.add(nag); hasNote = true; } } break; case token::Mark: if (data.peek() & 0x80) moveInfo.add().decode(data); else marks.add().decode(data); hasNote = true; break; case token::Comment: { uint8_t flag = data.get(); if (flag & comm::Ante) { buf.clear(); text.get(buf); preComment.swap(buf, bool(flag & comm::Ante_Eng), bool(flag & comm::Ante_Oth)); } if (flag & comm::Post) { buf.clear(); text.get(buf); comment.swap(buf, bool(flag & comm::Post_Eng), bool(flag & comm::Post_Oth)); } hasNote = true; } break; } } } }
void Decoder::decodeVariation(ByteStream& data) { unsigned pieceNum = 0; // satisfies the compiler Move move; while (true) { Byte b; while ((b = m_strm.get()) > token::End_Marker) { if (move) m_position.doMove(move, pieceNum); pieceNum = decodeMove(b, move); MoveNode* node = new MoveNode(move); m_currentNode->setNext(node); m_currentNode = node; } switch (b) { case token::End_Marker: { MoveNode* node = new MoveNode; m_currentNode->setNext(node); switch (m_strm.get()) { case token::Comment: node->setCommentFlag(data.get()); break; case token::End_Marker: break; default: return; //IO_RAISE(Game, Corrupted, "unexpected token"); } } return; case token::Start_Marker: { MoveNode* current = m_currentNode; m_position.push(); m_position.board().undoMove(move); current->addVariation(m_currentNode = new MoveNode); decodeVariation(data); m_currentNode = current; m_position.pop(); } break; case token::Nag: static_assert(Annotation::Max_Nags >= 7, "Scidb needs at least seven entries"); { nag::ID nag = nag::ID(m_strm.get()); if (nag == 0) move.setLegalMove(false); else m_currentNode->addAnnotation(nag); } break; case token::Mark: if (data.peek() & 0x80) { MoveInfo info; info.decode(data); m_currentNode->addMoveInfo(info); } else { Mark mark; mark.decode(data); m_currentNode->addMark(mark); } break; case token::Comment: m_currentNode->setCommentFlag(data.get()); break; } } }