text:
/**
@file
@author from CrypoNote (see copyright below; Andrey N. Sabelnikov)
@monero rfree
@brief the connection templated-class for one peer connection
*/
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// 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 Andrey N. Sabelnikov 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  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 <boost/foreach.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/chrono.hpp>
#include <boost/utility/value_init.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
#include <boost/thread/condition_variable.hpp> // TODO
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include "warnings.h"
#include "string_tools_lexical.h"
#include "misc_language.h"
#include "net/local_ip.h"
#include "pragma_comp_defs.h"

#include <sstream>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <random>
#include "common/stack_trace.h"

#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"

#define AGGRESSIVE_TIMEOUT_THRESHOLD 120 // sockets
#define NEW_CONNECTION_TIMEOUT_LOCAL 1200000 // 2 minutes
#define NEW_CONNECTION_TIMEOUT_REMOTE 10000 // 10 seconds
#define DEFAULT_TIMEOUT_MS_LOCAL 1800000 // 30 minutes
#define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes
#define TIMEOUT_EXTRA_MS_PER_BYTE 0.2

#include "connection_impl.inl"

PRAGMA_WARNING_PUSH
namespace epee
{
namespace net_utils
{
  /************************************************************************/
  /*                                                                      */
  /************************************************************************/

  template<class t_wire_handler>
  boosted_tcp_server<t_wire_handler>::boosted_tcp_server( t_connection_type connection_type ) :
    m_shared_state(std::make_shared<typename connection<t_wire_handler>::shared_state>()),
    m_io_service_local_instance(new worker()),
    io_service_(m_io_service_local_instance->io_service),
    acceptor_(io_service_),
    acceptor_ipv6(io_service_),
    m_stop_signal_sent(false), m_port(0),
    m_threads_count(0),
    m_thread_index(0),
		m_connection_type( connection_type ),
    new_connection_(),
    new_connection_ipv6()
  {
    create_server_type_map();
    m_thread_name_prefix = "NET";
  }

  template<class t_wire_handler>
  boosted_tcp_server<t_wire_handler>::boosted_tcp_server(boost::asio::io_service& extarnal_io_service, t_connection_type connection_type) :
    m_shared_state(std::make_shared<typename connection<t_wire_handler>::shared_state>()),
    io_service_(extarnal_io_service),
    acceptor_(io_service_),
    acceptor_ipv6(io_service_),
    m_stop_signal_sent(false), m_port(0),
    m_threads_count(0),
    m_thread_index(0),
		m_connection_type(connection_type),
    new_connection_(),
    new_connection_ipv6()
  {
    create_server_type_map();
    m_thread_name_prefix = "NET";
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  boosted_tcp_server<t_wire_handler>::~boosted_tcp_server()
  {
    this->send_stop_signal();
    timed_wait_server_stop(10000);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::create_server_type_map()
  {
		server_type_map["NET"] = e_connection_type_NET;
		server_type_map["RPC"] = e_connection_type_RPC;
		server_type_map["P2P"] = e_connection_type_P2P;
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
    bool boosted_tcp_server<t_wire_handler>::init_server(uint32_t port,  const std::string& address,
	uint32_t port_ipv6, const std::string& address_ipv6, bool use_ipv6, bool require_ipv4,
	ssl_options_t ssl_options)
  {
    TRY_ENTRY();
    m_stop_signal_sent = false;
    m_port = port;
    m_port_ipv6 = port_ipv6;
    m_address = address;
    m_address_ipv6 = address_ipv6;
    m_use_ipv6 = use_ipv6;
    m_require_ipv4 = require_ipv4;

    if (ssl_options)
      m_shared_state->configure_ssl(std::move(ssl_options));

    std::string ipv4_failed = "";
    std::string ipv6_failed = "";
    try
    {
      boost::asio::ip::tcp::resolver resolver(io_service_);
      boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
      boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
      acceptor_.open(endpoint.protocol());
#if !defined(_WIN32)
      acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
#endif
      acceptor_.bind(endpoint);
      acceptor_.listen();
      boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
      m_port = binded_endpoint.port();
      MINFO("start accept (IPv4) "<<address<<":"<<port);

      new_connection_.reset(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, m_shared_state->ssl_options().support));

      acceptor_.async_accept(new_connection_->socket(),	boost::bind(&MyType::handle_accept_ipv4, this,boost::asio::placeholders::error));
    }
    catch (const std::exception &e)
    {
      ipv4_failed = e.what();
    }

    if (ipv4_failed != "")
    {
      MERROR("Failed to bind IPv4: " << ipv4_failed);
      if (require_ipv4)
      {
        throw std::runtime_error("Failed to bind IPv4 (set to required)");
      }
    }

    if (use_ipv6)
    {
      try
      {
        if (port_ipv6 == 0) port_ipv6 = port; // default arg means bind to same port as ipv4
        boost::asio::ip::tcp::resolver resolver(io_service_);
        boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
        boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
        acceptor_ipv6.open(endpoint.protocol());
#if !defined(_WIN32)
        acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
#endif
        acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
        acceptor_ipv6.bind(endpoint);
        acceptor_ipv6.listen();
        boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
        m_port_ipv6 = binded_endpoint.port();
        MDEBUG("start accept (IPv6)");
        new_connection_ipv6.reset(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, m_shared_state->ssl_options().support));

        acceptor_ipv6.async_accept(new_connection_ipv6->socket(),boost::bind(&boosted_tcp_server<t_wire_handler>::handle_accept_ipv6, this,boost::asio::placeholders::error));
      }
      catch (const std::exception &e)
      {
        ipv6_failed = e.what();
      }
    }

      if (use_ipv6 && ipv6_failed != "")
      {
        MERROR("Failed to bind IPv6: " << ipv6_failed);
        if (ipv4_failed != "")
        {
          throw std::runtime_error("Failed to bind IPv4 and IPv6");
        }
      }

    return true;
    }
    catch (const std::exception &e)
    {
      MFATAL("Error starting server: " << e.what());
      return false;
    }
    catch (...)
    {
      MFATAL("Error starting server");
      return false;
    }
  }
  //-----------------------------------------------------------------------------
PUSH_WARNINGS
DISABLE_GCC_WARNING(maybe-uninitialized)
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::init_server(const std::string port,  const std::string& address,
      const std::string port_ipv6, const std::string address_ipv6, bool use_ipv6, bool require_ipv4,
      ssl_options_t ssl_options)
  {
    uint32_t p = 0;
    uint32_t p_ipv6 = 0;

    if (port.size() && !string_tools::get_xtype_from_string(p, port)) {
      MERROR("Failed to convert port no = " << port);
      return false;
    }

    if (port_ipv6.size() && !string_tools::get_xtype_from_string(p_ipv6, port_ipv6)) {
      MERROR("Failed to convert port no = " << port_ipv6);
      return false;
    }
    return this->init_server(p, address, p_ipv6, address_ipv6, use_ipv6, require_ipv4, std::move(ssl_options));
  }
POP_WARNINGS
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::worker_thread()
  {
    TRY_ENTRY();
    uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index);
    std::string thread_name = std::string("[") + m_thread_name_prefix;
    thread_name += boost::to_string(local_thr_index) + "]";
    MLOG_SET_THREAD_NAME(thread_name);
    MINFO("Thread name: " << m_thread_name_prefix<<" run");
    while(!m_stop_signal_sent)
    {
      try
      {
        io_service_.run();
        return true;
      }
      catch(const std::exception& ex)
      {
        _erro("Exception at server worker thread, what=" << ex.what());
      }
      catch(...)
      {
        _erro("Exception at server worker thread, unknown execption");
      }
    }
    //_info("Worker thread finished");
    return true;
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::worker_thread", false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::set_threads_prefix(const std::string& prefix_name)
  {
    m_thread_name_prefix = prefix_name;
		auto it = server_type_map.find(m_thread_name_prefix);
		if (it==server_type_map.end()) throw std::runtime_error("Unknown prefix/server type:" + std::string(prefix_name));
    auto connection_type = it->second; // the value of type
    MINFO("Set server type to: " << connection_type << " from name: " << m_thread_name_prefix << ", prefix_name = " << prefix_name);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::set_connection_filter(i_connection_filter* pfilter)
  {
    assert(m_shared_state != nullptr); // always set in constructor
    m_shared_state->pfilter = pfilter;
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::run_server(size_t threads_count, bool wait, const boost::thread::attributes& attrs)
  {
    TRY_ENTRY();
    m_threads_count = threads_count;
    m_main_thread_id = boost::this_thread::get_id();
    MLOG_SET_THREAD_NAME("[SRV_MAIN]");
    while(!m_stop_signal_sent)
    {

      // Create a pool of threads to run all of the io_services.
      CRITICAL_REGION_BEGIN(m_threads_lock);
      for (std::size_t i = 0; i < threads_count; ++i)
      {
        boost::shared_ptr<boost::thread> thread(new boost::thread(
          attrs, boost::bind(&MyType::worker_thread, this)));

        MINFO("Run server thread name: " << m_thread_name_prefix <<" "<<i);
        m_threads.push_back(thread);
      }
      CRITICAL_REGION_END();
      // Wait for all threads in the pool to exit.
      if (wait)
      {
		    MINFO("JOINING all threads");
        for (std::size_t i = 0; i < m_threads.size(); ++i) {
			   m_threads[i]->join();
         }
         MINFO("JOINING all threads - almost");
        m_threads.clear();
        MINFO("JOINING all threads - DONE");

      }
      else {
		    MINFO("Reiniting OK.");
        return true;
      }

      if(wait && !m_stop_signal_sent)
      {
        //some problems with the listening socket ?..
        _dbg1("Net service stopped without stop request, restarting...");
        if(!this->init_server(m_port, m_address, m_port_ipv6, m_address_ipv6, m_use_ipv6, m_require_ipv4))
        {
          _dbg1("Reiniting service failed, exit.");
          return false;
        }else
        {
          _dbg1("Reiniting OK.");
        }
      }
    }
    return true;
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::run_server", false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::is_thread_worker()
  {
    TRY_ENTRY();
    CRITICAL_REGION_LOCAL(m_threads_lock);
    BOOST_FOREACH(boost::shared_ptr<boost::thread>& thp,  m_threads)
    {
      if(thp->get_id() == boost::this_thread::get_id())
        return true;
    }
    if(m_threads_count == 1 && boost::this_thread::get_id() == m_main_thread_id)
      return true;
    return false;
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::is_thread_worker", false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::timed_wait_server_stop(uint64_t wait_mseconds)
  {
    TRY_ENTRY();
    boost::chrono::milliseconds ms(wait_mseconds);
    for (std::size_t i = 0; i < m_threads.size(); ++i)
    {
      if(m_threads[i]->joinable() && !m_threads[i]->try_join_for(ms))
      {
        _dbg1("Interrupting thread " << m_threads[i]->native_handle());
        m_threads[i]->interrupt();
      }
    }
    return true;
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::timed_wait_server_stop", false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::send_stop_signal()
  {
    m_stop_signal_sent = true;
    auto *state = static_cast<typename connection<t_wire_handler>::shared_state*>(m_shared_state.get());
    state->stop_signal_sent = true;
    TRY_ENTRY();
    connections_mutex.lock();
    for (auto &c: connections_)
    {
      c->cancel();
    }
    connections_.clear();
    connections_mutex.unlock();
    io_service_.stop();
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::send_stop_signal()", void());
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::handle_accept_ipv4(const boost::system::error_code& e)
  {
    this->handle_accept(e, false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::handle_accept_ipv6(const boost::system::error_code& e)
  {
    this->handle_accept(e, true);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  void boosted_tcp_server<t_wire_handler>::handle_accept(const boost::system::error_code& e, bool ipv6)
  {
    MINFO("handle_accept");

    boost::asio::ip::tcp::acceptor* current_acceptor = &acceptor_;
    connection_ptr* current_new_connection = &new_connection_;
    auto accept_function_pointer = &MyType::handle_accept_ipv4;
    if (ipv6)
    {
      current_acceptor = &acceptor_ipv6;
      current_new_connection = &new_connection_ipv6;
      accept_function_pointer = &MyType::handle_accept_ipv6;
    }

    try
    {
    if (!e)
    {
      if (m_connection_type == e_connection_type_RPC) {
        const char *ssl_message = "unknown";
        switch ((*current_new_connection)->get_ssl_support())
        {
          case epee::net_utils::ssl_support_t::e_ssl_support_disabled: ssl_message = "disabled"; break;
          case epee::net_utils::ssl_support_t::e_ssl_support_enabled: ssl_message = "enabled"; break;
          case epee::net_utils::ssl_support_t::e_ssl_support_autodetect: ssl_message = "autodetection"; break;
        }
        MDEBUG("New server for RPC connections, SSL " << ssl_message);
        (*current_new_connection)->setRpcStation(); // hopefully this is not needed actually
      }
      connection_ptr conn(std::move((*current_new_connection)));

      (*current_new_connection).reset(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, conn->get_ssl_support()));

      current_acceptor->async_accept((*current_new_connection)->socket(),
          boost::bind(accept_function_pointer, this,boost::asio::placeholders::error));

      boost::asio::socket_base::keep_alive opt(true);
      conn->socket().set_option(opt);

      const bool res = conn->start(true, 1 < m_threads_count);
      if (!res)
      {
        conn->cancel();
        return;
      }
      conn->save_dbg_log();
      return;
    }
    else
    {
      MERROR("Error in boosted_tcp_server<t_wire_handler>::handle_accept: " << e);
    }
    }
    catch (const std::exception &e)
    {
      MERROR("Exception in boosted_tcp_server<t_wire_handler>::handle_accept: " << e.what());
    }

    // error path, if e or exception
    assert(m_shared_state != nullptr); // always set in constructor
    _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_shared_state->sock_count);
    misc_utils::sleep_no_w(100);

    (*current_new_connection).reset(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, (*current_new_connection)->get_ssl_support()));

    current_acceptor->async_accept((*current_new_connection)->socket(),boost::bind(accept_function_pointer, this,boost::asio::placeholders::error));
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote, epee::net_utils::ssl_support_t ssl_support)
  {
    if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock)))
    {
      connection_ptr conn(new connection<t_wire_handler>(std::move(sock), m_shared_state, m_connection_type, ssl_support));
      if(conn->start(false, 1 < m_threads_count, std::move(real_remote)))
      {
        conn->get_context(out);
        conn->save_dbg_log();
        return true;
      }
    }
    else
    {
	MWARNING(out << " was not added, socket/io_service mismatch");
    }
    return false;
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  typename boosted_tcp_server<t_wire_handler>::try_connect_result_t boosted_tcp_server<t_wire_handler>::try_connect(connection_ptr new_connection_l, const std::string& adr, const std::string& port, boost::asio::ip::tcp::socket &sock_, const boost::asio::ip::tcp::endpoint &remote_endpoint, const std::string &bind_ip, uint32_t conn_timeout, epee::net_utils::ssl_support_t ssl_support)
  {
    TRY_ENTRY();

 MINFO("try_connect "<<adr<<","<<port<<","<<conn_timeout<<"remote "<<remote_endpoint<<",bind_ip "<<bind_ip<<",ssl "<<std::to_string((uint8_t)ssl_support)<<",connections_ size now " << connections_.size());

    sock_.open(remote_endpoint.protocol());
    if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
    {
      boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
      boost::system::error_code ec;
      sock_.bind(local_endpoint, ec);
      if (ec)
      {
        MERROR("Error binding to " << bind_ip << ": " << ec.message());
        if (sock_.is_open())
          sock_.close();
        return CONNECT_FAILURE;
      }
    }

    /*
    NOTICE: be careful to make sync connection from event handler: in case if all threads suddenly do sync connect, there will be no thread to dispatch events from io service.
    */

    boost::system::error_code ec = boost::asio::error::would_block;

    //have another free thread(s), work in wait mode, without event handling
    struct local_async_context
    {
      boost::system::error_code ec;
      boost::mutex connect_mut;
      boost::condition_variable cond;
    };

    boost::shared_ptr<local_async_context> local_shared_context(new local_async_context());
    local_shared_context->ec = boost::asio::error::would_block;
    boost::unique_lock<boost::mutex> lock(local_shared_context->connect_mut);
    auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr<local_async_context> shared_context)
    {
      shared_context->connect_mut.lock();
      shared_context->ec = ec_;
      shared_context->cond.notify_one();
      shared_context->connect_mut.unlock();
    };

    sock_.async_connect(remote_endpoint, std::bind<void>(connect_callback, std::placeholders::_1, local_shared_context));
    while(local_shared_context->ec == boost::asio::error::would_block)
    {
      bool r = local_shared_context->cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(conn_timeout));
      if (m_stop_signal_sent)
      {
        if (sock_.is_open())
          sock_.close();
        return CONNECT_FAILURE;
      }
      if(local_shared_context->ec == boost::asio::error::would_block && !r)
      {
        //timeout
        sock_.close();
        MINFO("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")");
        return CONNECT_FAILURE;
      }
    }
    ec = local_shared_context->ec;

    if (ec || !sock_.is_open())
    {
      MINFO("Some problems at connect, message: " << ec.message());
      if (sock_.is_open())
        sock_.close();
      return CONNECT_FAILURE;
    }

    MINFO("Connected success to " << adr << ':' << port);
    tools::log_stack_trace("conn");
    const ssl_support_t ssl_support = new_connection_l->get_ssl_support();
    if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
    {
      // Handshake
      MDEBUG("Handshaking SSL...");
      if (!new_connection_l->handshake(boost::asio::ssl::stream_base::client))
      {
        if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
        {
          boost::system::error_code ignored_ec;
          sock_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
          sock_.close();
          return CONNECT_NO_SSL;
        }
        MERROR("SSL handshake failed");
        if (sock_.is_open())
          sock_.close();
        return CONNECT_FAILURE;
      }
    }

    return CONNECT_SUCCESS;

    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::try_connect", CONNECT_FAILURE);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler>
  bool boosted_tcp_server<t_wire_handler>::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support)
  {

    TRY_ENTRY();

    connection_ptr new_connection_l(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, ssl_support) );
    connections_mutex.lock();
    connections_.insert(new_connection_l);
    MINFO("connect "<<adr<<","<<port<<","<<conn_timeout<<",bind_ip "<<bind_ip<<",ssl "<<std::to_string((uint8_t)ssl_support)<<",connections_ size now " << connections_.size());
    connections_mutex.unlock();
    epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); });
    boost::asio::ip::tcp::socket&  sock_ = new_connection_l->socket();

    bool try_ipv6 = false;

    boost::asio::ip::tcp::resolver resolver(io_service_);
    boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
    boost::system::error_code resolve_error;
    boost::asio::ip::tcp::resolver::iterator iterator;
    try
    {
      //resolving ipv4 address as ipv6 throws, catch here and move on
      iterator = resolver.resolve(query, resolve_error);
    }
    catch (const boost::system::system_error& e)
    {
      if (!m_use_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
            resolve_error != boost::asio::error::host_not_found_try_again))
      {
        throw;
      }
      try_ipv6 = true;
    }
    catch (...)
    {
      throw;
    }

    std::string bind_ip_to_use;

    boost::asio::ip::tcp::resolver::iterator end;
    if(iterator == end)
    {
      if (!m_use_ipv6)
      {
        _erro("Failed to resolve " << adr);
        return false;
      }
      else
      {
        try_ipv6 = true;
        MINFO("Resolving address as IPv4 failed, trying IPv6");
      }
    }
    else
    {
      bind_ip_to_use = bind_ip;
    }

    if (try_ipv6)
    {
      boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);

      iterator = resolver.resolve(query6, resolve_error);

      if(iterator == end)
      {
        _erro("Failed to resolve " << adr);
        return false;
      }
      else
      {
        if (bind_ip == "0.0.0.0")
        {
          bind_ip_to_use = "::";
        }
        else
        {
          bind_ip_to_use = "";
        }

      }

    }

      MINFO("Trying to connect to " << adr << ":" << port << ", bind_ip = " << bind_ip_to_use);

    //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
    boost::asio::ip::tcp::endpoint remote_endpoint(*iterator);

    auto try_connect_result = try_connect(new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_support);
    if (try_connect_result == CONNECT_FAILURE)
      return false;
    if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
    {
      // we connected, but could not connect with SSL, try without
      MERROR("SSL handshake failed on an autodetect connection, reconnecting without SSL");
      new_connection_l->disable_ssl();
      try_connect_result = try_connect(new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
      if (try_connect_result != CONNECT_SUCCESS)
        return false;
    }

    // start adds the connection to the config object's list, so we don't need to have it locally anymore
    connections_mutex.lock();
    connections_.erase(new_connection_l);
    connections_mutex.unlock();
    bool r = new_connection_l->start(false, 1 < m_threads_count);
    if (r)
    {
      new_connection_l->get_context(conn_context);
      //new_connection_l.reset(new connection<t_wire_handler>(io_service_, m_shared_state, m_sock_count, m_pfilter));
    }
    else
    {
      assert(m_shared_state != nullptr); // always set in constructor
      _erro("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_shared_state->sock_count);
    }

	new_connection_l->save_dbg_log();

    return r;

    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::connect", false);
  }
  //---------------------------------------------------------------------------------
  template<class t_wire_handler> template<class t_callback>
  bool boosted_tcp_server<t_wire_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support)
  {
    TRY_ENTRY();
    connection_ptr new_connection_l(new connection<t_wire_handler>(io_service_, m_shared_state, m_connection_type, ssl_support) );
    connections_mutex.lock();
    connections_.insert(new_connection_l);
    MINFO("connect_async "<<adr<<","<<port<<","<<conn_timeout<<",bind_ip "<<bind_ip<<",ssl "<<(uint8_t)ssl_support<<",connections_ size now " << connections_.size());
    connections_mutex.unlock();
    epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); });
    boost::asio::ip::tcp::socket&  sock_ = new_connection_l->socket();

    bool try_ipv6 = false;

    boost::asio::ip::tcp::resolver resolver(io_service_);
    boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
    boost::system::error_code resolve_error;
    boost::asio::ip::tcp::resolver::iterator iterator;
    try
    {
      //resolving ipv4 address as ipv6 throws, catch here and move on
      iterator = resolver.resolve(query, resolve_error);
    }
    catch (const boost::system::system_error& e)
    {
      if (!m_use_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
            resolve_error != boost::asio::error::host_not_found_try_again))
      {
        throw;
      }
      try_ipv6 = true;
    }
    catch (...)
    {
      throw;
    }

    boost::asio::ip::tcp::resolver::iterator end;
    if(iterator == end)
    {
      if (!try_ipv6)
      {
        _erro("Failed to resolve " << adr);
        return false;
      }
      else
      {
        MINFO("Resolving address as IPv4 failed, trying IPv6");
      }
    }

    if (try_ipv6)
    {
      boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);

      iterator = resolver.resolve(query6, resolve_error);

      if(iterator == end)
      {
        _erro("Failed to resolve " << adr);
        return false;
      }
    }

    boost::asio::ip::tcp::endpoint remote_endpoint(*iterator);

    sock_.open(remote_endpoint.protocol());
    if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
    {
      boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
      boost::system::error_code ec;
      sock_.bind(local_endpoint, ec);
      if (ec)
      {
        MERROR("Error binding to " << bind_ip << ": " << ec.message());
        if (sock_.is_open())
          sock_.close();
        return false;
      }
    }

    boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(io_service_));
    //start deadline
    sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout));
    sh_deadline->async_wait([=](const boost::system::error_code& error)
      {
          if(error != boost::asio::error::operation_aborted)
          {
            MINFO("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")");
            new_connection_l->socket().close();
          }
      });
    //start async connect
    sock_.async_connect(remote_endpoint, [=](const boost::system::error_code& ec_)
      {
        t_connection_context conn_context = AUTO_VAL_INIT(conn_context);
        boost::system::error_code ignored_ec;
        boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket().local_endpoint(ignored_ec);
        if(!ec_)
        {//success
          if(!sh_deadline->cancel())
          {
            cb(conn_context, boost::asio::error::operation_aborted);//this mean that deadline timer already queued callback with cancel operation, rare situation
          }else
          {
            MINFO("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port <<
              " from " << lep.address().to_string() << ':' << lep.port());

            // start adds the connection to the config object's list, so we don't need to have it locally anymore
            connections_mutex.lock();
            connections_.erase(new_connection_l);
            connections_mutex.unlock();
            bool r = new_connection_l->start(false, 1 < m_threads_count);
            if (r)
            {
              new_connection_l->get_context(conn_context);
              cb(conn_context, ec_);
            }
            else
            {
              MINFO("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection to " << adr << ':' << port);
              cb(conn_context, boost::asio::error::fault);
            }
          }
        }else
        {
          MINFO("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port <<
            " from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value());
          cb(conn_context, ec_);
        }
      });
    return true;
    CATCH_ENTRY_L0("boosted_tcp_server<t_wire_handler>::connect_async", false);
  }

} // namespace
} // namespace
PRAGMA_WARNING_POP

ext: inl

max_stars_repo_name: flywithfang/dfa

max_issues_repo_name: flywithfang/dfa

max_forks_repo_name: flywithfang/dfa


text:
/*
 *          Copyright Andrey Semashev 2007 - 2010.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   support/xpressive.hpp
 * \author Andrey Semashev
 * \date   18.07.2009
 *
 * This header enables Boost.Xpressive support for Boost.Log.
 */

#if (defined(_MSC_VER) && _MSC_VER > 1000)
#pragma once
#endif // _MSC_VER > 1000

#ifndef BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_
#define BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_

#include <boost/mpl/bool.hpp>
#include <boost/xpressive/basic_regex.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/regex_algorithms.hpp>
#include <boost/log/detail/prologue.hpp>
#include <boost/log/detail/functional.hpp>

namespace boost {

namespace BOOST_LOG_NAMESPACE {

namespace aux {

//! The trait verifies if the type can be converted to a Boost.Xpressive regex
template< typename T >
struct is_xpressive_regex< T, true >
{
private:
    typedef char yes_type;
    struct no_type { char dummy[2]; };

    template< typename U >
    static yes_type check(xpressive::basic_regex< U > const&);
    static no_type check(...);
    static T& get_T();

public:
    enum { value = sizeof(check(get_T())) == sizeof(yes_type) };
    typedef mpl::bool_< value > type;
};

//! The regex matching functor implementation
template< >
struct matches_fun_impl< boost_xpressive_expression_tag >
{
    template< typename StringT, typename T >
    static bool matches(
        StringT const& str,
        xpressive::basic_regex< T > const& expr,
        xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default)
    {
        return xpressive::regex_match(str, expr, flags);
    }
};

} // namespace aux

} // namespace log

} // namespace boost

#endif // BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_

ext: hpp


text:
// __BEGIN_LICENSE__
// Copyright (C) 2006-2011 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

// What's this file supposed to do ?
//
// (Pho)tometry (Init)ialize Phofile
//
// It's used to create project file and to solve for the starting ET.
//
// Solving for ET goes a like this. Ti =To*Ro/Ri. Where the R equals
// the average reflectance. To is the starting exposure time .. it
// needs to be provided by the user .. but I'm just going to provide 1.
//
// If we're not calculating R, all ET get defined as 1.

#include <vw/Image.h>
#include <photk/ProjectFileIO.h>
#include <photk/Macros.h>
#include <photk/Common.h>
using namespace vw;
using namespace photk;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

using namespace std;

struct Options : photk::BaseOptions {
  // Input for project file
  int32 max_iterations;
  std::string reflectance_type, datum, channel_type;
  double rel_tol, abs_tol;

  // Output
  std::string output_mode;
  std::string output_prefix;
};

void create_ptk( Options const& opt ) {
  ProjectMeta proj_meta;
  proj_meta.set_name( opt.output_prefix );
  proj_meta.set_num_cameras( 0 ); // Phodrg2plate .. will add the cameras
  proj_meta.set_max_iterations( opt.max_iterations );
  proj_meta.set_rel_tol( opt.rel_tol );
  proj_meta.set_abs_tol( opt.abs_tol );
  proj_meta.set_min_pixval( 0 );
  proj_meta.set_max_pixval( 0 );

  std::string reftype = opt.reflectance_type;
  boost::to_lower( reftype );
  if ( reftype == "lamb" || reftype == "lambertian" ) {
    proj_meta.set_reflectance( ProjectMeta::LAMBERTIAN );
  } else if ( reftype == "gaskall" || reftype == "lunarl_gaskall" ) {
    proj_meta.set_reflectance( ProjectMeta::LUNARL_GASKALL );
  } else if ( reftype == "mcewen" || reftype == "lunarl_mcewen" ) {
    proj_meta.set_reflectance( ProjectMeta::LUNARL_MCEWEN );
  } else {
    proj_meta.set_reflectance( ProjectMeta::NONE );
  }

  proj_meta.set_plate_manager( opt.output_mode );
  proj_meta.set_datum_name( opt.datum );
  proj_meta.set_drg_channel_type( opt.channel_type );

  std::list<CameraMeta> emptycams;
  write_pho_project( opt.output_prefix, proj_meta,
                     emptycams.begin(), emptycams.end() );
}

void handle_arguments( int argc, char *argv[], Options& opt ) {
  po::options_description general_options("");
  general_options.add_options()
    ("max_iterations", po::value(&opt.max_iterations)->default_value(100), "")
    ("mode,m", po::value(&opt.output_mode)->default_value("equi"),
     "Output mode [toast, equi, polar]")
    ("channel_type", po::value(&opt.channel_type)->default_value("FLOAT32"),
     "DRG channel type [FLOAT32, INT16, UINT8]")
    ("datum,d", po::value(&opt.datum)->default_value("D_MOON"),
     "Datum options are [WGS84,WGS72,D_MOON,D_MARS]")
    ("reflectance_type", po::value(&opt.reflectance_type)->default_value("none"), "Reflectance options are [none, lambertian, gaskall, mcewen]")
    ("rel_tol", po::value(&opt.rel_tol)->default_value(1e-2),
     "Minimium required amount of improvement between iterations")
    ("abs_tol", po::value(&opt.abs_tol)->default_value(1e-2),
     "Error shutoff threshold.");
  general_options.add( photk::BaseOptionsDescription(opt) );

  po::options_description positional("");
  positional.add_options()
    ("output_prefix", po::value(&opt.output_prefix), "Output prefix");

  po::positional_options_description positional_desc;
  positional_desc.add("output_prefix", 1);

  std::ostringstream usage;
  usage << "Usage: " << argv[0] << " <projectname> <optional project settings> \n";

  po::variables_map vm =
    photk::check_command_line( argc, argv, opt, general_options,
                             positional, positional_desc, usage.str() );

  boost::to_lower( opt.output_mode );
  if ( !( opt.output_mode == "equi" || opt.output_mode == "toast" ||
          opt.output_mode == "polar" ) )
    vw_throw( ArgumentErr() << "Unknown mode: \"" << opt.output_mode
              << "\".\n\n" << usage.str() << general_options );
  if ( opt.output_prefix.empty() )
    vw_throw( ArgumentErr() << "Missing output prefix!\n"
              << usage.str() << general_options );

  boost::to_lower( opt.channel_type );
  if ( !( opt.channel_type == "float32" || opt.channel_type == "int16" ||
          opt.channel_type == "uint8" ) )
    vw_throw( ArgumentErr() << "Unknown mode: \"" << opt.channel_type
              << "\".\n\n" << usage.str() << general_options );
}

int main( int argc, char *argv[] ) {

  Options opt;
  try {
    handle_arguments( argc, argv, opt );
    create_ptk( opt );
  } PHOTK_STANDARD_CATCHES;

  return 0;
}

ext: cc

max_stars_repo_name: NeoGeographyToolkit/PhotometryTK

max_issues_repo_name: NeoGeographyToolkit/PhotometryTK

max_forks_repo_name: NeoGeographyToolkit/PhotometryTK


text:
#include "muxer/mp4_muxer.hpp"

#include <cstdint>
#include <filesystem>
#include <iterator>
#include <string>
#include <vector>

#include <boost/cstdint.hpp>
#include <boost/rational.hpp>

#include "config.hpp"
#include "constants.hpp"
#include "metadata.hpp"
#include "muxer/audio_producer.hpp"
#include "muxer/multi_channel_vpx_video_producer.hpp"
#include "muxer/no_video_producer.hpp"
#include "muxer/opus_audio_producer.hpp"
#include "muxer/video_producer.hpp"
#include "muxer/vpx_video_producer.hpp"
#include "report/reporter.hpp"
#include "shiguredo/mp4/track/opus.hpp"
#include "shiguredo/mp4/track/soun.hpp"
#include "shiguredo/mp4/track/vide.hpp"
#include "shiguredo/mp4/track/vpx.hpp"
#include "shiguredo/mp4/writer/writer.hpp"

#ifdef USE_FDK_AAC
#include "muxer/fdk_aac_audio_producer.hpp"
#include "shiguredo/mp4/track/aac.hpp"
#endif

namespace hisui::muxer {

void MP4Muxer::initialize(const hisui::Config& config_orig,
                          const hisui::MetadataSet& metadata_set,
                          shiguredo::mp4::writer::Writer* writer,
                          const float duration) {
  m_writer = writer;
  hisui::Config config = config_orig;
  if (config.out_video_bit_rate == 0) {
    config.out_video_bit_rate = static_cast<std::uint32_t>(std::size(
                                    metadata_set.getNormalArchives())) *
                                hisui::Constants::VIDEO_VPX_BIT_RATE_PER_FILE;
  } else {
    config.out_video_bit_rate = config.out_video_bit_rate;
  }

  if (config.out_filename == "") {
    std::filesystem::path metadata_path(config.in_metadata_filename);
    if (config.audio_only) {
      config.out_filename = metadata_path.replace_extension(".m4a");
    } else {
      config.out_filename = metadata_path.replace_extension(".mp4");
    }
  }

  if (config.out_audio_codec == config::OutAudioCodec::FDK_AAC) {
    m_chunk_interval = 960;  // 960ms
  } else {
    m_chunk_interval = 1000;  // 1000 ms
  }

  m_ofs = std::ofstream(config.out_filename, std::ios_base::binary);

  if (config.out_audio_codec == config::OutAudioCodec::FDK_AAC) {
#ifdef USE_FDK_AAC
    m_audio_producer = new FDKAACAudioProducer(config, metadata_set);
    m_soun_track = new shiguredo::mp4::track::AACTrack({
        .timescale = 48000,
        .duration = duration,
        .track_id = m_writer->getAndUpdateNextTrackID(),
        .max_bitrate = config.out_aac_bit_rate,
        .avg_bitrate = config.out_aac_bit_rate,
        .writer = m_writer,
    });
#else
    throw std::logic_error("AAC: inconsistent setting");
#endif
  } else {
    OpusAudioProducer* audio_producer =
        new OpusAudioProducer(config, metadata_set, 48000);
    const auto skip = audio_producer->getSkip();
    m_audio_producer = audio_producer;
    m_soun_track = new shiguredo::mp4::track::OpusTrack(
        {.pre_skip = static_cast<std::uint64_t>(skip),
         .duration = duration,
         .track_id = m_writer->getAndUpdateNextTrackID(),
         .writer = m_writer});
  }

  if (config.audio_only) {
    m_video_producer = new NoVideoProducer();
    m_timescale_ratio.assign(1, 1);
  } else {
    if (metadata_set.hasPreferred()) {
      m_video_producer =
          new MultiChannelVPXVideoProducer(config, metadata_set, 16000);
    } else {
      m_video_producer =
          new VPXVideoProducer(config, metadata_set.getNormal(), 16000);
    }
    m_vide_track = new shiguredo::mp4::track::VPXTrack(
        {.timescale = 16000,
         .duration = duration,
         .track_id = m_writer->getAndUpdateNextTrackID(),
         .width = m_video_producer->getWidth(),
         .height = m_video_producer->getHeight(),
         .writer = m_writer});

    m_timescale_ratio.assign(m_soun_track->getTimescale(),
                             m_vide_track->getTimescale());
  }

  if (hisui::report::Reporter::hasInstance()) {
    hisui::report::Reporter::getInstance().registerOutput({
        .container = "MP4",
        .mux_type = config.mp4_muxer == config::MP4Muxer::Faststart
                        ? "faststart"
                        : "simple",
        .video_codec =
            config.audio_only ? "none"
            : m_video_producer->getFourcc() == hisui::Constants::VP9_FOURCC
                ? "vp9"
                : "vp8",
        .audio_codec = config.out_audio_codec == config::OutAudioCodec::FDK_AAC
                           ? "aac"
                           : "opus",
        .duration = metadata_set.getMaxStopTimeOffset(),
    });
  }
}

MP4Muxer::~MP4Muxer() {
  m_ofs.close();

  if (m_vide_track) {
    delete m_vide_track;
  }
  delete m_soun_track;
  delete m_video_producer;
  delete m_audio_producer;
}

void MP4Muxer::appendAudio(hisui::Frame frame) {
  if ((frame.timestamp * m_writer->getMvhdTimescale() /
       m_soun_track->getTimescale()) >= m_chunk_start + m_chunk_interval) {
    m_chunk_start += m_chunk_interval;
    writeTrackData();
  }

  m_audio_buffer.push_back(frame);
  m_audio_producer->bufferPop();
}

void MP4Muxer::appendVideo(hisui::Frame frame) {
  if ((frame.timestamp * m_writer->getMvhdTimescale() /
       m_vide_track->getTimescale()) >= m_chunk_start + m_chunk_interval) {
    m_chunk_start += m_chunk_interval;
    writeTrackData();
  }

  m_video_buffer.push_back(frame);
  m_video_producer->bufferPop();
}

void MP4Muxer::writeTrackData() {
  for (const auto f : m_audio_buffer) {
    m_soun_track->addMdatData(f.timestamp, f.data, f.data_size, f.is_key);
    delete[] f.data;
  }
  m_soun_track->terminateCurrentChunk();
  m_audio_buffer.clear();
  if (!m_vide_track) {
    return;
  }
  for (const auto f : m_video_buffer) {
    m_vide_track->addMdatData(f.timestamp, f.data, f.data_size, f.is_key);
    delete[] f.data;
  }
  m_vide_track->terminateCurrentChunk();
  m_video_buffer.clear();
}

void MP4Muxer::muxFinalize() {
  writeTrackData();
}

}  // namespace hisui::muxer

ext: cpp

max_stars_repo_name: shiguredo/hisui

max_issues_repo_name: shiguredo/hisui

max_forks_repo_name: shiguredo/hisui


text:
/* Copyright 2014-2018 Rsyn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "FastPlace.h"

#include "tool/timing/Timer.h"
#include "io/writer/Writer.h"

#include "util/AsciiProgressBar.h"
#include "util/Stepwatch.h"
#include <boost/algorithm/string.hpp>

#include "util/Json.h"

#include <cstdio>

namespace ICCAD15 {

bool FastPlace::run(const Rsyn::Json &params) {
        this->session = session;
        this->design = session.getDesign();
        this->timer = session.getService("rsyn.timer");
        this->writer = session.getService("rsyn.writer");
        this->module = design.getTopModule();

        const std::string &designName = session.getDesign().getName();
        const std::string tmp = createTemporaryDirectory();

        writer->writeBookshelf2(tmp);

        std::string cmd;
        cmd += session.getInstallationPath() + "/bin/FastPlace3.0_Linux32_GP ";
        cmd += tmp + " ";
        cmd += designName + ".aux ";
        cmd += tmp;

        std::cout << "Temporary directory:\n" << tmp << "\n";
        std::cout << "Command line:\n" << cmd << "\n";
        exec(cmd);

        Rsyn::Json config;
        config["path"] = tmp + "/" + designName + "_FP_gp.pl";
        session.runReader("loadDesignPosition", config);

        return true;
}  // end method

// -----------------------------------------------------------------------------

std::string FastPlace::createTemporaryDirectory() {
        FILE *in;
        char buff[1024];

        std::string result;

        if (!(in = popen("mktemp -d", "r"))) {
                return "";
        }  // end if
        while (fgets(buff, sizeof(buff), in) != NULL) {
                result += buff;
        }  // end while
        pclose(in);

        boost::trim(result);
        return result;
}  // end method

// -----------------------------------------------------------------------------

bool FastPlace::exec(const std::string &cmd, std::ostream &out) {
        FILE *in;
        char buff[1024];

        if (!(in = popen((cmd + " 2>&1").c_str(), "r"))) {
                return false;
        }  // end if
        while (fgets(buff, sizeof(buff), in) != NULL) {
                out << buff;
        }  // end while
        pclose(in);

        return true;
}  // end method

}  // end namescape


text:
#define BOOST_TEST_MODULE pcrblock voxel_at_height
#include <boost/test/unit_test.hpp>
#include <algorithm>
#include "block_voxelatheight.h"

BOOST_AUTO_TEST_CASE(test)
{
  using namespace block;

  {
    // Empty stack does not return true.
    VoxelAtHeight f(5.0, 5.0);
    BOOST_CHECK(!(f(0.0)));
    BOOST_CHECK( (f(1.0)));
  }

  {
    VoxelAtHeight f(5.0, 6.0);
    BOOST_CHECK(!(f(0.0)));
    BOOST_CHECK(!(f(0.5)));
    BOOST_CHECK(!(f(0.5)));
    BOOST_CHECK( (f(0.001)));
  }

  {
    VoxelAtHeight f(5.0, 9.0);
    BOOST_CHECK(!(f(0.0)));
    BOOST_CHECK(!(f(1.0)));
    BOOST_CHECK(!(f(1.0)));
    BOOST_CHECK(!(f(2.0)));
    BOOST_CHECK( (f(2.0)));
  }

  {
    VoxelAtHeight f(0.0, 4.0);
    BOOST_CHECK(!f(0.0));
    BOOST_CHECK(!f(1.0));
    BOOST_CHECK(!f(1.0));
    BOOST_CHECK(!f(1.0));

    // Top of the voxel does not return true here.
    BOOST_CHECK(!f(1.0));
    BOOST_CHECK(f(0.001));
  }

  {
    VoxelAtHeight f(-1.0, 1.0);
    BOOST_CHECK(!f(0.0));
    BOOST_CHECK(!f(1.0));
    BOOST_CHECK(!f(1.0));
    BOOST_CHECK(f(0.001));
  }

  {
    std::vector<REAL4> thicknesses;
    thicknesses.push_back(1.0);
    thicknesses.push_back(1.0);
    thicknesses.push_back(1.0);
    thicknesses.push_back(1.0);
    thicknesses.push_back(1.0);

    std::vector<REAL4>::const_iterator it;

    // Bottom of the first voxel equals the requested height and returns true.
    it = std::find_if(
           thicknesses.begin(), thicknesses.end(), VoxelAtHeight(0.0, 0.0));
    BOOST_CHECK(it == thicknesses.begin());

    // Bottom of the fourth voxel equals the requested height and returns true.
    it = std::find_if(
           thicknesses.begin(), thicknesses.end(), VoxelAtHeight(0.0, 3.0));
    BOOST_CHECK(it == thicknesses.begin() + 3);

    // Top of the voxel equals the requested heigth but does not return true.
    it = std::find_if(
           thicknesses.begin(), thicknesses.end(), VoxelAtHeight(0.0, 5.0));
    BOOST_CHECK(it == thicknesses.end());

    it = std::find_if(
           thicknesses.begin(), thicknesses.end(), VoxelAtHeight(0.0, 6.0));
    BOOST_CHECK(it == thicknesses.end());
  }
}

max_stars_repo_name: quanpands/wflow

max_issues_repo_name: quanpands/wflow

max_forks_repo_name: quanpands/wflow


text:
/***********************************************************************************************************************
*  OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
*  following conditions are met:
*
*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*  disclaimer.
*
*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
*  disclaimer in the documentation and/or other materials provided with the distribution.
*
*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
*  derived from this software without specific prior written permission from the respective party.
*
*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
*  written permission from Alliance for Sustainable Energy, LLC.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY 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 HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, 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.
***********************************************************************************************************************/

#ifndef UTILITIES_IDF_IDFREGEX_HPP
#define UTILITIES_IDF_IDFREGEX_HPP

#include "../UtilitiesAPI.hpp"
#include "../core/StaticInitializer.hpp"
#include <string>
#include <boost/regex.hpp>

namespace openstudio {
namespace idfRegex {

  // todo, I have capitalized all these functions as they are static, is that right
  UTILITIES_API const std::string& newLinestring();

  // Match an optional new line
  // matches[1], before new line and new line
  // matches[2], after new line
  UTILITIES_API const std::string& optionalNewLinestring();

  // Match comment only line
  // matches[1], the comment
  // matches[2], after new line
  UTILITIES_API const boost::regex& commentOnlyLine();

  // Match content and comment
  // matches[1], the content
  // matches[2], the comment
  UTILITIES_API const boost::regex& contentAndCommentLine();

  // Match object end in the idf
  UTILITIES_API const boost::regex& objectEnd();

  // Match line with an object type and name
  // matches[1], before first separator
  // matches[2], after first separator and before second separator
  UTILITIES_API const boost::regex& objectTypeAndName();

  // Match line with either a ',' or a ';' that are not preceded by '!'
  // matches[1], before separator
  // matches[2], after separator and before new line
  // matches[3], after new line
  UTILITIES_API const boost::regex& line();

  // Match an autosize field
  UTILITIES_API const boost::regex& autosize();

  // Match an autocalculate field
  UTILITIES_API const boost::regex& autocalculate();

  // Match line with '##def SomeSection[]' preceded only by whitespace
  // matches[1], the imf section name (e.g. 'SomeSection')
  // matches[2], inside the [] brackets
  UTILITIES_API const boost::regex& imfSection();

  // Match line with '##enddef' preceded and followed only by whitespace
  UTILITIES_API const boost::regex& imfSectionEnd();

}  // namespace idfRegex
}  // namespace openstudio

#endif  //UTILITIES_IDF_IDFREGEX_HPP

max_stars_repo_name: muehleisen/OpenStudio

max_issues_repo_name: muehleisen/OpenStudio

max_forks_repo_name: jmarrec/OpenStudio


text:
#include "stdafx.h"
#include "BoostGraph.h"
#include <sstream>
#include <boost/algorithm/string.hpp>

using std::vector;
using std::string;
using std::stringstream;

namespace
{

const char C_INPUT_DOT_1[] = R"***(
digraph G {
1 [root=1];
2;
3;
4;
5;
1->2 [weight=2];
2->3 [weight=3];
2->4 [weight=-3];
3->1 [weight=-4];
4->5 [weight=2];
}
)***";

const char C_INPUT_TEXT_1[] = R"***(
5 5 1
1 2 2
2 3 3
2 4 -3
3 1 -4
4 5 2
)***";

const char C_OUTPUT_1[] = R"***(
0 0
2 1 2
5 2 2 3
-1 2 2 4
1 3 2 4 5
)***";

const char C_INPUT_DOT_2[] = R"***(
digraph G {
1 [root=1];
2;
3;
4;
1->2 [weight=3];
1->3 [weight=7];
2->3 [weight=2];
2->4 [weight=1];
3->2 [weight=2];
3->4 [weight=2];
4->3 [weight=2];
}
)***";

const char C_OUTPUT_2[] = R"***(
0 0
3 1 2
5 2 2 3
4 2 2 4
)***";

const char C_INPUT_DOT_3[] = R"***(
digraph G {
1 [root=1];
2;
3;
4;
1->2 [weight=3];
3->4 [weight=4];
}
)***";

const char C_OUTPUT_3[] = R"***(
0 0
3 1 2
No
No
)***";

const char C_INPUT_TEXT_4[] = R"***(
4 4 1
1 2 2
2 3 4
3 1 -9
2 4 5
)***";

const char C_INPUT_DOT_4[] = R"***(
digraph G {
1 [root=1];
2;
3;
4;
1->2 [weight=2];
2->3 [weight=4];
3->1 [weight=-9];
2->4 [weight=5];
}
)***";

const char C_OUTPUT_4[] = R"***(
No
4 2 3 1 2
)***";

// Используем split для игнорирования пробелов и переносов строк при проверке.
vector<string> SplitWords(string const& text)
{
	std::string trimmed = boost::trim_copy(text);

	vector<string> words;
	boost::split(words, trimmed, boost::is_space(), boost::token_compress_on);
	return words;
}

void RunGraphvizInputTestcase(std::string const& inputText, std::string const& expectedOutput)
{
	CBoostGraph graph;
	stringstream input(inputText);
	stringstream output;
	BOOST_CHECK(graph.ReadGraphviz(input));
	graph.RunBellmanFord(output);
	vector<string> words = SplitWords(output.str());
	vector<string> checkWords = SplitWords(expectedOutput);
	BOOST_CHECK(words == checkWords);
}

void RunTextInputTestcase(std::string const& inputText, std::string const& expectedOutput)
{
	CBoostGraph graph;
	stringstream input(inputText);
	stringstream output;
	BOOST_CHECK(graph.ReadText(input));
	graph.RunBellmanFord(output);
	vector<string> words = SplitWords(output.str());
	vector<string> checkWords = SplitWords(expectedOutput);
	BOOST_CHECK(words == checkWords);
}

}

BOOST_AUTO_TEST_SUITE(Graph_with_Bellmand_Ford_algorithm)
	BOOST_AUTO_TEST_CASE(can_load_graphviz_format)
	{
		RunGraphvizInputTestcase(C_INPUT_DOT_1, C_OUTPUT_1);
	}

	BOOST_AUTO_TEST_CASE(can_load_text_format)
	{
		RunTextInputTestcase(C_INPUT_TEXT_1, C_OUTPUT_1);
	}

	BOOST_AUTO_TEST_CASE(has_no_negative_loop_false_positives)
	{
		RunGraphvizInputTestcase(C_INPUT_DOT_2, C_OUTPUT_2);
	}

	BOOST_AUTO_TEST_CASE(prints_No_if_no_path)
	{
		RunGraphvizInputTestcase(C_INPUT_DOT_3, C_OUTPUT_3);
	}

	BOOST_AUTO_TEST_CASE(finds_negative_loop_and_prints_it_for_dot_input)
	{
		RunGraphvizInputTestcase(C_INPUT_DOT_4, C_OUTPUT_4);
	}

	BOOST_AUTO_TEST_CASE(finds_negative_loop_and_prints_it_for_text_input)
	{
		RunTextInputTestcase(C_INPUT_TEXT_4, C_OUTPUT_4);
	}
BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: PS-Group/algorithm-samples

max_issues_repo_name: PS-Group/algorithm-samples

max_forks_repo_name: PS-Group/algorithm-samples


text:
/*=============================================================================
    Copyright (c) 2005-2013 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(BOOST_FUSION_BUILD_DEQUE_02032013_1921)
#define BOOST_FUSION_BUILD_DEQUE_02032013_1921

#if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
#error "C++03 only! This file should not have been included"
#endif

#include <boost/fusion/container/deque/detail/cpp03/as_deque.hpp>
#include <boost/fusion/container/deque/front_extended_deque.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>

namespace boost {
namespace fusion {
namespace result_of {
template <typename Sequence>
struct as_deque : detail::as_deque<result_of::size<Sequence>::value> {
  typedef typename detail::as_deque<result_of::size<Sequence>::value> gen;
  typedef typename gen::template apply<
      typename result_of::begin<Sequence>::type>::type type;
};
} // namespace result_of

template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED inline
    typename result_of::as_deque<Sequence>::type
    as_deque(Sequence &seq) {
  typedef typename result_of::as_deque<Sequence>::gen gen;
  return gen::call(fusion::begin(seq));
}

template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED inline
    typename result_of::as_deque<Sequence const>::type
    as_deque(Sequence const &seq) {
  typedef typename result_of::as_deque<Sequence const>::gen gen;
  return gen::call(fusion::begin(seq));
}
} // namespace fusion
} // namespace boost

#endif

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
#ifndef BOOST_TEXT_DETAIL_NORMALIZATION_DATA_HPP
#define BOOST_TEXT_DETAIL_NORMALIZATION_DATA_HPP

#include <boost/text/utf8.hpp>
#include <boost/text/detail/lzw.hpp>

#include <boost/container/small_vector.hpp>

#include <array>
#include <unordered_map>
#include <unordered_set>

namespace boost { namespace text { namespace detail {

    template<int Capacity>
    struct code_points
    {
        using storage_type = std::array<uint32_t, Capacity>;
        using iterator = typename storage_type::iterator;
        using const_iterator = typename storage_type::const_iterator;

        const_iterator begin() const { return storage_.begin(); }
        const_iterator end() const { return storage_.begin() + size_; }

        iterator begin() { return storage_.begin(); }
        iterator end() { return storage_.begin() + size_; }

        friend bool operator==(
            code_points<Capacity> const & lhs,
            code_points<Capacity> const & rhs)
        {
            return lhs.size_ == rhs.size_ && std::equal(
                                                 lhs.storage_.begin(),
                                                 lhs.storage_.end(),
                                                 rhs.storage_.begin());
        }
        friend bool operator!=(
            code_points<Capacity> const & lhs,
            code_points<Capacity> const & rhs)
        {
            return !(lhs == rhs);
        }

        storage_type storage_;
        int size_;
    };

    using canonical_decomposition = code_points<4>;

    /** See
       http://www.unicode.org/reports/tr44/#Character_Decomposition_Mappings for
        the source of the "18".
    */
    using compatible_decomposition = code_points<18>;

    /** The possible results returned by the single code point quick check
        functions.  A result of maybe indicates that a quick check is not
        possible and a full check must be performed. */
    enum class quick_check : uint8_t { yes, no, maybe };

    struct cp_range
    {
        uint16_t first_;
        uint16_t last_;
    };

    BOOST_TEXT_DECL std::array<uint32_t, 3404>
    make_all_canonical_decompositions();
    BOOST_TEXT_DECL std::array<uint32_t, 8974>
    make_all_compatible_decompositions();

    inline uint32_t const * all_canonical_decompositions_ptr()
    {
        static auto const retval = make_all_canonical_decompositions();
        return retval.data();
    }

    inline uint32_t const * all_compatible_decompositions_ptr()
    {
        static auto const retval = make_all_compatible_decompositions();
        return retval.data();
    }

    BOOST_TEXT_DECL std::unordered_map<uint64_t, uint32_t>
    make_composition_map();

    inline std::unordered_map<uint64_t, uint32_t> const & composition_map()
    {
        static auto const retval = make_composition_map();
        return retval;
    }

    struct cp_props
    {
        cp_range canonical_decomposition_;
        cp_range compatible_decomposition_;
        uint8_t ccc_;
        uint8_t nfd_quick_check_ : 4;
        uint8_t nfkd_quick_check_ : 4;
        uint8_t nfc_quick_check_ : 4;
        uint8_t nfkc_quick_check_ : 4;
    };

    static_assert(sizeof(cp_props) == 12, "");

    BOOST_TEXT_DECL std::unordered_map<uint32_t, cp_props> make_cp_props_map();

    inline std::unordered_map<uint32_t, cp_props> const & cp_props_map()
    {
        static auto const retval = make_cp_props_map();
        return retval;
    }

    inline constexpr bool hangul_syllable(uint32_t cp) noexcept
    {
        return 0xAC00 <= cp && cp <= 0xD7A3;
    }

    // Hangul decomposition as described in Unicode 11.0 Section 3.12.
    template<int Capacity>
    inline code_points<Capacity> decompose_hangul_syllable(uint32_t cp) noexcept
    {
        BOOST_ASSERT(hangul_syllable(cp));

        uint32_t const SBase = 0xAC00;
        uint32_t const LBase = 0x1100;
        uint32_t const VBase = 0x1161;
        uint32_t const TBase = 0x11A7;
        // uint32_t const LCount = 19;
        uint32_t const VCount = 21;
        uint32_t const TCount = 28;
        uint32_t const NCount = VCount * TCount; // 588
        // uint32_t const SCount = LCount * NCount; // 11172

        auto const SIndex = cp - SBase;

        auto const LIndex = SIndex / NCount;
        auto const VIndex = (SIndex % NCount) / TCount;
        auto const TIndex = SIndex % TCount;
        auto const LPart = LBase + LIndex;
        auto const VPart = VBase + VIndex;
        if (TIndex == 0) {
            return code_points<Capacity>{{{LPart, VPart}}, 2};
        } else {
            auto const TPart = TBase + TIndex;
            return code_points<Capacity>{{{LPart, VPart, TPart}}, 3};
        }
    }

    inline std::unordered_multimap<uint32_t, uint32_t> const &
    compositions_whose_decompositions_start_with_cp_map()
    {
        static std::unordered_multimap<uint32_t, uint32_t> retval;
        if (retval.empty()) {
            auto const & map = detail::cp_props_map();
            for (auto const & pair : map) {
                auto const decomp_it =
                    detail::all_canonical_decompositions_ptr() +
                    pair.second.canonical_decomposition_.first_;
                auto const decomp_end =
                    detail::all_canonical_decompositions_ptr() +
                    pair.second.canonical_decomposition_.last_;
                if (decomp_it != decomp_end) {
                    retval.insert(
                        std::pair<uint32_t, uint32_t>(*decomp_it, pair.first));
                }
            }

            for (uint32_t cp = 0xAC00, end = 0xD7A3 + 1; cp < end; ++cp) {
                auto const decomp = detail::decompose_hangul_syllable<4>(cp);
                retval.insert(
                    std::pair<uint32_t, uint32_t>(*decomp.begin(), cp));
            }
        }
        return retval;
    }

    inline std::unordered_set<uint32_t> const &
    appears_at_noninitial_position_of_decomp_set()
    {
        static std::unordered_set<uint32_t> retval;
        if (retval.empty()) {
            auto const & map = detail::cp_props_map();
            for (auto const & pair : map) {
                auto const decomp_it =
                    detail::all_canonical_decompositions_ptr() +
                    pair.second.canonical_decomposition_.first_;
                auto const decomp_end =
                    detail::all_canonical_decompositions_ptr() +
                    pair.second.canonical_decomposition_.last_;
                if (2 <= decomp_end - decomp_it)
                    retval.insert(*std::next(decomp_it));
            }

            for (uint32_t cp = 0xAC00, end = 0xD7A3 + 1; cp < end; ++cp) {
                auto const decomp = detail::decompose_hangul_syllable<4>(cp);
                if (2 <= decomp.size_)
                    retval.insert(*std::next(decomp.begin()));
            }
        }
        return retval;
    }

    inline constexpr uint64_t key(uint64_t cp0, uint32_t cp1) noexcept
    {
        return (cp0 << 32) | cp1;
    }

    inline canonical_decomposition canonical_decompose(uint32_t cp) noexcept
    {
        if (detail::hangul_syllable(cp))
            return detail::decompose_hangul_syllable<4>(cp);

        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end() || it->second.canonical_decomposition_.last_ ==
                                   it->second.canonical_decomposition_.first_) {
            return canonical_decomposition{{{cp}}, 1};
        }

        canonical_decomposition retval{
            {},
            it->second.canonical_decomposition_.last_ -
                it->second.canonical_decomposition_.first_};
        std::copy(
            detail::all_canonical_decompositions_ptr() +
                it->second.canonical_decomposition_.first_,
            detail::all_canonical_decompositions_ptr() +
                it->second.canonical_decomposition_.last_,
            retval.storage_.begin());

        return retval;
    }

    inline compatible_decomposition compatible_decompose(uint32_t cp) noexcept
    {
        if (detail::hangul_syllable(cp))
            return detail::decompose_hangul_syllable<18>(cp);

        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end() ||
            it->second.compatible_decomposition_.last_ ==
                it->second.compatible_decomposition_.first_) {
            return compatible_decomposition{{{cp}}, 1};
        }

        compatible_decomposition retval{
            {},
            it->second.compatible_decomposition_.last_ -
                it->second.compatible_decomposition_.first_};
        std::copy(
            detail::all_compatible_decompositions_ptr() +
                it->second.compatible_decomposition_.first_,
            detail::all_compatible_decompositions_ptr() +
                it->second.compatible_decomposition_.last_,
            retval.storage_.begin());

        return retval;
    }

    inline uint32_t
    compose_hangul(uint32_t cp0, uint32_t cp1, uint32_t cp2 = 0) noexcept
    {
        uint32_t const SBase = 0xAC00;
        uint32_t const LBase = 0x1100;
        uint32_t const VBase = 0x1161;
        uint32_t const TBase = 0x11A7;
        // uint32_t const LCount = 19;
        uint32_t const VCount = 21;
        uint32_t const TCount = 28;
        uint32_t const NCount = VCount * TCount; // 588
        // uint32_t const SCount = LCount * NCount; // 11172

        auto const LIndex = cp0 - LBase;
        auto const VIndex = cp1 - VBase;

        auto const LVIndex = LIndex * NCount + VIndex * TCount;
        if (cp2) {
            auto const TIndex = cp2 - TBase;
            return SBase + LVIndex + TIndex;
        } else {
            return SBase + LVIndex;
        }
    }

    inline uint32_t compose_unblocked(uint32_t cp0, uint32_t cp1) noexcept
    {
        auto const & map = detail::composition_map();
        auto const it = map.find(detail::key(cp0, cp1));
        if (it == map.end())
            return 0;
        return it->second;
    }

    inline int ccc(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return 0;
        return it->second.ccc_;
    }

    /** Returns yes, no, or maybe if the given code point indicates that the
        sequence in which it is found is normalized NFD. */
    inline quick_check quick_check_nfd_code_point(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return quick_check::yes;
        return quick_check(it->second.nfd_quick_check_);
    }

    /** Returns yes, no, or maybe if the given code point indicates that the
        sequence in which it is found is normalized NFKD. */
    inline quick_check quick_check_nfkd_code_point(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return quick_check::yes;
        return quick_check(it->second.nfkd_quick_check_);
    }

    /** Returns yes, no, or maybe if the given code point indicates that the
        sequence in which it is found is normalized NFC. */
    inline quick_check quick_check_nfc_code_point(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return quick_check::yes;
        return quick_check(it->second.nfc_quick_check_);
    }

    /** Returns yes, no, or maybe if the given code point indicates that the
        sequence in which it is found is normalized NFKC. */
    inline quick_check quick_check_nfkc_code_point(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return quick_check::yes;
        return quick_check(it->second.nfkc_quick_check_);
    }

    /** Returns true iff cp is a stable code point under FCC normalization
        (meaning that it is ccc=0 and Quick_Check_NFC=Yes).

        \see https://www.unicode.org/reports/tr15/#Stable_Code_Points */
    inline bool stable_fcc_code_point(uint32_t cp) noexcept
    {
        auto const & map = detail::cp_props_map();
        auto const it = map.find(cp);
        if (it == map.end())
            return true;
        return it->second.ccc_ == 0 &&
               quick_check(it->second.nfc_quick_check_) == quick_check::yes;
    }

    struct lzw_to_cp_props_iter
    {
        using value_type = std::pair<uint32_t, cp_props>;
        using difference_type = int;
        using pointer = value_type *;
        using reference = value_type &;
        using iterator_category = std::output_iterator_tag;
        using buffer_t = container::small_vector<unsigned char, 256>;

        lzw_to_cp_props_iter(
            std::unordered_map<uint32_t, cp_props> & map, buffer_t & buf) :
            map_(&map),
            buf_(&buf)
        {}

        template<typename BidiRange>
        lzw_to_cp_props_iter & operator=(BidiRange const & r)
        {
            buf_->insert(buf_->end(), r.rbegin(), r.rend());
            auto const element_bytes = 3 + 2 + 2 + 2 + 2 + 1 + 1 + 1;
            auto it = buf_->begin();
            for (auto end = buf_->end() - buf_->size() % element_bytes;
                 it != end;
                 it += element_bytes) {
                unsigned char * ptr = &*it;

                uint32_t const cp = bytes_to_cp(ptr);
                ptr += 3;

                cp_props props;
                props.canonical_decomposition_.first_ = bytes_to_uint16_t(ptr);
                ptr += 2;
                props.canonical_decomposition_.last_ = bytes_to_uint16_t(ptr);
                ptr += 2;
                props.compatible_decomposition_.first_ = bytes_to_uint16_t(ptr);
                ptr += 2;
                props.compatible_decomposition_.last_ = bytes_to_uint16_t(ptr);
                ptr += 2;
                props.ccc_ = *ptr++;
                unsigned char c = *ptr++;
                props.nfd_quick_check_ = (c >> 4) & 0xf;
                props.nfkd_quick_check_ = (c >> 0) & 0xf;
                c = *ptr++;
                props.nfc_quick_check_ = (c >> 4) & 0xf;
                props.nfkc_quick_check_ = (c >> 0) & 0xf;

                (*map_)[cp] = props;
            }
            buf_->erase(buf_->begin(), it);
            return *this;
        }
        lzw_to_cp_props_iter & operator*() { return *this; }
        lzw_to_cp_props_iter & operator++() { return *this; }
        lzw_to_cp_props_iter & operator++(int) { return *this; }

    private:
        std::unordered_map<uint32_t, cp_props> * map_;
        buffer_t * buf_;
    };

}}}

#endif

max_stars_repo_name: jan-moeller/text

max_issues_repo_name: jan-moeller/text

max_forks_repo_name: jan-moeller/text


text: #include <boost/mpl/aux_/clear_impl.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <boost/test/unit_test.hpp>

#include <opaque_external_type.h>
#include <term_strz.h>

#include <iostream>
#include <fstream>
#include <vector>

BOOST_AUTO_TEST_CASE(test_opaque_external_type) {
    std::ifstream ifs("src/term_strz.bin", std::ifstream::binary);
    kaitai::kstream ks(&ifs);
    opaque_external_type_t* r = new opaque_external_type_t(&ks);

    BOOST_CHECK_EQUAL(r->one()->s1(), "foo");
    BOOST_CHECK_EQUAL(r->one()->s2(), "bar");
    BOOST_CHECK_EQUAL(r->one()->s3(), "|baz@");

    delete r;
}


text:
/************************************************************************
MIT License

Copyright (c) 2021 Deqi Tang

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.
************************************************************************/

/// @file src/atomsciflow/elk/elk.cpp
/// @author DeqiTang
/// Mail: deqitang@gmail.com
/// Created Time: Wed 02 Mar 2022 02:39:17 PM CST

#include "atomsciflow/elk/elk.h"

#include <fstream>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>

#include "atomsciflow/base/element.h"
#include "atomsciflow/server/submit_script.h"
#include "atomsciflow/remote/server.h"

namespace atomsciflow {

namespace fs = boost::filesystem;

Elk::Elk() {

    job.set_run_default("bash");
    job.set_run_default("llhpc");
    job.set_run_default("pbs");
    job.set_run_default("bash");
    job.set_run_default("lsf_sz");
    job.set_run_default("lsf_sustc");
    job.set_run_default("cdcloud");
    job.set_run("cmd", "$ELK_BIN");
    job.set_run("runopt", "genrun");
    job.set_run("auto_level", "0");

    job.set_run("cmd", "$ASF_CMD_ELK");
    job.set_run("script_name_head", "elk-run");
}

Elk::~Elk() {
    for (const auto& item : this->blocks) {
        delete item.second;
    }
}

void Elk::new_block(const std::string &name) {
    if (this->blocks.find(name) == this->blocks.end()) {
        this->blocks[name] = new Block{};
    }
}

std::string Elk::to_string() {
    std::string out;
    for (const auto& item : this->blocks) {
        out += this->blocks[item.first]->to_string();
    }
    return out;
}

void Elk::get_xyz(std::string xyzfile) {
    //std::cout << "Elk::get_xyz starting!" << "\n";

    this->xyz.read_xyz_file(xyzfile);
    job.set_run("xyz_file", fs::absolute(xyzfile).string());

    this->new_block("data");

    auto element_map = get_element_number_map();
    this->set_param("data", "Cnv", 2);
    std::string atm;
    for (const auto& item : this->xyz.atoms) {
        atm = "";
        atm += std::to_string(element_map[item.name].mass);
        atm += " ";
        atm += std::to_string(item.x);
        atm += " ";
        atm += std::to_string(item.y);
        atm += " ";
        atm += std::to_string(item.z);
        this->set_param("data", item.name, atm);
    }
}

template <typename T>
void Elk::set_param(const std::string& group, std::string key, T value) {
    this->blocks[group]->set_param(key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, int value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, double value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::string value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<int> value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<double> value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<std::string> value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<std::vector<int>> value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<std::vector<double>> value) {
    this->set_param(group, key, value);
}

void Elk::py_set_param(const std::string& group, std::string key, std::vector<std::vector<std::string>> value) {
    this->set_param(group, key, value);
}

/// @param directory a place for all the generated files
void Elk::run(const std::string& directory) {
    job.steps.clear();
    std::ostringstream step;
    step << "cd ${ABSOLUTE_WORK_DIR}" << "\n";
    step << "cat > elk.in<<EOF\n";
    step << this->to_string();
    step << "EOF\n";

    step << "$CMD_HEAD " << this->job.run_params["cmd"] << "\n";
    job.steps.push_back(step.str());
    step.clear();

    job.run(directory);
}

// explicit template instantiation
template void Elk::set_param<int>(const std::string& group, std::string key, int);
template void Elk::set_param<double>(const std::string& group, std::string key, double);
template void Elk::set_param<std::string>(const std::string& group, std::string key, std::string);
template void Elk::set_param<std::vector<int>>(const std::string& group, std::string key, std::vector<int>);
template void Elk::set_param<std::vector<double>>(const std::string& group, std::string key, std::vector<double>);
template void Elk::set_param<std::vector<std::string>>(const std::string& group, std::string key, std::vector<std::string>);
template void Elk::set_param<std::vector<std::vector<int>>>(const std::string& group, std::string key, std::vector<std::vector<int>>);
template void Elk::set_param<std::vector<std::vector<double>>>(const std::string& group, std::string key, std::vector<std::vector<double>>);
template void Elk::set_param<std::vector<std::vector<std::string>>>(const std::string& group, std::string key, std::vector<std::vector<std::string>>);

} // namespace atomsciflow

max_stars_repo_name: DeqiTang/build-test-atomsciflow

max_issues_repo_name: DeqiTang/build-test-atomsciflow

max_forks_repo_name: DeqiTang/build-test-atomsciflow


text:
/*
Copyright 2014, 2015 Rogier van Dalen.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

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

/** \file
Define helpers for magmas that consist of other magmas.
*/

#ifndef MATH_DETAIL_TUPLE_HELPER_HPP_INCLUDED
#define MATH_DETAIL_TUPLE_HELPER_HPP_INCLUDED

#include <type_traits>

#include <boost/utility/enable_if.hpp>

#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>

#include "meta/vector.hpp"
#include "meta/count.hpp"
#include "meta/all_of_c.hpp"
#include "meta/any_of_c.hpp"

#include "range/core.hpp"
#include "range/equal.hpp"
#include "range/less_lexicographical.hpp"

#include "rime/call_if.hpp"
#include "rime/enable_if_constant.hpp"

#include "../magma.hpp"

namespace math {

/** \struct over
Tag to indicate component types of a composite magma.
*/
template <class ... Components> struct over;

namespace operation {

    namespace tuple_helper {

        /**
        Specialise this for a magma type with an operator() that returns the
        components of the magma as a range.
        */
        template <class TupleTag> struct get_components;

        /**
        Compare a tuple for equality by checking the components in parallel.
        \tparam Equality
            The predicate to use for each component.
        */
        template <class Equality> struct equal_components {
            template <class Left, class Right>
                auto operator() (Left const & left, Right const & right) const
            RETURNS (range::equal (
                get_components <typename magma_tag <Left>::type>() (left),
                get_components <typename magma_tag <Right>::type>() (right),
                Equality()));
        };

        /**
        Compare two tuples for equality, using is_annihilator \<Operation> first.
        If both arguments are annihilators, compare equal.
        If either is an annihilator, compare unequal.
        Otherwise, forward to \a NormalEquality().
        */
        template <class Operation, class NormalEquality>
            class equal_if_annihilator
        {
            struct compare_annihilators {
                template <class Left, class Right>
                auto operator() (Left const & left, Right const & right) const
                RETURNS (math::is_annihilator <Operation> (left) ==
                    math::is_annihilator <Operation> (right));
            };

        public:
            template <class Left, class Right>
            auto operator() (Left const & left, Right const & right) const
            RETURNS (rime::call_if (
                rime::or_ (math::is_annihilator <Operation> (left),
                    math::is_annihilator <Operation> (right)),
                compare_annihilators(), NormalEquality(),
                left, right));
        };

        /**
        Compare two tuples by checking the components in parallel.
        \tparam Compare
            The predicate to use for each component.
        */
        template <class Compare> struct compare_components {
            template <class Left, class Right>
                auto operator() (Left const & left, Right const & right) const
            RETURNS (range::less_lexicographical (
                get_components <typename magma_tag <Left>::type>() (left),
                get_components <typename magma_tag <Right>::type>() (right),
                Compare()));
        };

        /**
        Compare two tuples, ordering annihilators last.
        Annihilators for \a Operation are treated separately.
        Other elements are compared using \a NormalCompare().
        */
        template <class Operation, class NormalCompare>
            class compare_if_annihilator
        {
            // If either left or right is an annihilator:
            // true only if left is not an annihilator (and right is).
            struct not_is_annihilator_left {
                template <class Left, class Right>
                auto operator() (Left const & left, Right const &) const
                RETURNS (!math::is_annihilator <Operation> (left));
            };

        public:
            template <class Left, class Right>
            auto operator() (Left const & left, Right const & right) const
            RETURNS (rime::call_if (
                ! rime::or_ (math::is_annihilator <Operation> (left),
                    math::is_annihilator <Operation> (right)),
                NormalCompare(), not_is_annihilator_left(), left, right));
        };

        /**
        Implement a nullary operation which generates a tuple by calling a
        nullary operation for each element.
        */
        template <class Reassemble, class Operations, class Enable = void>
            struct nullary_operation
        : unimplemented {};

        template <class Reassemble, class ... Operations>
            struct nullary_operation <Reassemble, meta::vector <Operations ...>,
                typename boost::enable_if <meta::all_of_c <
                    is_implemented <Operations>::value ...>>::type>
        : approximate_if <
            meta::any_of_c <is_approximate <Operations>::value ...>>
        {
            typename std::result_of <Reassemble (
                typename std::result_of <Operations()>::type ...)>::type
            operator() () const
            { return Reassemble() (Operations()() ...); }
        };

        /**
        Implement a unary operation which takes the elements of a tuple in
        applies the sequence of operations to each of them, returning the
        results in a new tuple.
        This is implemented iff the operations are all implemented.
        This is marked as approximate iff any of the operations is.

        \tparam Reassemble
            Function class that is passed the new components as arguments.
        \tparam Operations
            Compile-time list of operations that are applied to the elements of
            the tuple.

        \internal
        Indices is a meta::vector of compile-time integrals used by the
        implementation.
        */
        template <class Reassemble, class Operations,
            class Indices =
                typename meta::count <meta::size <Operations>::value>::type,
            class Enable = void>
            struct unary_operation
        : unimplemented {};

        template <class Reassemble, class ... Operations, class ... Indices>
            struct unary_operation <Reassemble,
                meta::vector <Operations ...>, meta::vector <Indices ...>,
                typename boost::enable_if <meta::all_of_c <
                    is_implemented <Operations>::value ...>>::type>
        : approximate_if <
            meta::any_of_c <is_approximate <Operations>::value ...>>
        {
        private:
            // GCC 4.6 crashes if this is a static function instead of a class.
            struct compute {
                /*
                This is a telescoping implementation.
                "compute" is called with the tuple
                Operations is a list of operation functors.
                Indices is a list of compile-time constants 0, 1, 2...
                In the return value this is then expanded as
                Operation0() (components() [0]),
                Operation1() (components() [1]),
                Operation2() (components() [2])
                and so on.
                */
                template <class Components>
                    auto operator() (Components const & components) const
                RETURNS (Reassemble() (
                    Operations() (range::at (components, Indices())) ...));
            };

        public:
            template <class Tuple> auto operator() (Tuple const & tuple) const
            RETURNS (compute() (
                get_components <typename magma_tag <Tuple>::type>() (tuple)));
        };

        /**
        Implement a binary operation which takes the elements of two tuples in
        parallel and applies the sequence of operations to each of them,
        returning the results in a new tuple.
        This is implemented iff the operations are all implemented.
        This is marked as approximate iff any of the operations is.

        \tparam Reassemble
            Function class that is passed the new components as arguments.
        \tparam Operations
            Compile-time list of operations that are applied to the elements of
            the tuples in parallel.

        \internal
        Indices is a meta::vector of compile-time integrals used by the
        implementation.
        */
        template <class Reassemble, class Operations,
            class Indices =
                typename meta::count <meta::size <Operations>::value>::type,
            class Enable = void>
        struct binary_operation
        : unimplemented {};

        template <class Reassemble, class ... Operations, class ... Indices>
            struct binary_operation <Reassemble,
                meta::vector <Operations ...>, meta::vector <Indices ...>,
                typename boost::enable_if <meta::all_of_c <
                    is_implemented <Operations>::value ...>>::type>
        : approximate_if <
            meta::any_of_c <is_approximate <Operations>::value ...>>,
        associative_if <
            meta::all_of_c <is_associative <Operations>::value ...>>,
        commutative_if <
            meta::all_of_c <is_commutative <Operations>::value ...>>,
        idempotent_if <
            meta::all_of_c <is_idempotent <Operations>::value ...>>,
        path_operation_if <
            meta::all_of_c <is_path_operation <Operations>::value ...>>
        {
        private:
            // GCC 4.6 crashes if this is a static function instead of a class.
            struct compute {
                /*
                This implementation is similar to that of unary_operation above,
                but now the left and right components are extracted in parallel.
                */
                template <class LeftComponents, class RightComponents>
                    auto operator() (LeftComponents const & left_components,
                        RightComponents const & right_components) const
                RETURNS (Reassemble() (
                    Operations() (
                        range::at (left_components, Indices()),
                        range::at (right_components, Indices())) ...));
            };

        public:
            template <class Left, class Right> auto operator() (
                Left const & left, Right const & right) const
            RETURNS (compute() (
                get_components <typename magma_tag <Left>::type>() (left),
                get_components <typename magma_tag <Right>::type>() (right)));
        };

        /**
        Implement an operation that takes a stream and tuple, and outputs the
        elements of the tuple to the stream.
        Useful for implementing "print".
        */
        template <class ComponentTags, class Enable = void>
            class print_components
        : unimplemented {};

        template <class ... ComponentTags>
            class print_components <meta::vector <ComponentTags ...>, typename
                boost::enable_if <meta::all_of_c <
                    is_implemented <operation::print <ComponentTags>>::value ...
                >>::type>
        {
            // Known to be empty.
            template <class Stream, class Components, class Enable = typename
                rime::enable_if_constant_true <typename
                    range::result_of <range::callable::empty (Components)>::type
                >::type>
            void print_elements (Stream &, Components const &, bool) const {}

            // Not known to be empty at compile time.
            template <class Stream, class Components, class Enable = typename
                rime::disable_if_constant_true <typename
                    range::result_of <range::callable::empty (Components)>::type
                >::type>
            void print_elements (
                Stream & stream, Components const & components, bool first,
                void * = 0) const
            {
                if (!range::empty (components)) {
                    if (!first)
                        stream << ", ";
                    math::print (stream, range::first (components));
                    print_elements (stream, range::drop (components), false);
                }
            }

        public:
            template <class Stream, class Tuple>
                void operator() (Stream & stream, Tuple const & tuple) const
            {
                stream << '(';
                print_elements (stream, tuple.components(), true);
                stream << ')';
            }
        };

    } // namespace tuple_helper

} // namespace operation

namespace tuple_helper {

    /**
    Evaluate to \c true iff the two meta::vector's of components are of the
    same length, and the types in OtherComponents are explicitly convertible
    from the types in Components, but at least one is not implicitly
    convertible.
    This is useful for providing two overloads of a constructor, one of which
    is implicit and is only available if the conversion of all components is
    implicit, and one which is explicit and only available if the conversion
    is explicit for at least one component.
    */
    template <class Components, class OtherComponents>
        struct components_constructible_only
    : boost::mpl::and_ <
        utility::are_constructible <Components, OtherComponents>,
        boost::mpl::not_ <
            utility::are_convertible <OtherComponents, Components>>>
    {};

} // namespace tuple_helper

} // namespace math

#endif // MATH_DETAIL_TUPLE_HELPER_HPP_INCLUDED

max_stars_repo_name: rogiervd/math

max_issues_repo_name: rogiervd/math

max_forks_repo_name: rogiervd/math