text:
/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

/*
 * Agent parameters are derived from 3 entities in increasing priority,
 * - System information
 * - Configuration file
 * - Parameters
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <unistd.h>
#include <iostream>

#include <boost/property_tree/ini_parser.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>

#include <base/logging.h>
#include <base/misc_utils.h>
#include <sandesh/sandesh_types.h>
#include <sandesh/sandesh.h>
#include <sandesh/sandesh_trace.h>

#include <cmn/agent_cmn.h>
#include <cmn/agent_param.h>
#include <vgw/cfg_vgw.h>
#include <uve/agent_stats_collector.h>
#include <uve/flow_stats_collector.h>

using namespace std;
using namespace boost::property_tree;
using boost::optional;
namespace opt = boost::program_options;

template <typename ValueType>
bool AgentParam::GetOptValue
    (const boost::program_options::variables_map &var_map, ValueType &var,
     const std::string &val) {
    // Check if the value is present.
    if (var_map.count(val) && !var_map[val].defaulted()) {
        var = var_map[val].as<ValueType>();
        return true;
    }
    return false;
}

template <typename ValueType>
bool AgentParam::GetValueFromTree(ValueType &var, const std::string &val) {

    optional<ValueType> opt;

    if (opt = tree_.get_optional<ValueType>(val)) {
        var = opt.get();
        return true;
    }
    return false;
}

bool AgentParam::GetIpAddress(const string &str, Ip4Address *addr) {
    boost::system::error_code ec;
    Ip4Address tmp = Ip4Address::from_string(str, ec);
    if (ec.value() != 0) {
        return false;
    }
    *addr = tmp;
    return true;
}

bool AgentParam::ParseIp(const string &key, Ip4Address *server) {
    optional<string> opt_str;
    if (opt_str = tree_.get_optional<string>(key)) {
        Ip4Address addr;
        if (GetIpAddress(opt_str.get(), &addr) == false) {
            LOG(ERROR, "Error in config file <" << config_file_
                    << ">. Error parsing IP address from <"
                    << opt_str.get() << ">");
            return false;

        } else {
            *server = addr;
        }
    }
    return true;
}

bool AgentParam::ParseServerList(const string &key, Ip4Address *server1,
                                 Ip4Address *server2) {
    optional<string> opt_str;
    Ip4Address addr;
    vector<string> tokens;
    if (opt_str = tree_.get_optional<string>(key)) {
        boost::split(tokens, opt_str.get(), boost::is_any_of(" "));
        if (tokens.size() > 2) {
            LOG(ERROR, "Error in config file <" << config_file_
                    << ">. Cannot have more than 2 servers <"
                    << opt_str.get() << ">");
            return false;
        }
        vector<string>::iterator it = tokens.begin();
        if (it != tokens.end()) {
            if (!GetIpAddress(*it, server1)) {
                return false;
            }
            ++it;
            if (it != tokens.end()) {
                if (!GetIpAddress(*it, server2)) {
                    return false;
                }
            }
        }
    }
    return true;
}

void AgentParam::ParseIpArgument
    (const boost::program_options::variables_map &var_map, Ip4Address &server,
     const string &key) {

    if (var_map.count(key)) {
        Ip4Address addr;
        if (GetIpAddress(var_map[key].as<string>(), &addr)) {
            server = addr;
        }
    }
}

bool AgentParam::ParseServerListArguments
    (const boost::program_options::variables_map &var_map, Ip4Address &server1,
     Ip4Address &server2, const string &key) {

    if (var_map.count(key)) {
        vector<string> value = var_map[key].as<vector<string> >();
        if (value.size() > 2) {
            LOG(ERROR, "Error in Arguments. Cannot have more than 2 servers "
                    "for " << key );
            return false;
        }
        vector<string>::iterator it = value.begin();
        Ip4Address addr;
        if (it !=  value.end()) {
            if (GetIpAddress(*it, &addr)) {
                server1 = addr;
            }
            ++it;
            if (it != value.end()) {
                if (GetIpAddress(*it, &addr)) {
                    server2 = addr;
                }
            }
        }
    }
    return true;
}

void AgentParam::ParseCollector() {
    ParseIp("COLLECTOR.server", &collector_);
    GetValueFromTree<uint16_t>(collector_port_, "COLLECTOR.port");
}

void AgentParam::ParseVirtualHost() {
    boost::system::error_code ec;
    optional<string> opt_str;

    GetValueFromTree<string>(vhost_.name_, "VIRTUAL-HOST-INTERFACE.name");

    if (opt_str = tree_.get_optional<string>("VIRTUAL-HOST-INTERFACE.ip")) {
        ec = Ip4PrefixParse(opt_str.get(), &vhost_.addr_, &vhost_.plen_);
        if (ec != 0 || vhost_.plen_ >= 32) {
            cout << "Error in config file <" << config_file_
                    << ">. Error parsing vhost ip-address from <"
                    << opt_str.get() << ">\n";
        }
    }

    if (opt_str = tree_.get_optional<string>("VIRTUAL-HOST-INTERFACE.gateway")) {
        if (GetIpAddress(opt_str.get(), &vhost_.gw_) == false) {
            cout << "Error in config file <" << config_file_
                    << ">. Error parsing vhost gateway address from <"
                    << opt_str.get() << ">\n";
        }
    }

    GetValueFromTree<string>(eth_port_,
                             "VIRTUAL-HOST-INTERFACE.physical_interface");
}

void AgentParam::ParseDiscovery() {
    ParseIp("DISCOVERY.server", &dss_server_);
    GetValueFromTree<uint16_t>(xmpp_instance_count_,
                               "DISCOVERY.max_control_nodes");
}

void AgentParam::ParseNetworks() {
    ParseIp("NETWORKS.control_network_ip", &mgmt_ip_);
}

void AgentParam::ParseHypervisor() {
    optional<string> opt_str;
    if (opt_str = tree_.get_optional<string>("HYPERVISOR.type")) {
        // Initialize mode to KVM. Will be overwritten for XEN later
        mode_ = AgentParam::MODE_KVM;

        if (opt_str.get() == "xen") {
            mode_ = AgentParam::MODE_XEN;
            GetValueFromTree<string>(xen_ll_.name_,
                                     "HYPERVISOR.xen_ll_interface");

            boost::system::error_code ec;
            if (opt_str = tree_.get_optional<string>
                    ("HYPERVISOR.xen_ll_ip")) {
                ec = Ip4PrefixParse(opt_str.get(), &xen_ll_.addr_,
                                    &xen_ll_.plen_);
                if (ec != 0 || xen_ll_.plen_ >= 32) {
                    cout << "Error in config file <" << config_file_
                            << ">. Error parsing Xen Link-local ip-address from <"
                            << opt_str.get() << ">\n";
                    return;
                }
            }
        } else if (opt_str.get() == "vmware") {
            mode_ = AgentParam::MODE_VMWARE;
            GetValueFromTree<string>(vmware_physical_port_,
                                     "HYPERVISOR.vmware_physical_interface");
        } else {
            mode_ = AgentParam::MODE_KVM;
        }
    }
}

void AgentParam::ParseDefaultSection() {
    optional<string> opt_str;
    optional<unsigned int> opt_uint;

    if (!GetValueFromTree<uint16_t>(http_server_port_,
                                    "DEFAULT.http_server_port")) {
        http_server_port_ = ContrailPorts::HttpPortAgent;
    }

    GetValueFromTree<string>(tunnel_type_, "DEFAULT.tunnel_type");
    if ((tunnel_type_ != "MPLSoUDP") && (tunnel_type_ != "VXLAN"))
        tunnel_type_ = "MPLSoGRE";

    if (!GetValueFromTree<uint16_t>(flow_cache_timeout_,
                                    "DEFAULT.flow_cache_timeout")) {
        flow_cache_timeout_ = Agent::kDefaultFlowCacheTimeout;
    }

    GetValueFromTree<string>(host_name_, "DEFAULT.hostname");

    if (!GetValueFromTree<string>(log_level_, "DEFAULT.log_level")) {
        log_level_ = "SYS_DEBUG";
    }
    if (!GetValueFromTree<string>(log_file_, "DEFAULT.log_file")) {
        log_file_ = Agent::DefaultLogFile();
    }
    GetValueFromTree<string>(log_category_, "DEFAULT.log_category");
    unsigned int log_local = 0, debug_logging = 0;
    if (opt_uint = tree_.get_optional<unsigned int>("DEFAULT.log_local")) {
        log_local = opt_uint.get();
    }
    if (log_local) {
        log_local_ = true;
    } else {
        log_local_ = false;
    }
    if (opt_uint = tree_.get_optional<unsigned int>("DEFAULT.log_local")) {
        debug_logging = opt_uint.get();
    }
    if (debug_logging) {
        debug_ = true;
    } else {
        debug_ = false;
    }
}

void AgentParam::ParseMetadataProxy() {
    GetValueFromTree<string>(metadata_shared_secret_,
                             "METADATA.metadata_proxy_secret");
}

void AgentParam::ParseFlows() {
    if (!GetValueFromTree<float>(max_vm_flows_, "FLOWS.max_vm_flows")) {
        max_vm_flows_ = (float) 100;
    }
    if (!GetValueFromTree<uint16_t>(linklocal_system_flows_,
        "FLOWS.max_system_linklocal_flows")) {
        linklocal_system_flows_ = Agent::kDefaultMaxLinkLocalOpenFds;
    }
    if (!GetValueFromTree<uint16_t>(linklocal_vm_flows_,
        "FLOWS.max_vm_linklocal_flows")) {
        linklocal_vm_flows_ = Agent::kDefaultMaxLinkLocalOpenFds;
    }
}

void AgentParam::ParseHeadlessMode() {
    if (!GetValueFromTree<bool>(headless_mode_, "DEFAULT.headless")) {
        headless_mode_ = false;
    }
}

void AgentParam::ParseCollectorArguments
    (const boost::program_options::variables_map &var_map) {
    ParseIpArgument(var_map, collector_, "COLLECTOR.server");
    GetOptValue<uint16_t>(var_map, collector_port_, "COLLECTOR.port");
}

void AgentParam::ParseVirtualHostArguments
    (const boost::program_options::variables_map &var_map) {
    boost::system::error_code ec;

    GetOptValue<string>(var_map, vhost_.name_, "VIRTUAL-HOST-INTERFACE.name");
    string ip;
    if (GetOptValue<string>(var_map, ip, "VIRTUAL-HOST-INTERFACE.ip")) {
        ec = Ip4PrefixParse(ip, &vhost_.addr_, &vhost_.plen_);
        if (ec != 0 || vhost_.plen_ >= 32) {
            cout << "Error parsing vhost ip argument from <" << ip << ">\n";
        }
    }
    ParseIpArgument(var_map, vhost_.gw_, "VIRTUAL-HOST-INTERFACE.gateway");
    GetOptValue<string>(var_map, eth_port_,
                        "VIRTUAL-HOST-INTERFACE.physical_interface");
}

void AgentParam::ParseDiscoveryArguments
    (const boost::program_options::variables_map &var_map) {
    ParseIpArgument(var_map, dss_server_, "DISCOVERY.server");
    GetOptValue<uint16_t>(var_map, xmpp_instance_count_,
                          "DISCOVERY.max_control_nodes");
}

void AgentParam::ParseNetworksArguments
    (const boost::program_options::variables_map &var_map) {
    ParseIpArgument(var_map, mgmt_ip_, "NETWORKS.control_network_ip");
}

void AgentParam::ParseHypervisorArguments
    (const boost::program_options::variables_map &var_map) {
    boost::system::error_code ec;
    if (var_map.count("HYPERVISOR.type") &&
        !var_map["HYPERVISOR.type"].defaulted()) {
        if (var_map["HYPERVISOR.type"].as<string>() == "xen") {
            mode_ = AgentParam::MODE_XEN;
            GetOptValue<string>(var_map, xen_ll_.name_,
                                "HYPERVISOR.xen_ll_interface");

            if (var_map.count("HYPERVISOR.xen_ll_ip")) {
                string ip = var_map["HYPERVISOR.xen_ll_ip"].as<string>();
                ec = Ip4PrefixParse(ip, &xen_ll_.addr_, &xen_ll_.plen_);
                if (ec != 0 || xen_ll_.plen_ >= 32) {
                    cout << "Error in argument <" << config_file_
                            << ">. Error parsing Xen Link-local ip-address from <"
                            << ip << ">\n";
                    exit(EINVAL);
                }
            }
        } else if (var_map["HYPERVISOR.type"].as<string>() == "vmware") {
            mode_ = AgentParam::MODE_VMWARE;
            GetOptValue<string>(var_map, vmware_physical_port_,
                                "HYPERVISOR.vmware_physical_interface");
        } else {
            mode_ = AgentParam::MODE_KVM;
        }
    }
}

void AgentParam::ParseDefaultSectionArguments
    (const boost::program_options::variables_map &var_map) {
    GetOptValue<uint16_t>(var_map, flow_cache_timeout_,
                          "DEFAULT.flow_cache_timeout");
    GetOptValue<string>(var_map, host_name_, "DEFAULT.hostname");
    GetOptValue<uint16_t>(var_map, http_server_port_,
                          "DEFAULT.http_server_port");
    GetOptValue<string>(var_map, log_category_, "DEFAULT.log-category");
    GetOptValue<string>(var_map, log_file_, "DEFAULT.log_file");
    GetOptValue<string>(var_map, log_level_, "DEFAULT.log_level");
    if (var_map.count("DEFAULT.log_local")) {
         log_local_ = true;
    }
    if (var_map.count("DEFAULT.debug")) {
        debug_ = true;
    }
}

void AgentParam::ParseMetadataProxyArguments
    (const boost::program_options::variables_map &var_map) {
    GetOptValue<string>(var_map, metadata_shared_secret_,
                        "METADATA.metadata_proxy_secret");
}

void AgentParam::ParseFlowArguments
    (const boost::program_options::variables_map &var_map) {
    GetOptValue<float>(var_map, max_vm_flows_, "FLOWS.max_vm_flows");
    GetOptValue<uint16_t>(var_map, linklocal_system_flows_,
                          "FLOWS.max_system_linklocal_flows");
    GetOptValue<uint16_t>(var_map, linklocal_vm_flows_,
                          "FLOWS.max_vm_linklocal_flows");
}

void AgentParam::ParseHeadlessModeArguments
    (const boost::program_options::variables_map &var_map) {
    GetOptValue<bool>(var_map, headless_mode_, "DEFAULT.headless_mode");
}
// Initialize hypervisor mode based on system information
// If "/proc/xen" exists it means we are running in Xen dom0
void AgentParam::InitFromSystem() {
    boost::system::error_code error;
    host_name_ = boost::asio::ip::host_name(error);

    struct stat fstat;
    if (stat("/proc/xen", &fstat) == 0) {
        mode_ = MODE_XEN;
        cout << "Found file /proc/xen. Initializing mode to XEN\n";
    }
    xen_ll_.addr_ = Ip4Address::from_string("169.254.0.1");
    xen_ll_.plen_ = 16;

    return;
}

// Update agent parameters from config file
void AgentParam::InitFromConfig() {
    // Read and parse INI
    try {
        read_ini(config_file_, tree_);
    } catch (exception &e) {
        cout <<  "Error reading config file <" << config_file_
            << ">. INI format error??? <" << e.what() << ">\n";
        return;
    }

    ParseCollector();
    ParseVirtualHost();
    ParseServerList("CONTROL-NODE.server", &xmpp_server_1_, &xmpp_server_2_);
    ParseServerList("DNS.server", &dns_server_1_, &dns_server_2_);
    ParseDiscovery();
    ParseNetworks();
    ParseHypervisor();
    ParseDefaultSection();
    ParseMetadataProxy();
    ParseFlows();
    ParseHeadlessMode();
    cout << "Config file <" << config_file_ << "> parsing completed.\n";
    return;
}

void AgentParam::InitFromArguments
    (const boost::program_options::variables_map &var_map) {
    ParseCollectorArguments(var_map);
    ParseVirtualHostArguments(var_map);
    ParseServerListArguments(var_map, xmpp_server_1_, xmpp_server_2_,
                             "CONTROL-NODE.server");
    ParseServerListArguments(var_map, dns_server_1_, dns_server_2_,
                             "DNS.server");
    ParseDiscoveryArguments(var_map);
    ParseNetworksArguments(var_map);
    ParseHypervisorArguments(var_map);
    ParseDefaultSectionArguments(var_map);
    ParseMetadataProxyArguments(var_map);
    ParseHeadlessModeArguments(var_map);
    return;
}

// Update max_vm_flows_ if it is greater than 100.
// Update linklocal max flows if they are greater than the max allowed for the
// process. Also, ensure that the process is allowed to open upto
// linklocal_system_flows + kMaxOtherOpenFds files
void AgentParam::ComputeFlowLimits() {
    if (max_vm_flows_ > 100) {
        LOG(DEBUG, "Updating flows configuration max-vm-flows to : 100%");
        max_vm_flows_ = 100;
    }
    if (max_vm_flows_ < 0) {
        LOG(DEBUG, "Updating flows configuration max-vm-flows to : 0%");
        max_vm_flows_ = 0;
    }

    struct rlimit rl;
    int result = getrlimit(RLIMIT_NOFILE, &rl);
    if (result == 0) {
        if (rl.rlim_max <= Agent::kMaxOtherOpenFds + 1) {
            cout << "Updating linklocal flows configuration to 0\n";
            linklocal_system_flows_ = linklocal_vm_flows_ = 0;
            return;
        }
        if (linklocal_system_flows_ > rl.rlim_max - Agent::kMaxOtherOpenFds - 1) {
            linklocal_system_flows_ = rl.rlim_max - Agent::kMaxOtherOpenFds - 1;
            cout << "Updating linklocal-system-flows configuration to : " <<
                linklocal_system_flows_ << "\n";
        }
        if (rl.rlim_cur < linklocal_system_flows_ + Agent::kMaxOtherOpenFds + 1) {
            struct rlimit new_rl;
            new_rl.rlim_max = rl.rlim_max;
            new_rl.rlim_cur = linklocal_system_flows_ + Agent::kMaxOtherOpenFds + 1;
            result = setrlimit(RLIMIT_NOFILE, &new_rl);
            if (result != 0) {
                if (rl.rlim_cur <= Agent::kMaxOtherOpenFds + 1) {
                    linklocal_system_flows_ = 0;
                } else {
                    linklocal_system_flows_ = rl.rlim_cur - Agent::kMaxOtherOpenFds - 1;
                }
                cout << "Unable to set Max open files limit to : " <<
                    new_rl.rlim_cur <<
                    " Updating linklocal-system-flows configuration to : " <<
                    linklocal_system_flows_ << "\n";
            }
        }
        if (linklocal_vm_flows_ > linklocal_system_flows_) {
            linklocal_vm_flows_ = linklocal_system_flows_;
            cout << "Updating linklocal-vm-flows configuration to : " <<
                linklocal_vm_flows_ << "\n";
        }
    } else {
        cout << "Unable to validate linklocal flow configuration\n";
    }
}

static bool ValidateInterface(bool test_mode, const std::string &ifname) {
    if (test_mode) {
        return true;
    }
    int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
    assert(fd >= 0);

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
    int err = ioctl(fd, SIOCGIFHWADDR, (void *)&ifr);
    close (fd);

    if (err < 0) {
        LOG(ERROR, "Error reading interface <" << ifname << ">. Error number "
            << errno << " : " << strerror(errno));
        return false;
    }

    return true;
}

void AgentParam::Validate() {
    // Validate vhost interface name
    if (vhost_.name_ == "") {
        LOG(ERROR, "Configuration error. vhost interface name not specified");
        exit(EINVAL);
    }

    // Check if interface is already present
    if (ValidateInterface(test_mode_, vhost_.name_) == false) {
        exit(ENODEV);
    }

    // Validate ethernet port
    if (eth_port_ == "") {
        LOG(ERROR, "Configuration error. eth_port not specified");
        exit(EINVAL);
    }

    // Check if interface is already present
    if (ValidateInterface(test_mode_, eth_port_) == false) {
        exit(ENODEV);
    }

    // Validate physical port used in vmware
    if (mode_ == MODE_VMWARE) {
        if (vmware_physical_port_ == "") {
            LOG(ERROR, "Configuration error. Physical port connecting to "
                "virtual-machines not specified");
            exit(EINVAL);
        }

        if (ValidateInterface(test_mode_, vmware_physical_port_) == false) {
            exit(ENODEV);
        }
    }

}

void AgentParam::InitVhostAndXenLLPrefix() {
    // Set the prefix address for VHOST and XENLL interfaces
    uint32_t mask = vhost_.plen_ ? (0xFFFFFFFF << (32 - vhost_.plen_)) : 0;
    vhost_.prefix_ = Ip4Address(vhost_.addr_.to_ulong() & mask);

    mask = xen_ll_.plen_ ? (0xFFFFFFFF << (32 - xen_ll_.plen_)) : 0;
    xen_ll_.prefix_ = Ip4Address(xen_ll_.addr_.to_ulong() & mask);
}

void AgentParam::Init(const string &config_file, const string &program_name,
                      const boost::program_options::variables_map &var_map) {
    config_file_ = config_file;
    program_name_ = program_name;

    InitFromSystem();
    InitFromConfig();
    InitFromArguments(var_map);
    InitVhostAndXenLLPrefix();

    vgw_config_table_->Init(tree_);
    ComputeFlowLimits();
}

void AgentParam::LogConfig() const {
    LOG(DEBUG, "vhost interface name        : " << vhost_.name_);
    LOG(DEBUG, "vhost IP Address            : " << vhost_.addr_.to_string()
        << "/" << vhost_.plen_);
    LOG(DEBUG, "vhost gateway               : " << vhost_.gw_.to_string());
    LOG(DEBUG, "Ethernet port               : " << eth_port_);
    LOG(DEBUG, "XMPP Server-1               : " << xmpp_server_1_);
    LOG(DEBUG, "XMPP Server-2               : " << xmpp_server_2_);
    LOG(DEBUG, "DNS Server-1                : " << dns_server_1_);
    LOG(DEBUG, "DNS Server-2                : " << dns_server_2_);
    LOG(DEBUG, "Discovery Server            : " << dss_server_);
    LOG(DEBUG, "Controller Instances        : " << xmpp_instance_count_);
    LOG(DEBUG, "Tunnel-Type                 : " << tunnel_type_);
    LOG(DEBUG, "Metadata-Proxy Shared Secret: " << metadata_shared_secret_);
    LOG(DEBUG, "Max Vm Flows                : " << max_vm_flows_);
    LOG(DEBUG, "Linklocal Max System Flows  : " << linklocal_system_flows_);
    LOG(DEBUG, "Linklocal Max Vm Flows      : " << linklocal_vm_flows_);
    LOG(DEBUG, "Flow cache timeout          : " << flow_cache_timeout_);
    LOG(DEBUG, "Headless Mode               : " << headless_mode_);
    if (mode_ == MODE_KVM) {
    LOG(DEBUG, "Hypervisor mode             : kvm");
        return;
    }

    if (mode_ == MODE_XEN) {
    LOG(DEBUG, "Hypervisor mode             : xen");
    LOG(DEBUG, "XEN Link Local port         : " << xen_ll_.name_);
    LOG(DEBUG, "XEN Link Local IP Address   : " << xen_ll_.addr_.to_string()
        << "/" << xen_ll_.plen_);
    }

    if (mode_ == MODE_VMWARE) {
    LOG(DEBUG, "Hypervisor mode             : vmware");
    LOG(DEBUG, "Vmware port                 : " << vmware_physical_port_);
    }
}

void AgentParam::set_test_mode(bool mode) {
    test_mode_ = mode;
}

AgentParam::AgentParam(Agent *agent) :
        vhost_(), eth_port_(), xmpp_instance_count_(), xmpp_server_1_(),
        xmpp_server_2_(), dns_server_1_(), dns_server_2_(), dss_server_(),
        mgmt_ip_(), mode_(MODE_KVM), xen_ll_(), tunnel_type_(),
        metadata_shared_secret_(), max_vm_flows_(),
        linklocal_system_flows_(), linklocal_vm_flows_(),
        flow_cache_timeout_(), config_file_(), program_name_(),
        log_file_(), log_local_(false), log_level_(), log_category_(),
        collector_(), collector_port_(), http_server_port_(), host_name_(),
        agent_stats_interval_(AgentStatsCollector::AgentStatsInterval),
        flow_stats_interval_(FlowStatsCollector::FlowStatsInterval),
        vmware_physical_port_(""), test_mode_(false), debug_(false), tree_(),
        headless_mode_(false) {
    vgw_config_table_ = std::auto_ptr<VirtualGatewayConfigTable>
        (new VirtualGatewayConfigTable(agent));
}

AgentParam::~AgentParam() {
}

ext: cc

max_stars_repo_name: safchain/contrail-controller

max_issues_repo_name: safchain/contrail-controller

max_forks_repo_name: safchain/contrail-controller


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

#include "bempp/common/config_ahmed.hpp"

#ifdef WITH_AHMED

#include "weak_form_aca_assembly_helper.hpp"

#include "assembly_options.hpp"
#include "discrete_boundary_operator.hpp"
#include "local_dof_lists_cache.hpp"

#include "../common/boost_make_shared_fwd.hpp"
#include "../common/multidimensional_arrays.hpp"
#include "../fiber/types.hpp"
#include "../fiber/explicit_instantiation.hpp"
#include "../fiber/local_assembler_for_operators.hpp"
#include "../grid/grid_view.hpp"
#include "../space/space.hpp"

#include "ahmed_aux.hpp"
#include "ahmed_complex.hpp"

#include <map>
#include <set>
#include <utility>
#include <cstdio>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>

namespace Bempp
{

template <typename BasisFunctionType, typename ResultType>
WeakFormAcaAssemblyHelper<BasisFunctionType, ResultType>::WeakFormAcaAssemblyHelper(
        const Space<BasisFunctionType>& testSpace,
        const Space<BasisFunctionType>& trialSpace,
        const std::vector<unsigned int>& p2oTestDofs,
        const std::vector<unsigned int>& p2oTrialDofs,
        const std::vector<LocalAssembler*>& assemblers,
        const std::vector<const DiscreteLinOp*>& sparseTermsToAdd,
        const std::vector<ResultType>& denseTermsMultipliers,
        const std::vector<ResultType>& sparseTermsMultipliers,
        const AssemblyOptions& options) :
    m_testSpace(testSpace), m_trialSpace(trialSpace),
    m_p2oTestDofs(p2oTestDofs), m_p2oTrialDofs(p2oTrialDofs),
    m_assemblers(assemblers), m_sparseTermsToAdd(sparseTermsToAdd),
    m_denseTermsMultipliers(denseTermsMultipliers),
    m_sparseTermsMultipliers(sparseTermsMultipliers),
    m_options(options),
    m_indexWithGlobalDofs(m_options.acaOptions().globalAssemblyBeforeCompression),
    m_testDofListsCache(new LocalDofListsCache<BasisFunctionType>(
                            m_testSpace, m_p2oTestDofs, m_indexWithGlobalDofs)),
    m_trialDofListsCache(new LocalDofListsCache<BasisFunctionType>(
                            m_trialSpace, m_p2oTrialDofs, m_indexWithGlobalDofs))
    //,
//    m_trialDofListsCache(&testSpace == &trialSpace &&
//                         std::equal(p2oTestDofs.begin(), p2oTestDofs.end(),
//                                    p2oTrialDofs.begin()) ?
//                             m_testDofListsCache :
//                             boost::make_shared<LocalDofListsCache<BasisFunctionType> >(
//                                 m_trialSpace, m_p2oTrialDofs, m_indexWithGlobalDofs))
{
    if (!m_indexWithGlobalDofs && !m_sparseTermsToAdd.empty())
        throw std::invalid_argument(
                "WeakFormAcaAssemblyHelper::WeakFormAcaAssemblyHelper(): "
                "combining sparse and dense terms with "
                "globalAssemblyBeforeCompression set to false "
                "is not supported at present");
    for (size_t i = 0; i < assemblers.size(); ++i)
        if (!assemblers[i])
            throw std::invalid_argument(
                    "WeakFormAcaAssemblyHelper::WeakFormAcaAssemblyHelper(): "
                    "no elements of the 'assemblers' vector may be null");
    for (size_t i = 0; i < sparseTermsToAdd.size(); ++i)
        if (!sparseTermsToAdd[i])
            throw std::invalid_argument(
                    "WeakFormAcaAssemblyHelper::WeakFormAcaAssemblyHelper(): "
                    "no elements of the 'sparseTermsToAdd' vector may be null");
}

template <typename BasisFunctionType, typename ResultType>
void WeakFormAcaAssemblyHelper<BasisFunctionType, ResultType>::cmpbl(
        unsigned b1, unsigned n1, unsigned b2, unsigned n2,
        AhmedResultType* ahmedData,
        const cluster* c1, const cluster* c2) const
{
//    std::cout << "\nRequested block: (" << b1 << ", " << n1 << "; "
//              << b2 << ", " << n2 << ")" << std::endl;

    typedef typename Fiber::ScalarTraits<BasisFunctionType>::RealType CoordinateType;
    typedef AhmedDofWrapper<CoordinateType> AhmedDofType;
    typedef ExtendedBemCluster<AhmedDofType> AhmedBemCluster;

    AhmedBemCluster* cluster1 =
        const_cast<AhmedBemCluster*>(// AHMED is not const-correct
            dynamic_cast<const AhmedBemCluster*>(c1));
    AhmedBemCluster* cluster2 =
        const_cast<AhmedBemCluster*>(// AHMED is not const-correct
            dynamic_cast<const AhmedBemCluster*>(c2));
    // Lower bound on the minimum distance between elements from the two clusters
    CoordinateType minDist = -1.; // negative, read: unknown
    if (cluster1 && cluster2) {
        // both getdiam2() and dist2() are effectively const, but not declared so
        // in AHMED
        const double diam1 = sqrt(cluster1->getdiam2());
        const double diam2 = sqrt(cluster2->getdiam2());
        const double dist = sqrt(cluster1->dist2(cluster2));
        minDist = std::max(0., dist - (diam1 + diam2) / 2.);
    }
    // else
        // std::cout << "Warning: clusters not available" << std::endl;
    // std::cout << "minDist: " << minDist << std::endl;

    // This is a non-op for real types. For complex types, it converts a pointer
    // to Ahmed's scomp (resp. dcomp) to a pointer to std::complex<float>
    // (resp. std::complex<double>), which should be perfectly safe since these
    // types have the same binary representation.
    ResultType* data = reinterpret_cast<ResultType*>(ahmedData);

    // Convert AHMED matrix indices into DOF indices
    shared_ptr<const LocalDofLists> testDofLists = m_testDofListsCache->get(b1, n1);
    shared_ptr<const LocalDofLists> trialDofLists = m_trialDofListsCache->get(b2, n2);

    // Requested original matrix indices
    const std::vector<LocalDofLists::DofIndex>& testOriginalIndices =
            testDofLists->originalIndices;
    const std::vector<LocalDofLists::DofIndex>& trialOriginalIndices =
            trialDofLists->originalIndices;
    // Necessary elements
    const std::vector<int>& testElementIndices =
            testDofLists->elementIndices;
    const std::vector<int>& trialElementIndices =
            trialDofLists->elementIndices;
    // Necessary local dof indices in each element
    const std::vector<std::vector<LocalDofIndex> >& testLocalDofs =
            testDofLists->localDofIndices;
    const std::vector<std::vector<LocalDofIndex> >& trialLocalDofs =
            trialDofLists->localDofIndices;
    // Corresponding row and column indices in the matrix to be calculated
    // and stored in ahmedData
    const std::vector<std::vector<int> >& blockRows =
            testDofLists->arrayIndices;
    const std::vector<std::vector<int> >& blockCols =
            trialDofLists->arrayIndices;

    arma::Mat<ResultType> result(data, n1, n2, false /*copy_aux_mem*/,
                                 true /*strict*/);
    result.fill(0.);

    // First, evaluate the contributions of the dense terms
    if (n2 == 1)
    {
        // Only one column of the block needed. This means that we need only
        // one local DOF from just one or a few trialElements. Evaluate the
        // local weak form for one local trial DOF at a time.

        std::vector<arma::Mat<ResultType> > localResult;
        for (size_t nTrialElem = 0;
             nTrialElem < trialElementIndices.size();
             ++nTrialElem)
        {
            const int activeTrialElementIndex = trialElementIndices[nTrialElem];

            // The body of this loop will very probably only run once (single
            // local DOF per trial element)
            for (size_t nTrialDof = 0;
                 nTrialDof < trialLocalDofs[nTrialElem].size();
                 ++nTrialDof)
            {
                LocalDofIndex activeTrialLocalDof =
                        trialLocalDofs[nTrialElem][nTrialDof];
                for (size_t nTerm = 0; nTerm < m_assemblers.size(); ++nTerm)
                {
                    m_assemblers[nTerm]->evaluateLocalWeakForms(
                                Fiber::TEST_TRIAL, testElementIndices,
                                activeTrialElementIndex, activeTrialLocalDof,
                                localResult, minDist);
                    for (size_t nTestElem = 0;
                         nTestElem < testElementIndices.size();
                         ++nTestElem)
                        for (size_t nTestDof = 0;
                             nTestDof < testLocalDofs[nTestElem].size();
                             ++nTestDof)
                            result(blockRows[nTestElem][nTestDof], 0) +=
                                    m_denseTermsMultipliers[nTerm] *
                                    localResult[nTestElem](testLocalDofs[nTestElem][nTestDof]);
                }
            }
        }
    }
    else if (n1 == 1) // very few testElements
    {
        // Only one row of the block needed. This means that we need only
        // one local DOF from just one or a few testElements. Evaluate the
        // local weak form for one local test DOF at a time.

        std::vector<arma::Mat<ResultType> > localResult;
        for (size_t nTestElem = 0;
             nTestElem < testElementIndices.size();
             ++nTestElem)
        {
            const int activeTestElementIndex = testElementIndices[nTestElem];
            // The body of this loop will very probably only run once (single
            // local DOF per test element)
            for (size_t nTestDof = 0;
                 nTestDof < testLocalDofs[nTestElem].size();
                 ++nTestDof)
            {
                LocalDofIndex activeTestLocalDof =
                        testLocalDofs[nTestElem][nTestDof];
                for (size_t nTerm = 0; nTerm < m_assemblers.size(); ++nTerm)
                {
                    m_assemblers[nTerm]->evaluateLocalWeakForms(
                                Fiber::TRIAL_TEST, trialElementIndices,
                                activeTestElementIndex, activeTestLocalDof,
                                localResult, minDist);
                    for (size_t nTrialElem = 0;
                         nTrialElem < trialElementIndices.size();
                         ++nTrialElem)
                        for (size_t nTrialDof = 0;
                             nTrialDof < trialLocalDofs[nTrialElem].size();
                             ++nTrialDof)
                            result(0, blockCols[nTrialElem][nTrialDof]) +=
                                    m_denseTermsMultipliers[nTerm] *
                                    localResult[nTrialElem](trialLocalDofs[nTrialElem][nTrialDof]);
                }
            }
        }
    }
    else // a "fat" block
    {
        // The whole block or its submatrix needed. This means that we are
        // likely to need all or almost all local DOFs from most elements.
        // Evaluate the full local weak form for each pair of test and trial
        // elements and then select the entries that we need.

        Fiber::_2dArray<arma::Mat<ResultType> > localResult;
        for (size_t nTerm = 0; nTerm < m_assemblers.size(); ++nTerm)
        {
            m_assemblers[nTerm]->evaluateLocalWeakForms(
                    testElementIndices, trialElementIndices, localResult,
                    minDist);
            for (size_t nTrialElem = 0;
                 nTrialElem < trialElementIndices.size();
                 ++nTrialElem)
                for (size_t nTrialDof = 0;
                     nTrialDof < trialLocalDofs[nTrialElem].size();
                     ++nTrialDof)
                    for (size_t nTestElem = 0;
                         nTestElem < testElementIndices.size();
                         ++nTestElem)
                        for (size_t nTestDof = 0;
                             nTestDof < testLocalDofs[nTestElem].size();
                             ++nTestDof)
                            result(blockRows[nTestElem][nTestDof],
                                   blockCols[nTrialElem][nTrialDof]) +=
                                    m_denseTermsMultipliers[nTerm] *
                                    localResult(nTestElem, nTrialElem)
                                    (testLocalDofs[nTestElem][nTestDof],
                                     trialLocalDofs[nTrialElem][nTrialDof]);
        }
    }

    // Probably can be removed
    if (m_indexWithGlobalDofs)
        // Now, add the contributions of the sparse terms
        for (size_t nTerm = 0; nTerm < m_sparseTermsToAdd.size(); ++nTerm)
            m_sparseTermsToAdd[nTerm]->addBlock(
                        // since m_indexWithGlobalDofs is set, these refer
                        // to global DOFs
                        testOriginalIndices, trialOriginalIndices,
                        m_sparseTermsMultipliers[nTerm], result);
    // else m_sparseTermsToAdd is empty (as we have verified in the constructor)
}

template <typename BasisFunctionType, typename ResultType>
void WeakFormAcaAssemblyHelper<BasisFunctionType, ResultType>::cmpblsym(
        unsigned b1, unsigned n1, AhmedResultType* ahmedData,
        const cluster* c1) const
{
    // Calculate results as usual (without taking symmetry into account)
    arma::Mat<ResultType> block(n1, n1);
    cmpbl(b1, n1, b1, n1, ahmedCast(block.memptr()), c1, c1);

    // and now store the upper part of the matrix in the memory block
    // provided by Ahmed
    for (size_t col = 0; col < n1; ++col)
        for (size_t row = 0; row <= col; ++row)
            *ahmedData++ = ahmedCast(block(row, col));
}

template <typename BasisFunctionType, typename ResultType>
typename WeakFormAcaAssemblyHelper<BasisFunctionType, ResultType>::MagnitudeType
WeakFormAcaAssemblyHelper<BasisFunctionType, ResultType>::scale(
        unsigned b1, unsigned n1, unsigned b2, unsigned n2) const
{
    return m_options.acaOptions().scaling;
}

// Explicit instantiations

FIBER_INSTANTIATE_CLASS_TEMPLATED_ON_BASIS_AND_RESULT(WeakFormAcaAssemblyHelper);

}

#endif // WITH_AHMED

ext: cpp

max_stars_repo_name: nicolas-chaulet/bempp

max_issues_repo_name: nicolas-chaulet/bempp

max_forks_repo_name: nicolas-chaulet/bempp


text:
/*
 *  TOPPERS Software
 *      Toyohashi Open Platform for Embedded Real-Time Systems
 *
 *  Copyright (C) 2007-2012 by TAKAGI Nobuhisa
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 */
/*!
 *  \file   toppers/cpp.hpp
 *  \brief  Cプリプロセッサ代替機能に関する宣言定義
 */
#ifndef TOPPERS_CPP_HPP_
#define TOPPERS_CPP_HPP_

#include "toppers/codeset.hpp"
#include "toppers/diagnostics.hpp"
#include <boost/utility.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

namespace toppers
{

  /*!
   *  \brief  コメントの除去
   *  \param[in]  first     入力元の先頭位置
   *  \param[in]  last      入力元の終端位置の次
   *  \param[out] result    結果の出力先
   *  \param[in]  codeset   文字コード
   *  \return     処理完了後の result の値
   *
   *  CスタイルのブロックコメントとC++スタイルの行コメントを取り除きます。
   *  行コメントは、行末の \\ があっても次の行には続きません。
   */
  template < class ForwardIterator, class OutputIterator >
    OutputIterator remove_comment( ForwardIterator first, ForwardIterator last, OutputIterator result, codeset_t codeset = ascii )
  {
    enum { none, line_comment, block_comment, single_quote, double_quote } state = none;
    char prev = '\0';

    for ( ; first != last; ++first, ++result )
    {
      char c = *first;
      ForwardIterator next_iter = boost::next( first );
      char next = ( next_iter != last ? *next_iter : '\0' );

      switch ( state )
      {
      case line_comment:
        if ( c == '\n' )
        {
          state = none;
          *result = c;
        }
        break;
      case block_comment:
        if ( c == '*' && next == '/' )
        {
          state = none;
          ++first;
        }
        else if ( c == '\n' )
        {
          *result = c;
        }
        break;
      case single_quote:
        if ( c == '\\'
          && !( codeset == shift_jis && is_lead< shift_jis >( prev ) )
          && next == '\'' )   // '〜\'〜 の場合
        {
          *result++ = *first++;
        }
        else if ( c == '\'' )
        {
          state = none;
        }
        *result = *first;
        break;
      case double_quote:
        if ( c == '\\'
          && !( codeset == shift_jis && is_lead< shift_jis >( prev ) )
          && next == '\"' )   // "〜\"〜 の場合
        {
          *result++ = *first++;
        }
        else if ( c == '\"' )
        {
          state = none;
        }
        *result = *first;
        break;
      default:
        switch ( c )
        {
        case '/':   // コメント開始の検出
          if ( next == '*' )
          {
            state = block_comment;
            ++first;
          }
          else if ( next == '/' )
          {
            state = line_comment;
            ++first;
          }
          else
          {
            *result = *first;
          }
          break;
        case '\'':
          state = single_quote;
          *result = c;
          break;
        case '\"':
          state = double_quote;
          *result = c;
          break;
        default:
          *result = c;
          break;
        }
      }
      prev = *first;
    }
    switch ( state )
    {
    case line_comment:
    case block_comment:
      error( "unterminated comment" );
      break;
    }
    return result;
  }

  /*!
   *  \brief  インクルードパスの探索
   *  \param[in]  first       探索対象ディレクトリ列の先頭位置
   *  \param[in]  last        探索対象ディレクトリ列の終端位置の次
   *  \param[in]  headername  探索対象のヘッダ名
   *  \return     探索に成功すればヘッダへの相対またはフルパスを返す。失敗した場合は空文字列を返す。
   */
  template < class InputIterator >
    std::string search_include_file( InputIterator first, InputIterator last, std::string const& headername )
  {
    namespace fs = boost::filesystem;
//    fs::path filename( headername, fs::native );
    fs::path filename( headername );  // filesystem3対応

    if ( fs::exists( filename ) && !fs::is_directory( filename ) )
    {
      return headername;
    }
    while ( first != last )
    {
//      fs::path pathname = fs::path( *first, fs::native )/filename;
      fs::path pathname = fs::path( *first )/filename;  // filesystem3対応
      if ( fs::exists( pathname ) && !fs::is_directory( pathname ) )
      {
//        return pathname.native_file_string();
        return pathname.string();  // filesysytem3対応
      }
      ++first;
    }
    return std::string();
  }

  std::string expand_quote( std::string const& str );
  std::string quote_string( std::string const& str );

}

#endif  // ! TOPPERS_CPP_HPP_

ext: hpp


text:
// Boost.Units - A C++ library for zero-overhead dimensional analysis and
// unit/quantity manipulation and conversion
//
// Copyright (C) 2003-2008 Matthias Christian Schabel
// Copyright (C) 2008 Steven Watanabe
//
// 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_UNITS_CODATA_ELECTRON_CONSTANTS_HPP
#define BOOST_UNITS_CODATA_ELECTRON_CONSTANTS_HPP

#include <boost/units/static_constant.hpp>

#include <boost/units/systems/detail/constants.hpp>
#include <boost/units/systems/si/amount.hpp>
#include <boost/units/systems/si/area.hpp>
#include <boost/units/systems/si/electric_charge.hpp>
#include <boost/units/systems/si/energy.hpp>
#include <boost/units/systems/si/frequency.hpp>
#include <boost/units/systems/si/length.hpp>
#include <boost/units/systems/si/mass.hpp>
#include <boost/units/systems/si/magnetic_flux_density.hpp>
#include <boost/units/systems/si/time.hpp>
#include <boost/units/systems/si/wavenumber.hpp>

#include <boost/units/systems/si/codata/typedefs.hpp>

/// \file
/// CODATA recommended values of fundamental atomic and nuclear constants
/// CODATA 2006 values as of 2007/03/30

namespace boost {

namespace units {

namespace si {

namespace constants {

namespace codata {

/// CODATA recommended values of the fundamental physical constants: NIST SP 961

/// electron mass
BOOST_UNITS_PHYSICAL_CONSTANT(m_e,quantity<mass>,9.10938215e-31*kilograms,4.5e-38*kilograms);
/// electron-muon mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_mu,quantity<dimensionless>,4.83633171e-3*dimensionless(),1.2e-10*dimensionless());
/// electron-tau mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_tau,quantity<dimensionless>,2.87564e-4*dimensionless(),4.7e-8*dimensionless());
/// electron-proton mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_p,quantity<dimensionless>,5.4461702177e-4*dimensionless(),2.4e-13*dimensionless());
/// electron-neutron mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_n,quantity<dimensionless>,5.4386734459e-4*dimensionless(),3.3e-13*dimensionless());
/// electron-deuteron mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_d,quantity<dimensionless>,2.7244371093e-4*dimensionless(),1.2e-13*dimensionless());
/// electron-alpha particle mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_e_over_m_alpha,quantity<dimensionless>,1.37093355570e-4*dimensionless(),5.8e-14*dimensionless());
/// electron charge to mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(e_over_m_e,quantity<electric_charge_over_mass>,1.758820150e11*coulombs/kilogram,4.4e3*coulombs/kilogram);
/// electron molar mass
BOOST_UNITS_PHYSICAL_CONSTANT(M_e,quantity<mass_over_amount>,5.4857990943e-7*kilograms/mole,2.3e-16*kilograms/mole);
/// Compton wavelength
BOOST_UNITS_PHYSICAL_CONSTANT(lambda_C,quantity<length>,2.4263102175e-12*meters,3.3e-21*meters);
/// classical electron radius
BOOST_UNITS_PHYSICAL_CONSTANT(r_e,quantity<length>,2.8179402894e-15*meters,5.8e-24*meters);
/// Thompson cross section
BOOST_UNITS_PHYSICAL_CONSTANT(sigma_e,quantity<area>,0.6652458558e-28*square_meters,2.7e-37*square_meters);
/// electron magnetic moment
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e,quantity<energy_over_magnetic_flux_density>,-928.476377e-26*joules/tesla,2.3e-31*joules/tesla);
/// electron-Bohr magenton moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_B,quantity<dimensionless>,-1.00115965218111*dimensionless(),7.4e-13*dimensionless());
/// electron-nuclear magneton moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_N,quantity<dimensionless>,-183.28197092*dimensionless(),8.0e-7*dimensionless());
/// electron magnetic moment anomaly
BOOST_UNITS_PHYSICAL_CONSTANT(a_e,quantity<dimensionless>,1.15965218111e-3*dimensionless(),7.4e-13*dimensionless());
/// electron g-factor
BOOST_UNITS_PHYSICAL_CONSTANT(g_e,quantity<dimensionless>,-2.0023193043622*dimensionless(),1.5e-12*dimensionless());
/// electron-muon magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_mu,quantity<dimensionless>,206.7669877*dimensionless(),5.2e-6*dimensionless());
/// electron-proton magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_p,quantity<dimensionless>,-658.2106848*dimensionless(),5.4e-6*dimensionless());
/// electron-shielded proton magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_p_prime,quantity<dimensionless>,-658.2275971*dimensionless(),7.2e-6*dimensionless());
/// electron-neutron magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_n,quantity<dimensionless>,960.92050*dimensionless(),2.3e-4*dimensionless());
/// electron-deuteron magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_d,quantity<dimensionless>,-2143.923498*dimensionless(),1.8e-5*dimensionless());
/// electron-shielded helion magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_e_over_mu_h_prime,quantity<dimensionless>,864.058257*dimensionless(),1.0e-5*dimensionless());
/// electron gyromagnetic ratio
BOOST_UNITS_PHYSICAL_CONSTANT(gamma_e,quantity<frequency_over_magnetic_flux_density>,1.760859770e11/second/tesla,4.4e3/second/tesla);

} // namespace codata

} // namespace constants

} // namespace si

} // namespace units

} // namespace boost

#endif // BOOST_UNITS_CODATA_ELECTRON_CONSTANTS_HPP

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP

#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>

#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
#  include <boost/interprocess/detail/win32_api.hpp>
#else
#  ifdef BOOST_HAS_UNISTD_H
#     include <pthread.h>
#     include <unistd.h>
#     include <sched.h>
#  else
#     error Unknown platform
#  endif
#endif

namespace boost {
namespace interprocess {
namespace detail{

#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)

typedef unsigned long OS_process_id_t;
typedef unsigned long OS_thread_id_t;

inline OS_process_id_t get_current_process_id()
{  return winapi::get_current_process_id();  }

inline OS_thread_id_t get_current_thread_id()
{  return winapi::get_current_thread_id();  }

inline OS_thread_id_t get_invalid_thread_id()
{  return OS_thread_id_t(0xffffffff);  }

inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
{  return id1 == id2;  }

inline void thread_yield()
{  winapi::sched_yield();  }

#else    //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)

typedef pthread_t OS_thread_id_t;
typedef int OS_process_id_t;

inline OS_process_id_t get_current_process_id()
{  return getpid();  }

inline pthread_t get_current_thread_id()
{  return pthread_self();  }

inline OS_thread_id_t get_invalid_thread_id()
{
   static pthread_t invalid_id;
   return invalid_id;
}

inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
{  return 0 != pthread_equal(id1, id2);  }

inline void thread_yield()
{  sched_yield();  }

#endif   //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)

}  //namespace detail{
}  //namespace interprocess {
}  //namespace boost {

#include <boost/interprocess/detail/config_end.hpp>

#endif   //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP


text:
// Copyright (c) 2016
// Author: Chrono Law
#include <memory>
#include <std.hpp>
using namespace std;

///////////////////////////////////////

#include <boost/pointee.hpp>
//using namespace boost;

void case1()
{
    assert((is_same<boost::pointee<int*>::type, int>::value));
    assert((is_same<boost::pointee<unique_ptr<int> >::type, int>::value));
    assert((is_same<typename boost::pointee<string::iterator>::type, char>::value));

    typedef shared_ptr<int> P;
    P p(new int(10));
    boost::pointee<P>::type v = *p;
    assert(v == 10);
}

///////////////////////////////////////

#include <boost/indirect_reference.hpp>

void case2()
{
    assert((is_same<boost::indirect_reference<int*>::type, int&>::value));
    assert((is_same<boost::indirect_reference<unique_ptr<int> >::type, int&>::value));
    assert((is_same<boost::indirect_reference<string::iterator>::type, char&>::value));

}

///////////////////////////////////////

#include <boost/pointer_to_other.hpp>
#include <boost/smart_ptr.hpp>

void case3()
{
    assert((is_same<int*,
        boost::pointer_to_other<void*, int>::type>::value));
    assert((is_same<string*,
        boost::pointer_to_other<void*, string>::type>::value));

    assert((is_same<boost::scoped_ptr<int>,
        boost::pointer_to_other<boost::scoped_ptr<float>, int>::type>::value));
    assert((is_same<shared_ptr<int>,
        boost::pointer_to_other<shared_ptr<string>, int>::type>::value));

    assert((!is_same<unique_ptr<int>,
        boost::pointer_to_other<unique_ptr<char>, int>::type>::value));

    assert((is_same<unique_ptr<int>,
                       boost::pointer_to_other<unique_ptr<
                       char,default_delete<int>>,int>::type>::value));

}

///////////////////////////////////////

#include <boost/optional.hpp>
#include <boost/utility/compare_pointees.hpp>

void case4()
{
    boost::scoped_ptr<int> p1(new int(10));
    boost::scoped_ptr<int> p2(new int(20));

    assert(!boost::equal_pointees(p1, p2));
    assert(boost::less_pointees(p1, p2));

    p2.reset();
    assert(!boost::less_pointees(p1, p2));

    boost::optional<string> op1, op2;

    assert(boost::equal_pointees(op1, op2));
    op2 = "hello";
    assert(boost::less_pointees(op1, op2));
}

///////////////////////////////////////

void case5()
{
    assert((is_same<pointer_traits<int*>::pointer, int*>::value));
    assert((is_same<pointer_traits<int*>::element_type, int>::value));
    assert((is_same<pointer_traits<int*>::rebind<char>,
                 boost::pointer_to_other<int*, char>::type >::value));

    typedef shared_ptr<std::string> sptr;
    assert((is_same<pointer_traits<sptr>::element_type,
                    boost::pointee<sptr>::type>::value));

    assert((is_same<pointer_traits<sptr>::difference_type, ptrdiff_t>::value));
    assert((is_same<pointer_traits<sptr>::rebind<char>,
                 boost::pointer_to_other<sptr, char>::type >::value));

    typedef unique_ptr<char> char_ptr;
    typedef unique_ptr<int> int_ptr;
    typedef std::pointer_traits<char_ptr>::rebind<int> new_ptr;
    assert((!std::is_same<int_ptr, new_ptr>::value));

}

///////////////////////////////////////

int main()
{
    std::cout << "hello pointee" << std::endl;

    case1();
    case2();
    case3();
    case4();
    case5();
}


text:
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sstream>

#include <cppunit/Test.h>
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/HelperMacros.h>
#include <boost/thread/mutex.hpp>

#include "../lib/clientimpl.h"
#include <hedwig/exceptions.h>
#include <hedwig/callback.h>
#include <stdexcept>
#include <pthread.h>

#include <log4cxx/logger.h>

#include "util.h"

static log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("hedwig."__FILE__));

class PubSubTestSuite : public CppUnit::TestFixture {
private:
  CPPUNIT_TEST_SUITE( PubSubTestSuite );
  CPPUNIT_TEST(testPubSubOrderChecking);
  CPPUNIT_TEST(testRandomDelivery);
  CPPUNIT_TEST(testPubSubContinuousOverClose);
  //  CPPUNIT_TEST(testPubSubContinuousOverServerDown);
  CPPUNIT_TEST(testMultiTopic);
  CPPUNIT_TEST(testBigMessage);
  CPPUNIT_TEST(testMultiTopicMultiSubscriber);
  CPPUNIT_TEST(testPubSubInMultiDispatchThreads);
  CPPUNIT_TEST_SUITE_END();

public:
  PubSubTestSuite() {
  }

  ~PubSubTestSuite() {
  }

  void setUp()
  {
  }

  void tearDown()
  {
  }

  class MyMessageHandlerCallback : public Hedwig::MessageHandlerCallback {
  public:
    MyMessageHandlerCallback(const std::string& topic, const std::string& subscriberId) : messagesReceived(0), topic(topic), subscriberId(subscriberId) {

    }

    virtual void consume(const std::string& topic, const std::string& subscriberId, const Hedwig::Message& msg, Hedwig::OperationCallbackPtr& callback) {
      if (topic == this->topic && subscriberId == this->subscriberId) {
	boost::lock_guard<boost::mutex> lock(mutex);

	messagesReceived++;
	lastMessage = msg.body();
	callback->operationComplete();
      }
    }

    std::string getLastMessage() {
      boost::lock_guard<boost::mutex> lock(mutex);
      std::string s = lastMessage;
      return s;
    }

    int numMessagesReceived() {
      boost::lock_guard<boost::mutex> lock(mutex);
      int i = messagesReceived;
      return i;
    }

  protected:
    boost::mutex mutex;
    int messagesReceived;
    std::string lastMessage;
    std::string topic;
    std::string subscriberId;
  };

  // order checking callback
  class MyOrderCheckingMessageHandlerCallback : public Hedwig::MessageHandlerCallback {
  public:
    MyOrderCheckingMessageHandlerCallback(const std::string& topic, const std::string& subscriberId, const int startMsgId, const int sleepTimeInConsume)
      : messagesReceived(0), topic(topic), subscriberId(subscriberId), startMsgId(startMsgId),
        isInOrder(true), sleepTimeInConsume(sleepTimeInConsume) {
    }

    virtual void consume(const std::string& topic, const std::string& subscriberId,
                         const Hedwig::Message& msg, Hedwig::OperationCallbackPtr& callback) {
      if (topic == this->topic && subscriberId == this->subscriberId) {
        boost::lock_guard<boost::mutex> lock(mutex);

        messagesReceived++;

        int newMsgId = atoi(msg.body().c_str());
        // checking msgId
        LOG4CXX_DEBUG(logger, "received message " << newMsgId);
        if (startMsgId >= 0) { // need to check ordering if start msg id is larger than 0
          if (isInOrder) {
            if (newMsgId != startMsgId + 1) {
              LOG4CXX_ERROR(logger, "received out-of-order message : expected " << (startMsgId + 1) << ", actual " << newMsgId);
              isInOrder = false;
            } else {
              startMsgId = newMsgId;
            }
          }
        } else { // we set first msg id as startMsgId when startMsgId is -1
          startMsgId = newMsgId;
        }
        callback->operationComplete();
        sleep(sleepTimeInConsume);
      }
    }

    int numMessagesReceived() {
      boost::lock_guard<boost::mutex> lock(mutex);
      int i = messagesReceived;
      return i;
    }

    bool inOrder() {
      boost::lock_guard<boost::mutex> lock(mutex);
      return isInOrder;
    }

  protected:
    boost::mutex mutex;
    int messagesReceived;
    std::string topic;
    std::string subscriberId;
    int startMsgId;
    bool isInOrder;
    int sleepTimeInConsume;
  };

  // Publisher integer until finished
  class IntegerPublisher {
  public:
    IntegerPublisher(const std::string &topic, int startMsgId, int numMsgs, int sleepTime, Hedwig::Publisher &pub, long runTime)
      : topic(topic), startMsgId(startMsgId), numMsgs(numMsgs), sleepTime(sleepTime), pub(pub), running(true), runTime(runTime) {
    }

    void operator()() {
      int i = 1;
      long beginTime = curTime();
      long elapsedTime = 0;

      while (running) {
        try {
          int msg = startMsgId + i;
          std::stringstream ss;
          ss << msg;
          pub.publish(topic, ss.str());
          sleep(sleepTime);
          if (numMsgs > 0 && i >= numMsgs) {
            running = false;
          } else {
            if (i % 100 == 0 &&
                (elapsedTime = (curTime() - beginTime)) >= runTime) {
              LOG4CXX_DEBUG(logger, "Elapsed time : " << elapsedTime);
              running = false;
            }
          }
          ++i;
        } catch (std::exception &e) {
          LOG4CXX_WARN(logger, "Exception when publishing messages : " << e.what());
        }
      }
    }

    long curTime() {
      struct timeval tv;
      long mtime;
      gettimeofday(&tv, NULL);
      mtime = tv.tv_sec * 1000 + tv.tv_usec / 1000.0 + 0.5;
      return mtime;
    }

  private:
    std::string topic;
    int startMsgId;
    int numMsgs;
    int sleepTime;
    Hedwig::Publisher& pub;
    bool running;
    long runTime;
  };

  // test startDelivery / stopDelivery randomly
  void testRandomDelivery() {
    std::string topic = "randomDeliveryTopic";
    std::string subscriber = "mysub-randomDelivery";

    int nLoops = 300;
    int sleepTimePerLoop = 1;
    int syncTimeout = 10000;

    Hedwig::Configuration* conf = new TestServerConfiguration(syncTimeout);
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    // subscribe topic
    sub.subscribe(topic, subscriber, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);

    // start thread to publish message
    IntegerPublisher intPublisher = IntegerPublisher(topic, 0, 0, 0, pub, nLoops * sleepTimePerLoop * 1000);
    boost::thread pubThread(intPublisher);

    // start random delivery
    MyOrderCheckingMessageHandlerCallback* cb =
      new MyOrderCheckingMessageHandlerCallback(topic, subscriber, 0, 0);
    Hedwig::MessageHandlerCallbackPtr handler(cb);

    for (int i = 0; i < nLoops; i++) {
      LOG4CXX_DEBUG(logger, "Randomly Delivery : " << i);
      sub.startDelivery(topic, subscriber, handler);
      // sleep random time
      sleep(sleepTimePerLoop);
      sub.stopDelivery(topic, subscriber);
      CPPUNIT_ASSERT(cb->inOrder());
    }

    pubThread.join();
  }

  // check message ordering
  void testPubSubOrderChecking() {
    std::string topic = "orderCheckingTopic";
    std::string sid = "mysub-0";

    int numMessages = 5;
    int sleepTimeInConsume = 1;
    // sync timeout
    int syncTimeout = 10000;

    // in order to guarantee message order, message queue should be locked
    // so message received in io thread would be blocked, which also block
    // sent operations (publish). because we have only one io thread now
    // so increase sync timeout to 10s, which is more than numMessages * sleepTimeInConsume
    Hedwig::Configuration* conf = new TestServerConfiguration(syncTimeout);
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);

    // we don't start delivery first, so the message will be queued
    // publish ${numMessages} messages, so the messages will be queued
    for (int i=1; i<=numMessages; i++) {
      std::stringstream ss;
      ss << i;
      pub.publish(topic, ss.str());
    }

    MyOrderCheckingMessageHandlerCallback* cb = new MyOrderCheckingMessageHandlerCallback(topic, sid, 0, sleepTimeInConsume);
    Hedwig::MessageHandlerCallbackPtr handler(cb);

    // create a thread to publish another ${numMessages} messages
    boost::thread pubThread(IntegerPublisher(topic, numMessages, numMessages, sleepTimeInConsume, pub, 0));

    // start delivery will consumed the queued messages
    // new message will recevied and the queued message should be consumed
    // hedwig should ensure the message are received in order
    sub.startDelivery(topic, sid, handler);

    // wait until message are all published
    pubThread.join();

    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() == 2 * numMessages) {
        break;
      }
    }
    CPPUNIT_ASSERT(cb->inOrder());
  }

  // check message ordering
  void testPubSubInMultiDispatchThreads() {
    std::string topic = "PubSubInMultiDispatchThreadsTopic-";
    std::string sid = "mysub-0";

    int syncTimeout = 10000;
    int numDispatchThreads = 4;
    int numMessages = 100;
    int numTopics = 20;

    Hedwig::Configuration* conf = new TestServerConfiguration(syncTimeout, numDispatchThreads);
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    std::vector<Hedwig::MessageHandlerCallbackPtr> callbacks;

    for (int i=0; i<numTopics; i++) {
      std::stringstream ss;
      ss << topic << i;
      sub.subscribe(ss.str(), sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);

      MyOrderCheckingMessageHandlerCallback* cb = new MyOrderCheckingMessageHandlerCallback(ss.str(), sid, 0, 0);
      Hedwig::MessageHandlerCallbackPtr handler(cb);
      sub.startDelivery(ss.str(), sid, handler);
      callbacks.push_back(handler);
    }

    std::vector<boost::shared_ptr<boost::thread> > threads;

    for (int i=0; i<numTopics; i++) {
      std::stringstream ss;
      ss << topic << i;
      boost::shared_ptr<boost::thread> t = boost::shared_ptr<boost::thread>(
        new boost::thread(IntegerPublisher(ss.str(), 0, numMessages, 0, pub, 0)));
      threads.push_back(t);
    }

    for (int i=0; i<numTopics; i++) {
      threads[i]->join();
    }
    threads.clear();

    for (int j=0; j<numTopics; j++) {
      MyOrderCheckingMessageHandlerCallback *cb =
        (MyOrderCheckingMessageHandlerCallback *)(callbacks[j].get());
      for (int i = 0; i < 10; i++) {
        if (cb->numMessagesReceived() == numMessages) {
          break;
        }
        sleep(3);
      }
      CPPUNIT_ASSERT(cb->inOrder());
    }
    callbacks.clear();
  }

  void testPubSubContinuousOverClose() {
    std::string topic = "pubSubTopic";
    std::string sid = "MySubscriberid-1";

    Hedwig::Configuration* conf = new TestServerConfiguration();
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    MyMessageHandlerCallback* cb = new MyMessageHandlerCallback(topic, sid);
    Hedwig::MessageHandlerCallbackPtr handler(cb);

    sub.startDelivery(topic, sid, handler);
    pub.publish(topic, "Test Message 1");
    bool pass = false;
    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() > 0) {
	if (cb->getLastMessage() == "Test Message 1") {
	  pass = true;
	  break;
	}
      }
    }
    CPPUNIT_ASSERT(pass);
    sub.closeSubscription(topic, sid);

    pub.publish(topic, "Test Message 2");

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    sub.startDelivery(topic, sid, handler);
    pass = false;
    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() > 0) {
	if (cb->getLastMessage() == "Test Message 2") {
	  pass = true;
	  break;
	}
      }
    }
    CPPUNIT_ASSERT(pass);
  }

  /*  void testPubSubContinuousOverServerDown() {
    std::string topic = "pubSubTopic";
    std::string sid = "MySubscriberid-1";

    Hedwig::Configuration* conf = new TestServerConfiguration();
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    MyMessageHandlerCallback* cb = new MyMessageHandlerCallback(topic, sid);
    Hedwig::MessageHandlerCallbackPtr handler(cb);

    sub.startDelivery(topic, sid, handler);
    pub.publish(topic, "Test Message 1");
    bool pass = false;
    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() > 0) {
	if (cb->getLastMessage() == "Test Message 1") {
	  pass = true;
	  break;
	}
      }
    }
    CPPUNIT_ASSERT(pass);
    sub.closeSubscription(topic, sid);

    pub.publish(topic, "Test Message 2");

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    sub.startDelivery(topic, sid, handler);
    pass = false;
    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() > 0) {
	if (cb->getLastMessage() == "Test Message 2") {
	  pass = true;
	  break;
	}
      }
    }
    CPPUNIT_ASSERT(pass);
    }*/

  void testMultiTopic() {
    std::string topicA = "pubSubTopicA";
    std::string topicB = "pubSubTopicB";
    std::string sid = "MySubscriberid-3";

    Hedwig::Configuration* conf = new TestServerConfiguration();
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topicA, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    sub.subscribe(topicB, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);

    MyMessageHandlerCallback* cbA = new MyMessageHandlerCallback(topicA, sid);
    Hedwig::MessageHandlerCallbackPtr handlerA(cbA);
    sub.startDelivery(topicA, sid, handlerA);

    MyMessageHandlerCallback* cbB = new MyMessageHandlerCallback(topicB, sid);
    Hedwig::MessageHandlerCallbackPtr handlerB(cbB);
    sub.startDelivery(topicB, sid, handlerB);

    pub.publish(topicA, "Test Message A");
    pub.publish(topicB, "Test Message B");
    int passA = false, passB = false;

    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cbA->numMessagesReceived() > 0) {
	if (cbA->getLastMessage() == "Test Message A") {
	  passA = true;
	}
      }
      if (cbB->numMessagesReceived() > 0) {
	if (cbB->getLastMessage() == "Test Message B") {
	  passB = true;
	}
      }
      if (passA && passB) {
	break;
      }
    }
    CPPUNIT_ASSERT(passA && passB);
  }

  void testMultiTopicMultiSubscriber() {
    std::string topicA = "pubSubTopicA";
    std::string topicB = "pubSubTopicB";
    std::string sidA = "MySubscriberid-4";
    std::string sidB = "MySubscriberid-5";

    Hedwig::Configuration* conf = new TestServerConfiguration();
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topicA, sidA, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    sub.subscribe(topicB, sidB, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);

    MyMessageHandlerCallback* cbA = new MyMessageHandlerCallback(topicA, sidA);
    Hedwig::MessageHandlerCallbackPtr handlerA(cbA);
    sub.startDelivery(topicA, sidA, handlerA);

    MyMessageHandlerCallback* cbB = new MyMessageHandlerCallback(topicB, sidB);
    Hedwig::MessageHandlerCallbackPtr handlerB(cbB);
    sub.startDelivery(topicB, sidB, handlerB);

    pub.publish(topicA, "Test Message A");
    pub.publish(topicB, "Test Message B");
    int passA = false, passB = false;

    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cbA->numMessagesReceived() > 0) {
	if (cbA->getLastMessage() == "Test Message A") {
	  passA = true;
	}
      }
      if (cbB->numMessagesReceived() > 0) {
	if (cbB->getLastMessage() == "Test Message B") {
	  passB = true;
	}
      }
      if (passA && passB) {
	break;
      }
    }
    CPPUNIT_ASSERT(passA && passB);
  }

  static const int BIG_MESSAGE_SIZE = 16436*2; // MTU to lo0 is 16436 by default on linux

  void testBigMessage() {
    std::string topic = "pubSubTopic";
    std::string sid = "MySubscriberid-6";

    Hedwig::Configuration* conf = new TestServerConfiguration();
    std::auto_ptr<Hedwig::Configuration> confptr(conf);

    Hedwig::Client* client = new Hedwig::Client(*conf);
    std::auto_ptr<Hedwig::Client> clientptr(client);

    Hedwig::Subscriber& sub = client->getSubscriber();
    Hedwig::Publisher& pub = client->getPublisher();

    sub.subscribe(topic, sid, Hedwig::SubscribeRequest::CREATE_OR_ATTACH);
    MyMessageHandlerCallback* cb = new MyMessageHandlerCallback(topic, sid);
    Hedwig::MessageHandlerCallbackPtr handler(cb);

    sub.startDelivery(topic, sid, handler);

    char buf[BIG_MESSAGE_SIZE];
    std::string bigmessage(buf, BIG_MESSAGE_SIZE);
    pub.publish(topic, bigmessage);
    pub.publish(topic, "Test Message 1");
    bool pass = false;
    for (int i = 0; i < 10; i++) {
      sleep(3);
      if (cb->numMessagesReceived() > 0) {
	if (cb->getLastMessage() == "Test Message 1") {
	  pass = true;
	  break;
	}
      }
    }
    CPPUNIT_ASSERT(pass);
  }
};

CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PubSubTestSuite, "PubSub" );

max_issues_repo_name: jvrao/bookkeeper

max_forks_repo_name: jvrao/bookkeeper


text:
/// \file   loan.cpp
///
/// \brief
///
/// \authors    Maarten P. Scholl
/// \date       2018-04-29
/// \copyright  Copyright 2017-2019 The Institute for New Economic Thinking,
///             Oxford Martin School, University of Oxford
///
///             Licensed under the Apache License, Version 2.0 (the "License");
///             you may not use this file except in compliance with the License.
///             You may obtain a copy of the License at
///
///                 http://www.apache.org/licenses/LICENSE-2.0
///
///             Unless required by applicable law or agreed to in writing,
///             software distributed under the License is distributed on an "AS
///             IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
///             express or implied. See the License for the specific language
///             governing permissions and limitations under the License.
///
///             You may obtain instructions to fulfill the attribution
///             requirements in CITATION.cff
///

#include <esl/economics/finance/loan.hpp>
using namespace esl::economics::finance;

#ifdef WITH_PYTHON
#include <boost/python.hpp>

using namespace boost::python;

BOOST_PYTHON_MODULE(loan)
{
    class_<loan, bases<esl::law::contract>>
        ( "loan", init<esl::identity<esl::agent>, esl::identity<esl::agent>>())
        .add_property("lender"
            , make_function( &loan::lender
            , return_value_policy<copy_const_reference>())
            )
        .add_property("borrower"
            , make_function(&loan::borrower
            , return_value_policy<copy_const_reference>())
            )
        ;
}

#endif  // WITH_PYTHON


text:
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/

/// @file audio_karaoke.cpp
/// @brief Karaoke table UI in audio box (not in audio display)
/// @ingroup audio_ui
///

#include "config.h"

#include "audio_karaoke.h"

#include "include/aegisub/context.h"

#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_karaoke.h"
#include "audio_box.h"
#include "audio_controller.h"
#include "audio_timing.h"
#include "compat.h"
#include "libresrc/libresrc.h"
#include "options.h"
#include "selection_controller.h"
#include "utils.h"

#include <libaegisub/util.h>

#include <algorithm>
#include <boost/locale/boundary.hpp>
#include <numeric>

#include <wx/bmpbuttn.h>
#include <wx/button.h>
#include <wx/dcclient.h>
#include <wx/dcmemory.h>
#include <wx/menu.h>
#include <wx/panel.h>
#include <wx/settings.h>
#include <wx/sizer.h>

template<class Container, class Value>
static inline size_t last_lt_or_eq(Container const& c, Value const& v) {
	auto it = lower_bound(c.begin(), c.end(), v);
	// lower_bound gives first >=
	if (it == c.end() || *it > v)
		--it;
	return distance(c.begin(), it);
}

AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
: wxWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_SUNKEN)
, c(c)
, file_changed(c->ass->AddCommitListener(&AudioKaraoke::OnFileChanged, this))
, audio_opened(c->audioController->AddAudioOpenListener(&AudioKaraoke::OnAudioOpened, this))
, audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this))
, active_line_changed(c->selectionController->AddActiveLineListener(&AudioKaraoke::OnActiveLineChanged, this))
, kara(agi::util::make_unique<AssKaraoke>())
{
	using std::bind;

	cancel_button = new wxBitmapButton(this, -1, GETIMAGE(kara_split_cancel_16));
	cancel_button->SetToolTip(_("Discard all uncommitted splits"));
	cancel_button->Bind(wxEVT_BUTTON, bind(&AudioKaraoke::CancelSplit, this));

	accept_button = new wxBitmapButton(this, -1, GETIMAGE(kara_split_accept_16));
	accept_button->SetToolTip(_("Commit splits"));
	accept_button->Bind(wxEVT_BUTTON, bind(&AudioKaraoke::AcceptSplit, this));

	split_area = new wxPanel(this);

	wxSizer *main_sizer = new wxBoxSizer(wxHORIZONTAL);
	main_sizer->Add(cancel_button);
	main_sizer->Add(accept_button);
	main_sizer->Add(split_area, wxSizerFlags(1).Expand());
	SetSizerAndFit(main_sizer);

	/// @todo subscribe
	split_font.SetFaceName(FontFace("Audio/Karaoke"));
	split_font.SetPointSize(OPT_GET("Audio/Karaoke/Font Size")->GetInt());

	split_area->Bind(wxEVT_SIZE, &AudioKaraoke::OnSize, this);
	split_area->Bind(wxEVT_PAINT, &AudioKaraoke::OnPaint, this);
	split_area->Bind(wxEVT_LEFT_DOWN, &AudioKaraoke::OnMouse, this);
	split_area->Bind(wxEVT_LEFT_UP, &AudioKaraoke::OnMouse, this);
	split_area->Bind(wxEVT_MOTION, &AudioKaraoke::OnMouse, this);
	split_area->Bind(wxEVT_LEAVE_WINDOW, &AudioKaraoke::OnMouse, this);
	split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this);
	scroll_timer.Bind(wxEVT_TIMER, &AudioKaraoke::OnScrollTimer, this);

	accept_button->Enable(false);
	cancel_button->Enable(false);
	enabled = false;
}

AudioKaraoke::~AudioKaraoke() {
}

void AudioKaraoke::OnActiveLineChanged(AssDialogue *new_line) {
	active_line = new_line;
	if (enabled) {
		LoadFromLine();
		split_area->Refresh(false);
	}
}

void AudioKaraoke::OnFileChanged(int type, std::set<const AssEntry *> const& changed) {
	if (enabled && (type & AssFile::COMMIT_DIAG_FULL) && (changed.empty() || changed.count(active_line))) {
		LoadFromLine();
		split_area->Refresh(false);
	}
}

void AudioKaraoke::OnAudioOpened() {
	SetEnabled(enabled);
}

void AudioKaraoke::OnAudioClosed() {
	c->audioController->SetTimingController(nullptr);
}

void AudioKaraoke::SetEnabled(bool en) {
	enabled = en;

	c->audioBox->ShowKaraokeBar(enabled);
	if (enabled) {
		LoadFromLine();
		c->audioController->SetTimingController(CreateKaraokeTimingController(c, kara.get(), file_changed));
		Refresh(false);
	}
	else {
		c->audioController->SetTimingController(CreateDialogueTimingController(c));
	}
}

void AudioKaraoke::OnSize(wxSizeEvent &evt) {
	RenderText();
	Refresh(false);
}

void AudioKaraoke::OnPaint(wxPaintEvent &) {
	int w, h;
	split_area->GetClientSize(&w, &h);

	wxPaintDC dc(split_area);
	wxMemoryDC bmp_dc(rendered_line);

	// Draw the text and split lines
	dc.Blit(-scroll_x, 0, rendered_line.GetWidth(), h, &bmp_dc, 0, 0);

	// Draw the split line under the mouse
	if (click_will_remove_split)
		dc.SetPen(*wxRED);
	else
		dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
	dc.DrawLine(mouse_pos, 0, mouse_pos, h);

	dc.SetPen(*wxTRANSPARENT_PEN);

	int width_past_bmp = w + scroll_x - rendered_line.GetWidth();
	dc.SetBrush(*wxWHITE_BRUSH);
	if (width_past_bmp > 0)
		dc.DrawRectangle(w - width_past_bmp, 0, width_past_bmp, h);

	// Draw scroll arrows if needed
	if (scroll_x > 0) {
		dc.DrawRectangle(0, 0, 20, h);

		wxPoint triangle[] = {
			wxPoint(10, h / 2 - 6),
			wxPoint(4, h / 2),
			wxPoint(10, h / 2 + 6)
		};
		dc.SetBrush(*wxBLACK_BRUSH);
		dc.DrawPolygon(3, triangle);
	}

	if (rendered_line.GetWidth() - scroll_x > w) {
		dc.SetBrush(*wxWHITE_BRUSH);
		dc.DrawRectangle(w - 20, 0, 20, h);

		wxPoint triangle[] = {
			wxPoint(w - 10, h / 2 - 6),
			wxPoint(w - 4, h / 2),
			wxPoint(w - 10, h / 2 + 6)
		};
		dc.SetBrush(*wxBLACK_BRUSH);
		dc.DrawPolygon(3, triangle);
	}
}

void AudioKaraoke::RenderText() {
	wxSize bmp_size = split_area->GetClientSize();
	int line_width = spaced_text.size() * char_width + 5;
	if (line_width > bmp_size.GetWidth())
		bmp_size.SetWidth(line_width);

	if (!rendered_line.IsOk() || bmp_size != rendered_line.GetSize())
		rendered_line = wxBitmap(bmp_size);

	wxMemoryDC dc(rendered_line);

	// Draw background
	dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
	dc.SetPen(*wxTRANSPARENT_PEN);
	dc.DrawRectangle(wxPoint(), bmp_size);

	dc.SetFont(split_font);
	dc.SetTextForeground(wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)));

	// Draw each character in the line
	int y = (bmp_size.GetHeight() - char_height) / 2;
	for (size_t i = 0; i < spaced_text.size(); ++i)
		dc.DrawText(spaced_text[i], char_x[i], y);

	// Draw the lines between each syllable
	dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
	for (auto syl_line : syl_lines)
		dc.DrawLine(syl_line, 0, syl_line, bmp_size.GetHeight());
}

void AudioKaraoke::AddMenuItem(wxMenu &menu, std::string const& tag, wxString const& help, std::string const& selected) {
	wxMenuItem *item = menu.AppendCheckItem(-1, to_wx(tag), help);
	menu.Bind(wxEVT_MENU, std::bind(&AudioKaraoke::SetTagType, this, tag), item->GetId());
	item->Check(tag == selected);
}

void AudioKaraoke::OnContextMenu(wxContextMenuEvent&) {
	if (!enabled) return;

	wxMenu context_menu(_("Karaoke tag"));
	std::string type = kara->GetTagType();

	AddMenuItem(context_menu, "\\k", _("Change karaoke tag to \\k"), type);
	AddMenuItem(context_menu, "\\kf", _("Change karaoke tag to \\kf"), type);
	AddMenuItem(context_menu, "\\ko", _("Change karaoke tag to \\ko"), type);

	PopupMenu(&context_menu);
}

void AudioKaraoke::OnMouse(wxMouseEvent &event) {
	if (!enabled) return;

	mouse_pos = event.GetX();

	if (event.Leaving()) {
		mouse_pos = -1;
		split_area->Refresh(false);
		return;
	}

	if (scroll_timer.IsRunning() || split_area->HasCapture()) {
		if (event.LeftUp()) {
			scroll_timer.Stop();
			split_area->ReleaseMouse();
		}
		return;
	}

	// Check if the mouse is over a scroll arrow
	int client_width = split_area->GetClientSize().GetWidth();
	if (scroll_x > 0 && mouse_pos < 20)
		scroll_dir = -1;
	else if (scroll_x + client_width < rendered_line.GetWidth() && mouse_pos > client_width - 20)
		scroll_dir = 1;
	else
		scroll_dir = 0;

	if (scroll_dir) {
		mouse_pos = -1;
		if (event.LeftDown()) {
			split_area->Refresh(false);
			scroll_timer.Start(50);
			split_area->CaptureMouse();
			wxTimerEvent evt;
			OnScrollTimer(evt);
		}
		return;
	}

	int shifted_pos = mouse_pos + scroll_x;

	// Character to insert the new split point before
	int split_pos = std::min<int>((shifted_pos + char_width / 2) / char_width, spaced_text.size());

	// Syllable this character is in
	int syl = last_lt_or_eq(syl_start_points, split_pos);

	// If the click is sufficiently close to a line of a syllable split,
	// remove that split rather than adding a new one
	bool click_right = (syl > 0 && shifted_pos <= syl_lines[syl - 1] + 3);
	bool click_left = (syl < (int)syl_lines.size() && shifted_pos >= syl_lines[syl] - 3);
	click_will_remove_split = click_left || click_right;

	if (!event.LeftDown()) {
		// Erase the old line and draw the new one
		split_area->Refresh(false);
		return;
	}

	if (click_will_remove_split)
		kara->RemoveSplit(syl + (click_left && !click_right));
	else
		kara->AddSplit(syl, char_to_byte[split_pos] - 1);

	SetDisplayText();
	accept_button->Enable(true);
	cancel_button->Enable(true);
	split_area->Refresh(false);
}

void AudioKaraoke::OnScrollTimer(wxTimerEvent &) {
	scroll_x += scroll_dir * char_width * 3;

	int max_scroll = rendered_line.GetWidth() + 20 - split_area->GetClientSize().GetWidth();
	if (scroll_x < 0 || scroll_x > max_scroll) {
		scroll_x = mid(0, scroll_x, max_scroll);
		scroll_timer.Stop();
	}

	split_area->Refresh(false);
}

void AudioKaraoke::LoadFromLine() {
	scroll_x = 0;
	scroll_timer.Stop();
	kara->SetLine(active_line, true);
	SetDisplayText();
	accept_button->Enable(kara->GetText() != active_line->Text);
	cancel_button->Enable(false);
}

void AudioKaraoke::SetDisplayText() {
	using namespace boost::locale::boundary;

	wxMemoryDC dc;
	dc.SetFont(split_font);

	auto get_char_width = [&](std::string const& character) -> int {
		const auto it = char_widths.find(character);
		if (it != end(char_widths))
			return it->second;

		const auto size = dc.GetTextExtent(to_wx(character));
		char_height = std::max(char_height, size.GetHeight());
		char_widths[character] = size.GetWidth();
		return size.GetWidth();
	};

	char_width = get_char_width(" ");

	// Width in pixels of each character in this string
	std::vector<int> str_char_widths;

	spaced_text.clear();
	char_to_byte.clear();
	syl_start_points.clear();
	for (auto const& syl : *kara) {
		// The last (and only the last) syllable needs the width of the final
		// character in the syllable, so we unconditionally add it at the end
		// of this loop, then remove the extra ones here
		if (!char_to_byte.empty())
			char_to_byte.pop_back();

		syl_start_points.push_back(spaced_text.size());

		// Add a space between each syllable to avoid crowding
		spaced_text.emplace_back(wxS(" "));
		str_char_widths.push_back(char_width);
		char_to_byte.push_back(1);

		size_t syl_idx = 1;
		const ssegment_index characters(character, begin(syl.text), end(syl.text));
		for (auto chr : characters) {
			// Calculate the width in pixels of this character
			const std::string character = chr.str();
			const int width = get_char_width(character);
			char_width = std::max(char_width, width);
			str_char_widths.push_back(width);

			spaced_text.emplace_back(to_wx(character));
			char_to_byte.push_back(syl_idx);
			syl_idx += character.size();
		}

		char_to_byte.push_back(syl_idx);
	}

	// Center each character within the space available to it
	char_x.resize(str_char_widths.size());
	for (size_t i = 0; i < str_char_widths.size(); ++i)
		char_x[i] =  i * char_width + (char_width - str_char_widths[i]) / 2;

	// Calculate the positions of the syllable divider lines
	syl_lines.resize(syl_start_points.size() - 1);
	for (size_t i = 1; i < syl_start_points.size(); ++i)
		syl_lines[i - 1] = syl_start_points[i] * char_width + char_width / 2;

	RenderText();
}

void AudioKaraoke::CancelSplit() {
	LoadFromLine();
	split_area->Refresh(false);
}

void AudioKaraoke::AcceptSplit() {
	active_line->Text = kara->GetText();
	file_changed.Block();
	c->ass->Commit(_("karaoke split"), AssFile::COMMIT_DIAG_TEXT);
	file_changed.Unblock();

	accept_button->Enable(false);
	cancel_button->Enable(false);
}

void AudioKaraoke::SetTagType(std::string const& new_tag) {
	kara->SetTagType(new_tag);
	AcceptSplit();
}

max_stars_repo_name: rcombs/Aegisub

max_issues_repo_name: rcombs/Aegisub

max_forks_repo_name: rcombs/Aegisub


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// 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
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//

#ifndef BOOST_COMPUTE_CONTAINER_STRING_HPP
#define BOOST_COMPUTE_CONTAINER_STRING_HPP

#include <boost/compute/types/fundamental.hpp>
#include <boost/compute/container/basic_string.hpp>

namespace boost {
namespace compute {

typedef basic_string<char_> string;

} // end compute namespace
} // end boost namespace

#endif // BOOST_COMPUTE_CONTAINER_STRING_HPP

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
/**
 * Copyright Soramitsu Co., Ltd. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#include <gtest/gtest.h>

#include <binaryen/shell-interface.h>
#include <binaryen/wasm-s-parser.h>
#include <boost/format.hpp>
#include <utility>
using namespace wasm;

/**
 * An external interface with custom imported function. Should be used for
 * testing purposes
 */
class IntParamExternalInterface : public ShellExternalInterface {
 private:
  std::string env_name_;
  std::string fun_name_;

  using FunType = std::function<void(int)>;
  FunType f_;

 public:
  explicit IntParamExternalInterface(std::string env_name,
                                     std::string fun_name,
                                     FunType &&f)
      : env_name_(std::move(env_name)), fun_name_(std::move(fun_name)), f_(std::move(f)) {}

  Literal callImport(Function *import, LiteralList &arguments) override {
    if (import->module == env_name_.c_str()
        && import->base == fun_name_.c_str()) {
      if (arguments.size() != 1) {
        Fatal() << fun_name_ << "expected exactly 1 parameter";
      }
      auto arg = *arguments.begin();
      f_(arg.geti32());
      return Literal();
    }
    Fatal() << "callImport: unknown import: " << import->module.str << "."
            << import->name.str;
  }
};

/**
 * @given WebAssembly S-expression code with invocation of imported function
 * (foo) with given argument is implemented in C++
 * @when this code is interpreted using Binaryen
 * @then foo implementation on C++ is invoked with given argument
 */
TEST(BinaryenTest, InvokeCppFunctionFromWebAssembly) {
  int expected_argument = 1234;
  std::string env_name = "env";
  std::string fun_name = "foo";
  auto fun_impl = [&](int a) { ASSERT_EQ(a, expected_argument); };

  // wast code with imported function's call
  auto fmt = boost::format(
                 R"#(
              (module
                (type $v (func))
                (import "%1%" "%2%" (func $%2% (param i32)))
                (start $starter)
                (func $starter (; 1 ;) (type $v)
                  (call $%2%
                    (i32.const %3%)
                  )
                )
              )
              )#")
      % env_name % fun_name % expected_argument;

  std::string expression = fmt.str();

  // parse wast
  Module wasm{};

  // clang-8 doesn't know char * std::string::data(),
  // it returns only const char *
  char *data = const_cast<char *>(expression.data());
  SExpressionParser parser(data);
  Element &root = *parser.root;
  SExpressionWasmBuilder builder(wasm, *root[0]);

  // prepare external interface with imported function's implementation
  IntParamExternalInterface interface(env_name, fun_name, fun_impl);

  // interpret module
  ModuleInstance instance(wasm, &interface);
}

/**
 * @given WebAssembly S-expression code exporting a function
 * exported function (sumtwo) taking two arguments of type i32 returning their
 * sum of type i32 is implemented in assembly
 * @when this code is interpreted using Binaryen and invoked from C++ with given
 * arguments
 * @then result (the sum of two i32) is calculated and returned to C++ code
 */
TEST(BinaryenTest, InvokeWebAssemblyFunctionFromCpp) {
  // wast code with imported function's call
  char sexpr[] = R"#(
          (module
            (type $t0 (func (param i32 i32) (result i32)))
            (export "sumtwo" (func $sumtwo))
            (func $sumtwo (; 1 ;) (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
              (i32.add
                (local.get $p0)
                (local.get $p1)
              )
            )
          )
          )#";

  // parse wast
  SExpressionParser parser(sexpr);
  auto &root = *parser.root;

  // wasm
  Module wasm{};

  // build wasm module
  SExpressionWasmBuilder builder(wasm, *root[0]);

  // interface
  ShellExternalInterface shellInterface;

  // interpret module
  ModuleInstance moduleInstance(wasm, &shellInterface);

  // add arguments, their constructors are explicit, so no list-initialization
  LiteralList arguments = {Literal{1}, Literal{2}};

  // call exported function
  Literal result = moduleInstance.callExport("sumtwo", arguments);

  ASSERT_EQ(result.type, Type::i32);
  ASSERT_EQ(result.geti32(), 3);
}

max_stars_repo_name: FlorianFranzen/kagome

max_issues_repo_name: FlorianFranzen/kagome

max_forks_repo_name: FlorianFranzen/kagome


text:
// Copyright (c) 2018, Ryo Currency Project
// Portions copyright (c) 2014-2018, The Monero Project
//
// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details
// All rights reserved.
//
// Authors and copyright holders give permission for following:
//
// 1. Redistribution and use in source and binary forms WITHOUT modification.
//
// 2. Modification of the source form for your own personal use.
//
// As long as the following conditions are met:
//
// 3. You must not distribute modified copies of the to third parties. This includes
//    posting the work online, or hosting copies of the modified work for download.
//
// 4. Any derivative version of this work is also covered by this license, including point 8.
//
// 5. Neither the name of the copyright holders nor the names of the authors may be
//    used to endorse or promote products derived from this software without specific
//    prior written permission.
//
// 6. You agree that this licence is governed by and shall be construed in accordance
//    with the laws of England and Wales.
//
// 7. You agree to submit all disputes arising out of or in connection with this licence
//    to the exclusive jurisdiction of the Courts of England and Wales.
//
// Authors and copyright holders agree that:
//
// 8. This licence expires and the work covered by it is released into the
//    public domain on 1st of February 2019
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "updates.h"
#include "dns_utils.h"
#include "misc_log_ex.h"
#include "util.h"
#include <boost/algorithm/string.hpp>

//#undef RYO_DEFAULT_LOG_CATEGORY
//#define RYO_DEFAULT_LOG_CATEGORY "updates"

namespace tools
{
bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash)
{
	return false; //Temporarily disabled
#if 0
    std::vector<std::string> records;
    bool found = false;

    MDEBUG("Checking updates for " << buildtag << " " << software);

    // All four MoneroPulse domains have DNSSEC on and valid
    static const std::vector<std::string> dns_urls = {
        "updates.moneropulse.org",
        "updates.moneropulse.net",
        "updates.moneropulse.co",
        "updates.moneropulse.se"
    };

    if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls))
      return false;

    for (const auto& record : records)
    {
      std::vector<std::string> fields;
      boost::split(fields, record, boost::is_any_of(":"));
      if (fields.size() != 4)
      {
        MWARNING("Updates record does not have 4 fields: " << record);
        continue;
      }

      if (software != fields[0] || buildtag != fields[1])
        continue;

      bool alnum = true;
      for (auto c: hash)
        if (!isalnum(c))
          alnum = false;
      if (hash.size() != 64 && !alnum)
      {
        MWARNING("Invalid hash: " << hash);
        continue;
      }

      // use highest version
      if (found)
      {
        int cmp = vercmp(version.c_str(), fields[2].c_str());
        if (cmp > 0)
          continue;
        if (cmp == 0 && hash != fields[3])
          MWARNING("Two matches found for " << software << " version " << version << " on " << buildtag);
      }

      version = fields[2];
      hash = fields[3];

      MINFO("Found new version " << version << " with hash " << hash);
      found = true;
    }
    return found;
#endif
}

std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
{
#if 0
    const char *base = user ? "https://downloads.getmonero.org/" : "https://updates.getmonero.org/";
#ifdef _WIN32
    static const char *extension = strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe";
#else
    static const char extension[] = ".tar.bz2";
#endif

    std::string url;

    url =  base;
    if (!subdir.empty())
      url += subdir + "/";
    url = url + software + "-" + buildtag + "-v" + version + extension;
    return url;
#endif
	return "";
}
}

max_stars_repo_name: fireice-uk/ryo-currency

max_issues_repo_name: fireice-uk/ryo-currency

max_forks_repo_name: fireice-uk/ryo-currency


text: #include <boost/fusion/include/vector40.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino