<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/services/heartbeat_service.hpp>

#include <algorithm>
#include <cstdint>
#include <bitcoin/protocol.hpp>
#include <bitcoin/server/server_node.hpp>
#include <bitcoin/server/settings.hpp>

namespace libbitcoin {
namespace server {

static const auto domain = "heartbeat";

using namespace bc::config;
using namespace bc::protocol;

static uint32_t to_milliseconds(uint16_t seconds)
{
    const auto milliseconds = static_cast<uint32_t>(seconds) * 1000;
    return std::min(milliseconds, max_uint32);
};

// Heartbeat is capped at ~ 25 days by signed/millsecond conversions.
heartbeat_service::heartbeat_service(zmq::authenticator& authenticator,
    server_node& node, bool secure)
  : worker(node.thread_pool()),
    settings_(node.server_settings()),
    period_(to_milliseconds(settings_.heartbeat_interval_seconds)),
    authenticator_(authenticator),
    secure_(secure)
{
}

// Implement service as a publisher.
// The publisher does not block if there are no subscribers or at high water.
void heartbeat_service::work()
{
    zmq::socket publisher(authenticator_, zmq::socket::role::publisher);

    // Bind socket to the worker endpoint.
    if (!started(bind(publisher)))
        return;

    zmq::poller poller;
    poller.add(publisher);

    // Pick a random counter start, will wrap around at overflow.
    auto count = static_cast<uint32_t>(pseudo_random());

    // We will not receive on the poller, we use its timer and context stop.
    while (!poller.terminated() && !stopped())
    {
        poller.wait(period_);
        publish(count++, publisher);
    }

    // Unbind the socket and exit this thread.
    finished(unbind(publisher));
}

// Bind/Unbind.
//-----------------------------------------------------------------------------

bool heartbeat_service::bind(zmq::socket& publisher)
{
    const auto security = secure_ ? "secure" : "public";
    const auto& endpoint = secure_ ? settings_.secure_heartbeat_endpoint :
        settings_.public_heartbeat_endpoint;

    if (!authenticator_.apply(publisher, domain, secure_))
        return false;

    const auto ec = publisher.bind(endpoint);

    if (ec)
    {
        LOG_ERROR(LOG_SERVER)
            << "Failed to bind " << security << " heartbeat service to "
            << endpoint << " : " << ec.message();
        return false;
    }

    LOG_INFO(LOG_SERVER)
        << "Bound " << security << " heartbeat service to " << endpoint;
    return true;
}

bool heartbeat_service::unbind(zmq::socket& publisher)
{
    const auto security = secure_ ? "secure" : "public";

    // Don't log stop success.
    if (publisher.stop())
        return true;

    LOG_ERROR(LOG_SERVER)
        << "Failed to disconnect " << security << " heartbeat worker.";
    return false;
}

// Publish Execution (integral worker).
//-----------------------------------------------------------------------------

void heartbeat_service::publish(uint32_t count, zmq::socket& publisher)
{
    if (stopped())
        return;

    const auto security = secure_ ? "secure" : "public";

    zmq::message message;
    message.enqueue_little_endian(count);
    auto ec = publisher.send(message);

    if (ec == error::service_stopped)
        return;

    if (ec)
    {
        LOG_WARNING(LOG_SERVER)
            << "Failed to publish " << security << " heartbeat: "
            << ec.message();
        return;
    }

    // This isn't actually a request, should probably update settings.
    if (settings_.log_requests)
        LOG_DEBUG(LOG_SERVER)
            << "Published " << security << " heartbeat [" << count << "].";
}

} // namespace server
} // namespace libbitcoin
<commit_msg>Adapt to bc prng changes.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/services/heartbeat_service.hpp>

#include <algorithm>
#include <cstdint>
#include <bitcoin/protocol.hpp>
#include <bitcoin/server/server_node.hpp>
#include <bitcoin/server/settings.hpp>

namespace libbitcoin {
namespace server {

static const auto domain = "heartbeat";

using namespace bc::config;
using namespace bc::protocol;

static uint32_t to_milliseconds(uint16_t seconds)
{
    const auto milliseconds = static_cast<uint32_t>(seconds) * 1000;
    return std::min(milliseconds, max_uint32);
};

// Heartbeat is capped at ~ 25 days by signed/millsecond conversions.
heartbeat_service::heartbeat_service(zmq::authenticator& authenticator,
    server_node& node, bool secure)
  : worker(node.thread_pool()),
    settings_(node.server_settings()),
    period_(to_milliseconds(settings_.heartbeat_interval_seconds)),
    authenticator_(authenticator),
    secure_(secure)
{
}

// Implement service as a publisher.
// The publisher does not block if there are no subscribers or at high water.
void heartbeat_service::work()
{
    zmq::socket publisher(authenticator_, zmq::socket::role::publisher);

    // Bind socket to the worker endpoint.
    if (!started(bind(publisher)))
        return;

    zmq::poller poller;
    poller.add(publisher);

    // Pick a random counter start, will wrap around at overflow.
    auto count = static_cast<uint32_t>(pseudo_random(0, max_uint32));

    // We will not receive on the poller, we use its timer and context stop.
    while (!poller.terminated() && !stopped())
    {
        poller.wait(period_);
        publish(count++, publisher);
    }

    // Unbind the socket and exit this thread.
    finished(unbind(publisher));
}

// Bind/Unbind.
//-----------------------------------------------------------------------------

bool heartbeat_service::bind(zmq::socket& publisher)
{
    const auto security = secure_ ? "secure" : "public";
    const auto& endpoint = secure_ ? settings_.secure_heartbeat_endpoint :
        settings_.public_heartbeat_endpoint;

    if (!authenticator_.apply(publisher, domain, secure_))
        return false;

    const auto ec = publisher.bind(endpoint);

    if (ec)
    {
        LOG_ERROR(LOG_SERVER)
            << "Failed to bind " << security << " heartbeat service to "
            << endpoint << " : " << ec.message();
        return false;
    }

    LOG_INFO(LOG_SERVER)
        << "Bound " << security << " heartbeat service to " << endpoint;
    return true;
}

bool heartbeat_service::unbind(zmq::socket& publisher)
{
    const auto security = secure_ ? "secure" : "public";

    // Don't log stop success.
    if (publisher.stop())
        return true;

    LOG_ERROR(LOG_SERVER)
        << "Failed to disconnect " << security << " heartbeat worker.";
    return false;
}

// Publish Execution (integral worker).
//-----------------------------------------------------------------------------

void heartbeat_service::publish(uint32_t count, zmq::socket& publisher)
{
    if (stopped())
        return;

    const auto security = secure_ ? "secure" : "public";

    zmq::message message;
    message.enqueue_little_endian(count);
    auto ec = publisher.send(message);

    if (ec == error::service_stopped)
        return;

    if (ec)
    {
        LOG_WARNING(LOG_SERVER)
            << "Failed to publish " << security << " heartbeat: "
            << ec.message();
        return;
    }

    // This isn't actually a request, should probably update settings.
    if (settings_.log_requests)
        LOG_DEBUG(LOG_SERVER)
            << "Published " << security << " heartbeat [" << count << "].";
}

} // namespace server
} // namespace libbitcoin
<|endoftext|>


<commit_before>//
// Created by salmon on 17-9-3.
//

#include "EngineObject.h"
namespace simpla {
namespace engine {
struct EngineObject::pimpl_s {
    std::mutex m_mutex_;
    size_type m_click_ = 0;
    size_type m_click_tag_ = 0;
    bool m_is_initialized_ = false;
    bool m_is_setup_ = false;
};
EngineObject::EngineObject() : m_pimpl_(new pimpl_s) {}
EngineObject::~EngineObject() { Finalize(); }
std::shared_ptr<data::DataNode> EngineObject::Serialize() const { return base_type::Serialize(); }
void EngineObject::Deserialize(std::shared_ptr<data::DataNode> const &cfg) {
    ASSERT(!isSetUp());
    Initialize();
    base_type::Deserialize(cfg);
};
void EngineObject::lock() { m_pimpl_->m_mutex_.lock(); }
void EngineObject::unlock() { m_pimpl_->m_mutex_.unlock(); }
bool EngineObject::try_lock() { return m_pimpl_->m_mutex_.try_lock(); }

size_type EngineObject::GetTagCount() const { return m_pimpl_->m_click_tag_; }
size_type EngineObject::GetClickCount() const { return m_pimpl_->m_click_; }

void EngineObject::Click() { ++m_pimpl_->m_click_; }
void EngineObject::Tag() { m_pimpl_->m_click_tag_ = m_pimpl_->m_click_; }
void EngineObject::ResetTag() { m_pimpl_->m_click_tag_ = (m_pimpl_->m_click_ = 0); }

bool EngineObject::isModified() const { return m_pimpl_->m_click_tag_ != m_pimpl_->m_click_; }
bool EngineObject::isInitialized() const { return m_pimpl_->m_is_initialized_; }
bool EngineObject::isSetUp() const { return m_pimpl_->m_is_setup_; }

void EngineObject::Push(std::shared_ptr<data::DataNode> const &data) {
    ASSERT(isSetUp());
    base_type::Push(data);
    Click();
}
std::shared_ptr<data::DataNode> EngineObject::Pop() {
    Click();
    return base_type::Pop();
}

void EngineObject::DoInitialize() {}
void EngineObject::DoSetUp() {}
void EngineObject::DoUpdate() {}
void EngineObject::DoTearDown() { db()->Clear(); }
void EngineObject::DoFinalize() {}

void EngineObject::Initialize() {
    if (!isInitialized()) {
        DoInitialize();
        Click();
        m_pimpl_->m_is_initialized_ = true;
    }
}
void EngineObject::SetUp() {
    if (!isSetUp()) {
        VERBOSE << std::setw(15) << " Set Up : " << std::setw(20) << std::left << GetName() << " [ " << TypeName()
                << " ]";
        PreSetUp(this);
        DoSetUp();
        PostSetUp(this);
        Click();
        m_pimpl_->m_is_setup_ = true;
    }
}
void EngineObject::Update() {
    SetUp();
    if (isModified()) {
        PreUpdate(this);
        DoUpdate();
        PostUpdate(this);
        Tag();
    }
}
void EngineObject::TearDown() {
    if (isSetUp()) {
        PreTearDown(this);
        DoTearDown();
        PostTearDown(this);
        Click();
        m_pimpl_->m_is_setup_ = false;
        VERBOSE << std::setw(15) << " Tear Down : " << std::setw(20) << std::left << GetName() << " [ " << TypeName()
                << " ]";
    }
};
void EngineObject::Finalize() {
    if (isInitialized()) {
        TearDown();
        DoFinalize();
        ResetTag();
        m_pimpl_->m_is_initialized_ = false;
    }
};
}
}  // namespace simpla<commit_msg>engine test<commit_after>//
// Created by salmon on 17-9-3.
//

#include "EngineObject.h"
namespace simpla {
namespace engine {
struct EngineObject::pimpl_s {
    std::mutex m_mutex_;
    size_type m_click_ = 0;
    size_type m_click_tag_ = 0;
    bool m_is_initialized_ = false;
    bool m_is_setup_ = false;
};
EngineObject::EngineObject() : m_pimpl_(new pimpl_s) {}
EngineObject::~EngineObject() { Finalize(); }
std::shared_ptr<data::DataNode> EngineObject::Serialize() const { return base_type::Serialize(); }
void EngineObject::Deserialize(std::shared_ptr<data::DataNode> const &cfg) {
    ASSERT(!isSetUp());
    Initialize();
    base_type::Deserialize(cfg);
};
void EngineObject::lock() { m_pimpl_->m_mutex_.lock(); }
void EngineObject::unlock() { m_pimpl_->m_mutex_.unlock(); }
bool EngineObject::try_lock() { return m_pimpl_->m_mutex_.try_lock(); }

size_type EngineObject::GetTagCount() const { return m_pimpl_->m_click_tag_; }
size_type EngineObject::GetClickCount() const { return m_pimpl_->m_click_; }

void EngineObject::Click() { ++m_pimpl_->m_click_; }
void EngineObject::Tag() { m_pimpl_->m_click_tag_ = m_pimpl_->m_click_; }
void EngineObject::ResetTag() { m_pimpl_->m_click_tag_ = (m_pimpl_->m_click_ = 0); }

bool EngineObject::isModified() const { return m_pimpl_->m_click_tag_ != m_pimpl_->m_click_; }
bool EngineObject::isInitialized() const { return m_pimpl_->m_is_initialized_; }
bool EngineObject::isSetUp() const { return m_pimpl_->m_is_setup_; }

void EngineObject::Push(std::shared_ptr<data::DataNode> const &data) {
    ASSERT(isSetUp());
    base_type::Push(data);
    Click();
}
std::shared_ptr<data::DataNode> EngineObject::Pop() {
    Click();
    return base_type::Pop();
}

void EngineObject::DoInitialize() {}
void EngineObject::DoSetUp() {}
void EngineObject::DoUpdate() {}
void EngineObject::DoTearDown() { db()->Clear(); }
void EngineObject::DoFinalize() {}

void EngineObject::Initialize() {
    if (!isInitialized()) {
        DoInitialize();
        Click();
        m_pimpl_->m_is_initialized_ = true;
    }
}
void EngineObject::SetUp() {
    if (!isSetUp()) {

        VERBOSE << std::setw(15) << " Set Up : " << std::setw(20) << std::left << GetName() << " [ " << TypeName()
                << " ]";
        PreSetUp(this);
        DoSetUp();
        PostSetUp(this);
        Click();
        m_pimpl_->m_is_setup_ = true;
    }
}
void EngineObject::Update() {
    SetUp();
    if (isModified()) {
        PreUpdate(this);
        DoUpdate();
        PostUpdate(this);
        Tag();
    }
}
void EngineObject::TearDown() {
    if (isSetUp()) {
        PreTearDown(this);
        DoTearDown();
        PostTearDown(this);
        Click();
        m_pimpl_->m_is_setup_ = false;
        VERBOSE << std::setw(15) << " Tear Down : " << std::setw(20) << std::left << GetName() << " [ " << TypeName()
                << " ]";
    }
};
void EngineObject::Finalize() {
    if (isInitialized()) {
        TearDown();
        DoFinalize();
        ResetTag();
        m_pimpl_->m_is_initialized_ = false;
    }
};
}
}  // namespace simpla<|endoftext|>


<commit_before><commit_msg>use pf for some places, fix docs from random access to possibly unordered access for multi assign<commit_after><|endoftext|>


<commit_before><commit_msg>Added test for a given size != 0<commit_after><|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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.
 *
 * \file main.cxx
 *
 * Main file for the io board application on the Tiva Launchpad board.
 *
 * @author Balazs Racz
 * @date 5 Jun 2015
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "os/os.h"
#include "can_frame.h"
#include "nmranet_config.h"

#include "os/TempFile.hxx"
#include "nmranet/SimpleStack.hxx"
#include "nmranet/SimpleNodeInfoMockUserFile.hxx"
#include "nmranet/ConfiguredConsumer.hxx"

#include "freertos_drivers/ti/TivaGPIO.hxx"
#include "freertos_drivers/common/BlinkerGPIO.hxx"
#include "config.hxx"
#include "definitions.hxx"

#define SNIFF_ON_SERIAL

extern const nmranet::NodeID NODE_ID;

OVERRIDE_CONST(gc_generate_newlines, 1);
OVERRIDE_CONST(main_thread_stack_size, 2500);

nmranet::SimpleCanStack stack(NODE_ID);

const char *const nmranet::CONFIG_FILENAME = "/dev/eeprom";
const char *const nmranet::SNIP_DYNAMIC_FILENAME = nmranet::CONFIG_FILENAME;

static_assert(nmranet::ConfigDef::size() <= 256, "Need to adjust eeprom size");

GPIO_PIN(LED_GREEN, LedPin, F, 3);
GPIO_PIN(LED_BLUE, LedPin, F, 2);

GPIO_PIN(SW1, GpioInputPU, F, 4);
GPIO_PIN(SW2, GpioInputPU, F, 0);

nmranet::ConfigDef cfg(0);

nmranet::ConfiguredConsumer consumer_red(
    stack.node(), cfg.seg().consumers().entry<0>(), BLINKER_Pin());
nmranet::ConfiguredConsumer consumer_green(
    stack.node(), cfg.seg().consumers().entry<1>(), LED_GREEN_Pin());
nmranet::ConfiguredConsumer consumer_blue(
    stack.node(), cfg.seg().consumers().entry<2>(), LED_BLUE_Pin());

nmranet::ConfiguredProducer producer_sw1(
    stack.node(), cfg.seg().producers().entry<0>(), SW1_Pin());
nmranet::ConfiguredProducer producer_sw2(
    stack.node(), cfg.seg().producers().entry<1>(), SW2_Pin());

nmranet::RefreshLoop loop(stack.node(), {producer_sw1.polling(), producer_sw2.polling()});

nmranet::FileMemorySpace config_space(
    nmranet::CONFIG_FILENAME, cfg.seg().size() + cfg.seg().offset());

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
    stack.memory_config_handler()->registry()->insert(
        stack.node(), nmranet::MemoryConfigDefs::SPACE_CONFIG, &config_space);

#if defined(HAVE_PHYSICAL_CAN_PORT)
    stack.add_can_port_select("/dev/can0");
#endif

// Enable this to add sniffing through the usb or serial port.
#if defined(SNIFF_ON_USB)
    stack.add_gridconnect_port("/dev/serUSB0");
#endif
#if defined(SNIFF_ON_SERIAL)
    stack.add_gridconnect_port("/dev/ser0");
#endif

    stack.loop_executor();
    return 0;
}
<commit_msg>Prunes includes in main.cxx<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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.
 *
 * \file main.cxx
 *
 * Main file for the io board application on the Tiva Launchpad board.
 *
 * @author Balazs Racz
 * @date 5 Jun 2015
 */

#include "os/os.h"
#include "nmranet_config.h"

#include "nmranet/SimpleStack.hxx"
#include "nmranet/ConfiguredConsumer.hxx"
#include "nmranet/ConfiguredProducer.hxx"

#include "freertos_drivers/ti/TivaGPIO.hxx"
#include "freertos_drivers/common/BlinkerGPIO.hxx"
#include "config.hxx"

#define SNIFF_ON_SERIAL

extern const nmranet::NodeID NODE_ID;

OVERRIDE_CONST(gc_generate_newlines, 1);
OVERRIDE_CONST(main_thread_stack_size, 2500);

nmranet::SimpleCanStack stack(NODE_ID);

const char *const nmranet::CONFIG_FILENAME = "/dev/eeprom";
const char *const nmranet::SNIP_DYNAMIC_FILENAME = nmranet::CONFIG_FILENAME;

static_assert(nmranet::ConfigDef::size() <= 256, "Need to adjust eeprom size");

GPIO_PIN(LED_GREEN, LedPin, F, 3);
GPIO_PIN(LED_BLUE, LedPin, F, 2);

GPIO_PIN(SW1, GpioInputPU, F, 4);
GPIO_PIN(SW2, GpioInputPU, F, 0);

nmranet::ConfigDef cfg(0);

nmranet::ConfiguredConsumer consumer_red(
    stack.node(), cfg.seg().consumers().entry<0>(), BLINKER_Pin());
nmranet::ConfiguredConsumer consumer_green(
    stack.node(), cfg.seg().consumers().entry<1>(), LED_GREEN_Pin());
nmranet::ConfiguredConsumer consumer_blue(
    stack.node(), cfg.seg().consumers().entry<2>(), LED_BLUE_Pin());

nmranet::ConfiguredProducer producer_sw1(
    stack.node(), cfg.seg().producers().entry<0>(), SW1_Pin());
nmranet::ConfiguredProducer producer_sw2(
    stack.node(), cfg.seg().producers().entry<1>(), SW2_Pin());

nmranet::RefreshLoop loop(
    stack.node(), {producer_sw1.polling(), producer_sw2.polling()});

nmranet::FileMemorySpace config_space(
    nmranet::CONFIG_FILENAME, cfg.seg().size() + cfg.seg().offset());

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
    stack.memory_config_handler()->registry()->insert(
        stack.node(), nmranet::MemoryConfigDefs::SPACE_CONFIG, &config_space);

#if defined(HAVE_PHYSICAL_CAN_PORT)
    stack.add_can_port_select("/dev/can0");
#endif
#if defined(SNIFF_ON_USB)
    stack.add_gridconnect_port("/dev/serUSB0");
#endif
#if defined(SNIFF_ON_SERIAL)
    stack.add_gridconnect_port("/dev/ser0");
#endif

    stack.loop_executor();
    return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016-2017 Andrew D. Zonenberg                                                                          *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "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 AUTHORS BE HELD 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 "splashcore.h"

using namespace std;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

YosysToolchain::YosysToolchain(string basepath)
	: FPGAToolchain(basepath, TOOLCHAIN_YOSYS)
{
	//Save version info
	string sver = ShellCommand(basepath + " -V");
	sscanf(sver.c_str(), "Yosys %8d.%8d+%8d", &m_majorVersion, &m_minorVersion, &m_patchVersion);

	char tmp[128];
	snprintf(tmp, sizeof(tmp), "Yosys %d.%d+%d", m_majorVersion, m_minorVersion, m_patchVersion);
	m_stringVersion = tmp;

	//Set list of target architectures
	FindArchitectures();

	//File format suffixes
	m_fixes["netlist"] = stringpair("", ".json");
	m_fixes["formal-netlist"] = stringpair("", ".smt2");
	m_fixes["formal"] = stringpair("", ".txt");

	//Generate the hash based on the full git ID etc
	m_hash = sha256(sver);
}

YosysToolchain::~YosysToolchain()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Search for other toolchains

void YosysToolchain::FindArchitectures()
{
	//We always support formal targets b/c those don't need any extra tools
	m_triplets.emplace("generic-formal");

	//Get our search path
	vector<string> dirs;
	ParseSearchPath(dirs);

	//TODO: IceStorm stuff

	//Look for gp4par
	m_gp4parPath = FindExecutable("gp4par", dirs);
	if(m_gp4parPath != "")
	{
		m_triplets.emplace("greenpak4-slg46140");
		m_triplets.emplace("greenpak4-slg46620");
		m_triplets.emplace("greenpak4-slg46621");
	}
}

/**
	@brief Look for a binary anywhere in the search path
 */
string YosysToolchain::FindExecutable(string fname, vector<string>& dirs)
{
	for(auto dir : dirs)
	{
		string path = dir + "/" + fname;
		if(DoesFileExist(path))
			return path;
	}

	return "";
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Toolchain properties

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actual compilation

bool YosysToolchain::Build(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	//Switch on the triplet to decide how to handle it
	if(triplet == "generic-formal")
	{
		//If the output file is a .smt2 we're building for the model checker
		if(fname.find(".smt2") != string::npos)
			return BuildFormal(triplet, sources, fname, flags, outputs, stdout);

		//Otherwise we're running the checker
		else
			return CheckModel(triplet, sources, fname, flags, outputs, stdout);
	}
	else if(triplet.find("greenpak4-") == 0)
		return BuildGreenPAK(triplet, sources, fname, flags, outputs, stdout);

	else
	{
		stdout = string("ERROR: YosysToolchain doesn't know how to build for architecture ") + triplet + "\n";
		return false;
	}
}

/**
	@brief Synthesize for formal verification
 */
bool YosysToolchain::BuildFormal(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "";

	LogDebug("YosysToolchain::BuildFormal for %s\n", fname.c_str());
	string base = GetBasenameOfFileWithoutExt(fname);

	//TODO: Flags
	for(auto f : flags)
	{
		/*
		if(f.GetType() != BuildFlag::TYPE_DEFINE)
			continue;
		defines += f.GetFlag() + "=" + f.GetArgs() + " ";
		*/
		stdout += string("WARNING: YosysToolchain::BuildFormal: Don't know what to do with flag ") +
			static_cast<string>(f) + "\n";
	}

	//Write the synthesis script
	string ys_file = base + ".ys";
	string smt_file = base + ".smt2";
	FILE* fp = fopen(ys_file.c_str(), "w");
	if(!fp)
	{
		stdout += string("ERROR: Failed to create synthesis script ") + ys_file + "\n";
		return false;
	}
	for(auto s : sources)
	{
		//Ignore any non-Verilog sources
		if(s.find(".v") != string::npos)
			fprintf(fp, "read_verilog -formal \"%s\"\n", s.c_str());
	}
	fprintf(fp, "prep -nordff -top %s\n", base.c_str());
	fprintf(fp, "check -assert\n");
	fprintf(fp, "write_smt2 -wires %s", smt_file.c_str());
	fclose(fp);

	//Run synthesis
	string report_file = base + ".log";
	string cmdline = m_basepath + " -t -l " + report_file + " " + ys_file;
	string output;
	bool ok = (0 == ShellCommand(cmdline, output));

	//Crunch the synthesis log
	CrunchYosysLog(output, stdout);

	//Done, return results
	if(DoesFileExist(report_file))
		outputs[report_file] = sha256_file(report_file);
	if(DoesFileExist(smt_file))
		outputs[smt_file] = sha256_file(smt_file);
	else
	{
		stdout += "ERROR: No SMT file produced\n";
		return false;
	}

	return ok;
}

/**
	@brief Synthesize for formal verification
 */
bool YosysToolchain::CheckModel(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "";

	//TODO: Separate options to run base case and temporal induction??

	//Look up the constraints and source file
	string smt_file;
	string constraints_file;
	for(auto s : sources)
	{
		if(s.find(".smtc") != string::npos)
			constraints_file = s;
		else if(s.find(".smt2") != string::npos)
			smt_file = s;
		else
		{
			stdout = "ERROR: YosysToolchain::CheckModel: Don't know what to do with " + s  + "\n";
			return false;
		}
	}

	if(smt_file == "")
	{
		stdout = "ERROR: YosysToolchain: no SMT file specified\n";
		return false;
	}

	string report_file = GetBasenameOfFile(fname);

	//Format the bulk of the command line (beginning and end vary)
	string num_steps = "20";
	for(auto f : flags)
	{
		//TODO: Flags

		/*
		if(f.GetType() != BuildFlag::TYPE_DEFINE)
			continue;
		defines += f.GetFlag() + "=" + f.GetArgs() + " ";
		*/
		stdout += string("WARNING: YosysToolchain::BuildFormal: Don't know what to do with flag ") +
			static_cast<string>(f) + "\n";
	}
	string basename = GetBasenameOfFileWithoutExt(fname);
	string vcd_file = basename + ".vcd";
	string cmdline_meat = "-t " + num_steps + " --dump-vcd " + vcd_file + " ";
	if(constraints_file != "")
		cmdline_meat += string("--smtc ") + constraints_file + " ";
	cmdline_meat += smt_file + " ";

	//Run the inductive step first. Counterintuitive since it's meaningless w/o the base case!
	//But it usually runs a lot faster than the base case, and the vast majority of errors can be caught here.
	//This means we can skip the time-consuming base case and iterate faster during verification.
	string cmdline = m_basepath + "-smtbmc -i " + cmdline_meat;
	string report_induction;
	bool ok = (0 == ShellCommand(cmdline, report_induction));

	//Run the base case (append to the existing report)
	cmdline = m_basepath + "-smtbmc " + cmdline_meat;
	string report_base;
	ok &= (0 == ShellCommand(cmdline, report_base));

	//Write to the report file (TODO: be able to upload this directly?)
	string report = report_induction + "\n\n\n\n\n" + report_base;
	PutFileContents(report_file, report);

	//Filter the results and print to stdout clientside
	CrunchSMTLog(report, stdout);

	//Upload the report
	outputs[report_file] = sha256_file(report_file);
	if(DoesFileExist(vcd_file))
		outputs[vcd_file] = sha256_file(vcd_file);

	//Done
	return ok;
}

bool YosysToolchain::BuildGreenPAK(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "ERROR: YosysToolchain::BuildGreenPAK() not implemented\n";
	return false;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reporting helpers

/**
	@brief Read through the report and figure out what's interesting
 */
void YosysToolchain::CrunchYosysLog(const string& log, string& stdout)
{
	//Split the report up into lines
	vector<string> lines;
	ParseLines(log, lines);

	for(auto line : lines)
	{
		//TODO: Blacklist messages of no importance

		//Filter out errors and warnings
		if(line.find("Warning:") == 0)
			stdout += line + "\n";
		if(line.find("Error:") == 0)
			stdout += line + "\n";
	}
}

void YosysToolchain::CrunchSMTLog(const string& log, string& stdout)
{
	//Split the report up into lines
	vector<string> lines;
	ParseLines(log, lines);

	bool unfilter = false;
	for(auto line : lines)
	{
		if(line.find("Assert failed") != string::npos)
			stdout += string("ERROR: ") + line + "\n";

		if(line.find("Traceback (most recent call last)") != string::npos)
		{
			stdout += "ERROR: Something went wrong (got a stack trace)\n";
			unfilter = true;
		}

		//If we stopped filtering, copy everything
		if(unfilter)
			stdout += line + "\n";
	}
}
<commit_msg>splashcore: Yosys toolchain now has extension for bitstream. TODO: make this depend on architecture?<commit_after>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016-2017 Andrew D. Zonenberg                                                                          *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "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 AUTHORS BE HELD 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 "splashcore.h"

using namespace std;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

YosysToolchain::YosysToolchain(string basepath)
	: FPGAToolchain(basepath, TOOLCHAIN_YOSYS)
{
	//Save version info
	string sver = ShellCommand(basepath + " -V");
	sscanf(sver.c_str(), "Yosys %8d.%8d+%8d", &m_majorVersion, &m_minorVersion, &m_patchVersion);

	char tmp[128];
	snprintf(tmp, sizeof(tmp), "Yosys %d.%d+%d", m_majorVersion, m_minorVersion, m_patchVersion);
	m_stringVersion = tmp;

	//Set list of target architectures
	FindArchitectures();

	//File format suffixes
	m_fixes["netlist"] = stringpair("", ".json");
	m_fixes["formal-netlist"] = stringpair("", ".smt2");
	m_fixes["formal"] = stringpair("", ".txt");
	m_fixes["bitstream"] = stringpair("", ".txt");

	//Generate the hash based on the full git ID etc
	m_hash = sha256(sver);
}

YosysToolchain::~YosysToolchain()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Search for other toolchains

void YosysToolchain::FindArchitectures()
{
	//We always support formal targets b/c those don't need any extra tools
	m_triplets.emplace("generic-formal");

	//Get our search path
	vector<string> dirs;
	ParseSearchPath(dirs);

	//TODO: IceStorm stuff

	//Look for gp4par
	m_gp4parPath = FindExecutable("gp4par", dirs);
	if(m_gp4parPath != "")
	{
		m_triplets.emplace("greenpak4-slg46140");
		m_triplets.emplace("greenpak4-slg46620");
		m_triplets.emplace("greenpak4-slg46621");
	}
}

/**
	@brief Look for a binary anywhere in the search path
 */
string YosysToolchain::FindExecutable(string fname, vector<string>& dirs)
{
	for(auto dir : dirs)
	{
		string path = dir + "/" + fname;
		if(DoesFileExist(path))
			return path;
	}

	return "";
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Toolchain properties

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actual compilation

bool YosysToolchain::Build(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	//Switch on the triplet to decide how to handle it
	if(triplet == "generic-formal")
	{
		//If the output file is a .smt2 we're building for the model checker
		if(fname.find(".smt2") != string::npos)
			return BuildFormal(triplet, sources, fname, flags, outputs, stdout);

		//Otherwise we're running the checker
		else
			return CheckModel(triplet, sources, fname, flags, outputs, stdout);
	}
	else if(triplet.find("greenpak4-") == 0)
		return BuildGreenPAK(triplet, sources, fname, flags, outputs, stdout);

	else
	{
		stdout = string("ERROR: YosysToolchain doesn't know how to build for architecture ") + triplet + "\n";
		return false;
	}
}

/**
	@brief Synthesize for formal verification
 */
bool YosysToolchain::BuildFormal(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "";

	LogDebug("YosysToolchain::BuildFormal for %s\n", fname.c_str());
	string base = GetBasenameOfFileWithoutExt(fname);

	//TODO: Flags
	for(auto f : flags)
	{
		/*
		if(f.GetType() != BuildFlag::TYPE_DEFINE)
			continue;
		defines += f.GetFlag() + "=" + f.GetArgs() + " ";
		*/
		stdout += string("WARNING: YosysToolchain::BuildFormal: Don't know what to do with flag ") +
			static_cast<string>(f) + "\n";
	}

	//Write the synthesis script
	string ys_file = base + ".ys";
	string smt_file = base + ".smt2";
	FILE* fp = fopen(ys_file.c_str(), "w");
	if(!fp)
	{
		stdout += string("ERROR: Failed to create synthesis script ") + ys_file + "\n";
		return false;
	}
	for(auto s : sources)
	{
		//Ignore any non-Verilog sources
		if(s.find(".v") != string::npos)
			fprintf(fp, "read_verilog -formal \"%s\"\n", s.c_str());
	}
	fprintf(fp, "prep -nordff -top %s\n", base.c_str());
	fprintf(fp, "check -assert\n");
	fprintf(fp, "write_smt2 -wires %s", smt_file.c_str());
	fclose(fp);

	//Run synthesis
	string report_file = base + ".log";
	string cmdline = m_basepath + " -t -l " + report_file + " " + ys_file;
	string output;
	bool ok = (0 == ShellCommand(cmdline, output));

	//Crunch the synthesis log
	CrunchYosysLog(output, stdout);

	//Done, return results
	if(DoesFileExist(report_file))
		outputs[report_file] = sha256_file(report_file);
	if(DoesFileExist(smt_file))
		outputs[smt_file] = sha256_file(smt_file);
	else
	{
		stdout += "ERROR: No SMT file produced\n";
		return false;
	}

	return ok;
}

/**
	@brief Synthesize for formal verification
 */
bool YosysToolchain::CheckModel(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "";

	//TODO: Separate options to run base case and temporal induction??

	//Look up the constraints and source file
	string smt_file;
	string constraints_file;
	for(auto s : sources)
	{
		if(s.find(".smtc") != string::npos)
			constraints_file = s;
		else if(s.find(".smt2") != string::npos)
			smt_file = s;
		else
		{
			stdout = "ERROR: YosysToolchain::CheckModel: Don't know what to do with " + s  + "\n";
			return false;
		}
	}

	if(smt_file == "")
	{
		stdout = "ERROR: YosysToolchain: no SMT file specified\n";
		return false;
	}

	string report_file = GetBasenameOfFile(fname);

	//Format the bulk of the command line (beginning and end vary)
	string num_steps = "20";
	for(auto f : flags)
	{
		//TODO: Flags

		/*
		if(f.GetType() != BuildFlag::TYPE_DEFINE)
			continue;
		defines += f.GetFlag() + "=" + f.GetArgs() + " ";
		*/
		stdout += string("WARNING: YosysToolchain::BuildFormal: Don't know what to do with flag ") +
			static_cast<string>(f) + "\n";
	}
	string basename = GetBasenameOfFileWithoutExt(fname);
	string vcd_file = basename + ".vcd";
	string cmdline_meat = "-t " + num_steps + " --dump-vcd " + vcd_file + " ";
	if(constraints_file != "")
		cmdline_meat += string("--smtc ") + constraints_file + " ";
	cmdline_meat += smt_file + " ";

	//Run the inductive step first. Counterintuitive since it's meaningless w/o the base case!
	//But it usually runs a lot faster than the base case, and the vast majority of errors can be caught here.
	//This means we can skip the time-consuming base case and iterate faster during verification.
	string cmdline = m_basepath + "-smtbmc -i " + cmdline_meat;
	string report_induction;
	bool ok = (0 == ShellCommand(cmdline, report_induction));

	//Run the base case (append to the existing report)
	cmdline = m_basepath + "-smtbmc " + cmdline_meat;
	string report_base;
	ok &= (0 == ShellCommand(cmdline, report_base));

	//Write to the report file (TODO: be able to upload this directly?)
	string report = report_induction + "\n\n\n\n\n" + report_base;
	PutFileContents(report_file, report);

	//Filter the results and print to stdout clientside
	CrunchSMTLog(report, stdout);

	//Upload the report
	outputs[report_file] = sha256_file(report_file);
	if(DoesFileExist(vcd_file))
		outputs[vcd_file] = sha256_file(vcd_file);

	//Done
	return ok;
}

bool YosysToolchain::BuildGreenPAK(
	string triplet,
	set<string> sources,
	string fname,
	set<BuildFlag> flags,
	map<string, string>& outputs,
	string& stdout)
{
	stdout = "ERROR: YosysToolchain::BuildGreenPAK() not implemented\n";
	return false;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reporting helpers

/**
	@brief Read through the report and figure out what's interesting
 */
void YosysToolchain::CrunchYosysLog(const string& log, string& stdout)
{
	//Split the report up into lines
	vector<string> lines;
	ParseLines(log, lines);

	for(auto line : lines)
	{
		//TODO: Blacklist messages of no importance

		//Filter out errors and warnings
		if(line.find("Warning:") == 0)
			stdout += line + "\n";
		if(line.find("Error:") == 0)
			stdout += line + "\n";
	}
}

void YosysToolchain::CrunchSMTLog(const string& log, string& stdout)
{
	//Split the report up into lines
	vector<string> lines;
	ParseLines(log, lines);

	bool unfilter = false;
	for(auto line : lines)
	{
		if(line.find("Assert failed") != string::npos)
			stdout += string("ERROR: ") + line + "\n";

		if(line.find("Traceback (most recent call last)") != string::npos)
		{
			stdout += "ERROR: Something went wrong (got a stack trace)\n";
			unfilter = true;
		}

		//If we stopped filtering, copy everything
		if(unfilter)
			stdout += line + "\n";
	}
}
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2016 Frederic Culot <culot@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 <stdexcept>
#include <curses.h>

#include "window.h"

namespace portal {
namespace gfx {

class Window::Impl {
 public:
  WINDOW* win {nullptr};

  Size  size;
  Point pos, posStatus;
  Style style;

  // XXX Add a Point posCursor to allow for text spanning multi lines

  bool initialized() const;
  void create();
  void resize();
  void move();
  void destroy();
  void draw() const;
  void drawBorders() const;
  void print(const std::string& msg);
};

Window::Window() : impl_{new Impl} {
  impl_->create();
}

Window::Window(const Size& size, const Point& pos, const Style& style)
  : impl_{new Impl} {
  impl_->size = size;
  impl_->pos = pos;
  impl_->style = style;
  impl_->create();
  impl_->draw();
}

Window::~Window() {
  impl_->destroy();
}

void Window::setSize(const Size& size) {
  if (impl_->size != size) {
    impl_->size = size;
    impl_->resize();
  }
}

void Window::setPosition(const Point& pos) {
  if (impl_->pos != pos) {
    impl_->pos = pos;
    impl_->move();
  }
}

void Window::setStyle(const Style& style) {
  impl_->style = style;
  impl_->drawBorders();
}

Size Window::size() const {
  return impl_->size;
}

Point Window::position() const {
  return impl_->pos;
}

Style Window::style() const {
  return impl_->style;
}

  // XXX use provided style instead of class one
void Window::print(const std::string& msg, const Style& style) {
  if (impl_->style.color != Style::Color::none) {
    wattron(impl_->win, COLOR_PAIR(impl_->style.color));
  }
  impl_->print(msg);
  if (impl_->style.color != Style::Color::none) {
    wattroff(impl_->win, COLOR_PAIR(impl_->style.color));
  }
  wnoutrefresh(impl_->win);
}

void Window::print(int c, const Point& pos, const Style& style) const {
  int color =
    style.color != Style::Color::none ? style.color : impl_->style.color;
  wattron(impl_->win, COLOR_PAIR(color));
  if (!pos.isNull()) {
    wmove(impl_->win, pos.y(), pos.x());
  }
  waddch(impl_->win, c);
  wattroff(impl_->win, COLOR_PAIR(color));
  wnoutrefresh(impl_->win);
}

void Window::printStatus(const std::string& status, const Style& style) const {
  int statusLength = status.length();
  int xpos = impl_->size.width() - statusLength - 8;
  int ypos = impl_->size.height() - 1;
  impl_->posStatus.setX(xpos);
  impl_->posStatus.setY(ypos);
  mvwaddch(impl_->win, ypos, xpos++, ACS_RTEE);
  mvwaddch(impl_->win, ypos, xpos++, ' ');
  wattron(impl_->win, COLOR_PAIR(style.color) | style.cursesAttrs());
  mvwaddstr(impl_->win, ypos, xpos, status.c_str());
  wattroff(impl_->win, COLOR_PAIR(style.color) | style.cursesAttrs());
  xpos += statusLength;
  mvwaddch(impl_->win, ypos, xpos++, ' ');
  mvwaddch(impl_->win, ypos, xpos, ACS_LTEE);
  wnoutrefresh(impl_->win);
}

void Window::setStatusStyle(int xpos, int len, const Style& style) const {
  mvwchgat(impl_->win,
           impl_->posStatus.y(),
           impl_->posStatus.x() + xpos + 2,
           len,
           style.cursesAttrs(),
           style.color,
           nullptr);
  wnoutrefresh(impl_->win);
}

void Window::clearStatus() const {
  impl_->posStatus.reset();
  impl_->drawBorders();
}

void Window::draw() const {
  impl_->draw();
}

void Window::clear() {
  werase(impl_->win);
  wmove(impl_->win, 0, 0);
  impl_->draw();
}

bool Window::Impl::initialized() const {
  return win != nullptr;
}

void Window::Impl::create() {
  if (initialized()) {
    throw std::runtime_error("Window::Impl::create() - Object already initialized");
  }
  win = newwin(size.height(), size.width(), pos.y(), pos.x());
  drawBorders();
}

void Window::Impl::resize() {
  wresize(win, size.height(), size.width());
}

void Window::Impl::move() {
  mvwin(win, pos.y(), pos.x());
}

void Window::Impl::destroy() {
  if (!initialized()) {
    throw std::runtime_error("Window::Impl::destroy() - Object already destroyed");
  }
  delwin(win);
}

void Window::Impl::draw() const {
  wnoutrefresh(win);
}

void Window::Impl::drawBorders() const {
  // If a status is displayed (ie its position is not null), then we
  // must not override it by drawing the border, hence the following
  // test on posStatus.
  if (style.borders && posStatus.isNull()) {
    box(win, 0, 0);
  }
}

void Window::Impl::print(const std::string& msg) {
  int offset = style.borders ? 1 : 0;
  mvwaddstr(win, offset, offset, msg.c_str());
}

}
}
<commit_msg>Restore applyStyle method to underline search prompt<commit_after>/*-
 * Copyright (c) 2016 Frederic Culot <culot@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 <stdexcept>
#include <curses.h>

#include "window.h"

namespace portal {
namespace gfx {

class Window::Impl {
 public:
  WINDOW* win {nullptr};

  Size  size;
  Point pos, posStatus;
  Style style;

  // XXX Add a Point posCursor to allow for text spanning multi lines

  bool initialized() const;
  void create();
  void resize();
  void move();
  void destroy();
  void draw() const;
  void applyStyle() const;
  void drawBorders() const;
  void print(const std::string& msg);
};

Window::Window() : impl_{new Impl} {
  impl_->create();
}

Window::Window(const Size& size, const Point& pos, const Style& style)
  : impl_{new Impl} {
  impl_->size = size;
  impl_->pos = pos;
  impl_->style = style;
  impl_->create();
  impl_->draw();
}

Window::~Window() {
  impl_->destroy();
}

void Window::setSize(const Size& size) {
  if (impl_->size != size) {
    impl_->size = size;
    impl_->resize();
  }
}

void Window::setPosition(const Point& pos) {
  if (impl_->pos != pos) {
    impl_->pos = pos;
    impl_->move();
  }
}

void Window::setStyle(const Style& style) {
  impl_->style = style;
  impl_->drawBorders();
}

Size Window::size() const {
  return impl_->size;
}

Point Window::position() const {
  return impl_->pos;
}

Style Window::style() const {
  return impl_->style;
}

  // XXX use provided style instead of class one
void Window::print(const std::string& msg, const Style& style) {
  if (impl_->style.color != Style::Color::none) {
    wattron(impl_->win, COLOR_PAIR(impl_->style.color));
  }
  impl_->print(msg);
  if (impl_->style.color != Style::Color::none) {
    wattroff(impl_->win, COLOR_PAIR(impl_->style.color));
  }
  wnoutrefresh(impl_->win);
}

void Window::print(int c, const Point& pos, const Style& style) const {
  int color =
    style.color != Style::Color::none ? style.color : impl_->style.color;
  wattron(impl_->win, COLOR_PAIR(color));
  if (!pos.isNull()) {
    wmove(impl_->win, pos.y(), pos.x());
  }
  waddch(impl_->win, c);
  wattroff(impl_->win, COLOR_PAIR(color));
  wnoutrefresh(impl_->win);
}

void Window::printStatus(const std::string& status, const Style& style) const {
  int statusLength = status.length();
  int xpos = impl_->size.width() - statusLength - 8;
  int ypos = impl_->size.height() - 1;
  impl_->posStatus.setX(xpos);
  impl_->posStatus.setY(ypos);
  mvwaddch(impl_->win, ypos, xpos++, ACS_RTEE);
  mvwaddch(impl_->win, ypos, xpos++, ' ');
  wattron(impl_->win, COLOR_PAIR(style.color) | style.cursesAttrs());
  mvwaddstr(impl_->win, ypos, xpos, status.c_str());
  wattroff(impl_->win, COLOR_PAIR(style.color) | style.cursesAttrs());
  xpos += statusLength;
  mvwaddch(impl_->win, ypos, xpos++, ' ');
  mvwaddch(impl_->win, ypos, xpos, ACS_LTEE);
  wnoutrefresh(impl_->win);
}

void Window::setStatusStyle(int xpos, int len, const Style& style) const {
  mvwchgat(impl_->win,
           impl_->posStatus.y(),
           impl_->posStatus.x() + xpos + 2,
           len,
           style.cursesAttrs(),
           style.color,
           nullptr);
  wnoutrefresh(impl_->win);
}

void Window::clearStatus() const {
  impl_->posStatus.reset();
  impl_->drawBorders();
}

void Window::draw() const {
  impl_->draw();
}

void Window::clear() {
  werase(impl_->win);
  wmove(impl_->win, 0, 0);
  impl_->draw();
}

bool Window::Impl::initialized() const {
  return win != nullptr;
}

void Window::Impl::create() {
  if (initialized()) {
    throw std::runtime_error("Window::Impl::create() - Object already initialized");
  }
  win = newwin(size.height(), size.width(), pos.y(), pos.x());
  drawBorders();
}

void Window::Impl::resize() {
  wresize(win, size.height(), size.width());
}

void Window::Impl::move() {
  mvwin(win, pos.y(), pos.x());
}

void Window::Impl::destroy() {
  if (!initialized()) {
    throw std::runtime_error("Window::Impl::destroy() - Object already destroyed");
  }
  delwin(win);
}

void Window::Impl::draw() const {
  applyStyle();
  wnoutrefresh(win);
}

void Window::Impl::applyStyle() const {
  if (style.underline) {
    mvwchgat(win, 0, 0, size.width(), A_UNDERLINE, 0, nullptr);
  }
}

void Window::Impl::drawBorders() const {
  // If a status is displayed (ie its position is not null), then we
  // must not override it by drawing the border, hence the following
  // test on posStatus.
  if (style.borders && posStatus.isNull()) {
    box(win, 0, 0);
  }
}

void Window::Impl::print(const std::string& msg) {
  int offset = style.borders ? 1 : 0;
  mvwaddstr(win, offset, offset, msg.c_str());
}

}
}
<|endoftext|>


<commit_before>#include "xdr++.h"

#include <sstream>

#include <cstdio>
#include <arpa/inet.h>

bool xdr(XDR* xdrs, std::string& s)
{
	char* p;
	int32_t size, pad;
	char buf[BUFSIZ], zeros[] = { 0, 0, 0, 0 };
	std::ostringstream ss;

	switch (xdrs->x_op) {
	case XDR_ENCODE:
		p = const_cast<char*>(s.c_str());
		size = s.length();
		pad = (size | 0x03) - size + 1;
		return	   xdrs->x_ops->x_putint32(xdrs, &size)
			&& xdrs->x_ops->x_putbytes(xdrs, s.c_str(), size)
			&& xdrs->x_ops->x_putbytes(xdrs, zeros, pad);

	case XDR_DECODE:
		if (!xdrs->x_ops->x_getint32(xdrs, &size))
			return false;
		pad = (size | 0x03) - size + 1;
		p = buf;
		while (size) {
			uint32_t sz = size > sizeof (buf) ? sizeof (buf) : size;
			if (!xdrs->x_ops->x_getbytes(xdrs, p, sz))
				return false;
			ss.write(p, sz);
			size -= sz;
		}
		if (!xdrs->x_ops->x_getbytes(xdrs, p, pad))
			return false;
		s = ss.str();
		return true;

	default:
		break;
	}

	return false;
}

namespace {

	bool_t xdr_getlong_callback(XDR* xdrs, long* lp)
	{
		int32_t v;
		bool ret = static_cast<XDR_Base*>(xdrs)->get(v);
		if (ret)
			*lp = v;
		return ret;
	}

	bool_t xdr_putlong_callback(XDR* xdrs, const long* lp)
	{
		int32_t v = *lp;
		return static_cast<XDR_Base*>(xdrs)->put(v);
	}

	bool_t xdr_getbytes_callback(XDR* xdrs, caddr_t addr, u_int len)
	{
		return static_cast<XDR_Base*>(xdrs)->get(addr, len);
	}

	bool_t xdr_putbytes_callback(XDR* xdrs, const char* addr, u_int len)
	{
		return static_cast<XDR_Base*>(xdrs)->put(addr, len);
	}

	u_int xdr_getpostn_callback(const XDR* xdrs)
	{
		return static_cast<const XDR_Base*>(xdrs)->get_position();
	}

	bool_t xdr_setpostn_callback(XDR* xdrs, u_int pos)
	{
		return static_cast<XDR_Base*>(xdrs)->set_position(pos);
	}

	int32_t* xdr_inline_callback(XDR* xdrs, u_int len)
	{
		return reinterpret_cast<int32_t*>(static_cast<XDR_Base*>(xdrs)->get_inline(len));
	}

	void xdr_destroy_callback(XDR* xdrs)
	{
	}

	bool_t xdr_getint32_callback(XDR* xdrs, int32_t* ip)
	{
		return static_cast<XDR_Base*>(xdrs)->get(*ip);
	}

	bool_t xdr_putint32_callback(XDR* xdrs, const int32_t* ip)
	{
		return static_cast<XDR_Base*>(xdrs)->put(*ip);
	}

	struct XDR::xdr_ops xdr_base_ops = {
		&xdr_getlong_callback,
		&xdr_putlong_callback,
		&xdr_getbytes_callback,
		&xdr_putbytes_callback,
		&xdr_getpostn_callback,
		&xdr_setpostn_callback,
		&xdr_inline_callback,
		&xdr_destroy_callback,
		&xdr_getint32_callback,
		&xdr_putint32_callback
	};

}

XDR_Base::
XDR_Base(xdr_op op)
{
	x_op = op;
	x_ops = &xdr_base_ops;
	x_public = 0;
	x_private = 0;
	x_base = 0;
	x_handy = 0;
}

bool XDR_Base::
get(int32_t& v)
{
	int32_t tmp;
	bool ret = get(reinterpret_cast<char*>(&tmp), sizeof (tmp));
	if (ret)
		v = htonl(tmp);
	return ret;
}

bool XDR_Base::
put(int32_t v)
{
	v = htonl(v);
	return put(reinterpret_cast<char*>(&v), sizeof (v));
}
<commit_msg>Include <cstdint> instead of <stdint.h><commit_after>#include "xdr++.h"

#include <sstream>

#include <cstdio>
#include <cstdint>
#include <arpa/inet.h>

bool xdr(XDR* xdrs, std::string& s)
{
	char* p;
	int32_t size, pad;
	char buf[BUFSIZ], zeros[] = { 0, 0, 0, 0 };
	std::ostringstream ss;

	switch (xdrs->x_op) {
	case XDR_ENCODE:
		p = const_cast<char*>(s.c_str());
		size = s.length();
		pad = (size | 0x03) - size + 1;
		return	   xdrs->x_ops->x_putint32(xdrs, &size)
			&& xdrs->x_ops->x_putbytes(xdrs, s.c_str(), size)
			&& xdrs->x_ops->x_putbytes(xdrs, zeros, pad);

	case XDR_DECODE:
		if (!xdrs->x_ops->x_getint32(xdrs, &size))
			return false;
		pad = (size | 0x03) - size + 1;
		p = buf;
		while (size) {
			uint32_t sz = size > sizeof (buf) ? sizeof (buf) : size;
			if (!xdrs->x_ops->x_getbytes(xdrs, p, sz))
				return false;
			ss.write(p, sz);
			size -= sz;
		}
		if (!xdrs->x_ops->x_getbytes(xdrs, p, pad))
			return false;
		s = ss.str();
		return true;

	default:
		break;
	}

	return false;
}

namespace {

	bool_t xdr_getlong_callback(XDR* xdrs, long* lp)
	{
		int32_t v;
		bool ret = static_cast<XDR_Base*>(xdrs)->get(v);
		if (ret)
			*lp = v;
		return ret;
	}

	bool_t xdr_putlong_callback(XDR* xdrs, const long* lp)
	{
		int32_t v = *lp;
		return static_cast<XDR_Base*>(xdrs)->put(v);
	}

	bool_t xdr_getbytes_callback(XDR* xdrs, caddr_t addr, u_int len)
	{
		return static_cast<XDR_Base*>(xdrs)->get(addr, len);
	}

	bool_t xdr_putbytes_callback(XDR* xdrs, const char* addr, u_int len)
	{
		return static_cast<XDR_Base*>(xdrs)->put(addr, len);
	}

	u_int xdr_getpostn_callback(const XDR* xdrs)
	{
		return static_cast<const XDR_Base*>(xdrs)->get_position();
	}

	bool_t xdr_setpostn_callback(XDR* xdrs, u_int pos)
	{
		return static_cast<XDR_Base*>(xdrs)->set_position(pos);
	}

	int32_t* xdr_inline_callback(XDR* xdrs, u_int len)
	{
		return reinterpret_cast<int32_t*>(static_cast<XDR_Base*>(xdrs)->get_inline(len));
	}

	void xdr_destroy_callback(XDR* xdrs)
	{
	}

	bool_t xdr_getint32_callback(XDR* xdrs, int32_t* ip)
	{
		return static_cast<XDR_Base*>(xdrs)->get(*ip);
	}

	bool_t xdr_putint32_callback(XDR* xdrs, const int32_t* ip)
	{
		return static_cast<XDR_Base*>(xdrs)->put(*ip);
	}

	struct XDR::xdr_ops xdr_base_ops = {
		&xdr_getlong_callback,
		&xdr_putlong_callback,
		&xdr_getbytes_callback,
		&xdr_putbytes_callback,
		&xdr_getpostn_callback,
		&xdr_setpostn_callback,
		&xdr_inline_callback,
		&xdr_destroy_callback,
		&xdr_getint32_callback,
		&xdr_putint32_callback
	};

}

XDR_Base::
XDR_Base(xdr_op op)
{
	x_op = op;
	x_ops = &xdr_base_ops;
	x_public = 0;
	x_private = 0;
	x_base = 0;
	x_handy = 0;
}

bool XDR_Base::
get(int32_t& v)
{
	int32_t tmp;
	bool ret = get(reinterpret_cast<char*>(&tmp), sizeof (tmp));
	if (ret)
		v = htonl(tmp);
	return ret;
}

bool XDR_Base::
put(int32_t v)
{
	v = htonl(v);
	return put(reinterpret_cast<char*>(&v), sizeof (v));
}
<|endoftext|>


<commit_before>// ChangeAliasPswd.cpp : implementation file
//

#include "stdafx.h"
#include "ChangeAliasPswd.h"

// CChangeAliasPswd dialog

IMPLEMENT_DYNAMIC(CChangeAliasPswd, CPWDialog)

CChangeAliasPswd::CChangeAliasPswd(CWnd* pParent /*=NULL*/)
	: CPWDialog(CChangeAliasPswd::IDD, pParent)
{
}

CChangeAliasPswd::~CChangeAliasPswd()
{
}

void CChangeAliasPswd::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);

  DDX_Text(pDX, IDC_STATIC_BASE, m_BaseEntry);
}

BEGIN_MESSAGE_MAP(CChangeAliasPswd, CDialog)
  ON_BN_CLICKED(IDC_CHANGEBASEPSWD, OnChangeBasePswd)
  ON_BN_CLICKED(IDC_CHANGEALIASPSWD, OnChangeAliasPswd)
END_MESSAGE_MAP()

// CChangeAliasPswd message handlers

void CChangeAliasPswd::OnChangeBasePswd()
{
  CPWDialog::EndDialog(CHANGEBASE);
}

void CChangeAliasPswd::OnChangeAliasPswd()
{
  CPWDialog::EndDialog(CHANGEALIAS);
}
<commit_msg>Missing copyright header - found by finding source not updated during 2010->2011 change<commit_after>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

// ChangeAliasPswd.cpp : implementation file
//

#include "stdafx.h"
#include "ChangeAliasPswd.h"

// CChangeAliasPswd dialog

IMPLEMENT_DYNAMIC(CChangeAliasPswd, CPWDialog)

CChangeAliasPswd::CChangeAliasPswd(CWnd* pParent /*=NULL*/)
	: CPWDialog(CChangeAliasPswd::IDD, pParent)
{
}

CChangeAliasPswd::~CChangeAliasPswd()
{
}

void CChangeAliasPswd::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);

  DDX_Text(pDX, IDC_STATIC_BASE, m_BaseEntry);
}

BEGIN_MESSAGE_MAP(CChangeAliasPswd, CDialog)
  ON_BN_CLICKED(IDC_CHANGEBASEPSWD, OnChangeBasePswd)
  ON_BN_CLICKED(IDC_CHANGEALIASPSWD, OnChangeAliasPswd)
END_MESSAGE_MAP()

// CChangeAliasPswd message handlers

void CChangeAliasPswd::OnChangeBasePswd()
{
  CPWDialog::EndDialog(CHANGEBASE);
}

void CChangeAliasPswd::OnChangeAliasPswd()
{
  CPWDialog::EndDialog(CHANGEALIAS);
}
<|endoftext|>


<commit_before>#ifndef NET_INET4_HPP
#define NET_INET4_HPP

#include <syscalls.hpp> // panic()
#include <dev.hpp> // 107: auto& eth0 = Dev::eth(0);
#include <net/inet.hpp>
#include <net/ethernet.hpp>
#include <net/arp.hpp>
#include <net/ip4.hpp>
#include <net/icmp.hpp>
#include "ip4/udp.hpp"
#include "dns/client.hpp"
#include <net/tcp.hpp>
#include <net/dhcp/dh4client.hpp>
#include <vector>

#include <nic.hpp>

namespace net {

  /** A complete IP4 network stack */
  template <typename DRIVER>
  class Inet4 : public Inet<Ethernet, IP4>{
  public:

    inline const Ethernet::addr& link_addr() override
    { return eth_.mac(); }

    inline Ethernet& link() override
    { return eth_; }

    inline const IP4::addr& ip_addr() override
    { return ip4_addr_; }

    inline const IP4::addr& netmask() override
    { return netmask_; }

    inline const IP4::addr& router() override
    { return router_; }

    inline IP4& ip_obj() override
    { return ip4_; }

    /** Get the TCP-object belonging to this stack */
    inline TCP& tcp() override { debug("<TCP> Returning tcp-reference to %p \n",&tcp_); return tcp_; }

    /** Get the UDP-object belonging to this stack */
    inline UDP& udp() override { return udp_; }

    /** Get the DHCP client (if any) */
    inline std::shared_ptr<DHClient> dhclient() override { return dhcp_;  }

    /** Create a Packet, with a preallocated buffer.
	@param size : the "size" reported by the allocated packet.
	@note as of v0.6.3 this has no effect other than to force the size to be
	set explicitly by the caller.
	@todo make_shared will allocate with new. This is fast in IncludeOS,
	(no context switch for sbrk) but consider overloading operator new.
    */
    inline Packet_ptr createPacket(size_t size) override {
      // Create a release delegate, for returning buffers
      auto release = BufferStore::release_del::from
	<BufferStore, &BufferStore::release_offset_buffer>(nic_.bufstore());
      // Create the packet, using  buffer and .
      return std::make_shared<Packet>(bufstore_.get_offset_buffer(),
				      bufstore_.offset_bufsize(), size, release);
    }

    // We have to ask the Nic for the MTU
    virtual inline uint16_t MTU() const override
    { return nic_.MTU(); }

    /**
     * @func  a delegate that provides a hostname and its address, which is 0 if the
     * name @hostname was not found. Note: Test with INADDR_ANY for a 0-address.
    **/
    inline virtual void
    resolve(const std::string& hostname,
            resolve_func<IP4>  func) override
    {
      dns.resolve(this->dns_server, hostname, func);
    }

    inline virtual void
    set_dns_server(IP4::addr server) override
    {
      this->dns_server = server;
    }

    /** We don't want to copy or move an IP-stack. It's tied to a device. */
    Inet4(Inet4&) = delete;
    Inet4(Inet4&&) = delete;
    Inet4& operator=(Inet4) = delete;
    Inet4 operator=(Inet4&&) = delete;

    /** Initialize with static IP / netmask */
    Inet4(Nic<DRIVER>& nic, IP4::addr ip, IP4::addr netmask);

    /** Initialize with DHCP  */
    Inet4(Nic<DRIVER>& nic);

  private:
    virtual void
    network_config(IP4::addr addr, IP4::addr nmask, IP4::addr router, IP4::addr dns) override
    {
      INFO("Inet4", "Reconfiguring network. New IP: %s", addr.str().c_str());
      this->ip4_addr_  = addr;
      this->netmask_   = nmask;
      this->router_    = router;
      this->dns_server = dns;
    }

    IP4::addr ip4_addr_;
    IP4::addr netmask_;
    IP4::addr router_;
    IP4::addr dns_server;

    // This is the actual stack
    Nic<DRIVER>& nic_;
    Ethernet eth_;
    Arp arp_;
    IP4  ip4_;
    ICMP icmp_;
    UDP  udp_;
    TCP tcp_;
    // we need this to store the cache per-stack
    DNSClient dns;

    std::shared_ptr<net::DHClient> dhcp_{};
    BufferStore& bufstore_;
  };
}

#include "inet4.inc"

#endif
<commit_msg>Inet::network_config made public<commit_after>#ifndef NET_INET4_HPP
#define NET_INET4_HPP

#include <syscalls.hpp> // panic()
#include <dev.hpp> // 107: auto& eth0 = Dev::eth(0);
#include <net/inet.hpp>
#include <net/ethernet.hpp>
#include <net/arp.hpp>
#include <net/ip4.hpp>
#include <net/icmp.hpp>
#include "ip4/udp.hpp"
#include "dns/client.hpp"
#include <net/tcp.hpp>
#include <net/dhcp/dh4client.hpp>
#include <vector>

#include <nic.hpp>

namespace net {

  /** A complete IP4 network stack */
  template <typename DRIVER>
  class Inet4 : public Inet<Ethernet, IP4>{
  public:

    inline const Ethernet::addr& link_addr() override
    { return eth_.mac(); }

    inline Ethernet& link() override
    { return eth_; }

    inline const IP4::addr& ip_addr() override
    { return ip4_addr_; }

    inline const IP4::addr& netmask() override
    { return netmask_; }

    inline const IP4::addr& router() override
    { return router_; }

    inline IP4& ip_obj() override
    { return ip4_; }

    /** Get the TCP-object belonging to this stack */
    inline TCP& tcp() override { debug("<TCP> Returning tcp-reference to %p \n",&tcp_); return tcp_; }

    /** Get the UDP-object belonging to this stack */
    inline UDP& udp() override { return udp_; }

    /** Get the DHCP client (if any) */
    inline std::shared_ptr<DHClient> dhclient() override { return dhcp_;  }

    /** Create a Packet, with a preallocated buffer.
	@param size : the "size" reported by the allocated packet.
	@note as of v0.6.3 this has no effect other than to force the size to be
	set explicitly by the caller.
	@todo make_shared will allocate with new. This is fast in IncludeOS,
	(no context switch for sbrk) but consider overloading operator new.
    */
    inline Packet_ptr createPacket(size_t size) override {
      // Create a release delegate, for returning buffers
      auto release = BufferStore::release_del::from
	<BufferStore, &BufferStore::release_offset_buffer>(nic_.bufstore());
      // Create the packet, using  buffer and .
      return std::make_shared<Packet>(bufstore_.get_offset_buffer(),
				      bufstore_.offset_bufsize(), size, release);
    }

    // We have to ask the Nic for the MTU
    virtual inline uint16_t MTU() const override
    { return nic_.MTU(); }

    /**
     * @func  a delegate that provides a hostname and its address, which is 0 if the
     * name @hostname was not found. Note: Test with INADDR_ANY for a 0-address.
    **/
    inline virtual void
    resolve(const std::string& hostname,
            resolve_func<IP4>  func) override
    {
      dns.resolve(this->dns_server, hostname, func);
    }

    inline virtual void
    set_dns_server(IP4::addr server) override
    {
      this->dns_server = server;
    }

    /** We don't want to copy or move an IP-stack. It's tied to a device. */
    Inet4(Inet4&) = delete;
    Inet4(Inet4&&) = delete;
    Inet4& operator=(Inet4) = delete;
    Inet4 operator=(Inet4&&) = delete;

    /** Initialize with static IP / netmask */
    Inet4(Nic<DRIVER>& nic, IP4::addr ip, IP4::addr netmask);

    /** Initialize with DHCP  */
    Inet4(Nic<DRIVER>& nic);

    virtual void
    network_config(IP4::addr addr, IP4::addr nmask, IP4::addr router, IP4::addr dns) override
    {
      INFO("Inet4", "Reconfiguring network. New IP: %s", addr.str().c_str());
      this->ip4_addr_  = addr;
      this->netmask_   = nmask;
      this->router_    = router;
      this->dns_server = dns;
    }

  private:

    IP4::addr ip4_addr_;
    IP4::addr netmask_;
    IP4::addr router_;
    IP4::addr dns_server;

    // This is the actual stack
    Nic<DRIVER>& nic_;
    Ethernet eth_;
    Arp arp_;
    IP4  ip4_;
    ICMP icmp_;
    UDP  udp_;
    TCP tcp_;
    // we need this to store the cache per-stack
    DNSClient dns;

    std::shared_ptr<net::DHClient> dhcp_{};
    BufferStore& bufstore_;
  };
}

#include "inet4.inc"

#endif
<|endoftext|>


<commit_before>#ifndef TEST_UNIT_UTIL_HPP
#define TEST_UNIT_UTIL_HPP

#include <boost/typeof/typeof.hpp>
#include <gtest/gtest.h>
#include <type_traits>
#include <string>

#define EXPECT_MATRIX_EQ(A, B)                       \
  {                                                  \
    const Eigen::MatrixXd& A_eval = A;               \
    const Eigen::MatrixXd& B_eval = B;               \
    EXPECT_EQ(A_eval.rows(), B_eval.rows());         \
    EXPECT_EQ(A_eval.cols(), B_eval.cols());         \
    for (int i = 0; i < A_eval.size(); i++)          \
        EXPECT_EQ(A_eval(i), B_eval(i));             \
  }

#define EXPECT_MATRIX_FLOAT_EQ(A, B)                 \
  {                                                  \
    const Eigen::MatrixXd& A_eval = A;               \
    const Eigen::MatrixXd& B_eval = B;               \
    EXPECT_EQ(A_eval.rows(), B_eval.rows());         \
    EXPECT_EQ(A_eval.cols(), B_eval.cols());         \
    for (int i = 0; i < A_eval.size(); i++)          \
        EXPECT_FLOAT_EQ(A_eval(i), B_eval(i));       \
  }

#define EXPECT_STD_VECTOR_FLOAT_EQ(A, B) \
  EXPECT_EQ(A.size(), B.size());         \
  for (int i = 0; i < A.size(); ++i)     \
    EXPECT_FLOAT_EQ(A[i], B[i]);

#define EXPECT_MATRIX_NEAR(A, B, DELTA)              \
  {                                                  \
    const Eigen::MatrixXd& A_eval = A;               \
    const Eigen::MatrixXd& B_eval = B;               \
    EXPECT_EQ(A_eval.rows(), B_eval.rows());         \
    EXPECT_EQ(A_eval.cols(), B_eval.cols());         \
    for (int i = 0; i < A_eval.size(); i++)          \
      EXPECT_FLOAT_EQ(A_eval(i), B_eval(i), DELTA);  \
  }

#define EXPECT_THROW_MSG_WITH_COUNT(expr, T_e, msg, count) \
  EXPECT_THROW(expr, T_e);                                 \
  try {                                                    \
    expr;                                                  \
  } catch (const T_e& e) {                                 \
    EXPECT_EQ(count, count_matches(msg, e.what()))         \
        << "expected message: " << msg << std::endl        \
        << "found message:    " << e.what();               \
  }

#define EXPECT_THROW_MSG(expr, T_e, msg) \
  EXPECT_THROW_MSG_WITH_COUNT(expr, T_e, msg, 1)

int count_matches(const std::string& target, const std::string& s) {
  if (target.size() == 0)
    return -1;  // error
  int count = 0;
  for (size_t pos = 0; (pos = s.find(target, pos)) != std::string::npos;
       pos += target.size())
    ++count;
  return count;
}

namespace test {
template <typename T1, typename T2>
void expect_same_type() {
  bool b = std::is_same<T1, T2>::value;
  EXPECT_TRUE(b);
}
}  // namespace test

#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef TEST_UNIT_UTIL_HPP
#define TEST_UNIT_UTIL_HPP

#include <boost/typeof/typeof.hpp>
#include <gtest/gtest.h>
#include <type_traits>
#include <string>

#define EXPECT_MATRIX_EQ(A, B)               \
  {                                          \
    const Eigen::MatrixXd& A_eval = A;       \
    const Eigen::MatrixXd& B_eval = B;       \
    EXPECT_EQ(A_eval.rows(), B_eval.rows()); \
    EXPECT_EQ(A_eval.cols(), B_eval.cols()); \
    for (int i = 0; i < A_eval.size(); i++)  \
      EXPECT_EQ(A_eval(i), B_eval(i));       \
  }

#define EXPECT_MATRIX_FLOAT_EQ(A, B)         \
  {                                          \
    const Eigen::MatrixXd& A_eval = A;       \
    const Eigen::MatrixXd& B_eval = B;       \
    EXPECT_EQ(A_eval.rows(), B_eval.rows()); \
    EXPECT_EQ(A_eval.cols(), B_eval.cols()); \
    for (int i = 0; i < A_eval.size(); i++)  \
      EXPECT_FLOAT_EQ(A_eval(i), B_eval(i)); \
  }

#define EXPECT_STD_VECTOR_FLOAT_EQ(A, B) \
  EXPECT_EQ(A.size(), B.size());         \
  for (int i = 0; i < A.size(); ++i)     \
    EXPECT_FLOAT_EQ(A[i], B[i]);

#define EXPECT_MATRIX_NEAR(A, B, DELTA)             \
  {                                                 \
    const Eigen::MatrixXd& A_eval = A;              \
    const Eigen::MatrixXd& B_eval = B;              \
    EXPECT_EQ(A_eval.rows(), B_eval.rows());        \
    EXPECT_EQ(A_eval.cols(), B_eval.cols());        \
    for (int i = 0; i < A_eval.size(); i++)         \
      EXPECT_FLOAT_EQ(A_eval(i), B_eval(i), DELTA); \
  }

#define EXPECT_THROW_MSG_WITH_COUNT(expr, T_e, msg, count) \
  EXPECT_THROW(expr, T_e);                                 \
  try {                                                    \
    expr;                                                  \
  } catch (const T_e& e) {                                 \
    EXPECT_EQ(count, count_matches(msg, e.what()))         \
        << "expected message: " << msg << std::endl        \
        << "found message:    " << e.what();               \
  }

#define EXPECT_THROW_MSG(expr, T_e, msg) \
  EXPECT_THROW_MSG_WITH_COUNT(expr, T_e, msg, 1)

int count_matches(const std::string& target, const std::string& s) {
  if (target.size() == 0)
    return -1;  // error
  int count = 0;
  for (size_t pos = 0; (pos = s.find(target, pos)) != std::string::npos;
       pos += target.size())
    ++count;
  return count;
}

namespace test {
template <typename T1, typename T2>
void expect_same_type() {
  bool b = std::is_same<T1, T2>::value;
  EXPECT_TRUE(b);
}
}  // namespace test

#endif
<|endoftext|>


<commit_before>#include "../lib/urireader.cpp"
#include <iostream>

class URITest : public Util::DataCallback{
public:
  void dump(const char *ptr, size_t size);
  void dataCallback(const char *ptr, size_t size);
  int main(int argc, char **argv);
};

void URITest::dataCallback(const char *ptr, size_t size){
  dump(ptr, size);
}

void URITest::dump(const char *ptr, size_t size){
  if (fwrite(ptr, sizeof(char), size, stdout) != size){INFO_MSG("error: %s", strerror(errno));}
}

int URITest::main(int argc, char **argv){
  Util::redirectLogsIfNeeded();
  Util::Config cfg(argv[0]);
  JSON::Value option;
  option["arg_num"] = 1;
  option["arg"] = "string";
  option["help"] = "Name of the input URI or - for stdin";
  option["value"].append("-");
  cfg.addOption("input", option);
  option.null();
  option["short"] = "r";
  option["long"] = "readall";
  option["help"] = "Read all data all at once in blocking mode";
  option["value"].append(0);
  cfg.addOption("readall", option);
  if (!cfg.parseArgs(argc, argv)){return 1;}

  cfg.activate();
  HTTP::URIReader R(cfg.getString("input"));

  if (cfg.getBool("readall")){
    char *dPtr = 0;
    size_t dLen = 0;
    R.readAll(dPtr, dLen);
    dump(dPtr, dLen);
  }else{
    while (!R.isEOF() && cfg.is_active){R.readSome(10486, *this);}
  }
  return 0;
}

int main(int argc, char **argv){
  URITest t;
  t.main(argc, argv);
}
<commit_msg>Fixed URIReader compile warning<commit_after>#include "../lib/urireader.cpp"
#include <iostream>

class URITest : public Util::DataCallback{
public:
  void dump(const char *ptr, size_t size){
    if (fwrite(ptr, sizeof(char), size, stdout) != size){INFO_MSG("error: %s", strerror(errno));}
  }
  void dataCallback(const char *ptr, size_t size){
    dump(ptr, size);
  }
  int main(int argc, char **argv);
};

int URITest::main(int argc, char **argv){
  Util::redirectLogsIfNeeded();
  Util::Config cfg(argv[0]);
  JSON::Value option;
  option["arg_num"] = 1;
  option["arg"] = "string";
  option["help"] = "Name of the input URI or - for stdin";
  option["value"].append("-");
  cfg.addOption("input", option);
  option.null();
  option["short"] = "r";
  option["long"] = "readall";
  option["help"] = "Read all data all at once in blocking mode";
  option["value"].append(0);
  cfg.addOption("readall", option);
  if (!cfg.parseArgs(argc, argv)){return 1;}

  cfg.activate();
  HTTP::URIReader R(cfg.getString("input"));

  if (cfg.getBool("readall")){
    char *dPtr = 0;
    size_t dLen = 0;
    R.readAll(dPtr, dLen);
    dump(dPtr, dLen);
  }else{
    while (!R.isEOF() && cfg.is_active){R.readSome(10486, *this);}
  }
  return 0;
}

int main(int argc, char **argv){
  URITest t;
  t.main(argc, argv);
}
<|endoftext|>


<commit_before><commit_msg>vcl::DeleteOnDeinit for static BitmapEx objects<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS changefileheader (1.68.14); FILE MERGED 2008/04/01 15:57:37 thb 1.68.14.3: #i85898# Stripping all external header guards 2008/04/01 12:54:34 thb 1.68.14.2: #i85898# Stripping all external header guards 2008/03/31 16:55:15 rt 1.68.14.1: #i87441# Change license header to LPGL v3.<commit_after><|endoftext|>


<commit_before>// Author: Enrico Guiraud, Danilo Piparo CERN  02/2018

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TDFNODES_UTILS
#define ROOT_TDFNODES_UTILS

#include "ROOT/TVec.hxx"
#include "ROOT/TDFUtils.hxx" // ColumnNames_t

namespace ROOT {
namespace Internal {
namespace TDF {
using namespace ROOT::Experimental::TDF;
using namespace ROOT::Experimental::VecOps;
using namespace ROOT::Detail::TDF;

/// Choose between TTreeReader{Array,Value} depending on whether the branch type
/// T is a `TVec<T>` or any other type (respectively).
template <typename T>
struct TReaderValueOrArray {
   using Proxy_t = TTreeReaderValue<T>;
};

template <typename T>
struct TReaderValueOrArray<TVec<T>> {
   using Proxy_t = TTreeReaderArray<T>;
};

template <typename T>
using ReaderValueOrArray_t = typename TReaderValueOrArray<T>::Proxy_t;

/// Initialize a tuple of TColumnValues.
/// For real TTree branches a TTreeReader{Array,Value} is built and passed to the
/// TColumnValue. For temporary columns a pointer to the corresponding variable
/// is passed instead.
template <typename TDFValueTuple, int... S>
void InitTDFValues(unsigned int slot, TDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn,
                   const ColumnNames_t &tmpbn,
                   const std::map<std::string, std::shared_ptr<TCustomColumnBase>> &customCols, StaticSeq<S...>)
{
   // isTmpBranch has length bn.size(). Elements are true if the corresponding
   // branch is a temporary branch created with Define, false if they are
   // actual branches present in the TTree.
   std::array<bool, sizeof...(S)> isTmpColumn;
   for (auto i = 0u; i < isTmpColumn.size(); ++i)
      isTmpColumn[i] = std::find(tmpbn.begin(), tmpbn.end(), bn.at(i)) != tmpbn.end();

   // hack to expand a parameter pack without c++17 fold expressions.
   // The statement defines a variable with type std::initializer_list<int>, containing all zeroes, and SetTmpColumn or
   // SetProxy are conditionally executed as the braced init list is expanded. The final ... expands S.
   std::initializer_list<int> expander{(isTmpColumn[S]
                                           ? std::get<S>(valueTuple).SetTmpColumn(slot, customCols.at(bn.at(S)).get())
                                           : std::get<S>(valueTuple).MakeProxy(r, bn.at(S)),
                                        0)...};
   (void)expander; // avoid "unused variable" warnings for expander on gcc4.9
   (void)slot;     // avoid _bogus_ "unused variable" warnings for slot on gcc 4.9
   (void)r;        // avoid "unused variable" warnings for r on gcc5.2
}

template <typename Filter>
void CheckFilter(Filter &)
{
   using FilterRet_t = typename TDF::CallableTraits<Filter>::ret_type;
   static_assert(std::is_same<FilterRet_t, bool>::value, "filter functions must return a bool");
}

} // namespace TDF
} // namespace Internal
} // namespace ROOT

#endif
<commit_msg>[TDF] Fix InitTDFValues in the case of zero columns<commit_after>// Author: Enrico Guiraud, Danilo Piparo CERN  02/2018

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TDFNODES_UTILS
#define ROOT_TDFNODES_UTILS

#include "ROOT/TVec.hxx"
#include "ROOT/TDFUtils.hxx" // ColumnNames_t

namespace ROOT {
namespace Internal {
namespace TDF {
using namespace ROOT::Experimental::TDF;
using namespace ROOT::Experimental::VecOps;
using namespace ROOT::Detail::TDF;

/// Choose between TTreeReader{Array,Value} depending on whether the branch type
/// T is a `TVec<T>` or any other type (respectively).
template <typename T>
struct TReaderValueOrArray {
   using Proxy_t = TTreeReaderValue<T>;
};

template <typename T>
struct TReaderValueOrArray<TVec<T>> {
   using Proxy_t = TTreeReaderArray<T>;
};

template <typename T>
using ReaderValueOrArray_t = typename TReaderValueOrArray<T>::Proxy_t;

/// Initialize a tuple of TColumnValues.
/// For real TTree branches a TTreeReader{Array,Value} is built and passed to the
/// TColumnValue. For temporary columns a pointer to the corresponding variable
/// is passed instead.
template <typename TDFValueTuple, int... S>
void InitTDFValues(unsigned int slot, TDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn,
                   const ColumnNames_t &tmpbn,
                   const std::map<std::string, std::shared_ptr<TCustomColumnBase>> &customCols, StaticSeq<S...>)
{
   // isTmpBranch has length bn.size(). Elements are true if the corresponding
   // branch is a temporary branch created with Define, false if they are
   // actual branches present in the TTree.
   std::array<bool, sizeof...(S)> isTmpColumn;
   for (auto i = 0u; i < isTmpColumn.size(); ++i)
      isTmpColumn[i] = std::find(tmpbn.begin(), tmpbn.end(), bn.at(i)) != tmpbn.end();

   // hack to expand a parameter pack without c++17 fold expressions.
   // The statement defines a variable with type std::initializer_list<int>, containing all zeroes, and SetTmpColumn or
   // SetProxy are conditionally executed as the braced init list is expanded. The final ... expands S.
   int expander[] = {(isTmpColumn[S] ? std::get<S>(valueTuple).SetTmpColumn(slot, customCols.at(bn.at(S)).get())
                                     : std::get<S>(valueTuple).MakeProxy(r, bn.at(S)),
                      0)...,
                     0};
   (void)expander; // avoid "unused variable" warnings for expander on gcc4.9
   (void)slot;     // avoid _bogus_ "unused variable" warnings for slot on gcc 4.9
   (void)r;        // avoid "unused variable" warnings for r on gcc5.2
}

template <typename Filter>
void CheckFilter(Filter &)
{
   using FilterRet_t = typename TDF::CallableTraits<Filter>::ret_type;
   static_assert(std::is_same<FilterRet_t, bool>::value, "filter functions must return a bool");
}

} // namespace TDF
} // namespace Internal
} // namespace ROOT

#endif
<|endoftext|>