예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #4
0
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));
}
예제 #5
0
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;
}
예제 #6
0
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;
}