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 Node::visit(Visitor& visitor, List const& nodes, TagSet const& tags) { result::ID result = result::fromString(tags.value(tag::Result)); visitor.start(result); for (unsigned i = 0; i < nodes.size(); ++i) nodes[i]->visit(visitor); visitor.finish(result); }
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; }
DatabaseCodec::InfoData::InfoData(TagSet const& tags) :whiteCountry(country::Unknown) ,blackCountry(country::Unknown) ,eventCountry(country::Unknown) ,whiteTitle(title::None) ,blackTitle(title::None) ,whiteType(species::Unspecified) ,blackType(species::Unspecified) ,whiteSex(sex::Unspecified) ,blackSex(sex::Unspecified) ,whiteFideID(0) ,blackFideID(0) ,eventType(event::Unknown) ,timeMode(time::Unknown) ,eventMode(event::Undetermined) { if (tags.contains(tag::WhiteCountry)) whiteCountry = country::fromString(tags.value(tag::WhiteCountry)); if (tags.contains(tag::WhiteTitle)) whiteTitle = title::fromString(tags.value(tag::WhiteTitle)); if (tags.contains(tag::WhiteType)) whiteType = species::fromString(tags.value(tag::WhiteType)); if (tags.contains(tag::WhiteSex)) whiteSex = sex::fromChar(*tags.value(tag::WhiteSex)); if (tags.contains(tag::BlackCountry)) blackCountry = country::fromString(tags.value(tag::BlackCountry)); if (tags.contains(tag::BlackTitle)) blackTitle = title::fromString(tags.value(tag::BlackTitle)); if (tags.contains(tag::BlackType)) blackType = species::fromString(tags.value(tag::BlackType)); if (tags.contains(tag::BlackSex)) blackSex = sex::fromChar(*tags.value(tag::BlackSex)); if (tags.contains(tag::WhiteFideId)) whiteFideID = tags.asInt(tag::WhiteFideId); if (tags.contains(tag::BlackFideId)) blackFideID = tags.asInt(tag::BlackFideId); if (tags.contains(tag::EventType)) eventType = event::typeFromString(tags.value(tag::EventType)); if (tags.contains(tag::Mode)) eventMode = event::modeFromString(tags.value(tag::Mode)); if (tags.contains(tag::TimeMode)) timeMode = time::fromString(tags.value(tag::TimeMode)); if (tags.contains(tag::EventType)) eventType = event::typeFromString(tags.value(tag::EventType)); if (tags.contains(tag::EventCountry)) eventCountry = country::fromString(tags.value(tag::EventCountry)); if (tags.contains(tag::EventDate)) eventDate.fromString(tags.value(tag::EventDate)); }
save::State DatabaseCodec::saveGame(ByteStream const& gameData, TagSet const& tags, Provider const& provider) { //M_REQUIRE(isOpen()); typedef Namebase::PlayerEntry* Player; typedef Namebase::EventEntry* Event; typedef Namebase::SiteEntry* Site; typedef Namebase::Entry* Entry; if (gameData.size() > maxGameRecordLength()) return save::GameTooLong; if (provider.plyCount() > maxGameLength()) return save::GameTooLong; GameInfo* info = 0; unsigned index; if (provider.index() >= 0) { index = provider.index(); info = m_db->m_gameInfoList[index]; *m_storedInfo = *info; info->reset(m_db->m_namebases); } else if (m_db->size() == maxGameCount()) { return save::TooManyGames; } else { index = m_db->m_gameInfoList.size(); } unsigned maxAnnotatorCount = this->maxAnnotatorCount(); unsigned maxPlayerCount = this->maxPlayerCount(); InfoData data(tags); Player whiteEntry; Player blackEntry; Site siteEntry; switch (provider.sourceFormat()) { case format::Scid3: case format::Scid4: { mstl::string name; whiteEntry = namebase(Namebase::Player).insertPlayer( ::normalizePlayerName(tags.value(tag::White), name), data.whiteCountry, data.whiteTitle, data.whiteType, data.whiteSex, data.whiteFideID, maxPlayerCount); blackEntry = namebase(Namebase::Player).insertPlayer( ::normalizePlayerName(tags.value(tag::Black), name), data.blackCountry, data.blackTitle, data.blackType, data.blackSex, data.blackFideID, maxPlayerCount); siteEntry = namebase(Namebase::Site).insertSite( ::normalizeSiteName(tags.value(tag::Site), name), data.eventCountry, maxSiteCount()); } break; default: whiteEntry = namebase(Namebase::Player).insertPlayer( tags.value(tag::White), data.whiteCountry, data.whiteTitle, data.whiteType, data.whiteSex, data.whiteFideID, maxPlayerCount); blackEntry = namebase(Namebase::Player).insertPlayer( tags.value(tag::Black), data.blackCountry, data.blackTitle, data.blackType, data.blackSex, data.blackFideID, maxPlayerCount); siteEntry = namebase(Namebase::Site).insertSite( tags.value(tag::Site), data.eventCountry, maxSiteCount()); } Event eventEntry = namebase(Namebase::Event).insertEvent( tags.value(tag::Event), data.eventDate, data.eventType, data.timeMode, data.eventMode, maxEventCount(), siteEntry ? siteEntry : NamebaseEvent::emptySite()); Entry annotatorEntry = NamebaseEntry::emptyEntry(); if (maxAnnotatorCount) { annotatorEntry = namebase(Namebase::Annotator).insert(tags.value(tag::Annotator), maxAnnotatorCount); } save::State state = save::Ok; bool failed = whiteEntry == 0 || blackEntry == 0 || eventEntry == 0 || siteEntry == 0 || annotatorEntry == 0; unsigned gameOffset = 0; // shut up compiler if (!failed) { if (info) gameOffset = putGame(gameData, info->gameOffset(), info->gameRecordLength()); else gameOffset = putGame(gameData); } if (failed || int(gameOffset) < 0) { if (info) info->restore(*m_storedInfo, m_db->m_namebases); namebases().update(); switch (gameOffset) { /*case util::BlockFile::MaxFileSizeExceeded: IO_RAISE(Game, Max_File_Size_Exceeded, "maximal file size (2 GB) exceeded"); case util::BlockFile::SyncFailed: IO_RAISE(Game, Write_Failed, "sync failed"); case util::BlockFile::ReadError: IO_RAISE(Game, Read_Error, "read error"); case util::BlockFile::IllegalOffset: IO_RAISE(Game, Write_Failed, "offset failure (internal error)");*/ } if (!whiteEntry) return save::TooManyPlayerNames; if (!blackEntry) return save::TooManyPlayerNames; if (!eventEntry) return save::TooManyEventNames; if (!siteEntry) return save::TooManySiteNames; return save::TooManyAnnotatorNames; } if (info == 0) { info = allocGameInfo(); m_db->m_gameInfoList.push_back(info); } info->setup(gameOffset, gameData.size(), whiteEntry, blackEntry, eventEntry, annotatorEntry, tags, provider, m_db->m_namebases); return state; }
save::State DatabaseCodec::updateCharacteristics(unsigned index, TagSet const& tags) { //M_REQUIRE(isOpen()); typedef Namebase::PlayerEntry* Player; typedef Namebase::EventEntry* Event; typedef Namebase::SiteEntry* Site; typedef Namebase::Entry* Entry; GameInfo* info = m_db->m_gameInfoList[index]; *m_storedInfo = *info; info->resetCharacteristics(m_db->m_namebases); unsigned maxAnnotatorCount = this->maxAnnotatorCount(); unsigned maxPlayerCount = this->maxPlayerCount(); InfoData data(tags); Player whiteEntry = namebase(Namebase::Player).insertPlayer( tags.value(tag::White), data.whiteCountry, data.whiteTitle, data.whiteType, data.whiteSex, data.whiteFideID, maxPlayerCount); Player blackEntry = namebase(Namebase::Player).insertPlayer( tags.value(tag::Black), data.blackCountry, data.blackTitle, data.blackType, data.blackSex, data.blackFideID, maxPlayerCount); Site siteEntry = namebase(Namebase::Site).insertSite( tags.value(tag::Site), data.eventCountry, maxSiteCount()); Event eventEntry = namebase(Namebase::Event).insertEvent( tags.value(tag::Event), data.eventDate, data.eventType, data.timeMode, data.eventMode, maxEventCount(), siteEntry ? siteEntry : NamebaseEvent::emptySite()); Entry annotatorEntry = NamebaseEntry::emptyEntry(); if (maxAnnotatorCount) { annotatorEntry = namebase(Namebase::Annotator). insert(tags.value(tag::Annotator), maxAnnotatorCount); } bool failed = whiteEntry == 0 || blackEntry == 0 || eventEntry == 0 || siteEntry == 0 || annotatorEntry == 0; save::State state = save::Ok; if (!failed && format() != format::Scidb) { } if (failed) { info->restore(*m_storedInfo, m_db->m_namebases); namebases().update(); if (!whiteEntry) return save::TooManyPlayerNames; if (!blackEntry) return save::TooManyPlayerNames; if (!eventEntry) return save::TooManyEventNames; if (!siteEntry) return save::TooManySiteNames; return save::TooManyAnnotatorNames; } info->update( whiteEntry, blackEntry, eventEntry, annotatorEntry, tags, m_db->m_namebases); return state; }