<commit_before>#pragma once

//
// fastcgi.hpp
// ~~~~~~~~
//
// Copyright (c) 2017 Mohsen Khaki (mohsen dot khaki at gmail dot com)
//
// Distributed under the MIT License
//

#include <cstdint>
#include <algorithm>

namespace FastCGI
{

enum class Type : uint8_t
{
	BEGIN_REQUEST     = 1, /* [in]                              */
	ABORT_REQUEST     = 2, /* [in]                              */
	END_REQUEST       = 3, /* [out]                             */
	PARAM             = 4, /* [in]  environment variables       */
	STDIN             = 5, /* [in]  post data                   */
	STDOUT            = 6, /* [out] response                    */
	STDERR            = 7, /* [out] errors                      */
	DATA              = 8, /* [in]  filter data                 */
	GET_VALUES        = 9, /* [in]                              */
	GET_VALUES_RESULT = 10, /* [out]                             */
	UNKNOWN_TYPE      = 11, /* [out]                             */
};

struct RecordHeader
{
	uint8_t version = 0;
	Type    type = Type::UNKNOWN_TYPE;
	uint8_t requestIDB1 = 0;
	uint8_t requestIDB0 = 0;
	uint8_t contentLengthB1 = 0;
	uint8_t contentLengthB0 = 0;
	uint8_t paddingLength = 0;
	uint8_t reserved;

	uint16_t requestID() const
	{
		return (static_cast<uint16_t>(requestIDB1) << 8) | requestIDB0;
	}

	void requestID(uint16_t id)
	{
		requestIDB0 = id && 0xff;
		id >>= 8;
		requestIDB1 = id && 0xff;
	}

	uint16_t contentLength() const
	{
		return (static_cast<uint16_t>(contentLengthB1) << 8) | contentLengthB0;
	}

	void contentLength(uint16_t length)
	{
		contentLengthB0 = length && 0xff;
		length >>= 8;
		contentLengthB1 = length && 0xff;
	}
};

enum BeginRequestFlag : uint8_t
{
	KEEP_CONN = 0x01,
};

enum class BeginRequestRoles : uint16_t
{
	RESPONDER = 1,
	AUTHORIZER = 2,
	FILTER = 3,
};

enum class EndRequestApplicationStatus : uint16_t
{
	REQUEST_COMPLETE = 0,
	CANT_MPX_CONN = 1,
	OVERLOADED = 2,
	UNKNOWN_ROLE = 3,
};

struct Length
{
	uint8_t lengthB3 = 0;
	uint8_t lengthB2 = 0;
	uint8_t lengthB1 = 0;
	uint8_t lengthB0 = 0;
	uint32_t length() const
	{
		return (static_cast<uint32_t>(lengthB3 & 0x7fu) << 24) |
		       (static_cast<uint32_t>(lengthB2) << 16) |
		       (static_cast<uint32_t>(lengthB1) <<  8) | lengthB0;
	}
};

struct NameValue
{
	NameValue()
	{
	}
	NameValue(const char* name, const uint32_t nameLength, const char* value, const uint32_t valueLength)
		: name(name), nameLength(nameLength), value(value), valueLength(valueLength)
	{
	}
	const char* name = nullptr;
	uint32_t nameLength = 0;
	const char* value = nullptr;
	uint32_t valueLength = 0;
};

struct NameValueIterator
{
	NameValueIterator()
	{
	}
	NameValueIterator(const char* buffer, const size_t length)
	{
		initialize(buffer, length);
	}
	bool invalid() const
	{
		return length_ == 0;
	}
	NameValueIterator operator++(int) const
	{
		return NameValueIterator(buffer_ + sectionLength_, length_ - sectionLength_);
	}
	NameValueIterator& operator++()
	{
		if (length_ > sectionLength_)
		{
			initialize(buffer_ + sectionLength_, length_ - sectionLength_);
		}
		else
		{
			initialize(buffer_ + sectionLength_, 0);
		}
		return *this;
	}

	bool operator==(const NameValueIterator& other) const
	{
		return buffer_ == other.buffer_ && length_ == other.length_;
	}
	bool operator!=(const NameValueIterator& other) const
	{
		return !(*this == other);
	}

	const NameValue& operator*() const
	{
		return nameValue_;
	}
	const NameValue* operator->() const
	{
		return &nameValue_;
	}

	void initialize(const char* buffer, const size_t length)
	{
		buffer_ = buffer;
		length_ = length;
		if (length > 0)
		{
			uint32_t nameLength = readLength(buffer);
			uint32_t valueLength = readLength(buffer);
			nameValue_ = NameValue(buffer, nameLength, buffer + nameLength, valueLength);
			sectionLength_ = (buffer + nameLength + valueLength - buffer_);
		}
	}

	static uint32_t readLength(const char*& buffer)
	{
		uint8_t lengthB0 = *reinterpret_cast<const uint8_t*>(buffer);
		if ((lengthB0 & 0x80u) == 0)
		{
			buffer += 1;
			return lengthB0;
		}
		Length length;
		std::copy(buffer, buffer + sizeof(length), reinterpret_cast<char*>(&length));
		buffer += sizeof(length);
		return length.length();
	}

	NameValue nameValue_;
	const char* buffer_ = nullptr;
	size_t sectionLength_ = 0;
	size_t length_ = 0;

};

struct BeginRequest
{
	uint8_t roleB1 = 0;
	uint8_t roleB0 = 0;
	uint8_t flags = 0;
	uint8_t reserved[5];
	BeginRequestRoles role() const
	{
		return static_cast<BeginRequestRoles>((static_cast<uint16_t>(roleB1) << 8) | roleB0);
	}
	void role(const BeginRequestRoles role)
	{
		uint16_t roleValue = static_cast<uint16_t>(role);
		roleB0 = roleValue && 0xff;
		roleValue >>= 8;
		roleB1 = roleValue && 0xff;
	}
};

struct EndRequest
{
	uint8_t appStatusB3 = 0;
	uint8_t appStatusB2 = 0;
	uint8_t appStatusB1 = 0;
	uint8_t appStatusB0 = 0;
	uint8_t protocolStatus = 0;
	uint8_t reserved[3];
	EndRequestApplicationStatus appStatus() const
	{
		return static_cast<EndRequestApplicationStatus>(
		    (static_cast<uint32_t>(appStatusB3) << 24) |
		    (static_cast<uint32_t>(appStatusB2) << 16) |
		    (static_cast<uint32_t>(appStatusB1) <<  8) | appStatusB0);
	}
	void appStatus(const EndRequestApplicationStatus status)
	{
		uint32_t statusValue = static_cast<uint32_t>(status);
		appStatusB0 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB1 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB2 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB3 = statusValue && 0xff;
	}
};

struct UnknownType
{
	uint8_t type;
	uint8_t reserved[7];
};

template<Type TYPE>
struct Atom {};

class Decoder
{
public:
	template<class HANDLER>
	void write(const char* buffer, size_t lengthInBytes, HANDLER& handler)
	{
		if (!buffer_.empty())
		{
			while (expected_ > buffer_.size())
			{
				const size_t length = std::min(expected_, lengthInBytes);
				buffer_.insert(buffer_.end(), buffer, buffer + length);
				buffer += length;
				lengthInBytes -= length;
				if (!decode(buffer_.data(), buffer_.size(), expected_, handler) || lengthInBytes == 0)
				{
					return;
				}
				if (buffer_.size() >= expected_)
				{
					buffer_.clear();
					expected_ = 0;
					break;
				}
			}
		}
		while (true)
		{
			if (!decode(buffer, lengthInBytes, expected_, handler))
			{
				return;
			}
			if (lengthInBytes < expected_)
			{
				buffer_.assign(buffer, buffer + lengthInBytes);
				return;
			}
			lengthInBytes -= expected_;
			buffer += expected_;
		}
	}
private:
	template<class HANDLER>
	static bool decode(const char* buffer, size_t length, size_t& expected, HANDLER& handler)
	{
		if (length < sizeof(RecordHeader))
		{
			expected = sizeof(RecordHeader);
			return true;
		}
		RecordHeader header;
		std::copy(buffer, buffer + sizeof(RecordHeader), reinterpret_cast<char*>(&header));
		const size_t contentLength = header.contentLength();
		expected = sizeof(RecordHeader) + contentLength;
		if (contentLength > length)
		{
			return true;
		}
		buffer += sizeof(RecordHeader);
		switch (header.type)
		{
		case Type::BEGIN_REQUEST:
		{
			BeginRequest beginRequest;
			std::copy(buffer, buffer + sizeof(beginRequest), reinterpret_cast<char*>(&beginRequest));
			return handler(Atom<Type::BEGIN_REQUEST>(), header, beginRequest);
		}
		case Type::ABORT_REQUEST:
		{
			return handler(Atom<Type::ABORT_REQUEST>(), header);
		}
		case Type::END_REQUEST:
		{
			EndRequest endRequest;
			std::copy(buffer, buffer + sizeof(endRequest), reinterpret_cast<char*>(&endRequest));
			return handler(Atom<Type::END_REQUEST>(), header, endRequest);
		}
		case Type::PARAM:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::PARAM>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::STDIN:
		{
			return handler(Atom<Type::STDIN>(), header, buffer, contentLength);
		}
		case Type::STDOUT:
		{
			return handler(Atom<Type::STDOUT>(), header, buffer, contentLength);
		}
		case Type::STDERR:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::DATA:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::GET_VALUES:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::GET_VALUES_RESULT:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::UNKNOWN_TYPE:
		{
			return handler(Atom<Type::UNKNOWN_TYPE>(), header, buffer, contentLength);
		}
		}
		return handler(header, buffer, contentLength);
	}
	std::vector<char> buffer_;
	size_t expected_ = 0;
};

}
<commit_msg>Fix the unhandled padding bytes<commit_after>#pragma once

//
// fastcgi.hpp
// ~~~~~~~~
//
// Copyright (c) 2017 Mohsen Khaki (mohsen dot khaki at gmail dot com)
//
// Distributed under the MIT License
//

#include <cstdint>
#include <algorithm>

namespace FastCGI
{

enum class Type : uint8_t
{
	BEGIN_REQUEST     = 1, /* [in]                              */
	ABORT_REQUEST     = 2, /* [in]                              */
	END_REQUEST       = 3, /* [out]                             */
	PARAM             = 4, /* [in]  environment variables       */
	STDIN             = 5, /* [in]  post data                   */
	STDOUT            = 6, /* [out] response                    */
	STDERR            = 7, /* [out] errors                      */
	DATA              = 8, /* [in]  filter data                 */
	GET_VALUES        = 9, /* [in]                              */
	GET_VALUES_RESULT = 10, /* [out]                             */
	UNKNOWN_TYPE      = 11, /* [out]                             */
};

struct RecordHeader
{
	uint8_t version = 0;
	Type    type = Type::UNKNOWN_TYPE;
	uint8_t requestIDB1 = 0;
	uint8_t requestIDB0 = 0;
	uint8_t contentLengthB1 = 0;
	uint8_t contentLengthB0 = 0;
	uint8_t paddingLength = 0;
	uint8_t reserved;

	uint16_t requestID() const
	{
		return (static_cast<uint16_t>(requestIDB1) << 8) | requestIDB0;
	}

	void requestID(uint16_t id)
	{
		requestIDB0 = id && 0xff;
		id >>= 8;
		requestIDB1 = id && 0xff;
	}

	uint16_t contentLength() const
	{
		return (static_cast<uint16_t>(contentLengthB1) << 8) | contentLengthB0;
	}

	void contentLength(uint16_t length)
	{
		contentLengthB0 = length && 0xff;
		length >>= 8;
		contentLengthB1 = length && 0xff;
	}
};

enum BeginRequestFlag : uint8_t
{
	KEEP_CONN = 0x01,
};

enum class BeginRequestRoles : uint16_t
{
	RESPONDER = 1,
	AUTHORIZER = 2,
	FILTER = 3,
};

enum class EndRequestApplicationStatus : uint16_t
{
	REQUEST_COMPLETE = 0,
	CANT_MPX_CONN = 1,
	OVERLOADED = 2,
	UNKNOWN_ROLE = 3,
};

struct Length
{
	uint8_t lengthB3 = 0;
	uint8_t lengthB2 = 0;
	uint8_t lengthB1 = 0;
	uint8_t lengthB0 = 0;
	uint32_t length() const
	{
		return (static_cast<uint32_t>(lengthB3 & 0x7fu) << 24) |
		       (static_cast<uint32_t>(lengthB2) << 16) |
		       (static_cast<uint32_t>(lengthB1) <<  8) | lengthB0;
	}
};

struct NameValue
{
	NameValue()
	{
	}
	NameValue(const char* name, const uint32_t nameLength, const char* value, const uint32_t valueLength)
		: name(name), nameLength(nameLength), value(value), valueLength(valueLength)
	{
	}
	const char* name = nullptr;
	uint32_t nameLength = 0;
	const char* value = nullptr;
	uint32_t valueLength = 0;
};

struct NameValueIterator
{
	NameValueIterator()
	{
	}
	NameValueIterator(const char* buffer, const size_t length)
	{
		initialize(buffer, length);
	}
	bool invalid() const
	{
		return length_ == 0;
	}
	NameValueIterator operator++(int) const
	{
		return NameValueIterator(buffer_ + sectionLength_, length_ - sectionLength_);
	}
	NameValueIterator& operator++()
	{
		if (length_ > sectionLength_)
		{
			initialize(buffer_ + sectionLength_, length_ - sectionLength_);
		}
		else
		{
			initialize(buffer_ + sectionLength_, 0);
		}
		return *this;
	}

	bool operator==(const NameValueIterator& other) const
	{
		return buffer_ == other.buffer_ && length_ == other.length_;
	}
	bool operator!=(const NameValueIterator& other) const
	{
		return !(*this == other);
	}

	const NameValue& operator*() const
	{
		return nameValue_;
	}
	const NameValue* operator->() const
	{
		return &nameValue_;
	}

	void initialize(const char* buffer, const size_t length)
	{
		buffer_ = buffer;
		length_ = length;
		if (length > 0)
		{
			uint32_t nameLength = readLength(buffer);
			uint32_t valueLength = readLength(buffer);
			nameValue_ = NameValue(buffer, nameLength, buffer + nameLength, valueLength);
			sectionLength_ = (buffer + nameLength + valueLength - buffer_);
		}
	}

	static uint32_t readLength(const char*& buffer)
	{
		uint8_t lengthB0 = *reinterpret_cast<const uint8_t*>(buffer);
		if ((lengthB0 & 0x80u) == 0)
		{
			buffer += 1;
			return lengthB0;
		}
		Length length;
		std::copy(buffer, buffer + sizeof(length), reinterpret_cast<char*>(&length));
		buffer += sizeof(length);
		return length.length();
	}

	NameValue nameValue_;
	const char* buffer_ = nullptr;
	size_t sectionLength_ = 0;
	size_t length_ = 0;

};

struct BeginRequest
{
	uint8_t roleB1 = 0;
	uint8_t roleB0 = 0;
	uint8_t flags = 0;
	uint8_t reserved[5];
	BeginRequestRoles role() const
	{
		return static_cast<BeginRequestRoles>((static_cast<uint16_t>(roleB1) << 8) | roleB0);
	}
	void role(const BeginRequestRoles role)
	{
		uint16_t roleValue = static_cast<uint16_t>(role);
		roleB0 = roleValue && 0xff;
		roleValue >>= 8;
		roleB1 = roleValue && 0xff;
	}
};

struct EndRequest
{
	uint8_t appStatusB3 = 0;
	uint8_t appStatusB2 = 0;
	uint8_t appStatusB1 = 0;
	uint8_t appStatusB0 = 0;
	uint8_t protocolStatus = 0;
	uint8_t reserved[3];
	EndRequestApplicationStatus appStatus() const
	{
		return static_cast<EndRequestApplicationStatus>(
		    (static_cast<uint32_t>(appStatusB3) << 24) |
		    (static_cast<uint32_t>(appStatusB2) << 16) |
		    (static_cast<uint32_t>(appStatusB1) <<  8) | appStatusB0);
	}
	void appStatus(const EndRequestApplicationStatus status)
	{
		uint32_t statusValue = static_cast<uint32_t>(status);
		appStatusB0 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB1 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB2 = statusValue && 0xff;
		statusValue >>= 8;
		appStatusB3 = statusValue && 0xff;
	}
};

struct UnknownType
{
	uint8_t type;
	uint8_t reserved[7];
};

template<Type TYPE>
struct Atom {};

class Decoder
{
public:
	template<class HANDLER>
	void write(const char* buffer, size_t lengthInBytes, HANDLER& handler)
	{
		if (!buffer_.empty())
		{
			while (expected_ > buffer_.size())
			{
				const size_t length = std::min(expected_, lengthInBytes);
				buffer_.insert(buffer_.end(), buffer, buffer + length);
				buffer += length;
				lengthInBytes -= length;
				if (!decode(buffer_.data(), buffer_.size(), expected_, handler) || lengthInBytes == 0)
				{
					return;
				}
				if (buffer_.size() >= expected_)
				{
					buffer_.clear();
					expected_ = 0;
					break;
				}
			}
		}
		while (true)
		{
			if (!decode(buffer, lengthInBytes, expected_, handler))
			{
				return;
			}
			if (lengthInBytes < expected_)
			{
				buffer_.assign(buffer, buffer + lengthInBytes);
				return;
			}
			lengthInBytes -= expected_;
			buffer += expected_;
		}
	}
private:
	template<class HANDLER>
	static bool decode(const char* buffer, size_t length, size_t& expected, HANDLER& handler)
	{
		if (length < sizeof(RecordHeader))
		{
			expected = sizeof(RecordHeader);
			return true;
		}
		RecordHeader header;
		std::copy(buffer, buffer + sizeof(RecordHeader), reinterpret_cast<char*>(&header));
		const size_t contentLength = header.contentLength();
		expected = sizeof(RecordHeader) + contentLength + header.paddingLength;
		if (expected > length)
		{
			return true;
		}
		buffer += sizeof(RecordHeader);
		switch (header.type)
		{
		case Type::BEGIN_REQUEST:
		{
			BeginRequest beginRequest;
			std::copy(buffer, buffer + sizeof(beginRequest), reinterpret_cast<char*>(&beginRequest));
			return handler(Atom<Type::BEGIN_REQUEST>(), header, beginRequest);
		}
		case Type::ABORT_REQUEST:
		{
			return handler(Atom<Type::ABORT_REQUEST>(), header);
		}
		case Type::END_REQUEST:
		{
			EndRequest endRequest;
			std::copy(buffer, buffer + sizeof(endRequest), reinterpret_cast<char*>(&endRequest));
			return handler(Atom<Type::END_REQUEST>(), header, endRequest);
		}
		case Type::PARAM:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::PARAM>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::STDIN:
		{
			return handler(Atom<Type::STDIN>(), header, buffer, contentLength);
		}
		case Type::STDOUT:
		{
			return handler(Atom<Type::STDOUT>(), header, buffer, contentLength);
		}
		case Type::STDERR:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::DATA:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::GET_VALUES:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::GET_VALUES_RESULT:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::UNKNOWN_TYPE:
		{
			return handler(Atom<Type::UNKNOWN_TYPE>(), header, buffer, contentLength);
		}
		}
		return handler(header, buffer, contentLength);
	}
	std::vector<char> buffer_;
	size_t expected_ = 0;
};

}
<|endoftext|>


<commit_before>//
// Created by mwo on 5/11/15.
//

#include "MicroCore.h"

namespace xmreg
{
    /**
     * The constructor is interesting, as
     * m_mempool and m_blockchain_storage depend
     * on each other.
     *
     * So basically m_mempool is initialized with
     * reference to Blockchain (i.e., Blockchain&)
     * and m_blockchain_storage is initialized with
     * reference to m_mempool (i.e., tx_memory_pool&)
     *
     * The same is done in cryptonode::core.
     */
    MicroCore::MicroCore():
            m_mempool(m_blockchain_storage),
            m_blockchain_storage(m_mempool)
    {}

    /**
     * Initialized the MicroCore object.
     *
     * Create BlockchainLMDB on the heap.
     * Open database files located in blockchain_path.
     * Initialize m_blockchain_storage with the BlockchainLMDB object.
     */
    bool
    MicroCore::init(const string& _blockchain_path)
    {
        int db_flags = 0;

        blockchain_path = _blockchain_path;

        //db_flags |= MDB_RDONLY;
        //db_flags |= MDB_NOLOCK;
        //db_flags |= MDB_SYNC;

        uint64_t DEFAULT_FLAGS = MDB_NOMETASYNC | MDB_NORDAHEAD;

        db_flags = DEFAULT_FLAGS;

        BlockchainDB* db = nullptr;
        db = new BlockchainLMDB();

        try
        {
            // try opening lmdb database files
            db->open(blockchain_path, db_flags);
        }
        catch (const std::exception& e)
        {
            cerr << "Error opening database: " << e.what();
            return false;
        }

        // check if the blockchain database
        // is successful opened
        if(!db->is_open())
        {
            return false;
        }

        // initialize Blockchain object to manage
        // the database.
        return m_blockchain_storage.init(db, false);
    }

    /**
    * Get m_blockchain_storage.
    * Initialize m_blockchain_storage with the BlockchainLMDB object.
    */
    Blockchain&
    MicroCore::get_core()
    {
        return m_blockchain_storage;
    }

    /**
     * Get block by its height
     *
     * returns true if success
     */
    bool
    MicroCore::get_block_by_height(const uint64_t& height, block& blk)
    {

        crypto::hash block_id;

        try
        {
            block_id = m_blockchain_storage.get_block_id_by_height(height);
        }
        catch (const exception& e)
        {
            cerr << e.what() << endl;
            return false;
        }

        if (!m_blockchain_storage.get_block_by_hash(block_id, blk))
        {
            cerr << "Block with hash " << block_id
                 << "and height " << height << " not found!"
                 << endl;
            return false;
        }

        return true;
    }

    /**
     * Get transaction tx from the blockchain using it hash
     */
    bool
    MicroCore::get_tx(const crypto::hash& tx_hash, transaction& tx)
    {
        try
        {
            // get transaction with given hash
            tx = m_blockchain_storage.get_db().get_tx(tx_hash);
        }
        catch (const exception& e)
        {
            cerr << e.what() << endl;
            return false;
        }

        return true;
    }

    bool
    MicroCore::get_tx(const string& tx_hash_str, transaction& tx)
    {

        // parse tx hash string to hash object
        crypto::hash tx_hash;

        if (!xmreg::parse_str_secret_key(tx_hash_str, tx_hash))
        {
            cerr << "Cant parse tx hash: " << tx_hash_str << endl;
            return false;
        }

        if (!get_tx(tx_hash, tx))
        {
            return false;
        }

        return true;
    }

    /**
     * Find output with given public key in a given transaction
     */
    bool
    MicroCore::find_output_in_tx(const transaction& tx,
                                 const public_key& output_pubkey,
                                 tx_out& out,
                                 size_t& output_index)
    {

        size_t idx {0};

        // search in the ouputs for an output which
        // public key matches to what we want
        auto it = std::find_if(tx.vout.begin(), tx.vout.end(),
                               [&](const tx_out& o)
                               {
                                   const txout_to_key& tx_in_to_key
                                           = boost::get<txout_to_key>(o.target);

                                   ++idx;

                                   return tx_in_to_key.key == output_pubkey;
                               });

        if (it != tx.vout.end())
        {
            // we found the desired public key
            out = *it;
            output_index = idx > 0 ? idx - 1 : idx;

            //cout << idx << " " << output_index << endl;

            return true;
        }

        return false;
    }

    /**
     * Returns tx hash in a given block which
     * contains given output's public key
     */
    bool
    MicroCore::get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
                                              const uint64_t& block_height,
                                              crypto::hash& tx_hash,
                                              cryptonote::transaction& tx_found)
    {

        tx_hash = null_hash;

        // get block of given height
        block blk;
        if (!get_block_by_height(block_height, blk))
        {
            cerr << "Cant get block of height: " << block_height << endl;
            return false;
        }

        // get all transactions in the block found
        // initialize the first list with transaction for solving
        // the block i.e. coinbase.
        list<transaction> txs {blk.miner_tx};
        list<crypto::hash> missed_txs;

        if (!m_blockchain_storage.get_transactions(blk.tx_hashes, txs, missed_txs))
        {
            cerr << "Cant find transcations in block: " << block_height << endl;
            return false;
        }

        if (!missed_txs.empty())
        {
            cerr << "Transactions not found in blk: " << block_height << endl;

            for (const crypto::hash& h : missed_txs)
            {
                cerr << " - tx hash: " << h << endl;
            }

            return false;
        }

        // search outputs in each transactions
        // until output with pubkey of interest is found
        for (const transaction& tx : txs)
        {

            tx_out found_out;

            // we dont need here output_index
            size_t output_index;

            if (find_output_in_tx(tx, output_pubkey, found_out, output_index))
            {
                // we found the desired public key
                tx_hash = get_transaction_hash(tx);
                tx_found = tx;

                return true;
            }

        }

        return false;
    }

    uint64_t
    MicroCore::get_blk_timestamp(uint64_t blk_height)
    {
        cryptonote::block blk;

        if (!get_block_by_height(blk_height, blk))
        {
            cerr << "Cant get block by height: " << blk_height << endl;
            return 0;
        }

        return blk.timestamp;
    }

    /**
     * De-initialized Blockchain.
     *
     * since blockchain is opened as MDB_RDONLY
     * need to manually free memory taken on heap
     * by BlockchainLMDB
     */
    MicroCore::~MicroCore()
    {
        delete &m_blockchain_storage.get_db();
    }

    bool
    init_blockchain(const string& path,
                    MicroCore& mcore,
                    Blockchain*& core_storage)
    {

        // initialize the core using the blockchain path
        if (!mcore.init(path))
        {
            cerr << "Error accessing blockchain." << endl;
            return false;
        }

        // get the high level Blockchain object to interact
        // with the blockchain lmdb database
        core_storage = &(mcore.get_core());

        return true;
    }

    string
    MicroCore::get_blkchain_path()
    {
        return blockchain_path;
    }

}
<commit_msg>NOLOCK set for lmdb database<commit_after>//
// Created by mwo on 5/11/15.
//

#include "MicroCore.h"

namespace xmreg
{
    /**
     * The constructor is interesting, as
     * m_mempool and m_blockchain_storage depend
     * on each other.
     *
     * So basically m_mempool is initialized with
     * reference to Blockchain (i.e., Blockchain&)
     * and m_blockchain_storage is initialized with
     * reference to m_mempool (i.e., tx_memory_pool&)
     *
     * The same is done in cryptonode::core.
     */
    MicroCore::MicroCore():
            m_mempool(m_blockchain_storage),
            m_blockchain_storage(m_mempool)
    {}

    /**
     * Initialized the MicroCore object.
     *
     * Create BlockchainLMDB on the heap.
     * Open database files located in blockchain_path.
     * Initialize m_blockchain_storage with the BlockchainLMDB object.
     */
    bool
    MicroCore::init(const string& _blockchain_path)
    {
        int db_flags = 0;

        blockchain_path = _blockchain_path;

        //db_flags |= MDB_RDONLY;
        db_flags |= MDB_NOLOCK;
        //db_flags |= MDB_SYNC;

        // uint64_t DEFAULT_FLAGS = MDB_NOMETASYNC | MDB_NORDAHEAD;

        //db_flags = DEFAULT_FLAGS;

        BlockchainDB* db = nullptr;
        db = new BlockchainLMDB();

        try
        {
            // try opening lmdb database files
            db->open(blockchain_path, db_flags);
        }
        catch (const std::exception& e)
        {
            cerr << "Error opening database: " << e.what();
            return false;
        }

        // check if the blockchain database
        // is successful opened
        if(!db->is_open())
        {
            return false;
        }

        // initialize Blockchain object to manage
        // the database.
        return m_blockchain_storage.init(db, false);
    }

    /**
    * Get m_blockchain_storage.
    * Initialize m_blockchain_storage with the BlockchainLMDB object.
    */
    Blockchain&
    MicroCore::get_core()
    {
        return m_blockchain_storage;
    }

    /**
     * Get block by its height
     *
     * returns true if success
     */
    bool
    MicroCore::get_block_by_height(const uint64_t& height, block& blk)
    {

        crypto::hash block_id;

        try
        {
            block_id = m_blockchain_storage.get_block_id_by_height(height);
        }
        catch (const exception& e)
        {
            cerr << e.what() << endl;
            return false;
        }

        if (!m_blockchain_storage.get_block_by_hash(block_id, blk))
        {
            cerr << "Block with hash " << block_id
                 << "and height " << height << " not found!"
                 << endl;
            return false;
        }

        return true;
    }

    /**
     * Get transaction tx from the blockchain using it hash
     */
    bool
    MicroCore::get_tx(const crypto::hash& tx_hash, transaction& tx)
    {
        try
        {
            // get transaction with given hash
            tx = m_blockchain_storage.get_db().get_tx(tx_hash);
        }
        catch (const exception& e)
        {
            cerr << e.what() << endl;
            return false;
        }

        return true;
    }

    bool
    MicroCore::get_tx(const string& tx_hash_str, transaction& tx)
    {

        // parse tx hash string to hash object
        crypto::hash tx_hash;

        if (!xmreg::parse_str_secret_key(tx_hash_str, tx_hash))
        {
            cerr << "Cant parse tx hash: " << tx_hash_str << endl;
            return false;
        }

        if (!get_tx(tx_hash, tx))
        {
            return false;
        }

        return true;
    }

    /**
     * Find output with given public key in a given transaction
     */
    bool
    MicroCore::find_output_in_tx(const transaction& tx,
                                 const public_key& output_pubkey,
                                 tx_out& out,
                                 size_t& output_index)
    {

        size_t idx {0};

        // search in the ouputs for an output which
        // public key matches to what we want
        auto it = std::find_if(tx.vout.begin(), tx.vout.end(),
                               [&](const tx_out& o)
                               {
                                   const txout_to_key& tx_in_to_key
                                           = boost::get<txout_to_key>(o.target);

                                   ++idx;

                                   return tx_in_to_key.key == output_pubkey;
                               });

        if (it != tx.vout.end())
        {
            // we found the desired public key
            out = *it;
            output_index = idx > 0 ? idx - 1 : idx;

            //cout << idx << " " << output_index << endl;

            return true;
        }

        return false;
    }

    /**
     * Returns tx hash in a given block which
     * contains given output's public key
     */
    bool
    MicroCore::get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
                                              const uint64_t& block_height,
                                              crypto::hash& tx_hash,
                                              cryptonote::transaction& tx_found)
    {

        tx_hash = null_hash;

        // get block of given height
        block blk;
        if (!get_block_by_height(block_height, blk))
        {
            cerr << "Cant get block of height: " << block_height << endl;
            return false;
        }

        // get all transactions in the block found
        // initialize the first list with transaction for solving
        // the block i.e. coinbase.
        list<transaction> txs {blk.miner_tx};
        list<crypto::hash> missed_txs;

        if (!m_blockchain_storage.get_transactions(blk.tx_hashes, txs, missed_txs))
        {
            cerr << "Cant find transcations in block: " << block_height << endl;
            return false;
        }

        if (!missed_txs.empty())
        {
            cerr << "Transactions not found in blk: " << block_height << endl;

            for (const crypto::hash& h : missed_txs)
            {
                cerr << " - tx hash: " << h << endl;
            }

            return false;
        }

        // search outputs in each transactions
        // until output with pubkey of interest is found
        for (const transaction& tx : txs)
        {

            tx_out found_out;

            // we dont need here output_index
            size_t output_index;

            if (find_output_in_tx(tx, output_pubkey, found_out, output_index))
            {
                // we found the desired public key
                tx_hash = get_transaction_hash(tx);
                tx_found = tx;

                return true;
            }

        }

        return false;
    }

    uint64_t
    MicroCore::get_blk_timestamp(uint64_t blk_height)
    {
        cryptonote::block blk;

        if (!get_block_by_height(blk_height, blk))
        {
            cerr << "Cant get block by height: " << blk_height << endl;
            return 0;
        }

        return blk.timestamp;
    }

    /**
     * De-initialized Blockchain.
     *
     * since blockchain is opened as MDB_RDONLY
     * need to manually free memory taken on heap
     * by BlockchainLMDB
     */
    MicroCore::~MicroCore()
    {
        delete &m_blockchain_storage.get_db();
    }

    bool
    init_blockchain(const string& path,
                    MicroCore& mcore,
                    Blockchain*& core_storage)
    {

        // initialize the core using the blockchain path
        if (!mcore.init(path))
        {
            cerr << "Error accessing blockchain." << endl;
            return false;
        }

        // get the high level Blockchain object to interact
        // with the blockchain lmdb database
        core_storage = &(mcore.get_core());

        return true;
    }

    string
    MicroCore::get_blkchain_path()
    {
        return blockchain_path;
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
// Distributed under the terms of the BSD license (see the LICENSE
// file for the exact terms).
// Email: hermes1d@googlegroups.com, home page: http://hpfem.org/

#include "matrix.h"

#include "python_api.h"

void solve_linear_system_numpy(CooMatrix *mat, double *res)
{
    if (import__hermes_common())
        throw std::runtime_error("hermes_common failed to import.");
    CSRMatrix M(mat);
    insert_object("m", c2py_CSRMatrix(&M));
    insert_object("rhs", c2numpy_double_inplace(res, mat->get_size()));
    cmd("A = m.to_scipy_csr().todense()");
    cmd("from numpy.linalg import solve");
    cmd("x = solve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(get_object("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
}

void solve_linear_system_scipy_umfpack(CooMatrix *mat, double *res)
{
    if (import__hermes_common())
        throw std::runtime_error("hermes_common failed to import.");
    CSCMatrix M(mat);
    insert_object("m", c2py_CSCMatrix(&M));
    insert_object("rhs", c2numpy_double_inplace(res, mat->get_size()));
    cmd("A = m.to_scipy_csc()");
    cmd("from scipy.sparse.linalg import spsolve");
    cmd("x = spsolve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(get_object("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
}

void solve_linear_system_scipy_cg(CooMatrix *mat, double *res)
{
    if (import__hermes_common())
        throw std::runtime_error("hermes_common failed to import.");
    CSRMatrix M(mat);
    insert_object("m", c2py_CSRMatrix(&M));
    insert_object("rhs", c2numpy_double_inplace(res, mat->get_size()));
    cmd("A = m.to_scipy_csr()");
    cmd("from scipy.sparse.linalg import cg");
    cmd("x, res = cg(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(get_object("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
}

void solve_linear_system_scipy_gmres(CooMatrix *mat, double *res)
{
    if (import__hermes_common())
        throw std::runtime_error("hermes_common failed to import.");
    CSRMatrix M(mat);
    insert_object("m", c2py_CSRMatrix(&M));
    insert_object("rhs", c2numpy_double_inplace(res, mat->get_size()));
    cmd("A = m.to_scipy_csr()");
    cmd("from scipy.sparse.linalg import gmres");
    cmd("x, res = gmres(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(get_object("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
}
<commit_msg>Use the Python() class in solvers<commit_after>// Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
// Distributed under the terms of the BSD license (see the LICENSE
// file for the exact terms).
// Email: hermes1d@googlegroups.com, home page: http://hpfem.org/

#include "matrix.h"

#include "python_api.h"

void solve_linear_system_numpy(CooMatrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr().todense()");
    p->exec("from numpy.linalg import solve");
    p->exec("x = solve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_umfpack(CooMatrix *mat, double *res)
{
    CSCMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSCMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csc()");
    p->exec("from scipy.sparse.linalg import spsolve");
    p->exec("x = spsolve(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_cg(CooMatrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import cg");
    p->exec("x, res = cg(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}

void solve_linear_system_scipy_gmres(CooMatrix *mat, double *res)
{
    CSRMatrix M(mat);
    Python *p = new Python();
    p->push("m", c2py_CSRMatrix(&M));
    p->push("rhs", c2numpy_double_inplace(res, mat->get_size()));
    p->exec("A = m.to_scipy_csr()");
    p->exec("from scipy.sparse.linalg import gmres");
    p->exec("x, res = gmres(A, rhs)");
    double *x;
    int n;
    numpy2c_double_inplace(p->pull("x"), &x, &n);
    memcpy(res, x, n*sizeof(double));
    delete p;
}
<|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/.
 */

// Try to instantiate as many implementations as possible.  Finds all
// implementations reachable via the service manager.  If a given implementation
// is the only implementor of some service that has a zero-parameter
// constructor, instantiate the implementation through that service name.  If a
// given implementation does not offer any such contructors (because it does not
// support any single-interface--based service, or because for each relevant
// service there are multiple implementations or it does not have an appropriate
// constructor) but does support at least one accumulation-based service, then
// instantiate it through its implementation name (a heuristic to identify
// instantiatable implementations that appears to work well).

#include <sal/config.h>

#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
#include <utility>
#include <vector>

#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
#include <com/sun/star/reflection/XServiceTypeDescription2.hpp>
#include <cppuhelper/exc_hlp.hxx>
#include <rtl/strbuf.hxx>
#include <test/bootstrapfixture.hxx>
#include <vcl/svapp.hxx>

namespace {

OString msg(OUString const & string) {
    return OUStringToOString(string, osl_getThreadTextEncoding());
}

OString msg(css::uno::Sequence<OUString> const & strings) {
    OStringBuffer buf("{");
    for (sal_Int32 i = 0; i != strings.getLength(); ++i) {
        if (i != 0) {
            buf.append(", ");
        }
        buf.append('"');
        buf.append(msg(strings[i]));
        buf.append('"');
    }
    buf.append('}');
    return buf.makeStringAndClear();
}

bool unique(css::uno::Sequence<OUString> const & strings) {
    // Assumes small sequences for which quadratic algorithm is acceptable:
    for (sal_Int32 i = 0; i < strings.getLength() - 1; ++i) {
        for (sal_Int32 j = i + 1; j != strings.getLength(); ++j) {
            if (strings[j] == strings[i]) {
                return false;
            }
        }
    }
    return true;
}

bool contains(
    css::uno::Sequence<OUString> const & strings, OUString const & string)
{
    for (sal_Int32 i = 0; i != strings.getLength(); ++i) {
        if (string == strings[i]) {
            return true;
        }
    }
    return false;
}

bool contains(
    css::uno::Sequence<OUString> const & strings1,
    css::uno::Sequence<OUString> const & strings2)
{
    // Assumes small sequences for which quadratic algorithm is acceptable:
    for (sal_Int32 i = 0; i != strings2.getLength(); ++i) {
        if (!contains(strings1, strings2[i])) {
            return false;
        }
    }
    return true;
}

class Test: public test::BootstrapFixture {
public:
    void test();

    CPPUNIT_TEST_SUITE(Test);
    CPPUNIT_TEST(test);
    CPPUNIT_TEST_SUITE_END();

private:
    void createInstance(
        OUString const & name, bool withArguments,
        OUString const & implementationName,
        css::uno::Sequence<OUString> const & serviceNames,
        std::vector<css::uno::Reference<css::lang::XComponent>> * components);
};

void Test::test() {
    // On Windows, blacklist the com.sun.star.comp.report.OReportDefinition
    // implementation (reportdesign::OReportDefinition in
    // reportdesign/source/core/api/ReportDefinition.cxx), as it spawns a thread
    // that forever blocks in SendMessageW when no VCL event loop is running
    // (reportdesign::<anon>::FactoryLoader::execute ->
    // framework::Desktop::findFrame -> framework::TaskCreator::createTask ->
    // <anon>::TaskCreatorService::createInstanceWithArguments ->
    // <anon>::TaskCreatorService::impls_createContainerWindow ->
    // <anon>::VCLXToolkit::createWindow ->
    // <anon>::VCLXToolkit::ImplCreateWindow ->
    // <anon>::VCLXToolkit::ImplCreateWindow -> WorkWindow::WorkWindow ->
    // WorkWindow::ImplInit -> ImplBorderWindow::ImplBorderWindow ->
    // ImplBorderWindow::ImplInit -> Window::ImplInit ->
    // WinSalInstance::CreateFrame -> ImplSendMessage -> SendMessageW):
    std::vector<OUString> blacklist;
    blacklist.push_back("com.sun.star.comp.report.OReportDefinition");

    // <https://bugs.documentfoundation.org/show_bug.cgi?id=89343>
    // "~SwXMailMerge() goes into endless SwCache::Check()":
    blacklist.push_back("SwXMailMerge");

    css::uno::Reference<css::container::XContentEnumerationAccess> enumAcc(
        m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
    css::uno::Reference<css::container::XHierarchicalNameAccess> typeMgr(
        m_xContext->getValueByName(
            "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
        css::uno::UNO_QUERY_THROW);
    css::uno::Sequence<OUString> serviceNames(
        m_xContext->getServiceManager()->getAvailableServiceNames());
    struct Constructor {
        Constructor(
            OUString const & theServiceName, bool theDefaultConstructor):
            serviceName(theServiceName),
            defaultConstructor(theDefaultConstructor)
        {}
        Constructor(Constructor const &other):
            serviceName(other.serviceName),
            defaultConstructor(other.defaultConstructor)
        {}
        OUString serviceName;
        bool defaultConstructor;
    };
    struct Implementation {
        Implementation(
            css::uno::Reference<css::lang::XServiceInfo> const & theFactory,
            css::uno::Sequence<OUString> const & theServiceNames):
            factory(theFactory), serviceNames(theServiceNames),
            accumulationBased(false)
        {}
        css::uno::Reference<css::lang::XServiceInfo> const factory;
        css::uno::Sequence<OUString> const serviceNames;
        std::vector<Constructor> constructors;
        bool accumulationBased;
    };
    std::map<OUString, Implementation> impls;
    for (sal_Int32 i = 0; i != serviceNames.getLength(); ++i) {
        css::uno::Reference<css::container::XEnumeration> serviceImpls1(
            enumAcc->createContentEnumeration(serviceNames[i]),
            css::uno::UNO_SET_THROW);
        std::vector<css::uno::Reference<css::lang::XServiceInfo>> serviceImpls2;
        while (serviceImpls1->hasMoreElements()) {
            serviceImpls2.push_back(
                css::uno::Reference<css::lang::XServiceInfo>(
                    serviceImpls1->nextElement(), css::uno::UNO_QUERY_THROW));
        }
        css::uno::Reference<css::reflection::XServiceTypeDescription2> desc;
        if (typeMgr->hasByHierarchicalName(serviceNames[i])) {
            desc.set(
                typeMgr->getByHierarchicalName(serviceNames[i]),
                css::uno::UNO_QUERY_THROW);
        }
        if (serviceImpls2.empty()) {
            if (desc.is()) {
                CPPUNIT_ASSERT_MESSAGE(
                    (OString(
                        "no implementations of single-interface--based \""
                        + msg(serviceNames[i]) + "\"")
                     .getStr()),
                    !desc->isSingleInterfaceBased());
                std::cout
                    << "accumulation-based service \"" << serviceNames[i]
                    << "\" without implementations\n";
            } else {
                std::cout
                    << "fantasy service name \"" << serviceNames[i]
                    << "\" without implementations\n";
            }
        } else {
            for (auto const & j: serviceImpls2) {
                OUString name(j->getImplementationName());
                auto k = impls.find(name);
                if (k == impls.end()) {
                    css::uno::Sequence<OUString> servs(
                        j->getSupportedServiceNames());
                    CPPUNIT_ASSERT_MESSAGE(
                        (OString(
                            "implementation \"" + msg(name)
                            + "\" supports non-unique " + msg(servs))
                         .getStr()),
                        unique(servs));
                    k = impls.insert(
                            std::make_pair(name, Implementation(j, servs)))
                        .first;
                } else {
                    CPPUNIT_ASSERT_MESSAGE(
                        (OString(
                            "multiple implementations named \"" + msg(name)
                            + "\"")
                         .getStr()),
                        j == k->second.factory);
                }
                CPPUNIT_ASSERT_MESSAGE(
                    (OString(
                        "implementation \"" + msg(name) + "\" supports "
                        + msg(k->second.serviceNames) + " but not \""
                        + msg(serviceNames[i]) + "\"")
                     .getStr()),
                    contains(k->second.serviceNames, serviceNames[i]));
                if (desc.is()) {
                    if (desc->isSingleInterfaceBased()) {
                        if (serviceImpls2.size() == 1) {
                            css::uno::Sequence<
                                css::uno::Reference<
                                    css::reflection::XServiceConstructorDescription>>
                                        ctors(desc->getConstructors());
                            for (sal_Int32 l = 0; l != ctors.getLength(); ++l) {
                                if (!ctors[l]->getParameters().hasElements()) {
                                    k->second.constructors.push_back(
                                        Constructor(
                                            serviceNames[i],
                                            ctors[l]->isDefaultConstructor()));
                                    break;
                                }
                            }
                        }
                    } else {
                        k->second.accumulationBased = true;
                    }
                } else {
                    std::cout
                        << "implementation \"" << name
                        << "\" supports fantasy service name \""
                        << serviceNames[i] << "\"\n";
                }
            }
        }
    }
    std::vector<css::uno::Reference<css::lang::XComponent>> comps;
    for (auto const & i: impls) {
        if (std::find(blacklist.begin(), blacklist.end(), i.first)
            == blacklist.end())
        {
            if (i.second.constructors.empty()) {
                if (i.second.accumulationBased) {
                    createInstance(
                        i.first, false, i.first, i.second.serviceNames, &comps);
                } else {
                    std::cout
                        << "no obvious way to instantiate implementation \""
                        << i.first << "\"\n";
                }
            } else {
                for (auto const & j: i.second.constructors) {
                    createInstance(
                        j.serviceName, !j.defaultConstructor, i.first,
                        i.second.serviceNames, &comps);
                }
            }
        }
    }
    SolarMutexReleaser rel;
    for (auto const & i: comps) {
        i->dispose();
    }
}

void Test::createInstance(
    OUString const & name, bool withArguments,
    OUString const & implementationName,
    css::uno::Sequence<OUString> const & serviceNames,
    std::vector<css::uno::Reference<css::lang::XComponent>> * components)
{
    assert(components != nullptr);
    css::uno::Reference<css::uno::XInterface> inst;
    try {
        if (withArguments) {
            inst = m_xContext->getServiceManager()
                ->createInstanceWithArgumentsAndContext(
                    name, css::uno::Sequence<css::uno::Any>(), m_xContext);
        } else {
            inst = m_xContext->getServiceManager()->createInstanceWithContext(
                name, m_xContext);
        }
    } catch (css::uno::Exception & e) {
        css::uno::Any a(cppu::getCaughtException());
        CPPUNIT_FAIL(
            OString(
                "instantiating \"" + msg(implementationName) + "\" via \""
                + msg(name) + "\"  caused " + msg(a.getValueTypeName()) + " \""
                + msg(e.Message) + "\"")
            .getStr());
    }
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" returned null reference")
         .getStr()),
        inst.is());
    css::uno::Reference<css::lang::XComponent> comp(inst, css::uno::UNO_QUERY);
    if (comp.is()) {
        components->push_back(comp);
    }
    css::uno::Reference<css::lang::XServiceInfo> info(
        inst, css::uno::UNO_QUERY);
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" does not provide XServiceInfo")
         .getStr()),
        info.is());
    OUString expImpl(implementationName);
    css::uno::Sequence<OUString> expServs(serviceNames);
    // Special cases:
    if (name == "com.sun.star.comp.configuration.ConfigurationProvider") {
        // Instantiating a ConfigurationProvider with no or empty args must
        // return theDefaultProvider:
        expImpl = "com.sun.star.comp.configuration.DefaultProvider";
        expServs = {"com.sun.star.configuration.DefaultProvider"};
    } else if (name == "com.sun.star.datatransfer.clipboard.SystemClipboard") {
        // SystemClipboard is a wrapper returning either a platform-specific or
        // the generic VCLGenericClipboard:
#if defined WNT
        expImpl = "com.sun.star.datatransfer.clipboard.ClipboardW32";
#else
        expImpl = "com.sun.star.datatransfer.VCLGenericClipboard";
#endif
#if !defined WNT
    } else if (name == "com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"
               || name == "com.sun.star.datatransfer.dnd.XdndSupport")
    {
        expImpl = "com.sun.star.datatransfer.dnd.VclGenericDragSource";
        expServs = {"com.sun.star.datatransfer.dnd.GenericDragSource"};
    } else if (name == "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"
               || name == "com.sun.star.datatransfer.dnd.XdndDropTarget")
    {
        expImpl = "com.sun.star.datatransfer.dnd.VclGenericDropTarget";
        expServs = {"com.sun.star.datatransfer.dnd.GenericDropTarget"};
#endif
    } else if (name == "com.sun.star.ui.dialogs.FolderPicker") {
        // FolderPicker is a wrapper returning either a platform-specific or the
        // generic OfficeFolderPicker:
#if defined WNT
        expImpl = "com.sun.star.ui.dialogs.Win32FolderPicker";
        expServs = {"com.sun.star.ui.dialogs.SystemFolderPicker"};
#else
        expImpl = "com.sun.star.svtools.OfficeFolderPicker";
        expServs = {"com.sun.star.ui.dialogs.OfficeFolderPicker"};
#endif
    }
    CPPUNIT_ASSERT_EQUAL_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports wrong implementation name")
         .getStr()),
        expImpl, info->getImplementationName());
    css::uno::Sequence<OUString> servs(info->getSupportedServiceNames());
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports non-unique " + msg(servs))
         .getStr()),
        unique(servs));
    // Some implementations like "com.sun.star.comp.Calc.SpreadsheetDocument"
    // report sub-services like
    // "com.sun.star.sheet.SpreadsheetDocumentSettings", and
    // "com.sun.star.document.OfficeDocument" that are not listed in the
    // .component file, so check for containment instead of equality:
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports " + msg(servs) + " different from "
            + msg(expServs))
         .getStr()),
        contains(servs, expServs));
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Revert "give this a copy ctor"<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/.
 */

// Try to instantiate as many implementations as possible.  Finds all
// implementations reachable via the service manager.  If a given implementation
// is the only implementor of some service that has a zero-parameter
// constructor, instantiate the implementation through that service name.  If a
// given implementation does not offer any such contructors (because it does not
// support any single-interface--based service, or because for each relevant
// service there are multiple implementations or it does not have an appropriate
// constructor) but does support at least one accumulation-based service, then
// instantiate it through its implementation name (a heuristic to identify
// instantiatable implementations that appears to work well).

#include <sal/config.h>

#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
#include <utility>
#include <vector>

#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
#include <com/sun/star/reflection/XServiceTypeDescription2.hpp>
#include <cppuhelper/exc_hlp.hxx>
#include <rtl/strbuf.hxx>
#include <test/bootstrapfixture.hxx>
#include <vcl/svapp.hxx>

namespace {

OString msg(OUString const & string) {
    return OUStringToOString(string, osl_getThreadTextEncoding());
}

OString msg(css::uno::Sequence<OUString> const & strings) {
    OStringBuffer buf("{");
    for (sal_Int32 i = 0; i != strings.getLength(); ++i) {
        if (i != 0) {
            buf.append(", ");
        }
        buf.append('"');
        buf.append(msg(strings[i]));
        buf.append('"');
    }
    buf.append('}');
    return buf.makeStringAndClear();
}

bool unique(css::uno::Sequence<OUString> const & strings) {
    // Assumes small sequences for which quadratic algorithm is acceptable:
    for (sal_Int32 i = 0; i < strings.getLength() - 1; ++i) {
        for (sal_Int32 j = i + 1; j != strings.getLength(); ++j) {
            if (strings[j] == strings[i]) {
                return false;
            }
        }
    }
    return true;
}

bool contains(
    css::uno::Sequence<OUString> const & strings, OUString const & string)
{
    for (sal_Int32 i = 0; i != strings.getLength(); ++i) {
        if (string == strings[i]) {
            return true;
        }
    }
    return false;
}

bool contains(
    css::uno::Sequence<OUString> const & strings1,
    css::uno::Sequence<OUString> const & strings2)
{
    // Assumes small sequences for which quadratic algorithm is acceptable:
    for (sal_Int32 i = 0; i != strings2.getLength(); ++i) {
        if (!contains(strings1, strings2[i])) {
            return false;
        }
    }
    return true;
}

class Test: public test::BootstrapFixture {
public:
    void test();

    CPPUNIT_TEST_SUITE(Test);
    CPPUNIT_TEST(test);
    CPPUNIT_TEST_SUITE_END();

private:
    void createInstance(
        OUString const & name, bool withArguments,
        OUString const & implementationName,
        css::uno::Sequence<OUString> const & serviceNames,
        std::vector<css::uno::Reference<css::lang::XComponent>> * components);
};

void Test::test() {
    // On Windows, blacklist the com.sun.star.comp.report.OReportDefinition
    // implementation (reportdesign::OReportDefinition in
    // reportdesign/source/core/api/ReportDefinition.cxx), as it spawns a thread
    // that forever blocks in SendMessageW when no VCL event loop is running
    // (reportdesign::<anon>::FactoryLoader::execute ->
    // framework::Desktop::findFrame -> framework::TaskCreator::createTask ->
    // <anon>::TaskCreatorService::createInstanceWithArguments ->
    // <anon>::TaskCreatorService::impls_createContainerWindow ->
    // <anon>::VCLXToolkit::createWindow ->
    // <anon>::VCLXToolkit::ImplCreateWindow ->
    // <anon>::VCLXToolkit::ImplCreateWindow -> WorkWindow::WorkWindow ->
    // WorkWindow::ImplInit -> ImplBorderWindow::ImplBorderWindow ->
    // ImplBorderWindow::ImplInit -> Window::ImplInit ->
    // WinSalInstance::CreateFrame -> ImplSendMessage -> SendMessageW):
    std::vector<OUString> blacklist;
    blacklist.push_back("com.sun.star.comp.report.OReportDefinition");

    // <https://bugs.documentfoundation.org/show_bug.cgi?id=89343>
    // "~SwXMailMerge() goes into endless SwCache::Check()":
    blacklist.push_back("SwXMailMerge");

    css::uno::Reference<css::container::XContentEnumerationAccess> enumAcc(
        m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
    css::uno::Reference<css::container::XHierarchicalNameAccess> typeMgr(
        m_xContext->getValueByName(
            "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
        css::uno::UNO_QUERY_THROW);
    css::uno::Sequence<OUString> serviceNames(
        m_xContext->getServiceManager()->getAvailableServiceNames());
    struct Constructor {
        Constructor(
            OUString const & theServiceName, bool theDefaultConstructor):
            serviceName(theServiceName),
            defaultConstructor(theDefaultConstructor)
        {}
        OUString serviceName;
        bool defaultConstructor;
    };
    struct Implementation {
        Implementation(
            css::uno::Reference<css::lang::XServiceInfo> const & theFactory,
            css::uno::Sequence<OUString> const & theServiceNames):
            factory(theFactory), serviceNames(theServiceNames),
            accumulationBased(false)
        {}
        css::uno::Reference<css::lang::XServiceInfo> const factory;
        css::uno::Sequence<OUString> const serviceNames;
        std::vector<Constructor> constructors;
        bool accumulationBased;
    };
    std::map<OUString, Implementation> impls;
    for (sal_Int32 i = 0; i != serviceNames.getLength(); ++i) {
        css::uno::Reference<css::container::XEnumeration> serviceImpls1(
            enumAcc->createContentEnumeration(serviceNames[i]),
            css::uno::UNO_SET_THROW);
        std::vector<css::uno::Reference<css::lang::XServiceInfo>> serviceImpls2;
        while (serviceImpls1->hasMoreElements()) {
            serviceImpls2.push_back(
                css::uno::Reference<css::lang::XServiceInfo>(
                    serviceImpls1->nextElement(), css::uno::UNO_QUERY_THROW));
        }
        css::uno::Reference<css::reflection::XServiceTypeDescription2> desc;
        if (typeMgr->hasByHierarchicalName(serviceNames[i])) {
            desc.set(
                typeMgr->getByHierarchicalName(serviceNames[i]),
                css::uno::UNO_QUERY_THROW);
        }
        if (serviceImpls2.empty()) {
            if (desc.is()) {
                CPPUNIT_ASSERT_MESSAGE(
                    (OString(
                        "no implementations of single-interface--based \""
                        + msg(serviceNames[i]) + "\"")
                     .getStr()),
                    !desc->isSingleInterfaceBased());
                std::cout
                    << "accumulation-based service \"" << serviceNames[i]
                    << "\" without implementations\n";
            } else {
                std::cout
                    << "fantasy service name \"" << serviceNames[i]
                    << "\" without implementations\n";
            }
        } else {
            for (auto const & j: serviceImpls2) {
                OUString name(j->getImplementationName());
                auto k = impls.find(name);
                if (k == impls.end()) {
                    css::uno::Sequence<OUString> servs(
                        j->getSupportedServiceNames());
                    CPPUNIT_ASSERT_MESSAGE(
                        (OString(
                            "implementation \"" + msg(name)
                            + "\" supports non-unique " + msg(servs))
                         .getStr()),
                        unique(servs));
                    k = impls.insert(
                            std::make_pair(name, Implementation(j, servs)))
                        .first;
                } else {
                    CPPUNIT_ASSERT_MESSAGE(
                        (OString(
                            "multiple implementations named \"" + msg(name)
                            + "\"")
                         .getStr()),
                        j == k->second.factory);
                }
                CPPUNIT_ASSERT_MESSAGE(
                    (OString(
                        "implementation \"" + msg(name) + "\" supports "
                        + msg(k->second.serviceNames) + " but not \""
                        + msg(serviceNames[i]) + "\"")
                     .getStr()),
                    contains(k->second.serviceNames, serviceNames[i]));
                if (desc.is()) {
                    if (desc->isSingleInterfaceBased()) {
                        if (serviceImpls2.size() == 1) {
                            css::uno::Sequence<
                                css::uno::Reference<
                                    css::reflection::XServiceConstructorDescription>>
                                        ctors(desc->getConstructors());
                            for (sal_Int32 l = 0; l != ctors.getLength(); ++l) {
                                if (!ctors[l]->getParameters().hasElements()) {
                                    k->second.constructors.push_back(
                                        Constructor(
                                            serviceNames[i],
                                            ctors[l]->isDefaultConstructor()));
                                    break;
                                }
                            }
                        }
                    } else {
                        k->second.accumulationBased = true;
                    }
                } else {
                    std::cout
                        << "implementation \"" << name
                        << "\" supports fantasy service name \""
                        << serviceNames[i] << "\"\n";
                }
            }
        }
    }
    std::vector<css::uno::Reference<css::lang::XComponent>> comps;
    for (auto const & i: impls) {
        if (std::find(blacklist.begin(), blacklist.end(), i.first)
            == blacklist.end())
        {
            if (i.second.constructors.empty()) {
                if (i.second.accumulationBased) {
                    createInstance(
                        i.first, false, i.first, i.second.serviceNames, &comps);
                } else {
                    std::cout
                        << "no obvious way to instantiate implementation \""
                        << i.first << "\"\n";
                }
            } else {
                for (auto const & j: i.second.constructors) {
                    createInstance(
                        j.serviceName, !j.defaultConstructor, i.first,
                        i.second.serviceNames, &comps);
                }
            }
        }
    }
    SolarMutexReleaser rel;
    for (auto const & i: comps) {
        i->dispose();
    }
}

void Test::createInstance(
    OUString const & name, bool withArguments,
    OUString const & implementationName,
    css::uno::Sequence<OUString> const & serviceNames,
    std::vector<css::uno::Reference<css::lang::XComponent>> * components)
{
    assert(components != nullptr);
    css::uno::Reference<css::uno::XInterface> inst;
    try {
        if (withArguments) {
            inst = m_xContext->getServiceManager()
                ->createInstanceWithArgumentsAndContext(
                    name, css::uno::Sequence<css::uno::Any>(), m_xContext);
        } else {
            inst = m_xContext->getServiceManager()->createInstanceWithContext(
                name, m_xContext);
        }
    } catch (css::uno::Exception & e) {
        css::uno::Any a(cppu::getCaughtException());
        CPPUNIT_FAIL(
            OString(
                "instantiating \"" + msg(implementationName) + "\" via \""
                + msg(name) + "\"  caused " + msg(a.getValueTypeName()) + " \""
                + msg(e.Message) + "\"")
            .getStr());
    }
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" returned null reference")
         .getStr()),
        inst.is());
    css::uno::Reference<css::lang::XComponent> comp(inst, css::uno::UNO_QUERY);
    if (comp.is()) {
        components->push_back(comp);
    }
    css::uno::Reference<css::lang::XServiceInfo> info(
        inst, css::uno::UNO_QUERY);
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" does not provide XServiceInfo")
         .getStr()),
        info.is());
    OUString expImpl(implementationName);
    css::uno::Sequence<OUString> expServs(serviceNames);
    // Special cases:
    if (name == "com.sun.star.comp.configuration.ConfigurationProvider") {
        // Instantiating a ConfigurationProvider with no or empty args must
        // return theDefaultProvider:
        expImpl = "com.sun.star.comp.configuration.DefaultProvider";
        expServs = {"com.sun.star.configuration.DefaultProvider"};
    } else if (name == "com.sun.star.datatransfer.clipboard.SystemClipboard") {
        // SystemClipboard is a wrapper returning either a platform-specific or
        // the generic VCLGenericClipboard:
#if defined WNT
        expImpl = "com.sun.star.datatransfer.clipboard.ClipboardW32";
#else
        expImpl = "com.sun.star.datatransfer.VCLGenericClipboard";
#endif
#if !defined WNT
    } else if (name == "com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"
               || name == "com.sun.star.datatransfer.dnd.XdndSupport")
    {
        expImpl = "com.sun.star.datatransfer.dnd.VclGenericDragSource";
        expServs = {"com.sun.star.datatransfer.dnd.GenericDragSource"};
    } else if (name == "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"
               || name == "com.sun.star.datatransfer.dnd.XdndDropTarget")
    {
        expImpl = "com.sun.star.datatransfer.dnd.VclGenericDropTarget";
        expServs = {"com.sun.star.datatransfer.dnd.GenericDropTarget"};
#endif
    } else if (name == "com.sun.star.ui.dialogs.FolderPicker") {
        // FolderPicker is a wrapper returning either a platform-specific or the
        // generic OfficeFolderPicker:
#if defined WNT
        expImpl = "com.sun.star.ui.dialogs.Win32FolderPicker";
        expServs = {"com.sun.star.ui.dialogs.SystemFolderPicker"};
#else
        expImpl = "com.sun.star.svtools.OfficeFolderPicker";
        expServs = {"com.sun.star.ui.dialogs.OfficeFolderPicker"};
#endif
    }
    CPPUNIT_ASSERT_EQUAL_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports wrong implementation name")
         .getStr()),
        expImpl, info->getImplementationName());
    css::uno::Sequence<OUString> servs(info->getSupportedServiceNames());
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports non-unique " + msg(servs))
         .getStr()),
        unique(servs));
    // Some implementations like "com.sun.star.comp.Calc.SpreadsheetDocument"
    // report sub-services like
    // "com.sun.star.sheet.SpreadsheetDocumentSettings", and
    // "com.sun.star.document.OfficeDocument" that are not listed in the
    // .component file, so check for containment instead of equality:
    CPPUNIT_ASSERT_MESSAGE(
        (OString(
            "instantiating \"" + msg(implementationName) + "\" via \""
            + msg(name) + "\" reports " + msg(servs) + " different from "
            + msg(expServs))
         .getStr()),
        contains(servs, expServs));
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

}

CPPUNIT_PLUGIN_IMPLEMENT();

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


<commit_before>#ifndef ASTI_INTEGRATE1D_HPP
#define ASTI_INTEGRATE1D_HPP
#include <type_traits>
/*
  gl[n_, x_] := Solve[LegendreP[n, x] == 0];
  gldash[n_, a] := D[LegendreP[n, x], x] /. x -> a;
  weights[n_, x_] := 2/((1 - x^2) gldash[n, x]^2);
*/

/*
  Gauss-Legendre n-points quadrature, The method is exact for a
  polynomial of degree <=2n-1 in exact arithmetic
*/

template <int n>
struct gl_points_weights{};

template<>
struct gl_points_weights < 2 > {/* n = 2 */
    static const double points[];
    static const double weights[];
};

template <>
struct gl_points_weights < 4 > {/* n = 4 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 8 > {/* n = 8 */
    static const double points[] ;
    static const double weights[] ;
};
template <>
struct gl_points_weights < 16 > {/* n = 16 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 32 > {/* n = 32 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 64 > {/* n = 64 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 128 > {/* n = 128 */ ;
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 256 > {/* n = 256 */
    static const double points[] ;
    static const double weights[] ;
};

template<>
struct  gl_points_weights < 512 > /* n = 512 */ {
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 1024 > {/* n = 1024 */
    static const double points[] ;
    static const double weights[] ;
};

template <class Fn, int n>
double integrate1d(Fn f, std::integral_constant < int, n >,
                   double a,
                   double b)
{
    const double* points = gl_points_weights < n >::points;
    const double* w = gl_points_weights < n >::weights;

    size_t m = n>>1;

    double ga =  0.5 * (b - a);
    double mn =  0.5 * (b + a);

    auto auxf =  [ & f,& ga,& mn](double d) -> double {
        auto gad = ga * d;
        return f(mn + gad) + f(mn - gad);
    };

    double s = 0.0;
    for(size_t i = 0;i < m; ++i)
    {
        s += w[i] * auxf(points[i]);
    }
    return ga*s;
}

template <class Fn>
double integral(Fn speed, double t0, double t1)
{
    double lastlen = 0;
    double arclen = integrate1d(speed,
                                std::integral_constant < int, 8 >(),
                                t0, t1);
    int n = 8;
    while(tol::neq(lastlen, arclen))
    {
        lastlen = arclen;
        switch(n)
        {
        case 8:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 16>(),
                                 t0, t1);
            n = 16;
            break;
        case 16:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 32>(),
                                 t0, t1);
            n = 32;
            break;
        case 32:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 64>(),
                                 t0, t1);
            n = 64;
            break;
        case 64:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 128>(),
                                 t0, t1);
            n = 128;
            break;
        case 128:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 256>(),
                                 t0, t1);
            n = 256;
            break;
        case 256:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 512>(),
                                 t0, t1);
            n = 512;
            break;
        case 512:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 1024>(),
                                 t0, t1);
            n = 1024;
            break;
        case 1024:
            break;
        }
    }
    return arclen;
}

#endif // ASTI_INTEGRATE1D_HPP
<commit_msg>Update integrate1d.hpp<commit_after>#ifndef ASTI_INTEGRATE1D_HPP
#define ASTI_INTEGRATE1D_HPP
#include <type_traits>
#include <stdlib.h>
/*
  gl[n_, x_] := Solve[LegendreP[n, x] == 0];
  gldash[n_, a] := D[LegendreP[n, x], x] /. x -> a;
  weights[n_, x_] := 2/((1 - x^2) gldash[n, x]^2);
*/

/*
  Gauss-Legendre n-points quadrature, The method is exact for a
  polynomial of degree <=2n-1 in exact arithmetic
*/

template <int n>
struct gl_points_weights{};

template<>
struct gl_points_weights < 2 > {/* n = 2 */
    static const double points[];
    static const double weights[];
};

template <>
struct gl_points_weights < 4 > {/* n = 4 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 8 > {/* n = 8 */
    static const double points[] ;
    static const double weights[] ;
};
template <>
struct gl_points_weights < 16 > {/* n = 16 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 32 > {/* n = 32 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 64 > {/* n = 64 */
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 128 > {/* n = 128 */ ;
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 256 > {/* n = 256 */
    static const double points[] ;
    static const double weights[] ;
};

template<>
struct  gl_points_weights < 512 > /* n = 512 */ {
    static const double points[] ;
    static const double weights[] ;
};

template <>
struct gl_points_weights < 1024 > {/* n = 1024 */
    static const double points[] ;
    static const double weights[] ;
};

template <class Fn, int n>
double integrate1d(Fn f, std::integral_constant < int, n >,
                   double a,
                   double b)
{
    const double* points = gl_points_weights < n >::points;
    const double* w = gl_points_weights < n >::weights;

    size_t m = n>>1;

    double ga =  0.5 * (b - a);
    double mn =  0.5 * (b + a);

    auto auxf =  [ & f,& ga,& mn](double d) -> double {
        auto gad = ga * d;
        return f(mn + gad) + f(mn - gad);
    };

    double s = 0.0;
    for(size_t i = 0;i < m; ++i)
    {
        s += w[i] * auxf(points[i]);
    }
    return ga*s;
}

template <class Fn>
double integral(Fn speed, double t0, double t1)
{
    double lastlen = 0;
    double arclen = integrate1d(speed,
                                std::integral_constant < int, 8 >(),
                                t0, t1);
    int n = 8;
    while(tol::neq(lastlen, arclen))
    {
        lastlen = arclen;
        switch(n)
        {
        case 8:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 16>(),
                                 t0, t1);
            n = 16;
            break;
        case 16:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 32>(),
                                 t0, t1);
            n = 32;
            break;
        case 32:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 64>(),
                                 t0, t1);
            n = 64;
            break;
        case 64:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 128>(),
                                 t0, t1);
            n = 128;
            break;
        case 128:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 256>(),
                                 t0, t1);
            n = 256;
            break;
        case 256:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 512>(),
                                 t0, t1);
            n = 512;
            break;
        case 512:
            arclen = integrate1d(speed,
                                 std::integral_constant < int, 1024>(),
                                 t0, t1);
            n = 1024;
            break;
        case 1024:
            break;
        }
    }
    return arclen;
}

#endif // ASTI_INTEGRATE1D_HPP
<|endoftext|>


<commit_before>// Network API based on boost::asio
#ifndef LIBPORT_ASIO_HH
# define LIBPORT_ASIO_HH

# include <iostream>
# include <boost/asio.hpp>
#ifndef LIBPORT_NO_SSL
# include <boost/asio/ssl.hpp>
#endif
# include <boost/function.hpp>

# include <libport/destructible.hh>
# include <libport/finally.hh>

namespace libport
{
  class AsioDestructible: public Destructible
  {
    protected:
      virtual void doDestroy();
  };
  /** BaseSocket class.
   *
   * This class has a callback-based API: onReadFunc() and onErrorFunc().
   */
  class BaseSocket: public AsioDestructible
  {
    public:
      virtual ~BaseSocket(){}
      libport::Finally deletor;
      /// Write data asynchronously to the socket.
      virtual void write(const void* data, unsigned int length) = 0;
      /// Alias on write() for API compatibility.
      inline void send(void* addr, int len) {write((const void*)addr, len);}
      /// Alias on close() for API compatibility.
      inline void disconnect() {close();}
      /// Return if the socket is connected to a remote host.
      virtual bool isConnected() = 0;
      /// Disconnect the socket from the remote host.
      virtual void close() = 0;
      /// Callback function called each time new data is available.
      boost::function1<bool, boost::asio::streambuf&> onReadFunc;
      /// Callback function called in case of error on the socket.
      boost::function1<void, boost::system::error_code> onErrorFunc;
  };

  /** Socket class with a higher API.
   *
   */
  class Socket: public AsioDestructible
  {
    public:
      virtual ~Socket();
      /** Set underlying BaseSocket object, setup its callbacks to call our virtual functions.
       */
      virtual void setBase(BaseSocket*);

      /** Called each time new data is received.
       *   \return the number of bytes used in buffer. The remaining data will
       *   be passed again to this function as soon as at least an extra byte
       *   is available.
       */
      virtual int onRead(const void*, int length){return length;}

      /** Called in case of error on the socket.
      */
      virtual void onError(boost::system::error_code){}

      /// Ask for the asynchronous destruction of this object.
      virtual void destroy();

      inline void write(const void* data, unsigned int length)
      { base_->write(data, length);}
      /// Alias on write() for API compatibility.
      inline void send(void* addr, int len) {write((const void*)addr, len);}
      inline void close() {base_->close();}
      inline bool isConnected() {return base_->isConnected();}

      boost::system::error_code connect(const std::string& host,
	  const std::string& port, bool udp=false);

      typedef void* Handle;
      typedef boost::function0<Socket*> SocketFactory;

      static Handle listen(SocketFactory f, const std::string& host,
	  const std::string& port, boost::system::error_code & erc,
          bool udp = false);

      static Handle listenSSL(SocketFactory f, const std::string& host,
	  const std::string&  port,
	  boost::system::error_code& erc,
	  boost::asio::ssl::context_base::method ctx
	    = boost::asio::ssl::context::sslv23_server,
	  boost::asio::ssl::context::options options
	    = boost::asio::ssl::context::verify_none,
	  const std::string& privateKeyFile = "",
	  const std::string& certChainFile = "",
	  const std::string& tmpDHFile = "" ,
	  const std::string& cipherList = "");

    protected:
      bool onRead_(boost::asio::streambuf&);
      std::string buffer;
      BaseSocket* base_;
    private:
    template<typename Proto, typename BaseFactory> static boost::system::error_code
      listenProto(SocketFactory f, const std::string& host,
	  const std::string&port, BaseFactory bf);
    template<typename Proto, typename BaseFactory> boost::system::error_code
      connectProto(const std::string& host, const std::string& port, BaseFactory bf);
  };

}

# include "libport/asio.hxx"

#endif
<commit_msg>Fix a segv when calling isConnected on an uninitialized socket.<commit_after>// Network API based on boost::asio
#ifndef LIBPORT_ASIO_HH
# define LIBPORT_ASIO_HH

# include <iostream>
# include <boost/asio.hpp>
#ifndef LIBPORT_NO_SSL
# include <boost/asio/ssl.hpp>
#endif
# include <boost/function.hpp>

# include <libport/destructible.hh>
# include <libport/finally.hh>

namespace libport
{
  class AsioDestructible: public Destructible
  {
    protected:
      virtual void doDestroy();
  };
  /** BaseSocket class.
   *
   * This class has a callback-based API: onReadFunc() and onErrorFunc().
   */
  class BaseSocket: public AsioDestructible
  {
    public:
      virtual ~BaseSocket(){}
      libport::Finally deletor;
      /// Write data asynchronously to the socket.
      virtual void write(const void* data, unsigned int length) = 0;
      /// Alias on write() for API compatibility.
      inline void send(void* addr, int len) {write((const void*)addr, len);}
      /// Alias on close() for API compatibility.
      inline void disconnect() {close();}
      /// Return if the socket is connected to a remote host.
      virtual bool isConnected() = 0;
      /// Disconnect the socket from the remote host.
      virtual void close() = 0;
      /// Callback function called each time new data is available.
      boost::function1<bool, boost::asio::streambuf&> onReadFunc;
      /// Callback function called in case of error on the socket.
      boost::function1<void, boost::system::error_code> onErrorFunc;
  };

  /** Socket class with a higher API.
   *
   */
  class Socket: public AsioDestructible
  {
    public:
      Socket(): base_(0){}
      virtual ~Socket();
      /** Set underlying BaseSocket object, setup its callbacks to call our virtual functions.
       */
      virtual void setBase(BaseSocket*);

      /** Called each time new data is received.
       *   \return the number of bytes used in buffer. The remaining data will
       *   be passed again to this function as soon as at least an extra byte
       *   is available.
       */
      virtual int onRead(const void*, int length){return length;}

      /** Called in case of error on the socket.
      */
      virtual void onError(boost::system::error_code){}

      /// Ask for the asynchronous destruction of this object.
      virtual void destroy();

      inline void write(const void* data, unsigned int length)
      { base_->write(data, length);}
      /// Alias on write() for API compatibility.
      inline void send(void* addr, int len) {write((const void*)addr, len);}
      inline void close() {if (base_) base_->close();}
      inline bool isConnected() {return base_?base_->isConnected():false;}

      boost::system::error_code connect(const std::string& host,
	  const std::string& port, bool udp=false);

      typedef void* Handle;
      typedef boost::function0<Socket*> SocketFactory;

      static Handle listen(SocketFactory f, const std::string& host,
	  const std::string& port, boost::system::error_code & erc,
          bool udp = false);
#ifndef LIBPORT_NO_SSL
      static Handle listenSSL(SocketFactory f, const std::string& host,
	  const std::string&  port,
	  boost::system::error_code& erc,
	  boost::asio::ssl::context_base::method ctx
	    = boost::asio::ssl::context::sslv23_server,
	  boost::asio::ssl::context::options options
	    = boost::asio::ssl::context::verify_none,
	  const std::string& privateKeyFile = "",
	  const std::string& certChainFile = "",
	  const std::string& tmpDHFile = "" ,
	  const std::string& cipherList = "");
#endif
    protected:
      bool onRead_(boost::asio::streambuf&);
      std::string buffer;
      BaseSocket* base_;
    private:
    template<typename Proto, typename BaseFactory> static boost::system::error_code
      listenProto(SocketFactory f, const std::string& host,
	  const std::string&port, BaseFactory bf);
    template<typename Proto, typename BaseFactory> boost::system::error_code
      connectProto(const std::string& host, const std::string& port, BaseFactory bf);
  };

}

# include "libport/asio.hxx"

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

// Hash maps, depending on the environment

#ifndef LIBPORT_HASH_HH
# define LIBPORT_HASH_HH

// Define LIBPORT_HASH_NAMESPACE to the namespace name that contains
// hash_map, and include the right header.

# include <string>
# include <libport/cstring>

# include <libport/symbol.hh>

/*-----------.
| GCC part.  |
`-----------*/

# if defined __GNUC__

#  if (__GNUC__ == 2)
#    define LIBPORT_HASH_NAMESPACE stl
#  else
#    define LIBPORT_HASH_NAMESPACE __gnu_cxx
#  endif
#  ifdef __DEPRECATED
// Do not warn that ext/hash_map is deprecated
#   undef __DEPRECATED
#   include <ext/hash_map>
#   include <ext/hash_set>
#   define __DEPRECATED
#  else
#   include <ext/hash_map>
#   include <ext/hash_set>
#  endif

namespace LIBPORT_HASH_NAMESPACE
{

  // Be able to use hash_map with string easily.
  template<>
  struct hash<std::string>
  {
    size_t operator() (const std::string& x) const
    {
      return hash<const char*>() (x.c_str());
    }
  };

  template<>
  struct hash<libport::Symbol>
  {
    size_t operator() (const libport::Symbol& x) const
    {
      // The address of the string is unique, hash on it.
      return reinterpret_cast<size_t>(&x.name_get());
    }
  };

} // namespace LIBPORT_HASH_NAMESPACE

namespace std
{
  /// Used in the hash_map object to define equality of two variable names.
  template <>
  struct equal_to<const char *>
  {
    bool operator()(const char* s1, const char* s2) const
    {
      return ::libport::streq(s1, s2);
    }
  };

} // namespace std

# elif defined _MSC_VER

/*------------.
| VC++ part.  |
`------------*/

#  if (_MSC_VER >= 1400)
#   define LIBPORT_HASH_NAMESPACE stdext
#   pragma warning( disable : 4355 4996)
#  else
#   define LIBPORT_HASH_NAMESPACE std
#  endif
#  include <hash_map>
#  include <hash_set>

namespace LIBPORT_HASH_NAMESPACE
{
  //msc does not define a hash function for hash_compare

  /*--------.
  | char*.  |
  `--------*/
  template<>
  class hash_compare<const char*>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t operator ()(const char *c) const
    {
      size_t r = 0;
      while (*c!=0)
      {
	r = (*c)+31*r;
	c++;
      }
      return r;
    }
    bool operator()(const char* _Keyval1, const char* _Keyval2) const
    {
      // Whether _Keyval1 < _Keyval2.
      return strcmp(_Keyval1, _Keyval2) < 0;
    }
  };

  /*--------------.
  | std::string.  |
  `--------------*/
  template<>
  class hash_compare<std::string>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t
    operator() (const std::string& x) const
    {
      return hash_compare<const char*>()(x.c_str());
    }

    bool
    operator()(const std::string& _Keyval1, const std::string& _Keyval2) const
    {
      return _Keyval1 < _Keyval2;
    }
  };

  /*------------------.
  | libport::Symbol.  |
  `------------------*/
  template<>
  class hash_compare<libport::Symbol>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t
    operator() (const libport::Symbol& x) const
    {
      // The address of the string is unique, hash on it.
      return reinterpret_cast<size_t>(&x.name_get());
    }

    bool
    operator()(const libport::Symbol& _Keyval1,
	       const libport::Symbol& _Keyval2) const
    {
      return _Keyval1 < _Keyval2;
    }
  };

} // namespace LIBPORT_HASH_NAMESPACE

# else
#  error "Do not know where hash_map/hash_set are."
# endif

/*----------------------------.
| Compiler independent part.  |
`----------------------------*/

namespace libport
{
  using LIBPORT_HASH_NAMESPACE::hash_map;

  using LIBPORT_HASH_NAMESPACE::hash_set;

}

# undef LIBPORT_HASH_NAMESPACE

#endif // !LIBPORT_HASH_HH
<commit_msg>VC++ 2008.<commit_after>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

// Hash maps, depending on the environment

#ifndef LIBPORT_HASH_HH
# define LIBPORT_HASH_HH

// Define LIBPORT_HASH_NAMESPACE to the namespace name that contains
// hash_map, and include the right header.

# include <string>
# include <libport/cstring>

# include <libport/symbol.hh>

/*-----------.
| GCC part.  |
`-----------*/

# if defined __GNUC__

#  if (__GNUC__ == 2)
#    define LIBPORT_HASH_NAMESPACE stl
#  else
#    define LIBPORT_HASH_NAMESPACE __gnu_cxx
#  endif
#  ifdef __DEPRECATED
// Do not warn that ext/hash_map is deprecated
#   undef __DEPRECATED
#   include <ext/hash_map>
#   include <ext/hash_set>
#   define __DEPRECATED
#  else
#   include <ext/hash_map>
#   include <ext/hash_set>
#  endif

namespace LIBPORT_HASH_NAMESPACE
{

  // Be able to use hash_map with string easily.
  template<>
  struct hash<std::string>
  {
    size_t operator() (const std::string& x) const
    {
      return hash<const char*>() (x.c_str());
    }
  };

  template<>
  struct hash<libport::Symbol>
  {
    size_t operator() (const libport::Symbol& x) const
    {
      // The address of the string is unique, hash on it.
      return reinterpret_cast<size_t>(&x.name_get());
    }
  };

} // namespace LIBPORT_HASH_NAMESPACE

namespace std
{
  /// Used in the hash_map object to define equality of two variable names.
  template <>
  struct equal_to<const char *>
  {
    bool operator()(const char* s1, const char* s2) const
    {
      return ::libport::streq(s1, s2);
    }
  };

} // namespace std

# elif defined _MSC_VER

/*------------.
| VC++ part.  |
`------------*/

// Since Visual 2003 .NET, hash_compare changed of namespace ( std to
// stdext ).
//
// 1300: Visual 2002
// 1310: Visual 2003
// 1400: Visual 2005
// 1500: Visual 2008
#  if 1310 <= _MSC_VER
#   define LIBPORT_HASH_NAMESPACE stdext
#   pragma warning(disable : 4355 4996)
#  else
#   define LIBPORT_HASH_NAMESPACE std
#  endif
#  include <hash_map>
#  include <hash_set>

namespace LIBPORT_HASH_NAMESPACE
{
  // MSVC does not define a hash function for hash_compare.

  /*--------.
  | char*.  |
  `--------*/
  template<>
  class hash_compare<const char*>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t operator ()(const char *c) const
    {
      size_t r = 0;
      while (*c)
      {
	r = (*c)+31*r;
	c++;
      }
      return r;
    }
    bool operator()(const char* _Keyval1, const char* _Keyval2) const
    {
      // Whether _Keyval1 < _Keyval2.
      return strcmp(_Keyval1, _Keyval2) < 0;
    }
  };

  /*--------------.
  | std::string.  |
  `--------------*/
  template<>
  class hash_compare<std::string>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t
    operator() (const std::string& x) const
    {
      return hash_compare<const char*>()(x.c_str());
    }

    bool
    operator()(const std::string& _Keyval1, const std::string& _Keyval2) const
    {
      return _Keyval1 < _Keyval2;
    }
  };

  /*------------------.
  | libport::Symbol.  |
  `------------------*/
  template<>
  class hash_compare<libport::Symbol>
  {
    public:
    enum
    {
      // parameters for hash table
      bucket_size = 4,	// 0 < bucket_size
      min_buckets = 8
    };	// min_buckets = 2 ^^ N, 0 < N

    size_t
    operator() (const libport::Symbol& x) const
    {
      // The address of the string is unique, hash on it.
      return reinterpret_cast<size_t>(&x.name_get());
    }

    bool
    operator()(const libport::Symbol& _Keyval1,
	       const libport::Symbol& _Keyval2) const
    {
      return _Keyval1 < _Keyval2;
    }
  };

} // namespace LIBPORT_HASH_NAMESPACE

# else
#  error "Do not know where hash_map/hash_set are."
# endif

/*----------------------------.
| Compiler independent part.  |
`----------------------------*/

namespace libport
{
  using LIBPORT_HASH_NAMESPACE::hash_map;

  using LIBPORT_HASH_NAMESPACE::hash_set;

}

# undef LIBPORT_HASH_NAMESPACE

#endif // !LIBPORT_HASH_HH
<|endoftext|>