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::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; } } } }