<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
	if(!_player->IsInWorld()) return;
	typedef std::list<Aura*> AuraList;

	Player* p_User = GetPlayer();
	sLog.outDetail("WORLD: got use Item packet, data length = %i",recvPacket.size());
	int8 tmp1,slot,tmp3;
	uint64 item_guid;
	uint8 cn;
	uint32 spellId = 0;

	recvPacket >> tmp1 >> slot >> tmp3 >> cn >> item_guid;
	Item* tmpItem = NULL;
	tmpItem = p_User->GetItemInterface()->GetInventoryItem(tmp1,slot);
	if (!tmpItem)
		tmpItem = p_User->GetItemInterface()->GetInventoryItem(slot);
	if (!tmpItem)
		return;
	ItemPrototype *itemProto = tmpItem->GetProto();
	if(!itemProto)
		return;

	if(_player->getDeathState()==CORPSE)
		return;

	if(itemProto->Bonding == ITEM_BIND_ON_USE)
		tmpItem->SoulBind();

	if(sScriptMgr.CallScriptedItem(tmpItem,_player))
		return;

	if(itemProto->QuestId)
	{
		// Item Starter
		Quest *qst = QuestStorage.LookupEntry(itemProto->QuestId);
		if(!qst)
			return;

		WorldPacket data;
		sQuestMgr.BuildQuestDetails(&data, qst, tmpItem, 0, language, _player);
		SendPacket(&data);
	}

	SpellCastTargets targets(recvPacket, _player->GetGUID());
	uint32 x;
	for(x = 0; x < 5; x++)
	{
		if(itemProto->Spells[x].Trigger == USE)
		{
			if(itemProto->Spells[x].Id)
			{
				spellId = itemProto->Spells[x].Id;
				break;
			}
		}
	}
	if(!spellId)
		return;
	// check for spell id
	SpellEntry *spellInfo = dbcSpell.LookupEntryForced( spellId );

	if ( !spellInfo || !sHookInterface.OnCastSpell( _player, spellInfo ) )
	{
		sLog.outError("WORLD: unknown spell id %i\n", spellId);
		return;
	}

	if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP)
	{
		if (p_User->CombatStatus.IsInCombat() || p_User->IsMounted())
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_CANT_DO_IN_COMBAT);
			return;
		}
		if(p_User->GetStandState()!=1)
		p_User->SetStandState(STANDSTATE_SIT);
		// loop through the auras and removing existing eating spells
	}

	// ceberwow remove stealth on using item
	if (!(spellInfo->AuraInterruptFlags & ATTRIBUTESEX_NOT_BREAK_STEALTH))
	{
		if( p_User->IsStealth() )
			p_User->RemoveAllAuraType( SPELL_AURA_MOD_STEALTH );
	}

	if(itemProto->RequiredLevel)
	{
		if(_player->getLevel() < itemProto->RequiredLevel)
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}
	}

	if(itemProto->RequiredSkill)
	{
		if(!_player->_HasSkillLine(itemProto->RequiredSkill))
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}

		if(itemProto->RequiredSkillRank)
		{
			if(_player->_GetSkillLineCurrent(itemProto->RequiredSkill, false) < itemProto->RequiredSkillRank)
			{
				_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
				return;
			}
		}
	}

	if( itemProto->AllowableClass && !(_player->getClassMask() & itemProto->AllowableClass) || itemProto->AllowableRace && !(_player->getRaceMask() & itemProto->AllowableRace) )
	{
		_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_YOU_CAN_NEVER_USE_THAT_ITEM);
		return;
	}

	if( !_player->Cooldown_CanCast( itemProto, x ) )
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_NOT_READY, cn, 0);
		return;
	}

	if(_player->m_currentSpell)
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
		return;
	}

	if( itemProto->ForcedPetId >= 0 )
	{
		if( itemProto->ForcedPetId == 0 )
		{
			if( _player->GetGUID() != targets.m_unitTarget )
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_BAD_TARGETS, cn, 0);
				return;
			}
		}
		else
		{
			if( !_player->GetSummon() || _player->GetSummon()->GetEntry() != (uint32)itemProto->ForcedPetId )
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
				return;
			}
		}
	}

	Spell *spell = SpellPool.PooledNew();
	spell->Init(_player, spellInfo, false, NULL);
	uint8 result;
	spell->extra_cast_number=cn;
	spell->i_caster = tmpItem;
	//GetPlayer()->setCurrentSpell(spell);
	result = spell->prepare(&targets);

	//if( result == SPELL_CANCAST_OK ) // incorrect - should be on Completed Cast
	//	_player->Cooldown_AddItem( itemProto, x );
}

void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
	if(!_player->IsInWorld()) return;
	if(_player->getDeathState()==CORPSE)
		return;

	uint32 spellId;
	uint8 cn;

	recvPacket >> spellId >> cn;
	// check for spell id
	SpellEntry *spellInfo = dbcSpell.LookupEntryForced(spellId );

	if(!spellInfo || !sHookInterface.OnCastSpell(_player, spellInfo))
	{
		sLog.outError("WORLD: unknown spell id %i\n", spellId);
		return;
	}

	if (spellInfo->Attributes & ATTRIBUTES_NO_CAST)
	{
		sLog.outError("WORLD: attempt to cast spell %i, %s which has ATTRIBUTES_NO_CAST\n", spellId, spellInfo->Name);
		return;
	}

	sLog.outDetail("WORLD: got cast spell packet, spellId - %i (%s), data length = %i",
		spellId, spellInfo->Name, recvPacket.size());

	// Cheat Detection only if player and not from an item
	// this could fuck up things but meh it's needed ALOT of the newbs are using WPE now
	// WPE allows them to mod the outgoing packet and basicly choose what ever spell they want :(

	if( !GetPlayer()->HasSpell(spellId) || spellInfo->Attributes & ATTRIBUTES_PASSIVE )
	{
		sLog.outDetail("WORLD: Spell isn't casted because player \"%s\" is cheating", GetPlayer()->GetName());
		return;
	}

	if (GetPlayer()->GetOnMeleeSpell() != spellId)
	{
		//autoshot 75
		if((spellInfo->AttributesExB & FLAGS3_ACTIVATE_AUTO_SHOT) /*spellInfo->Attributes == 327698*/)	// auto shot..
		{
			//sLog.outString( "HandleSpellCast: Auto Shot-type spell cast (id %u, name %s)" , spellInfo->Id , spellInfo->Name );
			Item *weapon = GetPlayer()->GetItemInterface()->GetInventoryItem(EQUIPMENT_SLOT_RANGED);
			if(!weapon)
				return;
			uint32 spellid;
			switch(weapon->GetProto()->SubClass)
			{
			case 2:			 // bows
			case 3:			 // guns
            case 18:		 // crossbow
				spellid = SPELL_RANGED_GENERAL;
				break;
			case 16:			// thrown
				spellid = SPELL_RANGED_THROW;
				break;
			case 19:			// wands
				spellid = SPELL_RANGED_WAND;
				break;
			default:
				spellid = 0;
				break;
			}

			if(!spellid)
				spellid = spellInfo->Id;

			if(!_player->m_onAutoShot)
			{
				_player->m_AutoShotTarget = _player->GetSelection();
				uint32 duration = _player->GetUInt32Value(UNIT_FIELD_RANGEDATTACKTIME);
				SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID());
				if(!targets.m_unitTarget)
				{
					sLog.outString( "Cancelling auto-shot cast because targets.m_unitTarget is null!" );
					return;
				}
				SpellEntry *sp = dbcSpell.LookupEntry(spellid);

				_player->m_AutoShotSpell = sp;
				_player->m_AutoShotDuration = duration;
				//This will fix fast clicks
				if(_player->m_AutoShotAttackTimer < 500)
					_player->m_AutoShotAttackTimer = 500;
				_player->m_onAutoShot = true;
			}

			return;
		}
		/*const char * name = sSpellStore.LookupString(spellInfo->Name);
		if(name)
			sChatHandler.SystemMessageToPlr(_player, "%sSpell Cast:%s %s %s[Group %u, family %u]", MSG_COLOR_LIGHTBLUE,
			MSG_COLOR_SUBWHITE, name, MSG_COLOR_YELLOW, spellInfo->SpellGroupType, spellInfo->SpellFamilyName);*/

        if(_player->m_currentSpell)
        {
			if( _player->m_currentSpell->getState() == SPELL_STATE_CASTING )
			{
				// cancel the existing channel spell, cast this one
				_player->m_currentSpell->cancel();
			}
			else
			{
				// send the error message
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
				return;
			}
        }

		SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID());

		// some anticheat stuff
		if( spellInfo->self_cast_only )
		{
			if( targets.m_unitTarget && targets.m_unitTarget != _player->GetGUID() )
			{
				// send the error message
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_BAD_TARGETS, cn, 0);
				return;
			}
		}

		Spell *spell = SpellPool.PooledNew();
		spell->Init(GetPlayer(), spellInfo, false, NULL);
		spell->extra_cast_number=cn;
		spell->prepare(&targets);
	}
}

void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
{
	uint32 spellId;
	recvPacket >> spellId;

	if(GetPlayer()->m_currentSpell)
		GetPlayer()->m_currentSpell->cancel();
}

void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket )
{
	uint32 spellId;
	recvPacket >> spellId;

	if( _player->m_currentSpell && _player->m_currentSpell->GetProto()->Id == spellId )
		_player->m_currentSpell->cancel();
	else
		_player->RemoveAura( spellId );

	sLog.outDebug("removing aura %u",spellId);
}

void WorldSession::HandleCancelChannellingOpcode( WorldPacket& recvPacket)
{
	uint32 spellId;
	recvPacket >> spellId;

	Player *plyr = GetPlayer();
	if(!plyr)
		return;
	if(plyr->m_currentSpell)
	{
		plyr->m_currentSpell->cancel();
	}
}

void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& recv_data)
{
	//sLog.outString("Received CMSG_CANCEL_AUTO_REPEAT_SPELL message.");
	//on original we automatically enter combat when creature got close to us
//	GetPlayer()->GetSession()->OutPacket(SMSG_CANCEL_COMBAT);
	GetPlayer()->m_onAutoShot = false;
}

void WorldSession::HandleAddDynamicTargetOpcode(WorldPacket & recvPacket)
{
	uint64 guid;
	uint32 spellid;
	uint32 flags;
	recvPacket >> guid >> spellid >> flags;

	SpellEntry * sp = dbcSpell.LookupEntryForced(spellid);
	if ( !sp )
		return;
	// Summoned Elemental's Freeze
    if (spellid == 33395)
    {
        if (!_player->m_Summon)
            return;
    }
    else if ( guid != _player->m_CurrentCharm )
    {
        return;
    }

	/* burlex: this is.. strange */
	SpellCastTargets targets;
	targets.m_targetMask = flags;

	if(flags == 0)
		targets.m_unitTarget = guid;
	else if(flags & TARGET_FLAG_UNIT)
	{
		WoWGuid guid;
//		recvPacket >> flags;		// skip one byte
		recvPacket >> guid;
		targets.m_unitTarget = guid.GetOldGuid();
	}
	else if(flags & TARGET_FLAG_SOURCE_LOCATION)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_srcX >> targets.m_srcY >> targets.m_srcZ;
	}
	else if(flags & TARGET_FLAG_DEST_LOCATION)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_destX >> targets.m_destY >> targets.m_destZ;
	}
	else if (flags & TARGET_FLAG_STRING)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_strTarget;
	}
	if(spellid == 33395)	// Summoned Water Elemental's freeze
	{
		Spell * pSpell = SpellPool.PooledNew();
		pSpell->Init(_player->m_Summon, sp, false, 0);
		pSpell->prepare(&targets);
	}
	else			// trinket?
	{
		Unit *nc = _player->GetMapMgr()->GetUnit( _player->m_CurrentCharm );
		if( nc )
		{
			Spell * pSpell = SpellPool.PooledNew();
			pSpell->Init(nc, sp, false, 0);
			pSpell->prepare(&targets);
		}
	}
}
<commit_msg>Commeted the ATTRIBUTES_NO_CAST check since it breaks capturing flags at arathi basin<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
	if(!_player->IsInWorld()) return;
	typedef std::list<Aura*> AuraList;

	Player* p_User = GetPlayer();
	sLog.outDetail("WORLD: got use Item packet, data length = %i",recvPacket.size());
	int8 tmp1,slot,tmp3;
	uint64 item_guid;
	uint8 cn;
	uint32 spellId = 0;

	recvPacket >> tmp1 >> slot >> tmp3 >> cn >> item_guid;
	Item* tmpItem = NULL;
	tmpItem = p_User->GetItemInterface()->GetInventoryItem(tmp1,slot);
	if (!tmpItem)
		tmpItem = p_User->GetItemInterface()->GetInventoryItem(slot);
	if (!tmpItem)
		return;
	ItemPrototype *itemProto = tmpItem->GetProto();
	if(!itemProto)
		return;

	if(_player->getDeathState()==CORPSE)
		return;

	if(itemProto->Bonding == ITEM_BIND_ON_USE)
		tmpItem->SoulBind();

	if(sScriptMgr.CallScriptedItem(tmpItem,_player))
		return;

	if(itemProto->QuestId)
	{
		// Item Starter
		Quest *qst = QuestStorage.LookupEntry(itemProto->QuestId);
		if(!qst)
			return;

		WorldPacket data;
		sQuestMgr.BuildQuestDetails(&data, qst, tmpItem, 0, language, _player);
		SendPacket(&data);
	}

	SpellCastTargets targets(recvPacket, _player->GetGUID());
	uint32 x;
	for(x = 0; x < 5; x++)
	{
		if(itemProto->Spells[x].Trigger == USE)
		{
			if(itemProto->Spells[x].Id)
			{
				spellId = itemProto->Spells[x].Id;
				break;
			}
		}
	}
	if(!spellId)
		return;
	// check for spell id
	SpellEntry *spellInfo = dbcSpell.LookupEntryForced( spellId );

	if ( !spellInfo || !sHookInterface.OnCastSpell( _player, spellInfo ) )
	{
		sLog.outError("WORLD: unknown spell id %i\n", spellId);
		return;
	}

	if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP)
	{
		if (p_User->CombatStatus.IsInCombat() || p_User->IsMounted())
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_CANT_DO_IN_COMBAT);
			return;
		}
		if(p_User->GetStandState()!=1)
		p_User->SetStandState(STANDSTATE_SIT);
		// loop through the auras and removing existing eating spells
	}

	// ceberwow remove stealth on using item
	if (!(spellInfo->AuraInterruptFlags & ATTRIBUTESEX_NOT_BREAK_STEALTH))
	{
		if( p_User->IsStealth() )
			p_User->RemoveAllAuraType( SPELL_AURA_MOD_STEALTH );
	}

	if(itemProto->RequiredLevel)
	{
		if(_player->getLevel() < itemProto->RequiredLevel)
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}
	}

	if(itemProto->RequiredSkill)
	{
		if(!_player->_HasSkillLine(itemProto->RequiredSkill))
		{
			_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
			return;
		}

		if(itemProto->RequiredSkillRank)
		{
			if(_player->_GetSkillLineCurrent(itemProto->RequiredSkill, false) < itemProto->RequiredSkillRank)
			{
				_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_ITEM_RANK_NOT_ENOUGH);
				return;
			}
		}
	}

	if( itemProto->AllowableClass && !(_player->getClassMask() & itemProto->AllowableClass) || itemProto->AllowableRace && !(_player->getRaceMask() & itemProto->AllowableRace) )
	{
		_player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_YOU_CAN_NEVER_USE_THAT_ITEM);
		return;
	}

	if( !_player->Cooldown_CanCast( itemProto, x ) )
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_NOT_READY, cn, 0);
		return;
	}

	if(_player->m_currentSpell)
	{
		_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
		return;
	}

	if( itemProto->ForcedPetId >= 0 )
	{
		if( itemProto->ForcedPetId == 0 )
		{
			if( _player->GetGUID() != targets.m_unitTarget )
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_BAD_TARGETS, cn, 0);
				return;
			}
		}
		else
		{
			if( !_player->GetSummon() || _player->GetSummon()->GetEntry() != (uint32)itemProto->ForcedPetId )
			{
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
				return;
			}
		}
	}

	Spell *spell = SpellPool.PooledNew();
	spell->Init(_player, spellInfo, false, NULL);
	uint8 result;
	spell->extra_cast_number=cn;
	spell->i_caster = tmpItem;
	//GetPlayer()->setCurrentSpell(spell);
	result = spell->prepare(&targets);

	//if( result == SPELL_CANCAST_OK ) // incorrect - should be on Completed Cast
	//	_player->Cooldown_AddItem( itemProto, x );
}

void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
	if(!_player->IsInWorld()) return;
	if(_player->getDeathState()==CORPSE)
		return;

	uint32 spellId;
	uint8 cn;

	recvPacket >> spellId >> cn;
	// check for spell id
	SpellEntry *spellInfo = dbcSpell.LookupEntryForced(spellId );

	if(!spellInfo || !sHookInterface.OnCastSpell(_player, spellInfo))
	{
		sLog.outError("WORLD: unknown spell id %i\n", spellId);
		return;
	}

/*  this is breaks capturing flags at arathi basin (marcelo)
	if (spellInfo->Attributes & ATTRIBUTES_NO_CAST)
	{
		sLog.outError("WORLD: attempt to cast spell %i, %s which has ATTRIBUTES_NO_CAST\n", spellId, spellInfo->Name);
		return;
	}*/

	sLog.outDetail("WORLD: got cast spell packet, spellId - %i (%s), data length = %i",
		spellId, spellInfo->Name, recvPacket.size());

	// Cheat Detection only if player and not from an item
	// this could fuck up things but meh it's needed ALOT of the newbs are using WPE now
	// WPE allows them to mod the outgoing packet and basicly choose what ever spell they want :(

	if( !GetPlayer()->HasSpell(spellId) || spellInfo->Attributes & ATTRIBUTES_PASSIVE )
	{
		sLog.outDetail("WORLD: Spell isn't casted because player \"%s\" is cheating", GetPlayer()->GetName());
		return;
	}

	if (GetPlayer()->GetOnMeleeSpell() != spellId)
	{
		//autoshot 75
		if((spellInfo->AttributesExB & FLAGS3_ACTIVATE_AUTO_SHOT) /*spellInfo->Attributes == 327698*/)	// auto shot..
		{
			//sLog.outString( "HandleSpellCast: Auto Shot-type spell cast (id %u, name %s)" , spellInfo->Id , spellInfo->Name );
			Item *weapon = GetPlayer()->GetItemInterface()->GetInventoryItem(EQUIPMENT_SLOT_RANGED);
			if(!weapon)
				return;
			uint32 spellid;
			switch(weapon->GetProto()->SubClass)
			{
			case 2:			 // bows
			case 3:			 // guns
            case 18:		 // crossbow
				spellid = SPELL_RANGED_GENERAL;
				break;
			case 16:			// thrown
				spellid = SPELL_RANGED_THROW;
				break;
			case 19:			// wands
				spellid = SPELL_RANGED_WAND;
				break;
			default:
				spellid = 0;
				break;
			}

			if(!spellid)
				spellid = spellInfo->Id;

			if(!_player->m_onAutoShot)
			{
				_player->m_AutoShotTarget = _player->GetSelection();
				uint32 duration = _player->GetUInt32Value(UNIT_FIELD_RANGEDATTACKTIME);
				SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID());
				if(!targets.m_unitTarget)
				{
					sLog.outString( "Cancelling auto-shot cast because targets.m_unitTarget is null!" );
					return;
				}
				SpellEntry *sp = dbcSpell.LookupEntry(spellid);

				_player->m_AutoShotSpell = sp;
				_player->m_AutoShotDuration = duration;
				//This will fix fast clicks
				if(_player->m_AutoShotAttackTimer < 500)
					_player->m_AutoShotAttackTimer = 500;
				_player->m_onAutoShot = true;
			}

			return;
		}
		/*const char * name = sSpellStore.LookupString(spellInfo->Name);
		if(name)
			sChatHandler.SystemMessageToPlr(_player, "%sSpell Cast:%s %s %s[Group %u, family %u]", MSG_COLOR_LIGHTBLUE,
			MSG_COLOR_SUBWHITE, name, MSG_COLOR_YELLOW, spellInfo->SpellGroupType, spellInfo->SpellFamilyName);*/

        if(_player->m_currentSpell)
        {
			if( _player->m_currentSpell->getState() == SPELL_STATE_CASTING )
			{
				// cancel the existing channel spell, cast this one
				_player->m_currentSpell->cancel();
			}
			else
			{
				// send the error message
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, cn, 0);
				return;
			}
        }

		SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID());

		// some anticheat stuff
		if( spellInfo->self_cast_only )
		{
			if( targets.m_unitTarget && targets.m_unitTarget != _player->GetGUID() )
			{
				// send the error message
				_player->SendCastResult(spellInfo->Id, SPELL_FAILED_BAD_TARGETS, cn, 0);
				return;
			}
		}

		Spell *spell = SpellPool.PooledNew();
		spell->Init(GetPlayer(), spellInfo, false, NULL);
		spell->extra_cast_number=cn;
		spell->prepare(&targets);
	}
}

void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
{
	uint32 spellId;
	recvPacket >> spellId;

	if(GetPlayer()->m_currentSpell)
		GetPlayer()->m_currentSpell->cancel();
}

void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket )
{
	uint32 spellId;
	recvPacket >> spellId;

	if( _player->m_currentSpell && _player->m_currentSpell->GetProto()->Id == spellId )
		_player->m_currentSpell->cancel();
	else
		_player->RemoveAura( spellId );

	sLog.outDebug("removing aura %u",spellId);
}

void WorldSession::HandleCancelChannellingOpcode( WorldPacket& recvPacket)
{
	uint32 spellId;
	recvPacket >> spellId;

	Player *plyr = GetPlayer();
	if(!plyr)
		return;
	if(plyr->m_currentSpell)
	{
		plyr->m_currentSpell->cancel();
	}
}

void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& recv_data)
{
	//sLog.outString("Received CMSG_CANCEL_AUTO_REPEAT_SPELL message.");
	//on original we automatically enter combat when creature got close to us
//	GetPlayer()->GetSession()->OutPacket(SMSG_CANCEL_COMBAT);
	GetPlayer()->m_onAutoShot = false;
}

void WorldSession::HandleAddDynamicTargetOpcode(WorldPacket & recvPacket)
{
	uint64 guid;
	uint32 spellid;
	uint32 flags;
	recvPacket >> guid >> spellid >> flags;

	SpellEntry * sp = dbcSpell.LookupEntryForced(spellid);
	if ( !sp )
		return;
	// Summoned Elemental's Freeze
    if (spellid == 33395)
    {
        if (!_player->m_Summon)
            return;
    }
    else if ( guid != _player->m_CurrentCharm )
    {
        return;
    }

	/* burlex: this is.. strange */
	SpellCastTargets targets;
	targets.m_targetMask = flags;

	if(flags == 0)
		targets.m_unitTarget = guid;
	else if(flags & TARGET_FLAG_UNIT)
	{
		WoWGuid guid;
//		recvPacket >> flags;		// skip one byte
		recvPacket >> guid;
		targets.m_unitTarget = guid.GetOldGuid();
	}
	else if(flags & TARGET_FLAG_SOURCE_LOCATION)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_srcX >> targets.m_srcY >> targets.m_srcZ;
	}
	else if(flags & TARGET_FLAG_DEST_LOCATION)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_destX >> targets.m_destY >> targets.m_destZ;
	}
	else if (flags & TARGET_FLAG_STRING)
	{
//		recvPacket >> flags;		// skip one byte
		recvPacket >> targets.m_strTarget;
	}
	if(spellid == 33395)	// Summoned Water Elemental's freeze
	{
		Spell * pSpell = SpellPool.PooledNew();
		pSpell->Init(_player->m_Summon, sp, false, 0);
		pSpell->prepare(&targets);
	}
	else			// trinket?
	{
		Unit *nc = _player->GetMapMgr()->GetUnit( _player->m_CurrentCharm );
		if( nc )
		{
			Spell * pSpell = SpellPool.PooledNew();
			pSpell->Init(nc, sp, false, 0);
			pSpell->prepare(&targets);
		}
	}
}
<|endoftext|>


<commit_before>/*! \brief Very simple HTTP server. Everything's done for you.
 *
 * It just serves static pages.
 */
#include <x0/http/HttpServer.h>
#include <x0/flow/FlowRunner.h>
#include <iostream>
#include <fstream>
#include <memory>
#include <ev++.h>

class MyServer {
private:
	struct ev_loop* loop_;
	ev::sig sigterm_;
	std::unique_ptr<x0::HttpServer> http_;

public:
	MyServer() :
		loop_(ev_default_loop()),
		sigterm_(loop_),
		http_()
	{
	}

	~MyServer()
	{
		if (sigterm_.is_active()) {
			ev_ref(loop_);
			sigterm_.stop();
		}
	}

	bool requestHandler(x0::HttpRequest* r)
	{
		r->status = x0::HttpStatus::ServiceUnavailable;
		r->finish();
	}

	int run()
	{
		std::clog << "Initializing ..." << std::endl;
		sigterm_.set<MyServer, &MyServer::terminate_handler>(this);
		sigterm_.start(SIGTERM);
		ev_unref(loop_);

		http_.reset(x0::HttpServer(loop_));
		http_->requestHandler = std::bind(MyServer::requestHandler, this, std::placeholders::_1);

		std::clog << "Running ..." << std::endl;
		int rv = http_->run();

		std::clog << "Quitting ..." << std::endl;
		return rv;
	}

private:
	void terminate_handler(ev::sig& sig, int)
	{
		std::clog << "Terminate signal received ..." << std::endl;

		ev_ref(loop_);
		sig.stop();

		http_->stop();
	}
};

int main(int argc, const char *argv[])
{
	MyServer s;
	return s.run();
}
<commit_msg>examples: app1 fixes<commit_after>/*! \brief Very simple HTTP server. Everything's done for you.
 *
 * It just serves static pages.
 */
#include <x0/http/HttpServer.h>
#include <x0/http/HttpRequest.h>
#include <x0/io/BufferSource.h>
#include <iostream>
#include <fstream>
#include <memory>
#include <ev++.h>

class MyServer {
private:
	struct ev_loop* loop_;
	ev::sig sigterm_;
	std::unique_ptr<x0::HttpServer> http_;

public:
	MyServer() :
		loop_(ev_default_loop()),
		sigterm_(loop_),
		http_()
	{
	}

	~MyServer()
	{
		if (sigterm_.is_active()) {
			ev_ref(loop_);
			sigterm_.stop();
		}
	}

	bool requestHandler(x0::HttpRequest* r)
	{
		x0::Buffer body;
		body.push_back("Hello, World\n");

		r->status = x0::HttpStatus::ServiceUnavailable;
		r->responseHeaders.push_back("Content-Type", "text/plain");
		r->write<x0::BufferSource>(body);
		r->finish();

		return true;
	}

	int run()
	{
		std::clog << "Initializing ..." << std::endl;
		sigterm_.set<MyServer, &MyServer::terminate_handler>(this);
		sigterm_.start(SIGTERM);
		ev_unref(loop_);

		http_.reset(new x0::HttpServer(loop_));
		http_->requestHandler = std::bind(&MyServer::requestHandler, this, std::placeholders::_1);
		http_->setupListener("0.0.0.0", 3000);

		std::clog << "Running ..." << std::endl;
		int rv = http_->run();

		std::clog << "Quitting ..." << std::endl;
		return rv;
	}

private:
	void terminate_handler(ev::sig& sig, int)
	{
		std::clog << "Terminate signal received ..." << std::endl;

		ev_ref(loop_);
		sig.stop();

		http_->stop();
	}
};

int main(int argc, const char *argv[])
{
	MyServer s;
	return s.run();
}
<|endoftext|>


<commit_before>#include <stingray/toolkit/SystemException.h>

#include <errno.h>
#include <string.h>

#include <stingray/toolkit/StringUtils.h>

namespace stingray
{
	SystemException::SystemException(const std::string &message) throw():
		std::runtime_error(message + ": errno = " + ErrnoToStr(errno) + " (" + GetErrorMessage(errno) + ")") {}

	SystemException::SystemException(const std::string &message, int err) throw():
		std::runtime_error(message + ": errno = " + ErrnoToStr(err) + " (" + strerror(err) + ")") {}

	std::string SystemException::GetErrorMessage(int err) throw()
	{
		char buf[256];
		char *msg = strerror_r(err, buf, sizeof(buf));
		return msg? msg: "Unknown error";
	}

	std::string SystemException::GetErrorMessage() throw()
	{ return GetErrorMessage(errno); }

#define ERRNO_STR(val) case val: return #val
	std::string SystemException::ErrnoToStr(int e)
	{
		switch (e)
		{
		ERRNO_STR(EACCES);
		ERRNO_STR(EBUSY);
		ERRNO_STR(EFAULT);
		ERRNO_STR(EINVAL);
		ERRNO_STR(ELOOP);
		ERRNO_STR(EMFILE);
		ERRNO_STR(ENAMETOOLONG);
		ERRNO_STR(ENODEV);
		ERRNO_STR(ENOENT);
		ERRNO_STR(ENOMEM);
		ERRNO_STR(ENOTDIR);
		ERRNO_STR(ENXIO);
		ERRNO_STR(EPERM);
		default:
			return ToString(e);
		};
	}

#undef ERRNO_STR

}
<commit_msg>fixed non-default SystemException ctor<commit_after>#include <stingray/toolkit/SystemException.h>

#include <errno.h>
#include <string.h>

#include <stingray/toolkit/StringUtils.h>

namespace stingray
{
	SystemException::SystemException(const std::string &message) throw():
		std::runtime_error(message + ": errno = " + ErrnoToStr(errno) + " (" + GetErrorMessage(errno) + ")") {}

	SystemException::SystemException(const std::string &message, int err) throw():
		std::runtime_error(message + ": errno = " + ErrnoToStr(err) + " (" + GetErrorMessage(err) + ")") {}

	std::string SystemException::GetErrorMessage(int err) throw()
	{
		char buf[256];
		char *msg = strerror_r(err, buf, sizeof(buf));
		return msg? msg: "Unknown error";
	}

	std::string SystemException::GetErrorMessage() throw()
	{ return GetErrorMessage(errno); }

#define ERRNO_STR(val) case val: return #val
	std::string SystemException::ErrnoToStr(int e)
	{
		switch (e)
		{
		ERRNO_STR(EACCES);
		ERRNO_STR(EBUSY);
		ERRNO_STR(EFAULT);
		ERRNO_STR(EINVAL);
		ERRNO_STR(ELOOP);
		ERRNO_STR(EMFILE);
		ERRNO_STR(ENAMETOOLONG);
		ERRNO_STR(ENODEV);
		ERRNO_STR(ENOENT);
		ERRNO_STR(ENOMEM);
		ERRNO_STR(ENOTDIR);
		ERRNO_STR(ENXIO);
		ERRNO_STR(EPERM);
		default:
			return ToString(e);
		};
	}

#undef ERRNO_STR

}
<|endoftext|>


<commit_before>/*
 OFX TestOpenGL plugin.

 Copyright (C) 2015 INRIA

 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice, this
 list of conditions and the following disclaimer in the documentation and/or
 other materials provided with the distribution.

 Neither the name of the {organization} nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 INRIA
 Domaine de Voluceau
 Rocquencourt - B.P. 105
 78153 Le Chesnay Cedex - France

 */

#if defined(OFX_SUPPORTS_OPENGLRENDER) || defined(HAVE_OSMESA) // at least one is required for this plugin

#include "TestOpenGL.h"

#ifdef _WINDOWS
#include <windows.h>
#endif

#include "ofxsImageEffect.h"
#include "ofxsMacros.h"
#include "ofxOpenGLRender.h"

#define kPluginName "TestOpenGL"
#define kPluginGrouping "Other/Test"
#define kPluginDescription \
"Test OpenGL rendering.\n" \
"This plugin draws a 200x100 red square at (10,10)."

#define kPluginIdentifier "net.sf.openfx.TestOpenGL"
#define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
#define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.

#define kSupportsTiles 0
#define kSupportsMultiResolution 0
#define kSupportsRenderScale 1
#define kSupportsMultipleClipPARs false
#define kSupportsMultipleClipDepths false
#define kRenderThreadSafety eRenderFullySafe

#define kParamScale "scale"
#define kParamScaleLabel "Scale"
#define kParamScaleHint "Scales the red rect"

#define kParamSourceScale "sourceScale"
#define kParamSourceScaleLabel "Source Scale"
#define kParamSourceScaleHint "Scales the source image"

#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
#define kParamUseGPU "useGPUIfAvailable"
#define kParamUseGPULabel "Use GPU If Available"
#define kParamUseGPUHint "If GPU rendering is available, use it. If the checkbox is not available, GPU rendering is not available on this host."
#endif

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */

TestOpenGLPlugin::TestOpenGLPlugin(OfxImageEffectHandle handle)
: ImageEffect(handle)
, _dstClip(0)
, _srcClip(0)
, _scale(0)
, _sourceScale(0)
, _useGPUIfAvailable(0)
{
    _dstClip = fetchClip(kOfxImageEffectOutputClipName);
    assert(_dstClip && (_dstClip->getPixelComponents() == OFX::ePixelComponentRGBA ||
                        _dstClip->getPixelComponents() == OFX::ePixelComponentAlpha));
    _srcClip = getContext() == OFX::eContextGenerator ? NULL : fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert((!_srcClip && getContext() == OFX::eContextGenerator) ||
           (_srcClip && (_srcClip->getPixelComponents() == OFX::ePixelComponentRGBA ||
                         _srcClip->getPixelComponents() == OFX::ePixelComponentAlpha)));

    _scale = fetchDoubleParam(kParamScale);
    _sourceScale = fetchDoubleParam(kParamSourceScale);
    assert(_scale && _sourceScale);
#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    _useGPUIfAvailable = fetchBooleanParam(kParamUseGPU);
    assert(_useGPUIfAvailable);
    const OFX::ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (!gHostDescription.supportsOpenGLRender) {
        _useGPUIfAvailable->setEnabled(false);
    }
#endif

}

////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */

////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from

// the overridden render function
void
TestOpenGLPlugin::render(const OFX::RenderArguments &args)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }

    assert(kSupportsMultipleClipPARs   || !_srcClip || _srcClip->getPixelAspectRatio() == _dstClip->getPixelAspectRatio());
    assert(kSupportsMultipleClipDepths || !_srcClip || _srcClip->getPixelDepth()       == _dstClip->getPixelDepth());

    bool openGLRender = false;
#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    const OFX::ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (gHostDescription.supportsOpenGLRender) {
        _useGPUIfAvailable->getValueAtTime(args.time, openGLRender);
    }
#endif

    // do the rendering
#ifdef OFX_SUPPORTS_OPENGLRENDER
    if (openGLRender) {
        return renderGL(args);
    }
#endif
#ifdef HAVE_OSMESA
    if (!openGLRender) {
        return renderMesa(args);
    }
#endif // HAVE_OSMESA
    OFX::throwSuiteStatusException(kOfxStatFailed);
}

// overriding getRegionOfDefinition is necessary to tell the host that we do not support render scale
bool
TestOpenGLPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &/*rod*/)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }

    // use the default RoD
    return false;
}

void
TestOpenGLPlugin::getClipPreferences(OFX::ClipPreferencesSetter &clipPreferences)
{
    // We have to do this because the processing code does not support varying components for srcClip and dstClip
    // (The OFX spec doesn't state a default value for this)
    clipPreferences.setClipComponents(*_dstClip, _srcClip->getPixelComponents());
}

mDeclarePluginFactory(TestOpenGLPluginFactory, ;, {});

using namespace OFX;

void TestOpenGLPluginFactory::load()
{
    // we can't be used on hosts that don't support the stereoscopic suite
    // returning an error here causes a blank menu entry in Nuke
    //#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    //const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    //if (!gHostDescription.supportsOpenGLRender) {
    //    throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    //}
    //#endif
}

void
TestOpenGLPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // returning an error here crashes Nuke
    //#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    //const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    //if (!gHostDescription.supportsOpenGLRender) {
    //    throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    //}
    //#endif

    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts
    desc.addSupportedContext(eContextFilter);
    desc.addSupportedContext(eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(eBitDepthUByte);
    desc.addSupportedBitDepth(eBitDepthUShort);
    desc.addSupportedBitDepth(eBitDepthFloat);

    // set a few flags
    desc.setSingleInstance(false);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setSupportsTiles(kSupportsTiles);
    desc.setTemporalClipAccess(false);
    // We can render both fields in a fielded images in one hit if there is no animation
    // So set the flag that allows us to do this
    desc.setRenderTwiceAlways(false);
    desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
    // say we can support multiple pixel depths and let the clip preferences action deal with it all.
    desc.setSupportsMultipleClipDepths(kSupportsMultipleClipDepths);
    // we support OpenGL rendering (could also say "needed" here)
#ifdef OFX_SUPPORTS_OPENGLRENDER
#ifdef HAVE_MESA
    desc.setSupportsOpenGLRender(true);
#else
    desc.setNeedsOpenGLRender(true);
#endif
#endif
}

void
TestOpenGLPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum /*context*/)
{
#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (!gHostDescription.supportsOpenGLRender) {
        throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    }
#endif

    // Source clip only in the filter context
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->addSupportedComponent(ePixelComponentAlpha);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->addSupportedComponent(ePixelComponentAlpha);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make some pages and to things in
    PageParamDescriptor *page = desc.definePageParam("Controls");

    {
        OFX::DoubleParamDescriptor* param = desc.defineDoubleParam(kParamScale);
        param->setLabel(kParamScaleLabel);
        param->setHint(kParamScaleHint);
        // say we are a scaling parameter
        param->setDoubleType(eDoubleTypeScale);
        param->setDefault(1.);
        param->setRange(0., kOfxFlagInfiniteMax);
        param->setDisplayRange(0., 10.);
        param->setIncrement(0.01);
        if (page) {
            page->addChild(*param);
        }
    }

    {
        OFX::DoubleParamDescriptor* param = desc.defineDoubleParam(kParamSourceScale);
        param->setLabel(kParamSourceScaleLabel);
        param->setHint(kParamSourceScaleHint);
        // say we are a scaling parameter
        param->setDoubleType(eDoubleTypeScale);
        param->setDefault(1.);
        param->setRange(0., kOfxFlagInfiniteMax);
        param->setDisplayRange(0., 10.);
        param->setIncrement(0.01);
        if (page) {
            page->addChild(*param);
        }
    }

#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    {
        OFX::BooleanParamDescriptor* param = desc.defineBooleanParam(kParamUseGPU);
        param->setLabel(kParamUseGPULabel);
        param->setHint(kParamUseGPUHint);
        param->setDefault(true);
        if (page) {
            page->addChild(*param);
        }
    }
#endif
}

OFX::ImageEffect*
TestOpenGLPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum /*context*/)
{
    return new TestOpenGLPlugin(handle);
}

void getTestOpenGLPluginID(OFX::PluginFactoryArray &ids)
{
    static TestOpenGLPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}

#endif // OFX_SUPPORTS_OPENGLRENDER
<commit_msg>TestOpenGL: fix typo<commit_after>/*
 OFX TestOpenGL plugin.

 Copyright (C) 2015 INRIA

 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice, this
 list of conditions and the following disclaimer in the documentation and/or
 other materials provided with the distribution.

 Neither the name of the {organization} nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 INRIA
 Domaine de Voluceau
 Rocquencourt - B.P. 105
 78153 Le Chesnay Cedex - France

 */

#if defined(OFX_SUPPORTS_OPENGLRENDER) || defined(HAVE_OSMESA) // at least one is required for this plugin

#include "TestOpenGL.h"

#ifdef _WINDOWS
#include <windows.h>
#endif

#include "ofxsImageEffect.h"
#include "ofxsMacros.h"
#include "ofxOpenGLRender.h"

#define kPluginName "TestOpenGL"
#define kPluginGrouping "Other/Test"
#define kPluginDescription \
"Test OpenGL rendering.\n" \
"This plugin draws a 200x100 red square at (10,10)."

#define kPluginIdentifier "net.sf.openfx.TestOpenGL"
#define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
#define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.

#define kSupportsTiles 0
#define kSupportsMultiResolution 0
#define kSupportsRenderScale 1
#define kSupportsMultipleClipPARs false
#define kSupportsMultipleClipDepths false
#define kRenderThreadSafety eRenderFullySafe

#define kParamScale "scale"
#define kParamScaleLabel "Scale"
#define kParamScaleHint "Scales the red rect"

#define kParamSourceScale "sourceScale"
#define kParamSourceScaleLabel "Source Scale"
#define kParamSourceScaleHint "Scales the source image"

#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
#define kParamUseGPU "useGPUIfAvailable"
#define kParamUseGPULabel "Use GPU If Available"
#define kParamUseGPUHint "If GPU rendering is available, use it. If the checkbox is not enabled, GPU rendering is not available on this host."
#endif

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */

TestOpenGLPlugin::TestOpenGLPlugin(OfxImageEffectHandle handle)
: ImageEffect(handle)
, _dstClip(0)
, _srcClip(0)
, _scale(0)
, _sourceScale(0)
, _useGPUIfAvailable(0)
{
    _dstClip = fetchClip(kOfxImageEffectOutputClipName);
    assert(_dstClip && (_dstClip->getPixelComponents() == OFX::ePixelComponentRGBA ||
                        _dstClip->getPixelComponents() == OFX::ePixelComponentAlpha));
    _srcClip = getContext() == OFX::eContextGenerator ? NULL : fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert((!_srcClip && getContext() == OFX::eContextGenerator) ||
           (_srcClip && (_srcClip->getPixelComponents() == OFX::ePixelComponentRGBA ||
                         _srcClip->getPixelComponents() == OFX::ePixelComponentAlpha)));

    _scale = fetchDoubleParam(kParamScale);
    _sourceScale = fetchDoubleParam(kParamSourceScale);
    assert(_scale && _sourceScale);
#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    _useGPUIfAvailable = fetchBooleanParam(kParamUseGPU);
    assert(_useGPUIfAvailable);
    const OFX::ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (!gHostDescription.supportsOpenGLRender) {
        _useGPUIfAvailable->setEnabled(false);
    }
#endif

}

////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */

////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from

// the overridden render function
void
TestOpenGLPlugin::render(const OFX::RenderArguments &args)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }

    assert(kSupportsMultipleClipPARs   || !_srcClip || _srcClip->getPixelAspectRatio() == _dstClip->getPixelAspectRatio());
    assert(kSupportsMultipleClipDepths || !_srcClip || _srcClip->getPixelDepth()       == _dstClip->getPixelDepth());

    bool openGLRender = false;
#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    const OFX::ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (gHostDescription.supportsOpenGLRender) {
        _useGPUIfAvailable->getValueAtTime(args.time, openGLRender);
    }
#endif

    // do the rendering
#ifdef OFX_SUPPORTS_OPENGLRENDER
    if (openGLRender) {
        return renderGL(args);
    }
#endif
#ifdef HAVE_OSMESA
    if (!openGLRender) {
        return renderMesa(args);
    }
#endif // HAVE_OSMESA
    OFX::throwSuiteStatusException(kOfxStatFailed);
}

// overriding getRegionOfDefinition is necessary to tell the host that we do not support render scale
bool
TestOpenGLPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &/*rod*/)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }

    // use the default RoD
    return false;
}

void
TestOpenGLPlugin::getClipPreferences(OFX::ClipPreferencesSetter &clipPreferences)
{
    // We have to do this because the processing code does not support varying components for srcClip and dstClip
    // (The OFX spec doesn't state a default value for this)
    clipPreferences.setClipComponents(*_dstClip, _srcClip->getPixelComponents());
}

mDeclarePluginFactory(TestOpenGLPluginFactory, ;, {});

using namespace OFX;

void TestOpenGLPluginFactory::load()
{
    // we can't be used on hosts that don't support the stereoscopic suite
    // returning an error here causes a blank menu entry in Nuke
    //#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    //const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    //if (!gHostDescription.supportsOpenGLRender) {
    //    throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    //}
    //#endif
}

void
TestOpenGLPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // returning an error here crashes Nuke
    //#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    //const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    //if (!gHostDescription.supportsOpenGLRender) {
    //    throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    //}
    //#endif

    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts
    desc.addSupportedContext(eContextFilter);
    desc.addSupportedContext(eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(eBitDepthUByte);
    desc.addSupportedBitDepth(eBitDepthUShort);
    desc.addSupportedBitDepth(eBitDepthFloat);

    // set a few flags
    desc.setSingleInstance(false);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setSupportsTiles(kSupportsTiles);
    desc.setTemporalClipAccess(false);
    // We can render both fields in a fielded images in one hit if there is no animation
    // So set the flag that allows us to do this
    desc.setRenderTwiceAlways(false);
    desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
    // say we can support multiple pixel depths and let the clip preferences action deal with it all.
    desc.setSupportsMultipleClipDepths(kSupportsMultipleClipDepths);
    // we support OpenGL rendering (could also say "needed" here)
#ifdef OFX_SUPPORTS_OPENGLRENDER
#ifdef HAVE_MESA
    desc.setSupportsOpenGLRender(true);
#else
    desc.setNeedsOpenGLRender(true);
#endif
#endif
}

void
TestOpenGLPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum /*context*/)
{
#if defined(OFX_SUPPORTS_OPENGLRENDER) && !defined(HAVE_OSMESA)
    const ImageEffectHostDescription &gHostDescription = *OFX::getImageEffectHostDescription();
    if (!gHostDescription.supportsOpenGLRender) {
        throwHostMissingSuiteException(kOfxOpenGLRenderSuite);
    }
#endif

    // Source clip only in the filter context
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->addSupportedComponent(ePixelComponentAlpha);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->addSupportedComponent(ePixelComponentAlpha);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make some pages and to things in
    PageParamDescriptor *page = desc.definePageParam("Controls");

    {
        OFX::DoubleParamDescriptor* param = desc.defineDoubleParam(kParamScale);
        param->setLabel(kParamScaleLabel);
        param->setHint(kParamScaleHint);
        // say we are a scaling parameter
        param->setDoubleType(eDoubleTypeScale);
        param->setDefault(1.);
        param->setRange(0., kOfxFlagInfiniteMax);
        param->setDisplayRange(0., 10.);
        param->setIncrement(0.01);
        if (page) {
            page->addChild(*param);
        }
    }

    {
        OFX::DoubleParamDescriptor* param = desc.defineDoubleParam(kParamSourceScale);
        param->setLabel(kParamSourceScaleLabel);
        param->setHint(kParamSourceScaleHint);
        // say we are a scaling parameter
        param->setDoubleType(eDoubleTypeScale);
        param->setDefault(1.);
        param->setRange(0., kOfxFlagInfiniteMax);
        param->setDisplayRange(0., 10.);
        param->setIncrement(0.01);
        if (page) {
            page->addChild(*param);
        }
    }

#if defined(OFX_SUPPORTS_OPENGLRENDER) && defined(HAVE_OSMESA)
    {
        OFX::BooleanParamDescriptor* param = desc.defineBooleanParam(kParamUseGPU);
        param->setLabel(kParamUseGPULabel);
        param->setHint(kParamUseGPUHint);
        param->setDefault(true);
        if (page) {
            page->addChild(*param);
        }
    }
#endif
}

OFX::ImageEffect*
TestOpenGLPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum /*context*/)
{
    return new TestOpenGLPlugin(handle);
}

void getTestOpenGLPluginID(OFX::PluginFactoryArray &ids)
{
    static TestOpenGLPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}

#endif // OFX_SUPPORTS_OPENGLRENDER
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <iostream>
#include <strstream>
#include <stdio.h>
#include <direct.h>

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::cin;
	using std::endl;
	using std::ifstream;
	using std::ios_base;
	using std::ostrstream;
	using std::string;
#endif

// XERCES HEADERS...
//	Are included by HarnessInit.hpp

// XALAN HEADERS...
//	Are included by FileUtility.hpp

// HARNESS HEADERS...
#include <XMLFileReporter.hpp>
#include <FileUtility.hpp>
#include <HarnessInit.hpp>

#if defined(XALAN_NO_NAMESPACES)
	typedef map<XalanDOMString, XalanDOMString, less<XalanDOMString> >	Hashtable;
#else
	typedef std::map<XalanDOMString, XalanDOMString>  Hashtable;
#endif

// This is here for memory leak testing.
#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif

const char* const 	excludeStylesheets[] =
{
	"output22.xsl",
	0
};

FileUtility		futil;

void
printArgOptions()
{
	cerr << endl
		 << "conf dirname [-category -out -gold]"
		 << endl
		 << endl
		 << "dirname		(base directory for testcases)"
		 << endl
		 << "-category dirname (specific directory)"
		 << endl
		 << "-out dirname	(base directory for output)"
		 << endl
		 << "-gold dirname	(base directory for gold files)"
		 << endl;
}

bool
getParams(int argc,
		  const char*	argv[],
		  FileUtility& f,
		  XalanDOMString& baseDir,
		  XalanDOMString& outDir,
		  XalanDOMString& goldRoot,
		  XalanDOMString& category)
{
	bool fSuccess = true;	// Used to continue argument loop
	bool fsetOut = true;	// Set default output directory, set to false if data is provided
	bool fsetGold = true;	// Set default gold directory, set to false if data is provided

	// Insure that required "-base" argument is there.
	if (argc == 1 || argv[1][0] == '-')
	{
		printArgOptions();
		return false;
	}
	else
	{
		if (f.checkDir(pathSep + XalanDOMString(argv[1])))
		{
			assign(baseDir, XalanDOMString(argv[1]));
			insert(baseDir, 0, pathSep);
		}
		else
		{
			cout << endl << "Given base directory \"" << argv[1] << "\" does not exist" << endl;
			printArgOptions();
			return false;
		}
	}

	// Get the rest of the arguments in any order.
	for (int i = 2; i < argc && fSuccess == true; ++i)
	{
		if(!stricmp("-out", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(outDir, XalanDOMString(argv[i]));
				insert(outDir, 0, XalanDOMString("\\"));
				append(outDir, XalanDOMString("\\"));
				f.checkAndCreateDir(outDir);
				fsetOut = false;
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}
		else if(!stricmp("-gold", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(goldRoot, XalanDOMString(argv[i]));
				insert(goldRoot, 0, pathSep);
				fsetGold = false;
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}
		else if(!stricmp("-category", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(category, XalanDOMString(argv[i]));
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}

		else
		{
			printArgOptions();
			fSuccess = false;
		}

	} // End of for-loop

	// Do we need to set the default output directory??
	if (fsetOut)
	{
		unsigned int ii = lastIndexOf(baseDir,charAt(pathSep,0));
		outDir = substring(baseDir, 0, ii+1);
		append(outDir,XalanDOMString("CONF-results"));
		f.checkAndCreateDir(outDir);
		append(outDir,pathSep);
	}
	if (fsetGold)
	{
		goldRoot = baseDir;
		append(goldRoot,XalanDOMString("-gold"));
		f.checkAndCreateDir(goldRoot);
		//append(goldRoot,pathSep);
	}

	// Add the path seperator to the end of the base directory
	// here after we've finished using it for all directory creation.

	append(baseDir,pathSep);
	append(goldRoot,pathSep);
	return fSuccess;
}

inline bool
checkForExclusion(XalanDOMString currentFile)
{
	for (int i=0; excludeStylesheets[i] != 0; i++)
	{
		if (equals(currentFile, XalanDOMString(excludeStylesheets[i])))
		{
			return true;
		}
	}

	return false;
}

int
main(
	 int			argc,
	 const char*	argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	Hashtable runAttrs;	// Attribute lists for conformance testing.

	XalanDOMString  category;	// Test all of base dir by default
	XalanDOMString  baseDir, outputRoot, goldRoot;

	if (getParams(argc, argv, futil, baseDir, outputRoot, goldRoot, category) == true)
	{
		// Call the static initializers for xerces and xalan, and create a transformer
		HarnessInit xmlPlatformUtils;
		XalanTransformer::initialize();
		XalanTransformer xalan;

		// Generate Unique Run id and processor info
		const XalanDOMString& UniqRunid = futil.generateUniqRunid();

		// Defined basic constants for file manipulation and open results file
		const XalanDOMString  drive(futil.getDrive());
		const XalanDOMString  resultFilePrefix("cpp");
		const XalanDOMString  resultsFile(drive + outputRoot + resultFilePrefix + UniqRunid + XMLSuffix);

		XMLFileReporter	logFile(resultsFile);
		logFile.logTestFileInit("Conformance Testing:");

		// Get the list of Directories that are below conf
		const FileNameVectorType	dirs = futil.getDirectoryNames(baseDir);

		for(FileNameVectorType::size_type	j = 0; j < dirs.size(); ++j)
		{
			const XalanDOMString currentDir(dirs[j]);

			// Run specific category of files from given directory
			if (length(category) > 0 && !equals(currentDir, category))
			{
				continue;
			}

			// Check that output directory is there.
			const XalanDOMString  theOutputDir = outputRoot + currentDir;
			futil.checkAndCreateDir(theOutputDir);

			// Get the files found in the test directory
			const FileNameVectorType files = futil.getTestFileNames(baseDir, currentDir, true);

			logFile.logTestCaseInit(currentDir);

			for(FileNameVectorType::size_type i = 0; i < files.size(); i++)
			{
				Hashtable attrs;
				const XalanDOMString currentFile(files[i]);
				futil.data.testOrFile = currentFile;

				if (checkForExclusion(currentFile))
					continue;

				const XalanDOMString  theXSLFile = baseDir + currentDir + pathSep + currentFile;
				const XalanDOMString  theXMLFile = futil.generateFileName(theXSLFile,"xml");
				futil.data.xmlFileURL = theXMLFile;
				futil.data.xslFileURL = theXSLFile;
				futil.data.testBase = baseDir;

				XalanDOMString  theGoldFile = goldRoot + currentDir + pathSep + currentFile;
				theGoldFile = futil.generateFileName(theGoldFile, "out");

				const XalanDOMString  outbase =  outputRoot + currentDir + pathSep + currentFile;
				const XalanDOMString  theOutputFile = futil.generateFileName(outbase, "out");

				const XSLTInputSource	xslInputSource(c_wstr(theXSLFile));
				const XSLTInputSource	xmlInputSource(c_wstr(theXMLFile));
				const XSLTResultTarget	resultFile(theOutputFile);

				//
				// Parsing(compile) the XSL stylesheet and report the results..
				//
				const XalanCompiledStylesheet*	compiledSS = 0;
				xalan.compileStylesheet(xslInputSource, compiledSS);
				if (compiledSS == 0 )
				{
					// Report the failure and be sure to increment fail count.
					cout << "Failed to PARSE stylesheet for " << currentFile << endl;
					futil.data.fail += 1;
					logFile.logErrorResult(currentFile, XalanDOMString("Failed to PARSE stylesheet."));
					continue;
				}

				//
				// Parsing the input XML and report the results..
				//
				const XalanParsedSource*	parsedSource = 0;
				xalan.parseSource(xmlInputSource, parsedSource);
				if (parsedSource == 0)
				{
					// Report the failure and be sure to increment fail count.
					cout << "Failed to PARSE source document for " << currentFile << endl;
					futil.data.fail += 1;
					logFile.logErrorResult(currentFile, XalanDOMString("Failed to PARSE source document."));
					continue;
				}

				//
				// Perform One transform using parsed stylesheet and parsed xml source, report results...
				//
				xalan.transform(*parsedSource, compiledSS, resultFile);

				futil.checkResults(theOutputFile,
								  theGoldFile,
								  logFile);

				xalan.destroyParsedSource(parsedSource);
				xalan.destroyStylesheet(compiledSS);

			}	//for files

			logFile.logTestCaseClose("Done", "Pass");

		}		//for directories

		futil.reportPassFail(logFile, UniqRunid);
		logFile.logTestFileClose("Conformance ", "Done");
		logFile.close();

		futil.analyzeResults(xalan, resultsFile);

	} //if getParams

	XalanTransformer::terminate();

	return 0;
}
<commit_msg>Added additional option to run the tests using XercesDOMWrapperParsedSource for the xml source.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <iostream>
#include <strstream>
#include <stdio.h>
#include <direct.h>

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::cin;
	using std::endl;
	using std::ifstream;
	using std::ios_base;
	using std::ostrstream;
	using std::string;
#endif

// XERCES HEADERS...
//	Most are included by HarnessInit.hpp
#include <parsers/DOMParser.hpp>

// XALAN HEADERS...
//	Most are included by FileUtility.hpp
#include <XalanTransformer/XercesDOMWrapperParsedSource.hpp>

// HARNESS HEADERS...
#include <XMLFileReporter.hpp>
#include <FileUtility.hpp>
#include <HarnessInit.hpp>

#if defined(XALAN_NO_NAMESPACES)
	typedef map<XalanDOMString, XalanDOMString, less<XalanDOMString> >	Hashtable;
#else
	typedef std::map<XalanDOMString, XalanDOMString>  Hashtable;
#endif

// This is here for memory leak testing.
#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif

const char* const 	excludeStylesheets[] =
{
	"output22.xsl",
	"entref01.xsl",
	"select73.xsl",
	"sort07.xsl",
	0
};

FileUtility		futil;

void
printArgOptions()
{
	cerr << endl
		 << "conf dir [-category -out -gold -source (XST | XPL | DOM)]"
		 << endl
		 << endl
		 << "dir		(base directory for testcases)"
		 << endl
		 << "-sub dir	(specific directory)"
		 << endl
		 << "-out dir	(base directory for output)"
		 << endl
		 << "-gold dir	(base directory for gold files)"
		 << endl
		 << "-source	(parsed source; XalanSourceTree(d), XercesParserLiasion, XercesDOM)"
		 << endl;
}

bool
getParams(int argc,
		  const char*	argv[],
		  FileUtility& f,
		  XalanDOMString& baseDir,
		  XalanDOMString& outDir,
		  XalanDOMString& goldRoot,
		  XalanDOMString& category,
		  int& source)
{
	bool fSuccess = true;	// Used to continue argument loop
	bool fsetOut = true;	// Set default output directory, set to false if data is provided
	bool fsetGold = true;	// Set default gold directory, set to false if data is provided

	// Insure that required "-base" argument is there.
	if (argc == 1 || argv[1][0] == '-')
	{
		printArgOptions();
		return false;
	}
	else
	{
		if (f.checkDir(pathSep + XalanDOMString(argv[1])))
		{
			assign(baseDir, XalanDOMString(argv[1]));
			insert(baseDir, 0, pathSep);
		}
		else
		{
			cout << endl << "Given base directory \"" << argv[1] << "\" does not exist" << endl;
			printArgOptions();
			return false;
		}
	}

	// Get the rest of the arguments in any order.
	for (int i = 2; i < argc && fSuccess == true; ++i)
	{
		if(!stricmp("-out", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(outDir, XalanDOMString(argv[i]));
				insert(outDir, 0, XalanDOMString("\\"));
				append(outDir, XalanDOMString("\\"));
				f.checkAndCreateDir(outDir);
				fsetOut = false;
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}
		else if(!stricmp("-gold", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(goldRoot, XalanDOMString(argv[i]));
				insert(goldRoot, 0, pathSep);
				fsetGold = false;
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}
		else if(!stricmp("-source", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				if (stricmp(argv[i],"XPL") == 0)
				{
					source = 1;
				}
				else if (stricmp(argv[i], "DOM") == 0)
				{
					source = 2;
				}
				else
				{
					printArgOptions();
					fSuccess = false;
				}
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}
		else if(!stricmp("-sub", argv[i]))
		{
			++i;
			if(i < argc && argv[i][0] != '-')
			{
				assign(category, XalanDOMString(argv[i]));
			}
			else
			{
				printArgOptions();
				fSuccess = false;
			}
		}

		else
		{
			printArgOptions();
			fSuccess = false;
		}

	} // End of for-loop

	// Do we need to set the default output directory??
	if (fsetOut)
	{
		unsigned int ii = lastIndexOf(baseDir,charAt(pathSep,0));
		outDir = substring(baseDir, 0, ii+1);
		append(outDir,XalanDOMString("CONF-results"));
		f.checkAndCreateDir(outDir);
		append(outDir,pathSep);
	}
	if (fsetGold)
	{
		goldRoot = baseDir;
		append(goldRoot,XalanDOMString("-gold"));
		f.checkAndCreateDir(goldRoot);
		//append(goldRoot,pathSep);
	}

	// Add the path seperator to the end of the base directory
	// here after we've finished using it for all directory creation.

	append(baseDir,pathSep);
	append(goldRoot,pathSep);
	return fSuccess;
}

inline bool
checkForExclusion(XalanDOMString currentFile)
{
	for (int i=0; excludeStylesheets[i] != 0; i++)
	{
		if (equals(currentFile, XalanDOMString(excludeStylesheets[i])))
		{
			return true;
		}
	}

	return false;
}

void
parseWithTransformer(int &sourceType, XalanTransformer &xalan, const XSLTInputSource &xmlInput,
					 const XalanCompiledStylesheet* styleSheet, const XSLTResultTarget &output,
					 XMLFileReporter &logFile)
{
	const XalanParsedSource* parsedSource = 0;

	if (sourceType != 0 )
	{
		xalan.parseSource(xmlInput, parsedSource, true);
		futil.data.xmlFormat = XalanDOMString("XercesParserLiasion");
	}
	else
	{
		xalan.parseSource(xmlInput, parsedSource, false);
		futil.data.xmlFormat = XalanDOMString("XalanSourceTree");
	}

	if (parsedSource == 0)
	{
		// Report the failure and be sure to increment fail count.
		cout << "Failed to PARSE source document for " << futil.data.testOrFile << endl;
		futil.data.fail += 1;
		logFile.logErrorResult(futil.data.testOrFile, XalanDOMString("Failed to PARSE source document."));
	}

	xalan.transform(*parsedSource, styleSheet, output);
	xalan.destroyParsedSource(parsedSource);
}

void
parseWithXerces(int &sourceType, XalanTransformer &xalan, const XSLTInputSource &xmlInput,
				const XalanCompiledStylesheet* styleSheet, const XSLTResultTarget &output,
				XMLFileReporter &logFile)
{

	const XercesDOMWrapperParsedSource* parsedSource = 0;
	futil.data.xmlFormat = XalanDOMString("Xerces_DOM");

	DOMParser  theParser;
	theParser.setToCreateXMLDeclTypeNode(false);

	theParser.parse(xmlInput);
	const DOM_Document theDOM = theParser.getDocument();

	XercesDOMSupport	theDOMSupport;
	XercesParserLiaison theParserLiaison(theDOMSupport);

	parsedSource = new XercesDOMWrapperParsedSource(theDOM,
								 theParserLiaison,
								 theDOMSupport,
								 XalanDOMString(xmlInput.getSystemId()));

	if (parsedSource == 0)
	{
		// Report the failure and be sure to increment fail count.
		cout << "Failed to PARSE source document for " << futil.data.testOrFile << endl;
		futil.data.fail += 1;
		logFile.logErrorResult(futil.data.testOrFile, XalanDOMString("Failed to PARSE source document."));
	}

	xalan.transform(*parsedSource, styleSheet, output);
	delete parsedSource;

}

int
main(
	 int			argc,
	 const char*	argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	Hashtable runAttrs;	// Attribute lists for conformance testing.

	XalanDOMString  category;	// Test all of base dir by default
	XalanDOMString  baseDir, outputRoot, goldRoot;
	int source = 0;				// Format the source xml will be. Default is XalanSourceTree 0.

	if (getParams(argc, argv, futil, baseDir, outputRoot, goldRoot, category, source) == true)
	{
		// Call the static initializers for xerces and xalan, and create a transformer
		HarnessInit xmlPlatformUtils;
		XalanTransformer::initialize();
		XalanTransformer xalan;

		// Generate Unique Run id and processor info
		const XalanDOMString& UniqRunid = futil.generateUniqRunid();

		// Defined basic constants for file manipulation and open results file
		const XalanDOMString  drive(futil.getDrive());
		const XalanDOMString  resultFilePrefix("cpp");
		const XalanDOMString  resultsFile(drive + outputRoot + resultFilePrefix + UniqRunid + XMLSuffix);

		XMLFileReporter	logFile(resultsFile);
		logFile.logTestFileInit("Conformance Testing:");

		// Get the list of Directories that are below conf
		const FileNameVectorType	dirs = futil.getDirectoryNames(baseDir);

		for(FileNameVectorType::size_type	j = 0; j < dirs.size(); ++j)
		{
			const XalanDOMString currentDir(dirs[j]);

			// Run specific category of files from given directory
			if (length(category) > 0 && !equals(currentDir, category))
			{
				continue;
			}

			// Check that output directory is there.
			const XalanDOMString  theOutputDir = outputRoot + currentDir;
			futil.checkAndCreateDir(theOutputDir);

			// Get the files found in the test directory
			const FileNameVectorType files = futil.getTestFileNames(baseDir, currentDir, true);

			logFile.logTestCaseInit(currentDir);

			for(FileNameVectorType::size_type i = 0; i < files.size(); i++)
			{
				Hashtable attrs;
				const XalanDOMString currentFile(files[i]);
				futil.data.testOrFile = currentFile;

				if (checkForExclusion(currentFile))
					continue;

				const XalanDOMString  theXSLFile = baseDir + currentDir + pathSep + currentFile;
				const XalanDOMString  theXMLFile = futil.generateFileName(theXSLFile,"xml");
				futil.data.xmlFileURL = theXMLFile;
				futil.data.xslFileURL = theXSLFile;
				futil.data.testBase = baseDir;

				XalanDOMString  theGoldFile = goldRoot + currentDir + pathSep + currentFile;
				theGoldFile = futil.generateFileName(theGoldFile, "out");

				const XalanDOMString  outbase =  outputRoot + currentDir + pathSep + currentFile;
				const XalanDOMString  theOutputFile = futil.generateFileName(outbase, "out");

				const XSLTInputSource	xslInputSource(c_wstr(theXSLFile));
				const XSLTInputSource	xmlInputSource(c_wstr(theXMLFile));
				const XSLTResultTarget	resultFile(theOutputFile);

				//
				// Parsing(compile) the XSL stylesheet and report the results..
				//
				const XalanCompiledStylesheet*	compiledSS = 0;
				xalan.compileStylesheet(xslInputSource, compiledSS);
				if (compiledSS == 0 )
				{
					// Report the failure and be sure to increment fail count.
					cout << "Failed to PARSE stylesheet for " << currentFile << endl;
					futil.data.fail += 1;
					logFile.logErrorResult(currentFile, XalanDOMString("Failed to PARSE stylesheet."));
					continue;
				}

				//
				// Parsing the Source XML based on input params. Default is to use XalanParsedSource.
				//
				switch (source)
				{
					case 0:
					case 1:
						parseWithTransformer(source, xalan, xmlInputSource, compiledSS, resultFile, logFile);
						break;

					case 2:
						parseWithXerces(source, xalan, xmlInputSource, compiledSS, resultFile, logFile);
						break;
				}

				//
				// Perform One transform using parsed stylesheet and parsed xml source, report results...

				futil.checkResults(theOutputFile,
								  theGoldFile,
								  logFile);

				xalan.destroyStylesheet(compiledSS);

			}	//for files

			logFile.logTestCaseClose("Done", "Pass");

		}		//for directories

		futil.reportPassFail(logFile, UniqRunid);
		logFile.logTestFileClose("Conformance ", "Done");
		logFile.close();

		futil.analyzeResults(xalan, resultsFile);

	} //if getParams

	XalanTransformer::terminate();

	return 0;
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <test/Helpers.h>
#include <asp/Core/Common.h>

using namespace vw;
using namespace asp;

TEST( Common, StereoMultiCmdCheck ) {

  std::vector<std::string> files;
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img1.xml");
  files.push_back("img2.xml");
  files.push_back("run/run");

  std::vector<std::string> image_paths, camera_paths;
  std::string prefix, dem_path;
  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img1.xml", camera_paths[0]);
  EXPECT_EQ("img2.xml", camera_paths[1]);
  EXPECT_EQ("run/run" , prefix );
  EXPECT_EQ("",         dem_path);

  // ----

  files.clear();
  files.push_back("img1.cub");
  files.push_back("img2.cub");
  files.push_back("run/run");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.cub", image_paths [0]);
  EXPECT_EQ("img2.cub", image_paths [1]);
  EXPECT_EQ("img1.cub", camera_paths[0]);
  EXPECT_EQ("img2.cub", camera_paths[1]);
  EXPECT_EQ("run/run" , prefix);
  EXPECT_EQ("",         dem_path);

  // ----

  files.clear();
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img1.cub");
  files.push_back("img2.cub");
  files.push_back("run/run");
  files.push_back("test_dem.tif");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img1.cub", camera_paths[0]);
  EXPECT_EQ("img2.cub", camera_paths[1]);
  EXPECT_EQ("run/run",  prefix);
  EXPECT_EQ("test_dem.tif",  dem_path);

  // ----

  files.clear();
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img3.tif");
  files.push_back("img4.tif");
  files.push_back("run/run");
  files.push_back("test_dem.tif");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(4, image_paths.size());
  EXPECT_EQ(4, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img3.tif", image_paths [2]);
  EXPECT_EQ("img4.tif", image_paths [3]);
  EXPECT_EQ("img1.tif", camera_paths[0]);
  EXPECT_EQ("img2.tif", camera_paths[1]);
  EXPECT_EQ("img3.tif", camera_paths[2]);
  EXPECT_EQ("img4.tif", camera_paths[3]);
  EXPECT_EQ("run/run" , prefix);
  EXPECT_EQ("test_dem.tif" , dem_path);

} // End test StereoMultiCmdCheck
<commit_msg>TestCommon: Images must exist with valid georef for the test to pass<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <test/Helpers.h>
#include <asp/Core/Common.h>

using namespace vw;
using namespace asp;

TEST( Common, StereoMultiCmdCheck ) {

  // Init a georef, the numbers are pretty arbitrary, it just must be valid
  cartography::GeoReference georef;
  georef.set_geographic();
  georef.set_proj4_projection_str("+proj=longlat +a=3396190 +b=3396190 +no_defs ");
  georef.set_well_known_geogcs("D_MARS");
  Matrix3x3 affine;
  affine(0,0) = 0.01; // 100 pix/degree
  affine(1,1) = -0.01; // 100 pix/degree
  affine(2,2) = 1;
  affine(0,2) = 30;   // 30 deg east
  affine(1,2) = -35;  // 35 deg south
  georef.set_transform(affine);

  // For the test below to pass, the files must be present.
  ImageView<float> dem(100, 100);
  double nodata = -1000;
  bool has_nodata = true, has_georef = true;
  TerminalProgressCallback tpc("asp", ": ");
  asp::BaseOptions opt;

  asp::block_write_gdal_image("img1.tif", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("img2.tif", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("img3.tif", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("img4.tif", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("img1.cub", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("img2.cub", dem, has_georef, georef, has_nodata, nodata, opt, tpc);
  asp::block_write_gdal_image("dem.tif", dem, has_georef, georef, has_nodata, nodata, opt, tpc);

  std::ofstream ofs1("img1.xml"); ofs1 << "test" << std::endl; ofs1.close();
  std::ofstream ofs2("img2.xml"); ofs2 << "test" << std::endl; ofs2.close();

  std::vector<std::string> files;
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img1.xml");
  files.push_back("img2.xml");
  files.push_back("run/run");

  std::vector<std::string> image_paths, camera_paths;
  std::string prefix, dem_path;
  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img1.xml", camera_paths[0]);
  EXPECT_EQ("img2.xml", camera_paths[1]);
  EXPECT_EQ("run/run" , prefix );
  EXPECT_EQ("",         dem_path);

  // ----

  files.clear();
  files.push_back("img1.cub");
  files.push_back("img2.cub");
  files.push_back("run/run");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.cub", image_paths [0]);
  EXPECT_EQ("img2.cub", image_paths [1]);
  EXPECT_EQ("img1.cub", camera_paths[0]);
  EXPECT_EQ("img2.cub", camera_paths[1]);
  EXPECT_EQ("run/run" , prefix);
  EXPECT_EQ("",         dem_path);

  // ----
  files.clear();
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img1.cub");
  files.push_back("img2.cub");
  files.push_back("run/run");
  files.push_back("dem.tif");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(2, image_paths.size ());
  EXPECT_EQ(2, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img1.cub", camera_paths[0]);
  EXPECT_EQ("img2.cub", camera_paths[1]);
  EXPECT_EQ("run/run",  prefix);
  EXPECT_EQ("dem.tif",  dem_path);

  // ----
  files.clear();
  files.push_back("img1.tif");
  files.push_back("img2.tif");
  files.push_back("img3.tif");
  files.push_back("img4.tif");
  files.push_back("run/run");
  files.push_back("dem.tif");

  parse_multiview_cmd_files(files, image_paths, camera_paths, prefix, dem_path);
  EXPECT_EQ(4, image_paths.size());
  EXPECT_EQ(4, camera_paths.size());
  EXPECT_EQ("img1.tif", image_paths [0]);
  EXPECT_EQ("img2.tif", image_paths [1]);
  EXPECT_EQ("img3.tif", image_paths [2]);
  EXPECT_EQ("img4.tif", image_paths [3]);
  EXPECT_EQ("img1.tif", camera_paths[0]);
  EXPECT_EQ("img2.tif", camera_paths[1]);
  EXPECT_EQ("img3.tif", camera_paths[2]);
  EXPECT_EQ("img4.tif", camera_paths[3]);
  EXPECT_EQ("run/run" , prefix);
  EXPECT_EQ("dem.tif" , dem_path);

} // End test StereoMultiCmdCheck
<|endoftext|>


<commit_before>#include"../header/CThreadPool.hpp"
#include<memory>	//make_unique
#include<mutex>
#include<vector>
#include<unordered_map>
#include"../../lib/header/thread/CThread_forward_list.hpp"
#include"../../lib/header/thread/CThreadRingBuf.hpp"
#include"../header/CThreadPoolCommun.hpp"
#include"../header/CThreadPoolItem.hpp"
#include"../header/IThreadPoolItemExecutor.hpp"
using namespace std;

namespace nThread
{
	struct CThreadPool::Impl
	{
		unordered_map<thread_id,bool> is_joinable;
		mutex join_all_mut;	//only for join_all
		CThread_forward_list<CThreadPoolItem*> join_anyList;
		mutex wait_until_all_available_mut;	//only for wait_until_all_available
		CThreadRingBuf<CThreadPoolItem*> waiting_buf;
		unordered_map<thread_id,CThreadPoolItem> thr;
		Impl(CThreadPool::size_type);
		thread_id add(function<void()> &&);
		void add_and_detach(function<void()> &&);
		inline void join(const thread_id id)
		{
			thr[id].wait();
		}
		void join_all();
		bool joinable(thread_id) const noexcept;
		void wait_until_all_available();
	};

	CThreadPool::Impl::Impl(CThreadPool::size_type size)
		:is_joinable{size},waiting_buf{size},thr{size}
	{
		while(size--)
		{
			//because the key_type of thr is thread_id, and thread_id is returned by CThreadPoolItem
			//so, you have to create a CThreadPoolItem first, and emplace get_id to thr
			CThreadPoolItem item;
			const auto id{item.get_id()};
			//it means "not joinable"
			is_joinable.emplace(id,false);
			//thr.emplace(item.get_id(),move(item)); is wrong
			//you cannot guarantee item.get_id() will execute prior to move(item)
			waiting_buf.write(&thr.emplace(id,move(item)).first->second);
		}
	}

	CThreadPool::thread_id CThreadPool::Impl::add(function<void()> &&func)
	{
		auto temp{waiting_buf.read()};
		is_joinable[temp->get_id()]=true;
		temp->assign(make_unique<CThreadPoolItemExecutorJoin>(CThreadPoolCommunJoin{temp,&join_anyList,&waiting_buf},move(func)));
		return temp->get_id();
	}

	void CThreadPool::Impl::add_and_detach(function<void()> &&func)
	{
		auto temp{waiting_buf.read()};
		is_joinable[temp->get_id()]=false;
		temp->assign(make_unique<CThreadPoolItemExecutorDetach>(CThreadPoolCommunDetach{temp,&waiting_buf},move(func)));
	}

	void CThreadPool::Impl::join_all()
	{
		//if two threads call join_all at same time
		//because joinable and wait is not atomic
		//one thread may check joinable and execute wait
		//another thread may check same item, and because the first thread have not completed wait yet
		//it may call wait again, causing problem
		//so I use lock to prevent the event from happening
		lock_guard<mutex> lock{join_all_mut};
		for(auto &val:thr)
			if(joinable(val.first))
				join(val.first);
	}

	bool CThreadPool::Impl::joinable(const thread_id id) const noexcept
	{
		if(is_joinable.at(id))
			return thr.at(id).is_running();
		return false;
	}

	void CThreadPool::Impl::wait_until_all_available()
	{
		//speed up, you can construct a vector in each threads in advance
		vector<decltype(waiting_buf)::value_type> vec;
		vec.reserve(thr.size());
		lock_guard<mutex> lock{wait_until_all_available_mut};
		while(vec.size()!=vec.capacity())
			vec.emplace_back(waiting_buf.read());
		for(auto &val:vec)
			waiting_buf.write(move(val));
	}

	CThreadPool::thread_id CThreadPool::add_(std::function<void()> &&func)
	{
		return impl_.get().add(move(func));
	}

	void CThreadPool::add_and_detach_(std::function<void()> &&func)
	{
		impl_.get().add_and_detach(move(func));
	}

	CThreadPool::CThreadPool()
		:CThreadPool(thread::hardware_concurrency()){}

	CThreadPool::CThreadPool(const CThreadPool::size_type size)
		:impl_{size}{}

	CThreadPool::size_type CThreadPool::available() const noexcept
	{
		return static_cast<size_type>(impl_.get().waiting_buf.available());
	}

	void CThreadPool::join(const thread_id id)
	{
		impl_.get().join(id);
	}

	void CThreadPool::join_all()
	{
		impl_.get().join_all();
	}

	CThreadPool::thread_id CThreadPool::join_any()
	{
		auto temp{impl_.get().join_anyList.wait_and_pop_front()};
		temp->wait();
		return temp->get_id();
	}

	bool CThreadPool::joinable(const thread_id id) const noexcept
	{
		return impl_.get().joinable(id);
	}

	CThreadPool::size_type CThreadPool::size() const noexcept
	{
		return static_cast<size_type>(impl_.get().thr.size());
	}

	void CThreadPool::wait_until_all_available() const
	{
		impl_.get().wait_until_all_available();
	}

	CThreadPool::~CThreadPool()=default;
}<commit_msg>fix exception safety<commit_after>#include"../header/CThreadPool.hpp"
#include<memory>	//make_unique
#include<mutex>
#include<vector>
#include<unordered_map>
#include"../../lib/header/thread/CThread_forward_list.hpp"
#include"../../lib/header/thread/CThreadRingBuf.hpp"
#include"../header/CThreadPoolCommun.hpp"
#include"../header/CThreadPoolItem.hpp"
#include"../header/IThreadPoolItemExecutor.hpp"
using namespace std;

namespace nThread
{
	struct CThreadPool::Impl
	{
		unordered_map<thread_id,bool> is_joinable;
		mutex join_all_mut;	//only for join_all
		CThread_forward_list<CThreadPoolItem*> join_anyList;
		mutex wait_until_all_available_mut;	//only for wait_until_all_available
		CThreadRingBuf<CThreadPoolItem*> waiting_buf;
		unordered_map<thread_id,CThreadPoolItem> thr;
		Impl(CThreadPool::size_type);
		thread_id add(function<void()> &&);
		void add_and_detach(function<void()> &&);
		inline void join(const thread_id id)
		{
			thr[id].wait();
		}
		void join_all();
		bool joinable(thread_id) const noexcept;
		void wait_until_all_available();
	};

	CThreadPool::Impl::Impl(CThreadPool::size_type size)
		:is_joinable{size},waiting_buf{size},thr{size}
	{
		while(size--)
		{
			//because the key_type of thr is thread_id, and thread_id is returned by CThreadPoolItem
			//so, you have to create a CThreadPoolItem first, and emplace get_id to thr
			CThreadPoolItem item;
			const auto id{item.get_id()};
			//it means "not joinable"
			is_joinable.emplace(id,false);
			//thr.emplace(item.get_id(),move(item)); is wrong
			//you cannot guarantee item.get_id() will execute prior to move(item)
			waiting_buf.write(&thr.emplace(id,move(item)).first->second);
		}
	}

	CThreadPool::thread_id CThreadPool::Impl::add(function<void()> &&func)
	{
		auto temp{waiting_buf.read()};
		is_joinable[temp->get_id()]=true;
		try
		{
			temp->assign(make_unique<CThreadPoolItemExecutorJoin>(CThreadPoolCommunJoin{temp,&join_anyList,&waiting_buf},move(func)));
		}catch(...)
		{
			waiting_buf.write(temp);
			throw ;
		}
		return temp->get_id();
	}

	void CThreadPool::Impl::add_and_detach(function<void()> &&func)
	{
		auto temp{waiting_buf.read()};
		is_joinable[temp->get_id()]=false;
		try
		{
			temp->assign(make_unique<CThreadPoolItemExecutorDetach>(CThreadPoolCommunDetach{temp,&waiting_buf},move(func)));
		}catch(...)
		{
			waiting_buf.write(temp);
			throw ;
		}
	}

	void CThreadPool::Impl::join_all()
	{
		//if two threads call join_all at same time
		//because joinable and wait is not atomic
		//one thread may check joinable and execute wait
		//another thread may check same item, and because the first thread have not completed wait yet
		//it may call wait again, causing problem
		//so I use lock to prevent the event from happening
		lock_guard<mutex> lock{join_all_mut};
		for(auto &val:thr)
			if(joinable(val.first))
				join(val.first);
	}

	bool CThreadPool::Impl::joinable(const thread_id id) const noexcept
	{
		if(is_joinable.at(id))
			return thr.at(id).is_running();
		return false;
	}

	void CThreadPool::Impl::wait_until_all_available()
	{
		//speed up, you can construct a vector in each threads in advance
		vector<decltype(waiting_buf)::value_type> vec;
		vec.reserve(thr.size());
		lock_guard<mutex> lock{wait_until_all_available_mut};
		while(vec.size()!=vec.capacity())
			vec.emplace_back(waiting_buf.read());
		for(auto &val:vec)
			waiting_buf.write(move(val));
	}

	CThreadPool::thread_id CThreadPool::add_(std::function<void()> &&func)
	{
		return impl_.get().add(move(func));
	}

	void CThreadPool::add_and_detach_(std::function<void()> &&func)
	{
		impl_.get().add_and_detach(move(func));
	}

	CThreadPool::CThreadPool()
		:CThreadPool(thread::hardware_concurrency()){}

	CThreadPool::CThreadPool(const CThreadPool::size_type size)
		:impl_{size}{}

	CThreadPool::size_type CThreadPool::available() const noexcept
	{
		return static_cast<size_type>(impl_.get().waiting_buf.available());
	}

	void CThreadPool::join(const thread_id id)
	{
		impl_.get().join(id);
	}

	void CThreadPool::join_all()
	{
		impl_.get().join_all();
	}

	CThreadPool::thread_id CThreadPool::join_any()
	{
		auto temp{impl_.get().join_anyList.wait_and_pop_front()};
		temp->wait();
		return temp->get_id();
	}

	bool CThreadPool::joinable(const thread_id id) const noexcept
	{
		return impl_.get().joinable(id);
	}

	CThreadPool::size_type CThreadPool::size() const noexcept
	{
		return static_cast<size_type>(impl_.get().thr.size());
	}

	void CThreadPool::wait_until_all_available() const
	{
		impl_.get().wait_until_all_available();
	}

	CThreadPool::~CThreadPool()=default;
}<|endoftext|>