<commit_before>#include "generated.hpp"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/test/unit_test.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/source/memory_source.hpp>

BOOST_AUTO_TEST_CASE(async_client_with_callback)
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 0), true);
	acceptor.listen();
	boost::asio::ip::tcp::socket accepted_socket(io);
	std::array<std::uint8_t, 1024> receive_buffer;
	bool ok1 = false;
	acceptor.async_accept(accepted_socket, [&accepted_socket, &receive_buffer, &ok1](boost::system::error_code ec)
	                      {
		                      BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		                      accepted_socket.async_receive(
		                          boost::asio::buffer(receive_buffer),
		                          [&accepted_socket, &ok1](boost::system::error_code ec, std::size_t received)
		                          {
			                          BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
			                          BOOST_REQUIRE_EQUAL(23, received);
			                          BOOST_REQUIRE(!ok1);
			                          ok1 = true;
			                      });
		                  });
	boost::asio::ip::tcp::socket socket(io);
	async_test_interface_client<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> client(socket, socket);
	bool ok2 = false;
	socket.async_connect(
	    boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), acceptor.local_endpoint().port()),
	    [&client, &ok2](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    client.no_result_no_parameter(std::tuple<>(), [&ok2](boost::system::error_code ec, std::tuple<>)
		                                  {
			                                  BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
			                                  BOOST_REQUIRE(!ok2);
			                                  ok2 = true;
			                              });
		});
	io.run();
	BOOST_CHECK(ok1);
	BOOST_CHECK(ok2);
}

namespace
{
	struct impl_test_interface : async_test_interface
	{
		virtual void type_erased_integer_sizes(
		    std::tuple<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t> argument,
		    std::function<void(boost::system::error_code, std::vector<std::uint16_t>)> on_result) override
		{
			on_result({}, std::vector<std::uint16_t>{std::get<1>(argument)});
		}

		virtual void type_erased_no_result_no_parameter(
		    std::tuple<> argument, std::function<void(boost::system::error_code, std::tuple<>)> on_result) override
		{
			on_result({}, argument);
		}

		virtual void
		type_erased_two_parameters(std::tuple<std::uint64_t, std::uint64_t> argument,
		                           std::function<void(boost::system::error_code, std::uint64_t)> on_result) override
		{
			on_result({}, std::get<0>(argument) * std::get<1>(argument));
		}

		virtual void type_erased_two_results(
		    std::uint64_t argument,
		    std::function<void(boost::system::error_code, std::tuple<std::uint64_t, std::uint64_t>)> on_result) override
		{
			on_result({}, std::make_tuple(argument, argument));
		}

		virtual void type_erased_utf8(std::string argument,
		                              std::function<void(boost::system::error_code, std::string)> on_result) override
		{
			on_result({}, argument + "123");
		}

		virtual void type_erased_vectors(
		    std::vector<std::uint64_t> argument,
		    std::function<void(boost::system::error_code, std::vector<std::uint64_t>)> on_result) override
		{
			std::sort(argument.begin(), argument.end(), std::greater<std::uint64_t>());
			on_result({}, std::move(argument));
		}
	};
}

BOOST_AUTO_TEST_CASE(async_server_with_asio_spawn)
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 0), true);
	acceptor.listen();
	boost::asio::ip::tcp::socket accepted_socket(io);
	bool ok1 = false;
	impl_test_interface server_impl;
	acceptor.async_accept(
	    accepted_socket, [&accepted_socket, &ok1, &server_impl](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    auto server = std::make_shared<
		        async_test_interface_server<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket>>(
		        server_impl, accepted_socket, accepted_socket);
		    server->serve_one_request([&ok1, server](boost::system::error_code ec)
		                              {
			                              BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
			                              server->serve_one_request([&ok1, server](boost::system::error_code ec)
			                                                        {
				                                                        BOOST_REQUIRE_EQUAL(boost::system::error_code(),
				                                                                            ec);
				                                                        BOOST_REQUIRE(!ok1);
				                                                        ok1 = true;
				                                                    });
			                          });
		});
	boost::asio::ip::tcp::socket socket(io);
	async_test_interface_client<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> client(socket, socket);
	bool ok2 = false;
	socket.async_connect(
	    boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), acceptor.local_endpoint().port()),
	    [&io, &client, &ok2](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    boost::asio::spawn(
		        io, [&client, &ok2](boost::asio::yield_context yield)
		        {
			        std::vector<std::uint64_t> result = client.vectors(std::vector<std::uint64_t>{12, 34, 56}, yield);
			        std::vector<std::uint64_t> const expected{56, 34, 12};
			        BOOST_CHECK(expected == result);

			        BOOST_CHECK_EQUAL("hello123", client.utf8("hello", yield));

			        BOOST_REQUIRE(!ok2);
			        ok2 = true;
			    });
		});
	io.run();
	BOOST_CHECK(ok1);
	BOOST_CHECK(ok2);
}
<commit_msg>use asio::spawn for both client and server side<commit_after>#include "generated.hpp"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/test/unit_test.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/source/memory_source.hpp>

BOOST_AUTO_TEST_CASE(async_client_with_callback)
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 0), true);
	acceptor.listen();
	boost::asio::ip::tcp::socket accepted_socket(io);
	std::array<std::uint8_t, 1024> receive_buffer;
	bool ok1 = false;
	acceptor.async_accept(accepted_socket, [&accepted_socket, &receive_buffer, &ok1](boost::system::error_code ec)
	                      {
		                      BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		                      accepted_socket.async_receive(
		                          boost::asio::buffer(receive_buffer),
		                          [&accepted_socket, &ok1](boost::system::error_code ec, std::size_t received)
		                          {
			                          BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
			                          BOOST_REQUIRE_EQUAL(23, received);
			                          BOOST_REQUIRE(!ok1);
			                          ok1 = true;
			                      });
		                  });
	boost::asio::ip::tcp::socket socket(io);
	async_test_interface_client<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> client(socket, socket);
	bool ok2 = false;
	socket.async_connect(
	    boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), acceptor.local_endpoint().port()),
	    [&client, &ok2](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    client.no_result_no_parameter(std::tuple<>(), [&ok2](boost::system::error_code ec, std::tuple<>)
		                                  {
			                                  BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
			                                  BOOST_REQUIRE(!ok2);
			                                  ok2 = true;
			                              });
		});
	io.run();
	BOOST_CHECK(ok1);
	BOOST_CHECK(ok2);
}

namespace
{
	struct impl_test_interface : async_test_interface
	{
		virtual void type_erased_integer_sizes(
		    std::tuple<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t> argument,
		    std::function<void(boost::system::error_code, std::vector<std::uint16_t>)> on_result) override
		{
			on_result({}, std::vector<std::uint16_t>{std::get<1>(argument)});
		}

		virtual void type_erased_no_result_no_parameter(
		    std::tuple<> argument, std::function<void(boost::system::error_code, std::tuple<>)> on_result) override
		{
			on_result({}, argument);
		}

		virtual void
		type_erased_two_parameters(std::tuple<std::uint64_t, std::uint64_t> argument,
		                           std::function<void(boost::system::error_code, std::uint64_t)> on_result) override
		{
			on_result({}, std::get<0>(argument) * std::get<1>(argument));
		}

		virtual void type_erased_two_results(
		    std::uint64_t argument,
		    std::function<void(boost::system::error_code, std::tuple<std::uint64_t, std::uint64_t>)> on_result) override
		{
			on_result({}, std::make_tuple(argument, argument));
		}

		virtual void type_erased_utf8(std::string argument,
		                              std::function<void(boost::system::error_code, std::string)> on_result) override
		{
			on_result({}, argument + "123");
		}

		virtual void type_erased_vectors(
		    std::vector<std::uint64_t> argument,
		    std::function<void(boost::system::error_code, std::vector<std::uint64_t>)> on_result) override
		{
			std::sort(argument.begin(), argument.end(), std::greater<std::uint64_t>());
			on_result({}, std::move(argument));
		}
	};
}

BOOST_AUTO_TEST_CASE(async_server_with_asio_spawn)
{
	boost::asio::io_service io;
	boost::asio::ip::tcp::acceptor acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 0), true);
	acceptor.listen();
	boost::asio::ip::tcp::socket accepted_socket(io);
	bool ok1 = false;
	impl_test_interface server_impl;
	acceptor.async_accept(
	    accepted_socket, [&io, &accepted_socket, &ok1, &server_impl](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    boost::asio::spawn(
		        io, [&server_impl, &accepted_socket, &ok1](boost::asio::yield_context yield)
		        {
			        async_test_interface_server<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> server(
			            server_impl, accepted_socket, accepted_socket);
			        server.serve_one_request(yield);
			        server.serve_one_request(yield);
			        BOOST_REQUIRE(!ok1);
			        ok1 = true;
			    });
		});
	boost::asio::ip::tcp::socket socket(io);
	async_test_interface_client<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> client(socket, socket);
	bool ok2 = false;
	socket.async_connect(
	    boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), acceptor.local_endpoint().port()),
	    [&io, &client, &ok2](boost::system::error_code ec)
	    {
		    BOOST_REQUIRE_EQUAL(boost::system::error_code(), ec);
		    boost::asio::spawn(
		        io, [&client, &ok2](boost::asio::yield_context yield)
		        {
			        std::vector<std::uint64_t> result = client.vectors(std::vector<std::uint64_t>{12, 34, 56}, yield);
			        std::vector<std::uint64_t> const expected{56, 34, 12};
			        BOOST_CHECK(expected == result);

			        BOOST_CHECK_EQUAL("hello123", client.utf8("hello", yield));

			        BOOST_REQUIRE(!ok2);
			        ok2 = true;
			    });
		});
	io.run();
	BOOST_CHECK(ok1);
	BOOST_CHECK(ok2);
}
<|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/.
 *
 */

#include <TextEffectsHandler.hxx>
#include <rtl/ustrbuf.hxx>
#include <comphelper/string.hxx>
#include <ooxml/resourceids.hxx>
#include "dmapperLoggers.hxx"
#include <stack>

namespace writerfilter {
namespace dmapper
{

using namespace std;
using namespace css::uno;
using namespace css::beans;

struct GrabBagStackElement
{
    OUString maName;
    std::vector<beans::PropertyValue> maPropertyList;
};

/// Tool that is useful for construction of a nested Sequence/PropertyValue hierarchy
class GrabBagStack
{
public:
    GrabBagStack(OUString aName)
    {
        mCurrentElement.maName = aName;
    }

    virtual ~GrabBagStack()
    {}

    std::stack<GrabBagStackElement> mStack;
    GrabBagStackElement mCurrentElement;

    OUString getCurrentName()
    {
        return mCurrentElement.maName;
    }

    PropertyValue getRootProperty()
    {
        while(!mStack.empty())
            pop();

        PropertyValue aProperty;
        aProperty.Name = mCurrentElement.maName;

        Sequence<PropertyValue> aSequence(mCurrentElement.maPropertyList.size());
        PropertyValue* pSequence = aSequence.getArray();
        std::vector<PropertyValue>::iterator i;
        for (i = mCurrentElement.maPropertyList.begin(); i != mCurrentElement.maPropertyList.end(); ++i)
            *pSequence++ = *i;

        aProperty.Value = makeAny(aSequence);

        return aProperty;
    }

    void appendElement(OUString aName, Any aAny)
    {
        PropertyValue aValue;
        aValue.Name = aName;
        aValue.Value = aAny;
        mCurrentElement.maPropertyList.push_back(aValue);
    }

    void push(OUString aKey)
    {
        mStack.push(mCurrentElement);
        mCurrentElement.maName = aKey;
        mCurrentElement.maPropertyList.clear();
    }

    void pop()
    {
        OUString aName = mCurrentElement.maName;
        Sequence<PropertyValue> aSequence(mCurrentElement.maPropertyList.size());
        PropertyValue* pSequence = aSequence.getArray();
        std::vector<PropertyValue>::iterator i;
        for (i = mCurrentElement.maPropertyList.begin(); i != mCurrentElement.maPropertyList.end(); ++i)
            *pSequence++ = *i;

        mCurrentElement = mStack.top();
        mStack.pop();
        appendElement(aName, makeAny(aSequence));
    }
};

OUString TextEffectsHandler::getSchemeColorValTypeString(sal_Int32 nType)
{
    switch (nType)
    {
        case NS_ooxml::LN_ST_SchemeColorVal_bg1: return OUString("bg1");
        case NS_ooxml::LN_ST_SchemeColorVal_tx1: return OUString("tx1");
        case NS_ooxml::LN_ST_SchemeColorVal_bg2: return OUString("bg2");
        case NS_ooxml::LN_ST_SchemeColorVal_tx2: return OUString("tx2");
        case NS_ooxml::LN_ST_SchemeColorVal_accent1: return OUString("accent1");
        case NS_ooxml::LN_ST_SchemeColorVal_accent2: return OUString("accent2");
        case NS_ooxml::LN_ST_SchemeColorVal_accent3: return OUString("accent3");
        case NS_ooxml::LN_ST_SchemeColorVal_accent4: return OUString("accent4");
        case NS_ooxml::LN_ST_SchemeColorVal_accent5: return OUString("accent5");
        case NS_ooxml::LN_ST_SchemeColorVal_accent6: return OUString("accent6");

        default: break;
    }
    return OUString();
}

OUString TextEffectsHandler::getRectAlignmentString(sal_Int32 nType)
{
    switch (nType)
    {
        case NS_ooxml::LN_ST_RectAlignment_none: return OUString("none");
        case NS_ooxml::LN_ST_RectAlignment_tl: return OUString("tl");
        case NS_ooxml::LN_ST_RectAlignment_t: return OUString("t");
        case NS_ooxml::LN_ST_RectAlignment_tr: return OUString("tr");
        case NS_ooxml::LN_ST_RectAlignment_l: return OUString("l");
        case NS_ooxml::LN_ST_RectAlignment_ctr: return OUString("ctr");
        case NS_ooxml::LN_ST_RectAlignment_r: return OUString("r");
        case NS_ooxml::LN_ST_RectAlignment_bl: return OUString("bl");
        case NS_ooxml::LN_ST_RectAlignment_b: return OUString("b");
        case NS_ooxml::LN_ST_RectAlignment_br: return OUString("br");

        default: break;
    }
    return OUString();
}

void TextEffectsHandler::convertElementIdToPropertyId(sal_Int32 aElementId)
{
    switch(aElementId)
    {
        case NS_ooxml::LN_glow_glow:
            maPropertyId = PROP_CHAR_GLOW_TEXT_EFFECT;
            maElementName = "glow";
            break;
        case NS_ooxml::LN_shadow_shadow:
            maPropertyId = PROP_CHAR_SHADOW_TEXT_EFFECT;
            maElementName = "shadow";
            break;
        case NS_ooxml::LN_reflection_reflection:
        case NS_ooxml::LN_textOutline_textOutline:
        case NS_ooxml::LN_textFill_textFill:
        case NS_ooxml::LN_scene3d_scene3d:
        case NS_ooxml::LN_props3d_props3d:
        case NS_ooxml::LN_ligatures_ligatures:
        case NS_ooxml::LN_numForm_numForm:
        case NS_ooxml::LN_numSpacing_numSpacing:
        case NS_ooxml::LN_stylisticSets_stylisticSets:
        case NS_ooxml::LN_cntxtAlts_cntxtAlts:
        default:
            break;
    }
}

TextEffectsHandler::TextEffectsHandler(sal_uInt32 aElementId) :
    LoggedProperties(dmapper_logger, "TextEffectsHandler"),
    mpGrabBagStack(NULL)
{
    convertElementIdToPropertyId(aElementId);
    mpGrabBagStack.reset(new GrabBagStack(maElementName));
}

TextEffectsHandler::~TextEffectsHandler()
{
}

boost::optional<PropertyIds> TextEffectsHandler::getGrabBagPropertyId()
{
    return maPropertyId;
}

void TextEffectsHandler::lcl_attribute(Id aName, Value& aValue)
{

    if (mpGrabBagStack->getCurrentName() != "attributes")
        mpGrabBagStack->push("attributes");

    switch(aName)
    {
        case NS_ooxml::LN_CT_Percentage_val:
            mpGrabBagStack->appendElement("val", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_PositiveFixedPercentage_val:
            mpGrabBagStack->appendElement("val", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_PositivePercentage_val:
            mpGrabBagStack->appendElement("val", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_SchemeColor_val:
            mpGrabBagStack->appendElement("val", makeAny(getSchemeColorValTypeString(sal_Int32(aValue.getInt()))));
            break;
        case NS_ooxml::LN_CT_SRgbColor_val:
            {
                OUStringBuffer aBuf = OUString::number(aValue.getInt(), 16);
                OUStringBuffer aStr;
                comphelper::string::padToLength(aStr, 6 - aBuf.getLength(), '0');
                aStr.append(aBuf.getStr());
                mpGrabBagStack->appendElement("val", makeAny(aStr.makeStringAndClear().toAsciiUpperCase()));
            }
            break;
        case NS_ooxml::LN_CT_Glow_rad:
            mpGrabBagStack->appendElement("rad", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_blurRad:
            mpGrabBagStack->appendElement("blurRad", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_dist:
            mpGrabBagStack->appendElement("dist", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_dir:
            mpGrabBagStack->appendElement("dir", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_sx:
            mpGrabBagStack->appendElement("sx", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_sy:
            mpGrabBagStack->appendElement("sy", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_kx:
            mpGrabBagStack->appendElement("kx", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_ky:
            mpGrabBagStack->appendElement("ky", makeAny(sal_Int32(aValue.getInt())));
            break;
        case NS_ooxml::LN_CT_Shadow_algn:
            {
                uno::Any aAny = makeAny(getRectAlignmentString(sal_Int32(aValue.getInt())));
                mpGrabBagStack->appendElement("algn", aAny);
            }
            break;
        default:
            break;
    }
}

void TextEffectsHandler::lcl_sprm(Sprm& rSprm)
{
    if (mpGrabBagStack->getCurrentName() == "attributes")
        mpGrabBagStack->pop();

    sal_uInt32 nSprmId = rSprm.getId();

    switch(nSprmId)
    {
        case NS_ooxml::LN_EG_ColorChoice_srgbClr:
            mpGrabBagStack->push("srgbClr");
            break;
        case NS_ooxml::LN_EG_ColorChoice_schemeClr:
            mpGrabBagStack->push("schemeClr");
            break;
        case NS_ooxml::LN_EG_ColorTransform_tint:
            mpGrabBagStack->push("tint");
            break;
        case NS_ooxml::LN_EG_ColorTransform_shade:
            mpGrabBagStack->push("shade");
            break;
        case NS_ooxml::LN_EG_ColorTransform_alpha:
            mpGrabBagStack->push("alpha");
            break;
        case NS_ooxml::LN_EG_ColorTransform_hueMod:
            mpGrabBagStack->push("hueMod");
            break;
        case NS_ooxml::LN_EG_ColorTransform_sat:
            mpGrabBagStack->push("sat");
            break;
        case NS_ooxml::LN_EG_ColorTransform_satOff:
            mpGrabBagStack->push("satOff");
            break;
        case NS_ooxml::LN_EG_ColorTransform_satMod:
            mpGrabBagStack->push("satMod");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lum:
            mpGrabBagStack->push("lum");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lumOff:
            mpGrabBagStack->push("lumOff");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lumMod:
            mpGrabBagStack->push("lumMod");
            break;

        default:
            break;
    }

    writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
    if( !pProperties.get())
        return;

    pProperties.get()->resolve( *this );

    if (mpGrabBagStack->getCurrentName() == "attributes")
        mpGrabBagStack->pop();

    switch(nSprmId)
    {
        case NS_ooxml::LN_EG_ColorChoice_srgbClr:
        case NS_ooxml::LN_EG_ColorChoice_schemeClr:
        case NS_ooxml::LN_EG_ColorTransform_tint:
        case NS_ooxml::LN_EG_ColorTransform_shade:
        case NS_ooxml::LN_EG_ColorTransform_alpha:
        case NS_ooxml::LN_EG_ColorTransform_hueMod:
        case NS_ooxml::LN_EG_ColorTransform_sat:
        case NS_ooxml::LN_EG_ColorTransform_satOff:
        case NS_ooxml::LN_EG_ColorTransform_satMod:
        case NS_ooxml::LN_EG_ColorTransform_lum:
        case NS_ooxml::LN_EG_ColorTransform_lumOff:
        case NS_ooxml::LN_EG_ColorTransform_lumMod:
            mpGrabBagStack->pop();
            break;
    }
}

beans::PropertyValue TextEffectsHandler::getInteropGrabBag()
{
    beans::PropertyValue aReturn = mpGrabBagStack->getRootProperty();
    mpGrabBagStack.reset();
    return aReturn;
}

}//namespace dmapper
} //namespace writerfilter

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>writerfilter: TextEffectsHandler - simplyfy switch<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/.
 *
 */

#include <TextEffectsHandler.hxx>
#include <rtl/ustrbuf.hxx>
#include <comphelper/string.hxx>
#include <ooxml/resourceids.hxx>
#include "dmapperLoggers.hxx"
#include <stack>

namespace writerfilter {
namespace dmapper
{

using namespace std;
using namespace css::uno;
using namespace css::beans;

struct GrabBagStackElement
{
    OUString maName;
    std::vector<beans::PropertyValue> maPropertyList;
};

/// Tool that is useful for construction of a nested Sequence/PropertyValue hierarchy
class GrabBagStack
{
public:
    GrabBagStack(OUString aName)
    {
        mCurrentElement.maName = aName;
    }

    virtual ~GrabBagStack()
    {}

    std::stack<GrabBagStackElement> mStack;
    GrabBagStackElement mCurrentElement;

    OUString getCurrentName()
    {
        return mCurrentElement.maName;
    }

    PropertyValue getRootProperty()
    {
        while(!mStack.empty())
            pop();

        PropertyValue aProperty;
        aProperty.Name = mCurrentElement.maName;

        Sequence<PropertyValue> aSequence(mCurrentElement.maPropertyList.size());
        PropertyValue* pSequence = aSequence.getArray();
        std::vector<PropertyValue>::iterator i;
        for (i = mCurrentElement.maPropertyList.begin(); i != mCurrentElement.maPropertyList.end(); ++i)
            *pSequence++ = *i;

        aProperty.Value = makeAny(aSequence);

        return aProperty;
    }

    void appendElement(OUString aName, Any aAny)
    {
        PropertyValue aValue;
        aValue.Name = aName;
        aValue.Value = aAny;
        mCurrentElement.maPropertyList.push_back(aValue);
    }

    void push(OUString aKey)
    {
        mStack.push(mCurrentElement);
        mCurrentElement.maName = aKey;
        mCurrentElement.maPropertyList.clear();
    }

    void pop()
    {
        OUString aName = mCurrentElement.maName;
        Sequence<PropertyValue> aSequence(mCurrentElement.maPropertyList.size());
        PropertyValue* pSequence = aSequence.getArray();
        std::vector<PropertyValue>::iterator i;
        for (i = mCurrentElement.maPropertyList.begin(); i != mCurrentElement.maPropertyList.end(); ++i)
            *pSequence++ = *i;

        mCurrentElement = mStack.top();
        mStack.pop();
        appendElement(aName, makeAny(aSequence));
    }

    void addInt32(OUString aElementName, sal_Int32 aIntValue)
    {
        appendElement(aElementName, makeAny(aIntValue));
    }

    void addString(OUString aElementName, OUString aStringValue)
    {
        appendElement(aElementName, makeAny(aStringValue));
    }
};

OUString TextEffectsHandler::getSchemeColorValTypeString(sal_Int32 nType)
{
    switch (nType)
    {
        case NS_ooxml::LN_ST_SchemeColorVal_bg1: return OUString("bg1");
        case NS_ooxml::LN_ST_SchemeColorVal_tx1: return OUString("tx1");
        case NS_ooxml::LN_ST_SchemeColorVal_bg2: return OUString("bg2");
        case NS_ooxml::LN_ST_SchemeColorVal_tx2: return OUString("tx2");
        case NS_ooxml::LN_ST_SchemeColorVal_accent1: return OUString("accent1");
        case NS_ooxml::LN_ST_SchemeColorVal_accent2: return OUString("accent2");
        case NS_ooxml::LN_ST_SchemeColorVal_accent3: return OUString("accent3");
        case NS_ooxml::LN_ST_SchemeColorVal_accent4: return OUString("accent4");
        case NS_ooxml::LN_ST_SchemeColorVal_accent5: return OUString("accent5");
        case NS_ooxml::LN_ST_SchemeColorVal_accent6: return OUString("accent6");

        default: break;
    }
    return OUString();
}

OUString TextEffectsHandler::getRectAlignmentString(sal_Int32 nType)
{
    switch (nType)
    {
        case NS_ooxml::LN_ST_RectAlignment_none: return OUString("none");
        case NS_ooxml::LN_ST_RectAlignment_tl: return OUString("tl");
        case NS_ooxml::LN_ST_RectAlignment_t: return OUString("t");
        case NS_ooxml::LN_ST_RectAlignment_tr: return OUString("tr");
        case NS_ooxml::LN_ST_RectAlignment_l: return OUString("l");
        case NS_ooxml::LN_ST_RectAlignment_ctr: return OUString("ctr");
        case NS_ooxml::LN_ST_RectAlignment_r: return OUString("r");
        case NS_ooxml::LN_ST_RectAlignment_bl: return OUString("bl");
        case NS_ooxml::LN_ST_RectAlignment_b: return OUString("b");
        case NS_ooxml::LN_ST_RectAlignment_br: return OUString("br");

        default: break;
    }
    return OUString();
}

void TextEffectsHandler::convertElementIdToPropertyId(sal_Int32 aElementId)
{
    switch(aElementId)
    {
        case NS_ooxml::LN_glow_glow:
            maPropertyId = PROP_CHAR_GLOW_TEXT_EFFECT;
            maElementName = "glow";
            break;
        case NS_ooxml::LN_shadow_shadow:
            maPropertyId = PROP_CHAR_SHADOW_TEXT_EFFECT;
            maElementName = "shadow";
            break;
        case NS_ooxml::LN_reflection_reflection:
        case NS_ooxml::LN_textOutline_textOutline:
        case NS_ooxml::LN_textFill_textFill:
        case NS_ooxml::LN_scene3d_scene3d:
        case NS_ooxml::LN_props3d_props3d:
        case NS_ooxml::LN_ligatures_ligatures:
        case NS_ooxml::LN_numForm_numForm:
        case NS_ooxml::LN_numSpacing_numSpacing:
        case NS_ooxml::LN_stylisticSets_stylisticSets:
        case NS_ooxml::LN_cntxtAlts_cntxtAlts:
        default:
            break;
    }
}

TextEffectsHandler::TextEffectsHandler(sal_uInt32 aElementId) :
    LoggedProperties(dmapper_logger, "TextEffectsHandler"),
    mpGrabBagStack(NULL)
{
    convertElementIdToPropertyId(aElementId);
    mpGrabBagStack.reset(new GrabBagStack(maElementName));
}

TextEffectsHandler::~TextEffectsHandler()
{
}

boost::optional<PropertyIds> TextEffectsHandler::getGrabBagPropertyId()
{
    return maPropertyId;
}

void TextEffectsHandler::lcl_attribute(Id aName, Value& aValue)
{

    if (mpGrabBagStack->getCurrentName() != "attributes")
        mpGrabBagStack->push("attributes");

    switch(aName)
    {
        case NS_ooxml::LN_CT_Percentage_val:
        case NS_ooxml::LN_CT_PositiveFixedPercentage_val:
        case NS_ooxml::LN_CT_PositivePercentage_val:
            mpGrabBagStack->addInt32("val", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Glow_rad:
            mpGrabBagStack->addInt32("rad", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_SchemeColor_val:
            {
                OUString aString = getSchemeColorValTypeString(sal_Int32(aValue.getInt()));
                mpGrabBagStack->addString("val", aString);
            }
            break;
        case NS_ooxml::LN_CT_SRgbColor_val:
            {
                OUStringBuffer aBuffer = OUString::number(aValue.getInt(), 16);
                OUStringBuffer aString;
                comphelper::string::padToLength(aString, 6 - aBuffer.getLength(), '0');
                aString.append(aBuffer.getStr());
                mpGrabBagStack->addString("val", aString.makeStringAndClear().toAsciiUpperCase());
            }
            break;
        case NS_ooxml::LN_CT_Shadow_blurRad:
            mpGrabBagStack->addInt32("blurRad", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_dist:
            mpGrabBagStack->addInt32("dist", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_dir:
            mpGrabBagStack->addInt32("dir", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_sx:
            mpGrabBagStack->addInt32("sx", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_sy:
            mpGrabBagStack->addInt32("sy", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_kx:
            mpGrabBagStack->addInt32("kx", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_ky:
            mpGrabBagStack->addInt32("ky", sal_Int32(aValue.getInt()));
            break;
        case NS_ooxml::LN_CT_Shadow_algn:
            {
                uno::Any aAny = makeAny(getRectAlignmentString(sal_Int32(aValue.getInt())));
                mpGrabBagStack->appendElement("algn", aAny);
            }
            break;
        default:
            break;
    }
}

void TextEffectsHandler::lcl_sprm(Sprm& rSprm)
{
    if (mpGrabBagStack->getCurrentName() == "attributes")
        mpGrabBagStack->pop();

    sal_uInt32 nSprmId = rSprm.getId();

    switch(nSprmId)
    {
        case NS_ooxml::LN_EG_ColorChoice_srgbClr:
            mpGrabBagStack->push("srgbClr");
            break;
        case NS_ooxml::LN_EG_ColorChoice_schemeClr:
            mpGrabBagStack->push("schemeClr");
            break;
        case NS_ooxml::LN_EG_ColorTransform_tint:
            mpGrabBagStack->push("tint");
            break;
        case NS_ooxml::LN_EG_ColorTransform_shade:
            mpGrabBagStack->push("shade");
            break;
        case NS_ooxml::LN_EG_ColorTransform_alpha:
            mpGrabBagStack->push("alpha");
            break;
        case NS_ooxml::LN_EG_ColorTransform_hueMod:
            mpGrabBagStack->push("hueMod");
            break;
        case NS_ooxml::LN_EG_ColorTransform_sat:
            mpGrabBagStack->push("sat");
            break;
        case NS_ooxml::LN_EG_ColorTransform_satOff:
            mpGrabBagStack->push("satOff");
            break;
        case NS_ooxml::LN_EG_ColorTransform_satMod:
            mpGrabBagStack->push("satMod");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lum:
            mpGrabBagStack->push("lum");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lumOff:
            mpGrabBagStack->push("lumOff");
            break;
        case NS_ooxml::LN_EG_ColorTransform_lumMod:
            mpGrabBagStack->push("lumMod");
            break;

        default:
            break;
    }

    writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
    if( !pProperties.get())
        return;

    pProperties.get()->resolve( *this );

    if (mpGrabBagStack->getCurrentName() == "attributes")
        mpGrabBagStack->pop();

    switch(nSprmId)
    {
        case NS_ooxml::LN_EG_ColorChoice_srgbClr:
        case NS_ooxml::LN_EG_ColorChoice_schemeClr:
        case NS_ooxml::LN_EG_ColorTransform_tint:
        case NS_ooxml::LN_EG_ColorTransform_shade:
        case NS_ooxml::LN_EG_ColorTransform_alpha:
        case NS_ooxml::LN_EG_ColorTransform_hueMod:
        case NS_ooxml::LN_EG_ColorTransform_sat:
        case NS_ooxml::LN_EG_ColorTransform_satOff:
        case NS_ooxml::LN_EG_ColorTransform_satMod:
        case NS_ooxml::LN_EG_ColorTransform_lum:
        case NS_ooxml::LN_EG_ColorTransform_lumOff:
        case NS_ooxml::LN_EG_ColorTransform_lumMod:
            mpGrabBagStack->pop();
            break;
    }
}

beans::PropertyValue TextEffectsHandler::getInteropGrabBag()
{
    beans::PropertyValue aReturn = mpGrabBagStack->getRootProperty();
    mpGrabBagStack.reset();
    return aReturn;
}

}//namespace dmapper
} //namespace writerfilter

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


<commit_before>// Copyright (c) 2020 The Novo developers
// Authored by: Malcolm MacLeod (mmacleod@gmx.com)
// Distributed under the NOVO software license, see the accompanying
// file COPYING

//Workaround braindamaged 'hack' in libtool.m4 that defines DLL_EXPORT when building a dll via libtool (this in turn imports unwanted symbols from e.g. pthread that breaks static pthread linkage)
#ifdef DLL_EXPORT
#undef DLL_EXPORT
#endif

#include "appname.h"
#include "net.h"
#include "net_processing.h"
#include "validation/validation.h"
#include "validation/witnessvalidation.h"
#include "ui_interface.h"
#include "utilstrencodings.h"

#include "witnessutil.h"

#include <wallet/wallet.h>
#include <wallet/account.h>
#include <wallet/witness_operations.h>

// Unity specific includes
#include "../unity_impl.h"
#include "i_witness_controller.hpp"
#include "witness_estimate_info_record.hpp"
#include "witness_funding_result_record.hpp"

#include <consensus/validation.h>

std::unordered_map<std::string, std::string> IWitnessController::getNetworkLimits()
{
    std::unordered_map<std::string, std::string> ret;
    if (pactiveWallet)
    {
        ret.insert(std::pair("expected_blocks_per_day", i64tostr(DailyBlocksTarget())));
        ret.insert(std::pair("witness_cooldown_period", i64tostr(gMinimumParticipationAge)));
        ret.insert(std::pair("minimum_witness_amount", i64tostr(gMinimumWitnessAmount)));
        ret.insert(std::pair("minimum_witness_weight", i64tostr(gMinimumWitnessWeight)));
        ret.insert(std::pair("minimum_lock_period_blocks", i64tostr(gMinimumWitnessLockDays*DailyBlocksTarget())));
        ret.insert(std::pair("minimum_lock_period_days", i64tostr(gMinimumWitnessLockDays)));
        ret.insert(std::pair("maximum_lock_period_blocks", i64tostr(gMaximumWitnessLockDays*DailyBlocksTarget())));
        ret.insert(std::pair("maximum_lock_period_days", i64tostr(gMaximumWitnessLockDays)));
    }
    return ret;
}

static int64_t GetNetworkWeight()
{
    int64_t nNetworkWeight = 20000;
    if (chainActive.Tip())
    {
        static uint64_t lastUpdate = 0;
        // Only check this once a minute, no need to be constantly updating.
        if (GetTimeMillis() - lastUpdate > 60000)
        {
            LOCK(cs_main);

            lastUpdate = GetTimeMillis();
            if (IsPow2WitnessingActive(chainActive.TipPrev()->nHeight))
            {
                CGetWitnessInfo witnessInfo;
                CBlock block;
                if (!ReadBlockFromDisk(block, chainActive.Tip(), Params()))
                {
                    return nNetworkWeight;
                }
                if (!GetWitnessInfo(chainActive, Params(), nullptr, chainActive.Tip()->pprev, block, witnessInfo, chainActive.Tip()->nHeight))
                {
                    return nNetworkWeight;
                }
                nNetworkWeight = witnessInfo.nTotalWeightEligibleRaw;
            }
        }
    }
    return nNetworkWeight;
}

WitnessEstimateInfoRecord IWitnessController::getEstimatedWeight(int64_t amountToLock, int64_t lockPeriodInDays)
{
    int64_t lockPeriodInBlocks = lockPeriodInDays * DailyBlocksTarget();

    uint64_t networkWeight = GetNetworkWeight();
    const auto optimalAmounts = optimalWitnessDistribution(amountToLock, lockPeriodInBlocks, networkWeight);
    int64_t ourTotalWeight = combinedWeight(optimalAmounts, lockPeriodInDays);

    double witnessProbability = witnessFraction(optimalAmounts, lockPeriodInDays, networkWeight);
    double estimatedBlocksPerDay = DailyBlocksTarget() * witnessProbability;

    CAmount witnessSubsidy = GetBlockSubsidyWitness(chainActive.Tip()?chainActive.Tip()->nHeight:1);

    CAmount estimatedDaileyEarnings = estimatedBlocksPerDay * witnessSubsidy;
    CAmount estimatedLifetimeEarnings = estimatedBlocksPerDay * lockPeriodInDays * witnessSubsidy;

    return WitnessEstimateInfoRecord(networkWeight, ourTotalWeight, optimalAmounts.size(), witnessProbability, estimatedBlocksPerDay, estimatedDaileyEarnings, estimatedLifetimeEarnings);
}

WitnessFundingResultRecord IWitnessController::fundWitnessAccount(const std::string& fundingAccountUUID, const std::string& witnessAccountUUID, int64_t fundingAmount, int64_t requestedLockPeriodInBlocks)
{
    if (!pactiveWallet)
        return WitnessFundingResultRecord("no active wallet present", "", 0);;

    DS_LOCK2(cs_main, pactiveWallet->cs_wallet);

    auto findIter = pactiveWallet->mapAccounts.find(getUUIDFromString(fundingAccountUUID));
    if (findIter != pactiveWallet->mapAccounts.end())
        return WitnessFundingResultRecord("invalid funding account", "", 0);;
    CAccount* fundingAccount = findIter->second;

    findIter = pactiveWallet->mapAccounts.find(getUUIDFromString(witnessAccountUUID));
    if (findIter != pactiveWallet->mapAccounts.end())
        return WitnessFundingResultRecord("invalid witness account", "", 0);;
    CAccount* witnessAccount = findIter->second;

    if (!witnessAccount->IsPoW2Witness())
        return WitnessFundingResultRecord("not a witness account", "", 0);;

    try
    {
        std::string txid;
        CAmount fee;
        fundwitnessaccount(pactiveWallet, fundingAccount, witnessAccount, fundingAmount, requestedLockPeriodInBlocks, true, &txid, &fee);
        return WitnessFundingResultRecord("success", txid, fee);
    }
    catch (witness_error& e)
    {
        return WitnessFundingResultRecord(e.what(), "", 0);
    }
    catch (std::runtime_error& e)
    {
        return WitnessFundingResultRecord(e.what(), "", 0);
    }
}

<commit_msg>QA: Fix bug in fundWitnessAccount<commit_after>// Copyright (c) 2020 The Novo developers
// Authored by: Malcolm MacLeod (mmacleod@gmx.com)
// Distributed under the NOVO software license, see the accompanying
// file COPYING

//Workaround braindamaged 'hack' in libtool.m4 that defines DLL_EXPORT when building a dll via libtool (this in turn imports unwanted symbols from e.g. pthread that breaks static pthread linkage)
#ifdef DLL_EXPORT
#undef DLL_EXPORT
#endif

#include "appname.h"
#include "net.h"
#include "net_processing.h"
#include "validation/validation.h"
#include "validation/witnessvalidation.h"
#include "ui_interface.h"
#include "utilstrencodings.h"

#include "witnessutil.h"

#include <wallet/wallet.h>
#include <wallet/account.h>
#include <wallet/witness_operations.h>

// Unity specific includes
#include "../unity_impl.h"
#include "i_witness_controller.hpp"
#include "witness_estimate_info_record.hpp"
#include "witness_funding_result_record.hpp"

#include <consensus/validation.h>

std::unordered_map<std::string, std::string> IWitnessController::getNetworkLimits()
{
    std::unordered_map<std::string, std::string> ret;
    if (pactiveWallet)
    {
        ret.insert(std::pair("expected_blocks_per_day", i64tostr(DailyBlocksTarget())));
        ret.insert(std::pair("witness_cooldown_period", i64tostr(gMinimumParticipationAge)));
        ret.insert(std::pair("minimum_witness_amount", i64tostr(gMinimumWitnessAmount)));
        ret.insert(std::pair("minimum_witness_weight", i64tostr(gMinimumWitnessWeight)));
        ret.insert(std::pair("minimum_lock_period_blocks", i64tostr(gMinimumWitnessLockDays*DailyBlocksTarget())));
        ret.insert(std::pair("minimum_lock_period_days", i64tostr(gMinimumWitnessLockDays)));
        ret.insert(std::pair("maximum_lock_period_blocks", i64tostr(gMaximumWitnessLockDays*DailyBlocksTarget())));
        ret.insert(std::pair("maximum_lock_period_days", i64tostr(gMaximumWitnessLockDays)));
    }
    return ret;
}

static int64_t GetNetworkWeight()
{
    int64_t nNetworkWeight = 20000;
    if (chainActive.Tip())
    {
        static uint64_t lastUpdate = 0;
        // Only check this once a minute, no need to be constantly updating.
        if (GetTimeMillis() - lastUpdate > 60000)
        {
            LOCK(cs_main);

            lastUpdate = GetTimeMillis();
            if (IsPow2WitnessingActive(chainActive.TipPrev()->nHeight))
            {
                CGetWitnessInfo witnessInfo;
                CBlock block;
                if (!ReadBlockFromDisk(block, chainActive.Tip(), Params()))
                {
                    return nNetworkWeight;
                }
                if (!GetWitnessInfo(chainActive, Params(), nullptr, chainActive.Tip()->pprev, block, witnessInfo, chainActive.Tip()->nHeight))
                {
                    return nNetworkWeight;
                }
                nNetworkWeight = witnessInfo.nTotalWeightEligibleRaw;
            }
        }
    }
    return nNetworkWeight;
}

WitnessEstimateInfoRecord IWitnessController::getEstimatedWeight(int64_t amountToLock, int64_t lockPeriodInDays)
{
    int64_t lockPeriodInBlocks = lockPeriodInDays * DailyBlocksTarget();

    uint64_t networkWeight = GetNetworkWeight();
    const auto optimalAmounts = optimalWitnessDistribution(amountToLock, lockPeriodInBlocks, networkWeight);
    int64_t ourTotalWeight = combinedWeight(optimalAmounts, lockPeriodInDays);

    double witnessProbability = witnessFraction(optimalAmounts, lockPeriodInDays, networkWeight);
    double estimatedBlocksPerDay = DailyBlocksTarget() * witnessProbability;

    CAmount witnessSubsidy = GetBlockSubsidyWitness(chainActive.Tip()?chainActive.Tip()->nHeight:1);

    CAmount estimatedDaileyEarnings = estimatedBlocksPerDay * witnessSubsidy;
    CAmount estimatedLifetimeEarnings = estimatedBlocksPerDay * lockPeriodInDays * witnessSubsidy;

    return WitnessEstimateInfoRecord(networkWeight, ourTotalWeight, optimalAmounts.size(), witnessProbability, estimatedBlocksPerDay, estimatedDaileyEarnings, estimatedLifetimeEarnings);
}

WitnessFundingResultRecord IWitnessController::fundWitnessAccount(const std::string& fundingAccountUUID, const std::string& witnessAccountUUID, int64_t fundingAmount, int64_t requestedLockPeriodInBlocks)
{
    if (!pactiveWallet)
        return WitnessFundingResultRecord("no active wallet present", "", 0);;

    DS_LOCK2(cs_main, pactiveWallet->cs_wallet);

    auto findIter = pactiveWallet->mapAccounts.find(getUUIDFromString(fundingAccountUUID));
    if (findIter == pactiveWallet->mapAccounts.end())
        return WitnessFundingResultRecord("invalid funding account", "", 0);;
    CAccount* fundingAccount = findIter->second;

    findIter = pactiveWallet->mapAccounts.find(getUUIDFromString(witnessAccountUUID));
    if (findIter == pactiveWallet->mapAccounts.end())
        return WitnessFundingResultRecord("invalid witness account", "", 0);;
    CAccount* witnessAccount = findIter->second;

    if (!witnessAccount->IsPoW2Witness())
        return WitnessFundingResultRecord("not a witness account", "", 0);;

    try
    {
        std::string txid;
        CAmount fee;
        fundwitnessaccount(pactiveWallet, fundingAccount, witnessAccount, fundingAmount, requestedLockPeriodInBlocks, true, &txid, &fee);
        return WitnessFundingResultRecord("success", txid, fee);
    }
    catch (witness_error& e)
    {
        return WitnessFundingResultRecord(e.what(), "", 0);
    }
    catch (std::runtime_error& e)
    {
        return WitnessFundingResultRecord(e.what(), "", 0);
    }
}

<|endoftext|>


<commit_before>
/**
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <set>
#include <string>

#include <process/defer.hpp>
#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/id.hpp>
#include <process/logging.hpp>
#include <process/pid.hpp>
#include <process/process.hpp>

#include <stout/duration.hpp>
#include <stout/foreach.hpp>
#include <stout/lambda.hpp>

#include "common/protobuf_utils.hpp"

#include "master/constants.hpp"
#include "master/detector.hpp"
#include "master/master.hpp"

#include "messages/messages.hpp"

#include "zookeeper/detector.hpp"
#include "zookeeper/group.hpp"
#include "zookeeper/url.hpp"

using namespace process;
using namespace zookeeper;

using std::set;
using std::string;

namespace mesos {
namespace internal {

const Duration MASTER_DETECTOR_ZK_SESSION_TIMEOUT = Seconds(10);

class StandaloneMasterDetectorProcess
  : public Process<StandaloneMasterDetectorProcess>
{
public:
  StandaloneMasterDetectorProcess()
    : ProcessBase(ID::generate("standalone-master-detector")) {}
  explicit StandaloneMasterDetectorProcess(const MasterInfo& _leader)
    : ProcessBase(ID::generate("standalone-master-detector")),
      leader(_leader) {}
  ~StandaloneMasterDetectorProcess();

  void appoint(const Option<MasterInfo>& leader);
  Future<Option<MasterInfo> > detect(
      const Option<MasterInfo>& previous = None());

private:
  Option<MasterInfo> leader; // The appointed master.
  set<Promise<Option<MasterInfo> >*> promises;
};

class ZooKeeperMasterDetectorProcess
  : public Process<ZooKeeperMasterDetectorProcess>
{
public:
  explicit ZooKeeperMasterDetectorProcess(const URL& url);
  explicit ZooKeeperMasterDetectorProcess(Owned<Group> group);
  ~ZooKeeperMasterDetectorProcess();

  virtual void initialize();
  Future<Option<MasterInfo> > detect(const Option<MasterInfo>& previous);

private:
  // Invoked when the group leadership has changed.
  void detected(const Future<Option<Group::Membership> >& leader);

  // Invoked when we have fetched the data associated with the leader.
  void fetched(const Group::Membership& membership, const Future<string>& data);

  Owned<Group> group;
  LeaderDetector detector;

  // The leading Master.
  Option<MasterInfo> leader;
  set<Promise<Option<MasterInfo> >*> promises;

  // Potential non-retryable error.
  Option<Error> error;
};

Try<MasterDetector*> MasterDetector::create(const string& master)
{
  if (master == "") {
    return new StandaloneMasterDetector();
  } else if (master.find("zk://") == 0) {
    Try<URL> url = URL::parse(master);
    if (url.isError()) {
      return Error(url.error());
    }
    if (url.get().path == "/") {
      return Error(
          "Expecting a (chroot) path for ZooKeeper ('/' is not supported)");
    }
    return new ZooKeeperMasterDetector(url.get());
  } else if (master.find("file://") == 0) {
    const string& path = master.substr(7);
    const Try<string> read = os::read(path);
    if (read.isError()) {
      return Error("Failed to read from file at '" + path + "'");
    }

    return create(strings::trim(read.get()));
  }

  // Okay, try and parse what we got as a PID.
  UPID pid = master.find("master@") == 0
    ? UPID(master)
    : UPID("master@" + master);

  if (!pid) {
    return Error("Failed to parse '" + master + "'");
  }

  return new StandaloneMasterDetector(protobuf::createMasterInfo(pid));
}

MasterDetector::~MasterDetector() {}

StandaloneMasterDetectorProcess::~StandaloneMasterDetectorProcess()
{
  foreach (Promise<Option<MasterInfo> >* promise, promises) {
    promise->discard();
    delete promise;
  }
  promises.clear();
}

void StandaloneMasterDetectorProcess::appoint(const Option<MasterInfo>& _leader)
{
  leader = _leader;

  foreach (Promise<Option<MasterInfo> >* promise, promises) {
    promise->set(leader);
    delete promise;
  }
  promises.clear();
}

Future<Option<MasterInfo> > StandaloneMasterDetectorProcess::detect(
    const Option<MasterInfo>& previous)
{
  if (leader != previous) {
    return leader;
  }

  Promise<Option<MasterInfo> >* promise = new Promise<Option<MasterInfo> >();
  promises.insert(promise);
  return promise->future();
}

StandaloneMasterDetector::StandaloneMasterDetector()
{
  process = new StandaloneMasterDetectorProcess();
  spawn(process);
}

StandaloneMasterDetector::StandaloneMasterDetector(const MasterInfo& leader)
{
  process = new StandaloneMasterDetectorProcess(leader);
  spawn(process);
}

StandaloneMasterDetector::StandaloneMasterDetector(const UPID& leader)
{
  process =
    new StandaloneMasterDetectorProcess(protobuf::createMasterInfo(leader));

  spawn(process);
}

StandaloneMasterDetector::~StandaloneMasterDetector()
{
  terminate(process);
  process::wait(process);
  delete process;
}

void StandaloneMasterDetector::appoint(const Option<MasterInfo>& leader)
{
  dispatch(process, &StandaloneMasterDetectorProcess::appoint, leader);
}

void StandaloneMasterDetector::appoint(const UPID& leader)
{
  dispatch(process,
           &StandaloneMasterDetectorProcess::appoint,
           protobuf::createMasterInfo(leader));
}

Future<Option<MasterInfo> > StandaloneMasterDetector::detect(
    const Option<MasterInfo>& previous)
{
  return dispatch(process, &StandaloneMasterDetectorProcess::detect, previous);
}

// TODO(benh): Get ZooKeeper timeout from configuration.
// TODO(xujyan): Use peer constructor after switching to C++ 11.
ZooKeeperMasterDetectorProcess::ZooKeeperMasterDetectorProcess(
    const URL& url)
  : ProcessBase(ID::generate("zookeeper-master-detector")),
    group(new Group(url.servers,
                    MASTER_DETECTOR_ZK_SESSION_TIMEOUT,
                    url.path,
                    url.authentication)),
    detector(group.get()),
    leader(None()) {}

ZooKeeperMasterDetectorProcess::ZooKeeperMasterDetectorProcess(
    Owned<Group> _group)
  : ProcessBase(ID::generate("zookeeper-master-detector")),
    group(_group),
    detector(group.get()),
    leader(None()) {}

ZooKeeperMasterDetectorProcess::~ZooKeeperMasterDetectorProcess()
{
  foreach (Promise<Option<MasterInfo> >* promise, promises) {
    promise->discard();
    delete promise;
  }
  promises.clear();
}

void ZooKeeperMasterDetectorProcess::initialize()
{
  detector.detect()
    .onAny(defer(self(), &Self::detected, lambda::_1));
}

Future<Option<MasterInfo> > ZooKeeperMasterDetectorProcess::detect(
    const Option<MasterInfo>& previous)
{
  // Return immediately if the detector is no longer operational due
  // to a non-retryable error.
  if (error.isSome()) {
    return Failure(error.get().message);
  }

  if (leader != previous) {
    return leader;
  }

  Promise<Option<MasterInfo> >* promise = new Promise<Option<MasterInfo> >();
  promises.insert(promise);
  return promise->future();
}

void ZooKeeperMasterDetectorProcess::detected(
    const Future<Option<Group::Membership> >& _leader)
{
  CHECK(!_leader.isDiscarded());

  if (_leader.isFailed()) {
    LOG(ERROR) << "Failed to detect the leader: " << _leader.failure();

    // Setting this error stops the detection loop and the detector
    // transitions to an erroneous state. Further calls to detect()
    // will directly fail as a result.
    error = Error(_leader.failure());
    leader = None();
    foreach (Promise<Option<MasterInfo> >* promise, promises) {
      promise->fail(_leader.failure());
      delete promise;
    }
    promises.clear();
    return;
  }

  if (_leader.get().isNone()) {
    leader = None();

    foreach (Promise<Option<MasterInfo> >* promise, promises) {
      promise->set(leader);
      delete promise;
    }
    promises.clear();
  } else {
    // Fetch the data associated with the leader.
    group->data(_leader.get().get())
      .onAny(defer(self(), &Self::fetched, _leader.get().get(), lambda::_1));
  }

  // Keep trying to detect leadership changes.
  detector.detect(_leader.get())
    .onAny(defer(self(), &Self::detected, lambda::_1));
}

void ZooKeeperMasterDetectorProcess::fetched(
    const Group::Membership& membership,
    const Future<string>& data)
{
  CHECK(!data.isDiscarded());

  if (data.isFailed()) {
    leader = None();
    foreach (Promise<Option<MasterInfo> >* promise, promises) {
      promise->fail(data.failure());
      delete promise;
    }
    promises.clear();
    return;
  }

  // Parse the data based on the membership label and cache the
  // leader for subsequent requests.
  Option<string> label = membership.label();
  if (label.isNone()) {
    // If we are here it means some masters are still creating znodes
    // with the old format.
    UPID pid = UPID(data.get());
    LOG(WARNING) << "Leading master " << pid << " has data in old format";
    leader = protobuf::createMasterInfo(pid);
  } else if (label.isSome() && label.get() == master::MASTER_INFO_LABEL) {
    MasterInfo info;
    if (!info.ParseFromString(data.get())) {
      leader = None();
      foreach (Promise<Option<MasterInfo> >* promise, promises) {
        promise->fail("Failed to parse data into MasterInfo");
        delete promise;
      }
      promises.clear();
      return;
    }
    leader = info;
  } else {
    leader = None();
    foreach (Promise<Option<MasterInfo> >* promise, promises) {
      promise->fail("Failed to parse data of unknown label " + label.get());
      delete promise;
    }
    promises.clear();
    return;
  }

  LOG(INFO) << "A new leading master (UPID="
            << UPID(leader.get().pid()) << ") is detected";

  foreach (Promise<Option<MasterInfo> >* promise, promises) {
    promise->set(leader);
    delete promise;
  }
  promises.clear();
}

ZooKeeperMasterDetector::ZooKeeperMasterDetector(const URL& url)
{
  process = new ZooKeeperMasterDetectorProcess(url);
  spawn(process);
}

ZooKeeperMasterDetector::ZooKeeperMasterDetector(Owned<Group> group)
{
  process = new ZooKeeperMasterDetectorProcess(group);
  spawn(process);
}

ZooKeeperMasterDetector::~ZooKeeperMasterDetector()
{
  terminate(process);
  process::wait(process);
  delete process;
}

Future<Option<MasterInfo> > ZooKeeperMasterDetector::detect(
    const Option<MasterInfo>& previous)
{
  return dispatch(process, &ZooKeeperMasterDetectorProcess::detect, previous);
}

} // namespace internal {
} // namespace mesos {
<commit_msg>Master detector cleanups.<commit_after>
/**
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <set>
#include <string>

#include <process/defer.hpp>
#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/id.hpp>
#include <process/logging.hpp>
#include <process/pid.hpp>
#include <process/process.hpp>

#include <stout/duration.hpp>
#include <stout/foreach.hpp>
#include <stout/lambda.hpp>

#include "common/protobuf_utils.hpp"

#include "master/constants.hpp"
#include "master/detector.hpp"
#include "master/master.hpp"

#include "messages/messages.hpp"

#include "zookeeper/detector.hpp"
#include "zookeeper/group.hpp"
#include "zookeeper/url.hpp"

using namespace process;
using namespace zookeeper;

using std::set;
using std::string;

namespace mesos {
namespace internal {

const Duration MASTER_DETECTOR_ZK_SESSION_TIMEOUT = Seconds(10);

// TODO(bmahler): Consider moving these kinds of helpers into
// libprocess or a common header within mesos.
namespace promises {

// Helper for setting a set of Promises.
template <typename T>
void set(std::set<Promise<T>* >* promises, const T& t)
{
  foreach (Promise<T>* promise, *promises) {
    promise->set(t);
    delete promise;
  }
  promises->clear();
}

// Helper for failing a set of Promises.
template <typename T>
void fail(std::set<Promise<T>* >* promises, const string& failure)
{
  foreach (Promise<Option<MasterInfo> >* promise, *promises) {
    promise->fail(failure);
    delete promise;
  }
  promises->clear();
}

// Helper for discarding a set of Promises.
template <typename T>
void discard(std::set<Promise<T>* >* promises)
{
  foreach (Promise<T>* promise, *promises) {
    promise->discard();
    delete promise;
  }
  promises->clear();
}

} // namespace promises {

class StandaloneMasterDetectorProcess
  : public Process<StandaloneMasterDetectorProcess>
{
public:
  StandaloneMasterDetectorProcess()
    : ProcessBase(ID::generate("standalone-master-detector")) {}
  explicit StandaloneMasterDetectorProcess(const MasterInfo& _leader)
    : ProcessBase(ID::generate("standalone-master-detector")),
      leader(_leader) {}

  ~StandaloneMasterDetectorProcess()
  {
    promises::discard(&promises);
  }

  void appoint(const Option<MasterInfo>& leader_)
  {
    leader = leader_;

    promises::set(&promises, leader);
  }

  Future<Option<MasterInfo> > detect(
      const Option<MasterInfo>& previous = None())
  {
    if (leader != previous) {
      return leader;
    }

    Promise<Option<MasterInfo> >* promise = new Promise<Option<MasterInfo> >();
    promises.insert(promise);
    return promise->future();
  }

private:
  Option<MasterInfo> leader; // The appointed master.
  set<Promise<Option<MasterInfo> >*> promises;
};

class ZooKeeperMasterDetectorProcess
  : public Process<ZooKeeperMasterDetectorProcess>
{
public:
  explicit ZooKeeperMasterDetectorProcess(const URL& url);
  explicit ZooKeeperMasterDetectorProcess(Owned<Group> group);
  ~ZooKeeperMasterDetectorProcess();

  virtual void initialize();
  Future<Option<MasterInfo> > detect(const Option<MasterInfo>& previous);

private:
  // Invoked when the group leadership has changed.
  void detected(const Future<Option<Group::Membership> >& leader);

  // Invoked when we have fetched the data associated with the leader.
  void fetched(const Group::Membership& membership, const Future<string>& data);

  Owned<Group> group;
  LeaderDetector detector;

  // The leading Master.
  Option<MasterInfo> leader;
  set<Promise<Option<MasterInfo> >*> promises;

  // Potential non-retryable error.
  Option<Error> error;
};

Try<MasterDetector*> MasterDetector::create(const string& master)
{
  if (master == "") {
    return new StandaloneMasterDetector();
  } else if (master.find("zk://") == 0) {
    Try<URL> url = URL::parse(master);
    if (url.isError()) {
      return Error(url.error());
    }
    if (url.get().path == "/") {
      return Error(
          "Expecting a (chroot) path for ZooKeeper ('/' is not supported)");
    }
    return new ZooKeeperMasterDetector(url.get());
  } else if (master.find("file://") == 0) {
    const string& path = master.substr(7);
    const Try<string> read = os::read(path);
    if (read.isError()) {
      return Error("Failed to read from file at '" + path + "'");
    }

    return create(strings::trim(read.get()));
  }

  // Okay, try and parse what we got as a PID.
  UPID pid = master.find("master@") == 0
    ? UPID(master)
    : UPID("master@" + master);

  if (!pid) {
    return Error("Failed to parse '" + master + "'");
  }

  return new StandaloneMasterDetector(protobuf::createMasterInfo(pid));
}

MasterDetector::~MasterDetector() {}

StandaloneMasterDetector::StandaloneMasterDetector()
{
  process = new StandaloneMasterDetectorProcess();
  spawn(process);
}

StandaloneMasterDetector::StandaloneMasterDetector(const MasterInfo& leader)
{
  process = new StandaloneMasterDetectorProcess(leader);
  spawn(process);
}

StandaloneMasterDetector::StandaloneMasterDetector(const UPID& leader)
{
  process =
    new StandaloneMasterDetectorProcess(protobuf::createMasterInfo(leader));

  spawn(process);
}

StandaloneMasterDetector::~StandaloneMasterDetector()
{
  terminate(process);
  process::wait(process);
  delete process;
}

void StandaloneMasterDetector::appoint(const Option<MasterInfo>& leader)
{
  dispatch(process, &StandaloneMasterDetectorProcess::appoint, leader);
}

void StandaloneMasterDetector::appoint(const UPID& leader)
{
  dispatch(process,
           &StandaloneMasterDetectorProcess::appoint,
           protobuf::createMasterInfo(leader));
}

Future<Option<MasterInfo> > StandaloneMasterDetector::detect(
    const Option<MasterInfo>& previous)
{
  return dispatch(process, &StandaloneMasterDetectorProcess::detect, previous);
}

// TODO(benh): Get ZooKeeper timeout from configuration.
// TODO(xujyan): Use peer constructor after switching to C++ 11.
ZooKeeperMasterDetectorProcess::ZooKeeperMasterDetectorProcess(
    const URL& url)
  : ProcessBase(ID::generate("zookeeper-master-detector")),
    group(new Group(url.servers,
                    MASTER_DETECTOR_ZK_SESSION_TIMEOUT,
                    url.path,
                    url.authentication)),
    detector(group.get()),
    leader(None()) {}

ZooKeeperMasterDetectorProcess::ZooKeeperMasterDetectorProcess(
    Owned<Group> _group)
  : ProcessBase(ID::generate("zookeeper-master-detector")),
    group(_group),
    detector(group.get()),
    leader(None()) {}

ZooKeeperMasterDetectorProcess::~ZooKeeperMasterDetectorProcess()
{
  promises::discard(&promises);
}

void ZooKeeperMasterDetectorProcess::initialize()
{
  detector.detect()
    .onAny(defer(self(), &Self::detected, lambda::_1));
}

Future<Option<MasterInfo> > ZooKeeperMasterDetectorProcess::detect(
    const Option<MasterInfo>& previous)
{
  // Return immediately if the detector is no longer operational due
  // to a non-retryable error.
  if (error.isSome()) {
    return Failure(error.get().message);
  }

  if (leader != previous) {
    return leader;
  }

  Promise<Option<MasterInfo> >* promise = new Promise<Option<MasterInfo> >();
  promises.insert(promise);
  return promise->future();
}

void ZooKeeperMasterDetectorProcess::detected(
    const Future<Option<Group::Membership> >& _leader)
{
  CHECK(!_leader.isDiscarded());

  if (_leader.isFailed()) {
    LOG(ERROR) << "Failed to detect the leader: " << _leader.failure();

    // Setting this error stops the detection loop and the detector
    // transitions to an erroneous state. Further calls to detect()
    // will directly fail as a result.
    error = Error(_leader.failure());
    leader = None();

    promises::fail(&promises, _leader.failure());

    return;
  }

  if (_leader.get().isNone()) {
    leader = None();

    promises::set(&promises, leader);
  } else {
    // Fetch the data associated with the leader.
    group->data(_leader.get().get())
      .onAny(defer(self(), &Self::fetched, _leader.get().get(), lambda::_1));
  }

  // Keep trying to detect leadership changes.
  detector.detect(_leader.get())
    .onAny(defer(self(), &Self::detected, lambda::_1));
}

void ZooKeeperMasterDetectorProcess::fetched(
    const Group::Membership& membership,
    const Future<string>& data)
{
  CHECK(!data.isDiscarded());

  if (data.isFailed()) {
    leader = None();
    promises::fail(&promises, data.failure());
    return;
  }

  // Parse the data based on the membership label and cache the
  // leader for subsequent requests.
  Option<string> label = membership.label();
  if (label.isNone()) {
    // If we are here it means some masters are still creating znodes
    // with the old format.
    UPID pid = UPID(data.get());
    LOG(WARNING) << "Leading master " << pid << " has data in old format";
    leader = protobuf::createMasterInfo(pid);
  } else if (label.isSome() && label.get() == master::MASTER_INFO_LABEL) {
    MasterInfo info;
    if (!info.ParseFromString(data.get())) {
      leader = None();
      promises::fail(&promises, "Failed to parse data into MasterInfo");
      return;
    }
    leader = info;
  } else {
    leader = None();
    promises::fail(
        &promises,
        "Failed to parse data of unknown label '" + label.get() + "'");
    return;
  }

  LOG(INFO) << "A new leading master (UPID="
            << UPID(leader.get().pid()) << ") is detected";

  promises::set(&promises, leader);
}

ZooKeeperMasterDetector::ZooKeeperMasterDetector(const URL& url)
{
  process = new ZooKeeperMasterDetectorProcess(url);
  spawn(process);
}

ZooKeeperMasterDetector::ZooKeeperMasterDetector(Owned<Group> group)
{
  process = new ZooKeeperMasterDetectorProcess(group);
  spawn(process);
}

ZooKeeperMasterDetector::~ZooKeeperMasterDetector()
{
  terminate(process);
  process::wait(process);
  delete process;
}

Future<Option<MasterInfo> > ZooKeeperMasterDetector::detect(
    const Option<MasterInfo>& previous)
{
  return dispatch(process, &ZooKeeperMasterDetectorProcess::detect, previous);
}

} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "HTMLNames.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/Range.h"
#include "core/editing/FormatBlockCommand.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/htmlediting.h"

namespace WebCore {

using namespace HTMLNames;

static Node* enclosingBlockToSplitTreeTo(Node* startNode);
static bool isElementForFormatBlock(const QualifiedName& tagName);
static inline bool isElementForFormatBlock(Node* node)
{
    return node->isElementNode() && isElementForFormatBlock(toElement(node)->tagQName());
}

FormatBlockCommand::FormatBlockCommand(Document& document, const QualifiedName& tagName)
    : ApplyBlockElementCommand(document, tagName)
    , m_didApply(false)
{
}

void FormatBlockCommand::formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection)
{
    if (!isElementForFormatBlock(tagName()))
        return;
    ApplyBlockElementCommand::formatSelection(startOfSelection, endOfSelection);
    m_didApply = true;
}

void FormatBlockCommand::formatRange(const Position& start, const Position& end, const Position& endOfSelection, RefPtr<Element>& blockNode)
{
    Node* nodeToSplitTo = enclosingBlockToSplitTreeTo(start.deprecatedNode());
    RefPtr<Node> outerBlock = (start.deprecatedNode() == nodeToSplitTo) ? start.deprecatedNode() : splitTreeToNode(start.deprecatedNode(), nodeToSplitTo);
    RefPtr<Node> nodeAfterInsertionPosition = outerBlock;

    RefPtr<Range> range = Range::create(document(), start, endOfSelection);
    Element* refNode = enclosingBlockFlowElement(end);
    Element* root = editableRootForPosition(start);
    // Root is null for elements with contenteditable=false.
    if (!root || !refNode)
        return;
    if (isElementForFormatBlock(refNode->tagQName()) && start == startOfBlock(start)
        && (end == endOfBlock(end) || isNodeVisiblyContainedWithin(refNode, range.get()))
        && refNode != root && !root->isDescendantOf(refNode)) {
        // Already in a block element that only contains the current paragraph
        if (refNode->hasTagName(tagName()))
            return;
        nodeAfterInsertionPosition = refNode;
    }

    if (!blockNode) {
        // Create a new blockquote and insert it as a child of the root editable element. We accomplish
        // this by splitting all parents of the current paragraph up to that point.
        blockNode = createBlockElement();
        insertNodeBefore(blockNode, nodeAfterInsertionPosition);
    }

    Position lastParagraphInBlockNode = blockNode->lastChild() ? positionAfterNode(blockNode->lastChild()) : Position();
    bool wasEndOfParagraph = isEndOfParagraph(lastParagraphInBlockNode);

    moveParagraphWithClones(start, end, blockNode.get(), outerBlock.get());

    if (wasEndOfParagraph && !isEndOfParagraph(lastParagraphInBlockNode) && !isStartOfParagraph(lastParagraphInBlockNode))
        insertBlockPlaceholder(lastParagraphInBlockNode);
}

Element* FormatBlockCommand::elementForFormatBlockCommand(Range* range)
{
    if (!range)
        return 0;

    Node* commonAncestor = range->commonAncestorContainer(IGNORE_EXCEPTION);
    while (commonAncestor && !isElementForFormatBlock(commonAncestor))
        commonAncestor = commonAncestor->parentNode();

    if (!commonAncestor)
        return 0;

    Element* rootEditableElement = range->startContainer()->rootEditableElement();
    if (!rootEditableElement || commonAncestor->contains(rootEditableElement))
        return 0;

    return commonAncestor->isElementNode() ? toElement(commonAncestor) : 0;
}

bool isElementForFormatBlock(const QualifiedName& tagName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
    if (blockTags.isEmpty()) {
        blockTags.add(addressTag);
        blockTags.add(articleTag);
        blockTags.add(asideTag);
        blockTags.add(blockquoteTag);
        blockTags.add(ddTag);
        blockTags.add(divTag);
        blockTags.add(dlTag);
        blockTags.add(dtTag);
        blockTags.add(footerTag);
        blockTags.add(h1Tag);
        blockTags.add(h2Tag);
        blockTags.add(h3Tag);
        blockTags.add(h4Tag);
        blockTags.add(h5Tag);
        blockTags.add(h6Tag);
        blockTags.add(headerTag);
        blockTags.add(hgroupTag);
        blockTags.add(mainTag);
        blockTags.add(navTag);
        blockTags.add(pTag);
        blockTags.add(preTag);
        blockTags.add(sectionTag);
    }
    return blockTags.contains(tagName);
}

Node* enclosingBlockToSplitTreeTo(Node* startNode)
{
    Node* lastBlock = startNode;
    for (Node* n = startNode; n; n = n->parentNode()) {
        if (!n->rendererIsEditable())
            return lastBlock;
        if (isTableCell(n) || n->hasTagName(bodyTag) || !n->parentNode() || !n->parentNode()->rendererIsEditable() || isElementForFormatBlock(n))
            return n;
        if (isBlock(n))
            lastBlock = n;
        if (isListElement(n))
            return n->parentNode()->rendererIsEditable() ? n->parentNode() : n;
    }
    return lastBlock;
}

}
<commit_msg>Minor refactoring in FormatBlockCommand::formatRange. Do an early return if root and refNode elements are null. This shall help avoid making some unnecessary calls such as splitTreeToNode and creating range. No new tests are required for this change.<commit_after>/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "HTMLNames.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/Range.h"
#include "core/editing/FormatBlockCommand.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/htmlediting.h"

namespace WebCore {

using namespace HTMLNames;

static Node* enclosingBlockToSplitTreeTo(Node* startNode);
static bool isElementForFormatBlock(const QualifiedName& tagName);
static inline bool isElementForFormatBlock(Node* node)
{
    return node->isElementNode() && isElementForFormatBlock(toElement(node)->tagQName());
}

FormatBlockCommand::FormatBlockCommand(Document& document, const QualifiedName& tagName)
    : ApplyBlockElementCommand(document, tagName)
    , m_didApply(false)
{
}

void FormatBlockCommand::formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection)
{
    if (!isElementForFormatBlock(tagName()))
        return;
    ApplyBlockElementCommand::formatSelection(startOfSelection, endOfSelection);
    m_didApply = true;
}

void FormatBlockCommand::formatRange(const Position& start, const Position& end, const Position& endOfSelection, RefPtr<Element>& blockNode)
{
    Element* refNode = enclosingBlockFlowElement(end);
    Element* root = editableRootForPosition(start);
    // Root is null for elements with contenteditable=false.
    if (!root || !refNode)
        return;

    Node* nodeToSplitTo = enclosingBlockToSplitTreeTo(start.deprecatedNode());
    RefPtr<Node> outerBlock = (start.deprecatedNode() == nodeToSplitTo) ? start.deprecatedNode() : splitTreeToNode(start.deprecatedNode(), nodeToSplitTo);
    RefPtr<Node> nodeAfterInsertionPosition = outerBlock;
    RefPtr<Range> range = Range::create(document(), start, endOfSelection);

    if (isElementForFormatBlock(refNode->tagQName()) && start == startOfBlock(start)
        && (end == endOfBlock(end) || isNodeVisiblyContainedWithin(refNode, range.get()))
        && refNode != root && !root->isDescendantOf(refNode)) {
        // Already in a block element that only contains the current paragraph
        if (refNode->hasTagName(tagName()))
            return;
        nodeAfterInsertionPosition = refNode;
    }

    if (!blockNode) {
        // Create a new blockquote and insert it as a child of the root editable element. We accomplish
        // this by splitting all parents of the current paragraph up to that point.
        blockNode = createBlockElement();
        insertNodeBefore(blockNode, nodeAfterInsertionPosition);
    }

    Position lastParagraphInBlockNode = blockNode->lastChild() ? positionAfterNode(blockNode->lastChild()) : Position();
    bool wasEndOfParagraph = isEndOfParagraph(lastParagraphInBlockNode);

    moveParagraphWithClones(start, end, blockNode.get(), outerBlock.get());

    if (wasEndOfParagraph && !isEndOfParagraph(lastParagraphInBlockNode) && !isStartOfParagraph(lastParagraphInBlockNode))
        insertBlockPlaceholder(lastParagraphInBlockNode);
}

Element* FormatBlockCommand::elementForFormatBlockCommand(Range* range)
{
    if (!range)
        return 0;

    Node* commonAncestor = range->commonAncestorContainer(IGNORE_EXCEPTION);
    while (commonAncestor && !isElementForFormatBlock(commonAncestor))
        commonAncestor = commonAncestor->parentNode();

    if (!commonAncestor)
        return 0;

    Element* rootEditableElement = range->startContainer()->rootEditableElement();
    if (!rootEditableElement || commonAncestor->contains(rootEditableElement))
        return 0;

    return commonAncestor->isElementNode() ? toElement(commonAncestor) : 0;
}

bool isElementForFormatBlock(const QualifiedName& tagName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
    if (blockTags.isEmpty()) {
        blockTags.add(addressTag);
        blockTags.add(articleTag);
        blockTags.add(asideTag);
        blockTags.add(blockquoteTag);
        blockTags.add(ddTag);
        blockTags.add(divTag);
        blockTags.add(dlTag);
        blockTags.add(dtTag);
        blockTags.add(footerTag);
        blockTags.add(h1Tag);
        blockTags.add(h2Tag);
        blockTags.add(h3Tag);
        blockTags.add(h4Tag);
        blockTags.add(h5Tag);
        blockTags.add(h6Tag);
        blockTags.add(headerTag);
        blockTags.add(hgroupTag);
        blockTags.add(mainTag);
        blockTags.add(navTag);
        blockTags.add(pTag);
        blockTags.add(preTag);
        blockTags.add(sectionTag);
    }
    return blockTags.contains(tagName);
}

Node* enclosingBlockToSplitTreeTo(Node* startNode)
{
    Node* lastBlock = startNode;
    for (Node* n = startNode; n; n = n->parentNode()) {
        if (!n->rendererIsEditable())
            return lastBlock;
        if (isTableCell(n) || n->hasTagName(bodyTag) || !n->parentNode() || !n->parentNode()->rendererIsEditable() || isElementForFormatBlock(n))
            return n;
        if (isBlock(n))
            lastBlock = n;
        if (isListElement(n))
            return n->parentNode()->rendererIsEditable() ? n->parentNode() : n;
    }
    return lastBlock;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparamsbase.h>

#include <tinyformat.h>
#include <util/system.h>
#include <util/memory.h>

#include <assert.h>

const std::string CBaseChainParams::MAIN = "main";
const std::string CBaseChainParams::TESTNET = "test";
const std::string CBaseChainParams::REGTEST = "regtest";
const std::string CBaseChainParams::LIQUID1 = "liquidv1";

void SetupChainParamsBaseOptions()
{
    gArgs.AddArg("-chain=<chain>", "Use the chain <chain> (default: main). Reserved values: main, test, regtest", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
                                   "This is intended for regression testing tools and app development.", true, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest or custom only)", true, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-seednode=<ip>", "Use specified node as seed node. This option can be specified multiple times to connect to multiple nodes. (custom only)", true, OptionsCategory::CHAINPARAMS);

    //
    // ELEMENTS
    gArgs.AddArg("-con_mandatorycoinbase", "All non-zero valued coinbase outputs must go to this scriptPubKey, if set.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_blocksubsidy", "Defines the amount of block subsidy to start with, at genesis block, in satoshis.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_connect_genesis_outputs", "Connect outputs in genesis block to utxo database.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_elementsmode", "Use Elements-like instead of Core-like witness encoding.  This is required for CA/CT. (default: true)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_blockheightinheader", "Whether the chain includes the block height directly in the header, for easier validation of block height in low-resource environments. (default: true)", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_genesis_style=<style>", "Use genesis style <style> (default: elements). Results in genesis block compatibility with various networks. Allowed values: elements, bitcoin", true, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_signed_blocks", "Signed blockchain. Uses input of `-signblockscript` to define what signatures are necessary to solve it.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-signblockscript", "Signed blockchain enumberance. Only active when `-con_signed_blocks` set to true.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_max_block_sig_size", "Max allowed witness data for the signed block header.", false, OptionsCategory::CHAINPARAMS);

    gArgs.AddArg("-con_has_parent_chain", "Whether or not there is a parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-parentgenesisblockhash", "The genesis blockhash of the parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_parentpowlimit", "The proof-of-work limit value for the parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_parent_chain_signblockscript", "Whether parent chain uses pow or signed blocks. If the parent chain uses signed blocks, the challenge (scriptPubKey) script. If not, an empty string. (default: empty script [ie parent uses pow])", false, OptionsCategory::CHAINPARAMS);

    gArgs.AddArg("-fedpegscript", "The script for the federated peg.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-enforce_pak", "Causes standardness checks to enforce Pegout Authorization Key(PAK) validation, and miner to include PAK commitments when configured. Can not be set when acceptnonstdtx is set to true.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-pak", "Entries in the PAK list. Order of entries matter.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-multi_data_permitted", "Allow relay of multiple OP_RETURN outputs. (default: -enforce_pak)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_csv_deploy_start", "Starting height for CSV deployment. (default: -1, which means ACTIVE from genesis)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-dynamic_epoch_length", "Per-chain parameter that sets how many blocks dynamic federation voting and enforcement are in effect for.", false, OptionsCategory::ELEMENTS);
    // END ELEMENTS
    //
}

static std::unique_ptr<CBaseChainParams> globalChainBaseParams;

const CBaseChainParams& BaseParams()
{
    assert(globalChainBaseParams);
    return *globalChainBaseParams;
}

std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{
    if (chain == CBaseChainParams::MAIN)
        return MakeUnique<CBaseChainParams>("", 8332, 18332);
    else if (chain == CBaseChainParams::TESTNET)
        return MakeUnique<CBaseChainParams>("testnet3", 18332, 8332);
    else if (chain == CBaseChainParams::REGTEST)
        return MakeUnique<CBaseChainParams>("regtest", 18443, 18332);
    else if (chain == CBaseChainParams::LIQUID1)
        return MakeUnique<CBaseChainParams>("liquidv1", 7041, 8332);

    // ELEMENTS:
    return MakeUnique<CBaseChainParams>(chain, 7040, 18332);
}

void SelectBaseParams(const std::string& chain)
{
    globalChainBaseParams = CreateBaseChainParams(chain);
    gArgs.SelectConfigNetwork(chain);
}
<commit_msg>Add and update startup args for dynafed<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparamsbase.h>

#include <tinyformat.h>
#include <util/system.h>
#include <util/memory.h>

#include <assert.h>

const std::string CBaseChainParams::MAIN = "main";
const std::string CBaseChainParams::TESTNET = "test";
const std::string CBaseChainParams::REGTEST = "regtest";
const std::string CBaseChainParams::LIQUID1 = "liquidv1";

void SetupChainParamsBaseOptions()
{
    gArgs.AddArg("-chain=<chain>", "Use the chain <chain> (default: main). Reserved values: main, test, regtest", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
                                   "This is intended for regression testing tools and app development.", true, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest or custom only)", true, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-seednode=<ip>", "Use specified node as seed node. This option can be specified multiple times to connect to multiple nodes. (custom only)", true, OptionsCategory::CHAINPARAMS);

    //
    // ELEMENTS
    gArgs.AddArg("-con_mandatorycoinbase", "All non-zero valued coinbase outputs must go to this scriptPubKey, if set.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_blocksubsidy", "Defines the amount of block subsidy to start with, at genesis block, in satoshis.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_connect_genesis_outputs", "Connect outputs in genesis block to utxo database.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_elementsmode", "Use Elements-like instead of Core-like witness encoding.  This is required for CA/CT. (default: true)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_blockheightinheader", "Whether the chain includes the block height directly in the header, for easier validation of block height in low-resource environments. (default: true)", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_genesis_style=<style>", "Use genesis style <style> (default: elements). Results in genesis block compatibility with various networks. Allowed values: elements, bitcoin", true, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_signed_blocks", "Signed blockchain. Uses input of `-signblockscript` to define what signatures are necessary to solve it.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-signblockscript", "Signed blockchain enumberance. Only active when `-con_signed_blocks` set to true.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_max_block_sig_size", "Max allowed witness data for the signed block header.", false, OptionsCategory::CHAINPARAMS);

    gArgs.AddArg("-con_has_parent_chain", "Whether or not there is a parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-parentgenesisblockhash", "The genesis blockhash of the parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_parentpowlimit", "The proof-of-work limit value for the parent chain.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-con_parent_chain_signblockscript", "Whether parent chain uses pow or signed blocks. If the parent chain uses signed blocks, the challenge (scriptPubKey) script. If not, an empty string. (default: empty script [ie parent uses pow])", false, OptionsCategory::CHAINPARAMS);

    gArgs.AddArg("-fedpegscript", "The script for the federated peg enforce from genesis block. This script may stop being enforced once dynamic federations activates.", false, OptionsCategory::CHAINPARAMS);
    gArgs.AddArg("-enforce_pak", "Causes standardness checks to enforce Pegout Authorization Key(PAK) validation before dynamic federations, and consensus enforcement after.", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-multi_data_permitted", "Allow relay of multiple OP_RETURN outputs. (default: -enforce_pak)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_csv_deploy_start", "Starting height for CSV deployment. (default: -1, which means ACTIVE from genesis)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-con_dyna_deploy_start", "Starting height for Dynamic Federations deployment. Once active, signblockscript becomes a BIP141 WSH scriptPubKey of the original signblockscript. All other dynamic parameters stay constant.(default: -1, which means ACTIVE from genesis)", false, OptionsCategory::ELEMENTS);
    gArgs.AddArg("-dynamic_epoch_length", "Per-chain parameter that sets how many blocks dynamic federation voting and enforcement are in effect for.", false, OptionsCategory::ELEMENTS);
    // END ELEMENTS
    //
}

static std::unique_ptr<CBaseChainParams> globalChainBaseParams;

const CBaseChainParams& BaseParams()
{
    assert(globalChainBaseParams);
    return *globalChainBaseParams;
}

std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{
    if (chain == CBaseChainParams::MAIN)
        return MakeUnique<CBaseChainParams>("", 8332, 18332);
    else if (chain == CBaseChainParams::TESTNET)
        return MakeUnique<CBaseChainParams>("testnet3", 18332, 8332);
    else if (chain == CBaseChainParams::REGTEST)
        return MakeUnique<CBaseChainParams>("regtest", 18443, 18332);
    else if (chain == CBaseChainParams::LIQUID1)
        return MakeUnique<CBaseChainParams>("liquidv1", 7041, 8332);

    // ELEMENTS:
    return MakeUnique<CBaseChainParams>(chain, 7040, 18332);
}

void SelectBaseParams(const std::string& chain)
{
    globalChainBaseParams = CreateBaseChainParams(chain);
    gArgs.SelectConfigNetwork(chain);
}
<|endoftext|>