<commit_before>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "server.h"

#include <signal.h>

#include "mcrouter/config.h"
#include "mcrouter/lib/network/AsyncMcServer.h"
#include "mcrouter/lib/network/AsyncMcServerWorker.h"
#include "mcrouter/ManagedModeUtil.h"
#include "mcrouter/McrouterClient.h"
#include "mcrouter/McrouterLogFailure.h"
#include "mcrouter/proxy.h"
#include "mcrouter/ProxyThread.h"
#include "mcrouter/standalone_options.h"

namespace facebook { namespace memcache { namespace mcrouter {

namespace {

/**
 * Server callback for standalone Mcrouter
 */
class ServerOnRequest {
 public:
  explicit ServerOnRequest(McrouterClient* client)
      : client_(client) {
  }

  template <int M>
  void onRequest(McServerRequestContext&& ctx,
                 McRequest&& req,
                 McOperation<M>) {
    mcrouter_msg_t router_msg;

    auto op = mc_op_t(M);
    /* TODO: nasty C/C++ interface stuff.  We should hand off the McRequest
       directly here.  For now, hand off the dependentMsg() since we can assume
       req will stay alive. */
    auto p = folly::make_unique<McServerRequestContext>(std::move(ctx));
    router_msg.context = p.get();
    router_msg.saved_request = std::move(req);
    auto msg = router_msg.saved_request->dependentMsg(op);
    router_msg.req = const_cast<mc_msg_t*>(msg.get());
    /* mcrouter_send will incref req, it's ok to destroy msg after this call */
    client_->send(&router_msg, 1);
    p.release();
  }

 private:
  McrouterClient* client_;
};

void router_on_reply(mcrouter_msg_t* msg,
                     void* context) {
  std::unique_ptr<McServerRequestContext> p(
    reinterpret_cast<McServerRequestContext*>(msg->context));

  assert(p.get());
  McServerRequestContext::reply(std::move(*p),
                                std::move(msg->reply));
  msg->context = nullptr;
}

mcrouter_client_callbacks_t const server_callbacks = {
  router_on_reply,  // on_reply callback
  nullptr,
  nullptr
};

void serverLoop(
  McrouterInstance& router,
  size_t threadId,
  folly::EventBase& evb,
  AsyncMcServerWorker& worker,
  bool managedMode) {

  auto routerClient = router.createClient(
    server_callbacks,
    &worker,
    0);
  auto proxy = router.getProxy(threadId);
  proxy->attachEventBase(&evb);
  // Manually override proxy assignment
  routerClient->setProxy(proxy);

  worker.setOnRequest(ServerOnRequest(routerClient.get()));
  worker.setOnConnectionAccepted([proxy] () {
      stat_incr(proxy->stats, successful_client_connections_stat, 1);
      stat_incr(proxy->stats, num_clients_stat, 1);
    });
  worker.setOnConnectionClosed([proxy] (facebook::memcache::McServerSession&) {
      stat_decr(proxy->stats, num_clients_stat, 1);
    });
  if (managedMode) {
    worker.setOnShutdownOperation([&router] () {
        if (!shutdownFromChild()) {
          logFailure(&router, failure::Category::kSystemError,
                     "Could not shutdown mcrouter on user command.");
        }
      });
  }

  /* TODO(libevent): the only reason this is not simply evb.loop() is
     because we need to call asox stuff on every loop iteration.
     We can clean this up once we convert everything to EventBase */
  while (worker.isAlive() || worker.writesPending()) {
    mcrouterLoopOnce(&evb);
  }
}

}  // namespace

void runServer(const McrouterStandaloneOptions& standaloneOpts,
               McrouterInstance& router) {
  AsyncMcServer::Options opts;

  if (standaloneOpts.listen_sock_fd >= 0) {
    opts.existingSocketFd = standaloneOpts.listen_sock_fd;
  } else {
    opts.ports = standaloneOpts.ports;
    opts.sslPorts = standaloneOpts.ssl_ports;
    opts.pemCertPath = router.opts().pem_cert_path;
    opts.pemKeyPath = router.opts().pem_key_path;
    opts.pemCaPath = router.opts().pem_ca_path;
  }

  opts.numThreads = router.opts().num_proxies;

  opts.worker.versionString = MCROUTER_PACKAGE_STRING;
  opts.worker.maxInFlight = standaloneOpts.max_client_outstanding_reqs;
  opts.worker.sendTimeout = std::chrono::milliseconds{
    router.opts().server_timeout_ms};

  /* Default to one read per event to help latency-sensitive workloads.
     We can make this an option if this needs to be adjusted. */
  opts.worker.maxReadsPerEvent = 1;
  opts.worker.requestsPerRead = standaloneOpts.requests_per_read;

  try {
    LOG(INFO) << "Spawning AsyncMcServer";

    AsyncMcServer server(opts);
    server.spawn(
      [&router, &standaloneOpts] (size_t threadId,
                                  folly::EventBase& evb,
                                  AsyncMcServerWorker& worker) {
        serverLoop(router, threadId, evb, worker, standaloneOpts.managed);
      }
    );

    server.installShutdownHandler({SIGINT, SIGTERM});
    server.join();

    LOG(INFO) << "Shutting down";
  } catch (const std::exception& e) {
    LOG(ERROR) << e.what();
  }
}

}}}  // facebook::memcache::mcrouter
<commit_msg>Shutdown mcrouter before EventBase destruction<commit_after>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "server.h"

#include <signal.h>

#include "mcrouter/config.h"
#include "mcrouter/lib/network/AsyncMcServer.h"
#include "mcrouter/lib/network/AsyncMcServerWorker.h"
#include "mcrouter/ManagedModeUtil.h"
#include "mcrouter/McrouterClient.h"
#include "mcrouter/McrouterLogFailure.h"
#include "mcrouter/proxy.h"
#include "mcrouter/ProxyThread.h"
#include "mcrouter/standalone_options.h"

namespace facebook { namespace memcache { namespace mcrouter {

namespace {

/**
 * Server callback for standalone Mcrouter
 */
class ServerOnRequest {
 public:
  explicit ServerOnRequest(McrouterClient* client)
      : client_(client) {
  }

  template <int M>
  void onRequest(McServerRequestContext&& ctx,
                 McRequest&& req,
                 McOperation<M>) {
    mcrouter_msg_t router_msg;

    auto op = mc_op_t(M);
    /* TODO: nasty C/C++ interface stuff.  We should hand off the McRequest
       directly here.  For now, hand off the dependentMsg() since we can assume
       req will stay alive. */
    auto p = folly::make_unique<McServerRequestContext>(std::move(ctx));
    router_msg.context = p.get();
    router_msg.saved_request = std::move(req);
    auto msg = router_msg.saved_request->dependentMsg(op);
    router_msg.req = const_cast<mc_msg_t*>(msg.get());
    /* mcrouter_send will incref req, it's ok to destroy msg after this call */
    client_->send(&router_msg, 1);
    p.release();
  }

 private:
  McrouterClient* client_;
};

void router_on_reply(mcrouter_msg_t* msg,
                     void* context) {
  std::unique_ptr<McServerRequestContext> p(
    reinterpret_cast<McServerRequestContext*>(msg->context));

  assert(p.get());
  McServerRequestContext::reply(std::move(*p),
                                std::move(msg->reply));
  msg->context = nullptr;
}

mcrouter_client_callbacks_t const server_callbacks = {
  router_on_reply,  // on_reply callback
  nullptr,
  nullptr
};

void serverLoop(
  McrouterInstance& router,
  size_t threadId,
  folly::EventBase& evb,
  AsyncMcServerWorker& worker,
  bool managedMode) {

  auto routerClient = router.createClient(
    server_callbacks,
    &worker,
    0);
  auto proxy = router.getProxy(threadId);
  proxy->attachEventBase(&evb);
  // Manually override proxy assignment
  routerClient->setProxy(proxy);

  worker.setOnRequest(ServerOnRequest(routerClient.get()));
  worker.setOnConnectionAccepted([proxy] () {
      stat_incr(proxy->stats, successful_client_connections_stat, 1);
      stat_incr(proxy->stats, num_clients_stat, 1);
    });
  worker.setOnConnectionClosed([proxy] (facebook::memcache::McServerSession&) {
      stat_decr(proxy->stats, num_clients_stat, 1);
    });
  if (managedMode) {
    worker.setOnShutdownOperation([&router] () {
        if (!shutdownFromChild()) {
          logFailure(&router, failure::Category::kSystemError,
                     "Could not shutdown mcrouter on user command.");
        }
      });
  }

  /* TODO(libevent): the only reason this is not simply evb.loop() is
     because we need to call asox stuff on every loop iteration.
     We can clean this up once we convert everything to EventBase */
  while (worker.isAlive() ||
         worker.writesPending() ||
         proxy->fiberManager.hasTasks()) {
    mcrouterLoopOnce(&evb);
  }
}

}  // namespace

void runServer(const McrouterStandaloneOptions& standaloneOpts,
               McrouterInstance& router) {
  AsyncMcServer::Options opts;

  if (standaloneOpts.listen_sock_fd >= 0) {
    opts.existingSocketFd = standaloneOpts.listen_sock_fd;
  } else {
    opts.ports = standaloneOpts.ports;
    opts.sslPorts = standaloneOpts.ssl_ports;
    opts.pemCertPath = router.opts().pem_cert_path;
    opts.pemKeyPath = router.opts().pem_key_path;
    opts.pemCaPath = router.opts().pem_ca_path;
  }

  opts.numThreads = router.opts().num_proxies;

  opts.worker.versionString = MCROUTER_PACKAGE_STRING;
  opts.worker.maxInFlight = standaloneOpts.max_client_outstanding_reqs;
  opts.worker.sendTimeout = std::chrono::milliseconds{
    router.opts().server_timeout_ms};

  /* Default to one read per event to help latency-sensitive workloads.
     We can make this an option if this needs to be adjusted. */
  opts.worker.maxReadsPerEvent = 1;
  opts.worker.requestsPerRead = standaloneOpts.requests_per_read;

  try {
    LOG(INFO) << "Spawning AsyncMcServer";

    AsyncMcServer server(opts);
    server.spawn(
      [&router, &standaloneOpts] (size_t threadId,
                                  folly::EventBase& evb,
                                  AsyncMcServerWorker& worker) {
        serverLoop(router, threadId, evb, worker, standaloneOpts.managed);
      }
    );

    server.installShutdownHandler({SIGINT, SIGTERM});
    server.join();

    LOG(INFO) << "Shutting down";

    McrouterInstance::freeAllMcrouters();

  } catch (const std::exception& e) {
    LOG(ERROR) << e.what();
  }
}

}}}  // facebook::memcache::mcrouter
<|endoftext|>


<commit_before><commit_msg>Create 1183 - Above the Main Diagonal.cpp<commit_after><|endoftext|>


<commit_before>
#include "vh.h"

#include "entityhelper.h"
#include "convarhelper.h"
#include "renderhelper.h"

#include "scriptmanager.h"
#include "zeusmanager.h"
#include "cameramanager.h"
#include "fogmanager.h"

#include "tier1/interface.h"

#include "cbase.h"

#include "vstdlib/cvar.h"
#include "toolframework/ienginetool.h"
#include "cdll_int.h"
#include "igameevents.h"

#include "dotaplayer.h"
#include "dotahero.h"
#include "dotaresource.h"
#include "dotaability.h"
#include "dotagamerules.h"
#include "dotaitem.h"

#include <sourcehook/sourcehook.h>

#include <windows.h>

BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
	if ( fdwReason == DLL_PROCESS_ATTACH )
	{
		VH().Init();
	}
	else if ( fdwReason == DLL_PROCESS_DETACH )
	{
		VH().Shutdown();
	}

	return TRUE;
}

CVH &VH()
{
	static CVH vh;
	return vh;
}

// required sourcehook boilerplate
SourceHook::Impl::CSourceHookImpl g_SourceHook;
SourceHook::ISourceHook *g_SHPtr = &g_SourceHook;
int g_PLID = 0;

SH_DECL_HOOK1_void( IBaseClientDLL, FrameStageNotify, SH_NOATTRIB, 0, ClientFrameStage_t );

IGameEventManager2 *gameeventmanager = NULL;
IVEngineClient *engine = NULL;

CON_COMMAND( vh_test, "Test convar" )
{
	Msg( "In game: %d\n", VH().EngineClient()->IsInGame() );
	Msg( "Ent index: %d\n", VH().ClientTools()->GetEntIndex( VH().ClientTools()->GetLocalPlayer() ) );

	C_DOTAPlayer player = C_DOTAPlayer::GetLocalPlayer();

	if ( player.IsValid() )
	{
		C_DOTAHero hero = player.m_hAssignedHero;

		if ( hero.IsValid() )
		{
			for ( int x = 0 ; x < MAX_ABILITIES ; ++x )
			{
				C_DOTAAbility ability = hero.m_hAbilities[ x ];

				if ( ability.IsValid() )
				{
					Msg(
						"Ability %d (%s), Activated: %d, Hidden: %d, Level: %d, Cooldown: %0.2f, Mana cost: %d\n",
						x, (char *)ability.m_iName, (bool)ability.m_bActivated, (bool)ability.m_bHidden, (int)ability.m_iLevel, ability.GetCooldownTimeRemaining(), (int)ability.m_iManaCost
					);
				}
			}

			for ( int x = 0 ; x < MAX_UNIT_ITEMS ; ++x )
			{
				C_DOTAItem item = hero.m_hItems[ x ];

				if ( item.IsValid() )
				{
					Msg( "Item %d: %s (modifier: %s)\n", x, (char *)item.m_iName, item.GetIntrinsicModifierName() );
				}
			}

			Msg( "Magic Res: %0.2f, Mana: %0.2f, Max Mana: %0.2f\n", ( float )hero.m_flMagicalResistanceValue, ( float )hero.m_flMana, ( float )hero.m_flMaxMana );
			Msg( "Health: %d, Max Health: %d\n", ( int )hero.m_iHealth, ( int )hero.m_iMaxHealth  );
		}
	}

	C_DOTAGameRules gameRules = C_DOTAGameRules::GetGameRules();

	if ( gameRules.IsValid() )
	{
		Msg(
			"State: %d, game time: %0.2f, Time of day: %d, Start time: %0.2f\n",
			(int)gameRules.m_nGameState, (float)gameRules.m_fGameTime, (int)gameRules.m_iNetTimeOfDay, (float)gameRules.m_flGameStartTime
		);
	}

	for ( int x = 1 ; x <= MAX_PLAYERS ; ++x )
	{
		C_DOTAPlayer player = C_DOTAPlayer::GetPlayerByIndex( x );

		if ( !player.IsValid() )
			continue;

		C_DOTAHero hero = player.m_hAssignedHero;

		if ( !hero.IsValid() )
			continue;

		Msg(
			"Player %d (%d) is playing as %d at level %d, with %d/%d/%d kda, team: %d\n",
			x, ( int )hero.m_iPlayerID, hero.GetHeroID(), hero.GetLevel(), hero.GetNumKills(), hero.GetNumDeaths(), hero.GetNumAssists(), ( int )player.m_iTeamNum
		);
	}

}

void FactoryInfo_t::Init()
{
	engineFactory = Sys_GetFactory( "engine" );
	clientFactory = Sys_GetFactory( "client" );
	cvarFactory = VStdLib_GetICVarFactory();
	fileSystemFactory = Sys_GetFactory( "filesystem_stdio" );
	vguiFactory = Sys_GetFactory( "vgui2" );
}

void CVH::Init()
{
	m_factoryInfo.Init();

	CreateInterfaceFn factories[] =
	{
		m_factoryInfo.engineFactory,
		m_factoryInfo.clientFactory,
		m_factoryInfo.cvarFactory,
		m_factoryInfo.fileSystemFactory,
		m_factoryInfo.vguiFactory,
	};

	// connect tier1
	// passing the vstdlib factory sets up icvar for us
	ConnectTier1Libraries( factories, SIZE_OF_ARRAY( factories ) );

	if ( g_pCVar == NULL )
	{
		Error( "Unable to get ICVar!" );
		return;
	}

	// get engine interfaces
	m_pEngineClient = GetInterface<IVEngineClient>( m_factoryInfo.engineFactory, VENGINE_CLIENT_INTERFACE_VERSION );
	m_pEngineTool = GetInterface<IEngineTool>( m_factoryInfo.engineFactory, VENGINETOOL_INTERFACE_VERSION );
	m_pGameEventManager = GetInterface<IGameEventManager2>( m_factoryInfo.engineFactory, INTERFACEVERSION_GAMEEVENTSMANAGER2 );

	// get client interfaces
	m_pClientDLL = GetInterface<IBaseClientDLL>( m_factoryInfo.clientFactory, CLIENT_DLL_INTERFACE_VERSION );
	m_pClientTools = GetInterface<IClientTools>( m_factoryInfo.clientFactory, VCLIENTTOOLS_INTERFACE_VERSION );

	// get filesystem interfaces
	m_pFileSystem = GetInterface<IFileSystem>( m_factoryInfo.fileSystemFactory, FILESYSTEM_INTERFACE_VERSION );

	gameeventmanager = m_pGameEventManager;
	g_pFullFileSystem = m_pFileSystem;
	engine = m_pEngineClient;

	SH_ADD_HOOK( IBaseClientDLL, FrameStageNotify, m_pClientDLL, SH_MEMBER( this, &CVH::FrameStageNotify ), true );

	// register our convars and concommands
	ConVar_Register();

	// init our things
	RenderHelper().Init();
	EntityHelper().Init();
	ConVarHelper().Init();

	// init managers
	ScriptManager().Init();
	ZeusManager().Init();
	CameraManager().Init();
	FogManager().Init();
}

void CVH::Shutdown()
{
	// un-init our things
	FogManager().Shutdown();
	CameraManager().Shutdown();
	ZeusManager().Shutdown();
	ScriptManager().Shutdown();

	ConVarHelper().Shutdown();
	EntityHelper().Shutdown();
	RenderHelper().Shutdown();

	ConVar_Unregister();

	SH_REMOVE_HOOK( IBaseClientDLL, FrameStageNotify, m_pClientDLL, SH_MEMBER( this, &CVH::FrameStageNotify ), true );

	m_pClientTools = NULL;
	m_pClientDLL = NULL;

	m_pFileSystem = NULL;
	m_pGameEventManager = NULL;
	m_pEngineTool = NULL;
	m_pEngineClient = NULL;

	DisconnectTier1Libraries();

	m_FrameHooks.RemoveAll();
}

void CVH::AddFrameHook( const IFrameManager *manager )
{
	m_FrameHooks.AddToTail( const_cast<IFrameManager *>( manager ) );
}

void CVH::RemoveFrameHook( const IFrameManager *manager )
{
	FOR_EACH_VEC( m_FrameHooks, i )
	{
		const IFrameManager *frameManager = m_FrameHooks[ i ];

		if ( frameManager == manager )
		{
			m_FrameHooks.Remove( i );
			break;
		}
	}
}

void CVH::FrameStageNotify( ClientFrameStage_t curStage )
{
	if ( curStage == FRAME_RENDER_START )
	{
		// entity simulation happens here, so we'll think alongside
	FOR_EACH_VEC( m_FrameHooks, i )
	{
		// think for every installed frame hook
		m_FrameHooks[ i ]->Think();
	}
}

	RETURN_META( MRES_IGNORED );
}
<commit_msg>Use material system surface.<commit_after>
#include "vh.h"

#include "entityhelper.h"
#include "convarhelper.h"
#include "renderhelper.h"

#include "scriptmanager.h"
#include "zeusmanager.h"
#include "cameramanager.h"
#include "fogmanager.h"

#include "tier1/interface.h"

#include "cbase.h"

#include "vstdlib/cvar.h"
#include "toolframework/ienginetool.h"
#include "cdll_int.h"
#include "igameevents.h"

#include "dotaplayer.h"
#include "dotahero.h"
#include "dotaresource.h"
#include "dotaability.h"
#include "dotagamerules.h"
#include "dotaitem.h"

#include "vgui/ISurface.h"

#include <sourcehook/sourcehook.h>

#include <windows.h>

BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
	if ( fdwReason == DLL_PROCESS_ATTACH )
	{
		VH().Init();
	}
	else if ( fdwReason == DLL_PROCESS_DETACH )
	{
		VH().Shutdown();
	}

	return TRUE;
}

CVH &VH()
{
	static CVH vh;
	return vh;
}

// required sourcehook boilerplate
SourceHook::Impl::CSourceHookImpl g_SourceHook;
SourceHook::ISourceHook *g_SHPtr = &g_SourceHook;
int g_PLID = 0;

SH_DECL_HOOK1_void( IBaseClientDLL, FrameStageNotify, SH_NOATTRIB, 0, ClientFrameStage_t );

IGameEventManager2 *gameeventmanager = NULL;
IVEngineClient *engine = NULL;

CON_COMMAND( vh_test, "Test convar" )
{
	Msg( "In game: %d\n", VH().EngineClient()->IsInGame() );
	Msg( "Ent index: %d\n", VH().ClientTools()->GetEntIndex( VH().ClientTools()->GetLocalPlayer() ) );

	int wide = 0, tall = 0;
	RenderHelper().Surface()->GetScreenSize( wide, tall );
	Msg( "Res: %dx%d\n", wide, tall );

	C_DOTAPlayer player = C_DOTAPlayer::GetLocalPlayer();

	if ( player.IsValid() )
	{
		C_DOTAHero hero = player.m_hAssignedHero;

		if ( hero.IsValid() )
		{
			for ( int x = 0 ; x < MAX_ABILITIES ; ++x )
			{
				C_DOTAAbility ability = hero.m_hAbilities[ x ];

				if ( ability.IsValid() )
				{
					Msg(
						"Ability %d (%s), Activated: %d, Hidden: %d, Level: %d, Cooldown: %0.2f, Mana cost: %d\n",
						x, (char *)ability.m_iName, (bool)ability.m_bActivated, (bool)ability.m_bHidden, (int)ability.m_iLevel, ability.GetCooldownTimeRemaining(), (int)ability.m_iManaCost
					);
				}
			}

			for ( int x = 0 ; x < MAX_UNIT_ITEMS ; ++x )
			{
				C_DOTAItem item = hero.m_hItems[ x ];

				if ( item.IsValid() )
				{
					Msg( "Item %d: %s (modifier: %s)\n", x, (char *)item.m_iName, item.GetIntrinsicModifierName() );
				}
			}

			Msg( "Magic Res: %0.2f, Mana: %0.2f, Max Mana: %0.2f\n", ( float )hero.m_flMagicalResistanceValue, ( float )hero.m_flMana, ( float )hero.m_flMaxMana );
			Msg( "Health: %d, Max Health: %d\n", ( int )hero.m_iHealth, ( int )hero.m_iMaxHealth  );
		}
	}

	C_DOTAGameRules gameRules = C_DOTAGameRules::GetGameRules();

	if ( gameRules.IsValid() )
	{
		Msg(
			"State: %d, game time: %0.2f, Time of day: %d, Start time: %0.2f\n",
			(int)gameRules.m_nGameState, (float)gameRules.m_fGameTime, (int)gameRules.m_iNetTimeOfDay, (float)gameRules.m_flGameStartTime
		);
	}

	for ( int x = 1 ; x <= MAX_PLAYERS ; ++x )
	{
		C_DOTAPlayer player = C_DOTAPlayer::GetPlayerByIndex( x );

		if ( !player.IsValid() )
			continue;

		C_DOTAHero hero = player.m_hAssignedHero;

		if ( !hero.IsValid() )
			continue;

		Msg(
			"Player %d (%d) is playing as %d at level %d, with %d/%d/%d kda, team: %d\n",
			x, ( int )hero.m_iPlayerID, hero.GetHeroID(), hero.GetLevel(), hero.GetNumKills(), hero.GetNumDeaths(), hero.GetNumAssists(), ( int )player.m_iTeamNum
		);
	}

}

void FactoryInfo_t::Init()
{
	engineFactory = Sys_GetFactory( "engine" );
	clientFactory = Sys_GetFactory( "client" );
	cvarFactory = VStdLib_GetICVarFactory();
	fileSystemFactory = Sys_GetFactory( "filesystem_stdio" );
	vguiFactory = Sys_GetFactory( "vguimatsurface" );
}

void CVH::Init()
{
	m_factoryInfo.Init();

	CreateInterfaceFn factories[] =
	{
		m_factoryInfo.engineFactory,
		m_factoryInfo.clientFactory,
		m_factoryInfo.cvarFactory,
		m_factoryInfo.fileSystemFactory,
		m_factoryInfo.vguiFactory,
	};

	// connect tier1
	// passing the vstdlib factory sets up icvar for us
	ConnectTier1Libraries( factories, SIZE_OF_ARRAY( factories ) );

	if ( g_pCVar == NULL )
	{
		Error( "Unable to get ICVar!" );
		return;
	}

	// get engine interfaces
	m_pEngineClient = GetInterface<IVEngineClient>( m_factoryInfo.engineFactory, VENGINE_CLIENT_INTERFACE_VERSION );
	m_pEngineTool = GetInterface<IEngineTool>( m_factoryInfo.engineFactory, VENGINETOOL_INTERFACE_VERSION );
	m_pGameEventManager = GetInterface<IGameEventManager2>( m_factoryInfo.engineFactory, INTERFACEVERSION_GAMEEVENTSMANAGER2 );

	// get client interfaces
	m_pClientDLL = GetInterface<IBaseClientDLL>( m_factoryInfo.clientFactory, CLIENT_DLL_INTERFACE_VERSION );
	m_pClientTools = GetInterface<IClientTools>( m_factoryInfo.clientFactory, VCLIENTTOOLS_INTERFACE_VERSION );

	// get filesystem interfaces
	m_pFileSystem = GetInterface<IFileSystem>( m_factoryInfo.fileSystemFactory, FILESYSTEM_INTERFACE_VERSION );

	gameeventmanager = m_pGameEventManager;
	g_pFullFileSystem = m_pFileSystem;
	engine = m_pEngineClient;

	SH_ADD_HOOK( IBaseClientDLL, FrameStageNotify, m_pClientDLL, SH_MEMBER( this, &CVH::FrameStageNotify ), true );

	// register our convars and concommands
	ConVar_Register();

	// init our things
	RenderHelper().Init();
	EntityHelper().Init();
	ConVarHelper().Init();

	// init managers
	ScriptManager().Init();
	ZeusManager().Init();
	CameraManager().Init();
	FogManager().Init();
}

void CVH::Shutdown()
{
	// un-init our things
	FogManager().Shutdown();
	CameraManager().Shutdown();
	ZeusManager().Shutdown();
	ScriptManager().Shutdown();

	ConVarHelper().Shutdown();
	EntityHelper().Shutdown();
	RenderHelper().Shutdown();

	ConVar_Unregister();

	SH_REMOVE_HOOK( IBaseClientDLL, FrameStageNotify, m_pClientDLL, SH_MEMBER( this, &CVH::FrameStageNotify ), true );

	m_pClientTools = NULL;
	m_pClientDLL = NULL;

	m_pFileSystem = NULL;
	m_pGameEventManager = NULL;
	m_pEngineTool = NULL;
	m_pEngineClient = NULL;

	DisconnectTier1Libraries();

	m_FrameHooks.RemoveAll();
}

void CVH::AddFrameHook( const IFrameManager *manager )
{
	m_FrameHooks.AddToTail( const_cast<IFrameManager *>( manager ) );
}

void CVH::RemoveFrameHook( const IFrameManager *manager )
{
	FOR_EACH_VEC( m_FrameHooks, i )
	{
		const IFrameManager *frameManager = m_FrameHooks[ i ];

		if ( frameManager == manager )
		{
			m_FrameHooks.Remove( i );
			break;
		}
	}
}

void CVH::FrameStageNotify( ClientFrameStage_t curStage )
{
	if ( curStage == FRAME_RENDER_START )
	{
		// entity simulation happens here, so we'll think alongside
		FOR_EACH_VEC( m_FrameHooks, i )
		{
			// think for every installed frame hook
			m_FrameHooks[ i ]->Think();
		}
	}

	RETURN_META( MRES_IGNORED );
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <chrono>
#include "config.hpp"
#include "requestHandler.hpp"
#include "response.hpp"
#include "torrent.hpp"
#include "utility.hpp"
#include "mysql.hpp"

TorrentMap RequestHandler::torMap;
UserMap RequestHandler::usrMap;
Database* RequestHandler::db;

std::string RequestHandler::handle(std::string str, std::string ip)
{
	std::pair<Request, std::forward_list<std::string>> infos = Parser::parse(str); // parse the request
	Request* req = &infos.first;
	std::forward_list<std::string>* infoHashes = &infos.second;
	bool gzip = false;
	try { // check if the client accepts gzip
		if (req->at("accept-encoding").find("gzip") != std::string::npos)
			gzip = true;
	} catch (const std::exception& e) {}
	std::string check = Parser::check(*req); // check if we have all we need to process (saves time if not the case
	if (infoHashes->begin() == infoHashes->end())
		return error("missing info_hash", gzip);
	if (check != "success") // missing params
		return error(check, gzip);
	if (Config::get("type") == "private" && getUser(req->at("passkey")) == nullptr)
		return error("passkey not found", gzip);
	try {
		req->at("ip") = Utility::ip_hex_encode(req->at("ip")) + Utility::port_hex_encode(req->at("port"));
	} catch (const std::exception& e) {
		req->emplace("ip", ip + Utility::port_hex_encode(req->at("port")));
	}
	if (req->at("action") == "announce")
		return announce(req, infoHashes->front(), gzip);
	else if (req->at("action") == "scrape")
		return scrape(infoHashes, gzip);
	return error("invalid action", gzip); // not possible, since the request is checked, but, well, who knows :3
}

std::string RequestHandler::announce(const Request* req, const std::string& infoHash, const bool& gzip)
{
	auto time_point = std::chrono::system_clock::now();
	auto duration = time_point.time_since_epoch();
	long long now = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	if (Config::get("type") != "private")
		torMap.emplace(infoHash, 0);
	Torrent *tor = nullptr;
	try {
		tor = &torMap.at(infoHash);
	} catch (const std::exception& e) {
		return error("unregistered torrent", gzip);
	}
	Peers *peers = nullptr;
	if (req->at("left") != "0") {
		if (req->at("event") == "stopped") {
			if (tor->getLeechers()->getPeer(req->at("peer_id"), now) != nullptr) {
				db->record(tor->getLeechers()->getPeer(req->at("peer_id"), now)->record(std::stoul(req->at("left")), req->at("peer_id")));
				db->record(Peer::remove(req->at("peer_id"), tor->getID()));
				tor->getLeechers()->removePeer(*req);
			}
		} else if (tor->getLeechers()->getPeer(req->at("peer_id"), now) == nullptr) {
			tor->getLeechers()->addPeer(*req, tor->getID(), now);
		} else {
			tor->getLeechers()->getPeer(req->at("peer_id"), now)->updateStats(std::stoul(req->at("downloaded"))/(1-(tor->getFree()/100)), now);
		}
		peers = tor->getSeeders();
	} else {
		if (req->at("event") == "stopped" || req->at("event") == "completed") {
			if (tor->getSeeders()->getPeer(req->at("peer_id"), now) != nullptr) {
				if (req->at("event") == "completed") {
					tor->downloadedpp();
					tor->getSeeders()->addPeer(*req, tor->getID(), now);
					tor->getLeechers()->removePeer(*req);
				} else {
					db->record(tor->getSeeders()->getPeer(req->at("peer_id"), now)->record(std::stoul(req->at("left")), req->at("peer_id")));
					db->record(Peer::remove(req->at("peer_id"), tor->getID()));
				}
			}
		} else if (tor->getSeeders()->getPeer(req->at("peer_id"), now) == nullptr) {
			tor->getSeeders()->addPeer(*req, tor->getID(), now);
		} else {
			tor->getLeechers()->getPeer(req->at("peer_id"), now)->updateStats(std::stoul(req->at("downloaded"))/(1-(tor->getFree()/100)), now);
		}
		peers = tor->getLeechers();
	}
	std::string peerlist;
	unsigned long i = 0;
	if (req->at("event") != "stopped") {
		i = 10;
		try {
			i = std::stoi(req->at("numwant"));
		} catch (const std::exception& e) {}
		i = std::min(i, peers->size());
	}
	while (i-- > 0) {
		Peer* p = peers->nextPeer(now);
		if (p != nullptr)
			peerlist.append(*p->getHexIP());
	}
	return response(
			("d8:completei"
			 + std::to_string(tor->getSeeders()->size())
			 + "e10:incompletei"
			 + std::to_string(tor->getLeechers()->size())
			 + "e10:downloadedi"
			 + std::to_string(tor->getDownloaded())
			 + "e8:intervali"
			 + std::to_string(900)
			 + "e12:min intervali"
			 + std::to_string(300)
			 + "e5:peers"
			 + std::to_string(peerlist.length())
			 + ":"
			 + peerlist
			 + "e"),
			gzip
			); // doesn't look as bad as it is stated on ocelot, needs stresstesting to check
}

std::string RequestHandler::scrape(const std::forward_list<std::string>* infoHashes, const bool& gzip)
{
	std::string resp("d5:filesd");

	for (const auto& infoHash : *infoHashes) {
		const TorrentMap::iterator it = torMap.find(infoHash);
		if (it != torMap.end()) {
			resp += std::to_string(infoHash.length())
				+ ":"
				+ infoHash
				+ "d8:completei"
				+ std::to_string(it->second.getSeeders()->size())
				+ "e10:incompletei"
				+ std::to_string(it->second.getLeechers()->size())
				+ "e10:downloadedi"
				+ std::to_string(it->second.getDownloaded())
				+ "ee";
		}
	}
	resp += "ee";

	return response(resp, gzip);
}

std::string RequestHandler::update(const Request* req)
{
	std::string resp;
	const std::string& type = req->at("type");

	if (type == "change_passkey")
		resp = changePasskey(req);
	else if (type == "add_torrent")
		resp = addTorrent(req);
	else if (type == "delete_torrent")
		resp = deleteTorrent(req);
	else if (type == "update_torrent")
		resp = updateTorrent(req);
	else if (type == "add_user")
		resp = addUser(req);
	else if (type == "remove_user")
		resp = removeUser(req);

	return resp;
}

std::string RequestHandler::changePasskey(const Request* req)
{
	try {
		const std::string& old = req->at("oldpasskey");
		User* user = usrMap.at(old);
		usrMap.erase(old);
		usrMap.emplace(req->at("newpasskey"), user);

		return "success";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::addTorrent(const Request* req)
{
	try {
		auto t = torMap.emplace(req->at("info_hash"), std::stoul(req->at("id")));
		if (!t.second)
			return "failure";

		try {
			if (req->at("freetorrent") == "1")
				t.first->second.setFree(1);
			else
				t.first->second.setFree(0);
		}
		catch (const std::exception& e) {}

		return "success";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::deleteTorrent(const Request* req)
{
	const auto it = torMap.find(req->at("info_hash"));
	if (it != torMap.end())
		torMap.erase(it);

	return "success";
}

std::string RequestHandler::updateTorrent(const Request* req)
{
	auto it = torMap.find(req->at("info_hash"));
	if (it != torMap.end()) {
		if (req->at("freetorrent") == "1")
			it->second.setFree(1);
		else
			it->second.setFree(0);

		return "success";
	}

	return "failure";
}

std::string RequestHandler::addUser(const Request* req)
{
	try {
		return (usrMap.emplace(req->at("passkey"), new User(std::stoul(req->at("id")))).second) ? "success" : "failure";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::removeUser(const Request* req)
{
	return "failure";
}

User* RequestHandler::getUser(const std::string& passkey) {
	try {
		return usrMap.at(passkey);
	} catch (const std::exception& e) {
		return nullptr;
	}
}

void RequestHandler::init() {
	db = new MySQL();
	db->connect();
	db->loadUsers(usrMap);
	db->loadTorrents(torMap);
}

void RequestHandler::stop() {
	// TODO record every changes before flushing
	db->flush();
	db->disconnect();
}
<commit_msg>last fix tonite<commit_after>#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <chrono>
#include "config.hpp"
#include "requestHandler.hpp"
#include "response.hpp"
#include "torrent.hpp"
#include "utility.hpp"
#include "mysql.hpp"

TorrentMap RequestHandler::torMap;
UserMap RequestHandler::usrMap;
Database* RequestHandler::db;

std::string RequestHandler::handle(std::string str, std::string ip)
{
	std::pair<Request, std::forward_list<std::string>> infos = Parser::parse(str); // parse the request
	Request* req = &infos.first;
	std::forward_list<std::string>* infoHashes = &infos.second;
	bool gzip = false;
	try { // check if the client accepts gzip
		if (req->at("accept-encoding").find("gzip") != std::string::npos)
			gzip = true;
	} catch (const std::exception& e) {}
	std::string check = Parser::check(*req); // check if we have all we need to process (saves time if not the case
	if (infoHashes->begin() == infoHashes->end())
		return error("missing info_hash", gzip);
	if (check != "success") // missing params
		return error(check, gzip);
	if (Config::get("type") == "private" && getUser(req->at("passkey")) == nullptr)
		return error("passkey not found", gzip);
	try {
		req->at("ip") = Utility::ip_hex_encode(req->at("ip")) + Utility::port_hex_encode(req->at("port"));
	} catch (const std::exception& e) {
		req->emplace("ip", ip + Utility::port_hex_encode(req->at("port")));
	}
	if (req->at("action") == "announce")
		return announce(req, infoHashes->front(), gzip);
	else if (req->at("action") == "scrape")
		return scrape(infoHashes, gzip);
	return error("invalid action", gzip); // not possible, since the request is checked, but, well, who knows :3
}

std::string RequestHandler::announce(const Request* req, const std::string& infoHash, const bool& gzip)
{
	auto time_point = std::chrono::system_clock::now();
	auto duration = time_point.time_since_epoch();
	long long now = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	if (Config::get("type") != "private")
		torMap.emplace(infoHash, Torrent(0));
	Torrent *tor = nullptr;
	try {
		tor = &torMap.at(infoHash);
	} catch (const std::exception& e) {
		return error("unregistered torrent", gzip);
	}
	Peers *peers = nullptr;
	if (req->at("left") != "0") {
		if (req->at("event") == "stopped") {
			if (tor->getLeechers()->getPeer(req->at("peer_id"), now) != nullptr) {
				db->record(tor->getLeechers()->getPeer(req->at("peer_id"), now)->record(std::stoul(req->at("left")), req->at("peer_id")));
				db->record(Peer::remove(req->at("peer_id"), tor->getID()));
				tor->getLeechers()->removePeer(*req);
			}
		} else if (tor->getLeechers()->getPeer(req->at("peer_id"), now) == nullptr) {
			tor->getLeechers()->addPeer(*req, tor->getID(), now);
		} else {
			tor->getLeechers()->getPeer(req->at("peer_id"), now)->updateStats(std::stoul(req->at("downloaded"))/(1-(tor->getFree()/100)), now);
		}
		peers = tor->getSeeders();
	} else {
		if (req->at("event") == "stopped" || req->at("event") == "completed") {
			if (tor->getSeeders()->getPeer(req->at("peer_id"), now) != nullptr) {
				if (req->at("event") == "completed") {
					tor->downloadedpp();
					tor->getSeeders()->addPeer(*req, tor->getID(), now);
					tor->getLeechers()->removePeer(*req);
				} else {
					db->record(tor->getSeeders()->getPeer(req->at("peer_id"), now)->record(std::stoul(req->at("left")), req->at("peer_id")));
					db->record(Peer::remove(req->at("peer_id"), tor->getID()));
				}
			}
		} else if (tor->getSeeders()->getPeer(req->at("peer_id"), now) == nullptr) {
			tor->getSeeders()->addPeer(*req, tor->getID(), now);
		} else {
			tor->getLeechers()->getPeer(req->at("peer_id"), now)->updateStats(std::stoul(req->at("downloaded"))/(1-(tor->getFree()/100)), now);
		}
		peers = tor->getLeechers();
	}
	std::string peerlist;
	unsigned long i = 0;
	if (req->at("event") != "stopped") {
		i = 10;
		try {
			i = std::stoi(req->at("numwant"));
		} catch (const std::exception& e) {}
		i = std::min(i, peers->size());
	}
	while (i-- > 0) {
		Peer* p = peers->nextPeer(now);
		if (p != nullptr)
			peerlist.append(*p->getHexIP());
	}
	return response(
			("d8:completei"
			 + std::to_string(tor->getSeeders()->size())
			 + "e10:incompletei"
			 + std::to_string(tor->getLeechers()->size())
			 + "e10:downloadedi"
			 + std::to_string(tor->getDownloaded())
			 + "e8:intervali"
			 + std::to_string(900)
			 + "e12:min intervali"
			 + std::to_string(300)
			 + "e5:peers"
			 + std::to_string(peerlist.length())
			 + ":"
			 + peerlist
			 + "e"),
			gzip
			); // doesn't look as bad as it is stated on ocelot, needs stresstesting to check
}

std::string RequestHandler::scrape(const std::forward_list<std::string>* infoHashes, const bool& gzip)
{
	std::string resp("d5:filesd");

	for (const auto& infoHash : *infoHashes) {
		const TorrentMap::iterator it = torMap.find(infoHash);
		if (it != torMap.end()) {
			resp += std::to_string(infoHash.length())
				+ ":"
				+ infoHash
				+ "d8:completei"
				+ std::to_string(it->second.getSeeders()->size())
				+ "e10:incompletei"
				+ std::to_string(it->second.getLeechers()->size())
				+ "e10:downloadedi"
				+ std::to_string(it->second.getDownloaded())
				+ "ee";
		}
	}
	resp += "ee";

	return response(resp, gzip);
}

std::string RequestHandler::update(const Request* req)
{
	std::string resp;
	const std::string& type = req->at("type");

	if (type == "change_passkey")
		resp = changePasskey(req);
	else if (type == "add_torrent")
		resp = addTorrent(req);
	else if (type == "delete_torrent")
		resp = deleteTorrent(req);
	else if (type == "update_torrent")
		resp = updateTorrent(req);
	else if (type == "add_user")
		resp = addUser(req);
	else if (type == "remove_user")
		resp = removeUser(req);

	return resp;
}

std::string RequestHandler::changePasskey(const Request* req)
{
	try {
		const std::string& old = req->at("oldpasskey");
		User* user = usrMap.at(old);
		usrMap.erase(old);
		usrMap.emplace(req->at("newpasskey"), user);

		return "success";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::addTorrent(const Request* req)
{
	try {
		auto t = torMap.emplace(req->at("info_hash"), Torrent(std::stoul(req->at("id"))));
		if (!t.second)
			return "failure";

		try {
			if (req->at("freetorrent") == "1")
				t.first->second.setFree(1);
			else
				t.first->second.setFree(0);
		}
		catch (const std::exception& e) {}

		return "success";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::deleteTorrent(const Request* req)
{
	const auto it = torMap.find(req->at("info_hash"));
	if (it != torMap.end())
		torMap.erase(it);

	return "success";
}

std::string RequestHandler::updateTorrent(const Request* req)
{
	auto it = torMap.find(req->at("info_hash"));
	if (it != torMap.end()) {
		if (req->at("freetorrent") == "1")
			it->second.setFree(1);
		else
			it->second.setFree(0);

		return "success";
	}

	return "failure";
}

std::string RequestHandler::addUser(const Request* req)
{
	try {
		return (usrMap.emplace(req->at("passkey"), new User(std::stoul(req->at("id")))).second) ? "success" : "failure";
	}
	catch (const std::exception& e) {
		return "failure";
	}
}

std::string RequestHandler::removeUser(const Request* req)
{
	return "failure";
}

User* RequestHandler::getUser(const std::string& passkey) {
	try {
		return usrMap.at(passkey);
	} catch (const std::exception& e) {
		return nullptr;
	}
}

void RequestHandler::init() {
	db = new MySQL();
	db->connect();
	db->loadUsers(usrMap);
	db->loadTorrents(torMap);
}

void RequestHandler::stop() {
	// TODO record every changes before flushing
	db->flush();
	db->disconnect();
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  skeleton_modification_stack_3d.cpp                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "skeleton_modification_stack_3d.h"
#include "scene/3d/skeleton_3d.h"

///////////////////////////////////////
// ModificationStack3D
///////////////////////////////////////

void SkeletonModificationStack3D::_get_property_list(List<PropertyInfo> *p_list) const {
	for (uint32_t i = 0; i < modifications.size(); i++) {
		p_list->push_back(
				PropertyInfo(Variant::OBJECT, "modifications/" + itos(i),
						PROPERTY_HINT_RESOURCE_TYPE,
						"SkeletonModification3D",
						PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
	}
}

bool SkeletonModificationStack3D::_set(const StringName &p_path, const Variant &p_value) {
	String path = p_path;

	if (path.begins_with("modifications/")) {
		int mod_idx = path.get_slicec('/', 1).to_int();
		set_modification(mod_idx, p_value);
		return true;
	}
	return true;
}

bool SkeletonModificationStack3D::_get(const StringName &p_path, Variant &r_ret) const {
	String path = p_path;

	if (path.begins_with("modifications/")) {
		int mod_idx = path.get_slicec('/', 1).to_int();
		r_ret = get_modification(mod_idx);
		return true;
	}
	return true;
}

void SkeletonModificationStack3D::setup() {
	if (is_setup) {
		return;
	}

	if (skeleton != nullptr) {
		is_setup = true;
		for (uint32_t i = 0; i < modifications.size(); i++) {
			if (!modifications[i].is_valid()) {
				continue;
			}
			modifications[i]->_setup_modification(this);
		}
	} else {
		WARN_PRINT("Cannot setup SkeletonModificationStack3D: no skeleton set!");
	}
}

void SkeletonModificationStack3D::execute(real_t p_delta, int p_execution_mode) {
	ERR_FAIL_COND_MSG(!is_setup || skeleton == nullptr || is_queued_for_deletion(),
			"Modification stack is not properly setup and therefore cannot execute!");

	if (!skeleton->is_inside_tree()) {
		ERR_PRINT_ONCE("Skeleton is not inside SceneTree! Cannot execute modification!");
		return;
	}

	if (!enabled) {
		return;
	}

	for (uint32_t i = 0; i < modifications.size(); i++) {
		if (!modifications[i].is_valid()) {
			continue;
		}

		if (modifications[i]->get_execution_mode() == p_execution_mode) {
			modifications[i]->_execute(p_delta);
		}
	}
}

void SkeletonModificationStack3D::enable_all_modifications(bool p_enabled) {
	for (uint32_t i = 0; i < modifications.size(); i++) {
		if (!modifications[i].is_valid()) {
			continue;
		}
		modifications[i]->set_enabled(p_enabled);
	}
}

Ref<SkeletonModification3D> SkeletonModificationStack3D::get_modification(int p_mod_idx) const {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX_V(p_mod_idx, modifications_size, nullptr);
	return modifications[p_mod_idx];
}

void SkeletonModificationStack3D::add_modification(Ref<SkeletonModification3D> p_mod) {
	p_mod->_setup_modification(this);
	modifications.push_back(p_mod);
}

void SkeletonModificationStack3D::delete_modification(int p_mod_idx) {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX(p_mod_idx, modifications_size);
	modifications.remove(p_mod_idx);
}

void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonModification3D> p_mod) {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX(p_mod_idx, modifications_size);

	if (p_mod == nullptr) {
		modifications.remove(p_mod_idx);
	} else {
		p_mod->_setup_modification(this);
		modifications[p_mod_idx] = p_mod;
	}
}

void SkeletonModificationStack3D::set_modification_count(int p_count) {
	modifications.resize(p_count);
	notify_property_list_changed();
}

int SkeletonModificationStack3D::get_modification_count() const {
	return modifications.size();
}

void SkeletonModificationStack3D::set_skeleton(Skeleton3D *p_skeleton) {
	skeleton = p_skeleton;
}

Skeleton3D *SkeletonModificationStack3D::get_skeleton() const {
	return skeleton;
}

bool SkeletonModificationStack3D::get_is_setup() const {
	return is_setup;
}

void SkeletonModificationStack3D::set_enabled(bool p_enabled) {
	enabled = p_enabled;

	if (!enabled && is_setup && skeleton != nullptr) {
		skeleton->clear_bones_local_pose_override();
	}
}

bool SkeletonModificationStack3D::get_enabled() const {
	return enabled;
}

void SkeletonModificationStack3D::set_strength(real_t p_strength) {
	ERR_FAIL_COND_MSG(p_strength < 0, "Strength cannot be less than zero!");
	ERR_FAIL_COND_MSG(p_strength > 1, "Strength cannot be more than one!");
	strength = p_strength;
}

real_t SkeletonModificationStack3D::get_strength() const {
	return strength;
}

void SkeletonModificationStack3D::_bind_methods() {
	ClassDB::bind_method(D_METHOD("setup"), &SkeletonModificationStack3D::setup);
	ClassDB::bind_method(D_METHOD("execute", "delta", "execution_mode"), &SkeletonModificationStack3D::execute);

	ClassDB::bind_method(D_METHOD("enable_all_modifications", "enabled"), &SkeletonModificationStack3D::enable_all_modifications);
	ClassDB::bind_method(D_METHOD("get_modification", "mod_idx"), &SkeletonModificationStack3D::get_modification);
	ClassDB::bind_method(D_METHOD("add_modification", "modification"), &SkeletonModificationStack3D::add_modification);
	ClassDB::bind_method(D_METHOD("delete_modification", "mod_idx"), &SkeletonModificationStack3D::delete_modification);
	ClassDB::bind_method(D_METHOD("set_modification", "mod_idx", "modification"), &SkeletonModificationStack3D::set_modification);

	ClassDB::bind_method(D_METHOD("set_modification_count", "count"), &SkeletonModificationStack3D::set_modification_count);
	ClassDB::bind_method(D_METHOD("get_modification_count"), &SkeletonModificationStack3D::get_modification_count);

	ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModificationStack3D::get_is_setup);

	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModificationStack3D::set_enabled);
	ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModificationStack3D::get_enabled);

	ClassDB::bind_method(D_METHOD("set_strength", "strength"), &SkeletonModificationStack3D::set_strength);
	ClassDB::bind_method(D_METHOD("get_strength"), &SkeletonModificationStack3D::get_strength);

	ClassDB::bind_method(D_METHOD("get_skeleton"), &SkeletonModificationStack3D::get_skeleton);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_modification_count", "get_modification_count");
}

SkeletonModificationStack3D::SkeletonModificationStack3D() {
}
<commit_msg>Added error macro to ensure non null parameter<commit_after>/*************************************************************************/
/*  skeleton_modification_stack_3d.cpp                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "skeleton_modification_stack_3d.h"
#include "scene/3d/skeleton_3d.h"

///////////////////////////////////////
// ModificationStack3D
///////////////////////////////////////

void SkeletonModificationStack3D::_get_property_list(List<PropertyInfo> *p_list) const {
	for (uint32_t i = 0; i < modifications.size(); i++) {
		p_list->push_back(
				PropertyInfo(Variant::OBJECT, "modifications/" + itos(i),
						PROPERTY_HINT_RESOURCE_TYPE,
						"SkeletonModification3D",
						PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
	}
}

bool SkeletonModificationStack3D::_set(const StringName &p_path, const Variant &p_value) {
	String path = p_path;

	if (path.begins_with("modifications/")) {
		int mod_idx = path.get_slicec('/', 1).to_int();
		set_modification(mod_idx, p_value);
		return true;
	}
	return true;
}

bool SkeletonModificationStack3D::_get(const StringName &p_path, Variant &r_ret) const {
	String path = p_path;

	if (path.begins_with("modifications/")) {
		int mod_idx = path.get_slicec('/', 1).to_int();
		r_ret = get_modification(mod_idx);
		return true;
	}
	return true;
}

void SkeletonModificationStack3D::setup() {
	if (is_setup) {
		return;
	}

	if (skeleton != nullptr) {
		is_setup = true;
		for (uint32_t i = 0; i < modifications.size(); i++) {
			if (!modifications[i].is_valid()) {
				continue;
			}
			modifications[i]->_setup_modification(this);
		}
	} else {
		WARN_PRINT("Cannot setup SkeletonModificationStack3D: no skeleton set!");
	}
}

void SkeletonModificationStack3D::execute(real_t p_delta, int p_execution_mode) {
	ERR_FAIL_COND_MSG(!is_setup || skeleton == nullptr || is_queued_for_deletion(),
			"Modification stack is not properly setup and therefore cannot execute!");

	if (!skeleton->is_inside_tree()) {
		ERR_PRINT_ONCE("Skeleton is not inside SceneTree! Cannot execute modification!");
		return;
	}

	if (!enabled) {
		return;
	}

	for (uint32_t i = 0; i < modifications.size(); i++) {
		if (!modifications[i].is_valid()) {
			continue;
		}

		if (modifications[i]->get_execution_mode() == p_execution_mode) {
			modifications[i]->_execute(p_delta);
		}
	}
}

void SkeletonModificationStack3D::enable_all_modifications(bool p_enabled) {
	for (uint32_t i = 0; i < modifications.size(); i++) {
		if (!modifications[i].is_valid()) {
			continue;
		}
		modifications[i]->set_enabled(p_enabled);
	}
}

Ref<SkeletonModification3D> SkeletonModificationStack3D::get_modification(int p_mod_idx) const {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX_V(p_mod_idx, modifications_size, nullptr);
	return modifications[p_mod_idx];
}

void SkeletonModificationStack3D::add_modification(Ref<SkeletonModification3D> p_mod) {
	ERR_FAIL_NULL(p_mod);
	p_mod->_setup_modification(this);
	modifications.push_back(p_mod);
}

void SkeletonModificationStack3D::delete_modification(int p_mod_idx) {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX(p_mod_idx, modifications_size);
	modifications.remove(p_mod_idx);
}

void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonModification3D> p_mod) {
	const int modifications_size = modifications.size();
	ERR_FAIL_INDEX(p_mod_idx, modifications_size);

	if (p_mod == nullptr) {
		modifications.remove(p_mod_idx);
	} else {
		p_mod->_setup_modification(this);
		modifications[p_mod_idx] = p_mod;
	}
}

void SkeletonModificationStack3D::set_modification_count(int p_count) {
	modifications.resize(p_count);
	notify_property_list_changed();
}

int SkeletonModificationStack3D::get_modification_count() const {
	return modifications.size();
}

void SkeletonModificationStack3D::set_skeleton(Skeleton3D *p_skeleton) {
	skeleton = p_skeleton;
}

Skeleton3D *SkeletonModificationStack3D::get_skeleton() const {
	return skeleton;
}

bool SkeletonModificationStack3D::get_is_setup() const {
	return is_setup;
}

void SkeletonModificationStack3D::set_enabled(bool p_enabled) {
	enabled = p_enabled;

	if (!enabled && is_setup && skeleton != nullptr) {
		skeleton->clear_bones_local_pose_override();
	}
}

bool SkeletonModificationStack3D::get_enabled() const {
	return enabled;
}

void SkeletonModificationStack3D::set_strength(real_t p_strength) {
	ERR_FAIL_COND_MSG(p_strength < 0, "Strength cannot be less than zero!");
	ERR_FAIL_COND_MSG(p_strength > 1, "Strength cannot be more than one!");
	strength = p_strength;
}

real_t SkeletonModificationStack3D::get_strength() const {
	return strength;
}

void SkeletonModificationStack3D::_bind_methods() {
	ClassDB::bind_method(D_METHOD("setup"), &SkeletonModificationStack3D::setup);
	ClassDB::bind_method(D_METHOD("execute", "delta", "execution_mode"), &SkeletonModificationStack3D::execute);

	ClassDB::bind_method(D_METHOD("enable_all_modifications", "enabled"), &SkeletonModificationStack3D::enable_all_modifications);
	ClassDB::bind_method(D_METHOD("get_modification", "mod_idx"), &SkeletonModificationStack3D::get_modification);
	ClassDB::bind_method(D_METHOD("add_modification", "modification"), &SkeletonModificationStack3D::add_modification);
	ClassDB::bind_method(D_METHOD("delete_modification", "mod_idx"), &SkeletonModificationStack3D::delete_modification);
	ClassDB::bind_method(D_METHOD("set_modification", "mod_idx", "modification"), &SkeletonModificationStack3D::set_modification);

	ClassDB::bind_method(D_METHOD("set_modification_count", "count"), &SkeletonModificationStack3D::set_modification_count);
	ClassDB::bind_method(D_METHOD("get_modification_count"), &SkeletonModificationStack3D::get_modification_count);

	ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModificationStack3D::get_is_setup);

	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModificationStack3D::set_enabled);
	ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModificationStack3D::get_enabled);

	ClassDB::bind_method(D_METHOD("set_strength", "strength"), &SkeletonModificationStack3D::set_strength);
	ClassDB::bind_method(D_METHOD("get_strength"), &SkeletonModificationStack3D::get_strength);

	ClassDB::bind_method(D_METHOD("get_skeleton"), &SkeletonModificationStack3D::get_skeleton);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1"), "set_modification_count", "get_modification_count");
}

SkeletonModificationStack3D::SkeletonModificationStack3D() {
}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2003-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "FileParsers.h"
#include "MolFileStereochem.h"
#include <RDGeneral/Invariant.h>
#include <GraphMol/RDKitQueries.h>
#include <fstream>

namespace RDKit{

  //*************************************
  //
  // Every effort has been made to adhere to MDL's standard
  // for mol files
  //
  //*************************************

  std::string AtomGetMolFileSymbol(const Atom *atom){
    PRECONDITION(atom,"");
    // FIX: should eventually recognized dummies and do the right thing
    std::string res=atom->getSymbol();
    // pad the end with spaces
    while(res.size()<3) res += " ";
    return res;
    //return res.c_str();
  }
  std::string GetMolFileAtomLine(const Atom *atom, const Conformer *conf=0){
    PRECONDITION(atom,"");
    std::string res;
    char tmpStr[256];
    int massDiff,chg,stereoCare,hCount,totValence,rxnComponentType;
    int rxnComponentNumber,atomMapNumber,inversionFlag,exactChangeFlag;
    massDiff=0;
    chg=0;
    stereoCare=0;
    hCount=0;
    totValence=0;
    rxnComponentType=0;
    rxnComponentNumber=0;
    atomMapNumber=0;
    inversionFlag=0;
    exactChangeFlag=0;

    if(atom->getFormalCharge()!=0){
      switch(atom->getFormalCharge()){
      case 1: chg=3;break;
      case 2: chg=2;break;
      case 3: chg=1;break;
      case -1: chg=5;break;
      case -2: chg=6;break;
      case -3: chg=7;break;
      default: chg=0;
      }
    }
    double x, y, z;
    x = y = z = 0.0;
    if (conf) {
      const RDGeom::Point3D pos = conf->getAtomPos(atom->getIdx());
      x = pos.x; y = pos.y; z = pos.z;
    }
    std::string symbol = AtomGetMolFileSymbol(atom);
    sprintf(tmpStr,"% 10.4f% 10.4f% 10.4f %3s% 2d% 3d  0% 3d% 3d% 3d  0% 3d% 3d% 3d% 3d% 3d",
	    x,y,z,
	    symbol.c_str(),
	    massDiff,chg,hCount,stereoCare,totValence,rxnComponentType,
	    rxnComponentNumber,atomMapNumber,inversionFlag,exactChangeFlag
	    );
    res += tmpStr;
    return res;
  };

  std::string BondGetMolFileSymbol(const Bond *bond){
    PRECONDITION(bond,"");
    // FIX: should eventually recognize queries
    std::string res;
    if(bond->getIsAromatic()){
      res = "  4";
    } else {
      switch(bond->getBondType()){
      case Bond::SINGLE: res="  1";break;
      case Bond::DOUBLE: res="  2";break;
      case Bond::TRIPLE: res="  3";break;
      case Bond::AROMATIC: res="  4";break;
      }
    }
    return res;
    //return res.c_str();
  }

  // only valid for single bonds
  int BondGetDirCode(const Bond::BondDir dir){
    int res=0;
    switch(dir){
    case Bond::NONE: res=0;break;
    case Bond::BEGINWEDGE: res=1;break;
    case Bond::BEGINDASH: res=6;break;
    case Bond::UNKNOWN: res=4;break;
    default:
      break;
    }
    return res;
  }

  std::string GetMolFileBondLine(const Bond *bond, const INT_MAP_INT &wedgeBonds,
                                 const Conformer *conf){
    PRECONDITION(bond,"");
    std::string res;
    char tmpStr[256];
    std::string symbol = BondGetMolFileSymbol(bond);
    int dirCode=0;

    Bond::BondDir dir=Bond::NONE;
    bool reverse = false;
    if(bond->getBondType()==Bond::SINGLE){
      // single bond stereo chemistry
      dir = DetermineBondWedgeState(bond, wedgeBonds, conf);
      dirCode = BondGetDirCode(dir);
      // if this bond needs to be wedged it is possible that this wedgin was determined
      // by a chiral at the end of bond (instead of at the beginning. In this case we
      // to reverse the bond begin and end atoms for the bond when we write the
      // mol file
      if ((dirCode == 1) || (dirCode == 6)) {
        INT_MAP_INT_CI wbi = wedgeBonds.find(bond->getIdx());
        if (wbi->second != bond->getBeginAtomIdx()) {
          reverse = true;
        }
      }
    } else if (bond->getBondType()==Bond::DOUBLE) { // && (bond->hasProp("_CIPCode"))) {
      // double bond stereo chemistry -
      // we will worry about it only if it is  "any"
      Bond::BondStereo stType = bond->getStereo();
      if (stType == Bond::STEREOANY) { //"A") {
        dirCode = 3; // can be either cis/trans
      }
    }

    if (reverse) {
      // switch the begin and end atoms on the bond line
      sprintf(tmpStr,"% 3d% 3d%s % 2d",bond->getEndAtomIdx()+1,
              bond->getBeginAtomIdx()+1,
              symbol.c_str(),dirCode);
    } else {
      sprintf(tmpStr,"% 3d% 3d%s % 2d",bond->getBeginAtomIdx()+1,
              bond->getEndAtomIdx()+1,
              symbol.c_str(),dirCode);
    }
    res = tmpStr;
    return res;
  }

  //------------------------------------------------
  //
  //  gets a mol block as a string
  //
  //------------------------------------------------
  std::string MolToMolBlock(const ROMol &mol,bool includeStereo, int confId){
    // NOTE: kekulize the molecule before writing it out
    // because of the way mol files handle aroamticity
    ROMol tromol(mol);
    RWMol &trwmol = static_cast<RWMol &>(tromol);
    MolOps::Kekulize(trwmol);

    if(includeStereo){
      // assign "any" status to any stereo bond that are not
      // marked with "E" or "Z" code - these bonds need to be explictly written
      // out to the mol file
      MolOps::findPotentialStereoBonds(trwmol);
      // now assign stereo code if any have been specified by the directions on
      // single bonds
      MolOps::assignBondStereoCodes(trwmol);
    }
    const RWMol &tmol = const_cast<RWMol &>(trwmol);

    std::string res;
    char tmpStr[256];

    int nAtoms,nBonds,nLists,chiralFlag,nsText,nRxnComponents;
    int nReactants,nProducts,nIntermediates;
    nAtoms = tmol.getNumAtoms();
    nBonds = tmol.getNumBonds();
    nLists = 0;
    chiralFlag = 0;
    nsText=0;
    nRxnComponents=0;
    nReactants=0;
    nProducts=0;
    nIntermediates=0;

    if(tmol.hasProp("_Name")){
      std::string name;
      tmol.getProp("_Name",name);
      res += name;
    }
    res += "\n";

    // info
    if(tmol.hasProp("MolFileInfo")){
      std::string info;
      tmol.getProp("MolFileInfo",info);
      res += info;
    }
    res += "\n";
    // comments
    if(tmol.hasProp("MolFileComments")){
      std::string info;
      tmol.getProp("MolFileComments",info);
      res += info;
    }
    res += "\n";

    sprintf(tmpStr,"% 3d% 3d% 3d  0% 3d% 3d% 3d% 3d% 3d% 3d999 V2000\n",
	    nAtoms,nBonds,nLists,chiralFlag,nsText,nRxnComponents,
	    nReactants,nProducts,nIntermediates);
    res += tmpStr;
    const Conformer *conf;
    if(confId<0 && tmol.getNumConformers()==0){
      conf=0;
    } else {
      conf = &(tmol.getConformer(confId));
    }

    ROMol::ConstAtomIterator atomIt;
    for(atomIt=tmol.beginAtoms();atomIt!=tmol.endAtoms();atomIt++){
      res += GetMolFileAtomLine(*atomIt, conf);
      res += "\n";
    }

    INT_MAP_INT wedgeBonds = pickBondsToWedge(tmol);
    ROMol::ConstBondIterator bondIt;
    for(bondIt=tmol.beginBonds();bondIt!=tmol.endBonds();bondIt++){
      res += GetMolFileBondLine(*bondIt, wedgeBonds, conf);
      res += "\n";
    }

    // FIX: aliases, atom lists, etc.
    res += "M  END\n";
    return res;
  }

  //------------------------------------------------
  //
  //  Dump a molecule to a file
  //
  //------------------------------------------------
  void MolToMolFile(const ROMol &mol,std::string fName,bool includeStereo, int confId){
    std::ofstream *outStream = new std::ofstream(fName.c_str());
    CHECK_INVARIANT(outStream,"could not open output file");
    std::string outString = MolToMolBlock(mol,includeStereo, confId);
    *outStream  << outString;
  }
}

<commit_msg>fix a core leak<commit_after>// $Id$
//
//  Copyright (C) 2003-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "FileParsers.h"
#include "MolFileStereochem.h"
#include <RDGeneral/Invariant.h>
#include <GraphMol/RDKitQueries.h>
#include <fstream>

namespace RDKit{

  //*************************************
  //
  // Every effort has been made to adhere to MDL's standard
  // for mol files
  //
  //*************************************

  std::string AtomGetMolFileSymbol(const Atom *atom){
    PRECONDITION(atom,"");
    // FIX: should eventually recognized dummies and do the right thing
    std::string res=atom->getSymbol();
    // pad the end with spaces
    while(res.size()<3) res += " ";
    return res;
    //return res.c_str();
  }
  std::string GetMolFileAtomLine(const Atom *atom, const Conformer *conf=0){
    PRECONDITION(atom,"");
    std::string res;
    char tmpStr[256];
    int massDiff,chg,stereoCare,hCount,totValence,rxnComponentType;
    int rxnComponentNumber,atomMapNumber,inversionFlag,exactChangeFlag;
    massDiff=0;
    chg=0;
    stereoCare=0;
    hCount=0;
    totValence=0;
    rxnComponentType=0;
    rxnComponentNumber=0;
    atomMapNumber=0;
    inversionFlag=0;
    exactChangeFlag=0;

    if(atom->getFormalCharge()!=0){
      switch(atom->getFormalCharge()){
      case 1: chg=3;break;
      case 2: chg=2;break;
      case 3: chg=1;break;
      case -1: chg=5;break;
      case -2: chg=6;break;
      case -3: chg=7;break;
      default: chg=0;
      }
    }
    double x, y, z;
    x = y = z = 0.0;
    if (conf) {
      const RDGeom::Point3D pos = conf->getAtomPos(atom->getIdx());
      x = pos.x; y = pos.y; z = pos.z;
    }
    std::string symbol = AtomGetMolFileSymbol(atom);
    sprintf(tmpStr,"% 10.4f% 10.4f% 10.4f %3s% 2d% 3d  0% 3d% 3d% 3d  0% 3d% 3d% 3d% 3d% 3d",
	    x,y,z,
	    symbol.c_str(),
	    massDiff,chg,hCount,stereoCare,totValence,rxnComponentType,
	    rxnComponentNumber,atomMapNumber,inversionFlag,exactChangeFlag
	    );
    res += tmpStr;
    return res;
  };

  std::string BondGetMolFileSymbol(const Bond *bond){
    PRECONDITION(bond,"");
    // FIX: should eventually recognize queries
    std::string res;
    if(bond->getIsAromatic()){
      res = "  4";
    } else {
      switch(bond->getBondType()){
      case Bond::SINGLE: res="  1";break;
      case Bond::DOUBLE: res="  2";break;
      case Bond::TRIPLE: res="  3";break;
      case Bond::AROMATIC: res="  4";break;
      }
    }
    return res;
    //return res.c_str();
  }

  // only valid for single bonds
  int BondGetDirCode(const Bond::BondDir dir){
    int res=0;
    switch(dir){
    case Bond::NONE: res=0;break;
    case Bond::BEGINWEDGE: res=1;break;
    case Bond::BEGINDASH: res=6;break;
    case Bond::UNKNOWN: res=4;break;
    default:
      break;
    }
    return res;
  }

  std::string GetMolFileBondLine(const Bond *bond, const INT_MAP_INT &wedgeBonds,
                                 const Conformer *conf){
    PRECONDITION(bond,"");
    std::string res;
    char tmpStr[256];
    std::string symbol = BondGetMolFileSymbol(bond);
    int dirCode=0;

    Bond::BondDir dir=Bond::NONE;
    bool reverse = false;
    if(bond->getBondType()==Bond::SINGLE){
      // single bond stereo chemistry
      dir = DetermineBondWedgeState(bond, wedgeBonds, conf);
      dirCode = BondGetDirCode(dir);
      // if this bond needs to be wedged it is possible that this wedgin was determined
      // by a chiral at the end of bond (instead of at the beginning. In this case we
      // to reverse the bond begin and end atoms for the bond when we write the
      // mol file
      if ((dirCode == 1) || (dirCode == 6)) {
        INT_MAP_INT_CI wbi = wedgeBonds.find(bond->getIdx());
        if (wbi->second != bond->getBeginAtomIdx()) {
          reverse = true;
        }
      }
    } else if (bond->getBondType()==Bond::DOUBLE) { // && (bond->hasProp("_CIPCode"))) {
      // double bond stereo chemistry -
      // we will worry about it only if it is  "any"
      Bond::BondStereo stType = bond->getStereo();
      if (stType == Bond::STEREOANY) { //"A") {
        dirCode = 3; // can be either cis/trans
      }
    }

    if (reverse) {
      // switch the begin and end atoms on the bond line
      sprintf(tmpStr,"% 3d% 3d%s % 2d",bond->getEndAtomIdx()+1,
              bond->getBeginAtomIdx()+1,
              symbol.c_str(),dirCode);
    } else {
      sprintf(tmpStr,"% 3d% 3d%s % 2d",bond->getBeginAtomIdx()+1,
              bond->getEndAtomIdx()+1,
              symbol.c_str(),dirCode);
    }
    res = tmpStr;
    return res;
  }

  //------------------------------------------------
  //
  //  gets a mol block as a string
  //
  //------------------------------------------------
  std::string MolToMolBlock(const ROMol &mol,bool includeStereo, int confId){
    // NOTE: kekulize the molecule before writing it out
    // because of the way mol files handle aroamticity
    ROMol tromol(mol);
    RWMol &trwmol = static_cast<RWMol &>(tromol);
    MolOps::Kekulize(trwmol);

    if(includeStereo){
      // assign "any" status to any stereo bond that are not
      // marked with "E" or "Z" code - these bonds need to be explictly written
      // out to the mol file
      MolOps::findPotentialStereoBonds(trwmol);
      // now assign stereo code if any have been specified by the directions on
      // single bonds
      MolOps::assignBondStereoCodes(trwmol);
    }
    const RWMol &tmol = const_cast<RWMol &>(trwmol);

    std::string res;
    char tmpStr[256];

    int nAtoms,nBonds,nLists,chiralFlag,nsText,nRxnComponents;
    int nReactants,nProducts,nIntermediates;
    nAtoms = tmol.getNumAtoms();
    nBonds = tmol.getNumBonds();
    nLists = 0;
    chiralFlag = 0;
    nsText=0;
    nRxnComponents=0;
    nReactants=0;
    nProducts=0;
    nIntermediates=0;

    if(tmol.hasProp("_Name")){
      std::string name;
      tmol.getProp("_Name",name);
      res += name;
    }
    res += "\n";

    // info
    if(tmol.hasProp("MolFileInfo")){
      std::string info;
      tmol.getProp("MolFileInfo",info);
      res += info;
    }
    res += "\n";
    // comments
    if(tmol.hasProp("MolFileComments")){
      std::string info;
      tmol.getProp("MolFileComments",info);
      res += info;
    }
    res += "\n";

    sprintf(tmpStr,"% 3d% 3d% 3d  0% 3d% 3d% 3d% 3d% 3d% 3d999 V2000\n",
	    nAtoms,nBonds,nLists,chiralFlag,nsText,nRxnComponents,
	    nReactants,nProducts,nIntermediates);
    res += tmpStr;
    const Conformer *conf;
    if(confId<0 && tmol.getNumConformers()==0){
      conf=0;
    } else {
      conf = &(tmol.getConformer(confId));
    }

    ROMol::ConstAtomIterator atomIt;
    for(atomIt=tmol.beginAtoms();atomIt!=tmol.endAtoms();atomIt++){
      res += GetMolFileAtomLine(*atomIt, conf);
      res += "\n";
    }

    INT_MAP_INT wedgeBonds = pickBondsToWedge(tmol);
    ROMol::ConstBondIterator bondIt;
    for(bondIt=tmol.beginBonds();bondIt!=tmol.endBonds();bondIt++){
      res += GetMolFileBondLine(*bondIt, wedgeBonds, conf);
      res += "\n";
    }

    // FIX: aliases, atom lists, etc.
    res += "M  END\n";
    return res;
  }

  //------------------------------------------------
  //
  //  Dump a molecule to a file
  //
  //------------------------------------------------
  void MolToMolFile(const ROMol &mol,std::string fName,bool includeStereo, int confId){
    std::ofstream *outStream = new std::ofstream(fName.c_str());
    CHECK_INVARIANT(outStream,"could not open output file");
    std::string outString = MolToMolBlock(mol,includeStereo, confId);
    *outStream  << outString;
    delete outStream;
  }
}

<|endoftext|>


<commit_before>#include <string>
#include <map>
#include "tr/cat/catenum.h"
#include "tr/cat/catjournal.h"

using namespace std;

#define NameTree map<string, xptr>
#define NameTreeIterator map<string, xptr>::iterator

xptr catalog_complex_iterator::get_object() const
{
    return (* (NameTreeIterator *) this->it)->second;
}

const char * catalog_complex_iterator::get_name() const
{
    return (* (NameTreeIterator *) this->it)->first.c_str();
}

bool catalog_complex_iterator::next()
{
    NameTree * a = (NameTree *) this->tmp_tree;

    if (this->it == NULL) {
        this->it = new NameTreeIterator(a->begin());
    } else {
        (* (NameTreeIterator *) this->it)++;
    }

    return ((* (NameTreeIterator *) this->it) != a->end());
}

void catalog_complex_iterator::build_tree(enum catalog_named_objects ot)
{
    NameTree * a = new NameTree();
    this->tmp_tree = a;
    SafeMetadataSemaphore lock;

    lock.Aquire();

    catalog_update_metadata();

    bt_cursor c = bt_lm(catalog_get_names(ot));

    if (!c.is_null()) { c.bt_next_key(); }
    while (!c.is_null()) {
        (*a)[string((char *) c.get_key().data())] = c.bt_next_obj();
        c.bt_next_key();
    }
    lock.Release();

    catalog_journal_record *r = local_catalog->catalog_journal;

    while (r != NULL) {
        switch (r->type) {
        case catalog_journal_record::add_name:
            if (r->nor.object_type == ot) {
                (*a)[string(r->nor.name_to_save->name)] = r->nor.name_to_save->obj->p;
            }
            break;

        case catalog_journal_record::del_name:
            if (r->nor.object_type == ot) {
                (*a)[string(r->nor.name_to_save->name)] = XNULL;
            }
            break;
        }

        r = r->next;
    }
}

void catalog_complex_iterator::release_tree()
{
    if (this->it != NULL) {
        delete ((NameTreeIterator *) (this->it));
    }
    delete ((NameTree *) this->tmp_tree);
}
<commit_msg>catalog names fix 3<commit_after>#include <string>
#include <map>
#include "tr/cat/catenum.h"
#include "tr/cat/catjournal.h"

using namespace std;

#define NameTree map<string, xptr>
#define NameTreeIterator map<string, xptr>::iterator

xptr catalog_complex_iterator::get_object() const
{
    return (* (NameTreeIterator *) this->it)->second;
}

const char * catalog_complex_iterator::get_name() const
{
    return (* (NameTreeIterator *) this->it)->first.c_str();
}

bool catalog_complex_iterator::next()
{
    NameTree * a = (NameTree *) this->tmp_tree;

    if (this->it == NULL) {
        this->it = new NameTreeIterator(a->begin());
    } else {
        (* (NameTreeIterator *) this->it)++;
    }

    return ((* (NameTreeIterator *) this->it) != a->end());
}

void catalog_complex_iterator::build_tree(enum catalog_named_objects ot)
{
    NameTree * a = new NameTree();
    this->tmp_tree = a;
    SafeMetadataSemaphore lock;

    lock.Aquire();

    catalog_update_metadata();

    bt_cursor c = bt_lm(catalog_get_names(ot));

    while (!c.is_null()) {
        (*a)[string((char *) c.get_key().data())] = c.bt_next_obj();
        if (!c.bt_next_key()) break;
    }
    lock.Release();

    catalog_journal_record *r = local_catalog->catalog_journal;

    while (r != NULL) {
        switch (r->type) {
        case catalog_journal_record::add_name:
            if (r->nor.object_type == ot) {
                (*a)[string(r->nor.name_to_save->name)] = r->nor.name_to_save->obj->p;
            }
            break;

        case catalog_journal_record::del_name:
            if (r->nor.object_type == ot) {
                (*a)[string(r->nor.name_to_save->name)] = XNULL;
            }
            break;
        }

        r = r->next;
    }
}

void catalog_complex_iterator::release_tree()
{
    if (this->it != NULL) {
        delete ((NameTreeIterator *) (this->it));
    }
    delete ((NameTree *) this->tmp_tree);
}
<|endoftext|>