text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_COMPARE_LESS_EQUAL_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_COMPARE_LESS_EQUAL_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

  /*!
    @ingroup group-reduction
    Function object implementing compare_less_equal capabilities

    Returns a logical scalar that is the result of the lexicographic
    test for <= on all elements of the entries

    It is probably not what you wish. Have a look to @ref is_less_equal

    @par Semantic:

    For every parameters of type T0:

    @code
    bool r = compare_less_equal(x,y);
    @endcode

    is similar to:

    @code
    bool r = !compare_greater(y, x)
    @endcode

    @see is_less_equal
  **/
  bool compare_less_equal(Value const& v0, Value const& v1);
} }
#endif

#include <boost/simd/function/scalar/compare_less_equal.hpp>
#include <boost/simd/function/simd/compare_less_equal.hpp>

#endif

ext: hpp

max_stars_repo_name: xmar/pythran

max_issues_repo_name: xmar/pythran

max_forks_repo_name: xmar/pythran


text:
//
// gnutls/host_name_verification.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2020 Paul-Louis Ageneau (paul-louis at ageneau dot org)
//
// 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)
//

#ifndef BOOST_ASIO_GNUTLS_HOST_NAME_VERIFICATION_HPP
#define BOOST_ASIO_GNUTLS_HOST_NAME_VERIFICATION_HPP

#include <boost/asio/gnutls/verify_context.hpp>

#include <gnutls/x509.h>

#include <string>

namespace boost {
namespace asio {
namespace gnutls {

// Verifies a certificate against a host_name according to the rules described in RFC 6125.
class host_name_verification
{
public:
  typedef bool result_type;

  explicit host_name_verification(std::string host)
      : m_host(std::move(host))
  {}

  // Perform certificate verification.
  bool operator()(bool preverified, verify_context& ctx) const
  {
      // Don't bother looking at certificates that have failed pre-verification.
      if (!preverified) return false;

      // Return non-zero for a successful match
      return gnutls_x509_crt_check_hostname(ctx.native_handle(), m_host.c_str()) != 0;
  }

private:
    // The host name to be checked.
    std::string m_host;
};

} // namespace gnutls
} // namespace asio
} // namespace boost

#endif // BOOST_ASIO_GNUTLS_HOST_NAME_VERIFICATION_HPP

max_stars_repo_name: SylemST-UtilCollection/libtorrent-build

max_issues_repo_name: SylemST-UtilCollection/libtorrent-build

max_forks_repo_name: SylemST-UtilCollection/libtorrent-build


text:
#pragma once
#include "bmcweb_config.h"

#include "authorization.hpp"
#include "http_response.hpp"
#include "http_utility.hpp"
#include "logging.hpp"
#include "timer_queue.hpp"
#include "utility.hpp"

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>
#include <boost/beast/websocket.hpp>
#include <json_html_serializer.hpp>
#include <security_headers.hpp>
#include <ssl_key_handler.hpp>

#include <atomic>
#include <chrono>
#include <vector>

namespace crow
{

inline void prettyPrintJson(crow::Response& res)
{
    json_html_util::dumpHtml(res.body(), res.jsonValue);

    res.addHeader("Content-Type", "text/html;charset=UTF-8");
}

#ifdef BMCWEB_ENABLE_DEBUG
static std::atomic<int> connectionCount;
#endif

// request body limit size set by the bmcwebHttpReqBodyLimitMb option
constexpr unsigned int httpReqBodyLimit =
    1024 * 1024 * bmcwebHttpReqBodyLimitMb;

constexpr uint64_t loggedOutPostBodyLimit = 4096;

constexpr uint32_t httpHeaderLimit = 8192;

// drop all connections after 1 minute, this time limit was chosen
// arbitrarily and can be adjusted later if needed
static constexpr const size_t loggedInAttempts =
    (60 / timerQueueTimeoutSeconds);

static constexpr const size_t loggedOutAttempts =
    (15 / timerQueueTimeoutSeconds);

template <typename Adaptor, typename Handler>
class Connection :
    public std::enable_shared_from_this<Connection<Adaptor, Handler>>
{
  public:
    Connection(Handler* handlerIn,
               std::function<std::string()>& getCachedDateStrF,
               detail::TimerQueue& timerQueueIn, Adaptor adaptorIn) :
        adaptor(std::move(adaptorIn)),
        handler(handlerIn), getCachedDateStr(getCachedDateStrF),
        timerQueue(timerQueueIn)
    {
        parser.emplace(std::piecewise_construct, std::make_tuple());
        parser->body_limit(httpReqBodyLimit);
        parser->header_limit(httpHeaderLimit);
        req.emplace(parser->get());

#ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
        std::error_code error;
        std::filesystem::path caPath(ensuressl::trustStorePath);
        auto caAvailable = !std::filesystem::is_empty(caPath, error);
        caAvailable = caAvailable && !error;
        if (caAvailable && persistent_data::SessionStore::getInstance()
                               .getAuthMethodsConfig()
                               .tls)
        {
            adaptor.set_verify_mode(boost::asio::ssl::verify_peer);
            std::string id = "bmcweb";
            int ret = SSL_set_session_id_context(
                adaptor.native_handle(),
                reinterpret_cast<const unsigned char*>(id.c_str()),
                static_cast<unsigned int>(id.length()));
            if (ret == 0)
            {
                BMCWEB_LOG_ERROR << this << " failed to set SSL id";
            }
        }

        adaptor.set_verify_callback([this](
                                        bool preverified,
                                        boost::asio::ssl::verify_context& ctx) {
            // do nothing if TLS is disabled
            if (!persistent_data::SessionStore::getInstance()
                     .getAuthMethodsConfig()
                     .tls)
            {
                BMCWEB_LOG_DEBUG << this << " TLS auth_config is disabled";
                return true;
            }

            // We always return true to allow full auth flow
            if (!preverified)
            {
                BMCWEB_LOG_DEBUG << this << " TLS preverification failed.";
                return true;
            }

            X509_STORE_CTX* cts = ctx.native_handle();
            if (cts == nullptr)
            {
                BMCWEB_LOG_DEBUG << this << " Cannot get native TLS handle.";
                return true;
            }

            // Get certificate
            X509* peerCert =
                X509_STORE_CTX_get_current_cert(ctx.native_handle());
            if (peerCert == nullptr)
            {
                BMCWEB_LOG_DEBUG << this
                                 << " Cannot get current TLS certificate.";
                return true;
            }

            // Check if certificate is OK
            int error = X509_STORE_CTX_get_error(cts);
            if (error != X509_V_OK)
            {
                BMCWEB_LOG_INFO << this << " Last TLS error is: " << error;
                return true;
            }
            // Check that we have reached final certificate in chain
            int32_t depth = X509_STORE_CTX_get_error_depth(cts);
            if (depth != 0)

            {
                BMCWEB_LOG_DEBUG
                    << this << " Certificate verification in progress (depth "
                    << depth << "), waiting to reach final depth";
                return true;
            }

            BMCWEB_LOG_DEBUG << this
                             << " Certificate verification of final depth";

            // Verify KeyUsage
            bool isKeyUsageDigitalSignature = false;
            bool isKeyUsageKeyAgreement = false;

            ASN1_BIT_STRING* usage = static_cast<ASN1_BIT_STRING*>(
                X509_get_ext_d2i(peerCert, NID_key_usage, nullptr, nullptr));

            if (usage == nullptr)
            {
                BMCWEB_LOG_DEBUG << this << " TLS usage is null";
                return true;
            }

            for (int i = 0; i < usage->length; i++)
            {
                if (KU_DIGITAL_SIGNATURE & usage->data[i])
                {
                    isKeyUsageDigitalSignature = true;
                }
                if (KU_KEY_AGREEMENT & usage->data[i])
                {
                    isKeyUsageKeyAgreement = true;
                }
            }

            if (!isKeyUsageDigitalSignature || !isKeyUsageKeyAgreement)
            {
                BMCWEB_LOG_DEBUG << this
                                 << " Certificate ExtendedKeyUsage does "
                                    "not allow provided certificate to "
                                    "be used for user authentication";
                return true;
            }
            ASN1_BIT_STRING_free(usage);

            // Determine that ExtendedKeyUsage includes Client Auth

            stack_st_ASN1_OBJECT* extUsage =
                static_cast<stack_st_ASN1_OBJECT*>(X509_get_ext_d2i(
                    peerCert, NID_ext_key_usage, nullptr, nullptr));

            if (extUsage == nullptr)
            {
                BMCWEB_LOG_DEBUG << this << " TLS extUsage is null";
                return true;
            }

            bool isExKeyUsageClientAuth = false;
            for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++)
            {
                if (NID_client_auth ==
                    OBJ_obj2nid(sk_ASN1_OBJECT_value(extUsage, i)))
                {
                    isExKeyUsageClientAuth = true;
                    break;
                }
            }
            sk_ASN1_OBJECT_free(extUsage);

            // Certificate has to have proper key usages set
            if (!isExKeyUsageClientAuth)
            {
                BMCWEB_LOG_DEBUG << this
                                 << " Certificate ExtendedKeyUsage does "
                                    "not allow provided certificate to "
                                    "be used for user authentication";
                return true;
            }
            std::string sslUser;
            // Extract username contained in CommonName
            sslUser.resize(256, '\0');

            int status = X509_NAME_get_text_by_NID(
                X509_get_subject_name(peerCert), NID_commonName, sslUser.data(),
                static_cast<int>(sslUser.size()));

            if (status == -1)
            {
                BMCWEB_LOG_DEBUG
                    << this << " TLS cannot get username to create session";
                return true;
            }

            size_t lastChar = sslUser.find('\0');
            if (lastChar == std::string::npos || lastChar == 0)
            {
                BMCWEB_LOG_DEBUG << this << " Invalid TLS user name";
                return true;
            }
            sslUser.resize(lastChar);
            std::string unsupportedClientId = "";
            session = persistent_data::SessionStore::getInstance()
                          .generateUserSession(
                              sslUser, req->ipAddress.to_string(),
                              unsupportedClientId,
                              persistent_data::PersistenceType::TIMEOUT);
            if (auto sp = session.lock())
            {
                BMCWEB_LOG_DEBUG << this
                                 << " Generating TLS session: " << sp->uniqueId;
            }
            return true;
        });
#endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION

#ifdef BMCWEB_ENABLE_DEBUG
        connectionCount++;
        BMCWEB_LOG_DEBUG << this << " Connection open, total "
                         << connectionCount;
#endif
    }

    ~Connection()
    {
        res.completeRequestHandler = nullptr;
        cancelDeadlineTimer();
#ifdef BMCWEB_ENABLE_DEBUG
        connectionCount--;
        BMCWEB_LOG_DEBUG << this << " Connection closed, total "
                         << connectionCount;
#endif
    }

    Adaptor& socket()
    {
        return adaptor;
    }

    void start()
    {

        startDeadline(0);

        // TODO(ed) Abstract this to a more clever class with the idea of an
        // asynchronous "start"
        if constexpr (std::is_same_v<Adaptor,
                                     boost::beast::ssl_stream<
                                         boost::asio::ip::tcp::socket>>)
        {
            adaptor.async_handshake(boost::asio::ssl::stream_base::server,
                                    [this, self(shared_from_this())](
                                        const boost::system::error_code& ec) {
                                        if (ec)
                                        {
                                            return;
                                        }
                                        doReadHeaders();
                                    });
        }
        else
        {
            doReadHeaders();
        }
    }

    void handle()
    {
        cancelDeadlineTimer();

        // Fetch the client IP address
        readClientIp();

        bool isInvalidRequest = false;

        // Check for HTTP version 1.1.
        if (req->version() == 11)
        {
            if (req->getHeaderValue(boost::beast::http::field::host).empty())
            {
                isInvalidRequest = true;
                res.result(boost::beast::http::status::bad_request);
            }
        }

        BMCWEB_LOG_INFO << "Request: "
                        << " " << this << " HTTP/" << req->version() / 10 << "."
                        << req->version() % 10 << ' ' << req->methodString()
                        << " " << req->target() << " " << req->ipAddress;

        needToCallAfterHandlers = false;

        if (!isInvalidRequest)
        {
            res.completeRequestHandler = [] {};
            res.isAliveHelper = [this]() -> bool { return isAlive(); };

            req->ioService = static_cast<decltype(req->ioService)>(
                &adaptor.get_executor().context());

            if (!res.completed)
            {
                needToCallAfterHandlers = true;
                res.completeRequestHandler = [self(shared_from_this())] {
                    boost::asio::post(self->adaptor.get_executor(),
                                      [self] { self->completeRequest(); });
                };
                if (req->isUpgrade() &&
                    boost::iequals(
                        req->getHeaderValue(boost::beast::http::field::upgrade),
                        "websocket"))
                {
                    handler->handleUpgrade(*req, res, std::move(adaptor));
                    // delete lambda with self shared_ptr
                    // to enable connection destruction
                    res.completeRequestHandler = nullptr;
                    return;
                }
                auto asyncResp = std::make_shared<bmcweb::AsyncResp>(res);
                handler->handle(*req, asyncResp);
            }
            else
            {
                completeRequest();
            }
        }
        else
        {
            completeRequest();
        }
    }

    bool isAlive()
    {

        if constexpr (std::is_same_v<Adaptor,
                                     boost::beast::ssl_stream<
                                         boost::asio::ip::tcp::socket>>)
        {
            return adaptor.next_layer().is_open();
        }
        else
        {
            return adaptor.is_open();
        }
    }
    void close()
    {
        if constexpr (std::is_same_v<Adaptor,
                                     boost::beast::ssl_stream<
                                         boost::asio::ip::tcp::socket>>)
        {
            adaptor.next_layer().close();
#ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
            if (auto sp = session.lock())
            {
                BMCWEB_LOG_DEBUG << this
                                 << " Removing TLS session: " << sp->uniqueId;
                persistent_data::SessionStore::getInstance().removeSession(sp);
            }
#endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
        }
        else
        {
            adaptor.close();
        }
    }

    void completeRequest()
    {
        BMCWEB_LOG_INFO << "Response: " << this << ' ' << req->url << ' '
                        << res.resultInt() << " keepalive=" << req->keepAlive();

        addSecurityHeaders(*req, res);

        if (needToCallAfterHandlers)
        {
            crow::authorization::cleanupTempSession(*req);
        }

        if (!isAlive())
        {
            // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " <<
            // isReading
            // << ' ' << isWriting;
            // delete this;

            // delete lambda with self shared_ptr
            // to enable connection destruction
            res.completeRequestHandler = nullptr;
            return;
        }
        if (res.body().empty() && !res.jsonValue.empty())
        {
            if (http_helpers::requestPrefersHtml(*req))
            {
                prettyPrintJson(res);
            }
            else
            {
                res.jsonMode();
                res.body() = res.jsonValue.dump(
                    2, ' ', true, nlohmann::json::error_handler_t::replace);
            }
        }

        if (res.resultInt() >= 400 && res.body().empty())
        {
            res.body() = std::string(res.reason());
        }

        if (res.result() == boost::beast::http::status::no_content)
        {
            // Boost beast throws if content is provided on a no-content
            // response.  Ideally, this would never happen, but in the case that
            // it does, we don't want to throw.
            BMCWEB_LOG_CRITICAL
                << this << " Response content provided but code was no-content";
            res.body().clear();
        }

        res.addHeader(boost::beast::http::field::date, getCachedDateStr());

        res.keepAlive(req->keepAlive());

        doWrite();

        // delete lambda with self shared_ptr
        // to enable connection destruction
        res.completeRequestHandler = nullptr;
    }

    void readClientIp()
    {
        boost::system::error_code ec;
        BMCWEB_LOG_DEBUG << "Fetch the client IP address";
        boost::asio::ip::tcp::endpoint endpoint =
            boost::beast::get_lowest_layer(adaptor).remote_endpoint(ec);

        if (ec)
        {
            // If remote endpoint fails keep going. "ClientOriginIPAddress"
            // will be empty.
            BMCWEB_LOG_ERROR << "Failed to get the client's IP Address. ec : "
                             << ec;
        }
        else
        {
            req->ipAddress = endpoint.address();
        }
    }

  private:
    void doReadHeaders()
    {
        BMCWEB_LOG_DEBUG << this << " doReadHeaders";

        // Clean up any previous Connection.
        boost::beast::http::async_read_header(
            adaptor, buffer, *parser,
            [this,
             self(shared_from_this())](const boost::system::error_code& ec,
                                       std::size_t bytesTransferred) {
                BMCWEB_LOG_ERROR << this << " async_read_header "
                                 << bytesTransferred << " Bytes";
                bool errorWhileReading = false;
                if (ec)
                {
                    errorWhileReading = true;
                    BMCWEB_LOG_ERROR
                        << this << " Error while reading: " << ec.message();
                }
                else
                {
                    // if the adaptor isn't open anymore, and wasn't handed to a
                    // websocket, treat as an error
                    if (!isAlive() && !req->isUpgrade())
                    {
                        errorWhileReading = true;
                    }
                }

                cancelDeadlineTimer();

                if (errorWhileReading)
                {
                    close();
                    BMCWEB_LOG_DEBUG << this << " from read(1)";
                    return;
                }

                if (!req)
                {
                    close();
                    return;
                }

                // Note, despite the bmcweb coding policy on use of exceptions
                // for error handling, this one particular use of exceptions is
                // deemed acceptible, as it solved a significant error handling
                // problem that resulted in seg faults, the exact thing that the
                // exceptions rule is trying to avoid. If at some point,
                // boost::urls makes the parser object public (or we port it
                // into bmcweb locally) this will be replaced with
                // parser::parse, which returns a status code

                try
                {
                    req->urlView = boost::urls::url_view(req->target());
                    req->url = req->urlView.encoded_path();
                }
                catch (std::exception& p)
                {
                    BMCWEB_LOG_ERROR << p.what();
                }

                crow::authorization::authenticate(*req, res, session);

                bool loggedIn = req && req->session;
                if (loggedIn)
                {
                    startDeadline(loggedInAttempts);
                    BMCWEB_LOG_DEBUG << "Starting slow deadline";

                    req->urlParams = req->urlView.params();

#ifdef BMCWEB_ENABLE_DEBUG
                    std::string paramList = "";
                    for (const auto param : req->urlParams)
                    {
                        paramList += param->key() + " " + param->value() + " ";
                    }
                    BMCWEB_LOG_DEBUG << "QueryParams: " << paramList;
#endif
                }
                else
                {
                    const boost::optional<uint64_t> contentLength =
                        parser->content_length();
                    if (contentLength &&
                        *contentLength > loggedOutPostBodyLimit)
                    {
                        BMCWEB_LOG_DEBUG << "Content length greater than limit "
                                         << *contentLength;
                        close();
                        return;
                    }

                    startDeadline(loggedOutAttempts);
                    BMCWEB_LOG_DEBUG << "Starting quick deadline";
                }
                doRead();
            });
    }

    void doRead()
    {
        BMCWEB_LOG_DEBUG << this << " doRead";

        boost::beast::http::async_read(
            adaptor, buffer, *parser,
            [this,
             self(shared_from_this())](const boost::system::error_code& ec,
                                       std::size_t bytesTransferred) {
                BMCWEB_LOG_DEBUG << this << " async_read " << bytesTransferred
                                 << " Bytes";

                bool errorWhileReading = false;
                if (ec)
                {
                    BMCWEB_LOG_ERROR
                        << this << " Error while reading: " << ec.message();
                    errorWhileReading = true;
                }
                else
                {
                    if (isAlive())
                    {
                        cancelDeadlineTimer();
                        bool loggedIn = req && req->session;
                        if (loggedIn)
                        {
                            startDeadline(loggedInAttempts);
                        }
                        else
                        {
                            startDeadline(loggedOutAttempts);
                        }
                    }
                    else
                    {
                        errorWhileReading = true;
                    }
                }
                if (errorWhileReading)
                {
                    cancelDeadlineTimer();
                    close();
                    BMCWEB_LOG_DEBUG << this << " from read(1)";
                    return;
                }
                handle();
            });
    }

    void doWrite()
    {
        bool loggedIn = req && req->session;
        if (loggedIn)
        {
            startDeadline(loggedInAttempts);
        }
        else
        {
            startDeadline(loggedOutAttempts);
        }
        BMCWEB_LOG_DEBUG << this << " doWrite";
        res.preparePayload();
        serializer.emplace(*res.stringResponse);
        boost::beast::http::async_write(
            adaptor, *serializer,
            [this,
             self(shared_from_this())](const boost::system::error_code& ec,
                                       std::size_t bytesTransferred) {
                BMCWEB_LOG_DEBUG << this << " async_write " << bytesTransferred
                                 << " bytes";

                cancelDeadlineTimer();

                if (ec)
                {
                    BMCWEB_LOG_DEBUG << this << " from write(2)";
                    return;
                }
                if (!res.keepAlive())
                {
                    close();
                    BMCWEB_LOG_DEBUG << this << " from write(1)";
                    return;
                }

                serializer.reset();
                BMCWEB_LOG_DEBUG << this << " Clearing response";
                res.clear();
                parser.emplace(std::piecewise_construct, std::make_tuple());
                parser->body_limit(httpReqBodyLimit); // reset body limit for
                                                      // newly created parser
                buffer.consume(buffer.size());

                req.emplace(parser->get());
                doReadHeaders();
            });
    }

    void cancelDeadlineTimer()
    {
        if (timerCancelKey)
        {
            BMCWEB_LOG_DEBUG << this << " timer cancelled: " << &timerQueue
                             << ' ' << *timerCancelKey;
            timerQueue.cancel(*timerCancelKey);
            timerCancelKey.reset();
        }
    }

    void startDeadline(size_t timerIterations)
    {
        cancelDeadlineTimer();

        if (timerIterations)
        {
            timerIterations--;
        }

        timerCancelKey =
            timerQueue.add([self(shared_from_this()), timerIterations,
                            readCount{parser->get().body().size()}] {
                // Mark timer as not active to avoid canceling it during
                // Connection destructor which leads to double free issue
                self->timerCancelKey.reset();
                if (!self->isAlive())
                {
                    return;
                }

                bool loggedIn = self->req && self->req->session;
                // allow slow uploads for logged in users
                if (loggedIn && self->parser->get().body().size() > readCount)
                {
                    BMCWEB_LOG_DEBUG << self.get()
                                     << " restart timer - read in progress";
                    self->startDeadline(timerIterations);
                    return;
                }

                // Threshold can be used to drop slow connections
                // to protect against slow-rate DoS attack
                if (timerIterations)
                {
                    BMCWEB_LOG_DEBUG << self.get() << " restart timer";
                    self->startDeadline(timerIterations);
                    return;
                }

                self->close();
            });

        if (!timerCancelKey)
        {
            close();
            return;
        }
        BMCWEB_LOG_DEBUG << this << " timer added: " << &timerQueue << ' '
                         << *timerCancelKey;
    }

  private:
    Adaptor adaptor;
    Handler* handler;

    // Making this a std::optional allows it to be efficiently destroyed and
    // re-created on Connection reset
    std::optional<
        boost::beast::http::request_parser<boost::beast::http::string_body>>
        parser;

    boost::beast::flat_static_buffer<8192> buffer;

    std::optional<boost::beast::http::response_serializer<
        boost::beast::http::string_body>>
        serializer;

    std::optional<crow::Request> req;
    crow::Response res;

    std::weak_ptr<persistent_data::UserSession> session;

    std::optional<size_t> timerCancelKey;

    bool needToCallAfterHandlers{};
    bool needToStartReadAfterComplete{};

    std::function<std::string()>& getCachedDateStr;
    detail::TimerQueue& timerQueue;

    using std::enable_shared_from_this<
        Connection<Adaptor, Handler>>::shared_from_this;
};
} // namespace crow

max_stars_repo_name: pachu-nc/bmcweb

max_issues_repo_name: pachu-nc/bmcweb

max_forks_repo_name: pachu-nc/bmcweb


text:
//  boost/filesystem/convenience.hpp  ----------------------------------------//

//  Copyright Beman Dawes, 2002-2005
//  Copyright Vladimir Prus, 2002
//  Use, modification, and distribution is subject to 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)

//  See library home page at http://www.boost.org/libs/filesystem

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

#ifndef BOOST_FILESYSTEM3_CONVENIENCE_HPP
#define BOOST_FILESYSTEM3_CONVENIENCE_HPP

#include <boost/config.hpp>

# if defined( BOOST_NO_STD_WSTRING )
#   error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
# endif

#include <boost/filesystem/v3/operations.hpp>
#include <boost/system/error_code.hpp>

#include <boost/config/abi_prefix.hpp> // must be the last #include

namespace boost
{
  namespace filesystem3
  {

# ifndef BOOST_FILESYSTEM_NO_DEPRECATED

    inline std::string extension(const path & p)
    {
      return p.extension().string();
    }

    inline std::string basename(const path & p)
    {
      return p.stem().string();
    }

    inline path change_extension( const path & p, const path & new_extension )
    {
      path new_p( p );
      new_p.replace_extension( new_extension );
      return new_p;
    }

# endif

  } // namespace filesystem3
} // namespace boost

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

namespace boost
{
  namespace filesystem
  {
# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
    using filesystem3::extension;
    using filesystem3::basename;
    using filesystem3::change_extension;
# endif
  }
}

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

#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
#endif // BOOST_FILESYSTEM3_CONVENIENCE_HPP

max_stars_repo_name: dyzmapl/BumpTop

max_issues_repo_name: dyzmapl/BumpTop

max_forks_repo_name: dyzmapl/BumpTop


text:
/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.net/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * HproseClient.hpp                                       *
 *                                                        *
 * hprose client class for Cpp.                           *
 *                                                        *
 * LastModified: Jul 7, 2015                              *
 * Author: Chen fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

#ifndef HPROSE_CLIENT_HPROSE_CLIENT_HPP
#define HPROSE_CLIENT_HPROSE_CLIENT_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <hprose/io.hpp>
#include <boost/thread.hpp>

namespace hprose {

namespace HproseTags {

const char ResultTags[4] = { TagResult, TagArgument, TagError, TagEnd }; // Todo: Remove

} // namespace HproseTags

class HproseClient {
protected: // structors

    HproseClient() {
    }

    HproseClient(const std::string & uri) {
        UseService(uri);
    }

    virtual ~HproseClient() {
    }

protected:

    virtual void * GetInvokeContext() = 0;

    virtual void SendData(void * context) = 0;

    virtual void EndInvoke(void * context) = 0;

    virtual std::ostream & GetOutputStream(void * context) = 0;

    virtual std::istream & GetInputStream(void * context) = 0;

public:

    virtual void UseService(const std::string & uri) {
        this->uri = uri;
    }

    template<typename ReturnType>
    inline ReturnType Invoke(const std::string & name) {
        std::vector<Any> args;
        return Invoke<ReturnType>(name, args);
    }

    template<typename ReturnType>
    inline void Invoke(ReturnType & ret, const std::string & name) {
        std::vector<Any> args;
        Invoke(ret, name, args);
    }

#ifndef BOOST_NO_INITIALIZER_LISTS
    template<typename ReturnType, typename ArgType>
    inline ReturnType Invoke(const std::string & name, const std::initializer_list<ArgType> & args) {
        return Invoke<ReturnType>(name, args, false);
    }

    template<typename ReturnType, typename ArgType>
    inline void Invoke(ReturnType & ret, const std::string & name, const std::initializer_list<ArgType> & args) {
        Invoke(ret, name, args, false);
    }
#endif

    template<typename ReturnType, typename ArgsType>
    inline ReturnType Invoke(const std::string & name, ArgsType & args, bool ref = false) {
        ReturnType ret = ReturnType();
        Invoke(ret, name, args, ref);
        return ret;
    }

    template<typename ReturnType, typename ArgsType>
    void Invoke(ReturnType & ret, const std::string & name, ArgsType & args, bool ref = false) {
        std::string error;
        void * context = 0;
        context = GetInvokeContext();
        try {
            DoOutput(name, args, ref, GetOutputStream(context));
            SendData(context);
            DoInput(ret, args, error, GetInputStream(context));
        }
        catch (...) {
        }
        EndInvoke(context);
        if (!error.empty()) {
            HPROSE_THROW_EXCEPTION(error);
        }
    }

    template<typename ReturnType, typename Functor>
    inline void AsyncInvoke(const std::string & name, Functor func) {
        static std::vector<Any> args;
        AsyncInvoke<ReturnType>(name, args, func, false);
    }

    template<typename ReturnType, typename ArgsType, typename Functor>
    inline void AsyncInvoke(const std::string & name, const ArgsType & args, Functor func, bool ref = false) {
        boost::thread thread(Async<ReturnType, ArgsType, Functor>(*this, name, args, func, ref));
    }

    template<typename ReturnType, typename ArgsType, typename Functor, size_t ArraySize>
    inline void AsyncInvoke(const std::string & name, const ArgsType (&args)[ArraySize], Functor func, bool ref = false) {
        std::vector<ArgsType> newArgs(ArraySize);
        for (int i = 0; i < ArraySize; ++i) {
            newArgs[i] = args[i];
        }
        AsyncInvoke<ReturnType>(name, newArgs, func, ref);
    }

private:

    template<typename ReturnType, typename ArgsType, typename Functor>
    class Async {
    public:

        Async(HproseClient & client, const std::string & name, ArgsType args, Functor func, bool ref)
            : client(client), name(name), args(args), func(func), ref(ref) {
        }

    public:

        inline void operator()() {
            ReturnType ret = ReturnType();
            client.Invoke(ret, name, args, ref);
            func(ret, args);
        }

    private:

        HproseClient & client;
        std::string name;
        ArgsType args;
        Functor func;
        bool ref;

    }; // class Async

private:

    template<typename ReturnType, typename ArgsType>
    void DoInput(ReturnType & ret, ArgsType & args, std::string & error, std::istream & stream) {
        HproseReader reader(stream);
        while (true) {
            switch (reader.CheckTags(HproseTags::ResultTags)) {
                case HproseTags::TagResult:
                    ret = reader.Unserialize<ReturnType>();
                    break;
                case HproseTags::TagArgument:
                    //args = reader.ReadList<ArgsType>();
                    break;
                case HproseTags::TagError:
                    error = reader.ReadString();
                    return;
                case HproseTags::TagEnd:
                    return;
            }
        }
    }

    template<typename ArgsType>
    void DoOutput(const std::string & name, ArgsType & args, bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        if (!args.empty()) {
            writer.WriteList(args, false);
            if (ref) {
                writer.WriteBool(true);
            }
        }

        stream << HproseTags::TagEnd;
    }

    template<typename ArgsType, size_t ArraySize>
    void DoOutput(const std::string & name, ArgsType (&args)[ArraySize], bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        if (ArraySize > 0) {
            writer.WriteList(args, false);
            if (ref) {
                writer.WriteBool(true);
            }
        }

        stream << HproseTags::TagEnd;
    }

protected:

    std::string uri;

}; // class HproseClient

} // namespace hprose

#endif // HPROSE_CLIENT_HPROSE_CLIENT_HPP

max_stars_repo_name: hprose/hprose-cpp

max_issues_repo_name: hprose/hprose-cpp

max_forks_repo_name: hprose/hprose-cpp


text:
//------------------------------------------------------------------------------
/// \file
/// \brief
/// \copyright (C) Copyright Aquaveo 2018. Distributed under the xmsng
///  Software License, Version 1.0. (See accompanying file
///  LICENSE_1_0.txt or copy at http://www.aquaveo.com/xmsng/LICENSE_1_0.txt)
//------------------------------------------------------------------------------

//----- Included files ---------------------------------------------------------
#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/shared_ptr.hpp> // boost::shared_ptr
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

#include <xmscore/misc/xmstype.h> // XM_NODATA
#include <xmscore/python/misc/PyUtils.h> // PyIterFromVecPt3d, etc.

#include <xmsgrid/triangulate/TrTin.h>

#include <xmsstamper/python/stamper/stamper_py.h>
#include <xmsstamper/stamper/XmStamperIo.h>

//----- Namespace declaration --------------------------------------------------
namespace py = pybind11;

//----- Internal functions -----------------------------------------------------

//----- Python Interface -------------------------------------------------------
PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr<T>);

void initXmStamperIo(py::module &m)
{
// -----------------------------------------------------------------------------
// XMSTAMPRASTER
// -----------------------------------------------------------------------------
  py::class_<xms::XmStampRaster, boost::shared_ptr<xms::XmStampRaster>> stamp_raster(m, "XmStampRaster");

  stamp_raster.def(py::init<>([](py::object num_pixels_x, py::object num_pixels_y,
           py::object pixel_size_x, py::object pixel_size_y, py::object min,
           py::object vals, py::object no_data) {
    boost::shared_ptr<xms::XmStampRaster> xm_stamp_raster(new xms::XmStampRaster());
    if (!num_pixels_x.is_none())
    {
      xm_stamp_raster->m_numPixelsX = py::cast<int>(num_pixels_x);
    }
    if (!num_pixels_y.is_none())
    {
      xm_stamp_raster->m_numPixelsY = py::cast<int>(num_pixels_y);
    }
    if (!pixel_size_x.is_none())
    {
      xm_stamp_raster->m_pixelSizeX = py::cast<double>(pixel_size_x);
    }
    if (!pixel_size_y.is_none())
    {
      xm_stamp_raster->m_pixelSizeY = py::cast<double>(pixel_size_y);
    }
    if (!min.is_none())
    {
      xm_stamp_raster->m_min = xms::Pt3dFromPyIter(min);
    }
    if (!vals.is_none())
    {
      xm_stamp_raster->m_vals = *xms::VecDblFromPyIter(vals);
    }
    if (!no_data.is_none())
    {
      xm_stamp_raster->m_noData = py::cast<float>(no_data);
    }
    return xm_stamp_raster;
  }),
  py::arg("num_pixels_x") = py::none(), py::arg("num_pixels_y") = py::none(),
  py::arg("pixel_size_x") = py::none(), py::arg("pixel_size_y") = py::none(),
  py::arg("min") = py::none(), py::arg("vals") = py::none(),
  py::arg("no_data") = py::none());

  // ---------------------------------------------------------------------------
  // property: num_pixels_x
  // ---------------------------------------------------------------------------
  stamp_raster.def_readwrite("numPixelsX", &xms::XmStampRaster::m_numPixelsX);
  // ---------------------------------------------------------------------------
  // property: num_pixels_y
  // ---------------------------------------------------------------------------
  stamp_raster.def_readwrite("numPixelsY", &xms::XmStampRaster::m_numPixelsY);
  // ---------------------------------------------------------------------------
  // property: pixel_size_x
  // ---------------------------------------------------------------------------
  stamp_raster.def_readwrite("pixelSizeX", &xms::XmStampRaster::m_pixelSizeX);
  // ---------------------------------------------------------------------------
  // property: pixel_size_y
  // ---------------------------------------------------------------------------
  stamp_raster.def_readwrite("pixelSizeY", &xms::XmStampRaster::m_pixelSizeY);
  // ---------------------------------------------------------------------------
  // property: no_data
  // ---------------------------------------------------------------------------
  stamp_raster.def_readwrite("noData", &xms::XmStampRaster::m_noData);
  // ---------------------------------------------------------------------------
  // property: min
  // ---------------------------------------------------------------------------
  stamp_raster.def_property("min",
  [](xms::XmStampRaster &self) -> py::tuple
  {
    return xms::PyIterFromPt3d(self.m_min);
  },
  [](xms::XmStampRaster &self, py::tuple _min)
  {
    self.m_min = xms::Pt3dFromPyIter(_min);
  });
  // ---------------------------------------------------------------------------
  // property: vals
  // ---------------------------------------------------------------------------
  stamp_raster.def_property("vals",
  [](xms::XmStampRaster &self) -> py::iterable
  {
    return xms::PyIterFromVecDbl(self.m_vals);
  },
  [](xms::XmStampRaster &self, py::iterable _vals)
  {
    self.m_vals = *xms::VecDblFromPyIter(_vals);
  });
  // ---------------------------------------------------------------------------
  // function: GetCellIndexFromColRow
  // ---------------------------------------------------------------------------
  stamp_raster.def("GetCellIndexFromColRow", &xms::XmStampRaster::GetCellIndexFromColRow,
    py::arg("col"), py::arg("row"));
  // ---------------------------------------------------------------------------
  // function: GetColRowFromCellIndex
  // ---------------------------------------------------------------------------
  stamp_raster.def("GetColRowFromCellIndex",
  [](xms::XmStampRaster &self, int index)
  {
    int c, r;
    self.GetColRowFromCellIndex(index, c, r);
    return py::make_tuple(c, r);
  }, py::arg("int"));
  // ---------------------------------------------------------------------------
  // function: GetLocationFromCellIndex
  // ---------------------------------------------------------------------------
  stamp_raster.def("GetLocationFromCellIndex",
  [](xms::XmStampRaster &self, int index)
  {
    return xms::PyIterFromPt3d(self.GetLocationFromCellIndex(index));
  }, py::arg("index"));
  // ---------------------------------------------------------------------------
  // function: WriteGridFile
  // ---------------------------------------------------------------------------
  stamp_raster.def("WriteGridFile", &xms::XmStampRaster::WriteGridFile,
    py::arg("file_name"), py::arg("format"));
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamp_raster.def("ReadFromFile",
  [](xms::XmStampRaster &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamp_raster.def("WriteToFile",
  [](xms::XmStampRaster &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMSTAMPRASTERENUM
// -----------------------------------------------------------------------------
  py::enum_<xms::XmStampRaster::XmRasterFormatEnum>(stamp_raster,
         "raster_format_enum", "weight_enum for InterpIdw class")
    .value("RS_ARCINFO_ASCII",
                 xms::XmStampRaster::XmRasterFormatEnum::RS_ARCINFO_ASCII)
    .export_values();

// -----------------------------------------------------------------------------
// XMWINGWALL
// -----------------------------------------------------------------------------
  py::class_<xms::XmWingWall, boost::shared_ptr<xms::XmWingWall>>
    stamper_wing_wall(m, "XmWingWall");

  stamper_wing_wall.def(py::init<>([](py::object wing_wall_angle) {
    boost::shared_ptr<xms::XmWingWall> rval(new xms::XmWingWall());
    if (!wing_wall_angle.is_none())
    {
      rval->m_wingWallAngle = py::cast<double>(wing_wall_angle);
    }
    return rval;
  }), py::arg("wing_wall_angle") = py::none());
  // ---------------------------------------------------------------------------
  // property: wingWallAngle
  // ---------------------------------------------------------------------------
  stamper_wing_wall.def_readwrite("wingWallAngle",
             &xms::XmWingWall::m_wingWallAngle);
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_wing_wall.def("ReadFromFile",
    [](xms::XmWingWall &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_wing_wall.def("WriteToFile",
    [](xms::XmWingWall &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMSLOPEDABUTMENT
// -----------------------------------------------------------------------------
  py::class_<xms::XmSlopedAbutment, boost::shared_ptr<xms::XmSlopedAbutment>>
    stamper_sloped_abutment(m, "XmSlopedAbutment");

  stamper_sloped_abutment.def(py::init<>([](py::object max_x, py::object slope) {
    boost::shared_ptr<xms::XmSlopedAbutment> xm_sloped_abutment(new xms::XmSlopedAbutment());
    if (!max_x.is_none())
    {
      xm_sloped_abutment->m_maxX = py::cast<double>(max_x);
    }
    if (!slope.is_none())
    {
      xm_sloped_abutment->m_slope = *xms::VecPt3dFromPyIter(slope);
    }
    return xm_sloped_abutment;
  }),
  py::arg("max_x") = py::none(), py::arg("slope") = py::none());
  // ---------------------------------------------------------------------------
  // property: maxX
  // ---------------------------------------------------------------------------
  stamper_sloped_abutment.def_readwrite("maxX",
    &xms::XmSlopedAbutment::m_maxX);
  // ---------------------------------------------------------------------------
  // property: slope
  // ---------------------------------------------------------------------------
  stamper_sloped_abutment.def_property("slope",
    [](xms::XmSlopedAbutment &self) -> py::iterable
  {
    return xms::PyIterFromVecPt3d(self.m_slope);
  },
    [](xms::XmSlopedAbutment &self, py::iterable slope)
  {
    self.m_slope = *xms::VecPt3dFromPyIter(slope);
  });
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_sloped_abutment.def("ReadFromFile",
    [](xms::XmSlopedAbutment &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_sloped_abutment.def("WriteToFile",
    [](xms::XmSlopedAbutment &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMGUIDEBANK
// -----------------------------------------------------------------------------
  py::class_<xms::XmGuidebank, boost::shared_ptr<xms::XmGuidebank>>
    stamper_guide_bank(m, "XmGuidebank");

  stamper_guide_bank.def(py::init<>([](py::object side, py::object radius1,
           py::object radius2, py::object width, py::object n_pts) {
    boost::shared_ptr<xms::XmGuidebank> xm_guidebank(new xms::XmGuidebank());
    if (!side.is_none())
    {
      xm_guidebank->m_side = py::cast<int>(side);
    }
    if (!radius1.is_none())
    {
      xm_guidebank->m_radius1 = py::cast<double>(radius1);
    }
    if (!radius2.is_none())
    {
      xm_guidebank->m_radius2 = py::cast<double>(radius2);
    }
    if (!width.is_none())
    {
      xm_guidebank->m_width = py::cast<double>(width);
    }
    if (!n_pts.is_none())
    {
      xm_guidebank->m_nPts = py::cast<int>(n_pts);
    }
    return xm_guidebank;
  }),
  py::arg("side") = py::none(), py::arg("radius1") = py::none(),
  py::arg("radius2") = py::none(), py::arg("width") = py::none(),
  py::arg("n_pts") = py::none());
  // ---------------------------------------------------------------------------
  // property: side
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def_readwrite("side",
    &xms::XmGuidebank::m_side);
  // ---------------------------------------------------------------------------
  // property: radius1
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def_readwrite("radius1",
    &xms::XmGuidebank::m_radius1);
  // ---------------------------------------------------------------------------
  // property: m_radius2
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def_readwrite("radius2",
    &xms::XmGuidebank::m_radius2);
  // ---------------------------------------------------------------------------
  // property: m_width
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def_readwrite("width",
    &xms::XmGuidebank::m_width);
  // ---------------------------------------------------------------------------
  // property: n_pts
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def_readwrite("nPts",
    &xms::XmGuidebank::m_nPts);
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def("ReadFromFile",
    [](xms::XmGuidebank &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_guide_bank.def("WriteToFile",
    [](xms::XmGuidebank &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMSTAMPERENDCAP
// -----------------------------------------------------------------------------
  py::class_<xms::XmStamperEndCap, boost::shared_ptr<xms::XmStamperEndCap>>
    stamper_end_cap(m, "XmStamperEndCap");

  stamper_end_cap.def(py::init<>(
  [](int endcap_type, double angle, py::object guidebank,
     py::object sloped_abutment, py::object wing_wall) {
    boost::shared_ptr<xms::XmStamperEndCap> rval(new xms::XmStamperEndCap);
    rval->m_angle = angle;
    if (!guidebank.is_none())
    {
      rval->m_guidebank = py::cast<xms::XmGuidebank>(guidebank);
      rval->m_type = 0;
    }
    else if (!sloped_abutment.is_none())
    {
      rval->m_slopedAbutment = py::cast<xms::XmSlopedAbutment>(sloped_abutment);
      rval->m_type = 1;
    }
    else if (!wing_wall.is_none())
    {
      rval->m_wingWall = py::cast<xms::XmWingWall>(wing_wall);
      rval->m_type = 2;
    }
    else
    {
      if (endcap_type < 0 || endcap_type > 2)
        rval->m_type = 2;
      else
        rval->m_type = endcap_type;
    }
    return rval;
  }
  ), py::arg("endcap_type") = -1, py::arg("angle") = 0,
     py::arg("guidebank") = py::none(), py::arg("sloped_abutment") = py::none(),
     py::arg("wing_wall") = py::none());
  // ---------------------------------------------------------------------------
  // property: type
  // ---------------------------------------------------------------------------
  stamper_end_cap.def_readwrite("type",
    &xms::XmStamperEndCap::m_type);
  // ---------------------------------------------------------------------------
  // property: angle
  // ---------------------------------------------------------------------------
  stamper_end_cap.def_readwrite("angle",
    &xms::XmStamperEndCap::m_angle);
  // ---------------------------------------------------------------------------
  // property: guidebank
  // ---------------------------------------------------------------------------
  stamper_end_cap.def_readwrite("guidebank",
    &xms::XmStamperEndCap::m_guidebank);
  // ---------------------------------------------------------------------------
  // property: slopedAbutment
  // ---------------------------------------------------------------------------
  stamper_end_cap.def_readwrite("slopedAbutment",
    &xms::XmStamperEndCap::m_slopedAbutment);
  // ---------------------------------------------------------------------------
  // property: wingWall
  // ---------------------------------------------------------------------------
  stamper_end_cap.def_readwrite("wingWall",
    &xms::XmStamperEndCap::m_wingWall);
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_end_cap.def("ReadFromFile",
    [](xms::XmStamperEndCap &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_end_cap.def("WriteToFile",
    [](xms::XmStamperEndCap &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMSTAMPCROSSSECTION
// -----------------------------------------------------------------------------
  py::class_<xms::XmStampCrossSection,
    boost::shared_ptr<xms::XmStampCrossSection>>
    stamper_cross_section(m, "XmStampCrossSection");
  stamper_cross_section.def(py::init<>(
  [](py::iterable left, py::iterable right, float left_max, float right_max,
     int index_left_shoulder, int index_right_shoulder) {
      boost::shared_ptr<xms::XmStampCrossSection> rval(new xms::XmStampCrossSection);
      rval->m_left = *xms::VecPt3dFromPyIter(left);
      rval->m_right = *xms::VecPt3dFromPyIter(right);
      rval->m_leftMax = left_max;
      rval->m_rightMax = right_max;
      rval->m_idxLeftShoulder = index_left_shoulder;
      rval->m_idxRightShoulder = index_right_shoulder;
      return rval;
  }
  ), py::arg("left"), py::arg("right"), py::arg("left_max") = 0.0,
     py::arg("right_max") = 0.0, py::arg("index_left_shoulder") = 0,
     py::arg("index_right_shoulder") = 0);
  // ---------------------------------------------------------------------------
  // property: left
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_property("left",
  [](xms::XmStampCrossSection &self) -> py::iterable
  {
      return xms::PyIterFromVecPt3d(self.m_left);
  },
  [](xms::XmStampCrossSection &self, py::iterable left)
  {
      self.m_left = *xms::VecPt3dFromPyIter(left);
  });
  // ---------------------------------------------------------------------------
  // property: leftMax
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_readwrite("leftMax", &xms::XmStampCrossSection::m_leftMax);
  // ---------------------------------------------------------------------------
  // property: idxLeftShoulder
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_readwrite("idxLeftShoulder", &xms::XmStampCrossSection::m_idxLeftShoulder);
  // ---------------------------------------------------------------------------
  // property: right
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_property("right",
  [](xms::XmStampCrossSection &self) -> py::iterable
  {
      return xms::PyIterFromVecPt3d(self.m_right);
  },
  [](xms::XmStampCrossSection &self, py::iterable right)
  {
      self.m_right = *xms::VecPt3dFromPyIter(right);
  });
  // ---------------------------------------------------------------------------
  // property: rightMax
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_readwrite("rightMax", &xms::XmStampCrossSection::m_rightMax);
  // ---------------------------------------------------------------------------
  // property: idxRightShoulder
  // ---------------------------------------------------------------------------
  stamper_cross_section.def_readwrite("idxRightShoulder", &xms::XmStampCrossSection::m_idxRightShoulder);
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_cross_section.def("ReadFromFile",
    [](xms::XmStampCrossSection &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_cross_section.def("WriteToFile",
    [](xms::XmStampCrossSection &self, std::string file_name, std::string card_name)
  {
    // TODO: This needs some error checking
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));

// -----------------------------------------------------------------------------
// XMSTAMPERIO
// -----------------------------------------------------------------------------
  py::class_<xms::XmStamperIo, boost::shared_ptr<xms::XmStamperIo>>
    stamper_io(m, "XmStamperIo");
  stamper_io.def(py::init<>(
  [](py::iterable centerline, py::object stamping_type, py::iterable cs,
     py::object first_end_cap, py::object last_end_cap,
     py::object bathymetry, py::object raster) {
    boost::shared_ptr<xms::XmStamperIo> rval(new xms::XmStamperIo);

    if (!centerline.is_none())
    {
      rval->m_centerLine = *xms::VecPt3dFromPyIter(centerline);
    }
    if (!stamping_type.is_none())
    {
      rval->m_stampingType = py::cast<int>(stamping_type);
    }
    if (!cs.is_none())
    {
      std::vector<xms::XmStampCrossSection> vec_cs;
      vec_cs.resize(py::len(cs));
      int i = 0;
      for (auto item : cs)
      {
        if (!item.is_none())
        {
          vec_cs.at(i) = item.cast<xms::XmStampCrossSection>();
        }
        i++;
      }
      rval->m_cs = vec_cs;
    }
    if (!first_end_cap.is_none())
    {
      rval->m_firstEndCap= py::cast<xms::XmStamperEndCap>(first_end_cap);
    }
    if (!last_end_cap.is_none())
    {
      rval->m_lastEndCap= py::cast<xms::XmStamperEndCap>(last_end_cap);
    }
    if (!bathymetry.is_none())
    {

      rval->m_bathymetry = py::cast<boost::shared_ptr<xms::TrTin>>(bathymetry);
    }
    if (!raster.is_none())
    {

      rval->m_raster = py::cast<xms::XmStampRaster>(raster);
    }
    return rval;
  }), py::arg("centerline"), py::arg("stamping_type") = py::none(), py::arg("cs"),
     py::arg("first_end_cap") = py::none(), py::arg("last_end_cap") = py::none(),
     py::arg("bathymetry") = py::none(), py::arg("raster") = py::none());
  // ---------------------------------------------------------------------------
  // property: centerLine
  // ---------------------------------------------------------------------------
  stamper_io.def_property("centerLine",
  [](xms::XmStamperIo &self) -> py::iterable
  {
  return xms::PyIterFromVecPt3d(self.m_centerLine);
  },
  [](xms::XmStamperIo &self, py::iterable centerline)
  {
    self.m_centerLine = *xms::VecPt3dFromPyIter(centerline);
  });
  // ---------------------------------------------------------------------------
  // property: stampingType
  // ---------------------------------------------------------------------------
  stamper_io.def_readwrite("stampingType",
    &xms::XmStamperIo::m_stampingType);
  // ---------------------------------------------------------------------------
  // property: cs
  // ---------------------------------------------------------------------------
  stamper_io.def_property("cs",
    [](xms::XmStamperIo &self) -> py::iterable
  {
    auto tuple_ret = py::tuple(self.m_cs.size());
    for (size_t i = 0; i < tuple_ret.size(); i++) {
      tuple_ret[i] = self.m_cs.at(i);
    }
    return tuple_ret;
  },
  [](xms::XmStamperIo &self, py::iterable& py_cs)
  {
    std::vector<xms::XmStampCrossSection> vec_cs;
    vec_cs.resize(py::len(py_cs));
    int i = 0;
    for (auto item : py_cs)
    {
        if (!item.is_none())
        {
            vec_cs.at(i) = item.cast<xms::XmStampCrossSection>();
        }
        i++;
    }
    self.m_cs = vec_cs;
  });
  // ---------------------------------------------------------------------------
  // property: firstEndCap
  // ---------------------------------------------------------------------------
  stamper_io.def_readwrite("firstEndCap", &xms::XmStamperIo::m_firstEndCap);
  // ---------------------------------------------------------------------------
  // property: last_end_cap
  // ---------------------------------------------------------------------------
  stamper_io.def_readwrite("lastEndCap", &xms::XmStamperIo::m_lastEndCap);
  // ---------------------------------------------------------------------------
  // property: raster
  // ---------------------------------------------------------------------------
  stamper_io.def_readwrite("raster", &xms::XmStamperIo::m_raster);
  // ---------------------------------------------------------------------------
  // property: bathymetry
  // ---------------------------------------------------------------------------
  stamper_io.def_property("bathymetry",
  [](xms::XmStamperIo &self) -> boost::shared_ptr<xms::TrTin>
  {
    return self.m_bathymetry;
  },
  [](xms::XmStamperIo &self, boost::shared_ptr<xms::TrTin> &bathymetry)
  {
    self.m_bathymetry = bathymetry;
  });
  // ---------------------------------------------------------------------------
  // function: outTin
  // ---------------------------------------------------------------------------
  stamper_io.def_property_readonly("outTin",
  [](xms::XmStamperIo &self) -> boost::shared_ptr<xms::TrTin>
  {
    return self.m_outTin;
  });
  // ---------------------------------------------------------------------------
  // property: outBreaklines
  // ---------------------------------------------------------------------------
  stamper_io.def_property_readonly("outBreaklines",
  [](xms::XmStamperIo &self) -> py::iterable
  {
    return xms::PyIterFromVecInt2d(self.m_outBreakLines);
  });
  // ---------------------------------------------------------------------------
  // function: ReadFromFile
  // ---------------------------------------------------------------------------
  stamper_io.def("ReadFromFile",
  [](xms::XmStamperIo &self, std::string file_name)
  {
    std::ifstream is;
    is.open(file_name, std::ios::in);
    self.ReadFromFile(is);
    is.close();
  }, py::arg("file_name"));
  // ---------------------------------------------------------------------------
  // function: WriteToFile
  // ---------------------------------------------------------------------------
  stamper_io.def("WriteToFile",
  [](xms::XmStamperIo &self, std::string file_name, std::string card_name)
  {
    std::ofstream os;
    os.open(file_name, std::ios::out);
    self.WriteToFile(os, card_name);
    os.close();
  }, py::arg("file_name"), py::arg("card_name"));
}

ext: cpp

max_stars_repo_name: rohankumardubey/xmsstamper

max_issues_repo_name: rohankumardubey/xmsstamper

max_forks_repo_name: Aquaveo/xmsstamper


text:
// Copyright (c) 2014-2020 The Virie Project
// Copyright (c) 2012-2013 The Boolberry developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/algorithm/string/case_conv.hpp>

#include "string_coding.h"
#include "offers_services_helpers.h"
#include "etc_custom_serialization.h"

#include "misc_language.h"
#include "currency_basic.h"

namespace bc_services
{

  bool order_offers_by_timestamp(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->timestamp < b->timestamp;
  }
  //------------------------------------------------------------------
  bool order_offers_by_amount_primary(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->amount_primary < b->amount_primary;
  }
  //------------------------------------------------------------------
  bool order_offers_by_amount_target(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->amount_target < b->amount_target;
  }
  //------------------------------------------------------------------
  bool order_offers_by_rate(const offer_details_ex* a, const offer_details_ex* b)
  {
    return calculate_offer_rate(*a) < calculate_offer_rate(*b);
  }
  //------------------------------------------------------------------
  bool order_offers_by_payment_types(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->payment_types < b->payment_types;
  }
  //------------------------------------------------------------------
  bool order_offers_by_contacts(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->contacts < b->contacts;
  }
  //------------------------------------------------------------------
  bool order_offers_by_location(const offer_details_ex* a, const offer_details_ex* b)
  {
    return a->location_city < b->location_city;
  }
  //------------------------------------------------------------------
  bool order_offers_by_name(const offer_details_ex* a, const offer_details_ex* b)
  {
    return currency::utf8_to_lower(a->target) < currency::utf8_to_lower(b->target);
  }
  //------------------------------------------------------------------
  std::vector<sort_offers_func_type> gsort_offers_predicates;
  bool init_vector = epee::misc_utils::static_initializer([](){
    gsort_offers_predicates.resize(ORDER_CALLBACKS_COUNT);
    gsort_offers_predicates[ORDER_BY_TIMESTAMP] = &order_offers_by_timestamp;
    gsort_offers_predicates[ORDER_BY_AMOUNT_PRIMARY] = &order_offers_by_amount_primary;
    gsort_offers_predicates[ORDER_BY_AMOUNT_TARGET] = &order_offers_by_amount_target;
    gsort_offers_predicates[ORDER_BY_AMOUNT_RATE] = &order_offers_by_rate;
    gsort_offers_predicates[ORDER_BY_PAYMENT_TYPES] = &order_offers_by_payment_types;
    gsort_offers_predicates[ORDER_BY_CONTACTS] = &order_offers_by_contacts;
    gsort_offers_predicates[ORDER_BY_LOCATION] = &order_offers_by_location;
    gsort_offers_predicates[ORDER_BY_NAME] = &order_offers_by_name;
    return true;
  });
  //  std::locale locale_utf8;
  bool init_locale = epee::misc_utils::static_initializer([](){
    setlocale(LC_ALL, "");
    return true;
  });

  to_low_case_ptr_type to_low_case_external = nullptr;

  void set_external_to_low_converter(to_low_case_ptr_type cb)
  {
    to_low_case_external = cb;
  }

  std::wstring to_lower_local_w(const std::string& s)
  {
    //std::u16string a;
    std::wstring ws = epee::string_encoding::utf8_to_wstring(s);
    if (to_low_case_external)
      return to_low_case_external(ws);
    //std::transform(ws.begin(), ws.end(), ws.begin(), ::towlower);
    boost::algorithm::to_lower(ws);
    return ws;
  }

#define SECONDS_IN_ONE_DAY (60*60*24)

  bool is_offer_matched_by_filter(const offer_details_ex& o, const core_offers_filter& of, uint64_t current_time)
  {
    if (o.stopped)
      return false;
    //check offer type condition
    if (of.offer_type_mask)
    {
      switch (o.offer_type)
      {
      case OFFER_TYPE_PRIMARY_TO_TARGET:
        if (!(of.offer_type_mask & OFFER_TYPE_MASK_PRIMARY_TO_TARGET))
          return false;
        break;
      case OFFER_TYPE_TARGET_TO_PRIMARY:
        if (!(of.offer_type_mask & OFFER_TYPE_MASK_TARGET_TO_PRIMARY))
          return false;
        break;
      case OFFER_TYPE_GOODS_TO_PRIMARY:
        if (!(of.offer_type_mask & OFFER_TYPE_MASK_GOODS_TO_PRIMARY))
          return false;
        break;
      case OFFER_TYPE_PRIMARY_TO_GOODS:
        if (!(of.offer_type_mask & OFFER_TYPE_MASK_PRIMARY_TO_GOODS))
          return false;
        break;
      default:
        return false;
      }
    }

    //check timestamp condition
    if (of.timestamp_start && (o.timestamp < of.timestamp_start))
      return false;
    if (of.timestamp_stop && (o.timestamp > of.timestamp_stop))
      return false;

    //check bonus field
    if (of.bonus && o.bonus.empty())
      return false;

    //check category
    if (!of.category.empty() && o.category.find(of.category) == std::string::npos)
      return false;

    //check target condition
    if (of.target.size() && !currency::utf8_substring_test_case_insensitive(of.target, o.target))
      return false;

    if (of.primary.size() && !currency::utf8_substring_test_case_insensitive(of.primary, o.primary))
      return false;

    //check payment_types condition (TODO: add more complicated algo here)
    if (of.payment_types.size())
    {
      for (const auto& ot : of.payment_types)
      {
        if (std::string::npos == o.payment_types.find(ot))
          return false;
      }
    }

    //check target condition
    if (of.location_country.size() && (of.location_country != o.location_country))
      return false;

    //check target condition
    if (of.location_city.size() && !currency::utf8_substring_test_case_insensitive(of.location_city, o.location_city))
      return false;

    //check amount
    if (of.amount_low_limit && (of.amount_low_limit > o.amount_primary))
      return false;
    if (of.amount_up_limit && (of.amount_up_limit < o.amount_primary))
      return false;

    double rate = ((static_cast<double>(o.amount_target) / ETC_AMOUNT_DIVIDER)) / (static_cast<double>(o.amount_primary) / COIN);
    //check rate
    if (of.rate_low_limit && (of.rate_low_limit > rate))
      return false;
    if (of.rate_up_limit && (of.rate_up_limit < rate))
      return false;

    //check keywords
    if (!of.keyword.empty())
    {
      std::wstring keyword_lowcase = to_lower_local_w(of.keyword);
      auto check_func = [&keyword_lowcase] (const std::vector<const std::string *> &values) -> bool
      {
        for (auto value : values)
          if (to_lower_local_w(*value).find(keyword_lowcase) != std::wstring::npos)
            return true;
        return false;
      };
      if (!check_func({ &o.bonus, &o.target, &o.location_country, &o.location_city, &o.contacts, &o.comment,
                        &o.payment_types, &o.deal_option, &o.category }))
        return false;
    }
    if (o.expiration_time && current_time > o.timestamp && current_time - o.timestamp > o.expiration_time*SECONDS_IN_ONE_DAY)
      return false;

    return true;
  }
  //--------------------------------------------------------------------------------
  bool filter_offers_list(std::list<bc_services::offer_details_ex>& offers, const bc_services::core_offers_filter& filter, uint64_t current_core_time)
  {

    //filter
    offers.remove_if([&](bc_services::offer_details_ex& o) -> bool {
      return !is_offer_matched_by_filter(o, filter, current_core_time);
    });

    //sort
    CHECK_AND_ASSERT_MES(filter.order_by < gsort_offers_predicates.size(), false, "Wrong cof.order_by value");
    auto cb = *gsort_offers_predicates[static_cast<size_t>(filter.order_by)];

    //sort iterators in needed way
    if (!filter.reverse)
    {
      offers.sort([&](const bc_services::offer_details_ex& a, const bc_services::offer_details_ex& b)
      {
        return cb(&a, &b);
      });
    }
    else
    {
      offers.sort([&](const bc_services::offer_details_ex& a, const bc_services::offer_details_ex& b)
      {
        return cb(&b, &a);
      });
    }

    //now cut what not needed
    auto it = std::next(offers.begin(), std::min<uint64_t>(filter.offset, offers.size()));
    offers.erase(offers.begin(), it);
    // cut limit
    it = std::next(offers.begin(), std::min<uint64_t>(filter.limit, offers.size()));
    offers.erase(it, offers.end());

    return true;
  }
  //--------------------------------------------------------------------------------
  crypto::hash offer_id_from_hash_and_index(const crypto::hash& tx_id, uint64_t index)
  {
    crypto::hash r = tx_id;
    //xor
    *(uint64_t*)&r ^= index;
    return r;
  }
  //---------------------------------------------------------------
  crypto::hash offer_id_from_hash_and_index(const offer_id& oid)
  {
    return offer_id_from_hash_and_index(oid.tx_id, oid.index);
  }
  //---------------------------------------------------------------
  const crypto::public_key get_offer_secure_key_by_index_from_tx(const currency::transaction& tx, size_t index)
  {
    size_t count = 0;
    for (const auto& a : tx.attachment)
    {
      if (a.type() == typeid(currency::tx_service_attachment))
      {
        const currency::tx_service_attachment& txsa = boost::get<currency::tx_service_attachment>(a);
        if (txsa.service_id == BC_OFFERS_SERVICE_ID)
        {
          if (count != index)
          {
            count++;
            continue;
          }

          if (txsa.security.empty())
            return currency::null_pkey;
          return txsa.security.back();
        }
      }
    }
    return currency::null_pkey;
  }

} // namespace bc_services

max_stars_repo_name: Virie/Virie

max_issues_repo_name: Virie/Virie

max_forks_repo_name: Virie/Virie


text:
#include "util/static_rtree.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "engine/geospatial_query.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/exception.hpp"
#include "util/rectangle.hpp"
#include "util/typedefs.hpp"

#include "../common/temporary_file.hpp"
#include "mocks/mock_datafacade.hpp"

#include <boost/functional/hash.hpp>
#include <boost/test/unit_test.hpp>

#include <cmath>
#include <cstdint>

#include <algorithm>
#include <filesystem>
#include <memory>
#include <random>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

// explicit TBB scheduler init to register resources cleanup at exit
#if TBB_VERSION_MAJOR == 2020
#include <tbb/global_control.h>
tbb::global_control scheduler(tbb::global_control::max_allowed_parallelism, 2);
#else
#include <tbb/task_scheduler_init.h>
tbb::task_scheduler_init init(2);
#endif

BOOST_AUTO_TEST_SUITE(static_rtree)

using namespace osrm;
using namespace osrm::util;
using namespace osrm::test;

constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
constexpr uint32_t TEST_LEAF_NODE_SIZE = 64;

using TestData = extractor::EdgeBasedNodeSegment;
using TestStaticRTree = StaticRTree<TestData,
                                    osrm::storage::Ownership::Container,
                                    TEST_BRANCHING_FACTOR,
                                    TEST_LEAF_NODE_SIZE>;
using MiniStaticRTree = StaticRTree<TestData, osrm::storage::Ownership::Container, 2, 128>;
using TestDataFacade = MockDataFacade<osrm::engine::routing_algorithms::ch::Algorithm>;

// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 42;
static const int32_t WORLD_MIN_LAT = -85 * COORDINATE_PRECISION;
static const int32_t WORLD_MAX_LAT = 85 * COORDINATE_PRECISION;
static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;

template <typename DataT> class LinearSearchNN
{
  public:
    LinearSearchNN(const std::vector<Coordinate> &coords, const std::vector<DataT> &edges)
        : coords(coords), edges(edges)
    {
    }

    std::vector<DataT> Nearest(const Coordinate &input_coordinate, const unsigned num_results)
    {
        std::vector<DataT> local_edges(edges);

        auto projected_input = web_mercator::fromWGS84(input_coordinate);
        const auto segment_comparator = [this, &projected_input](const DataT &lhs,
                                                                 const DataT &rhs) {
            using web_mercator::fromWGS84;
            const auto lhs_result = coordinate_calculation::projectPointOnSegment(
                fromWGS84(coords[lhs.u]), fromWGS84(coords[lhs.v]), projected_input);
            const auto rhs_result = coordinate_calculation::projectPointOnSegment(
                fromWGS84(coords[rhs.u]), fromWGS84(coords[rhs.v]), projected_input);
            const auto lhs_squared_dist = coordinate_calculation::squaredEuclideanDistance(
                lhs_result.second, projected_input);
            const auto rhs_squared_dist = coordinate_calculation::squaredEuclideanDistance(
                rhs_result.second, projected_input);
            return lhs_squared_dist < rhs_squared_dist;
        };

        std::nth_element(local_edges.begin(),
                         local_edges.begin() + num_results,
                         local_edges.end(),
                         segment_comparator);
        local_edges.resize(num_results);

        return local_edges;
    }

  private:
    const std::vector<Coordinate> &coords;
    const std::vector<TestData> &edges;
};

template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
{
    struct TupleHash
    {
        typedef std::pair<unsigned, unsigned> argument_type;
        typedef std::size_t result_type;

        result_type operator()(const argument_type &t) const
        {
            std::size_t val{0};
            boost::hash_combine(val, t.first);
            boost::hash_combine(val, t.second);
            return val;
        }
    };

    RandomGraphFixture()
    {
        std::mt19937 g(RANDOM_SEED);

        std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
        std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);

        for (unsigned i = 0; i < NUM_NODES; i++)
        {
            int lon = lon_udist(g);
            int lat = lat_udist(g);
            coords.emplace_back(Coordinate(FixedLongitude{lon}, FixedLatitude{lat}));
        }

        std::uniform_int_distribution<> edge_udist(0, coords.size() - 1);

        std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;

        while (edges.size() < NUM_EDGES)
        {
            TestData data;
            data.u = edge_udist(g);
            data.v = edge_udist(g);
            data.is_startpoint = true;
            if (used_edges.find(std::pair<unsigned, unsigned>(
                    std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
            {
                edges.emplace_back(data);
                used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
            }
        }
    }

    std::vector<Coordinate> coords;
    std::vector<TestData> edges;
};

struct GraphFixture
{
    GraphFixture(const std::vector<std::pair<FloatLongitude, FloatLatitude>> &input_coords,
                 const std::vector<std::tuple<unsigned, unsigned, bool>> &input_edges)
    {

        for (unsigned i = 0; i < input_coords.size(); i++)
        {
            coords.emplace_back(input_coords[i].first, input_coords[i].second);
        }

        for (const auto &pair : input_edges)
        {
            TestData d;
            d.u = std::get<0>(pair);
            d.v = std::get<1>(pair);
            // We set the forward nodes to the target node-based-node IDs, just
            // so we have something to test against.  Because this isn't a real
            // graph, the actual values aren't important, we just need something
            // to examine during tests.
            d.forward_segment_id = {std::get<1>(pair), true};
            d.reverse_segment_id = {std::get<0>(pair), true};
            d.fwd_segment_position = 0;
            d.is_startpoint = std::get<2>(pair);
            edges.emplace_back(d);
        }
    }

    std::vector<Coordinate> coords;
    std::vector<TestData> edges;
};

typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 3, TEST_LEAF_NODE_SIZE / 2>
    TestRandomGraphFixture_LeafHalfFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 5, TEST_LEAF_NODE_SIZE>
    TestRandomGraphFixture_LeafFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 10, TEST_LEAF_NODE_SIZE * 2>
    TestRandomGraphFixture_TwoLeaves;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
                           TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR>
    TestRandomGraphFixture_Branch;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
                           TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 2>
    TestRandomGraphFixture_MultipleLevels;
typedef RandomGraphFixture<10, 30> TestRandomGraphFixture_10_30;

template <typename RTreeT>
void simple_verify_rtree(RTreeT &rtree,
                         const std::vector<Coordinate> &coords,
                         const std::vector<TestData> &edges)
{
    for (const auto &e : edges)
    {
        const Coordinate &pu = coords[e.u];
        const Coordinate &pv = coords[e.v];
        auto result_u = rtree.Nearest(pu, 1);
        auto result_v = rtree.Nearest(pv, 1);
        BOOST_CHECK(result_u.size() == 1 && result_v.size() == 1);
        BOOST_CHECK(result_u.front().u == e.u || result_u.front().v == e.u);
        BOOST_CHECK(result_v.front().u == e.v || result_v.front().v == e.v);
    }
}

template <typename RTreeT>
void sampling_verify_rtree(RTreeT &rtree,
                           LinearSearchNN<TestData> &lsnn,
                           const std::vector<Coordinate> &coords,
                           unsigned num_samples)
{
    std::mt19937 g(RANDOM_SEED);
    std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
    std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
    std::vector<Coordinate> queries;
    for (unsigned i = 0; i < num_samples; i++)
    {
        queries.emplace_back(FixedLongitude{lon_udist(g)}, FixedLatitude{lat_udist(g)});
    }

    for (const auto &q : queries)
    {
        auto result_rtree = rtree.Nearest(q, 1);
        auto result_lsnn = lsnn.Nearest(q, 1);
        BOOST_CHECK(result_rtree.size() == 1);
        BOOST_CHECK(result_lsnn.size() == 1);
        auto rtree_u = result_rtree.back().u;
        auto rtree_v = result_rtree.back().v;
        auto lsnn_u = result_lsnn.back().u;
        auto lsnn_v = result_lsnn.back().v;

        const double rtree_dist =
            coordinate_calculation::perpendicularDistance(coords[rtree_u], coords[rtree_v], q);
        const double lsnn_dist =
            coordinate_calculation::perpendicularDistance(coords[lsnn_u], coords[lsnn_v], q);

        BOOST_CHECK_CLOSE(rtree_dist, lsnn_dist, 0.0001);
    }
}

template <typename RTreeT, typename FixtureT>
auto make_rtree(const std::filesystem::path &path, FixtureT &fixture)
{
    return RTreeT(fixture.edges, fixture.coords, path);
}

template <typename RTreeT = TestStaticRTree, typename FixtureT>
void construction_test(const std::string &path, FixtureT &fixture)
{
    std::string leaves_path;
    std::string nodes_path;
    auto rtree = make_rtree<RTreeT>(path, fixture);
    LinearSearchNN<TestData> lsnn(fixture.coords, fixture.edges);

    simple_verify_rtree(rtree, fixture.coords, fixture.edges);
    sampling_verify_rtree(rtree, lsnn, fixture.coords, 100);
}

BOOST_FIXTURE_TEST_CASE(construct_tiny, TestRandomGraphFixture_10_30)
{
    using TinyTestTree = StaticRTree<TestData, osrm::storage::Ownership::Container, 2, 64>;
    construction_test<TinyTestTree>("test_tiny", *this);
}

BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
{
    construction_test("test_1", *this);
}

BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull)
{
    construction_test("test_2", *this);
}

BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves)
{
    construction_test("test_3", *this);
}

BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch)
{
    construction_test("test_4", *this);
}

BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels)
{
    construction_test("test_5", *this);
}

// Bug: If you querry a point that lies between two BBs that have a gap,
// one BB will be pruned, even if it could contain a nearer match.
BOOST_AUTO_TEST_CASE(regression_test)
{
    using Coord = std::pair<FloatLongitude, FloatLatitude>;
    using Edge = std::tuple<unsigned, unsigned, bool>;
    GraphFixture fixture(
        {
            Coord{FloatLongitude{0.0}, FloatLatitude{40.0}},   //
            Coord{FloatLongitude{5.0}, FloatLatitude{35.0}},   //
            Coord{FloatLongitude{5.0}, FloatLatitude{5.0}},    //
            Coord{FloatLongitude{10.0}, FloatLatitude{0.0}},   //
            Coord{FloatLongitude{10.0}, FloatLatitude{20.0}},  //
            Coord{FloatLongitude{5.0}, FloatLatitude{20.0}},   //
            Coord{FloatLongitude{100.0}, FloatLatitude{40.0}}, //
            Coord{FloatLongitude{105.0}, FloatLatitude{35.0}}, //
            Coord{FloatLongitude{105.0}, FloatLatitude{5.0}},  //
            Coord{FloatLongitude{110.0}, FloatLatitude{0.0}},  //
        },
        {Edge(0, 1, true), Edge(2, 3, true), Edge(4, 5, true), Edge(6, 7, true), Edge(8, 9, true)});

    TemporaryFile tmp;
    auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
    LinearSearchNN<TestData> lsnn(fixture.coords, fixture.edges);

    // query a node just right of the center of the gap
    Coordinate input(FloatLongitude{55.1}, FloatLatitude{20.0});
    auto result_rtree = rtree.Nearest(input, 1);
    auto result_ls = lsnn.Nearest(input, 1);

    BOOST_CHECK(result_rtree.size() == 1);
    BOOST_CHECK(result_ls.size() == 1);

    BOOST_CHECK_EQUAL(result_ls.front().u, result_rtree.front().u);
    BOOST_CHECK_EQUAL(result_ls.front().v, result_rtree.front().v);
}

// Bug: If you querry a point with a narrow radius, no result should be returned
BOOST_AUTO_TEST_CASE(radius_regression_test)
{
    using Coord = std::pair<FloatLongitude, FloatLatitude>;
    using Edge = std::tuple<unsigned, unsigned, bool>;
    GraphFixture fixture(
        {
            Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
            Coord(FloatLongitude{10.0}, FloatLatitude{10.0}),
        },
        {Edge(0, 1, true), Edge(1, 0, true)});

    TemporaryFile tmp;
    auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
    TestDataFacade mockfacade;
    engine::GeospatialQuery<MiniStaticRTree, TestDataFacade> query(
        rtree, fixture.coords, mockfacade);

    Coordinate input(FloatLongitude{5.2}, FloatLatitude{5.0});

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 0.01, osrm::engine::Approach::UNRESTRICTED, true);
        BOOST_CHECK_EQUAL(results.size(), 0);
    }
}

BOOST_AUTO_TEST_CASE(permissive_edge_snapping)
{
    using Coord = std::pair<FloatLongitude, FloatLatitude>;
    using Edge = std::tuple<unsigned, unsigned, bool>;
    GraphFixture fixture(
        {
            Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
            Coord(FloatLongitude{0.001}, FloatLatitude{0.001}),
        },
        {Edge(0, 1, true), Edge(1, 0, false)});

    TemporaryFile tmp;
    auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
    TestDataFacade mockfacade;
    engine::GeospatialQuery<MiniStaticRTree, TestDataFacade> query(
        rtree, fixture.coords, mockfacade);

    Coordinate input(FloatLongitude{0.0005}, FloatLatitude{0.0005});

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 1000, osrm::engine::Approach::UNRESTRICTED, false);
        BOOST_CHECK_EQUAL(results.size(), 1);
    }

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 1000, osrm::engine::Approach::UNRESTRICTED, true);
        BOOST_CHECK_EQUAL(results.size(), 2);
    }
}

BOOST_AUTO_TEST_CASE(bearing_tests)
{
    using Coord = std::pair<FloatLongitude, FloatLatitude>;
    using Edge = std::tuple<unsigned, unsigned, bool>;
    GraphFixture fixture(
        {
            Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
            Coord(FloatLongitude{10.0}, FloatLatitude{10.0}),
        },
        {Edge(0, 1, true), Edge(1, 0, true)});

    TemporaryFile tmp;
    auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
    TestDataFacade mockfacade;
    engine::GeospatialQuery<MiniStaticRTree, TestDataFacade> query(
        rtree, fixture.coords, mockfacade);

    Coordinate input(FloatLongitude{5.1}, FloatLatitude{5.0});

    {
        auto results = query.NearestPhantomNodes(input, 5, osrm::engine::Approach::UNRESTRICTED);
        BOOST_CHECK_EQUAL(results.size(), 2);
        BOOST_CHECK_EQUAL(results.back().phantom_node.forward_segment_id.id, 0);
        BOOST_CHECK_EQUAL(results.back().phantom_node.reverse_segment_id.id, 1);
    }

    {
        auto results =
            query.NearestPhantomNodes(input, 5, 270, 10, osrm::engine::Approach::UNRESTRICTED);
        BOOST_CHECK_EQUAL(results.size(), 0);
    }

    {
        auto results =
            query.NearestPhantomNodes(input, 5, 45, 10, osrm::engine::Approach::UNRESTRICTED);
        BOOST_CHECK_EQUAL(results.size(), 2);

        BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled);
        BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled);
        BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1);

        BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled);
        BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled);
        BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1);
    }

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 11000, osrm::engine::Approach::UNRESTRICTED, true);
        BOOST_CHECK_EQUAL(results.size(), 2);
    }

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 11000, 270, 10, osrm::engine::Approach::UNRESTRICTED, true);
        BOOST_CHECK_EQUAL(results.size(), 0);
    }

    {
        auto results = query.NearestPhantomNodesInRange(
            input, 11000, 45, 10, osrm::engine::Approach::UNRESTRICTED, true);
        BOOST_CHECK_EQUAL(results.size(), 2);

        BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled);
        BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled);
        BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1);

        BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled);
        BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled);
        BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1);
    }
}

BOOST_AUTO_TEST_CASE(bbox_search_tests)
{
    using Coord = std::pair<FloatLongitude, FloatLatitude>;
    using Edge = std::tuple<unsigned, unsigned, bool>;

    GraphFixture fixture(
        {
            Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
            Coord(FloatLongitude{1.0}, FloatLatitude{1.0}),
            Coord(FloatLongitude{2.0}, FloatLatitude{2.0}),
            Coord(FloatLongitude{3.0}, FloatLatitude{3.0}),
            Coord(FloatLongitude{4.0}, FloatLatitude{4.0}),
        },
        {Edge(0, 1, true), Edge(1, 2, true), Edge(2, 3, true), Edge(3, 4, true)});

    TemporaryFile tmp;
    auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
    TestDataFacade mockfacade;
    engine::GeospatialQuery<MiniStaticRTree, TestDataFacade> query(
        rtree, fixture.coords, mockfacade);

    {
        RectangleInt2D bbox = {
            FloatLongitude{0.5}, FloatLongitude{1.5}, FloatLatitude{0.5}, FloatLatitude{1.5}};
        auto results = query.Search(bbox);
        BOOST_CHECK_EQUAL(results.size(), 2);
    }

    {
        RectangleInt2D bbox = {
            FloatLongitude{1.5}, FloatLongitude{3.5}, FloatLatitude{1.5}, FloatLatitude{3.5}};
        auto results = query.Search(bbox);
        BOOST_CHECK_EQUAL(results.size(), 3);
    }
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: ambasta/osrm-backend

max_issues_repo_name: ambasta/osrm-backend

max_forks_repo_name: ambasta/osrm-backend