<commit_before>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <Beard/ui/Defs.hpp>
#include <Beard/ui/Context.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Widget/Defs.hpp>
#include <Beard/ui/Widget/Base.hpp>
#include <Beard/ui/Container.hpp>

#include <utility>

#include <Beard/detail/gr_ceformat.hpp>

namespace Beard {
namespace ui {

// class Context implementation

#define BEARD_SCOPE_CLASS ui::Context

Context::~Context() noexcept {
	close();
}

Context::Context() = default;
Context::Context(Context&&) = default;

Context& Context::operator=(Context&&) = default;

Context::Context(
	ui::PropertyMap property_map
)
	: m_terminal()
	, m_property_map(std::move(property_map))
{}

Context::Context(
	tty::TerminalInfo term_info,
	ui::PropertyMap property_map
)
	: m_terminal(std::move(term_info))
	, m_property_map(std::move(property_map))
{}

bool
Context::push_event(
	ui::Event const& event,
	ui::Widget::SPtr widget
) noexcept {
	while (widget) {
		if (widget->handle_event(event)) {
			return true;
		}
		widget = widget->get_parent();
	}
	return false;
}

// update queue

ui::UpdateActions
Context::run_actions(
	ui::Widget::RenderData& rd,
	ui::Widget::Base* widget,
	ui::UpdateActions const mask
) {
	auto const actions
		= widget->get_queued_actions()
		& (mask | ui::UpdateActions::mask_flags)
	;
	if (enum_cast(actions & ui::UpdateActions::reflow)) {
		widget->reflow(
			(widget == m_root.get())
			? Rect{{0, 0}, m_terminal.get_size()}
			: widget->get_geometry().get_area(),
			true
		);
	}
	if (enum_cast(actions & ui::UpdateActions::render)) {
		// TODO: Optimization: only clear if the terminal hasn't been
		// cleared entirely?
		if (!enum_cast(actions & ui::UpdateActions::flag_noclear)) {
			m_terminal.clear_back(widget->get_geometry().get_area());
		}
		rd.update_group(widget->get_group());
		widget->render(rd);
	}
	return actions;
}

inline static bool
widget_depth_less(
	ui::Widget::Base const* const lhs,
	ui::Widget::Base const* const rhs
) noexcept {
	return lhs->get_depth() < rhs->get_depth();
}

void
Context::run_all_actions() {
	ui::Widget::RenderData rd{
		*this,
		m_terminal,
		m_property_map,
		ui::group_null,
		m_property_map.cend(),
		m_property_map.find(m_fallback_group)
	};

	for (auto wp : m_action_queue) {
		if (!wp.expired()) {
			auto const widget = wp.lock();
			auto const actions = widget->get_queued_actions();
			if (
				enum_cast(actions & ui::UpdateActions::flag_parent) &&
				widget->has_parent()
			) {
				auto parent = widget->get_parent();
				if (parent->is_action_queued()) {
					widget->clear_actions(false);
					parent->queue_actions(actions);
					continue;
				}
			}
			if (widget->is_visible()) {
				widget->push_action_graph(m_execution_set, actions);
			} else {
				widget->clear_actions(false);
			}
		}
	}

	for (auto widget : m_execution_set) {
		m_execution_set_ordered.push_back(widget);
	}
	std::sort(
		m_execution_set_ordered.begin(),
		m_execution_set_ordered.end(),
		widget_depth_less
	);

	for (auto widget : m_execution_set_ordered) {
		run_actions(rd, widget, ui::UpdateActions::reflow);
	}
	for (auto widget : m_execution_set_ordered) {
		run_actions(rd, widget, ui::UpdateActions::render);
		widget->clear_actions(false);
	}
	clear_actions();
}

void
Context::enqueue_widget(
	ui::Widget::SPtr const& widget
) {
	m_action_queue.emplace(widget);
}

void
Context::dequeue_widget(
	ui::Widget::SPtr const& widget
) {
	auto it = m_action_queue.find(widget);
	if (m_action_queue.cend() != it) {
		m_action_queue.erase(it);
	}
}

void
Context::clear_actions() {
	for (auto wp : m_action_queue) {
		if (!wp.expired()) {
			wp.lock()->clear_actions(false);
		}
	}
	m_action_queue.clear();
	m_execution_set.clear();
	m_execution_set_ordered.clear();
}

void
Context::set_root(
	ui::RootSPtr root
) noexcept {
	m_root = std::move(root);
	if (m_root) {
		m_root->get_geometry().set_area(
			{{0, 0}, m_terminal.get_size()}
		);
		m_root->queue_actions(
			ui::UpdateActions::reflow
		);
	}
}

// operations

#define BEARD_SCOPE_FUNC open
void
Context::open(
	String const& tty_path,
	bool const use_sigwinch
) {
	if (m_terminal.is_open()) {
		BEARD_THROW_FQN(
			ErrorCode::ui_context_already_open,
			"context is already open"
		);
	}
	m_terminal.open(tty_path, use_sigwinch);
}
#undef BEARD_SCOPE_FUNC

void
Context::close() noexcept {
	clear_actions();
	m_terminal.close();
}

bool
Context::update(
	unsigned const input_timeout
) {
	tty::Event tty_event;
	ui::Widget::SPtr focus;
	m_event.type = ui::EventType::none;
	switch (m_terminal.poll(tty_event, input_timeout)) {
	case tty::EventType::resize:
		render(true);
		break;

	case tty::EventType::key_input:
		m_event.type = ui::EventType::key_input;
		m_event.key_input = tty_event.key_input;
		focus
			= get_root()->has_focus()
			? get_root()->get_focus()
			: get_root()
		;
		if (push_event(m_event, focus)) {
			return true;
		}
		break;

	case tty::EventType::none:
		break;
	}

	if (!m_action_queue.empty()) {
		run_all_actions();
		m_terminal.present();
	}
	return false;
}

void
Context::render(
	bool const reflow
) {
	m_root->queue_actions(
		ui::UpdateActions::render |
		(reflow ? ui::UpdateActions::reflow : ui::UpdateActions::none)
	);
	run_all_actions();
	m_terminal.present();
}

#undef BEARD_SCOPE_CLASS // ui::Context

} // namespace ui
} // namespace Beard
<commit_msg>ui::Context: set root area and queue actions on terminal resize instead of explicitly rendering.<commit_after>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <Beard/ui/Defs.hpp>
#include <Beard/ui/Context.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Widget/Defs.hpp>
#include <Beard/ui/Widget/Base.hpp>
#include <Beard/ui/Container.hpp>

#include <utility>

#include <Beard/detail/gr_ceformat.hpp>

namespace Beard {
namespace ui {

// class Context implementation

#define BEARD_SCOPE_CLASS ui::Context

Context::~Context() noexcept {
	close();
}

Context::Context() = default;
Context::Context(Context&&) = default;

Context& Context::operator=(Context&&) = default;

Context::Context(
	ui::PropertyMap property_map
)
	: m_terminal()
	, m_property_map(std::move(property_map))
{}

Context::Context(
	tty::TerminalInfo term_info,
	ui::PropertyMap property_map
)
	: m_terminal(std::move(term_info))
	, m_property_map(std::move(property_map))
{}

bool
Context::push_event(
	ui::Event const& event,
	ui::Widget::SPtr widget
) noexcept {
	while (widget) {
		if (widget->handle_event(event)) {
			return true;
		}
		widget = widget->get_parent();
	}
	return false;
}

// update queue

ui::UpdateActions
Context::run_actions(
	ui::Widget::RenderData& rd,
	ui::Widget::Base* widget,
	ui::UpdateActions const mask
) {
	auto const actions
		= widget->get_queued_actions()
		& (mask | ui::UpdateActions::mask_flags)
	;
	if (enum_cast(actions & ui::UpdateActions::reflow)) {
		widget->reflow(
			(widget == m_root.get())
			? Rect{{0, 0}, m_terminal.get_size()}
			: widget->get_geometry().get_area(),
			true
		);
	}
	if (enum_cast(actions & ui::UpdateActions::render)) {
		// TODO: Optimization: only clear if the terminal hasn't been
		// cleared entirely?
		if (!enum_cast(actions & ui::UpdateActions::flag_noclear)) {
			m_terminal.clear_back(widget->get_geometry().get_area());
		}
		rd.update_group(widget->get_group());
		widget->render(rd);
	}
	return actions;
}

inline static bool
widget_depth_less(
	ui::Widget::Base const* const lhs,
	ui::Widget::Base const* const rhs
) noexcept {
	return lhs->get_depth() < rhs->get_depth();
}

void
Context::run_all_actions() {
	ui::Widget::RenderData rd{
		*this,
		m_terminal,
		m_property_map,
		ui::group_null,
		m_property_map.cend(),
		m_property_map.find(m_fallback_group)
	};

	for (auto wp : m_action_queue) {
		if (!wp.expired()) {
			auto const widget = wp.lock();
			auto const actions = widget->get_queued_actions();
			if (
				enum_cast(actions & ui::UpdateActions::flag_parent) &&
				widget->has_parent()
			) {
				auto parent = widget->get_parent();
				if (parent->is_action_queued()) {
					widget->clear_actions(false);
					parent->queue_actions(actions);
					continue;
				}
			}
			if (widget->is_visible()) {
				widget->push_action_graph(m_execution_set, actions);
			} else {
				widget->clear_actions(false);
			}
		}
	}

	for (auto widget : m_execution_set) {
		m_execution_set_ordered.push_back(widget);
	}
	std::sort(
		m_execution_set_ordered.begin(),
		m_execution_set_ordered.end(),
		widget_depth_less
	);

	for (auto widget : m_execution_set_ordered) {
		run_actions(rd, widget, ui::UpdateActions::reflow);
	}
	for (auto widget : m_execution_set_ordered) {
		run_actions(rd, widget, ui::UpdateActions::render);
		widget->clear_actions(false);
	}
	clear_actions();
}

void
Context::enqueue_widget(
	ui::Widget::SPtr const& widget
) {
	m_action_queue.emplace(widget);
}

void
Context::dequeue_widget(
	ui::Widget::SPtr const& widget
) {
	auto it = m_action_queue.find(widget);
	if (m_action_queue.cend() != it) {
		m_action_queue.erase(it);
	}
}

void
Context::clear_actions() {
	for (auto wp : m_action_queue) {
		if (!wp.expired()) {
			wp.lock()->clear_actions(false);
		}
	}
	m_action_queue.clear();
	m_execution_set.clear();
	m_execution_set_ordered.clear();
}

void
Context::set_root(
	ui::RootSPtr root
) noexcept {
	m_root = std::move(root);
	if (m_root) {
		m_root->get_geometry().set_area(
			{{0, 0}, m_terminal.get_size()}
		);
		m_root->queue_actions(
			ui::UpdateActions::reflow
		);
	}
}

// operations

#define BEARD_SCOPE_FUNC open
void
Context::open(
	String const& tty_path,
	bool const use_sigwinch
) {
	if (m_terminal.is_open()) {
		BEARD_THROW_FQN(
			ErrorCode::ui_context_already_open,
			"context is already open"
		);
	}
	m_terminal.open(tty_path, use_sigwinch);
}
#undef BEARD_SCOPE_FUNC

void
Context::close() noexcept {
	clear_actions();
	m_terminal.close();
}

bool
Context::update(
	unsigned const input_timeout
) {
	tty::Event tty_event;
	ui::Widget::SPtr focus;
	m_event.type = ui::EventType::none;
	switch (m_terminal.poll(tty_event, input_timeout)) {
	case tty::EventType::resize:
		m_root->get_geometry().set_area(
			{{0, 0}, m_terminal.get_size()}
		);
		m_root->queue_actions(
			ui::UpdateActions::render |
			ui::UpdateActions::reflow
		);
		break;

	case tty::EventType::key_input:
		m_event.type = ui::EventType::key_input;
		m_event.key_input = tty_event.key_input;
		focus
			= get_root()->has_focus()
			? get_root()->get_focus()
			: get_root()
		;
		if (push_event(m_event, focus)) {
			return true;
		}
		break;

	case tty::EventType::none:
		break;
	}

	if (!m_action_queue.empty()) {
		run_all_actions();
		m_terminal.present();
	}
	return false;
}

void
Context::render(
	bool const reflow
) {
	m_root->queue_actions(
		ui::UpdateActions::render |
		(reflow ? ui::UpdateActions::reflow : ui::UpdateActions::none)
	);
	run_all_actions();
	m_terminal.present();
}

#undef BEARD_SCOPE_CLASS // ui::Context

} // namespace ui
} // namespace Beard
<|endoftext|>


<commit_before>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/filesystem/operations.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionPlugin.hpp>

#ifdef PION_WIN32
	#include <windows.h>
#else
	#include <dlfcn.h>
#endif

namespace pion {	// begin namespace pion

// static members of PionPlugin

const std::string			PionPlugin::PION_PLUGIN_CREATE("pion_create_");
const std::string			PionPlugin::PION_PLUGIN_DESTROY("pion_destroy_");
#ifdef PION_WIN32
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".dll");
#else
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".so");
#endif
const std::string			PionPlugin::PION_CONFIG_EXTENSION(".conf");
std::vector<std::string>	PionPlugin::m_plugin_dirs;
PionPlugin::PluginMap		PionPlugin::m_plugin_map;
boost::mutex				PionPlugin::m_plugin_mutex;
PionPlugin::StaticEntryPointList	*PionPlugin::m_entry_points_ptr = NULL;

// PionPlugin member functions

void PionPlugin::checkCygwinPath(boost::filesystem::path& final_path,
								 const std::string& start_path)
{
#if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
	// try prepending PION_CYGWIN_DIRECTORY if not complete
	if (! final_path.is_complete() && final_path.has_root_directory()) {
		final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
	}
#endif
}

void PionPlugin::addPluginDirectory(const std::string& dir)
{
#ifdef PION_WIN32
	// work around bug in boost::filesystem on Windows -> do not plugin directories
	// basically, if you create a path object on Windows, then convert it to
	// directory_string() or file_string(), then try to construct
	// a new path object based on the string, it throws an exception (ugh!!!)
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.push_back(dir);
#else
	boost::filesystem::path plugin_path(dir);
	checkCygwinPath(plugin_path, dir);
	if (! boost::filesystem::exists(plugin_path) )
		throw DirectoryNotFoundException(dir);
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.push_back(plugin_path.directory_string());
#endif
}

void PionPlugin::resetPluginDirectories(void)
{
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.clear();
}

void PionPlugin::open(const std::string& plugin_file)
{
	releaseData();	// make sure we're not already pointing to something

	// use a temporary object first since openPlugin() may throw
	PionPluginData plugin_data(getPluginName(plugin_file));

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_data.m_plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// open up the shared library using our temporary data object
		openPlugin(plugin_file, plugin_data);	// may throw

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_data);
		m_plugin_map.insert( std::make_pair(m_plugin_data->m_plugin_name,
											m_plugin_data) );
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::openStaticLinked(const std::string& plugin_name,
								  void *create_func,
								  void *destroy_func)
{
	releaseData();	// make sure we're not already pointing to something

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_name);
		m_plugin_data->m_lib_handle = NULL; // this will indicate that we are using statically linked plug-in
		m_plugin_data->m_create_func = create_func;
		m_plugin_data->m_destroy_func = destroy_func;
		m_plugin_map.insert(std::make_pair(m_plugin_data->m_plugin_name,
										   m_plugin_data));
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::releaseData(void)
{
	if (m_plugin_data != NULL) {
		boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
		// double-check after locking mutex
		if (m_plugin_data != NULL && --m_plugin_data->m_references == 0) {

// The handling of dynamic libraries on Windows is EXTREMELY buggy, so if
// we are running on Windows, never release the shared libraries
#ifndef PION_WIN32
			// no more references to the plug-in library

			// release the shared object
			closeDynamicLibrary(m_plugin_data->m_lib_handle);

			// remove it from the plug-in map
			PluginMap::iterator itr = m_plugin_map.find(m_plugin_data->m_plugin_name);
			// check itr just to be safe (it SHOULD always find a match)
			if (itr != m_plugin_map.end())
				m_plugin_map.erase(itr);

			// release the heap object
			delete m_plugin_data;
#endif

		}
		m_plugin_data = NULL;
	}
}

void PionPlugin::grabData(const PionPlugin& p)
{
	releaseData();	// make sure we're not already pointing to something
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_data = const_cast<PionPluginData*>(p.m_plugin_data);
	if (m_plugin_data != NULL) {
		++ m_plugin_data->m_references;
	}
}

bool PionPlugin::findFile(std::string& path_to_file, const std::string& name,
						  const std::string& extension)
{
	// first, try the name as-is
	if (checkForFile(path_to_file, name, "", extension))
		return true;

	// nope, check search paths
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	for (std::vector<std::string>::iterator i = m_plugin_dirs.begin();
		 i != m_plugin_dirs.end(); ++i)
	{
		if (checkForFile(path_to_file, *i, name, extension))
			return true;
	}

	// no plug-in file found
	return false;
}

bool PionPlugin::checkForFile(std::string& final_path, const std::string& start_path,
							  const std::string& name, const std::string& extension)
{
	// check for cygwin path oddities
	boost::filesystem::path cygwin_safe_path(start_path);
	checkCygwinPath(cygwin_safe_path, start_path);
	boost::filesystem::path test_path(cygwin_safe_path);

	// if a name is specified, append it to the test path
	if (! name.empty())
		test_path /= name;

	// check for existence of plug-in (without extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// next, try appending the plug-in extension
	if (name.empty()) {
		// no "name" specified -> append it directly to start_path
		test_path = boost::filesystem::path(start_path + extension);
		// in this case, we need to re-check for the cygwin oddities
		checkCygwinPath(test_path, start_path + extension);
	} else {
		// name is specified, so we can just re-use cygwin_safe_path
		test_path = cygwin_safe_path /
			boost::filesystem::path(name + extension);
	}

	// re-check for existence of plug-in (after adding extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// no plug-in file found
	return false;
}

void PionPlugin::openPlugin(const std::string& plugin_file,
							PionPluginData& plugin_data)
{
	// get the name of the plugin (for create/destroy symbol names)
	plugin_data.m_plugin_name = getPluginName(plugin_file);

	// attempt to open the plugin; note that this tries all search paths
	// and also tries a variety of platform-specific extensions
	plugin_data.m_lib_handle = loadDynamicLibrary(plugin_file.c_str());
	if (plugin_data.m_lib_handle == NULL)
		throw PluginNotFoundException(plugin_file);

	// find the function used to create new plugin objects
	plugin_data.m_create_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
	if (plugin_data.m_create_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingCreateException(plugin_file);
	}

	// find the function used to destroy existing plugin objects
	plugin_data.m_destroy_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
	if (plugin_data.m_destroy_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingDestroyException(plugin_file);
	}
}

std::string PionPlugin::getPluginName(const std::string& plugin_file)
{
	// strip path
#ifdef PION_WIN32
	std::string::size_type pos = plugin_file.find_last_of('\\');
#else
	std::string::size_type pos = plugin_file.find_last_of('/');
#endif
	std::string plugin_name = (pos == std::string::npos ?
							   plugin_file : plugin_file.substr(pos+1));
	pos = plugin_name.find('.');

	// truncate extension
	if (pos != std::string::npos)
		plugin_name.resize(pos);

	return plugin_name;
}

void *PionPlugin::loadDynamicLibrary(const std::string& plugin_file)
{
#ifdef PION_WIN32
	#ifdef BOOST_MSVC
		return LoadLibraryA(plugin_file.c_str());
	#else
		return LoadLibrary(plugin_file.c_str());
	#endif
#else
	return dlopen(plugin_file.c_str(), RTLD_LAZY);
#endif
}

void PionPlugin::closeDynamicLibrary(void *lib_handle)
{
#ifdef PION_WIN32
	FreeLibrary((HINSTANCE) lib_handle);
#else
	dlclose(lib_handle);
#endif
}

void *PionPlugin::getLibrarySymbol(void *lib_handle, const std::string& symbol)
{
#ifdef PION_WIN32
	return (void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
#else
	return dlsym(lib_handle, symbol.c_str());
#endif
}

bool PionPlugin::findStaticEntryPoint(const std::string& plugin_name,
									  void **create_func,
									  void **destroy_func)
{
	// check simple case first: no entry points exist
	if (m_entry_points_ptr == NULL || m_entry_points_ptr->empty())
		return false;

	// try to find the entry point for the plugin
	for (std::list<StaticEntryPoint>::const_iterator i = m_entry_points_ptr->begin();
		 i != m_entry_points_ptr->end(); ++i) {
			if (i->m_plugin_name==plugin_name) {
				*create_func  = i->m_create_func;
				*destroy_func = i->m_destroy_func;
				return true;
			}
	}
	return false;
}

void PionPlugin::addStaticEntryPoint(const std::string& plugin_name,
									 void *create_func,
									 void *destroy_func)
{
	// make sure that this function can only be called by one thread at a time
	static boost::mutex			entrypoint_mutex;
	boost::mutex::scoped_lock	entrypoint_lock(entrypoint_mutex);

	// create the entry point list if it doesn't already exist
	if (m_entry_points_ptr == NULL)
		m_entry_points_ptr = new StaticEntryPointList;

	// insert it into the entry point list
	m_entry_points_ptr->push_back(StaticEntryPoint(plugin_name, create_func, destroy_func));
}

}	// end namespace pion
<commit_msg>Removed no longer needed work-around from PionPlugin::addPluginDirectory.<commit_after>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/filesystem/operations.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionPlugin.hpp>

#ifdef PION_WIN32
	#include <windows.h>
#else
	#include <dlfcn.h>
#endif

namespace pion {	// begin namespace pion

// static members of PionPlugin

const std::string			PionPlugin::PION_PLUGIN_CREATE("pion_create_");
const std::string			PionPlugin::PION_PLUGIN_DESTROY("pion_destroy_");
#ifdef PION_WIN32
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".dll");
#else
	const std::string			PionPlugin::PION_PLUGIN_EXTENSION(".so");
#endif
const std::string			PionPlugin::PION_CONFIG_EXTENSION(".conf");
std::vector<std::string>	PionPlugin::m_plugin_dirs;
PionPlugin::PluginMap		PionPlugin::m_plugin_map;
boost::mutex				PionPlugin::m_plugin_mutex;
PionPlugin::StaticEntryPointList	*PionPlugin::m_entry_points_ptr = NULL;

// PionPlugin member functions

void PionPlugin::checkCygwinPath(boost::filesystem::path& final_path,
								 const std::string& start_path)
{
#if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
	// try prepending PION_CYGWIN_DIRECTORY if not complete
	if (! final_path.is_complete() && final_path.has_root_directory()) {
		final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
	}
#endif
}

void PionPlugin::addPluginDirectory(const std::string& dir)
{
	boost::filesystem::path plugin_path(dir);
	checkCygwinPath(plugin_path, dir);
	if (! boost::filesystem::exists(plugin_path) )
		throw DirectoryNotFoundException(dir);
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.push_back(plugin_path.directory_string());
}

void PionPlugin::resetPluginDirectories(void)
{
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_dirs.clear();
}

void PionPlugin::open(const std::string& plugin_file)
{
	releaseData();	// make sure we're not already pointing to something

	// use a temporary object first since openPlugin() may throw
	PionPluginData plugin_data(getPluginName(plugin_file));

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_data.m_plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// open up the shared library using our temporary data object
		openPlugin(plugin_file, plugin_data);	// may throw

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_data);
		m_plugin_map.insert( std::make_pair(m_plugin_data->m_plugin_name,
											m_plugin_data) );
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::openStaticLinked(const std::string& plugin_name,
								  void *create_func,
								  void *destroy_func)
{
	releaseData();	// make sure we're not already pointing to something

	// check to see if we already have a matching shared library
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	PluginMap::iterator itr = m_plugin_map.find(plugin_name);
	if (itr == m_plugin_map.end()) {
		// no plug-ins found with the same name

		// all is good -> insert it into the plug-in map
		m_plugin_data = new PionPluginData(plugin_name);
		m_plugin_data->m_lib_handle = NULL; // this will indicate that we are using statically linked plug-in
		m_plugin_data->m_create_func = create_func;
		m_plugin_data->m_destroy_func = destroy_func;
		m_plugin_map.insert(std::make_pair(m_plugin_data->m_plugin_name,
										   m_plugin_data));
	} else {
		// found an existing plug-in with the same name
		m_plugin_data = itr->second;
	}

	// increment the number of references
	++ m_plugin_data->m_references;
}

void PionPlugin::releaseData(void)
{
	if (m_plugin_data != NULL) {
		boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
		// double-check after locking mutex
		if (m_plugin_data != NULL && --m_plugin_data->m_references == 0) {

// The handling of dynamic libraries on Windows is EXTREMELY buggy, so if
// we are running on Windows, never release the shared libraries
#ifndef PION_WIN32
			// no more references to the plug-in library

			// release the shared object
			closeDynamicLibrary(m_plugin_data->m_lib_handle);

			// remove it from the plug-in map
			PluginMap::iterator itr = m_plugin_map.find(m_plugin_data->m_plugin_name);
			// check itr just to be safe (it SHOULD always find a match)
			if (itr != m_plugin_map.end())
				m_plugin_map.erase(itr);

			// release the heap object
			delete m_plugin_data;
#endif

		}
		m_plugin_data = NULL;
	}
}

void PionPlugin::grabData(const PionPlugin& p)
{
	releaseData();	// make sure we're not already pointing to something
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	m_plugin_data = const_cast<PionPluginData*>(p.m_plugin_data);
	if (m_plugin_data != NULL) {
		++ m_plugin_data->m_references;
	}
}

bool PionPlugin::findFile(std::string& path_to_file, const std::string& name,
						  const std::string& extension)
{
	// first, try the name as-is
	if (checkForFile(path_to_file, name, "", extension))
		return true;

	// nope, check search paths
	boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
	for (std::vector<std::string>::iterator i = m_plugin_dirs.begin();
		 i != m_plugin_dirs.end(); ++i)
	{
		if (checkForFile(path_to_file, *i, name, extension))
			return true;
	}

	// no plug-in file found
	return false;
}

bool PionPlugin::checkForFile(std::string& final_path, const std::string& start_path,
							  const std::string& name, const std::string& extension)
{
	// check for cygwin path oddities
	boost::filesystem::path cygwin_safe_path(start_path);
	checkCygwinPath(cygwin_safe_path, start_path);
	boost::filesystem::path test_path(cygwin_safe_path);

	// if a name is specified, append it to the test path
	if (! name.empty())
		test_path /= name;

	// check for existence of plug-in (without extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// next, try appending the plug-in extension
	if (name.empty()) {
		// no "name" specified -> append it directly to start_path
		test_path = boost::filesystem::path(start_path + extension);
		// in this case, we need to re-check for the cygwin oddities
		checkCygwinPath(test_path, start_path + extension);
	} else {
		// name is specified, so we can just re-use cygwin_safe_path
		test_path = cygwin_safe_path /
			boost::filesystem::path(name + extension);
	}

	// re-check for existence of plug-in (after adding extension)
	if (boost::filesystem::exists(test_path)) {
		final_path = test_path.file_string();
		return true;
	}

	// no plug-in file found
	return false;
}

void PionPlugin::openPlugin(const std::string& plugin_file,
							PionPluginData& plugin_data)
{
	// get the name of the plugin (for create/destroy symbol names)
	plugin_data.m_plugin_name = getPluginName(plugin_file);

	// attempt to open the plugin; note that this tries all search paths
	// and also tries a variety of platform-specific extensions
	plugin_data.m_lib_handle = loadDynamicLibrary(plugin_file.c_str());
	if (plugin_data.m_lib_handle == NULL)
		throw PluginNotFoundException(plugin_file);

	// find the function used to create new plugin objects
	plugin_data.m_create_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
	if (plugin_data.m_create_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingCreateException(plugin_file);
	}

	// find the function used to destroy existing plugin objects
	plugin_data.m_destroy_func =
		getLibrarySymbol(plugin_data.m_lib_handle,
						 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
	if (plugin_data.m_destroy_func == NULL) {
		closeDynamicLibrary(plugin_data.m_lib_handle);
		throw PluginMissingDestroyException(plugin_file);
	}
}

std::string PionPlugin::getPluginName(const std::string& plugin_file)
{
	// strip path
#ifdef PION_WIN32
	std::string::size_type pos = plugin_file.find_last_of('\\');
#else
	std::string::size_type pos = plugin_file.find_last_of('/');
#endif
	std::string plugin_name = (pos == std::string::npos ?
							   plugin_file : plugin_file.substr(pos+1));
	pos = plugin_name.find('.');

	// truncate extension
	if (pos != std::string::npos)
		plugin_name.resize(pos);

	return plugin_name;
}

void *PionPlugin::loadDynamicLibrary(const std::string& plugin_file)
{
#ifdef PION_WIN32
	#ifdef BOOST_MSVC
		return LoadLibraryA(plugin_file.c_str());
	#else
		return LoadLibrary(plugin_file.c_str());
	#endif
#else
	return dlopen(plugin_file.c_str(), RTLD_LAZY);
#endif
}

void PionPlugin::closeDynamicLibrary(void *lib_handle)
{
#ifdef PION_WIN32
	FreeLibrary((HINSTANCE) lib_handle);
#else
	dlclose(lib_handle);
#endif
}

void *PionPlugin::getLibrarySymbol(void *lib_handle, const std::string& symbol)
{
#ifdef PION_WIN32
	return (void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
#else
	return dlsym(lib_handle, symbol.c_str());
#endif
}

bool PionPlugin::findStaticEntryPoint(const std::string& plugin_name,
									  void **create_func,
									  void **destroy_func)
{
	// check simple case first: no entry points exist
	if (m_entry_points_ptr == NULL || m_entry_points_ptr->empty())
		return false;

	// try to find the entry point for the plugin
	for (std::list<StaticEntryPoint>::const_iterator i = m_entry_points_ptr->begin();
		 i != m_entry_points_ptr->end(); ++i) {
			if (i->m_plugin_name==plugin_name) {
				*create_func  = i->m_create_func;
				*destroy_func = i->m_destroy_func;
				return true;
			}
	}
	return false;
}

void PionPlugin::addStaticEntryPoint(const std::string& plugin_name,
									 void *create_func,
									 void *destroy_func)
{
	// make sure that this function can only be called by one thread at a time
	static boost::mutex			entrypoint_mutex;
	boost::mutex::scoped_lock	entrypoint_lock(entrypoint_mutex);

	// create the entry point list if it doesn't already exist
	if (m_entry_points_ptr == NULL)
		m_entry_points_ptr = new StaticEntryPointList;

	// insert it into the entry point list
	m_entry_points_ptr->push_back(StaticEntryPoint(plugin_name, create_func, destroy_func));
}

}	// end namespace pion
<|endoftext|>


<commit_before>#ifndef TOKENS_H_
#define TOKENS_H_

#include <string>
#include <vector>

#include "global.hpp"
#include "operators.hpp"
#include "builtins.hpp"

namespace lang {
  // This means the token was created by the interpreter
  #define PHONY_TOKEN -2

  enum TokenType: int {
    INTEGER, FLOAT, BOOLEAN, STRING, ARRAY, // Literals
    OPERATOR, KEYWORD, CONSTRUCT, // Language parts
    TYPE, MEMBER, VARIABLE, FUNCTION, // Defined structures
    UNPROCESSED
  };

  class Token {
  public:
    std::string data = "";
    TokenType type = UNPROCESSED;
    /*
    * Depending on the TokenType, the pointer has the following possible types:
    * For OPERATOR: Operator*
    * For INTEGER: Integer*
    * For FLOAT: Float*
    * For VARIABLE: Variable*
    */
    void* typeData = nullptr;
    /*
    * Location of Token in code.
    * -1 by default. -2 when Token was created by interpreter.
    */
    int line = -1;

    Token();
    Token(std::string data, TokenType type, int line);
    Token(Operator* opContent, TokenType type, int line);
    Token(Object* obj, TokenType type, int line);
  };

  inline std::ostream& operator<<(std::ostream& os, Token& tok) {
    return os << "Token " << tok.data << ", TokenType " << tok.type << ", with data pointer " << tok.typeData << ", at line " << tok.line;
  }

  extern std::function<bool(Token)> isNewLine;

} /* namespace lang */

#endif /* TOKENS_H_ */
<commit_msg>Made TokenType easier to identify<commit_after>#ifndef TOKENS_H_
#define TOKENS_H_

#include <string>
#include <vector>

#include "global.hpp"
#include "operators.hpp"
#include "builtins.hpp"

namespace lang {
  // This means the token was created by the interpreter
  #define PHONY_TOKEN -2

  enum TokenType: int {
    INTEGER = 0, FLOAT, BOOLEAN, STRING, ARRAY, // Literals
    OPERATOR = 5, KEYWORD, CONSTRUCT, // Language parts
    TYPE, MEMBER, VARIABLE = 10, FUNCTION, // Defined structures
    UNPROCESSED
  };

  class Token {
  public:
    std::string data = "";
    TokenType type = UNPROCESSED;
    /*
    * Depending on the TokenType, the pointer has the following possible types:
    * For OPERATOR: Operator*
    * For INTEGER: Integer*
    * For FLOAT: Float*
    * For VARIABLE: Variable*
    */
    void* typeData = nullptr;
    /*
    * Location of Token in code.
    * -1 by default. -2 when Token was created by interpreter.
    */
    int line = -1;

    Token();
    Token(std::string data, TokenType type, int line);
    Token(Operator* opContent, TokenType type, int line);
    Token(Object* obj, TokenType type, int line);
  };

  inline std::ostream& operator<<(std::ostream& os, Token& tok) {
    return os << "Token " << tok.data << ", TokenType " << tok.type << ", with data pointer " << tok.typeData << ", at line " << tok.line;
  }

  extern std::function<bool(Token)> isNewLine;

} /* namespace lang */

#endif /* TOKENS_H_ */
<|endoftext|>


<commit_before>/* YO @Flowing-water we gotta start plopping GPL all up in here */

#include "ssl_fn.h"
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char *create_sha1sum(char *dst)
{
    SHA_CTX ctx; // sha1 struct (look at sha.h)
    unsigned char *sha1sum = NULL; // sha1sum dest
    char buffer[file_input_buff_size]; // buffer for file i/o
    FILE *p_dst = NULL; // fd to dst

    p_dst = fopen(dst, "r");
    if (!p_dst) {
	/* we gonna have a log fn? */
	perror("fopen");
	goto end;
    }

    // wtf spartan naming and camel case? nice libssl
    if (!SHA1_Init(&ctx))// init the struct
	goto end; // ssl calls return 0 on fail

    // read file in
    while (fgets(buffer, file_input_buff_size, p_dst)) {
	// update teh sha1sum with what we read
	if(!SHA1_Update(&ctx,
			(void*)buffer,
			strlen(buffer))) // u like this syntax @ flowing? u mad bro?
	    goto end;
    }
    // create hash
    sha1sum = (unsigned char*)malloc(sizeof(char) * SHA_DIGEST_LENGTH);
    if (!sha1sum)
	goto end;
    SHA1_Final(sha1sum, &ctx);

 end:
    return sha1sum;
}
<commit_msg>forgot to close fd<commit_after>/* YO @Flowing-water we gotta start plopping GPL all up in here */

#include "ssl_fn.h"
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char *create_sha1sum(char *dst)
{
    SHA_CTX ctx; // sha1 struct (look at sha.h)
    unsigned char *sha1sum = NULL; // sha1sum dest
    unsigned char buffer[file_input_buff_size]; // buffer for file i/o
    FILE *p_dst = NULL; // fd to dst
    size_t read_size = 0;

    p_dst = fopen(dst, "r");
    if (!p_dst) {
	/* we gonna have a log fn? */
	perror("fopen");
	goto end;
    }

    // wtf spartan naming and camel case? nice libssl
    if (!SHA1_Init(&ctx))// init the struct
	goto end; // ssl calls return 0 on fail

    // read file in
    do {
	read_size = fread(buffer, sizeof(unsigned char), file_input_buff_size, p_dst);
	// update teh sha1sum with what we read
	if(!SHA1_Update(&ctx,
			(void*)buffer,
			read_size)) // u like this syntax @ flowing? u mad bro?
	    goto end;
    } while (read_size == file_input_buff_size); // fread returns less than that size on failure

    // create hash
    sha1sum = (unsigned char*)malloc(sizeof(char) * SHA_DIGEST_LENGTH);
    if (!sha1sum)
	goto end;
    SHA1_Final(sha1sum, &ctx);

 end:
    if(p_dst)
	fclose(p_dst);
    return sha1sum;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "timing.hpp"

using namespace eddic;

timing_timer::timing_timer(timing_system& system, const std::string& name) : system(system), name(name) {
    //Nothing
}

timing_timer::~timing_timer(){
    system.register_timing(name, timer.elapsed());
}

timing_system::timing_system(std::shared_ptr<Configuration> configuration) : configuration(configuration) {
    //Nothing
}

timing_system::~timing_system(){
    for(auto& timing : timings){
        std::cout << timing.first << ":" << timing.second << "ms" << std::endl;
    }
}

void timing_system::register_timing(std::string name, double time){
    timings[name] += time;
}
<commit_msg>Display only if the option is defined<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "timing.hpp"

using namespace eddic;

timing_timer::timing_timer(timing_system& system, const std::string& name) : system(system), name(name) {
    //Nothing
}

timing_timer::~timing_timer(){
    system.register_timing(name, timer.elapsed());
}

timing_system::timing_system(std::shared_ptr<Configuration> configuration) : configuration(configuration) {
    //Nothing
}

timing_system::~timing_system(){
    if(configuration->option_defined("timing")){
        for(auto& timing : timings){
            std::cout << timing.first << ":" << timing.second << "ms" << std::endl;
        }
    }
}

void timing_system::register_timing(std::string name, double time){
    timings[name] += time;
}
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"
#include "eventpipe.h"
#include "eventpipeeventinstance.h"
#include "eventpipebuffer.h"

#ifdef FEATURE_PERFTRACING

EventPipeBuffer::EventPipeBuffer(unsigned int bufferSize)
{
    CONTRACTL
    {
        THROWS;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    m_pBuffer = new BYTE[bufferSize];
    memset(m_pBuffer, 0, bufferSize);
    m_pLimit = m_pBuffer + bufferSize;
    m_pCurrent = GetNextAlignedAddress(m_pBuffer);

    m_mostRecentTimeStamp.QuadPart = 0;
    m_pLastPoppedEvent = NULL;
    m_pPrevBuffer = NULL;
    m_pNextBuffer = NULL;
}

EventPipeBuffer::~EventPipeBuffer()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    if(m_pBuffer != NULL)
    {
        delete[] m_pBuffer;
    }
}

bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeSession &session, EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
        PRECONDITION(((size_t)m_pCurrent % AlignmentSize) == 0);
    }
    CONTRACTL_END;

    // Calculate the size of the event.
    unsigned int eventSize = sizeof(EventPipeEventInstance) + payload.GetSize();

    // Make sure we have enough space to write the event.
    if(m_pCurrent + eventSize >= m_pLimit)
    {
        return false;
    }

    bool success = true;
    EX_TRY
    {
        // Calculate the location of the data payload.
        BYTE *pDataDest = payload.GetSize() == 0 ? NULL : m_pCurrent + sizeof(EventPipeEventInstance);

        // Placement-new the EventPipeEventInstance.
        // if pthread is NULL, it's likely we are running in something like a GC thread which is not a Thread object, so it can't have an activity ID set anyway
        EventPipeEventInstance *pInstance = new (m_pCurrent) EventPipeEventInstance(
            session,
            event,
            (pThread == NULL) ? ::GetCurrentThreadId() : pThread->GetOSThreadId(),
            pDataDest,
            payload.GetSize(),
            (pThread == NULL) ? NULL : pActivityId,
            pRelatedActivityId);

        // Copy the stack if a separate stack trace was provided.
        if(pStack != NULL)
        {
            StackContents *pInstanceStack = pInstance->GetStack();
            pStack->CopyTo(pInstanceStack);
        }

        // Write the event payload data to the buffer.
        if(payload.GetSize() > 0)
        {
            payload.CopyData(pDataDest);
        }

        // Save the most recent event timestamp.
        m_mostRecentTimeStamp = *pInstance->GetTimeStamp();

    }
    EX_CATCH
    {
        // If a failure occurs, bail out and don't advance the pointer.
        success = false;
    }
    EX_END_CATCH(SwallowAllExceptions);

    if(success)
    {
        // Advance the current pointer past the event.
        m_pCurrent = GetNextAlignedAddress(m_pCurrent + eventSize);
    }

    return success;
}

LARGE_INTEGER EventPipeBuffer::GetMostRecentTimeStamp() const
{
    LIMITED_METHOD_CONTRACT;

    return m_mostRecentTimeStamp;
}

void EventPipeBuffer::Clear()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

    memset(m_pBuffer, 0, (size_t)(m_pLimit - m_pBuffer));
    m_pCurrent = GetNextAlignedAddress(m_pBuffer);
    m_mostRecentTimeStamp.QuadPart = 0;
    m_pLastPoppedEvent = NULL;
}

EventPipeEventInstance* EventPipeBuffer::GetNext(EventPipeEventInstance *pEvent, LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    EventPipeEventInstance *pNextInstance = NULL;
    // If input is NULL, return the first event if there is one.
    if(pEvent == NULL)
    {
        // If this buffer contains an event, select it.
        BYTE *pFirstAlignedInstance = GetNextAlignedAddress(m_pBuffer);
        if(m_pCurrent > pFirstAlignedInstance)
        {
            pNextInstance = (EventPipeEventInstance*)pFirstAlignedInstance;
        }
        else
        {
            return NULL;
        }
    }
    else
    {
        // Confirm that pEvent is within the used range of the buffer.
        if(((BYTE*)pEvent < m_pBuffer) || ((BYTE*)pEvent >= m_pCurrent))
        {
            _ASSERT(!"Input pointer is out of range.");
            return NULL;
        }

        // We have a pointer within the bounds of the buffer.
        // Find the next event by skipping the current event with it's data payload immediately after the instance.
        pNextInstance = (EventPipeEventInstance *)GetNextAlignedAddress(const_cast<BYTE *>(pEvent->GetData() + pEvent->GetDataLength()));

        // Check to see if we've reached the end of the written portion of the buffer.
        if((BYTE*)pNextInstance >= m_pCurrent)
        {
            return NULL;
        }
    }

    // Ensure that the timestamp is valid.  The buffer is zero'd before use, so a zero timestamp is invalid.
    LARGE_INTEGER nextTimeStamp = *pNextInstance->GetTimeStamp();
    if(nextTimeStamp.QuadPart == 0)
    {
        return NULL;
    }

    // Ensure that the timestamp is earlier than the beforeTimeStamp.
    if(nextTimeStamp.QuadPart >= beforeTimeStamp.QuadPart)
    {
        return NULL;
    }

    return pNextInstance;
}

EventPipeEventInstance* EventPipeBuffer::PeekNext(LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Get the next event using the last popped event as a marker.
    return GetNext(m_pLastPoppedEvent, beforeTimeStamp);
}

EventPipeEventInstance* EventPipeBuffer::PopNext(LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Get the next event using the last popped event as a marker.
    EventPipeEventInstance *pNext = PeekNext(beforeTimeStamp);
    if(pNext != NULL)
    {
        m_pLastPoppedEvent = pNext;
    }

    return pNext;
}

#ifdef _DEBUG
bool EventPipeBuffer::EnsureConsistency()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Check to see if the buffer is empty.
    if(GetNextAlignedAddress(m_pBuffer) == m_pCurrent)
    {
        // Make sure that the buffer size is greater than zero.
        _ASSERTE(m_pBuffer != m_pLimit);
    }

    // Validate the contents of the filled portion of the buffer.
    BYTE *ptr = GetNextAlignedAddress(m_pBuffer);
    while(ptr < m_pCurrent)
    {
        // Validate the event.
        EventPipeEventInstance *pInstance = (EventPipeEventInstance*)ptr;
        _ASSERTE(pInstance->EnsureConsistency());

        // Validate that payload and length match.
        _ASSERTE((pInstance->GetData() != NULL && pInstance->GetDataLength() > 0) || (pInstance->GetData() == NULL && pInstance->GetDataLength() == 0));

        // Skip the event.
        ptr = GetNextAlignedAddress(ptr + sizeof(*pInstance) + pInstance->GetDataLength());
    }

    // When we're done walking the filled portion of the buffer,
    // ptr should be the same as m_pCurrent.
    _ASSERTE(ptr == m_pCurrent);

    // Walk the rest of the buffer, making sure it is properly zeroed.
    while(ptr < m_pLimit)
    {
        _ASSERTE(*ptr++ == 0);
    }

    return true;
}
#endif // _DEBUG

#endif // FEATURE_PERFTRACING
<commit_msg>Fix issue 23040<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"
#include "eventpipe.h"
#include "eventpipeeventinstance.h"
#include "eventpipebuffer.h"

#ifdef FEATURE_PERFTRACING

EventPipeBuffer::EventPipeBuffer(unsigned int bufferSize)
{
    CONTRACTL
    {
        THROWS;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    m_pBuffer = new BYTE[bufferSize];
    memset(m_pBuffer, 0, bufferSize);
    m_pLimit = m_pBuffer + bufferSize;
    m_pCurrent = GetNextAlignedAddress(m_pBuffer);

    m_mostRecentTimeStamp.QuadPart = 0;
    m_pLastPoppedEvent = NULL;
    m_pPrevBuffer = NULL;
    m_pNextBuffer = NULL;
}

EventPipeBuffer::~EventPipeBuffer()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    if(m_pBuffer != NULL)
    {
        delete[] m_pBuffer;
    }
}

bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeSession &session, EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
        PRECONDITION(((size_t)m_pCurrent % AlignmentSize) == 0);
    }
    CONTRACTL_END;

    // Calculate the size of the event.
    unsigned int eventSize = sizeof(EventPipeEventInstance) + payload.GetSize();

    // Make sure we have enough space to write the event.
    if(m_pCurrent + eventSize >= m_pLimit)
    {
        return false;
    }

    bool success = true;
    EX_TRY
    {
        // Calculate the location of the data payload.
        BYTE *pDataDest = payload.GetSize() == 0 ? NULL : m_pCurrent + sizeof(EventPipeEventInstance);

        // Placement-new the EventPipeEventInstance.
        // if pthread is NULL, it's likely we are running in something like a GC thread which is not a Thread object, so it can't have an activity ID set anyway
        EventPipeEventInstance *pInstance = new (m_pCurrent) EventPipeEventInstance(
            session,
            event,
            (pThread == NULL) ? ::GetCurrentThreadId() : pThread->GetOSThreadId(),
            pDataDest,
            payload.GetSize(),
            (pThread == NULL) ? NULL : pActivityId,
            pRelatedActivityId);

        // Copy the stack if a separate stack trace was provided.
        if(pStack != NULL)
        {
            StackContents *pInstanceStack = pInstance->GetStack();
            pStack->CopyTo(pInstanceStack);
        }

        // Write the event payload data to the buffer.
        if(payload.GetSize() > 0)
        {
            payload.CopyData(pDataDest);
        }

        // Save the most recent event timestamp.
        m_mostRecentTimeStamp = *pInstance->GetTimeStamp();

    }
    EX_CATCH
    {
        // If a failure occurs, bail out and don't advance the pointer.
        success = false;
    }
    EX_END_CATCH(SwallowAllExceptions);

    if(success)
    {
        // Advance the current pointer past the event.
        m_pCurrent = GetNextAlignedAddress(m_pCurrent + eventSize);
    }

    return success;
}

LARGE_INTEGER EventPipeBuffer::GetMostRecentTimeStamp() const
{
    LIMITED_METHOD_CONTRACT;

    return m_mostRecentTimeStamp;
}

void EventPipeBuffer::Clear()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

    memset(m_pBuffer, 0, (size_t)(m_pLimit - m_pBuffer));
    m_pCurrent = GetNextAlignedAddress(m_pBuffer);
    m_mostRecentTimeStamp.QuadPart = 0;
    m_pLastPoppedEvent = NULL;
}

EventPipeEventInstance* EventPipeBuffer::GetNext(EventPipeEventInstance *pEvent, LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    EventPipeEventInstance *pNextInstance = NULL;
    // If input is NULL, return the first event if there is one.
    if(pEvent == NULL)
    {
        // If this buffer contains an event, select it.
        BYTE *pFirstAlignedInstance = GetNextAlignedAddress(m_pBuffer);
        if(m_pCurrent > pFirstAlignedInstance)
        {
            pNextInstance = (EventPipeEventInstance*)pFirstAlignedInstance;
        }
        else
        {
            return NULL;
        }
    }
    else
    {
        // Confirm that pEvent is within the used range of the buffer.
        if(((BYTE*)pEvent < m_pBuffer) || ((BYTE*)pEvent >= m_pCurrent))
        {
            _ASSERT(!"Input pointer is out of range.");
            return NULL;
        }

        if (pEvent->GetData())
        {
            // We have a pointer within the bounds of the buffer.
            // Find the next event by skipping the current event with it's data payload immediately after the instance.
            pNextInstance = (EventPipeEventInstance *)GetNextAlignedAddress(const_cast<BYTE *>(pEvent->GetData() + pEvent->GetDataLength()));
        }
        else
        {
            // In case we do not have a payload, the next instance is right after the current instance
            pNextInstance = (EventPipeEventInstance*)GetNextAlignedAddress((BYTE*)(pEvent + 1));
        }

        // Check to see if we've reached the end of the written portion of the buffer.
        if((BYTE*)pNextInstance >= m_pCurrent)
        {
            return NULL;
        }
    }

    // Ensure that the timestamp is valid.  The buffer is zero'd before use, so a zero timestamp is invalid.
    LARGE_INTEGER nextTimeStamp = *pNextInstance->GetTimeStamp();
    if(nextTimeStamp.QuadPart == 0)
    {
        return NULL;
    }

    // Ensure that the timestamp is earlier than the beforeTimeStamp.
    if(nextTimeStamp.QuadPart >= beforeTimeStamp.QuadPart)
    {
        return NULL;
    }

    return pNextInstance;
}

EventPipeEventInstance* EventPipeBuffer::PeekNext(LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Get the next event using the last popped event as a marker.
    return GetNext(m_pLastPoppedEvent, beforeTimeStamp);
}

EventPipeEventInstance* EventPipeBuffer::PopNext(LARGE_INTEGER beforeTimeStamp)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Get the next event using the last popped event as a marker.
    EventPipeEventInstance *pNext = PeekNext(beforeTimeStamp);
    if(pNext != NULL)
    {
        m_pLastPoppedEvent = pNext;
    }

    return pNext;
}

#ifdef _DEBUG
bool EventPipeBuffer::EnsureConsistency()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Check to see if the buffer is empty.
    if(GetNextAlignedAddress(m_pBuffer) == m_pCurrent)
    {
        // Make sure that the buffer size is greater than zero.
        _ASSERTE(m_pBuffer != m_pLimit);
    }

    // Validate the contents of the filled portion of the buffer.
    BYTE *ptr = GetNextAlignedAddress(m_pBuffer);
    while(ptr < m_pCurrent)
    {
        // Validate the event.
        EventPipeEventInstance *pInstance = (EventPipeEventInstance*)ptr;
        _ASSERTE(pInstance->EnsureConsistency());

        // Validate that payload and length match.
        _ASSERTE((pInstance->GetData() != NULL && pInstance->GetDataLength() > 0) || (pInstance->GetData() == NULL && pInstance->GetDataLength() == 0));

        // Skip the event.
        ptr = GetNextAlignedAddress(ptr + sizeof(*pInstance) + pInstance->GetDataLength());
    }

    // When we're done walking the filled portion of the buffer,
    // ptr should be the same as m_pCurrent.
    _ASSERTE(ptr == m_pCurrent);

    // Walk the rest of the buffer, making sure it is properly zeroed.
    while(ptr < m_pLimit)
    {
        _ASSERTE(*ptr++ == 0);
    }

    return true;
}
#endif // _DEBUG

#endif // FEATURE_PERFTRACING
<|endoftext|>


<commit_before>
#include <Windows.h>

#if defined( DEBUG ) || defined( _DEBUG )
#define _CRTDBG_AMP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif

#include "CameraController.h"
#include "CubeFactory.h"
#include "DebugGUI.h"
#include "HeightMap.h"
#include "InputHelper.h"
#include "ManagementDebug.h"
#include "ObjFileReader.h"
#include "XInputFetcher.h"
#include "camera.h"
#include "inputDesc.h"
#include "keyCodes.h"
#include "managementMenu.h"
#include "managementSprite.h"
#include "managementWrite.h"
#include "mathHelper.h"
#include "renderer.h"
#include "utility.h"
#include "window.h"
#include "EntityBufferInfo.h"
#include "PivotPoint.h"

//Loading
#include <LoaderMAC.h>

HRESULT initialize(HINSTANCE hInstance, int cmdShow);
void initDebugGui( float* p_dt, float* p_fps );
void handleInput(XInputFetcher* xinput, float dt);
void clean();

Window* g_window;
Renderer* g_renderer;
Camera* g_camera;
ManagementMenu* g_managementMenu;
//CameraController* g_cameraControl;
bool g_menuIsActive;

//Temp: Using whilst testing XML-Loader unt Writer-.
//#include <LoaderXML.h>
//#include <WriterXML.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int cmdShow)
{
#if defined( DEBUG ) || defined( _DEBUG )
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	_CrtSetReportMode ( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
#endif

	AllocConsole();
	HRESULT hr = S_OK;
	hr = initialize(hInstance, cmdShow);
	DebugGUI::getInstance()->init( g_renderer->getD3DManagement(),
		g_window->getWindowHandle() );

	float dt = 0.0f;
	float fps = 0.0f;
	initDebugGui( &dt, &fps );
	XInputFetcher* xinput = new XInputFetcher();
	xinput->calibrate(0.4);

	//Detta r kanske typ nstan helt och hllet lite smtt temporrt.
	Mac mac;
	LoaderMAC* loaderMAC = new LoaderMAC();
	bool sucessfulLoad = loaderMAC->init( mac );
	delete loaderMAC;

	HeightMap* heightMap = new HeightMap(
		g_renderer->getD3DManagement(),
		mac.heightmap,
		(float)std::atof(			mac.macDesc.heightmap.cellSize.c_str()	),	//Jag ska fixa detta. Lovar.
		(unsigned int)std::atoi(	mac.macDesc.heightmap.cntCol.c_str()	),	//Jag ska fixa detta. Lovar.
		(unsigned int)std::atoi(	mac.macDesc.heightmap.cntRow.c_str()	));	//Jag ska fixa detta. Lovar.
	EntityBufferInfo* heightMapBuffers = heightMap->getEntityBufferInfo();
	g_renderer->addEntity( heightMapBuffers );

	ObjFileReader reader;
	EntityBufferInfo* blueberry = reader.readFile( "../../resources/",
		"sphere.obj", false, g_renderer->getD3DManagement() );
	blueberry->m_blendState = ManagementBS::BSTypes_ADDITIVE;
	g_renderer->addEntity( blueberry );

	PivotPoint* pivot = new PivotPoint( xinput, heightMap, blueberry );

	CameraController* cameraControl = new CameraController( g_camera, xinput );

	g_managementMenu = new ManagementMenu(xinput);
		hr = g_managementMenu->init(g_renderer->getD3DManagement()->getDevice(),
			g_renderer->getD3DManagement()->getDeviceContext());

	if(SUCCEEDED(hr))
	{
		LARGE_INTEGER freq, old, current;
		QueryPerformanceFrequency (&freq);
		QueryPerformanceCounter (&old);

		while(g_window->isActive())
		{
			QueryPerformanceCounter(&current);
			dt = float (current.QuadPart - old.QuadPart) / float(freq.QuadPart);
			fps = 1/dt;

			g_window->checkMessages();

			xinput->update();
			handleInput(xinput, dt);

			heightMap->update( g_renderer->getD3DManagement(), pivot, dt );
			pivot->update( dt, cameraControl->getForward(), cameraControl->getRight() );
			if( !g_menuIsActive) {
				cameraControl->update( dt, pivot->getPosition() );
			}

			DirectX::XMFLOAT4X4 finalMatrix = MathHelper::multiplyMatrix(
				g_camera->getViewMatrix(), g_camera->getProjectionMatrix() );

			g_renderer->update( finalMatrix, cameraControl->getPosition() );
			g_renderer->beginRender();
			g_renderer->renderEntities();
			g_renderer->renderSprites(g_managementMenu->getManagementSprite());
			g_renderer->renderText(g_managementMenu->getTextStrings());
			g_renderer->endRender();

			g_managementMenu->clearTextStrings();

			old.QuadPart = current.QuadPart;

			//Sleep(8);
		}
	}

	delete cameraControl;
	delete heightMap;
	delete xinput;
	delete pivot;

	DebugGUI::getInstance()->terminate();

//#define DEBUG_D3D
#ifdef DEBUG_D3D
	ManagementDebug md;
	md.init(g_renderer->getD3DManagement()->getDevice());
#endif // DEBUG_D3D

	clean();

#ifdef DEBUG_D3D
	md.reportLiveObjects();
#endif // !DEBUG_D3D

	return 0;
}

HRESULT initialize(HINSTANCE hInstance, int cmdShow)
{
	HRESULT hr = S_OK;

	g_window = new Window(hInstance, cmdShow);
	hr = g_window->initialize();
	if(SUCCEEDED(hr))
	{
		g_renderer = new Renderer();
		hr = g_renderer->init(g_window->getWindowHandle());
	}
	if(SUCCEEDED(hr))
	{
		g_camera = new Camera();
		g_camera->setLens(DirectX::XM_PIDIV4, static_cast<float>(SCREEN_WIDTH)/static_cast<float>(SCREEN_HEIGHT), 1.0f, 1000.0f);
	}

	return hr;
}

void initDebugGui( float* p_dt, float* p_fps )
{
	int answerToLifeTheUniverseAndEverything = 42;
	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_INT,
		DebugGUI::Permissions_READ_ONLY,
		"Answer to life, the universe and everything",
		&answerToLifeTheUniverseAndEverything, "");

	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_FLOAT,
		DebugGUI::Permissions_READ_ONLY, "dt", p_dt, "");

	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_FLOAT,
		DebugGUI::Permissions_READ_ONLY, "fps", p_fps, "");
}

void handleInput(XInputFetcher* xinput, float dt)
{
	g_menuIsActive = false;

	static bool s_textInput		 = false;
	static bool s_alreadyPressed = false;
	static float s_timer		 = 0.0f;

	float leftAnalogSens  = 64.0f;
	float rightAnalogSens = 2.0f;

	double walkDistance		= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_LY_NEGATIVE);
	double strafeDistance	= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_LX_NEGATIVE);
	double yawAngle			= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_RX_NEGATIVE);
	double pitchAngle		= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_RY_NEGATIVE);

	if(xinput->getBtnState(InputHelper::Xbox360Digitals_BTN_BACK) == InputHelper::KeyStates_KEY_PRESSED)
	{
		if(!s_textInput)
			s_textInput = true;
		else
			s_textInput = false;
	}

	if(!s_textInput)
	{
		if(xinput->getBtnState(InputHelper::Xbox360Digitals_SHOULDER_PRESS_L) == InputHelper::KeyStates_KEY_DOWN)
		{
			g_menuIsActive = true;
			g_managementMenu->useToolsMenu();
		}
		else if(xinput->getBtnState(InputHelper::Xbox360Digitals_SHOULDER_PRESS_R) == InputHelper::KeyStates_KEY_DOWN)
		{
			g_menuIsActive = true;
			g_managementMenu->useToolPropertiesMenu();
		}
		else
			g_managementMenu->useNoMenu();

		if(!g_menuIsActive)
		{
			g_managementMenu->setSelectedTool();
		}
	}
	else
		g_managementMenu->useTextMenu();
}

void clean()
{
	SAFE_DELETE(g_window);
	SAFE_DELETE(g_renderer);
	SAFE_DELETE(g_camera);
	SAFE_DELETE(g_managementMenu);
}
<commit_msg>Restricted movement when menu is active.<commit_after>
#include <Windows.h>

#if defined( DEBUG ) || defined( _DEBUG )
#define _CRTDBG_AMP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif

#include "CameraController.h"
#include "CubeFactory.h"
#include "DebugGUI.h"
#include "HeightMap.h"
#include "InputHelper.h"
#include "ManagementDebug.h"
#include "ObjFileReader.h"
#include "XInputFetcher.h"
#include "camera.h"
#include "inputDesc.h"
#include "keyCodes.h"
#include "managementMenu.h"
#include "managementSprite.h"
#include "managementWrite.h"
#include "mathHelper.h"
#include "renderer.h"
#include "utility.h"
#include "window.h"
#include "EntityBufferInfo.h"
#include "PivotPoint.h"

//Loading
#include <LoaderMAC.h>

HRESULT initialize(HINSTANCE hInstance, int cmdShow);
void initDebugGui( float* p_dt, float* p_fps );
void handleInput(XInputFetcher* xinput, float dt);
void clean();

Window* g_window;
Renderer* g_renderer;
Camera* g_camera;
ManagementMenu* g_managementMenu;
//CameraController* g_cameraControl;
bool g_menuIsActive;

//Temp: Using whilst testing XML-Loader unt Writer-.
//#include <LoaderXML.h>
//#include <WriterXML.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int cmdShow)
{
#if defined( DEBUG ) || defined( _DEBUG )
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	_CrtSetReportMode ( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
#endif

	AllocConsole();
	HRESULT hr = S_OK;
	hr = initialize(hInstance, cmdShow);
	DebugGUI::getInstance()->init( g_renderer->getD3DManagement(),
		g_window->getWindowHandle() );

	float dt = 0.0f;
	float fps = 0.0f;
	initDebugGui( &dt, &fps );
	XInputFetcher* xinput = new XInputFetcher();
	xinput->calibrate(0.4);

	//Detta r kanske typ nstan helt och hllet lite smtt temporrt.
	Mac mac;
	LoaderMAC* loaderMAC = new LoaderMAC();
	bool sucessfulLoad = loaderMAC->init( mac );
	delete loaderMAC;

	HeightMap* heightMap = new HeightMap(
		g_renderer->getD3DManagement(),
		mac.heightmap,
		(float)std::atof(			mac.macDesc.heightmap.cellSize.c_str()	),	//Jag ska fixa detta. Lovar.
		(unsigned int)std::atoi(	mac.macDesc.heightmap.cntCol.c_str()	),	//Jag ska fixa detta. Lovar.
		(unsigned int)std::atoi(	mac.macDesc.heightmap.cntRow.c_str()	));	//Jag ska fixa detta. Lovar.
	EntityBufferInfo* heightMapBuffers = heightMap->getEntityBufferInfo();
	g_renderer->addEntity( heightMapBuffers );

	ObjFileReader reader;
	EntityBufferInfo* blueberry = reader.readFile( "../../resources/",
		"sphere.obj", false, g_renderer->getD3DManagement() );
	blueberry->m_blendState = ManagementBS::BSTypes_ADDITIVE;
	g_renderer->addEntity( blueberry );

	PivotPoint* pivot = new PivotPoint( xinput, heightMap, blueberry );

	CameraController* cameraControl = new CameraController( g_camera, xinput );

	g_managementMenu = new ManagementMenu(xinput);
		hr = g_managementMenu->init(g_renderer->getD3DManagement()->getDevice(),
			g_renderer->getD3DManagement()->getDeviceContext());

	if(SUCCEEDED(hr))
	{
		LARGE_INTEGER freq, old, current;
		QueryPerformanceFrequency (&freq);
		QueryPerformanceCounter (&old);

		while(g_window->isActive())
		{
			QueryPerformanceCounter(&current);
			dt = float (current.QuadPart - old.QuadPart) / float(freq.QuadPart);
			fps = 1/dt;

			g_window->checkMessages();

			xinput->update();
			handleInput(xinput, dt);

			if( !g_menuIsActive)
			{
				heightMap->update( g_renderer->getD3DManagement(), pivot, dt );
				pivot->update( dt, cameraControl->getForward(), cameraControl->getRight() );
				cameraControl->update( dt, pivot->getPosition() );
			}

			DirectX::XMFLOAT4X4 finalMatrix = MathHelper::multiplyMatrix(
				g_camera->getViewMatrix(), g_camera->getProjectionMatrix() );

			g_renderer->update( finalMatrix, cameraControl->getPosition() );
			g_renderer->beginRender();
			g_renderer->renderEntities();
			g_renderer->renderSprites(g_managementMenu->getManagementSprite());
			g_renderer->renderText(g_managementMenu->getTextStrings());
			g_renderer->endRender();

			g_managementMenu->clearTextStrings();

			old.QuadPart = current.QuadPart;

			//Sleep(8);
		}
	}

	delete cameraControl;
	delete heightMap;
	delete xinput;
	delete pivot;

	DebugGUI::getInstance()->terminate();

//#define DEBUG_D3D
#ifdef DEBUG_D3D
	ManagementDebug md;
	md.init(g_renderer->getD3DManagement()->getDevice());
#endif // DEBUG_D3D

	clean();

#ifdef DEBUG_D3D
	md.reportLiveObjects();
#endif // !DEBUG_D3D

	return 0;
}

HRESULT initialize(HINSTANCE hInstance, int cmdShow)
{
	HRESULT hr = S_OK;

	g_window = new Window(hInstance, cmdShow);
	hr = g_window->initialize();
	if(SUCCEEDED(hr))
	{
		g_renderer = new Renderer();
		hr = g_renderer->init(g_window->getWindowHandle());
	}
	if(SUCCEEDED(hr))
	{
		g_camera = new Camera();
		g_camera->setLens(DirectX::XM_PIDIV4, static_cast<float>(SCREEN_WIDTH)/static_cast<float>(SCREEN_HEIGHT), 1.0f, 1000.0f);
	}

	return hr;
}

void initDebugGui( float* p_dt, float* p_fps )
{
	int answerToLifeTheUniverseAndEverything = 42;
	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_INT,
		DebugGUI::Permissions_READ_ONLY,
		"Answer to life, the universe and everything",
		&answerToLifeTheUniverseAndEverything, "");

	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_FLOAT,
		DebugGUI::Permissions_READ_ONLY, "dt", p_dt, "");

	DebugGUI::getInstance()->addVar( "Main", DebugGUI::Types_FLOAT,
		DebugGUI::Permissions_READ_ONLY, "fps", p_fps, "");
}

void handleInput(XInputFetcher* xinput, float dt)
{
//	g_menuIsActive = false;

	static bool s_textInput		 = false;
	static bool s_alreadyPressed = false;
	static float s_timer		 = 0.0f;

	float leftAnalogSens  = 64.0f;
	float rightAnalogSens = 2.0f;

	double walkDistance		= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_LY_NEGATIVE);
	double strafeDistance	= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_LX_NEGATIVE);
	double yawAngle			= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_RX_NEGATIVE);
	double pitchAngle		= xinput->getCalibratedAnalog(InputHelper::Xbox360Analogs_THUMB_RY_NEGATIVE);

	if(xinput->getBtnState(InputHelper::Xbox360Digitals_BTN_BACK) == InputHelper::KeyStates_KEY_PRESSED)
	{
		if(!s_textInput)
			s_textInput = true;
		else
			s_textInput = false;
	}

	if(!s_textInput)
	{
		if(xinput->getBtnState(InputHelper::Xbox360Digitals_SHOULDER_PRESS_L) == InputHelper::KeyStates_KEY_DOWN)
		{
			g_menuIsActive = true;
			g_managementMenu->useToolsMenu();
		}
		else if(xinput->getBtnState(InputHelper::Xbox360Digitals_SHOULDER_PRESS_R) == InputHelper::KeyStates_KEY_DOWN)
		{
			g_menuIsActive = true;
			g_managementMenu->useToolPropertiesMenu();
		}
		else
		{
			g_managementMenu->useNoMenu();
			g_menuIsActive = false;
		}

		if(!g_menuIsActive)
		{
			g_managementMenu->setSelectedTool();
		}
	}
	else
	{
		g_menuIsActive = true;
		g_managementMenu->useTextMenu();
	}
}

void clean()
{
	SAFE_DELETE(g_window);
	SAFE_DELETE(g_renderer);
	SAFE_DELETE(g_camera);
	SAFE_DELETE(g_managementMenu);
}
<|endoftext|>


<commit_before>#include "Cam.h"

Cam::Cam() :
	zoom_(1)
{
	screen_size_[0] = screen_size_[1] = 0;
}

void Cam::SetupProjection() {
	glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glViewport(0, 0, Width(), Height());
		gluPerspective(40, Width()/(float)Height(), 0.1, 100);
		//glFrustum(-1*HalfWidth()/100.0,
			     //HalfWidth()/100.0,
			  //-1*HalfHeight()/100.0,
			     //HalfHeight()/100.0,
			  //10/zoom_, 100);
	glMatrixMode(GL_MODELVIEW);
}

void Cam::SetupView() {
	glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt(pos_.i, pos_.j, -5,
		          pos_.i, pos_.j,  0,
			  0,      1,       0);
}

Cam& Cam::I() {
	static Cam instance;
	return instance;
}

void GLFWCALL Cam::ResizeCallback(int width, int height) {
	I().screen_size_[0] = width;
	I().screen_size_[1] = height;

	I().SetupProjection();
	I().SetupView();
}

int Cam::Width() {
	return screen_size_[0];
}

int Cam::Height() {
	return screen_size_[1];
}

int Cam::HalfWidth() {
	return screen_size_[0] / 2;
}

int Cam::HalfHeight() {
	return screen_size_[1] / 2;
}

void Cam::SetZoom(float zoom) {
	zoom_ = zoom;

	SetupProjection();
}

void Cam::SetPos(Vector pos) {
	pos_ = pos;

	SetupView();
}

float Cam::GetZoom() {
	return zoom_;
}

Vector Cam::GetPos() {
	return pos_;
}
<commit_msg>Use glFrustum for more consistent coordinates<commit_after>#include "Cam.h"

Cam::Cam() :
	zoom_(1)
{
	screen_size_[0] = screen_size_[1] = 0;
}

void Cam::SetupProjection() {
	glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glViewport(0, 0, Width(), Height());

		float frac = Width() / (float) Height();
		glFrustum(-.5*frac,
			   .5*frac,
			  -.5,
			   .5,
			  1, 100);
	glMatrixMode(GL_MODELVIEW);
}

void Cam::SetupView() {
	glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt(pos_.i, pos_.j, -5,
		          pos_.i, pos_.j,  0,
			  0,      1,       0);
}

Cam& Cam::I() {
	static Cam instance;
	return instance;
}

void GLFWCALL Cam::ResizeCallback(int width, int height) {
	I().screen_size_[0] = width;
	I().screen_size_[1] = height;

	I().SetupProjection();
	I().SetupView();
}

int Cam::Width() {
	return screen_size_[0];
}

int Cam::Height() {
	return screen_size_[1];
}

int Cam::HalfWidth() {
	return screen_size_[0] / 2;
}

int Cam::HalfHeight() {
	return screen_size_[1] / 2;
}

void Cam::SetZoom(float zoom) {
	zoom_ = zoom;

	SetupProjection();
}

void Cam::SetPos(Vector pos) {
	pos_ = pos;

	SetupView();
}

float Cam::GetZoom() {
	return zoom_;
}

Vector Cam::GetPos() {
	return pos_;
}
<|endoftext|>


<commit_before>#ifndef TOKENS_H_
#define TOKENS_H_

#include <string>
#include <vector>

#include "global.hpp"
#include "operators.hpp"
#include "builtins.hpp"

enum TokenType: int {
  INTEGER, FLOAT, STRING, ARRAY, // Literals
  OPERATOR, KEYWORD, CONSTRUCT, // Language parts
  TYPE, VARIABLE, FUNCTION, // Defined structures
  UNPROCESSED
};

class Token {
public:
  std::string data = "";
  TokenType type = UNPROCESSED;
  /*
   * Depending on the TokenType, the pointer has the following possible types:
   * For OPERATOR: ops::Operator*
   * For INTEGER: builtins::Integer*
   * For FLOAT: builtins::Float*
   */
  void* typeData = nullptr;
  // Location of Token in code
  int line = -1;

  Token();
  Token(std::string data, TokenType type, int line);
  Token(ops::Operator* opContent, TokenType type, int line);
  Token(builtins::Object* obj, TokenType type, int line);
};

inline std::ostream& operator<<(std::ostream& os, Token& tok) {
  return os << "Token " << tok.data << ", TokenType " << tok.type << ", at line " << tok.line;
}

#endif /* TOKENS_H_ */
<commit_msg>Added documentation for Token.line<commit_after>#ifndef TOKENS_H_
#define TOKENS_H_

#include <string>
#include <vector>

#include "global.hpp"
#include "operators.hpp"
#include "builtins.hpp"

enum TokenType: int {
  INTEGER, FLOAT, STRING, ARRAY, // Literals
  OPERATOR, KEYWORD, CONSTRUCT, // Language parts
  TYPE, VARIABLE, FUNCTION, // Defined structures
  UNPROCESSED
};

class Token {
public:
  std::string data = "";
  TokenType type = UNPROCESSED;
  /*
   * Depending on the TokenType, the pointer has the following possible types:
   * For OPERATOR: ops::Operator*
   * For INTEGER: builtins::Integer*
   * For FLOAT: builtins::Float*
   */
  void* typeData = nullptr;
  /*
   * Location of Token in code.
   * -1 by default. -2 when Token was created by interpreter.
   */
  int line = -1;

  Token();
  Token(std::string data, TokenType type, int line);
  Token(ops::Operator* opContent, TokenType type, int line);
  Token(builtins::Object* obj, TokenType type, int line);
};

inline std::ostream& operator<<(std::ostream& os, Token& tok) {
  return os << "Token " << tok.data << ", TokenType " << tok.type << ", at line " << tok.line;
}

#endif /* TOKENS_H_ */
<|endoftext|>


<commit_before>//===------------------------- string.cpp ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "string"
#include "cstdlib"
#include "cwchar"
#include "cerrno"
#include "limits"
#include "stdexcept"
#ifdef _LIBCPP_MSVCRT
#include "support/win32/support.h"
#endif // _LIBCPP_MSVCRT
#include <stdio.h>

_LIBCPP_BEGIN_NAMESPACE_STD

template class __basic_string_common<true>;

template class basic_string<char>;
template class basic_string<wchar_t>;

template
    string
    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);

namespace
{

template<typename T>
inline
void throw_helper( const string& msg )
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    throw T( msg );
#else
    printf("%s\n", msg.c_str());
    abort();
#endif
}

inline
void throw_from_string_out_of_range( const string& func )
{
    throw_helper<out_of_range>(func + ": out of range");
}

inline
void throw_from_string_invalid_arg( const string& func )
{
    throw_helper<invalid_argument>(func + ": no conversion");
}

// as_integer

template<typename V, typename S, typename F>
inline
V
as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
{
    typename S::value_type* ptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr, base);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V
as_integer(const string& func, const S& s, size_t* idx, int base);

// string
template<>
inline
int
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    // Use long as no Standard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, strtol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, strtol );
}

template<>
inline
unsigned long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
}

template<>
inline
long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, strtoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
}

// wstring
template<>
inline
int
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    // Use long as no Stantard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, wcstol );
}

template<>
inline
unsigned long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
}

template<>
inline
long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
}

// as_float

template<typename V, typename S, typename F>
inline
V
as_float_helper(const string& func, const S& str, size_t* idx, F f )
{
    typename S::value_type* ptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V as_float( const string& func, const S& s, size_t* idx = nullptr );

template<>
inline
float
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, strtof );
}

template<>
inline
double
as_float(const string& func, const string& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, strtod );
}

template<>
inline
long double
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, strtold );
}

template<>
inline
float
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, wcstof );
}

template<>
inline
double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, wcstod );
}

template<>
inline
long double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, wcstold );
}

}  // unnamed namespace

int
stoi(const string& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

int
stoi(const wstring& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

long
stol(const string& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

long
stol(const wstring& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

unsigned long
stoul(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

unsigned long
stoul(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

long long
stoll(const string& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

long long
stoll(const wstring& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

unsigned long long
stoull(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

unsigned long long
stoull(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

float
stof(const string& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

float
stof(const wstring& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

double
stod(const string& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

double
stod(const wstring& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

long double
stold(const string& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

long double
stold(const wstring& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

// to_string

namespace
{

// as_string

template<typename S, typename P, typename V >
inline
S
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
{
    typedef typename S::size_type size_type;
    size_type available = s.size();
    while (true)
    {
        int status = sprintf_like(&s[0], available + 1, fmt, a);
        if ( status >= 0 )
        {
            size_type used = static_cast<size_type>(status);
            if ( used <= available )
            {
                s.resize( used );
                break;
            }
            available = used; // Assume this is advice of how much space we need.
        }
        else
            available = available * 2 + 1;
        s.resize(available);
    }
    return s;
}

template <class S, class V, bool = is_floating_point<V>::value>
struct initial_string;

template <class V, bool b>
struct initial_string<string, V, b>
{
    string
    operator()() const
    {
        string s;
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, false>
{
    wstring
    operator()() const
    {
        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
          + 1;
        wstring s(n, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, true>
{
    wstring
    operator()() const
    {
        wstring s(20, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);

inline
wide_printf
get_swprintf()
{
#ifndef _LIBCPP_MSVCRT
    return swprintf;
#else
    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
#endif
}

}  // unnamed namespace

string to_string(int val)
{
    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
}

string to_string(unsigned val)
{
    return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
}

string to_string(long val)
{
    return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
}

string to_string(unsigned long val)
{
    return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
}

string to_string(long long val)
{
    return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
}

string to_string(unsigned long long val)
{
    return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
}

string to_string(float val)
{
    return as_string(snprintf, initial_string<string, float>()(), "%f", val);
}

string to_string(double val)
{
    return as_string(snprintf, initial_string<string, double>()(), "%f", val);
}

string to_string(long double val)
{
    return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
}

wstring to_wstring(int val)
{
    return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
}

wstring to_wstring(unsigned val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
}

wstring to_wstring(long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
}

wstring to_wstring(unsigned long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
}

wstring to_wstring(long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
}

wstring to_wstring(unsigned long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
}

wstring to_wstring(float val)
{
    return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
}

wstring to_wstring(double val)
{
    return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
}

wstring to_wstring(long double val)
{
    return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
}
_LIBCPP_END_NAMESPACE_STD
<commit_msg>Initialize pointer in string conversion helpers to prevent MSAN diagnostic.<commit_after>//===------------------------- string.cpp ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "string"
#include "cstdlib"
#include "cwchar"
#include "cerrno"
#include "limits"
#include "stdexcept"
#ifdef _LIBCPP_MSVCRT
#include "support/win32/support.h"
#endif // _LIBCPP_MSVCRT
#include <stdio.h>

_LIBCPP_BEGIN_NAMESPACE_STD

template class __basic_string_common<true>;

template class basic_string<char>;
template class basic_string<wchar_t>;

template
    string
    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);

namespace
{

template<typename T>
inline
void throw_helper( const string& msg )
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    throw T( msg );
#else
    printf("%s\n", msg.c_str());
    abort();
#endif
}

inline
void throw_from_string_out_of_range( const string& func )
{
    throw_helper<out_of_range>(func + ": out of range");
}

inline
void throw_from_string_invalid_arg( const string& func )
{
    throw_helper<invalid_argument>(func + ": no conversion");
}

// as_integer

template<typename V, typename S, typename F>
inline
V
as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
{
    typename S::value_type* ptr = nullptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr, base);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V
as_integer(const string& func, const S& s, size_t* idx, int base);

// string
template<>
inline
int
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    // Use long as no Standard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, strtol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer(const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, strtol );
}

template<>
inline
unsigned long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
}

template<>
inline
long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, strtoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const string& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
}

// wstring
template<>
inline
int
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    // Use long as no Stantard string to integer exists.
    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
        throw_from_string_out_of_range(func);
    return static_cast<int>(r);
}

template<>
inline
long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long>( func, s, idx, base, wcstol );
}

template<>
inline
unsigned long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
}

template<>
inline
long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
}

template<>
inline
unsigned long long
as_integer( const string& func, const wstring& s, size_t* idx, int base )
{
    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
}

// as_float

template<typename V, typename S, typename F>
inline
V
as_float_helper(const string& func, const S& str, size_t* idx, F f )
{
    typename S::value_type* ptr = nullptr;
    const typename S::value_type* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    V r = f(p, &ptr);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw_from_string_out_of_range(func);
    if (ptr == p)
        throw_from_string_invalid_arg(func);
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

template<typename V, typename S>
inline
V as_float( const string& func, const S& s, size_t* idx = nullptr );

template<>
inline
float
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, strtof );
}

template<>
inline
double
as_float(const string& func, const string& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, strtod );
}

template<>
inline
long double
as_float( const string& func, const string& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, strtold );
}

template<>
inline
float
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<float>( func, s, idx, wcstof );
}

template<>
inline
double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<double>( func, s, idx, wcstod );
}

template<>
inline
long double
as_float( const string& func, const wstring& s, size_t* idx )
{
    return as_float_helper<long double>( func, s, idx, wcstold );
}

}  // unnamed namespace

int
stoi(const string& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

int
stoi(const wstring& str, size_t* idx, int base)
{
    return as_integer<int>( "stoi", str, idx, base );
}

long
stol(const string& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

long
stol(const wstring& str, size_t* idx, int base)
{
    return as_integer<long>( "stol", str, idx, base );
}

unsigned long
stoul(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

unsigned long
stoul(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long>( "stoul", str, idx, base );
}

long long
stoll(const string& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

long long
stoll(const wstring& str, size_t* idx, int base)
{
    return as_integer<long long>( "stoll", str, idx, base );
}

unsigned long long
stoull(const string& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

unsigned long long
stoull(const wstring& str, size_t* idx, int base)
{
    return as_integer<unsigned long long>( "stoull", str, idx, base );
}

float
stof(const string& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

float
stof(const wstring& str, size_t* idx)
{
    return as_float<float>( "stof", str, idx );
}

double
stod(const string& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

double
stod(const wstring& str, size_t* idx)
{
    return as_float<double>( "stod", str, idx );
}

long double
stold(const string& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

long double
stold(const wstring& str, size_t* idx)
{
    return as_float<long double>( "stold", str, idx );
}

// to_string

namespace
{

// as_string

template<typename S, typename P, typename V >
inline
S
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
{
    typedef typename S::size_type size_type;
    size_type available = s.size();
    while (true)
    {
        int status = sprintf_like(&s[0], available + 1, fmt, a);
        if ( status >= 0 )
        {
            size_type used = static_cast<size_type>(status);
            if ( used <= available )
            {
                s.resize( used );
                break;
            }
            available = used; // Assume this is advice of how much space we need.
        }
        else
            available = available * 2 + 1;
        s.resize(available);
    }
    return s;
}

template <class S, class V, bool = is_floating_point<V>::value>
struct initial_string;

template <class V, bool b>
struct initial_string<string, V, b>
{
    string
    operator()() const
    {
        string s;
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, false>
{
    wstring
    operator()() const
    {
        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
          + 1;
        wstring s(n, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, true>
{
    wstring
    operator()() const
    {
        wstring s(20, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);

inline
wide_printf
get_swprintf()
{
#ifndef _LIBCPP_MSVCRT
    return swprintf;
#else
    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
#endif
}

}  // unnamed namespace

string to_string(int val)
{
    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
}

string to_string(unsigned val)
{
    return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
}

string to_string(long val)
{
    return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
}

string to_string(unsigned long val)
{
    return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
}

string to_string(long long val)
{
    return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
}

string to_string(unsigned long long val)
{
    return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
}

string to_string(float val)
{
    return as_string(snprintf, initial_string<string, float>()(), "%f", val);
}

string to_string(double val)
{
    return as_string(snprintf, initial_string<string, double>()(), "%f", val);
}

string to_string(long double val)
{
    return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
}

wstring to_wstring(int val)
{
    return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
}

wstring to_wstring(unsigned val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
}

wstring to_wstring(long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
}

wstring to_wstring(unsigned long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
}

wstring to_wstring(long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
}

wstring to_wstring(unsigned long long val)
{
    return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
}

wstring to_wstring(float val)
{
    return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
}

wstring to_wstring(double val)
{
    return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
}

wstring to_wstring(long double val)
{
    return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
}
_LIBCPP_END_NAMESPACE_STD
<|endoftext|>