示例#1
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;
}