<commit_before>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "args.h"
#include "utils.h"
#include "coreclr.h"

arguments_t::arguments_t() :
    managed_application(_X("")),
    own_path(_X("")),
    app_dir(_X("")),
    app_argc(0),
    app_argv(nullptr),
    nuget_packages(_X("")),
    dotnet_packages_cache(_X("")),
    dotnet_servicing(_X("")),
    dotnet_runtime_servicing(_X("")),
    dotnet_home(_X("")),
    deps_path(_X(""))
{
}

void display_help()
{
    xerr <<
        _X("Usage: " HOST_EXE_NAME " [ASSEMBLY] [ARGUMENTS]\n")
        _X("Execute the specified managed assembly with the passed in arguments\n\n")
        _X("The Host's behavior can be altered using the following environment variables:\n")
        _X(" DOTNET_HOME            Set the dotnet home directory. The CLR is expected to be in the runtime subdirectory of this directory. Overrides all other values for CLR search paths\n")
        _X(" COREHOST_TRACE          Set to affect trace levels (0 = Errors only (default), 1 = Warnings, 2 = Info, 3 = Verbose)\n");
}

bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args)
{
    // Get the full name of the application
    if (!pal::get_own_executable_path(&args.own_path) || !pal::realpath(&args.own_path))
    {
        trace::error(_X("Failed to locate current executable"));
        return false;
    }

    auto own_name = get_filename(args.own_path);
    auto own_dir = get_directory(args.own_path);

    if (own_name.compare(HOST_EXE_NAME) == 0)
    {
        // corerun mode. First argument is managed app
        if (argc < 2)
        {
            display_help();
            return false;
        }
        args.managed_application = pal::string_t(argv[1]);
        if (!pal::realpath(&args.managed_application))
        {
            trace::error(_X("Failed to locate managed application: %s"), args.managed_application.c_str());
            return false;
        }
        args.app_dir = get_directory(args.managed_application);
        args.app_argc = argc - 2;
        args.app_argv = &argv[2];
    }
    else
    {
        // coreconsole mode. Find the managed app in the same directory
        pal::string_t managed_app(own_dir);
        managed_app.push_back(DIR_SEPARATOR);
        managed_app.append(get_executable(own_name));
        managed_app.append(_X(".dll"));
        args.managed_application = managed_app;
        if (!pal::realpath(&args.managed_application))
        {
            trace::error(_X("Failed to locate managed application: %s"), args.managed_application.c_str());
            return false;
        }
        args.app_dir = own_dir;
        args.app_argv = &argv[1];
        args.app_argc = argc - 1;
    }

    if(args.app_argc > 0)
    {
        auto depsfile_candidate = pal::string_t(args.app_argv[0]);

        if (starts_with(depsfile_candidate, s_depsArgPrefix))
        {
            args.deps_path = depsfile_candidate.substr(s_depsArgPrefix.length());
            if (!pal::realpath(&args.deps_path))
            {
                trace::error(_X("Failed to locate deps file: %s"), args.deps_path.c_str());
                return false;
            }
            args.app_argc = args.app_argc - 1;
            args.app_argv = &args.app_argv[1];
        }
    }

    if (args.deps_path.empty())
    {
        const auto& app_base = args.app_dir;
        auto app_name = get_filename(args.managed_application);

        args.deps_path.reserve(app_base.length() + 1 + app_name.length() + 5);
        args.deps_path.append(app_base);
        args.deps_path.push_back(DIR_SEPARATOR);
        args.deps_path.append(app_name, 0, app_name.find_last_of(_X(".")));
        args.deps_path.append(_X(".deps"));
    }

    pal::getenv(_X("NUGET_PACKAGES"), &args.nuget_packages);
    pal::getenv(_X("DOTNET_PACKAGES_CACHE"), &args.dotnet_packages_cache);
    pal::getenv(_X("DOTNET_SERVICING"), &args.dotnet_servicing);
    pal::getenv(_X("DOTNET_RUNTIME_SERVICING"), &args.dotnet_runtime_servicing);
    pal::getenv(_X("DOTNET_HOME"), &args.dotnet_home);
    return true;
}
<commit_msg>When deps file path is provided, use it to resolve the app_dir.<commit_after>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "args.h"
#include "utils.h"
#include "coreclr.h"

arguments_t::arguments_t() :
    managed_application(_X("")),
    own_path(_X("")),
    app_dir(_X("")),
    app_argc(0),
    app_argv(nullptr),
    nuget_packages(_X("")),
    dotnet_packages_cache(_X("")),
    dotnet_servicing(_X("")),
    dotnet_runtime_servicing(_X("")),
    dotnet_home(_X("")),
    deps_path(_X(""))
{
}

void display_help()
{
    xerr <<
        _X("Usage: " HOST_EXE_NAME " [ASSEMBLY] [ARGUMENTS]\n")
        _X("Execute the specified managed assembly with the passed in arguments\n\n")
        _X("The Host's behavior can be altered using the following environment variables:\n")
        _X(" DOTNET_HOME            Set the dotnet home directory. The CLR is expected to be in the runtime subdirectory of this directory. Overrides all other values for CLR search paths\n")
        _X(" COREHOST_TRACE          Set to affect trace levels (0 = Errors only (default), 1 = Warnings, 2 = Info, 3 = Verbose)\n");
}

bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args)
{
    // Get the full name of the application
    if (!pal::get_own_executable_path(&args.own_path) || !pal::realpath(&args.own_path))
    {
        trace::error(_X("Failed to locate current executable"));
        return false;
    }

    auto own_name = get_filename(args.own_path);
    auto own_dir = get_directory(args.own_path);

    if (own_name.compare(HOST_EXE_NAME) == 0)
    {
        // corerun mode. First argument is managed app
        if (argc < 2)
        {
            display_help();
            return false;
        }
        args.managed_application = pal::string_t(argv[1]);
        if (!pal::realpath(&args.managed_application))
        {
            trace::error(_X("Failed to locate managed application: %s"), args.managed_application.c_str());
            return false;
        }
        args.app_dir = get_directory(args.managed_application);
        args.app_argc = argc - 2;
        args.app_argv = &argv[2];
    }
    else
    {
        // coreconsole mode. Find the managed app in the same directory
        pal::string_t managed_app(own_dir);
        managed_app.push_back(DIR_SEPARATOR);
        managed_app.append(get_executable(own_name));
        managed_app.append(_X(".dll"));
        args.managed_application = managed_app;
        if (!pal::realpath(&args.managed_application))
        {
            trace::error(_X("Failed to locate managed application: %s"), args.managed_application.c_str());
            return false;
        }
        args.app_dir = own_dir;
        args.app_argv = &argv[1];
        args.app_argc = argc - 1;
    }

    if(args.app_argc > 0)
    {
        auto depsfile_candidate = pal::string_t(args.app_argv[0]);

        if (starts_with(depsfile_candidate, s_depsArgPrefix))
        {
            args.deps_path = depsfile_candidate.substr(s_depsArgPrefix.length());
            if (!pal::realpath(&args.deps_path))
            {
                trace::error(_X("Failed to locate deps file: %s"), args.deps_path.c_str());
                return false;
            }
            args.app_dir = get_directory(args.deps_path);
            args.app_argc = args.app_argc - 1;
            args.app_argv = &args.app_argv[1];
        }
    }

    if (args.deps_path.empty())
    {
        const auto& app_base = args.app_dir;
        auto app_name = get_filename(args.managed_application);

        args.deps_path.reserve(app_base.length() + 1 + app_name.length() + 5);
        args.deps_path.append(app_base);
        args.deps_path.push_back(DIR_SEPARATOR);
        args.deps_path.append(app_name, 0, app_name.find_last_of(_X(".")));
        args.deps_path.append(_X(".deps"));
    }

    pal::getenv(_X("NUGET_PACKAGES"), &args.nuget_packages);
    pal::getenv(_X("DOTNET_PACKAGES_CACHE"), &args.dotnet_packages_cache);
    pal::getenv(_X("DOTNET_SERVICING"), &args.dotnet_servicing);
    pal::getenv(_X("DOTNET_RUNTIME_SERVICING"), &args.dotnet_runtime_servicing);
    pal::getenv(_X("DOTNET_HOME"), &args.dotnet_home);
    return true;
}
<|endoftext|>


<commit_before>#include <silicium/tcp_acceptor.hpp>
#include <silicium/coroutine.hpp>
#include <silicium/total_consumer.hpp>
#include <silicium/flatten.hpp>
#include <silicium/socket_observable.hpp>
#include <silicium/sending_observable.hpp>
#include <silicium/received_from_socket_source.hpp>
#include <silicium/observable_source.hpp>
#include <silicium/optional.hpp>
#include <silicium/http/http.hpp>
#include <boost/interprocess/sync/null_mutex.hpp>
#include <boost/container/vector.hpp>

namespace
{
	using response_part = Si::incoming_bytes;

	boost::iterator_range<char const *> to_range(response_part part)
	{
		return boost::make_iterator_range(part.begin, part.end);
	}

	struct content_request
	{
#ifdef _MSC_VER
		std::vector
#else
		boost::container::vector
#endif
			<unsigned char> digest;
	};

	Si::optional<unsigned char> decode_ascii_hex_digit(char digit)
	{
		switch (digit)
		{
		case '0': return 0;
		case '1': return 1;
		case '2': return 2;
		case '3': return 3;
		case '4': return 4;
		case '5': return 5;
		case '6': return 6;
		case '7': return 7;
		case '8': return 8;
		case '9': return 9;
		case 'a': case 'A': return 10;
		case 'b': case 'B': return 11;
		case 'c': case 'C': return 12;
		case 'd': case 'D': return 13;
		case 'e': case 'E': return 14;
		case 'f': case 'F': return 15;
		default:
			return Si::none;
		}
	}

	template <class InputIterator, class OutputIterator>
	std::pair<InputIterator, OutputIterator> decode_ascii_hex_bytes(InputIterator begin, InputIterator end, OutputIterator bytes)
	{
		for (;;)
		{
			if (begin == end)
			{
				break;
			}
			char const first_char = *begin;
			Si::optional<unsigned char> const first = decode_ascii_hex_digit(first_char);
			if (!first)
			{
				break;
			}
			auto const next = begin + 1;
			if (next == end)
			{
				break;
			}
			char const second_char = *next;
			Si::optional<unsigned char> const second = decode_ascii_hex_digit(second_char);
			if (!second)
			{
				break;
			}
			begin = next + 1;
			unsigned char const digit = (*first * 16) + *second;
			*bytes = digit;
			++bytes;
		}
		return std::make_pair(begin, bytes);
	}

	Si::optional<content_request> parse_request_path(std::string const &path)
	{
		if (path.empty())
		{
			return Si::none;
		}
		auto digest_begin = path.begin();
		if (*digest_begin == '/')
		{
			++digest_begin;
		}
		content_request request;
		auto const rest = decode_ascii_hex_bytes(digest_begin, path.end(), std::back_inserter(request.digest));
		if (rest.first != path.end())
		{
			return Si::none;
		}
		return std::move(request);
	}

	template <class ReceiveObservable, class MakeSender, class Shutdown>
	void serve_client(
		Si::yield_context<Si::nothing> &yield,
		ReceiveObservable &receive,
		MakeSender const &make_sender,
		Shutdown const &shutdown)
	{
		auto receive_sync = Si::make_observable_source(Si::ref(receive), yield);
		Si::received_from_socket_source receive_bytes(receive_sync);
		auto header = Si::http::parse_header(receive_bytes);
		if (!header)
		{
			return;
		}

		auto const request = parse_request_path(header->path);
		if (!request)
		{
			//TODO: 404 or sth
			return;
		}

		auto const &request_ = *request;
		std::string const body = "Hello at " + header->path;

		auto const try_send = [&yield, &make_sender](std::string const &data)
		{
			auto sender = make_sender(Si::incoming_bytes(data.data(), data.data() + data.size()));
			auto error = yield.get_one(sender);
			assert(error);
			return !*error;
		};

		{
			Si::http::response_header response;
			response.http_version = "HTTP/1.0";
			response.status_text = "OK";
			response.status = 200;
			response.arguments["Content-Length"] = boost::lexical_cast<std::string>(body.size());
			response.arguments["Connection"] = "close";

			std::string response_header;
			auto header_sink = Si::make_container_sink(response_header);
			Si::http::write_header(header_sink, response);

			if (!try_send(response_header))
			{
				return;
			}
		}

		if (!try_send(body))
		{
			return;
		}

		shutdown();

		while (Si::get(receive_bytes))
		{
		}
	}

	//TODO: use unique_observable
	using session_handle = Si::shared_observable<Si::nothing>;
}

int main()
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 8080));
	Si::tcp_acceptor clients(acceptor);

	auto accept_all = Si::make_coroutine<session_handle>([&clients](Si::yield_context<session_handle> &yield)
	{
		for (;;)
		{
			auto accepted = yield.get_one(clients);
			if (!accepted)
			{
				return;
			}
			Si::visit<void>(
				*accepted,
				[&yield](std::shared_ptr<boost::asio::ip::tcp::socket> socket)
				{
					auto prepare_socket = [socket](Si::yield_context<Si::nothing> &yield)
					{
						std::array<char, 1024> receive_buffer;
						Si::socket_observable received(*socket, boost::make_iterator_range(receive_buffer.data(), receive_buffer.data() + receive_buffer.size()));
						auto make_sender = [socket](Si::incoming_bytes sent)
						{
							return Si::sending_observable(*socket, to_range(sent));
						};
						auto shutdown = [socket]()
						{
							socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
						};
						serve_client(yield, received, make_sender, shutdown);
					};
					yield(Si::erase_shared(Si::make_coroutine<Si::nothing>(prepare_socket)));
				},
				[](boost::system::error_code)
				{
					throw std::logic_error("to do");
				}
			);
		}
	});
	auto all_sessions_finished = Si::flatten<boost::interprocess::null_mutex>(std::move(accept_all));
	auto done = Si::make_total_consumer(std::move(all_sessions_finished));
	done.start();
	io.run();
}
<commit_msg>fix warnings<commit_after>#include <silicium/tcp_acceptor.hpp>
#include <silicium/coroutine.hpp>
#include <silicium/total_consumer.hpp>
#include <silicium/flatten.hpp>
#include <silicium/socket_observable.hpp>
#include <silicium/sending_observable.hpp>
#include <silicium/received_from_socket_source.hpp>
#include <silicium/observable_source.hpp>
#include <silicium/optional.hpp>
#include <silicium/http/http.hpp>
#include <boost/interprocess/sync/null_mutex.hpp>
#include <boost/container/vector.hpp>

namespace
{
	using response_part = Si::incoming_bytes;

	boost::iterator_range<char const *> to_range(response_part part)
	{
		return boost::make_iterator_range(part.begin, part.end);
	}

	struct content_request
	{
#ifdef _MSC_VER
		std::vector
#else
		boost::container::vector
#endif
			<unsigned char> digest;
	};

	Si::optional<unsigned char> decode_ascii_hex_digit(char digit)
	{
		switch (digit)
		{
		case '0': return 0;
		case '1': return 1;
		case '2': return 2;
		case '3': return 3;
		case '4': return 4;
		case '5': return 5;
		case '6': return 6;
		case '7': return 7;
		case '8': return 8;
		case '9': return 9;
		case 'a': case 'A': return 10;
		case 'b': case 'B': return 11;
		case 'c': case 'C': return 12;
		case 'd': case 'D': return 13;
		case 'e': case 'E': return 14;
		case 'f': case 'F': return 15;
		default:
			return Si::none;
		}
	}

	template <class InputIterator, class OutputIterator>
	std::pair<InputIterator, OutputIterator> decode_ascii_hex_bytes(InputIterator begin, InputIterator end, OutputIterator bytes)
	{
		for (;;)
		{
			if (begin == end)
			{
				break;
			}
			char const first_char = *begin;
			Si::optional<unsigned char> const first = decode_ascii_hex_digit(first_char);
			if (!first)
			{
				break;
			}
			auto const next = begin + 1;
			if (next == end)
			{
				break;
			}
			char const second_char = *next;
			Si::optional<unsigned char> const second = decode_ascii_hex_digit(second_char);
			if (!second)
			{
				break;
			}
			begin = next + 1;
			unsigned char const digit = static_cast<unsigned char>((*first * 16) + *second);
			*bytes = digit;
			++bytes;
		}
		return std::make_pair(begin, bytes);
	}

	Si::optional<content_request> parse_request_path(std::string const &path)
	{
		if (path.empty())
		{
			return Si::none;
		}
		auto digest_begin = path.begin();
		if (*digest_begin == '/')
		{
			++digest_begin;
		}
		content_request request;
		auto const rest = decode_ascii_hex_bytes(digest_begin, path.end(), std::back_inserter(request.digest));
		if (rest.first != path.end())
		{
			return Si::none;
		}
		return std::move(request);
	}

	template <class ReceiveObservable, class MakeSender, class Shutdown>
	void serve_client(
		Si::yield_context<Si::nothing> &yield,
		ReceiveObservable &receive,
		MakeSender const &make_sender,
		Shutdown const &shutdown)
	{
		auto receive_sync = Si::make_observable_source(Si::ref(receive), yield);
		Si::received_from_socket_source receive_bytes(receive_sync);
		auto header = Si::http::parse_header(receive_bytes);
		if (!header)
		{
			return;
		}

		auto const request = parse_request_path(header->path);
		if (!request)
		{
			//TODO: 404 or sth
			return;
		}

		std::string const body = "Hello at " + header->path;

		auto const try_send = [&yield, &make_sender](std::string const &data)
		{
			auto sender = make_sender(Si::incoming_bytes(data.data(), data.data() + data.size()));
			auto error = yield.get_one(sender);
			assert(error);
			return !*error;
		};

		{
			Si::http::response_header response;
			response.http_version = "HTTP/1.0";
			response.status_text = "OK";
			response.status = 200;
			response.arguments["Content-Length"] = boost::lexical_cast<std::string>(body.size());
			response.arguments["Connection"] = "close";

			std::string response_header;
			auto header_sink = Si::make_container_sink(response_header);
			Si::http::write_header(header_sink, response);

			if (!try_send(response_header))
			{
				return;
			}
		}

		if (!try_send(body))
		{
			return;
		}

		shutdown();

		while (Si::get(receive_bytes))
		{
		}
	}

	//TODO: use unique_observable
	using session_handle = Si::shared_observable<Si::nothing>;
}

int main()
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 8080));
	Si::tcp_acceptor clients(acceptor);

	auto accept_all = Si::make_coroutine<session_handle>([&clients](Si::yield_context<session_handle> &yield)
	{
		for (;;)
		{
			auto accepted = yield.get_one(clients);
			if (!accepted)
			{
				return;
			}
			Si::visit<void>(
				*accepted,
				[&yield](std::shared_ptr<boost::asio::ip::tcp::socket> socket)
				{
					auto prepare_socket = [socket](Si::yield_context<Si::nothing> &yield)
					{
						std::array<char, 1024> receive_buffer;
						Si::socket_observable received(*socket, boost::make_iterator_range(receive_buffer.data(), receive_buffer.data() + receive_buffer.size()));
						auto make_sender = [socket](Si::incoming_bytes sent)
						{
							return Si::sending_observable(*socket, to_range(sent));
						};
						auto shutdown = [socket]()
						{
							socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
						};
						serve_client(yield, received, make_sender, shutdown);
					};
					yield(Si::erase_shared(Si::make_coroutine<Si::nothing>(prepare_socket)));
				},
				[](boost::system::error_code)
				{
					throw std::logic_error("to do");
				}
			);
		}
	});
	auto all_sessions_finished = Si::flatten<boost::interprocess::null_mutex>(std::move(accept_all));
	auto done = Si::make_total_consumer(std::move(all_sessions_finished));
	done.start();
	io.run();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ItemPropertyMap.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: bm $ $Date: 2003-10-07 17:18:18 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2003 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef CHART_ITEMPROPERTYMAP_HXX
#define CHART_ITEMPROPERTYMAP_HXX

#include "InlineContainer.hxx"

namespace comphelper
{

typedef ::std::map< USHORT, ::rtl::OUString > ItemPropertyMapType;
typedef ::comphelper::MakeMap< USHORT, ::rtl::OUString > MakeItemPropertyMap;

class FillItemSetFunc : public ::std::unary_function< void, ItemConverter * >
{
public:
    explicit FillItemSetFunc( SfxItemSet & rOutItemSet ) :
            m_rOutItemSet( rOutItemSet )
    {}

    void operator() ( ItemConverter * pConv )
    {
        pConv->FillItemSet( m_rOutItemSet );
    }

private:
    SfxItemSet & m_rOutItemSet;
};

class ApplyItemSetFunc : public ::std::unary_function< void, ItemConverter * >
{
public:
    explicit ApplyItemSetFunc( const SfxItemSet & rItemSet,
                               bool & rOutResult ) :
            m_rItemSet( rItemSet ),
            m_rOutResult( rOutResult )
    {}

    void operator() ( ItemConverter * pConv )
    {
        m_rOutResult = pConv->ApplyItemSet( m_rItemSet ) || m_rOutResult;
    }

private:
    const SfxItemSet & m_rItemSet;
    bool & m_rOutResult;
};

struct DeleteItemConverterPtr : public ::std::unary_function< void, ItemConverter * >
{
    void operator() ( ItemConverter * pConv )
    { delete pConv; }
};

} //  namespace comphelper

// CHART_ITEMPROPERTYMAP_HXX
#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.110); FILE MERGED 2005/09/05 18:42:33 rt 1.2.110.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ItemPropertyMap.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 00:23:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef CHART_ITEMPROPERTYMAP_HXX
#define CHART_ITEMPROPERTYMAP_HXX

#include "InlineContainer.hxx"

namespace comphelper
{

typedef ::std::map< USHORT, ::rtl::OUString > ItemPropertyMapType;
typedef ::comphelper::MakeMap< USHORT, ::rtl::OUString > MakeItemPropertyMap;

class FillItemSetFunc : public ::std::unary_function< void, ItemConverter * >
{
public:
    explicit FillItemSetFunc( SfxItemSet & rOutItemSet ) :
            m_rOutItemSet( rOutItemSet )
    {}

    void operator() ( ItemConverter * pConv )
    {
        pConv->FillItemSet( m_rOutItemSet );
    }

private:
    SfxItemSet & m_rOutItemSet;
};

class ApplyItemSetFunc : public ::std::unary_function< void, ItemConverter * >
{
public:
    explicit ApplyItemSetFunc( const SfxItemSet & rItemSet,
                               bool & rOutResult ) :
            m_rItemSet( rItemSet ),
            m_rOutResult( rOutResult )
    {}

    void operator() ( ItemConverter * pConv )
    {
        m_rOutResult = pConv->ApplyItemSet( m_rItemSet ) || m_rOutResult;
    }

private:
    const SfxItemSet & m_rItemSet;
    bool & m_rOutResult;
};

struct DeleteItemConverterPtr : public ::std::unary_function< void, ItemConverter * >
{
    void operator() ( ItemConverter * pConv )
    { delete pConv; }
};

} //  namespace comphelper

// CHART_ITEMPROPERTYMAP_HXX
#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "VLegendSymbolFactory.hxx"
#include "macros.hxx"
#include "PropertyMapper.hxx"
#include "AbstractShapeFactory.hxx"
#include "ObjectIdentifier.hxx"
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/chart2/Symbol.hpp>

using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;

namespace
{

void getPropNamesAndValues( const Reference< beans::XPropertySet >& xProp,
        ::chart::tNameSequence& rNames,
        ::chart::tAnySequence& rValues,
        ::chart::VLegendSymbolFactory::tPropertyType ePropertyType,
        const awt::Size& aMaxSymbolExtent = awt::Size(0,0))
{
    const ::chart::tPropertyNameMap & aFilledSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForFilledSeriesProperties());
    const ::chart::tPropertyNameMap & aLineSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineSeriesProperties());
    const ::chart::tPropertyNameMap & aLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineProperties());
    const ::chart::tPropertyNameMap & aFillNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillProperties());
    const ::chart::tPropertyNameMap & aFillLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties());

    ::chart::tPropertyNameValueMap aValueMap;
    switch( ePropertyType )
    {
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFilledSeriesNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE_SERIES:
            ::chart::PropertyMapper::getValueMap( aValueMap, aLineSeriesNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE:
            ::chart::PropertyMapper::getValueMap( aValueMap, aLineNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFillNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL_AND_LINE:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFillLineNameMap, xProp );
            break;
    }

    ::chart::PropertyMapper::getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap );

    uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(rValues,rNames,"LineWidth");
    sal_Int32 nLineWidth = 0;
    if( pLineWidthAny && (*pLineWidthAny>>=nLineWidth) )
    {
        // use legend entry height as upper limit for line width
        sal_Int32 nMaxLineWidthForLegend = aMaxSymbolExtent.Height;
        if( nLineWidth>nMaxLineWidthForLegend )
            *pLineWidthAny = uno::makeAny( nMaxLineWidthForLegend );
    }
}

void lcl_setPropetiesToShape(
    const Reference< beans::XPropertySet > & xProp,
    const Reference< drawing::XShape > & xShape,
    ::chart::VLegendSymbolFactory::tPropertyType ePropertyType,
    const awt::Size& aMaxSymbolExtent = awt::Size(0,0))
{
    ::chart::tNameSequence aPropNames;
    ::chart::tAnySequence aPropValues;
    getPropNamesAndValues( xProp, aPropNames, aPropValues,
            ePropertyType, aMaxSymbolExtent );

    Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
    ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
}

} // anonymous namespace

namespace chart
{

Reference< drawing::XShape > VLegendSymbolFactory::createSymbol(
    const awt::Size& rEntryKeyAspectRatio,
    const Reference< drawing::XShapes > xSymbolContainer,
    LegendSymbolStyle eStyle,
    const Reference< lang::XMultiServiceFactory > & xShapeFactory,
    const Reference< beans::XPropertySet > & xLegendEntryProperties,
    tPropertyType ePropertyType, const uno::Any& rExplicitSymbol )
{
    Reference< drawing::XShape > xResult;

    if( ! (xSymbolContainer.is() && xShapeFactory.is()))
        return xResult;

    AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(xShapeFactory);
    xResult.set( pShapeFactory->createGroup2D( xSymbolContainer ), uno::UNO_QUERY );

    Reference< drawing::XShapes > xResultGroup( xResult, uno::UNO_QUERY );
    if( ! xResultGroup.is())
        return xResult;

    // add an invisible square box to maintain aspect ratio
    Reference< drawing::XShape > xBound( pShapeFactory->createInvisibleRectangle(
                xResultGroup, rEntryKeyAspectRatio  ));

    // create symbol
    try
    {
        if( eStyle == LegendSymbolStyle_LINE )
        {
            Reference< drawing::XShape > xLine =
                pShapeFactory->createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ),
                        awt::Point( 0, rEntryKeyAspectRatio.Height/2 ));
            if( xLine.is())
            {
                lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio );
            }

            Reference< drawing::XShape > xSymbol;
            const sal_Int32 nSize = std::min(rEntryKeyAspectRatio.Width,rEntryKeyAspectRatio.Height);
            chart2::Symbol aSymbol;
            if( rExplicitSymbol >>= aSymbol )
            {
                drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
                drawing::Position3D aPos( rEntryKeyAspectRatio.Width/2, rEntryKeyAspectRatio.Height/2, 0 );
                AbstractShapeFactory* pFactory = AbstractShapeFactory::getOrCreateShapeFactory( xShapeFactory );
                if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
                {
                    // take series color as fill color
                    xLegendEntryProperties->getPropertyValue( "Color") >>= aSymbol.FillColor;
                    // border of symbols always same as fill color
                    aSymbol.BorderColor = aSymbol.FillColor;

                    xSymbol.set( pFactory->createSymbol2D(
                                     xResultGroup,
                                     aPos,
                                     aSymbolSize,
                                     aSymbol.StandardSymbol,
                                     aSymbol.BorderColor,
                                     aSymbol.FillColor ));
                }
                else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
                {
                    xSymbol.set( pFactory->createGraphic2D(
                                     xResultGroup,
                                     aPos,
                                     aSymbolSize,
                                     aSymbol.Graphic ));
                }
                else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
                {
                    SAL_WARN("chart2", "the given parameter is not allowed to contain an automatic symbol style");
                }
            }
        }
        else if( eStyle == LegendSymbolStyle_CIRCLE )
        {
            sal_Int32 nSize = std::min( rEntryKeyAspectRatio.Width, rEntryKeyAspectRatio.Height );
            Reference< drawing::XShape > xShape =
                pShapeFactory->createCircle( xResultGroup, awt::Size( nSize, nSize ),
                        awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 ));
            if( xShape.is() )
            {
                lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
            }
        }
        else // eStyle == LegendSymbolStyle_BOX
        {
            tNameSequence aPropNames;
            tAnySequence aPropValues;

            getPropNamesAndValues( xLegendEntryProperties, aPropNames, aPropValues,
                    ePropertyType );// PROP_TYPE_FILLED_SERIES

            Reference< drawing::XShape > xShape =
                pShapeFactory->createRectangle( xResultGroup,
                        rEntryKeyAspectRatio, awt::Point( 0, 0 ),
                        aPropNames, aPropValues );
        }
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    return xResult;
}

} //  namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#1242832 Result is not floating-point<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "VLegendSymbolFactory.hxx"
#include "macros.hxx"
#include "PropertyMapper.hxx"
#include "AbstractShapeFactory.hxx"
#include "ObjectIdentifier.hxx"
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/chart2/Symbol.hpp>

using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;

namespace
{

void getPropNamesAndValues( const Reference< beans::XPropertySet >& xProp,
        ::chart::tNameSequence& rNames,
        ::chart::tAnySequence& rValues,
        ::chart::VLegendSymbolFactory::tPropertyType ePropertyType,
        const awt::Size& aMaxSymbolExtent = awt::Size(0,0))
{
    const ::chart::tPropertyNameMap & aFilledSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForFilledSeriesProperties());
    const ::chart::tPropertyNameMap & aLineSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineSeriesProperties());
    const ::chart::tPropertyNameMap & aLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineProperties());
    const ::chart::tPropertyNameMap & aFillNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillProperties());
    const ::chart::tPropertyNameMap & aFillLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties());

    ::chart::tPropertyNameValueMap aValueMap;
    switch( ePropertyType )
    {
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFilledSeriesNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE_SERIES:
            ::chart::PropertyMapper::getValueMap( aValueMap, aLineSeriesNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE:
            ::chart::PropertyMapper::getValueMap( aValueMap, aLineNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFillNameMap, xProp );
            break;
        case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL_AND_LINE:
            ::chart::PropertyMapper::getValueMap( aValueMap, aFillLineNameMap, xProp );
            break;
    }

    ::chart::PropertyMapper::getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap );

    uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(rValues,rNames,"LineWidth");
    sal_Int32 nLineWidth = 0;
    if( pLineWidthAny && (*pLineWidthAny>>=nLineWidth) )
    {
        // use legend entry height as upper limit for line width
        sal_Int32 nMaxLineWidthForLegend = aMaxSymbolExtent.Height;
        if( nLineWidth>nMaxLineWidthForLegend )
            *pLineWidthAny = uno::makeAny( nMaxLineWidthForLegend );
    }
}

void lcl_setPropetiesToShape(
    const Reference< beans::XPropertySet > & xProp,
    const Reference< drawing::XShape > & xShape,
    ::chart::VLegendSymbolFactory::tPropertyType ePropertyType,
    const awt::Size& aMaxSymbolExtent = awt::Size(0,0))
{
    ::chart::tNameSequence aPropNames;
    ::chart::tAnySequence aPropValues;
    getPropNamesAndValues( xProp, aPropNames, aPropValues,
            ePropertyType, aMaxSymbolExtent );

    Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
    ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
}

} // anonymous namespace

namespace chart
{

Reference< drawing::XShape > VLegendSymbolFactory::createSymbol(
    const awt::Size& rEntryKeyAspectRatio,
    const Reference< drawing::XShapes > xSymbolContainer,
    LegendSymbolStyle eStyle,
    const Reference< lang::XMultiServiceFactory > & xShapeFactory,
    const Reference< beans::XPropertySet > & xLegendEntryProperties,
    tPropertyType ePropertyType, const uno::Any& rExplicitSymbol )
{
    Reference< drawing::XShape > xResult;

    if( ! (xSymbolContainer.is() && xShapeFactory.is()))
        return xResult;

    AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(xShapeFactory);
    xResult.set( pShapeFactory->createGroup2D( xSymbolContainer ), uno::UNO_QUERY );

    Reference< drawing::XShapes > xResultGroup( xResult, uno::UNO_QUERY );
    if( ! xResultGroup.is())
        return xResult;

    // add an invisible square box to maintain aspect ratio
    Reference< drawing::XShape > xBound( pShapeFactory->createInvisibleRectangle(
                xResultGroup, rEntryKeyAspectRatio  ));

    // create symbol
    try
    {
        if( eStyle == LegendSymbolStyle_LINE )
        {
            Reference< drawing::XShape > xLine =
                pShapeFactory->createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ),
                        awt::Point( 0, rEntryKeyAspectRatio.Height/2 ));
            if( xLine.is())
            {
                lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio );
            }

            Reference< drawing::XShape > xSymbol;
            const sal_Int32 nSize = std::min(rEntryKeyAspectRatio.Width,rEntryKeyAspectRatio.Height);
            chart2::Symbol aSymbol;
            if( rExplicitSymbol >>= aSymbol )
            {
                drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
                drawing::Position3D aPos( rEntryKeyAspectRatio.Width/2.0, rEntryKeyAspectRatio.Height/2.0, 0 );
                AbstractShapeFactory* pFactory = AbstractShapeFactory::getOrCreateShapeFactory( xShapeFactory );
                if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
                {
                    // take series color as fill color
                    xLegendEntryProperties->getPropertyValue( "Color") >>= aSymbol.FillColor;
                    // border of symbols always same as fill color
                    aSymbol.BorderColor = aSymbol.FillColor;

                    xSymbol.set( pFactory->createSymbol2D(
                                     xResultGroup,
                                     aPos,
                                     aSymbolSize,
                                     aSymbol.StandardSymbol,
                                     aSymbol.BorderColor,
                                     aSymbol.FillColor ));
                }
                else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
                {
                    xSymbol.set( pFactory->createGraphic2D(
                                     xResultGroup,
                                     aPos,
                                     aSymbolSize,
                                     aSymbol.Graphic ));
                }
                else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
                {
                    SAL_WARN("chart2", "the given parameter is not allowed to contain an automatic symbol style");
                }
            }
        }
        else if( eStyle == LegendSymbolStyle_CIRCLE )
        {
            sal_Int32 nSize = std::min( rEntryKeyAspectRatio.Width, rEntryKeyAspectRatio.Height );
            Reference< drawing::XShape > xShape =
                pShapeFactory->createCircle( xResultGroup, awt::Size( nSize, nSize ),
                        awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 ));
            if( xShape.is() )
            {
                lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
            }
        }
        else // eStyle == LegendSymbolStyle_BOX
        {
            tNameSequence aPropNames;
            tAnySequence aPropValues;

            getPropNamesAndValues( xLegendEntryProperties, aPropNames, aPropValues,
                    ePropertyType );// PROP_TYPE_FILLED_SERIES

            Reference< drawing::XShape > xShape =
                pShapeFactory->createRectangle( xResultGroup,
                        rEntryKeyAspectRatio, awt::Point( 0, 0 ),
                        aPropNames, aPropValues );
        }
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    return xResult;
}

} //  namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Ethereum client.
 */

#include <thread>
#include <chrono>
#include <fstream>
#include "Defaults.h"
#include "Client.h"
#include "PeerNetwork.h"
#include "BlockChain.h"
#include "State.h"
#include "FileSystem.h"
#include "Instruction.h"
#include "BuildInfo.h"
using namespace std;
using namespace eth;
using eth::Instruction;
using eth::c_instructionInfo;

bool isTrue(std::string const& _m)
{
	return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
}

bool isFalse(std::string const& _m)
{
	return _m == "off" || _m == "no" || _m == "false" || _m == "0";
}

void help()
{
	cout
        << "Usage eth [OPTIONS] <remote-host>" << endl
        << "Options:" << endl
        << "    -a,--address <addr>  Set the coinbase (mining payout) address to addr (default: auto)." << endl
        << "    -c,--client-name <name>  Add a name to your client's version string (default: blank)." << endl
        << "    -d,--db-path <path>  Load database from path (default:  ~/.ethereum " << endl
        << "                         <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
        << "    -h,--help  Show this help message and exit." << endl
        << "    -i,--interactive  Enter interactive mode (default: non-interactive)." << endl
        << "    -l,--listen <port>  Listen on the given port for incoming connected (default: 30303)." << endl
		<< "    -m,--mining <on/off/number>  Enable mining, optionally for a specified number of blocks (Default: off)" << endl
        << "    -n,--upnp <on/off>  Use upnp for NAT (default: on)." << endl
        << "    -o,--mode <full/peer>  Start a full node or a peer node (Default: full)." << endl
        << "    -p,--port <port>  Connect to remote port (default: 30303)." << endl
        << "    -r,--remote <host>  Connect to remote host (default: none)." << endl
        << "    -s,--secret <secretkeyhex>  Set the secret key for use with send command (default: auto)." << endl
        << "    -u,--public-ip <ip>  Force public ip to given (default; auto)." << endl
        << "    -v,--verbosity <0 - 9>  Set the log verbosity from 0 to 9 (Default: 8)." << endl
        << "    -x,--peers <number>  Attempt to connect to given number of peers (Default: 5)." << endl
        << "    -V,--version  Show the version and exit." << endl;
        exit(0);
}

void interactiveHelp()
{
	cout
        << "Commands:" << endl
        << "    netstart <port> Starts the network sybsystem on a specific port." << endl
        << "    netstop   Stops the network subsystem." << endl
        << "    connect <addr> <port>  Connects to a specific peer." << endl
        << "    minestart  Starts mining." << endl
        << "    minestop  Stops mining." << endl
        << "    address  Gives the current address." << endl
        << "    secret  Gives the current secret" << endl
        << "    block  Gives the current block height." << endl
        << "    balance  Gives the current balance." << endl
        << "    transact <secret> <dest> <amount>  Executes a given transaction." << endl
        << "    send <dest> <amount>  Executes a given transaction with current secret." << endl
        << "    inspect <contract> Dumps a contract to <APPDATA>/<contract>.evm." << endl
        << "    exit  Exits the application." << endl;
}

void version()
{
	cout << "eth version " << ETH_QUOTED(ETH_VERSION) << endl;
	cout << "Build: " << ETH_QUOTED(ETH_BUILD_PLATFORM) << "/" << ETH_QUOTED(ETH_BUILD_TYPE) << endl;
	exit(0);
}

int main(int argc, char** argv)
{
	unsigned short listenPort = 30303;
	string remoteHost;
	unsigned short remotePort = 30303;
	bool interactive = false;
	string dbPath;
	eth::uint mining = ~(eth::uint)0;
	NodeMode mode = NodeMode::Full;
	unsigned peers = 5;
	string publicIP;
	bool upnp = true;
	string clientName;

	// Init defaults
	Defaults::get();

	// Our address.
	KeyPair us = KeyPair::create();
	Address coinbase = us.address();

	string configFile = getDataDir() + "/config.rlp";
	bytes b = contents(configFile);
	if (b.size())
	{
		RLP config(b);
		us = KeyPair(config[0].toHash<Secret>());
		coinbase = config[1].toHash<Address>();
	}
	else
	{
		RLPStream config(2);
		config << us.secret() << coinbase;
		writeFile(configFile, config.out());
	}

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
			publicIP = argv[++i];
		else if ((arg == "-r" || arg == "--remote") && i + 1 < argc)
			remoteHost = argv[++i];
		else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
		{
			string m = argv[++i];
			if (isTrue(m))
				upnp = true;
			else if (isFalse(m))
				upnp = false;
			else
			{
				cerr << "Invalid UPnP option: " << m << endl;
				return -1;
			}
		}
		else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
			clientName = argv[++i];
		else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc)
			coinbase = h160(fromHex(argv[++i]));
		else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
			us = KeyPair(h256(fromHex(argv[++i])));
		else if (arg == "-i" || arg == "--interactive")
			interactive = true;
		else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc)
			dbPath = argv[++i];
		else if ((arg == "-m" || arg == "--mining") && i + 1 < argc)
		{
			string m = argv[++i];
			if (isTrue(m))
				mining = ~(eth::uint)0;
			else if (isFalse(m))
				mining = 0;
			else if (int i = stoi(m))
				mining = i;
			else
			{
				cerr << "Unknown mining option: " << m << endl;
				return -1;
			}
		}
		else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
			g_logVerbosity = atoi(argv[++i]);
		else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
			peers = atoi(argv[++i]);
		else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
		{
			string m = argv[++i];
			if (m == "full")
				mode = NodeMode::Full;
			else if (m == "peer")
				mode = NodeMode::PeerServer;
			else
			{
				cerr << "Unknown mode: " << m << endl;
				return -1;
			}
		}
		else if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-V" || arg == "--version")
			version();
		else
			remoteHost = argv[i];
	}

	if (!clientName.empty())
		clientName += "/";
	Client c("Ethereum(++)/" + clientName + "v" ETH_QUOTED(ETH_VERSION) "/" ETH_QUOTED(ETH_BUILD_TYPE) "/" ETH_QUOTED(ETH_BUILD_PLATFORM), coinbase, dbPath);

	if (interactive)
	{
		cout << "Ethereum (++)" << endl;
		cout << "  Code by Gav Wood, (c) 2013, 2014." << endl;
		cout << "  Based on a design by Vitalik Buterin." << endl << endl;

		while (true)
		{
			cout << "> " << flush;
			std::string cmd;
			cin >> cmd;
			if (cmd == "netstart")
			{
				eth::uint port;
				cin >> port;
				c.startNetwork((short)port);
			}
			else if (cmd == "connect")
			{
				string addr;
				eth::uint port;
				cin >> addr >> port;
				c.connect(addr, (short)port);
			}
			else if (cmd == "netstop")
			{
				c.stopNetwork();
			}
			else if (cmd == "minestart")
			{
				c.startMining();
			}
			else if (cmd == "minestop")
			{
				c.stopMining();
			}
			else if (cmd == "address")
			{
				cout << endl;
				cout << "Current address: " + toHex(us.address().asArray()) << endl;
				cout << "===" << endl;
			}
			else if (cmd == "secret")
			{
				cout << endl;
				cout << "Current secret: " + toHex(us.secret().asArray()) << endl;
				cout << "===" << endl;
			}
			else if (cmd == "block")
			{
				eth::uint n = c.blockChain().details().number;
				cout << endl;
				cout << "Current block # " << n << endl;
				cout << "===" << endl;
			}
			else if (cmd == "balance")
			{
				u256 balance = c.state().balance(us.address());
				cout << endl;
				cout << "Current balance: ";
				cout << balance << endl;
				cout << "===" << endl;
			}
			else if (cmd == "transact")
			{
				string sechex;
				string rechex;
				u256 amount;
				cin >> sechex >> rechex >> amount;
				Secret secret = h256(fromHex(sechex));
				Address dest = h160(fromHex(rechex));
				c.transact(secret, dest, amount);
			}
			else if (cmd == "send")
			{
				string rechex;
				u256 amount;
				cin >> rechex >> amount;
				Address dest = h160(fromHex(rechex));
				c.transact(us.secret(), dest, amount);
			}
			else if (cmd == "inspect")
			{
				string rechex;
				cin >> rechex;

				c.lock();
				auto hba = h160(fromHex(rechex));
				auto h = h160((byte const*)hba.data(), h160::ConstructFromPointer);

				stringstream s;
				auto mem = c.state().contractMemory(h);
				u256 next = 0;
				unsigned numerics = 0;
				bool unexpectedNumeric = false;
				for (auto i: mem)
				{
					if (next < i.first)
					{
						unsigned j;
						for (j = 0; j <= numerics && next + j < i.first; ++j)
							s << (j < numerics || unexpectedNumeric ? " 0" : " STOP");
						unexpectedNumeric = false;
						numerics -= min(numerics, j);
						if (next + j < i.first)
							s << "\n@" << showbase << hex << i.first << "    ";
					}
					else if (!next)
					{
						s << "@" << showbase << hex << i.first << "    ";
					}
					auto iit = c_instructionInfo.find((Instruction)(unsigned)i.second);
					if (numerics || iit == c_instructionInfo.end() || (u256)(unsigned)iit->first != i.second)	// not an instruction or expecting an argument...
					{
						if (numerics)
							numerics--;
						else
							unexpectedNumeric = true;
						s << " " << showbase << hex << i.second;
					}
					else
					{
						auto const& ii = iit->second;
						s << " " << ii.name;
						numerics = ii.additional;
					}
					next = i.first + 1;
				}

				string outFile = getDataDir() + "/" + rechex + ".evm";
				ofstream ofs;
				ofs.open(outFile, ofstream::binary);
				ofs.write(s.str().c_str(), s.str().length());
				ofs.close();

				c.unlock();
			}
			else if (cmd == "help")
			{
				interactiveHelp();
			}
			else if (cmd == "exit")
			{
				break;
			}
		}
	}
	else
	{
		cout << "Address: " << endl << toHex(us.address().asArray()) << endl;
		c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp);
		eth::uint n = c.blockChain().details().number;
		if (mining)
			c.startMining();
		while (true)
		{
			if (c.blockChain().details().number - n == mining)
				c.stopMining();
			this_thread::sleep_for(chrono::milliseconds(100));
		}
	}

	return 0;
}
<commit_msg>remove unnecessary replication of the contract's address<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Ethereum client.
 */

#include <thread>
#include <chrono>
#include <fstream>
#include "Defaults.h"
#include "Client.h"
#include "PeerNetwork.h"
#include "BlockChain.h"
#include "State.h"
#include "FileSystem.h"
#include "Instruction.h"
#include "BuildInfo.h"
using namespace std;
using namespace eth;
using eth::Instruction;
using eth::c_instructionInfo;

bool isTrue(std::string const& _m)
{
	return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
}

bool isFalse(std::string const& _m)
{
	return _m == "off" || _m == "no" || _m == "false" || _m == "0";
}

void help()
{
	cout
        << "Usage eth [OPTIONS] <remote-host>" << endl
        << "Options:" << endl
        << "    -a,--address <addr>  Set the coinbase (mining payout) address to addr (default: auto)." << endl
        << "    -c,--client-name <name>  Add a name to your client's version string (default: blank)." << endl
        << "    -d,--db-path <path>  Load database from path (default:  ~/.ethereum " << endl
        << "                         <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
        << "    -h,--help  Show this help message and exit." << endl
        << "    -i,--interactive  Enter interactive mode (default: non-interactive)." << endl
        << "    -l,--listen <port>  Listen on the given port for incoming connected (default: 30303)." << endl
		<< "    -m,--mining <on/off/number>  Enable mining, optionally for a specified number of blocks (Default: off)" << endl
        << "    -n,--upnp <on/off>  Use upnp for NAT (default: on)." << endl
        << "    -o,--mode <full/peer>  Start a full node or a peer node (Default: full)." << endl
        << "    -p,--port <port>  Connect to remote port (default: 30303)." << endl
        << "    -r,--remote <host>  Connect to remote host (default: none)." << endl
        << "    -s,--secret <secretkeyhex>  Set the secret key for use with send command (default: auto)." << endl
        << "    -u,--public-ip <ip>  Force public ip to given (default; auto)." << endl
        << "    -v,--verbosity <0 - 9>  Set the log verbosity from 0 to 9 (Default: 8)." << endl
        << "    -x,--peers <number>  Attempt to connect to given number of peers (Default: 5)." << endl
        << "    -V,--version  Show the version and exit." << endl;
        exit(0);
}

void interactiveHelp()
{
	cout
        << "Commands:" << endl
        << "    netstart <port> Starts the network sybsystem on a specific port." << endl
        << "    netstop   Stops the network subsystem." << endl
        << "    connect <addr> <port>  Connects to a specific peer." << endl
        << "    minestart  Starts mining." << endl
        << "    minestop  Stops mining." << endl
        << "    address  Gives the current address." << endl
        << "    secret  Gives the current secret" << endl
        << "    block  Gives the current block height." << endl
        << "    balance  Gives the current balance." << endl
        << "    transact <secret> <dest> <amount>  Executes a given transaction." << endl
        << "    send <dest> <amount>  Executes a given transaction with current secret." << endl
        << "    inspect <contract> Dumps a contract to <APPDATA>/<contract>.evm." << endl
        << "    exit  Exits the application." << endl;
}

void version()
{
	cout << "eth version " << ETH_QUOTED(ETH_VERSION) << endl;
	cout << "Build: " << ETH_QUOTED(ETH_BUILD_PLATFORM) << "/" << ETH_QUOTED(ETH_BUILD_TYPE) << endl;
	exit(0);
}

int main(int argc, char** argv)
{
	unsigned short listenPort = 30303;
	string remoteHost;
	unsigned short remotePort = 30303;
	bool interactive = false;
	string dbPath;
	eth::uint mining = ~(eth::uint)0;
	NodeMode mode = NodeMode::Full;
	unsigned peers = 5;
	string publicIP;
	bool upnp = true;
	string clientName;

	// Init defaults
	Defaults::get();

	// Our address.
	KeyPair us = KeyPair::create();
	Address coinbase = us.address();

	string configFile = getDataDir() + "/config.rlp";
	bytes b = contents(configFile);
	if (b.size())
	{
		RLP config(b);
		us = KeyPair(config[0].toHash<Secret>());
		coinbase = config[1].toHash<Address>();
	}
	else
	{
		RLPStream config(2);
		config << us.secret() << coinbase;
		writeFile(configFile, config.out());
	}

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
			publicIP = argv[++i];
		else if ((arg == "-r" || arg == "--remote") && i + 1 < argc)
			remoteHost = argv[++i];
		else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
		{
			string m = argv[++i];
			if (isTrue(m))
				upnp = true;
			else if (isFalse(m))
				upnp = false;
			else
			{
				cerr << "Invalid UPnP option: " << m << endl;
				return -1;
			}
		}
		else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
			clientName = argv[++i];
		else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc)
			coinbase = h160(fromHex(argv[++i]));
		else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
			us = KeyPair(h256(fromHex(argv[++i])));
		else if (arg == "-i" || arg == "--interactive")
			interactive = true;
		else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc)
			dbPath = argv[++i];
		else if ((arg == "-m" || arg == "--mining") && i + 1 < argc)
		{
			string m = argv[++i];
			if (isTrue(m))
				mining = ~(eth::uint)0;
			else if (isFalse(m))
				mining = 0;
			else if (int i = stoi(m))
				mining = i;
			else
			{
				cerr << "Unknown mining option: " << m << endl;
				return -1;
			}
		}
		else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
			g_logVerbosity = atoi(argv[++i]);
		else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
			peers = atoi(argv[++i]);
		else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
		{
			string m = argv[++i];
			if (m == "full")
				mode = NodeMode::Full;
			else if (m == "peer")
				mode = NodeMode::PeerServer;
			else
			{
				cerr << "Unknown mode: " << m << endl;
				return -1;
			}
		}
		else if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-V" || arg == "--version")
			version();
		else
			remoteHost = argv[i];
	}

	if (!clientName.empty())
		clientName += "/";
	Client c("Ethereum(++)/" + clientName + "v" ETH_QUOTED(ETH_VERSION) "/" ETH_QUOTED(ETH_BUILD_TYPE) "/" ETH_QUOTED(ETH_BUILD_PLATFORM), coinbase, dbPath);

	if (interactive)
	{
		cout << "Ethereum (++)" << endl;
		cout << "  Code by Gav Wood, (c) 2013, 2014." << endl;
		cout << "  Based on a design by Vitalik Buterin." << endl << endl;

		while (true)
		{
			cout << "> " << flush;
			std::string cmd;
			cin >> cmd;
			if (cmd == "netstart")
			{
				eth::uint port;
				cin >> port;
				c.startNetwork((short)port);
			}
			else if (cmd == "connect")
			{
				string addr;
				eth::uint port;
				cin >> addr >> port;
				c.connect(addr, (short)port);
			}
			else if (cmd == "netstop")
			{
				c.stopNetwork();
			}
			else if (cmd == "minestart")
			{
				c.startMining();
			}
			else if (cmd == "minestop")
			{
				c.stopMining();
			}
			else if (cmd == "address")
			{
				cout << endl;
				cout << "Current address: " + toHex(us.address().asArray()) << endl;
				cout << "===" << endl;
			}
			else if (cmd == "secret")
			{
				cout << endl;
				cout << "Current secret: " + toHex(us.secret().asArray()) << endl;
				cout << "===" << endl;
			}
			else if (cmd == "block")
			{
				eth::uint n = c.blockChain().details().number;
				cout << endl;
				cout << "Current block # " << n << endl;
				cout << "===" << endl;
			}
			else if (cmd == "balance")
			{
				u256 balance = c.state().balance(us.address());
				cout << endl;
				cout << "Current balance: ";
				cout << balance << endl;
				cout << "===" << endl;
			}
			else if (cmd == "transact")
			{
				string sechex;
				string rechex;
				u256 amount;
				cin >> sechex >> rechex >> amount;
				Secret secret = h256(fromHex(sechex));
				Address dest = h160(fromHex(rechex));
				c.transact(secret, dest, amount);
			}
			else if (cmd == "send")
			{
				string rechex;
				u256 amount;
				cin >> rechex >> amount;
				Address dest = h160(fromHex(rechex));
				c.transact(us.secret(), dest, amount);
			}
			else if (cmd == "inspect")
			{
				string rechex;
				cin >> rechex;

				c.lock();
				auto h = h160(fromHex(rechex));

				stringstream s;
				auto mem = c.state().contractMemory(h);
				u256 next = 0;
				unsigned numerics = 0;
				bool unexpectedNumeric = false;
				for (auto i: mem)
				{
					if (next < i.first)
					{
						unsigned j;
						for (j = 0; j <= numerics && next + j < i.first; ++j)
							s << (j < numerics || unexpectedNumeric ? " 0" : " STOP");
						unexpectedNumeric = false;
						numerics -= min(numerics, j);
						if (next + j < i.first)
							s << "\n@" << showbase << hex << i.first << "    ";
					}
					else if (!next)
					{
						s << "@" << showbase << hex << i.first << "    ";
					}
					auto iit = c_instructionInfo.find((Instruction)(unsigned)i.second);
					if (numerics || iit == c_instructionInfo.end() || (u256)(unsigned)iit->first != i.second)	// not an instruction or expecting an argument...
					{
						if (numerics)
							numerics--;
						else
							unexpectedNumeric = true;
						s << " " << showbase << hex << i.second;
					}
					else
					{
						auto const& ii = iit->second;
						s << " " << ii.name;
						numerics = ii.additional;
					}
					next = i.first + 1;
				}

				string outFile = getDataDir() + "/" + rechex + ".evm";
				ofstream ofs;
				ofs.open(outFile, ofstream::binary);
				ofs.write(s.str().c_str(), s.str().length());
				ofs.close();

				c.unlock();
			}
			else if (cmd == "help")
			{
				interactiveHelp();
			}
			else if (cmd == "exit")
			{
				break;
			}
		}
	}
	else
	{
		cout << "Address: " << endl << toHex(us.address().asArray()) << endl;
		c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp);
		eth::uint n = c.blockChain().details().number;
		if (mining)
			c.startMining();
		while (true)
		{
			if (c.blockChain().details().number - n == mining)
				c.stopMining();
			this_thread::sleep_for(chrono::milliseconds(100));
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>#ifndef SERVER_HTTP_HPP
#define	SERVER_HTTP_HPP

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

#include <regex>
#include <unordered_map>
#include <thread>
#include <functional>

namespace SimpleWeb {
    template <class socket_type>
    class ServerBase {
    public:
        class Response {
            friend class ServerBase<socket_type>;
        private:
            std::shared_ptr<boost::asio::strand> strand;

            boost::asio::yield_context& yield;

            boost::asio::streambuf streambuf;

            std::shared_ptr<socket_type> socket;

            std::shared_ptr<boost::asio::deadline_timer> async_timer;

            std::shared_ptr<bool> async_writing;
            std::shared_ptr<bool> async_waiting;

            Response(boost::asio::io_service& io_service, std::shared_ptr<socket_type> socket, std::shared_ptr<boost::asio::strand> strand,
                    boost::asio::yield_context& yield):
                    strand(strand), yield(yield), socket(socket), async_timer(new boost::asio::deadline_timer(io_service)),
                    async_writing(new bool(false)), async_waiting(new bool(false)), stream(&streambuf) {}

            void async_flush(std::function<void((const boost::system::error_code&))> callback=nullptr) {
                if(!callback && !socket->lowest_layer().is_open()) {
                    if(*async_waiting)
                        async_timer->cancel();
                    throw std::runtime_error("Broken pipe.");
                }

                std::shared_ptr<boost::asio::streambuf> write_buffer(new boost::asio::streambuf);
                std::ostream response(write_buffer.get());
                response << stream.rdbuf();

                //Wait until previous async_flush is finished
                strand->dispatch([this](){
                    if(*async_writing) {
                        *async_waiting=true;
                        try {
                            async_timer->async_wait(yield);
                        }
                        catch(std::exception& e) {
                        }
                        *async_waiting=false;
                    }
                });

                *async_writing=true;

                auto socket_=this->socket;
                auto async_writing_=this->async_writing;
                auto async_timer_=this->async_timer;
                auto async_waiting_=this->async_waiting;

                boost::asio::async_write(*socket, *write_buffer,
                        strand->wrap([socket_, write_buffer, callback, async_writing_, async_timer_, async_waiting_]
                        (const boost::system::error_code& ec, size_t bytes_transferred) {
                    *async_writing_=false;
                    if(*async_waiting_)
                        async_timer_->cancel();
                    if(callback)
                        callback(ec);
                }));
            }

            void flush() {
                boost::asio::streambuf write_buffer;
                std::ostream response(&write_buffer);
                response << stream.rdbuf();

                boost::asio::async_write(*socket, write_buffer, yield);
            }

        public:
            std::ostream stream;

            template <class T>
            Response& operator<<(const T& t) {
                stream << t;
                return *this;
            }

            Response& operator<<(std::ostream& (*manip)(std::ostream&)) {
                stream << manip;
                return *this;
            }

            Response& operator<<(Response& (*manip)(Response&)) {
                return manip(*this);
            }
        };

        static Response& async_flush(Response& r) {
            r.async_flush();
            return r;
        }

        static Response& flush(Response& r) {
            r.flush();
            return r;
        }

        class Request {
            friend class ServerBase<socket_type>;
        public:
            std::string method, path, http_version;

            std::istream content;

            std::unordered_map<std::string, std::string> header;

            std::smatch path_match;

        private:
            Request(): content(&streambuf) {}

            boost::asio::streambuf streambuf;
        };

        std::unordered_map<std::string, std::unordered_map<std::string,
            std::function<void(ServerBase<socket_type>::Response&, std::shared_ptr<ServerBase<socket_type>::Request>)> > >  resource;

        std::unordered_map<std::string,
            std::function<void(ServerBase<socket_type>::Response&, std::shared_ptr<ServerBase<socket_type>::Request>)> > default_resource;

    private:
        std::vector<std::pair<std::string, std::vector<std::pair<std::regex,
            std::function<void(ServerBase<socket_type>::Response&, std::shared_ptr<ServerBase<socket_type>::Request>)> > > > > opt_resource;

    public:
        void start() {
            //Copy the resources to opt_resource for more efficient request processing
            opt_resource.clear();
            for(auto& res: resource) {
                for(auto& res_method: res.second) {
                    auto it=opt_resource.end();
                    for(auto opt_it=opt_resource.begin();opt_it!=opt_resource.end();opt_it++) {
                        if(res_method.first==opt_it->first) {
                            it=opt_it;
                            break;
                        }
                    }
                    if(it==opt_resource.end()) {
                        opt_resource.emplace_back();
                        it=opt_resource.begin()+(opt_resource.size()-1);
                        it->first=res_method.first;
                    }
                    it->second.emplace_back(std::regex(res.first), res_method.second);
                }
            }

            accept();

            //If num_threads>1, start m_io_service.run() in (num_threads-1) threads for thread-pooling
            threads.clear();
            for(size_t c=1;c<num_threads;c++) {
                threads.emplace_back([this](){
                    io_service.run();
                });
            }

            //Main thread
            io_service.run();

            //Wait for the rest of the threads, if any, to finish as well
            for(auto& t: threads) {
                t.join();
            }
        }

        void stop() {
            io_service.stop();
        }

    protected:
        boost::asio::io_service io_service;
        boost::asio::ip::tcp::endpoint endpoint;
        boost::asio::ip::tcp::acceptor acceptor;
        size_t num_threads;
        std::vector<std::thread> threads;

        size_t timeout_request;
        size_t timeout_content;

        ServerBase(unsigned short port, size_t num_threads, size_t timeout_request, size_t timeout_send_or_receive) :
                endpoint(boost::asio::ip::tcp::v4(), port), acceptor(io_service, endpoint), num_threads(num_threads),
                timeout_request(timeout_request), timeout_content(timeout_send_or_receive) {}

        virtual void accept()=0;

        std::shared_ptr<boost::asio::deadline_timer> set_timeout_on_socket(std::shared_ptr<socket_type> socket, size_t seconds) {
            std::shared_ptr<boost::asio::deadline_timer> timer(new boost::asio::deadline_timer(io_service));
            timer->expires_from_now(boost::posix_time::seconds(seconds));
            timer->async_wait([socket](const boost::system::error_code& ec){
                if(!ec) {
                    boost::system::error_code ec;
                    socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket->lowest_layer().close();
                }
            });
            return timer;
        }

        std::shared_ptr<boost::asio::deadline_timer> set_timeout_on_socket(std::shared_ptr<socket_type> socket, std::shared_ptr<boost::asio::strand> strand, size_t seconds) {
            std::shared_ptr<boost::asio::deadline_timer> timer(new boost::asio::deadline_timer(io_service));
            timer->expires_from_now(boost::posix_time::seconds(seconds));
            timer->async_wait(strand->wrap([socket](const boost::system::error_code& ec){
                if(!ec) {
                    boost::system::error_code ec;
                    socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket->lowest_layer().close();
                }
            }));
            return timer;
        }

        void read_request_and_content(std::shared_ptr<socket_type> socket) {
            //Create new streambuf (Request::streambuf) for async_read_until()
            //shared_ptr is used to pass temporary objects to the asynchronous functions
            std::shared_ptr<Request> request(new Request());

            //Set timeout on the following boost::asio::async-read or write function
            std::shared_ptr<boost::asio::deadline_timer> timer;
            if(timeout_request>0)
                timer=set_timeout_on_socket(socket, timeout_request);

            boost::asio::async_read_until(*socket, request->streambuf, "\r\n\r\n",
                    [this, socket, request, timer](const boost::system::error_code& ec, size_t bytes_transferred) {
                if(timeout_request>0)
                    timer->cancel();
                if(!ec) {
                    //request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
                    //"After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter"
                    //The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the
                    //streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content).
                    size_t num_additional_bytes=request->streambuf.size()-bytes_transferred;

                    parse_request(request, request->content);

                    //If content, read that as well
                    if(request->header.count("Content-Length")>0) {
                        //Set timeout on the following boost::asio::async-read or write function
                        std::shared_ptr<boost::asio::deadline_timer> timer;
                        if(timeout_content>0)
                            timer=set_timeout_on_socket(socket, timeout_content);

                        boost::asio::async_read(*socket, request->streambuf,
                                boost::asio::transfer_exactly(stoull(request->header["Content-Length"])-num_additional_bytes),
                                [this, socket, request, timer]
                                (const boost::system::error_code& ec, size_t bytes_transferred) {
                            if(timeout_content>0)
                                timer->cancel();
                            if(!ec)
                                find_resource(socket, request);
                        });
                    }
                    else {
                        find_resource(socket, request);
                    }
                }
            });
        }

        void parse_request(std::shared_ptr<Request> request, std::istream& stream) const {
            std::string line;
            getline(stream, line);
            size_t method_end=line.find(' ');
            size_t path_end=line.find(' ', method_end+1);
            if(method_end!=std::string::npos && path_end!=std::string::npos) {
                request->method=line.substr(0, method_end);
                request->path=line.substr(method_end+1, path_end-method_end-1);
                request->http_version=line.substr(path_end+6, line.size()-path_end-7);

                getline(stream, line);
                size_t param_end=line.find(':');
                while(param_end!=std::string::npos) {
                    size_t value_start=param_end+1;
                    if(line[value_start]==' ')
                        value_start++;

                    request->header[line.substr(0, param_end)]=line.substr(value_start, line.size()-value_start-1);

                    getline(stream, line);
                    param_end=line.find(':');
                }
            }
        }

        void find_resource(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request) {
            //Find path- and method-match, and call write_response
            for(auto& res: opt_resource) {
                if(request->method==res.first) {
                    for(auto& res_path: res.second) {
                        std::smatch sm_res;
                        if(std::regex_match(request->path, sm_res, res_path.first)) {
                            request->path_match=std::move(sm_res);
                            write_response(socket, request, res_path.second);
                            return;
                        }
                    }
                }
            }
            auto it_method=default_resource.find(request->method);
            if(it_method!=default_resource.end()) {
                write_response(socket, request, it_method->second);
            }
        }

        void write_response(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request,
                std::function<void(ServerBase<socket_type>::Response&, std::shared_ptr<ServerBase<socket_type>::Request>)>& resource_function) {
            std::shared_ptr<boost::asio::strand> strand(new boost::asio::strand(io_service));

            //Set timeout on the following boost::asio::async-read or write function
            std::shared_ptr<boost::asio::deadline_timer> timer;
            if(timeout_content>0)
                timer=set_timeout_on_socket(socket, strand, timeout_content);

            boost::asio::spawn(*strand, [this, strand, &resource_function, socket, request, timer](boost::asio::yield_context yield) {
                Response response(io_service, socket, strand, yield);

                try {
                    resource_function(response, request);
                }
                catch(std::exception& e) {
                    return;
                }

                response.async_flush([this, socket, request, timer](const boost::system::error_code& ec) {
                    if(timeout_content>0)
                        timer->cancel();
                    if(!ec && stof(request->http_version)>1.05)
                        read_request_and_content(socket);
                });
            });
        }
    };

    template<class socket_type>
    class Server : public ServerBase<socket_type> {};

    typedef boost::asio::ip::tcp::socket HTTP;

    template<>
    class Server<HTTP> : public ServerBase<HTTP> {
    public:
        Server(unsigned short port, size_t num_threads=1, size_t timeout_request=5, size_t timeout_content=300) :
                ServerBase<HTTP>::ServerBase(port, num_threads, timeout_request, timeout_content) {};

    private:
        void accept() {
            //Create new socket for this connection
            //Shared_ptr is used to pass temporary objects to the asynchronous functions
            std::shared_ptr<HTTP> socket(new HTTP(io_service));

            acceptor.async_accept(*socket, [this, socket](const boost::system::error_code& ec){
                //Immediately start accepting a new connection
                accept();

                if(!ec) {
                    boost::asio::ip::tcp::no_delay option(true);
                    socket->set_option(option);

                    read_request_and_content(socket);
                }
            });
        }
    };
}
#endif	/* SERVER_HTTP_HPP */<commit_msg>Fixed MSVC build of HTTP server.<commit_after>#ifndef SERVER_HTTP_HPP
#define	SERVER_HTTP_HPP

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

#include <regex>
#include <unordered_map>
#include <thread>
#include <functional>

namespace SimpleWeb {
    template <class socket_type>
    class ServerBase {
    public:
        class Response {
            friend class ServerBase<socket_type>;
        private:
            std::shared_ptr<boost::asio::strand> strand;

            boost::asio::yield_context& yield;

            boost::asio::streambuf streambuf;

            std::shared_ptr<socket_type> socket;

            std::shared_ptr<boost::asio::deadline_timer> async_timer;

            std::shared_ptr<bool> async_writing;
            std::shared_ptr<bool> async_waiting;

            Response(boost::asio::io_service& io_service, std::shared_ptr<socket_type> socket, std::shared_ptr<boost::asio::strand> strand,
                    boost::asio::yield_context& yield):
                    strand(strand), yield(yield), socket(socket), async_timer(new boost::asio::deadline_timer(io_service)),
                    async_writing(new bool(false)), async_waiting(new bool(false)), stream(&streambuf) {}

            void async_flush(std::function<void(const boost::system::error_code&)> callback=nullptr) {
                if(!callback && !socket->lowest_layer().is_open()) {
                    if(*async_waiting)
                        async_timer->cancel();
                    throw std::runtime_error("Broken pipe.");
                }

                std::shared_ptr<boost::asio::streambuf> write_buffer(new boost::asio::streambuf);
                std::ostream response(write_buffer.get());
                response << stream.rdbuf();

                //Wait until previous async_flush is finished
                strand->dispatch([this](){
                    if(*async_writing) {
                        *async_waiting=true;
                        try {
                            async_timer->async_wait(yield);
                        }
                        catch(std::exception& e) {
                        }
                        *async_waiting=false;
                    }
                });

                *async_writing=true;

                auto socket_=this->socket;
                auto async_writing_=this->async_writing;
                auto async_timer_=this->async_timer;
                auto async_waiting_=this->async_waiting;

                boost::asio::async_write(*socket, *write_buffer,
                        strand->wrap([socket_, write_buffer, callback, async_writing_, async_timer_, async_waiting_]
                        (const boost::system::error_code& ec, size_t bytes_transferred) {
                    *async_writing_=false;
                    if(*async_waiting_)
                        async_timer_->cancel();
                    if(callback)
                        callback(ec);
                }));
            }

            void flush() {
                boost::asio::streambuf write_buffer;
                std::ostream response(&write_buffer);
                response << stream.rdbuf();

                boost::asio::async_write(*socket, write_buffer, yield);
            }

        public:
            std::ostream stream;

            template <class T>
            Response& operator<<(const T& t) {
                stream << t;
                return *this;
            }

            Response& operator<<(std::ostream& (*manip)(std::ostream&)) {
                stream << manip;
                return *this;
            }

            Response& operator<<(Response& (*manip)(Response&)) {
                return manip(*this);
            }
        };

        static Response& async_flush(Response& r) {
            r.async_flush();
            return r;
        }

        static Response& flush(Response& r) {
            r.flush();
            return r;
        }

        class Request {
            friend class ServerBase<socket_type>;
        public:
            std::string method, path, http_version;

            std::istream content;

            std::unordered_map<std::string, std::string> header;

            std::smatch path_match;

        private:
            Request(): content(&streambuf) {}

            boost::asio::streambuf streambuf;
        };

        std::unordered_map<std::string, std::unordered_map<std::string,
            std::function<void(typename ServerBase<socket_type>::Response&, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > >  resource;

        std::unordered_map<std::string,
            std::function<void(typename ServerBase<socket_type>::Response&, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > default_resource;

    private:
        std::vector<std::pair<std::string, std::vector<std::pair<std::regex,
            std::function<void(typename ServerBase<socket_type>::Response&, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > > > > opt_resource;

    public:
        void start() {
            //Copy the resources to opt_resource for more efficient request processing
            opt_resource.clear();
            for(auto& res: resource) {
                for(auto& res_method: res.second) {
                    auto it=opt_resource.end();
                    for(auto opt_it=opt_resource.begin();opt_it!=opt_resource.end();opt_it++) {
                        if(res_method.first==opt_it->first) {
                            it=opt_it;
                            break;
                        }
                    }
                    if(it==opt_resource.end()) {
                        opt_resource.emplace_back();
                        it=opt_resource.begin()+(opt_resource.size()-1);
                        it->first=res_method.first;
                    }
                    it->second.emplace_back(std::regex(res.first), res_method.second);
                }
            }

            accept();

            //If num_threads>1, start m_io_service.run() in (num_threads-1) threads for thread-pooling
            threads.clear();
            for(size_t c=1;c<num_threads;c++) {
                threads.emplace_back([this](){
                    io_service.run();
                });
            }

            //Main thread
            io_service.run();

            //Wait for the rest of the threads, if any, to finish as well
            for(auto& t: threads) {
                t.join();
            }
        }

        void stop() {
            io_service.stop();
        }

    protected:
        boost::asio::io_service io_service;
        boost::asio::ip::tcp::endpoint endpoint;
        boost::asio::ip::tcp::acceptor acceptor;
        size_t num_threads;
        std::vector<std::thread> threads;

        size_t timeout_request;
        size_t timeout_content;

        ServerBase(unsigned short port, size_t num_threads, size_t timeout_request, size_t timeout_send_or_receive) :
                endpoint(boost::asio::ip::tcp::v4(), port), acceptor(io_service, endpoint), num_threads(num_threads),
                timeout_request(timeout_request), timeout_content(timeout_send_or_receive) {}

        virtual void accept()=0;

        std::shared_ptr<boost::asio::deadline_timer> set_timeout_on_socket(std::shared_ptr<socket_type> socket, size_t seconds) {
            std::shared_ptr<boost::asio::deadline_timer> timer(new boost::asio::deadline_timer(io_service));
            timer->expires_from_now(boost::posix_time::seconds(seconds));
            timer->async_wait([socket](const boost::system::error_code& ec){
                if(!ec) {
                    boost::system::error_code ec;
                    socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket->lowest_layer().close();
                }
            });
            return timer;
        }

        std::shared_ptr<boost::asio::deadline_timer> set_timeout_on_socket(std::shared_ptr<socket_type> socket, std::shared_ptr<boost::asio::strand> strand, size_t seconds) {
            std::shared_ptr<boost::asio::deadline_timer> timer(new boost::asio::deadline_timer(io_service));
            timer->expires_from_now(boost::posix_time::seconds(seconds));
            timer->async_wait(strand->wrap([socket](const boost::system::error_code& ec){
                if(!ec) {
                    boost::system::error_code ec;
                    socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket->lowest_layer().close();
                }
            }));
            return timer;
        }

        void read_request_and_content(std::shared_ptr<socket_type> socket) {
            //Create new streambuf (Request::streambuf) for async_read_until()
            //shared_ptr is used to pass temporary objects to the asynchronous functions
            std::shared_ptr<Request> request(new Request());

            //Set timeout on the following boost::asio::async-read or write function
            std::shared_ptr<boost::asio::deadline_timer> timer;
            if(timeout_request>0)
                timer=set_timeout_on_socket(socket, timeout_request);

            boost::asio::async_read_until(*socket, request->streambuf, "\r\n\r\n",
                    [this, socket, request, timer](const boost::system::error_code& ec, size_t bytes_transferred) {
                if(timeout_request>0)
                    timer->cancel();
                if(!ec) {
                    //request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
                    //"After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter"
                    //The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the
                    //streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content).
                    size_t num_additional_bytes=request->streambuf.size()-bytes_transferred;

                    parse_request(request, request->content);

                    //If content, read that as well
                    if(request->header.count("Content-Length")>0) {
                        //Set timeout on the following boost::asio::async-read or write function
                        std::shared_ptr<boost::asio::deadline_timer> timer;
                        if(timeout_content>0)
                            timer=set_timeout_on_socket(socket, timeout_content);

                        boost::asio::async_read(*socket, request->streambuf,
                                boost::asio::transfer_exactly(stoull(request->header["Content-Length"])-num_additional_bytes),
                                [this, socket, request, timer]
                                (const boost::system::error_code& ec, size_t bytes_transferred) {
                            if(timeout_content>0)
                                timer->cancel();
                            if(!ec)
                                find_resource(socket, request);
                        });
                    }
                    else {
                        find_resource(socket, request);
                    }
                }
            });
        }

        void parse_request(std::shared_ptr<Request> request, std::istream& stream) const {
            std::string line;
            getline(stream, line);
            size_t method_end=line.find(' ');
            size_t path_end=line.find(' ', method_end+1);
            if(method_end!=std::string::npos && path_end!=std::string::npos) {
                request->method=line.substr(0, method_end);
                request->path=line.substr(method_end+1, path_end-method_end-1);
                request->http_version=line.substr(path_end+6, line.size()-path_end-7);

                getline(stream, line);
                size_t param_end=line.find(':');
                while(param_end!=std::string::npos) {
                    size_t value_start=param_end+1;
                    if(line[value_start]==' ')
                        value_start++;

                    request->header[line.substr(0, param_end)]=line.substr(value_start, line.size()-value_start-1);

                    getline(stream, line);
                    param_end=line.find(':');
                }
            }
        }

        void find_resource(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request) {
            //Find path- and method-match, and call write_response
            for(auto& res: opt_resource) {
                if(request->method==res.first) {
                    for(auto& res_path: res.second) {
                        std::smatch sm_res;
                        if(std::regex_match(request->path, sm_res, res_path.first)) {
                            request->path_match=std::move(sm_res);
                            write_response(socket, request, res_path.second);
                            return;
                        }
                    }
                }
            }
            auto it_method=default_resource.find(request->method);
            if(it_method!=default_resource.end()) {
                write_response(socket, request, it_method->second);
            }
        }

        void write_response(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request,
                std::function<void(typename ServerBase<socket_type>::Response&, std::shared_ptr<typename ServerBase<socket_type>::Request>)>& resource_function) {
            std::shared_ptr<boost::asio::strand> strand(new boost::asio::strand(io_service));

            //Set timeout on the following boost::asio::async-read or write function
            std::shared_ptr<boost::asio::deadline_timer> timer;
            if(timeout_content>0)
                timer=set_timeout_on_socket(socket, strand, timeout_content);

            boost::asio::spawn(*strand, [this, strand, &resource_function, socket, request, timer](boost::asio::yield_context yield) {
                Response response(io_service, socket, strand, yield);

                try {
                    resource_function(response, request);
                }
                catch(std::exception& e) {
                    return;
                }

                response.async_flush([this, socket, request, timer](const boost::system::error_code& ec) {
                    if(timeout_content>0)
                        timer->cancel();
                    if(!ec && stof(request->http_version)>1.05)
                        read_request_and_content(socket);
                });
            });
        }
    };

    template<class socket_type>
    class Server : public ServerBase<socket_type> {};

    typedef boost::asio::ip::tcp::socket HTTP;

    template<>
    class Server<HTTP> : public ServerBase<HTTP> {
    public:
        Server(unsigned short port, size_t num_threads=1, size_t timeout_request=5, size_t timeout_content=300) :
                ServerBase<HTTP>::ServerBase(port, num_threads, timeout_request, timeout_content) {};

    private:
        void accept() {
            //Create new socket for this connection
            //Shared_ptr is used to pass temporary objects to the asynchronous functions
            std::shared_ptr<HTTP> socket(new HTTP(io_service));

            acceptor.async_accept(*socket, [this, socket](const boost::system::error_code& ec){
                //Immediately start accepting a new connection
                accept();

                if(!ec) {
                    boost::asio::ip::tcp::no_delay option(true);
                    socket->set_option(option);

                    read_request_and_content(socket);
                }
            });
        }
    };
}
#endif	/* SERVER_HTTP_HPP */<|endoftext|>