<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/socks5_stream.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{

	void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h)
	{
		if (e || i == tcp::resolver::iterator())
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_sock.async_connect(i->endpoint(), boost::bind(
			&socks5_stream::connected, this, _1, h));
	}

	void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;
		// send SOCKS5 authentication methods
		m_buffer.resize(m_user.empty()?3:4);
		char* p = &m_buffer[0];
		write_uint8(5, p); // SOCKS VERSION 5
		if (m_user.empty())
		{
			write_uint8(1, p); // 1 authentication method (no auth)
			write_uint8(0, p); // no authentication
		}
		else
		{
			write_uint8(2, p); // 2 authentication methods
			write_uint8(0, p); // no authentication
			write_uint8(2, p); // username/password
		}
		asio::async_write(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake1, this, _1, h));
	}

	void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(2);
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake2, this, _1, h));
	}

	void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		char* p = &m_buffer[0];
		int version = read_uint8(p);
		int method = read_uint8(p);

		if (version < 5)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		if (method == 0)
		{
			socks_connect(h);
		}
		else if (method == 2)
		{
			if (m_user.empty())
			{
				(*h)(asio::error::operation_not_supported);
				asio::error_code ec;
				close(ec);
				return;
			}

			// start sub-negotiation
			m_buffer.resize(m_user.size() + m_password.size() + 3);
			char* p = &m_buffer[0];
			write_uint8(1, p);
			write_uint8(m_user.size(), p);
			write_string(m_user, p);
			write_uint8(m_password.size(), p);
			write_string(m_password, p);
			asio::async_write(m_sock, asio::buffer(m_buffer)
				, boost::bind(&socks5_stream::handshake3, this, _1, h));
		}
		else
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
	}

	void socks5_stream::handshake3(asio::error_code const& e
		, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(2);
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake4, this, _1, h));
	}

	void socks5_stream::handshake4(asio::error_code const& e
		, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		char* p = &m_buffer[0];
		int version = read_uint8(p);
		int status = read_uint8(p);

		if (version != 1)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		if (status != 0)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		std::vector<char>().swap(m_buffer);
		(*h)(e);
	}

	void socks5_stream::socks_connect(boost::shared_ptr<handler_type> h)
	{
		using namespace libtorrent::detail;

		// send SOCKS5 connect command
		m_buffer.resize(6 + (m_remote_endpoint.address().is_v4()?4:16));
		char* p = &m_buffer[0];
		write_uint8(5, p); // SOCKS VERSION 5
		write_uint8(1, p); // CONNECT command
		write_uint8(0, p); // reserved
		write_uint8(m_remote_endpoint.address().is_v4()?1:4, p); // address type
		write_address(m_remote_endpoint.address(), p);
		write_uint16(m_remote_endpoint.port(), p);
		TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size()));

		asio::async_write(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect1, this, _1, h));
	}

	void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(6 + 4); // assume an IPv4 address
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect2, this, _1, h));
	}

	void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		// send SOCKS5 connect command
		char* p = &m_buffer[0];
		int version = read_uint8(p);
		if (version < 5)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
		int response = read_uint8(p);
		if (response != 0)
		{
			asio::error_code e = asio::error::fault;
			switch (response)
			{
				case 1: e = asio::error::fault; break;
				case 2: e = asio::error::no_permission; break;
				case 3: e = asio::error::network_unreachable; break;
				case 4: e = asio::error::host_unreachable; break;
				case 5: e = asio::error::connection_refused; break;
				case 6: e = asio::error::timed_out; break;
				case 7: e = asio::error::operation_not_supported; break;
				case 8: e = asio::error::address_family_not_supported; break;
			}
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}
		p += 1; // reserved
		int atyp = read_uint8(p);
		// we ignore the proxy IP it was bound to
		if (atyp == 1)
		{
			std::vector<char>().swap(m_buffer);
			(*h)(e);
			return;
		}
		int skip_bytes = 0;
		if (atyp == 4)
		{
			skip_bytes = 12;
		}
		else if (atyp == 3)
		{
			skip_bytes = read_uint8(p) - 3;
		}
		else
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
		m_buffer.resize(skip_bytes);

		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect3, this, _1, h));
	}

	void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		std::vector<char>().swap(m_buffer);
		(*h)(e);
	}
}

<commit_msg>fixed bug in socks5 implementation when using user/pass authentication<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/socks5_stream.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{

	void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h)
	{
		if (e || i == tcp::resolver::iterator())
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_sock.async_connect(i->endpoint(), boost::bind(
			&socks5_stream::connected, this, _1, h));
	}

	void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;
		// send SOCKS5 authentication methods
		m_buffer.resize(m_user.empty()?3:4);
		char* p = &m_buffer[0];
		write_uint8(5, p); // SOCKS VERSION 5
		if (m_user.empty())
		{
			write_uint8(1, p); // 1 authentication method (no auth)
			write_uint8(0, p); // no authentication
		}
		else
		{
			write_uint8(2, p); // 2 authentication methods
			write_uint8(0, p); // no authentication
			write_uint8(2, p); // username/password
		}
		asio::async_write(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake1, this, _1, h));
	}

	void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(2);
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake2, this, _1, h));
	}

	void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		char* p = &m_buffer[0];
		int version = read_uint8(p);
		int method = read_uint8(p);

		if (version < 5)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		if (method == 0)
		{
			socks_connect(h);
		}
		else if (method == 2)
		{
			if (m_user.empty())
			{
				(*h)(asio::error::operation_not_supported);
				asio::error_code ec;
				close(ec);
				return;
			}

			// start sub-negotiation
			m_buffer.resize(m_user.size() + m_password.size() + 3);
			char* p = &m_buffer[0];
			write_uint8(1, p);
			write_uint8(m_user.size(), p);
			write_string(m_user, p);
			write_uint8(m_password.size(), p);
			write_string(m_password, p);
			asio::async_write(m_sock, asio::buffer(m_buffer)
				, boost::bind(&socks5_stream::handshake3, this, _1, h));
		}
		else
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
	}

	void socks5_stream::handshake3(asio::error_code const& e
		, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(2);
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::handshake4, this, _1, h));
	}

	void socks5_stream::handshake4(asio::error_code const& e
		, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		char* p = &m_buffer[0];
		int version = read_uint8(p);
		int status = read_uint8(p);

		if (version != 1)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		if (status != 0)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}

		std::vector<char>().swap(m_buffer);
		socks_connect(h);
	}

	void socks5_stream::socks_connect(boost::shared_ptr<handler_type> h)
	{
		using namespace libtorrent::detail;

		// send SOCKS5 connect command
		m_buffer.resize(6 + (m_remote_endpoint.address().is_v4()?4:16));
		char* p = &m_buffer[0];
		write_uint8(5, p); // SOCKS VERSION 5
		write_uint8(1, p); // CONNECT command
		write_uint8(0, p); // reserved
		write_uint8(m_remote_endpoint.address().is_v4()?1:4, p); // address type
		write_address(m_remote_endpoint.address(), p);
		write_uint16(m_remote_endpoint.port(), p);
		TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size()));

		asio::async_write(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect1, this, _1, h));
	}

	void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		m_buffer.resize(6 + 4); // assume an IPv4 address
		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect2, this, _1, h));
	}

	void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		using namespace libtorrent::detail;

		// send SOCKS5 connect command
		char* p = &m_buffer[0];
		int version = read_uint8(p);
		if (version < 5)
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
		int response = read_uint8(p);
		if (response != 0)
		{
			asio::error_code e = asio::error::fault;
			switch (response)
			{
				case 1: e = asio::error::fault; break;
				case 2: e = asio::error::no_permission; break;
				case 3: e = asio::error::network_unreachable; break;
				case 4: e = asio::error::host_unreachable; break;
				case 5: e = asio::error::connection_refused; break;
				case 6: e = asio::error::timed_out; break;
				case 7: e = asio::error::operation_not_supported; break;
				case 8: e = asio::error::address_family_not_supported; break;
			}
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}
		p += 1; // reserved
		int atyp = read_uint8(p);
		// we ignore the proxy IP it was bound to
		if (atyp == 1)
		{
			std::vector<char>().swap(m_buffer);
			(*h)(e);
			return;
		}
		int skip_bytes = 0;
		if (atyp == 4)
		{
			skip_bytes = 12;
		}
		else if (atyp == 3)
		{
			skip_bytes = read_uint8(p) - 3;
		}
		else
		{
			(*h)(asio::error::operation_not_supported);
			asio::error_code ec;
			close(ec);
			return;
		}
		m_buffer.resize(skip_bytes);

		asio::async_read(m_sock, asio::buffer(m_buffer)
			, boost::bind(&socks5_stream::connect3, this, _1, h));
	}

	void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h)
	{
		if (e)
		{
			(*h)(e);
			asio::error_code ec;
			close(ec);
			return;
		}

		std::vector<char>().swap(m_buffer);
		(*h)(e);
	}
}

<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#ifndef SET_HPP
#define SET_HPP

#include "coloredkdbio.hpp"
#include <command.hpp>
#include <kdb.hpp>

class SetCommand : public Command
{
	kdb::KDB kdb;

public:
	SetCommand ();
	~SetCommand ();

	virtual std::string getShortOptions () override
	{
		return "qN";
	}

	virtual std::string getSynopsis () override
	{
		return "<name> [<value>]";
	}

	virtual std::string getShortHelpText () override
	{
		return "Set the value of an individual key.";
	}

	virtual std::string getLongHelpText () override
	{
		return "If no value is given, it will be set to a null-value\n"
		       "To get an empty value you need to quote like \"\" (depending on shell)\n"
		       "To set a negative value you need to use '--' to stop option processing.\n"
		       "(e.g. 'kdb set -- /tests/neg -3')\n";
	}

	virtual int execute (Cmdline const & cmdline) override;
};

#endif
<commit_msg>kdb: remove null key setting in header file<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#ifndef SET_HPP
#define SET_HPP

#include "coloredkdbio.hpp"
#include <command.hpp>
#include <kdb.hpp>

class SetCommand : public Command
{
	kdb::KDB kdb;

public:
	SetCommand ();
	~SetCommand ();

	virtual std::string getShortOptions () override
	{
		return "qN";
	}

	virtual std::string getSynopsis () override
	{
		return "<name> <value>";
	}

	virtual std::string getShortHelpText () override
	{
		return "Set the value of an individual key.";
	}

	virtual std::string getLongHelpText () override
	{
		return "To get an empty value you need to quote like \"\" (depending on shell)\n"
		       "To set a negative value you need to use '--' to stop option processing.\n"
		       "(e.g. 'kdb set -- /tests/neg -3')\n";
	}

	virtual int execute (Cmdline const & cmdline) override;
};

#endif
<|endoftext|>


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

#include <fstream>
#include <iostream>
#include <limits>
#include <lpcore>
#include <sstream>

#include <cerrno>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <getopt.h>

void help() noexcept;
double to_double(const char* s, double bad_value) noexcept;
long to_long(const char* s, long bad_value) noexcept;
std::tuple<std::string, lp::parameter> split_param(const char* param) noexcept;
const char* file_format_error_format(lp::file_format_error::tag) noexcept;
const char* problem_definition_error_format(
  lp::problem_definition_error::tag) noexcept;
const char* solver_error_format(lp::solver_error::tag) noexcept;

int
main(int argc, char* argv[])
{
    const char* const short_opts = "hp:l:qv:";
    const struct option long_opts[] = {
        { "help", 0, nullptr, 'h' },    { "param", 1, nullptr, 'p' },
        { "limit", 1, nullptr, 'l' },   { "quiet", 0, nullptr, 0 },
        { "verbose", 1, nullptr, 'v' }, { 0, 0, nullptr, 0 }
    };

    int opt_index;
    int verbose = 1;
    bool fail = false;
    bool quiet = false;
    std::map<std::string, lp::parameter> parameters;

    while (not fail) {
        const auto opt =
          getopt_long(argc, argv, short_opts, long_opts, &opt_index);
        if (opt == -1)
            break;

        switch (opt) {
            case 0:
                break;
            case 'l':
                parameters["limit"] = to_long(::optarg, 1000l);
                break;

            case 'h':
                help();
                return EXIT_SUCCESS;
            case 'p': {
                std::string name;
                lp::parameter value;
                std::tie(name, value) = split_param(::optarg);
                parameters[name] = value;
            } break;
            case '?':
            default:
                fail = true;
                std::fprintf(stderr, "Unknown command line option\n");
                break;
        };
    }

    if (fail)
        return EXIT_FAILURE;

    (void)verbose;
    (void)quiet;

    for (int i = ::optind; i < argc; ++i) {
        try {
            auto pb = lp::make_problem(argv[i]);
            auto ret = lp::solve(pb, parameters);

            if (ret.solution_found and
                lp::is_valid_solution(pb, ret.variable_value)) {
                std::fprintf(stdout, "Solution found: %f\n", ret.value);
                for (std::size_t i{ 0 }, e{ ret.variable_name.size() }; i != e;
                     ++i)
                    std::fprintf(stdout,
                                 "%s = %d",
                                 ret.variable_name[i].c_str(),
                                 ret.variable_value[i]);
            } else {
                std::fprintf(stdout, "No solution found\n");
            }
        } catch (const lp::precondition_error& e) {
            std::fprintf(stderr, "internal failure\n");
        } catch (const lp::postcondition_error& e) {
            std::fprintf(stderr, "internal failure\n");
        } catch (const lp::numeric_cast_error& e) {
            std::fprintf(stderr, "numeric cast interal failure\n");
        } catch (const lp::file_access_error& e) {
            std::fprintf(stderr,
                         "file `%s' fail %d: %s\n",
                         e.file().c_str(),
                         e.error(),
                         std::strerror(e.error()));
        } catch (const lp::file_format_error& e) {
            std::fprintf(stderr,
                         "file format error at line %d column %d "
                         "%s\n",
                         e.line(),
                         e.column(),
                         file_format_error_format(e.failure()));
        } catch (const lp::problem_definition_error& e) {
            std::fprintf(stderr,
                         "definition problem error at %s: %s\n",
                         e.element().c_str(),
                         problem_definition_error_format(e.failure()));
        } catch (const lp::solver_error& e) {
            std::fprintf(
              stderr, "solver error: %s\n", solver_error_format(e.failure()));
        } catch (const std::exception& e) {
            std::fprintf(stderr, "failure: %s.\n", e.what());
        }
    }

    return EXIT_SUCCESS;
}

void
help() noexcept
{
    std::fprintf(stdout,
                 "--help|-h                   This help message\n"
                 "--param|-p [name]:[value]   Add a new parameter (name is"
                 " [a-z][A-Z]_ value can be a double, an integer otherwise a"
                 " string.\n"
                 "--limit int                 Set limit\n"
                 "--quiet                     Remove any verbose message\n"
                 "--verbose|-v int            Set verbose level\n");
}

const char*
file_format_error_format(lp::file_format_error::tag failure) noexcept
{
    static const char* const tag[] = {
        "end of file",     "unknown",
        "already defined", "incomplete",
        "bad name",        "bad operator",
        "bad integer",     "bad objective function type",
        "bad bound",       "bad function element",
        "bad constraint"
    };

    switch (failure) {
        case lp::file_format_error::tag::end_of_file:
            return tag[0];
        case lp::file_format_error::tag::unknown:
            return tag[1];
        case lp::file_format_error::tag::already_defined:
            return tag[2];
        case lp::file_format_error::tag::incomplete:
            return tag[3];
        case lp::file_format_error::tag::bad_name:
            return tag[4];
        case lp::file_format_error::tag::bad_operator:
            return tag[5];
        case lp::file_format_error::tag::bad_integer:
            return tag[6];
        case lp::file_format_error::tag::bad_objective_function_type:
            return tag[7];
        case lp::file_format_error::tag::bad_bound:
            return tag[8];
        case lp::file_format_error::tag::bad_function_element:
            return tag[9];
        case lp::file_format_error::tag::bad_constraint:
            return tag[10];
    }

    return nullptr;
}

const char*
problem_definition_error_format(
  lp::problem_definition_error::tag failure) noexcept
{
    static const char* const tag[] = {
        "empty variables",
        "empty objective function",
        "variable not used",
        "bad bound",
        "multiple constraints with different value"
    };

    switch (failure) {
        case lp::problem_definition_error::tag::empty_variables:
            return tag[0];
        case lp::problem_definition_error::tag::empty_objective_function:
            return tag[1];
        case lp::problem_definition_error::tag::variable_not_used:
            return tag[2];
        case lp::problem_definition_error::tag::bad_bound:
            return tag[3];
        case lp::problem_definition_error::tag::multiple_constraint:
            return tag[4];
    }

    return nullptr;
}

const char*
solver_error_format(lp::solver_error::tag failure) noexcept
{
    static const char* const tag[] = { "no solver available",
                                       "unrealisable constraint",
                                       "not enough memory" };

    switch (failure) {
        case lp::solver_error::tag::no_solver_available:
            return tag[0];
        case lp::solver_error::tag::unrealisable_constraint:
            return tag[1];
        case lp::solver_error::tag::not_enough_memory:
            return tag[2];
    }

    return nullptr;
}

double
to_double(const char* s, double bad_value) noexcept
{
    char* c;
    errno = 0;
    double value = std::strtof(s, &c);

    if ((errno == ERANGE and (value == std::numeric_limits<double>::lowest() or
                              value == -std::numeric_limits<double>::max())) or
        (errno != 0 and value == 0) or (c == ::optarg))
        return bad_value;

    return value;
}

long
to_long(const char* s, long bad_value) noexcept
{
    char* c;
    errno = 0;
    long value = std::strtol(s, &c, 10);

    if ((errno == ERANGE and (value == std::numeric_limits<long>::lowest() or
                              value == std::numeric_limits<long>::max())) or
        (errno != 0 and value == 0) or (c == ::optarg))
        return bad_value;

    return value;
}

std::tuple<std::string, lp::parameter>
split_param(const char* param) noexcept
{
    std::string name, value;

    while (*param) {
        if (isalpha(*param) or *param == '_' or *param == '-')
            name += *param;
        else
            break;

        param++;
    }

    if (*param and (*param == ':' or *param == '=')) {
        param++;

        while (*param) {
            if (isalnum(*param) or *param == '.')
                value += *param;
            else
                break;

            param++;
        }
    }

    auto valuel = to_long(value.c_str(), std::numeric_limits<long>::min());
    auto valued = to_double(value.c_str(), std::numeric_limits<double>::min());

    double tmp;
    if (valued != std::numeric_limits<double>::min() and
        std::modf(valued, &tmp))
        return std::make_tuple(name, lp::parameter(valued));

    if (valuel != std::numeric_limits<long>::min())
        return std::make_tuple(name, lp::parameter(valuel));

    return std::make_tuple(name, lp::parameter(value));
}
<commit_msg>main: fix detection of bad long or double<commit_after>/* Copyright (C) 2016 INRA
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <fstream>
#include <iostream>
#include <limits>
#include <lpcore>
#include <sstream>

#include <cerrno>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <getopt.h>

void help() noexcept;
double to_double(const char* s, double bad_value) noexcept;
long to_long(const char* s, long bad_value) noexcept;
std::tuple<std::string, lp::parameter> split_param(const char* param) noexcept;
const char* file_format_error_format(lp::file_format_error::tag) noexcept;
const char* problem_definition_error_format(
  lp::problem_definition_error::tag) noexcept;
const char* solver_error_format(lp::solver_error::tag) noexcept;

int
main(int argc, char* argv[])
{
    const char* const short_opts = "hp:l:qv:";
    const struct option long_opts[] = {
        { "help", 0, nullptr, 'h' },    { "param", 1, nullptr, 'p' },
        { "limit", 1, nullptr, 'l' },   { "quiet", 0, nullptr, 0 },
        { "verbose", 1, nullptr, 'v' }, { 0, 0, nullptr, 0 }
    };

    int opt_index;
    int verbose = 1;
    bool fail = false;
    bool quiet = false;
    std::map<std::string, lp::parameter> parameters;

    while (not fail) {
        const auto opt =
          getopt_long(argc, argv, short_opts, long_opts, &opt_index);
        if (opt == -1)
            break;

        switch (opt) {
            case 0:
                break;
            case 'l':
                parameters["limit"] = to_long(::optarg, 1000l);
                break;

            case 'h':
                help();
                return EXIT_SUCCESS;
            case 'p': {
                std::string name;
                lp::parameter value;
                std::tie(name, value) = split_param(::optarg);
                parameters[name] = value;
            } break;
            case '?':
            default:
                fail = true;
                std::fprintf(stderr, "Unknown command line option\n");
                break;
        };
    }

    if (fail)
        return EXIT_FAILURE;

    (void)verbose;
    (void)quiet;

    for (int i = ::optind; i < argc; ++i) {
        try {
            auto pb = lp::make_problem(argv[i]);
            auto ret = lp::solve(pb, parameters);

            if (ret.solution_found and
                lp::is_valid_solution(pb, ret.variable_value)) {
                std::fprintf(stdout, "Solution found: %f\n", ret.value);
                for (std::size_t i{ 0 }, e{ ret.variable_name.size() }; i != e;
                     ++i)
                    std::fprintf(stdout,
                                 "%s = %d",
                                 ret.variable_name[i].c_str(),
                                 ret.variable_value[i]);
            } else {
                std::fprintf(stdout, "No solution found\n");
            }
        } catch (const lp::precondition_error& e) {
            std::fprintf(stderr, "internal failure\n");
        } catch (const lp::postcondition_error& e) {
            std::fprintf(stderr, "internal failure\n");
        } catch (const lp::numeric_cast_error& e) {
            std::fprintf(stderr, "numeric cast interal failure\n");
        } catch (const lp::file_access_error& e) {
            std::fprintf(stderr,
                         "file `%s' fail %d: %s\n",
                         e.file().c_str(),
                         e.error(),
                         std::strerror(e.error()));
        } catch (const lp::file_format_error& e) {
            std::fprintf(stderr,
                         "file format error at line %d column %d "
                         "%s\n",
                         e.line(),
                         e.column(),
                         file_format_error_format(e.failure()));
        } catch (const lp::problem_definition_error& e) {
            std::fprintf(stderr,
                         "definition problem error at %s: %s\n",
                         e.element().c_str(),
                         problem_definition_error_format(e.failure()));
        } catch (const lp::solver_error& e) {
            std::fprintf(
              stderr, "solver error: %s\n", solver_error_format(e.failure()));
        } catch (const std::exception& e) {
            std::fprintf(stderr, "failure: %s.\n", e.what());
        }
    }

    return EXIT_SUCCESS;
}

void
help() noexcept
{
    std::fprintf(stdout,
                 "--help|-h                   This help message\n"
                 "--param|-p [name]:[value]   Add a new parameter (name is"
                 " [a-z][A-Z]_ value can be a double, an integer otherwise a"
                 " string.\n"
                 "--limit int                 Set limit\n"
                 "--quiet                     Remove any verbose message\n"
                 "--verbose|-v int            Set verbose level\n");
}

const char*
file_format_error_format(lp::file_format_error::tag failure) noexcept
{
    static const char* const tag[] = {
        "end of file",     "unknown",
        "already defined", "incomplete",
        "bad name",        "bad operator",
        "bad integer",     "bad objective function type",
        "bad bound",       "bad function element",
        "bad constraint"
    };

    switch (failure) {
        case lp::file_format_error::tag::end_of_file:
            return tag[0];
        case lp::file_format_error::tag::unknown:
            return tag[1];
        case lp::file_format_error::tag::already_defined:
            return tag[2];
        case lp::file_format_error::tag::incomplete:
            return tag[3];
        case lp::file_format_error::tag::bad_name:
            return tag[4];
        case lp::file_format_error::tag::bad_operator:
            return tag[5];
        case lp::file_format_error::tag::bad_integer:
            return tag[6];
        case lp::file_format_error::tag::bad_objective_function_type:
            return tag[7];
        case lp::file_format_error::tag::bad_bound:
            return tag[8];
        case lp::file_format_error::tag::bad_function_element:
            return tag[9];
        case lp::file_format_error::tag::bad_constraint:
            return tag[10];
    }

    return nullptr;
}

const char*
problem_definition_error_format(
  lp::problem_definition_error::tag failure) noexcept
{
    static const char* const tag[] = {
        "empty variables",
        "empty objective function",
        "variable not used",
        "bad bound",
        "multiple constraints with different value"
    };

    switch (failure) {
        case lp::problem_definition_error::tag::empty_variables:
            return tag[0];
        case lp::problem_definition_error::tag::empty_objective_function:
            return tag[1];
        case lp::problem_definition_error::tag::variable_not_used:
            return tag[2];
        case lp::problem_definition_error::tag::bad_bound:
            return tag[3];
        case lp::problem_definition_error::tag::multiple_constraint:
            return tag[4];
    }

    return nullptr;
}

const char*
solver_error_format(lp::solver_error::tag failure) noexcept
{
    static const char* const tag[] = { "no solver available",
                                       "unrealisable constraint",
                                       "not enough memory" };

    switch (failure) {
        case lp::solver_error::tag::no_solver_available:
            return tag[0];
        case lp::solver_error::tag::unrealisable_constraint:
            return tag[1];
        case lp::solver_error::tag::not_enough_memory:
            return tag[2];
    }

    return nullptr;
}

double
to_double(const char* s, double bad_value) noexcept
{
    char* c;
    errno = 0;
    double value = std::strtod(s, &c);

    if ((errno == ERANGE and (value == HUGE_VAL or value == -HUGE_VAL)) or
        (value == 0.0 and c == s))
        return bad_value;

    return value;
}

long
to_long(const char* s, long bad_value) noexcept
{
    char* c;
    errno = 0;
    long value = std::strtol(s, &c, 10);

    if ((errno == ERANGE and (value == LONG_MIN or value == LONG_MAX)) or
        (value == 0 and c == s))
        return bad_value;

    return value;
}

std::tuple<std::string, lp::parameter>
split_param(const char* param) noexcept
{
    std::string name, value;

    while (*param) {
        if (isalpha(*param) or *param == '_' or *param == '-')
            name += *param;
        else
            break;

        param++;
    }

    if (*param and (*param == ':' or *param == '=')) {
        param++;

        while (*param)
            value += *param++;
    }

    auto valuel = to_long(value.c_str(), LONG_MIN);
    auto valued = to_double(value.c_str(), -HUGE_VAL);

    double tmp;
    if (valued != -HUGE_VAL and std::modf(valued, &tmp))
        return std::make_tuple(name, lp::parameter(valued));

    if (valuel != LONG_MIN)
        return std::make_tuple(name, lp::parameter(valuel));

    return std::make_tuple(name, lp::parameter(value));
}
<|endoftext|>


<commit_before>/*
    This file is part of Csound.

        Copyright (C) 2014 Rory Walsh

    The Csound Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Lesser General Public
    License along with Csound; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    02110-1301 USA
 */

#include "OpcodeBase.hpp"
#include <algorithm>
#include <cmath>
#include <dirent.h>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <vector>

using namespace std;
using namespace csound;

/* this function will load all samples of supported types into function
   tables number 'index' and upwards.
   It return the number of samples loaded */
int loadSamplesToTables(CSOUND *csound, int index, char *directory,
                        int skiptime, int format, int channel);

//-----------------------------------------------------------------
//      i-rate class
//-----------------------------------------------------------------
class iftsamplebank : public OpcodeBase<iftsamplebank> {
public:
  // Outputs.
  MYFLT *numberOfFiles;
  // Inputs.
  STRINGDAT *sDirectory;
  MYFLT *index;
  //    MYFLT* trigger;
  MYFLT *skiptime;
  MYFLT *format;
  MYFLT *channel;

  iftsamplebank() {
    channel = 0;
    index = 0;
    skiptime = 0;
    format = 0;
    index = 0;
    numberOfFiles = 0;
    sDirectory = NULL;
  }

  // init-pass
  int init(CSOUND *csound) {

    *numberOfFiles = loadSamplesToTables(
        csound, *index, (char *)sDirectory->data, *skiptime, *format, *channel);
    return OK;
  }

  int noteoff(CSOUND *) { return OK; }
};

//-----------------------------------------------------------------
//      k-rate class
//-----------------------------------------------------------------
class kftsamplebank : public OpcodeBase<kftsamplebank> {
public:
  // Outputs.
  MYFLT *numberOfFiles;
  // Inputs.
  STRINGDAT *sDirectory;
  MYFLT *index;
  MYFLT *trigger;
  MYFLT *skiptime;
  MYFLT *format;
  MYFLT *channel;
  int internalCounter;
  kftsamplebank() : internalCounter(0) {
    channel = 0;
    index = 0;
    skiptime = 0;
    format = 0;
    index = 0;
    trigger = 0;
  }

  // init-pass
  int init(CSOUND *csound) {
    IGN(csound);
    *numberOfFiles = 0;
    // loadSamplesToTables(csound, *index, fileNames,
    // (char* )sDirectory->data, *skiptime, *format, *channel);
    // csound->Message(csound, (char* )sDirectory->data);
    *trigger = 0;
    return OK;
  }

  int noteoff(CSOUND *) { return OK; }

  int kontrol(CSOUND *csound) {
    // if directry changes update tables..
    if (*trigger == 1) {
      *numberOfFiles =
          loadSamplesToTables(csound, *index, (char *)sDirectory->data,
                              *skiptime, *format, *channel);
      *trigger = 0;
    }
    return OK;
  }
};

//-----------------------------------------------------------------
//      load samples into function tables
//-----------------------------------------------------------------
int loadSamplesToTables(CSOUND *csound, int index, char *directory,
                        int skiptime, int format, int channel) {

  if (directory) {
    DIR *dir = opendir(directory);
    std::vector<std::string> fileNames;
    std::vector<std::string> fileExtensions;
    int noOfFiles = 0;
    fileExtensions.push_back(".wav");
    fileExtensions.push_back(".aiff");
    fileExtensions.push_back(".ogg");
    fileExtensions.push_back(".flac");

    // check for valid path first
    if (dir) {
      struct dirent *ent;
      while ((ent = readdir(dir)) != NULL) {
        std::ostringstream fullFileName;
        // only use supported file types
        for (int i = 0; (size_t)i < fileExtensions.size(); i++)
        {
          std::string fname = ent->d_name;
          std::string extension;
          if(fname.find_last_of(".") != std::string::npos)
            extension = fname.substr(fname.find_last_of(".")+1);

          if(extension == fileExtensions[i])
            {
              if (strlen(directory) > 2) {
#if defined(WIN32)
              fullFileName << directory << "\\" << ent->d_name;
#else
              fullFileName << directory << "/" << ent->d_name;
#endif
            }
            else
              fullFileName << ent->d_name;

            noOfFiles++;
            fileNames.push_back(fullFileName.str());
          }
        }
      }

      // Sort names
      std::sort(fileNames.begin(), fileNames.end());

      // push statements to score, starting with table number 'index'
      for (int y = 0; (size_t)y < fileNames.size(); y++) {
        std::ostringstream statement;
        statement << "f" << index + y << " 0 0 1 \"" << fileNames[y] << "\" "
                  << skiptime << " " << format << " " << channel << "\n";
        // csound->MessageS(csound, CSOUNDMSG_ORCH, statement.str().c_str());
        csound->InputMessage(csound, statement.str().c_str());
      }

      closedir(dir);
    } else {
      csound->Message(csound,
                      Str("Cannot load file. Error opening directory: %s\n"),
                      directory);
    }

    // return number of files
    return noOfFiles;
  } else
    return 0;
}

typedef struct {
  OPDS h;
  ARRAYDAT *outArr;
  STRINGDAT *directoryName;
  MYFLT *extension;
} DIR_STRUCT;

/* this function will looks for files of a set type, in a particular directory
 */
std::vector<std::string> searchDir(CSOUND *csound, char *directory,
                                   char *extension);

#include "arrays.h"
#if 0
/* from Opcodes/arrays.c */
static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) {
    if (p->data==NULL || p->dimensions == 0 ||
        (p->dimensions==1 && p->sizes[0] < size)) {
      size_t ss;
      if (p->data == NULL) {
        CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL);
        p->arrayMemberSize = var->memBlockSize;
      }
      ss = p->arrayMemberSize*size;
      if (p->data==NULL) {
        p->data = (MYFLT*)csound->Calloc(csound, ss);
        p->allocated = ss;
      }
      else if (ss > p->allocated) {
        p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss);
        p->allocated = ss;
      }
      if (p->dimensions==0) {
        p->dimensions = 1;
        p->sizes = (int32_t*)csound->Malloc(csound, sizeof(int32_t));
      }
    }
    p->sizes[0] = size;
}
#endif

static int directory(CSOUND *csound, DIR_STRUCT *p) {
  int inArgCount = p->INOCOUNT;
  char *extension, *file;
  std::vector<std::string> fileNames;

  if (inArgCount == 0)
    return csound->InitError(
        csound, "%s", Str("Error: you must pass a directory as a string."));

  if (inArgCount == 1) {
    fileNames = searchDir(csound, p->directoryName->data, (char *)"");
  }

  else if (inArgCount == 2) {
    CS_TYPE *argType = csound->GetTypeForArg(p->extension);
    if (strcmp("S", argType->varTypeName) == 0) {
      extension = csound->Strdup(csound, ((STRINGDAT *)p->extension)->data);
      fileNames = searchDir(csound, p->directoryName->data, extension);
    } else
      return csound->InitError(csound,
                               "%s", Str("Error: second parameter to directory"
                                   " must be a string"));
  }

  int numberOfFiles = fileNames.size();
  tabinit(csound, p->outArr, numberOfFiles);
  STRINGDAT *strings = (STRINGDAT *)p->outArr->data;

  for (int i = 0; i < numberOfFiles; i++) {
    file = &fileNames[i][0u];
    strings[i].size = strlen(file) + 1;
    strings[i].data = csound->Strdup(csound, file);
  }

  fileNames.clear();

  return OK;
}

//-----------------------------------------------------------------
//      load samples into function tables
//-----------------------------------------------------------------
std::vector<std::string> searchDir(CSOUND *csound, char *directory,
                                   char *extension) {
  std::vector<std::string> fileNames;
  if (directory) {
    DIR *dir = opendir(directory);
    std::string fileExtension(extension);
    int noOfFiles = 0;

    // check for valid path first
    if (dir) {
      struct dirent *ent;
      while ((ent = readdir(dir)) != NULL) {
        std::ostringstream fullFileName;

        std::string fname = ent->d_name;
        size_t lastPos = fname.find_last_of(".");
        if (fname.length() > 2 && (fileExtension.empty() ||
            (lastPos != std::string::npos &&
            fname.substr(lastPos) == fileExtension))) {
          if (strlen(directory) > 2) {
#if defined(WIN32)
            fullFileName << directory << "\\" << ent->d_name;
#else
            fullFileName << directory << "/" << ent->d_name;
#endif
          } else
            fullFileName << ent->d_name;

          noOfFiles++;
          fileNames.push_back(fullFileName.str());
        }
      }

      // Sort names
      std::sort(fileNames.begin(), fileNames.end());
    } else {
      csound->Message(csound, Str("Cannot find directory. "
                                  "Error opening directory: %s\n"),
                      directory);
    }
    closedir(dir);
  }

  return fileNames;
}

extern "C" {

PUBLIC int csoundModuleInit_ftsamplebank(CSOUND *csound) {

  int status = csound->AppendOpcode(
      csound, (char *)"ftsamplebank.k", sizeof(kftsamplebank), 0, 3,
      (char *)"k", (char *)"Skkkkk",
      (int (*)(CSOUND *, void *))kftsamplebank::init_,
      (int (*)(CSOUND *, void *))kftsamplebank::kontrol_,
      (int (*)(CSOUND *, void *))0);

  status |= csound->AppendOpcode(
      csound, (char *)"ftsamplebank.i", sizeof(iftsamplebank), 0, 1,
      (char *)"i", (char *)"Siiii",
      (int (*)(CSOUND *, void *))iftsamplebank::init_,
      (int (*)(CSOUND *, void *))0, (int (*)(CSOUND *, void *))0);

  /*  status |= csound->AppendOpcode(csound,
      (char*)"ftsamplebank",
      0xffff,
      0,
      0,
      0,
      0,
      0,
      0,
      0); */

  status |= csound->AppendOpcode(
      csound, (char *)"directory", sizeof(DIR_STRUCT), 0, 1, (char *)"S[]",
      (char *)"SN", (int (*)(CSOUND *, void *))directory,
      (int (*)(CSOUND *, void *))0, (int (*)(CSOUND *, void *))0);
  return status;
}

#ifndef INIT_STATIC_MODULES
PUBLIC int csoundModuleCreate(CSOUND *csound) {
  IGN(csound);
  return 0;
}

PUBLIC int csoundModuleInit(CSOUND *csound) {
  return csoundModuleInit_ftsamplebank(csound);
}

PUBLIC int csoundModuleDestroy(CSOUND *csound) {
  IGN(csound);
  return 0;
}
#endif
}
<commit_msg>rory's changes<commit_after>/*
    This file is part of Csound.

        Copyright (C) 2014 Rory Walsh

    The Csound Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Lesser General Public
    License along with Csound; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    02110-1301 USA
 */

#include "OpcodeBase.hpp"
#include <algorithm>
#include <cmath>
#include <dirent.h>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <vector>

using namespace std;
using namespace csound;

/* this function will load all samples of supported types into function
   tables number 'index' and upwards.
   It return the number of samples loaded */
int loadSamplesToTables(CSOUND *csound, int index, char *directory,
                        int skiptime, int format, int channel);

//-----------------------------------------------------------------
//      i-rate class
//-----------------------------------------------------------------
class iftsamplebank : public OpcodeBase<iftsamplebank> {
public:
  // Outputs.
  MYFLT *numberOfFiles;
  // Inputs.
  STRINGDAT *sDirectory;
  MYFLT *index;
  //    MYFLT* trigger;
  MYFLT *skiptime;
  MYFLT *format;
  MYFLT *channel;

  iftsamplebank() {
    channel = 0;
    index = 0;
    skiptime = 0;
    format = 0;
    index = 0;
    numberOfFiles = 0;
    sDirectory = NULL;
  }

  // init-pass
  int init(CSOUND *csound) {

    *numberOfFiles = loadSamplesToTables(
        csound, *index, (char *)sDirectory->data, *skiptime, *format, *channel);
    return OK;
  }

  int noteoff(CSOUND *) { return OK; }
};

//-----------------------------------------------------------------
//      k-rate class
//-----------------------------------------------------------------
class kftsamplebank : public OpcodeBase<kftsamplebank> {
public:
  // Outputs.
  MYFLT *numberOfFiles;
  // Inputs.
  STRINGDAT *sDirectory;
  MYFLT *index;
  MYFLT *trigger;
  MYFLT *skiptime;
  MYFLT *format;
  MYFLT *channel;
  int internalCounter;
  kftsamplebank() : internalCounter(0) {
    channel = 0;
    index = 0;
    skiptime = 0;
    format = 0;
    index = 0;
    trigger = 0;
  }

  // init-pass
  int init(CSOUND *csound) {
    IGN(csound);
    *numberOfFiles =
          loadSamplesToTables(csound, *index, (char *)sDirectory->data,
                              *skiptime, *format, *channel);
    *trigger = 0;
    return OK;
  }

  int noteoff(CSOUND *) { return OK; }

  int kontrol(CSOUND *csound) {
    // if directry changes update tables..
    if (*trigger == 1) {
      *numberOfFiles =
          loadSamplesToTables(csound, *index, (char *)sDirectory->data,
                              *skiptime, *format, *channel);
      *trigger = 0;
    }
    return OK;
  }
};

//-----------------------------------------------------------------
//      load samples into function tables
//-----------------------------------------------------------------
int loadSamplesToTables(CSOUND *csound, int index, char *directory,
                        int skiptime, int format, int channel) {

  if (directory) {
    DIR *dir = opendir(directory);
    std::vector<std::string> fileNames;
    std::vector<std::string> fileExtensions;
    int noOfFiles = 0;
    fileExtensions.push_back(".wav");
    fileExtensions.push_back(".aiff");
    fileExtensions.push_back(".ogg");
    fileExtensions.push_back(".flac");

    // check for valid path first
    if (dir) {
      struct dirent *ent;
      while ((ent = readdir(dir)) != NULL) {
        std::ostringstream fullFileName;
        // only use supported file types
        for (int i = 0; (size_t)i < fileExtensions.size(); i++)
        {
          std::string fname = ent->d_name;
          std::string extension;
          if(fname.find_last_of(".") != std::string::npos)
            extension = fname.substr(fname.find_last_of("."));

          csound->Message(csound, "Extension: %s", extension.c_str());

          if(extension == fileExtensions[i])
            {
              if (strlen(directory) > 2) {
#if defined(WIN32)
              fullFileName << directory << "\\" << ent->d_name;
#else
              fullFileName << directory << "/" << ent->d_name;
#endif
            }
            else
              fullFileName << ent->d_name;

            noOfFiles++;

            fileNames.push_back(fullFileName.str());
          }
        }
      }

      // Sort names
      std::sort(fileNames.begin(), fileNames.end());

      // push statements to score, starting with table number 'index'
      for (int y = 0; (size_t)y < fileNames.size(); y++) {
        std::ostringstream statement;
        statement << "f" << index + y << " 0 0 1 \"" << fileNames[y] << "\" "
                  << skiptime << " " << format << " " << channel << "\n";
        // csound->MessageS(csound, CSOUNDMSG_ORCH, statement.str().c_str());
        csound->InputMessage(csound, statement.str().c_str());
      }

      closedir(dir);
    } else {
      csound->Message(csound,
                      Str("Cannot load file. Error opening directory: %s\n"),
                      directory);
    }

    // return number of files
    return noOfFiles;
  } else
    return 0;
}

typedef struct {
  OPDS h;
  ARRAYDAT *outArr;
  STRINGDAT *directoryName;
  MYFLT *extension;
} DIR_STRUCT;

/* this function will looks for files of a set type, in a particular directory
 */
std::vector<std::string> searchDir(CSOUND *csound, char *directory,
                                   char *extension);

#include "arrays.h"
#if 0
/* from Opcodes/arrays.c */
static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) {
    if (p->data==NULL || p->dimensions == 0 ||
        (p->dimensions==1 && p->sizes[0] < size)) {
      size_t ss;
      if (p->data == NULL) {
        CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL);
        p->arrayMemberSize = var->memBlockSize;
      }
      ss = p->arrayMemberSize*size;
      if (p->data==NULL) {
        p->data = (MYFLT*)csound->Calloc(csound, ss);
        p->allocated = ss;
      }
      else if (ss > p->allocated) {
        p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss);
        p->allocated = ss;
      }
      if (p->dimensions==0) {
        p->dimensions = 1;
        p->sizes = (int32_t*)csound->Malloc(csound, sizeof(int32_t));
      }
    }
    p->sizes[0] = size;
}
#endif

static int directory(CSOUND *csound, DIR_STRUCT *p) {
  int inArgCount = p->INOCOUNT;
  char *extension, *file;
  std::vector<std::string> fileNames;

  if (inArgCount == 0)
    return csound->InitError(
        csound, "%s", Str("Error: you must pass a directory as a string."));

  if (inArgCount == 1) {
    fileNames = searchDir(csound, p->directoryName->data, (char *)"");
  }

  else if (inArgCount == 2) {
    CS_TYPE *argType = csound->GetTypeForArg(p->extension);
    if (strcmp("S", argType->varTypeName) == 0) {
      extension = csound->Strdup(csound, ((STRINGDAT *)p->extension)->data);
      fileNames = searchDir(csound, p->directoryName->data, extension);
    } else
      return csound->InitError(csound,
                               "%s", Str("Error: second parameter to directory"
                                   " must be a string"));
  }

  int numberOfFiles = fileNames.size();
  tabinit(csound, p->outArr, numberOfFiles);
  STRINGDAT *strings = (STRINGDAT *)p->outArr->data;

  for (int i = 0; i < numberOfFiles; i++) {
    file = &fileNames[i][0u];
    strings[i].size = strlen(file) + 1;
    strings[i].data = csound->Strdup(csound, file);
  }

  fileNames.clear();

  return OK;
}

//-----------------------------------------------------------------
//      load samples into function tables
//-----------------------------------------------------------------
std::vector<std::string> searchDir(CSOUND *csound, char *directory,
                                   char *extension) {
  std::vector<std::string> fileNames;
  if (directory) {
    DIR *dir = opendir(directory);
    std::string fileExtension(extension);
    int noOfFiles = 0;

    // check for valid path first
    if (dir) {
      struct dirent *ent;
      while ((ent = readdir(dir)) != NULL) {
        std::ostringstream fullFileName;

        std::string fname = ent->d_name;
        size_t lastPos = fname.find_last_of(".");
        if (fname.length() > 2 && (fileExtension.empty() ||
            (lastPos != std::string::npos &&
            fname.substr(lastPos) == fileExtension))) {
          if (strlen(directory) > 2) {
#if defined(WIN32)
            fullFileName << directory << "\\" << ent->d_name;
#else
            fullFileName << directory << "/" << ent->d_name;
#endif
          } else
            fullFileName << ent->d_name;

          noOfFiles++;
          fileNames.push_back(fullFileName.str());
        }
      }

      // Sort names
      std::sort(fileNames.begin(), fileNames.end());
    } else {
      csound->Message(csound, Str("Cannot find directory. "
                                  "Error opening directory: %s\n"),
                      directory);
    }
    closedir(dir);
  }

  return fileNames;
}

extern "C" {

PUBLIC int csoundModuleInit_ftsamplebank(CSOUND *csound) {

  int status = csound->AppendOpcode(
      csound, (char *)"ftsamplebank.k", sizeof(kftsamplebank), 0, 3,
      (char *)"k", (char *)"Skkkkk",
      (int (*)(CSOUND *, void *))kftsamplebank::init_,
      (int (*)(CSOUND *, void *))kftsamplebank::kontrol_,
      (int (*)(CSOUND *, void *))0);

  status |= csound->AppendOpcode(
      csound, (char *)"ftsamplebank.i", sizeof(iftsamplebank), 0, 1,
      (char *)"i", (char *)"Siiii",
      (int (*)(CSOUND *, void *))iftsamplebank::init_,
      (int (*)(CSOUND *, void *))0, (int (*)(CSOUND *, void *))0);

  /*  status |= csound->AppendOpcode(csound,
      (char*)"ftsamplebank",
      0xffff,
      0,
      0,
      0,
      0,
      0,
      0,
      0); */

  status |= csound->AppendOpcode(
      csound, (char *)"directory", sizeof(DIR_STRUCT), 0, 1, (char *)"S[]",
      (char *)"SN", (int (*)(CSOUND *, void *))directory,
      (int (*)(CSOUND *, void *))0, (int (*)(CSOUND *, void *))0);
  return status;
}

#ifndef INIT_STATIC_MODULES
PUBLIC int csoundModuleCreate(CSOUND *csound) {
  IGN(csound);
  return 0;
}

PUBLIC int csoundModuleInit(CSOUND *csound) {
  return csoundModuleInit_ftsamplebank(csound);
}

PUBLIC int csoundModuleDestroy(CSOUND *csound) {
  IGN(csound);
  return 0;
}
#endif
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include <catch/catch.hpp>

#include "plant_generator.h"
#include "from_json.h"

using namespace std;
using namespace plantgen;

namespace
{
    constexpr size_t num_range_rng_tests = 1000;
}

TEST_CASE("Testing the Test Framework")
{
    SECTION("Variant Comparators")
    {
        SECTION("Value Comparators")
        {
            string std_string = "string";
            variant_value_t variant_string = "string";

            REQUIRE(variant_string == std_string);
            REQUIRE(std_string == variant_string);

            std::string other_str = "something else entirely";
            variant_value_t other_variant_str = "something_else_entirely";

            REQUIRE(std_string != other_str);
            REQUIRE(variant_string != other_variant_str);

            REQUIRE(variant_string != other_str);
            //REQUIRE(other_str != variant_string);

            REQUIRE(other_variant_str != std_string);
            //REQUIRE(std_string != other_variant_str);
        }

        SECTION("Value List Comparators")
        {
            std::vector<std::string> string_list = {"A", "B", "C", "D"};
            value_list_t variant_list = {"A", "B", "C", "D"};

            CHECK(string_list == variant_list);
            CHECK(variant_list == string_list);

            auto auto_strings = {"A","B","C","D"};
            REQUIRE(variant_list == auto_strings);

            std::vector<std::string> wrong_strings = {"X", "Y", "Z", "W"};
            REQUIRE(variant_list != wrong_strings);
        }
    }

    SECTION("Basic Node")
    {
        pregen_node_t node = node_from_json("data/basic_node.json");

        REQUIRE(node.name == "Basic Node");
        REQUIRE(node.values.size() == 4);
        REQUIRE(node.children.size() == 1); //properties

        REQUIRE(node.children[0].name == "Property");
        REQUIRE(node.children[0].values.size() == 4);

        std::vector<std::string> expected_node_value_strings = {"A", "B", "C", "D"};
        CHECK(node.values == expected_node_value_strings);

        expected_node_value_strings = {"1 A", "1 B", "1 C", "1 D"};
        CHECK(node.children[0].values == expected_node_value_strings);
    }

    SECTION("Fancy Node")
    {
        pregen_node_t node = node_from_json("data/fancy_node.json");

        REQUIRE(node.name == "Fancy Node");

        /// Properties
        REQUIRE(node.children.size() == 2);

        auto const& p1 = node.children[0];
        REQUIRE(p1.children.size() == 0);

        auto const& p2 = node.children[1];
        REQUIRE(p2.children.size() == 2);

        auto const& p2a = p2.children[0];
        auto const& p2b = p2.children[1];
        REQUIRE(p2a.children.size() == 0);
        REQUIRE(p2a.children.size() == 1);

        auto const& p2b_1 = p2b.children[0];
        REQUIRE(p2b_1.children.size() == 0);

        /// Values
        REQUIRE(node.values.size() == 2);
        REQUIRE(node.value_nodes.size() == 1);

        auto node_value_strings = {"ValueString A", "ValueString B"};
        CHECK(node.values == node_value_strings);

        auto const& vn = node.value_nodes[0];
        CHECK(vn.name == "ValueObj A");
        REQUIRE(vn.children.size() == 1);
        REQUIRE(vn.values.size() == 4);
        REQUIRE(vn.value_nodes.size() == 1);

        auto vn_value_strings = {"ValueObj Value A", "ValueObj Value B", "ValueObj Value C", "ValueObj Value D"};
        CHECK(vn.values == vn_value_strings);
        REQUIRE(vn.value_nodes[0].name == "Value Obj Value Obj");

        auto const& vn_p1 = vn.children[0];
        REQUIRE(vn_p1.name == "ValueObj Property One");
        auto vn_p1_value_strings = {"VObj P1 A", "VObj P1 B", "VObj P1 C", "VObj P1 D"};
        REQUIRE(vn_p1.values == vn_p1_value_strings);

        auto p1_value_strings = {"1 A", "1 B"};
        CHECK(p1.values == p1_value_strings);
        CHECK(p1.value_nodes[0].name == "ValueObj 1 A");
        CHECK(p1.value_nodes[1].name == "ValueObj 1 B");

        auto p2a_value_strings = {"2A - A", "2A - B", "2A - C", "2A - D"};
        CHECK(p2a.values == p2a_value_strings);

        REQUIRE(p2b_1.value_nodes.size() == 1);
        auto const& p2b_1_vnode = p2b_1.value_nodes[0];
        CHECK(p2b_1_vnode.name == "P2B_1 Value Node A");
        auto p2b_1_vnode_value_strings = {"Value Node Value A", "Value Node Value B", "Value Node Value C", "Value Node Value D"};
        REQUIRE(p2b_1_vnode.values == p2b_1_vnode_value_strings);
    }

    SECTION("Range Value")
    {
        pregen_node_t node = node_from_json("data/range_value.json");

        REQUIRE(node.name == "Range Value");

        REQUIRE(node.children.size() == 1);
        REQUIRE(node.values.size() == 2);
        REQUIRE(node.value_nodes.size() == 0);

        REQUIRE(std::holds_alternative<range_value_t>(node.values[0]));
        REQUIRE(std::holds_alternative<range_value_t>(node.values[1]));

        range_value_t r0 = std::get<range_value_t>(node.values[0]);
        std::vector<std::string> r0_strings = {"1 A", "1 B", "1 C", "1 D"};
        REQUIRE(r0 == r0_strings);

        range_value_t r1 = std::get<range_value_t>(node.values[1]);
        std::vector<std::string> r1_strings = {"2 A", "2 B", "2 C", "2 D"};
        REQUIRE(r1 == r1_strings);

        auto const& p1 = node.children[0];
        REQUIRE(p1.children.size() == 0);
        REQUIRE(p1.values.size() == 5);
        REQUIRE(p1.value_nodes.size() == 1);

        CHECK(p1.values[0] == std::string("NotRange A"));
        CHECK(p1.values[1] == std::string("NotRange B"));
        CHECK(p1.values[2] == std::string("NotRange C"));
        REQUIRE(std::holds_alternative<range_value_t>(p1.values[3]));
        REQUIRE(std::holds_alternative<range_value_t>(p1.values[4]));

        range_value_t p1r0 = std::get<range_value_t>(p1.values[3]);
        std::vector<std::string> p1r0_strings = {"P1R1 A", "P1R1 B", "P1R1 C", "P1R1 D"};
        REQUIRE(p1r0 == p1r0_strings);

        range_value_t p1r1 = std::get<range_value_t>(p1.values[4]);
        std::vector<std::string> p1r1_strings = {"P1R2 A", "P1R2 B", "P1R2 C", "P1R2 D"};
        REQUIRE(p1r1 == p1r1_strings);

        SECTION("Range Generation")
        {
            auto generated = generate_node(node);

            REQUIRE(generated.name == node.name);
            REQUIRE(generated.generated_values.size() == node.children.size());

            auto get_total = [](std::vector<std::string> const& gend_vals) -> uint32_t
            {
                uint32_t total = 0;
                for(auto const& v : gend_vals)
                {
                    total += stoi(v);
                }
            };

            REQUIRE(get_total(generated.generated_values) == 100);

            bool all_range_rng_passed = true;
            for(size_t i = 0; i < num_range_rng_tests; ++i)
                all_range_rng_passed &= (get_total(generated.generated_values) == 100);

            REQUIRE(all_range_rng_passed);
        }
    }
}<commit_msg>weight tests<commit_after>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include <catch/catch.hpp>

#include "plant_generator.h"
#include "from_json.h"

using namespace std;
using namespace plantgen;

namespace
{
    constexpr size_t num_range_rng_tests = 1000;
}

TEST_CASE("Testing the Test Framework")
{
    SECTION("Variant Comparators")
    {
        SECTION("Value Comparators")
        {
            string std_string = "string";
            variant_value_t variant_string = "string";

            REQUIRE(variant_string == std_string);
            REQUIRE(std_string == variant_string);

            std::string other_str = "something else entirely";
            variant_value_t other_variant_str = "something_else_entirely";

            REQUIRE(std_string != other_str);
            REQUIRE(variant_string != other_variant_str);

            REQUIRE(variant_string != other_str);
            //REQUIRE(other_str != variant_string);

            REQUIRE(other_variant_str != std_string);
            //REQUIRE(std_string != other_variant_str);
        }

        SECTION("Value List Comparators")
        {
            std::vector<std::string> string_list = {"A", "B", "C", "D"};
            value_list_t variant_list = {"A", "B", "C", "D"};

            CHECK(string_list == variant_list);
            CHECK(variant_list == string_list);

            auto auto_strings = {"A","B","C","D"};
            REQUIRE(variant_list == auto_strings);

            std::vector<std::string> wrong_strings = {"X", "Y", "Z", "W"};
            REQUIRE(variant_list != wrong_strings);
        }
    }

    SECTION("Basic Node")
    {
        pregen_node_t node = node_from_json("data/basic_node.json");

        REQUIRE(node.name == "Basic Node");
        REQUIRE(node.values.size() == 4);
        REQUIRE(node.children.size() == 1); //properties

        REQUIRE(node.children[0].name == "Property");
        REQUIRE(node.children[0].values.size() == 4);

        std::vector<std::string> expected_node_value_strings = {"A", "B", "C", "D"};
        CHECK(node.values == expected_node_value_strings);

        expected_node_value_strings = {"1 A", "1 B", "1 C", "1 D"};
        CHECK(node.children[0].values == expected_node_value_strings);
    }

    SECTION("Fancy Node")
    {
        pregen_node_t node = node_from_json("data/fancy_node.json");

        REQUIRE(node.name == "Fancy Node");

        /// Properties
        REQUIRE(node.children.size() == 2);

        auto const& p1 = node.children[0];
        REQUIRE(p1.children.size() == 0);

        auto const& p2 = node.children[1];
        REQUIRE(p2.children.size() == 2);

        auto const& p2a = p2.children[0];
        auto const& p2b = p2.children[1];
        REQUIRE(p2a.children.size() == 0);
        REQUIRE(p2a.children.size() == 1);

        auto const& p2b_1 = p2b.children[0];
        REQUIRE(p2b_1.children.size() == 0);

        /// Values
        REQUIRE(node.values.size() == 2);
        REQUIRE(node.value_nodes.size() == 1);

        auto node_value_strings = {"ValueString A", "ValueString B"};
        CHECK(node.values == node_value_strings);

        auto const& vn = node.value_nodes[0];
        CHECK(vn.name == "ValueObj A");
        REQUIRE(vn.children.size() == 1);
        REQUIRE(vn.values.size() == 4);
        REQUIRE(vn.value_nodes.size() == 1);

        auto vn_value_strings = {"ValueObj Value A", "ValueObj Value B", "ValueObj Value C", "ValueObj Value D"};
        CHECK(vn.values == vn_value_strings);
        REQUIRE(vn.value_nodes[0].name == "Value Obj Value Obj");

        auto const& vn_p1 = vn.children[0];
        REQUIRE(vn_p1.name == "ValueObj Property One");
        auto vn_p1_value_strings = {"VObj P1 A", "VObj P1 B", "VObj P1 C", "VObj P1 D"};
        REQUIRE(vn_p1.values == vn_p1_value_strings);

        auto p1_value_strings = {"1 A", "1 B"};
        CHECK(p1.values == p1_value_strings);
        CHECK(p1.value_nodes[0].name == "ValueObj 1 A");
        CHECK(p1.value_nodes[1].name == "ValueObj 1 B");

        auto p2a_value_strings = {"2A - A", "2A - B", "2A - C", "2A - D"};
        CHECK(p2a.values == p2a_value_strings);

        REQUIRE(p2b_1.value_nodes.size() == 1);
        auto const& p2b_1_vnode = p2b_1.value_nodes[0];
        CHECK(p2b_1_vnode.name == "P2B_1 Value Node A");
        auto p2b_1_vnode_value_strings = {"Value Node Value A", "Value Node Value B", "Value Node Value C", "Value Node Value D"};
        REQUIRE(p2b_1_vnode.values == p2b_1_vnode_value_strings);
    }

    SECTION("Range Value")
    {
        pregen_node_t node = node_from_json("data/range_value.json");

        REQUIRE(node.name == "Range Value");

        REQUIRE(node.children.size() == 1);
        REQUIRE(node.values.size() == 2);
        REQUIRE(node.value_nodes.size() == 0);

        REQUIRE(std::holds_alternative<range_value_t>(node.values[0]));
        REQUIRE(std::holds_alternative<range_value_t>(node.values[1]));

        range_value_t r0 = std::get<range_value_t>(node.values[0]);
        std::vector<std::string> r0_strings = {"1 A", "1 B", "1 C", "1 D"};
        REQUIRE(r0 == r0_strings);

        range_value_t r1 = std::get<range_value_t>(node.values[1]);
        std::vector<std::string> r1_strings = {"2 A", "2 B", "2 C", "2 D"};
        REQUIRE(r1 == r1_strings);

        auto const& p1 = node.children[0];
        REQUIRE(p1.children.size() == 0);
        REQUIRE(p1.values.size() == 5);
        REQUIRE(p1.value_nodes.size() == 1);

        CHECK(p1.values[0] == std::string("NotRange A"));
        CHECK(p1.values[1] == std::string("NotRange B"));
        CHECK(p1.values[2] == std::string("NotRange C"));
        REQUIRE(std::holds_alternative<range_value_t>(p1.values[3]));
        REQUIRE(std::holds_alternative<range_value_t>(p1.values[4]));

        range_value_t p1r0 = std::get<range_value_t>(p1.values[3]);
        std::vector<std::string> p1r0_strings = {"P1R1 A", "P1R1 B", "P1R1 C", "P1R1 D"};
        REQUIRE(p1r0 == p1r0_strings);

        range_value_t p1r1 = std::get<range_value_t>(p1.values[4]);
        std::vector<std::string> p1r1_strings = {"P1R2 A", "P1R2 B", "P1R2 C", "P1R2 D"};
        REQUIRE(p1r1 == p1r1_strings);

        SECTION("Range Generation")
        {
            auto generated = generate_node(node);

            REQUIRE(generated.name == node.name);
            REQUIRE(generated.generated_values.size() == node.children.size());

            auto get_total = [](std::vector<std::string> const& gend_vals) -> uint32_t
            {
                uint32_t total = 0;
                for(auto const& v : gend_vals)
                {
                    total += stoi(v);
                }
            };

            REQUIRE(get_total(generated.generated_values) == 100);

            bool all_range_rng_passed = true;
            for(size_t i = 0; i < num_range_rng_tests; ++i)
                all_range_rng_passed &= (get_total(generated.generated_values) == 100);

            REQUIRE(all_range_rng_passed);
        }
    }

    SECTION("Multi Value")
    {
        //TODO
    }

    /*
    SECTION("Weights")
    {
        pregen_node_t node = node_from_json("data/weights.json");

        REQUIRE(node.name == "Weights");

        REQUIRE(node.children.size() == 4);

        REQUIRE(node.values.size() == 5);
        CHECK(node.values[0].weight == 100);
        CHECK(node.values[0] == "A");
        CHECK(node.values[1].weight == 20);
        CHECK(node.values[1] == "B");
        CHECK(node.values[2].weight == 1);
        CHECK(node.values[2] == "C");
        CHECK(node.values[3].weight == 1);
        CHECK(node.values[3] == "D");
        CHECK(node.values[4].weight == 0);
        CHECK(node.values[4] == "E");

        CHECK(node.value_nodes[0].name == "ValueNode A");
        CHECK(node.value_nodes[0].weight == 25);
        CHECK(node.value_nodes[1].name == "ValueNode B");
        CHECK(node.value_nodes[1].weight == 250);
        CHECK(node.value_nodes[2].name == "ValueNode C");
        CHECK(node.value_nodes[2].weight == 4);
        CHECK(node.value_nodes[2].values.size() == 4);

        SECTION("Normal Weights")
        {
            auto const& n = node.children[0];
            REQUIRE(n.name == "Normal Weights");
            REQUIRE(n.values.size() == 0);
            REQUIRE(n.values_nodes.size() == 3);

            CHECK(n.values_nodes[0].name == "Normal A");
            CHECK(n.values_nodes[0].weight == 123)
            CHECK(n.values_nodes[1].name == "Normal B");
            CHECK(n.values_nodes[1].weight == 456)
            CHECK(n.values_nodes[2].name == "Normal C");
            CHECK(n.values_nodes[2].weight == 789)
        }

        SECTION("Inline Weights")
        {
            auto const& n = node.children[1];
            REQUIRE(n.name == "Inline Weights");
            REQUIRE(n.values.size() == 3);
            REQUIRE(n.values_nodes.size() == 0);

            CHECK(n.values_nodes[0].name == "Inline A");
            CHECK(n.values_nodes[0].weight == 123)
            CHECK(n.values_nodes[1].name == "Inline B");
            CHECK(n.values_nodes[1].weight == 456)
            CHECK(n.values_nodes[2].name == "Inline C");
            CHECK(n.values_nodes[2].weight == 789)
        }

        SECTION("Inline Normal Mix")
        {
            auto const& n = node.children[2];
            REQUIRE(n.name == "Inline Normal Mix");
            REQUIRE(n.values.size() == 3);
            REQUIRE(n.values_nodes.size() == 3);

            //lazy copypaste
            CHECK(n.values_nodes[0].name == "Normal A");
            CHECK(n.values_nodes[0].weight == 123)
            CHECK(n.values_nodes[1].name == "Normal B");
            CHECK(n.values_nodes[1].weight == 456)
            CHECK(n.values_nodes[2].name == "Normal C");
            CHECK(n.values_nodes[2].weight == 789)

            //lazy copypaste
            CHECK(n.values_nodes[0].name == "Inline A");
            CHECK(n.values_nodes[0].weight == 123)
            CHECK(n.values_nodes[1].name == "Inline B");
            CHECK(n.values_nodes[1].weight == 456)
            CHECK(n.values_nodes[2].name == "Inline C");
            CHECK(n.values_nodes[2].weight == 789)
        }

        SECTION("Weight of Values")
        {
            auto const& n = node.children[3];
            REQUIRE(n.name == "Weight of Values");
            REQUIRE(n.values.size() == 0);
            REQUIRE(n.values_nodes.size() == 1);

            auto const& vn = node.value_nodes[0];
            auto sum = total_weight(vn);
            REQUIRE(vn.weight == sum);
        }
    }
    */
}<|endoftext|>


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

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#define RM_PROPERTY_ID_LABEL        1
#define RM_PROPERTY_ID_ID           2
#define RM_PROPERTY_ID_ENABLED      4
#define RM_PROPERTY_ID_INTERACTIVE  5

typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::lang::XServiceInfo
                                >   ORoadmapEntry_Base;

class ORoadmapEntry :public ORoadmapEntry_Base
            ,public ::comphelper::OMutexAndBroadcastHelper
            ,public ::comphelper::OPropertyContainer
            ,public ::comphelper::OPropertyArrayUsageHelper< ORoadmapEntry >
{

public:
       ORoadmapEntry();

protected:
    DECLARE_XINTERFACE()        // merge XInterface implementations
    DECLARE_XTYPEPROVIDER()     // merge XTypeProvider implementations

    /// @see ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
        SAL_CALL getPropertySetInfo()
        throw (::com::sun::star::uno::RuntimeException);

    // OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const;

    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

    // other stuff
    // ...
    // (e.g. DECLARE_SERVICE_INFO();)

protected:
    // <properties>
    ::rtl::OUString     m_sLabel;
    sal_Int32           m_nID;
    sal_Bool            m_bEnabled;
    sal_Bool            m_bInteractive;

    // </properties>
};

#endif

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

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#define RM_PROPERTY_ID_LABEL        1
#define RM_PROPERTY_ID_ID           2
#define RM_PROPERTY_ID_ENABLED      4
#define RM_PROPERTY_ID_INTERACTIVE  5

typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::lang::XServiceInfo
                                >   ORoadmapEntry_Base;

class ORoadmapEntry :public ORoadmapEntry_Base
            ,public ::comphelper::OMutexAndBroadcastHelper
            ,public ::comphelper::OPropertyContainer
            ,public ::comphelper::OPropertyArrayUsageHelper< ORoadmapEntry >
{

public:
       ORoadmapEntry();

protected:
    DECLARE_XINTERFACE()        // merge XInterface implementations
    DECLARE_XTYPEPROVIDER()     // merge XTypeProvider implementations

    /// @see ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
        SAL_CALL getPropertySetInfo()
        throw (::com::sun::star::uno::RuntimeException);

    // OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const;

    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

    // other stuff
    // ...
    // (e.g. DECLARE_SERVICE_INFO();)

protected:
    // <properties>
    ::rtl::OUString     m_sLabel;
    sal_Int32           m_nID;
    sal_Bool            m_bEnabled;
    sal_Bool            m_bInteractive;

    // </properties>
};

#endif

<|endoftext|>


<commit_before>#include <stdio.h>
#include "utl/Logger.h"

#include "db.h"
using namespace odb;

dbMaster* createMaster2X1(dbLib*      lib,
                          const char* name,
                          uint        width,
                          uint        height,
                          const char* in1,
                          const char* in2,
                          const char* out)
{
  dbMaster* master = dbMaster::create(lib, name);
  master->setWidth(width);
  master->setHeight(height);
  master->setType(dbMasterType::CORE);
  dbMTerm::create(master, in1, dbIoType::INPUT, dbSigType::SIGNAL);
  dbMTerm::create(master, in2, dbIoType::INPUT, dbSigType::SIGNAL);
  dbMTerm::create(master, out, dbIoType::OUTPUT, dbSigType::SIGNAL);
  master->setFrozen();
  return master;
}

dbDatabase* createSimpleDB()
{
  utl::Logger* logger = new utl::Logger();
  dbDatabase*  db   = dbDatabase::create();
  db->setLogger(logger);
  dbTech*      tech = dbTech::create(db);
  dbTechLayer* layer
      = dbTechLayer::create(tech, "L1", dbTechLayerType::MASTERSLICE);
  dbLib*    lib   = dbLib::create(db, "lib1", ',');
  dbChip*   chip  = dbChip::create(db);
  dbBlock*  block = dbBlock::create(chip, "simple_block");
  dbMaster* and2  = createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o");
  dbMaster* or2   = createMaster2X1(lib, "or2", 500, 500, "a", "b", "o");
  return db;
}

// #     (n1)   +-----
// #    --------|a    \    (n5)
// #     (n2)   | (i1)o|-----------+
// #    --------|b    /            |       +-------
// #            +-----             +--------\a     \    (n7)
// #                                         ) (i3)o|---------------
// #     (n3)   +-----             +--------/b     /
// #    --------|a    \    (n6)    |       +-------
// #     (n4)   | (i2)o|-----------+
// #    --------|b    /
// #            +-----
dbDatabase* create2LevetDbNoBTerms()
{
  dbDatabase* db    = createSimpleDB();
  dbLib*      lib   = db->findLib("lib1");
  dbChip*     chip  = db->getChip();
  dbBlock*    block = chip->getBlock();
  auto        and2  = lib->findMaster("and2");
  auto        or2   = lib->findMaster("or2");
  dbInst*     i1    = dbInst::create(block, and2, "i1");
  dbInst*     i2    = dbInst::create(block, and2, "i2");
  dbInst*     i3    = dbInst::create(block, or2, "i3");
  dbNet*      n1    = dbNet::create(block, "n1");
  dbNet*      n2    = dbNet::create(block, "n2");
  dbNet*      n3    = dbNet::create(block, "n3");
  dbNet*      n4    = dbNet::create(block, "n4");
  dbNet*      n5    = dbNet::create(block, "n5");
  dbNet*      n6    = dbNet::create(block, "n6");
  dbNet*      n7    = dbNet::create(block, "n7");
  dbITerm::connect(i1->findITerm("a"), n1);
  dbITerm::connect(i1->findITerm("b"), n2);
  dbITerm::connect(i2->findITerm("a"), n3);
  dbITerm::connect(i2->findITerm("b"), n4);
  dbITerm::connect(i3->findITerm("a"), n5);
  dbITerm::connect(i3->findITerm("b"), n6);
  dbITerm::connect(i1->findITerm("o"), n5);
  dbITerm::connect(i2->findITerm("o"), n6);
  dbITerm::connect(i3->findITerm("o"), n7);
  return db;
}
dbDatabase* create2LevetDbWithBTerms()
{
  dbDatabase* db    = create2LevetDbNoBTerms();
  dbBlock*    block = db->getChip()->getBlock();
  auto        n1    = block->findNet("n1");
  auto        n2    = block->findNet("n2");
  auto        n7    = block->findNet("n7");
  dbBTerm*    IN1   = dbBTerm::create(n1, "IN1");
  IN1->setIoType(dbIoType::INPUT);
  dbBTerm* IN2 = dbBTerm::create(n2, "IN2");
  IN1->setIoType(dbIoType::INPUT);
  dbBTerm* OUT = dbBTerm::create(n7, "IN3");
  IN1->setIoType(dbIoType::OUTPUT);
  return db;
}

dbDatabase* create3LevetDbNoBTerms()
{
  dbDatabase* db    = createSimpleDB();
  dbLib*      lib   = db->findLib("lib1");
  dbChip*     chip  = db->getChip();
  dbBlock*    block = chip->getBlock();
  auto        and2  = lib->findMaster("and2");
  auto        or2   = lib->findMaster("or2");
  dbInst*     i1    = dbInst::create(block, and2, "i1");
  dbInst*     i2    = dbInst::create(block, and2, "i2");
  dbInst*     i3    = dbInst::create(block, or2, "i3");
  dbInst*     i4    = dbInst::create(block, or2, "i4");
  dbNet*      n1    = dbNet::create(block, "n1");
  dbNet*      n2    = dbNet::create(block, "n2");
  dbNet*      n3    = dbNet::create(block, "n3");
  dbNet*      n4    = dbNet::create(block, "n4");
  dbNet*      n5    = dbNet::create(block, "n5");
  dbNet*      n6    = dbNet::create(block, "n6");
  dbNet*      n7    = dbNet::create(block, "n7");
  dbNet*      n8    = dbNet::create(block, "n8");
  dbNet*      n9    = dbNet::create(block, "n9");
  dbITerm::connect(i1->findITerm("a"), n1);
  dbITerm::connect(i1->findITerm("b"), n2);
  dbITerm::connect(i2->findITerm("a"), n3);
  dbITerm::connect(i2->findITerm("b"), n4);
  dbITerm::connect(i3->findITerm("a"), n5);
  dbITerm::connect(i3->findITerm("b"), n6);
  dbITerm::connect(i1->findITerm("o"), n5);
  dbITerm::connect(i2->findITerm("o"), n6);
  dbITerm::connect(i3->findITerm("o"), n7);
  dbITerm::connect(i4->findITerm("a"), n7);
  dbITerm::connect(i4->findITerm("b"), n8);
  dbITerm::connect(i4->findITerm("o"), n9);

  return db;
}
<commit_msg>remove outdated db test helper method<commit_after>#include <stdio.h>
#include "utl/Logger.h"

#include "db.h"
using namespace odb;

dbMaster* createMaster2X1(dbLib*      lib,
                          const char* name,
                          uint        width,
                          uint        height,
                          const char* in1,
                          const char* in2,
                          const char* out)
{
  dbMaster* master = dbMaster::create(lib, name);
  master->setWidth(width);
  master->setHeight(height);
  master->setType(dbMasterType::CORE);
  dbMTerm::create(master, in1, dbIoType::INPUT, dbSigType::SIGNAL);
  dbMTerm::create(master, in2, dbIoType::INPUT, dbSigType::SIGNAL);
  dbMTerm::create(master, out, dbIoType::OUTPUT, dbSigType::SIGNAL);
  master->setFrozen();
  return master;
}

dbDatabase* createSimpleDB()
{
  utl::Logger* logger = new utl::Logger();
  dbDatabase*  db   = dbDatabase::create();
  db->setLogger(logger);
  dbTech*      tech = dbTech::create(db);
  dbTechLayer* layer
      = dbTechLayer::create(tech, "L1", dbTechLayerType::MASTERSLICE);
  dbLib*    lib   = dbLib::create(db, "lib1", ',');
  dbChip*   chip  = dbChip::create(db);
  dbBlock*  block = dbBlock::create(chip, "simple_block");
  dbMaster* and2  = createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o");
  dbMaster* or2   = createMaster2X1(lib, "or2", 500, 500, "a", "b", "o");
  return db;
}

// #     (n1)   +-----
// #    --------|a    \    (n5)
// #     (n2)   | (i1)o|-----------+
// #    --------|b    /            |       +-------
// #            +-----             +--------\a     \    (n7)
// #                                         ) (i3)o|---------------
// #     (n3)   +-----             +--------/b     /
// #    --------|a    \    (n6)    |       +-------
// #     (n4)   | (i2)o|-----------+
// #    --------|b    /
// #            +-----
dbDatabase* create2LevetDbNoBTerms()
{
  dbDatabase* db    = createSimpleDB();
  dbLib*      lib   = db->findLib("lib1");
  dbChip*     chip  = db->getChip();
  dbBlock*    block = chip->getBlock();
  auto        and2  = lib->findMaster("and2");
  auto        or2   = lib->findMaster("or2");
  dbInst*     i1    = dbInst::create(block, and2, "i1");
  dbInst*     i2    = dbInst::create(block, and2, "i2");
  dbInst*     i3    = dbInst::create(block, or2, "i3");
  dbNet*      n1    = dbNet::create(block, "n1");
  dbNet*      n2    = dbNet::create(block, "n2");
  dbNet*      n3    = dbNet::create(block, "n3");
  dbNet*      n4    = dbNet::create(block, "n4");
  dbNet*      n5    = dbNet::create(block, "n5");
  dbNet*      n6    = dbNet::create(block, "n6");
  dbNet*      n7    = dbNet::create(block, "n7");
  dbITerm::connect(i1->findITerm("a"), n1);
  dbITerm::connect(i1->findITerm("b"), n2);
  dbITerm::connect(i2->findITerm("a"), n3);
  dbITerm::connect(i2->findITerm("b"), n4);
  dbITerm::connect(i3->findITerm("a"), n5);
  dbITerm::connect(i3->findITerm("b"), n6);
  dbITerm::connect(i1->findITerm("o"), n5);
  dbITerm::connect(i2->findITerm("o"), n6);
  dbITerm::connect(i3->findITerm("o"), n7);
  return db;
}
dbDatabase* create2LevetDbWithBTerms()
{
  dbDatabase* db    = create2LevetDbNoBTerms();
  dbBlock*    block = db->getChip()->getBlock();
  auto        n1    = block->findNet("n1");
  auto        n2    = block->findNet("n2");
  auto        n7    = block->findNet("n7");
  dbBTerm*    IN1   = dbBTerm::create(n1, "IN1");
  IN1->setIoType(dbIoType::INPUT);
  dbBTerm* IN2 = dbBTerm::create(n2, "IN2");
  IN1->setIoType(dbIoType::INPUT);
  dbBTerm* OUT = dbBTerm::create(n7, "IN3");
  IN1->setIoType(dbIoType::OUTPUT);
  return db;
}
<|endoftext|>